mirror of
https://github.com/timberjoegithub/grafana-statusmap.git
synced 2026-07-21 23:42:03 +00:00
Merge pull request #109 from flant/feat_one_tooltip
ref: one codebase for the hover tooltip and the frozen tooltip
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+12
-11
@@ -22,6 +22,15 @@
|
|||||||
pointer-events: visiblePainted; }
|
pointer-events: visiblePainted; }
|
||||||
|
|
||||||
.statusmap-tooltip {
|
.statusmap-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 200;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-width: 800px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 14px;
|
||||||
|
z-index: 9999;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background-color: #141414;
|
background-color: #141414;
|
||||||
@@ -32,17 +41,9 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
||||||
|
|
||||||
.statusmap-tooltip-extraseries {
|
.statusmap-tooltip-frozen {
|
||||||
white-space: nowrap;
|
position: relative;
|
||||||
font-size: 12px;
|
z-index: 1; }
|
||||||
background-color: #141414;
|
|
||||||
color: #d8d9da; }
|
|
||||||
.statusmap-tooltip-extraseries .discrete-item {
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 1px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 0;
|
|
||||||
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
|
||||||
|
|
||||||
.statusmap-histogram rect {
|
.statusmap-histogram rect {
|
||||||
fill: #8e8e8e; }
|
fill: #8e8e8e; }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EACjB,WAAW,EAAE,MAAM;EACnB,SAAS,EE5CI,IAAI;EF6CjB,gBAAgB,EC1CC,OAAO;ED2CxB,KAAK,EC7CM,OAAO;ED+ClB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,8BAA+B;EAC7B,WAAW,EAAE,MAAM;EACnB,SAAS,EE1DI,IAAI;EF2DjB,gBAAgB,ECxDC,OAAO;EDyDxB,KAAK,EC3DM,OAAO;ED6DlB,6CAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,IAAI,ECtEY,OAAO;;AD0EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,ECxHG,OAAO;IDyHd,KAAK,ECzHE,OAAO;ID0Hd,SAAS,EE1HE,IAAI;EF6HjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC9HM,OAAO;EDiIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECnIM,OAAO",
|
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3HG,OAAO;ID4Hd,KAAK,EC5HE,OAAO;ID6Hd,SAAS,EE7HE,IAAI;EFgIjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjIM,OAAO;EDoIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtIM,OAAO",
|
||||||
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.dark.scss","../../src/css/_variables.scss"],
|
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.dark.scss","../../src/css/_variables.scss"],
|
||||||
"names": [],
|
"names": [],
|
||||||
"file": "statusmap.dark.css"
|
"file": "statusmap.dark.css"
|
||||||
|
|||||||
Vendored
+12
-11
@@ -22,6 +22,15 @@
|
|||||||
pointer-events: visiblePainted; }
|
pointer-events: visiblePainted; }
|
||||||
|
|
||||||
.statusmap-tooltip {
|
.statusmap-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 200;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-width: 800px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 14px;
|
||||||
|
z-index: 9999;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background-color: #dde4ed;
|
background-color: #dde4ed;
|
||||||
@@ -32,17 +41,9 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
||||||
|
|
||||||
.statusmap-tooltip-extraseries {
|
.statusmap-tooltip-frozen {
|
||||||
white-space: nowrap;
|
position: relative;
|
||||||
font-size: 12px;
|
z-index: 1; }
|
||||||
background-color: #dde4ed;
|
|
||||||
color: #52545c; }
|
|
||||||
.statusmap-tooltip-extraseries .discrete-item {
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 1px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 0;
|
|
||||||
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
|
|
||||||
|
|
||||||
.statusmap-histogram rect {
|
.statusmap-histogram rect {
|
||||||
fill: #767980; }
|
fill: #767980; }
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 3,
|
"version": 3,
|
||||||
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EACjB,WAAW,EAAE,MAAM;EACnB,SAAS,EE5CI,IAAI;EF6CjB,gBAAgB,EC1CC,OAAO;ED2CxB,KAAK,EC7CM,OAAO;ED+ClB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,8BAA+B;EAC7B,WAAW,EAAE,MAAM;EACnB,SAAS,EE1DI,IAAI;EF2DjB,gBAAgB,ECxDC,OAAO;EDyDxB,KAAK,EC3DM,OAAO;ED6DlB,6CAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,IAAI,ECtEY,OAAO;;AD0EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,ECxHG,OAAO;IDyHd,KAAK,ECzHE,OAAO;ID0Hd,SAAS,EE1HE,IAAI;EF6HjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC9HM,OAAO;EDiIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECnIM,OAAO",
|
"mappings": "AAAA,8BAA+B;EAE7B,MAAM,EAAE,SAAS;EAGjB,kDAAoB;IAClB,cAAc,EAAE,IAAI;EAGtB,uDAAyB;IACzB,gBAAgB,ECNL,OAAO;IDOlB,KAAK,ECVM,OAAO;IDWlB,OAAO,EAAE,GAAG;;AAId,gBAAiB;EACf,QAAQ,EAAE,QAAQ;EAGhB,iCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,iCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,oBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,yBAAK;MACH,cAAc,EAAE,cAAc;;AAKpC,kBAAmB;EAGjB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,GAAG;EAChB,aAAa,EAAE,GAAG;EAClB,SAAS,EAAE,KAAK;EAChB,UAAU,EAAE,KAAK;EACjB,QAAQ,EAAE,MAAM;EAChB,WAAW,EAAE,IAAI;EACjB,OAAO,EAAE,IAAI;EAGb,WAAW,EAAE,MAAM;EACnB,SAAS,EEzDI,IAAI;EF0DjB,gBAAgB,ECvDC,OAAO;EDwDxB,KAAK,EC1DM,OAAO;ED4DlB,iCAAe;IACb,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,uDAAuD;;AAIxE,yBAA0B;EACxB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,yBAA0B;EACxB,IAAI,ECzEY,OAAO;;AD6EvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAGlC,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AACA,WAAY;EACV,KAAK,EAAE,gBACT;;AAEA,8BAA+B;EAC7B,MAAM,EAAE,MAAM;EAEd,kCAAI;IACF,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,MAAM;EAIrB,2DAA6B;IAC3B,UAAU,EAAE,GAAG;EAGjB,4DAA8B;IAC5B,OAAO,EAAE,YAAY;EAIrB,+CAAK;IACH,IAAI,EC3HG,OAAO;ID4Hd,KAAK,EC5HE,OAAO;ID6Hd,SAAS,EE7HE,IAAI;EFgIjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECjIM,OAAO;EDoIrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECtIM,OAAO",
|
||||||
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.light.scss","../../src/css/_variables.scss"],
|
"sources": ["../../src/css/_statusmap.scss","../../src/css/_variables.light.scss","../../src/css/_variables.scss"],
|
||||||
"names": [],
|
"names": [],
|
||||||
"file": "statusmap.light.css"
|
"file": "statusmap.light.css"
|
||||||
|
|||||||
Vendored
-28
@@ -1,28 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
System.register([], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var ExtraSeriesFormat, ExtraSeriesFormatValue;
|
|
||||||
|
|
||||||
_export({
|
|
||||||
ExtraSeriesFormat: void 0,
|
|
||||||
ExtraSeriesFormatValue: void 0
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [],
|
|
||||||
execute: function () {
|
|
||||||
(function (ExtraSeriesFormat) {
|
|
||||||
ExtraSeriesFormat["Date"] = "Date";
|
|
||||||
ExtraSeriesFormat["Raw"] = "Raw";
|
|
||||||
})(ExtraSeriesFormat || _export("ExtraSeriesFormat", ExtraSeriesFormat = {}));
|
|
||||||
|
|
||||||
(function (ExtraSeriesFormatValue) {
|
|
||||||
ExtraSeriesFormatValue["Date"] = "YYYY/MM/DD/HH_mm_ss";
|
|
||||||
ExtraSeriesFormatValue["Raw"] = "";
|
|
||||||
})(ExtraSeriesFormatValue || _export("ExtraSeriesFormatValue", ExtraSeriesFormatValue = {}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=extra_series_format.js.map
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["../src/extra_series_format.ts"],"names":["ExtraSeriesFormat","ExtraSeriesFormatValue"],"mappings":";;;;;;;;;;;;;;;iBAAYA,iB;AAAAA,QAAAA,iB;AAAAA,QAAAA,iB;SAAAA,iB,iCAAAA,iB;;iBAKAC,sB;AAAAA,QAAAA,sB;AAAAA,QAAAA,sB;SAAAA,sB,sCAAAA,sB","sourcesContent":["export enum ExtraSeriesFormat {\n Date = 'Date',\n Raw = 'Raw',\n}\n\nexport enum ExtraSeriesFormatValue {\n Date = 'YYYY/MM/DD/HH_mm_ss',\n Raw = '',\n}"],"file":"extra_series_format.js"}
|
|
||||||
Vendored
+28
-310
@@ -1,9 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/sdk", "./statusmap_data", "./rendering", "./options_editor", "./color_mode_discrete", "./extra_series_format"], function (_export, _context) {
|
System.register(["lodash", "./color_legend", "./options_editor", "./tooltip_editor", "./panel_config_migration", "app/core/utils/kbn", "app/plugins/sdk", "./statusmap_data", "./rendering", "./color_mode_discrete"], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _, kbn, loadPluginCss, MetricsPanelCtrl, Bucket, BucketMatrix, rendering, statusHeatmapOptionsEditor, ColorModeDiscrete, ExtraSeriesFormat, ExtraSeriesFormatValue, VALUE_INDEX, TIME_INDEX, colorSchemes, colorModes, opacityScales, StatusHeatmapCtrl;
|
var _, optionsEditorCtrl, tooltipEditorCtrl, migratePanelConfig, kbn, loadPluginCss, MetricsPanelCtrl, Bucket, BucketMatrix, rendering, ColorModeDiscrete, VALUE_INDEX, TIME_INDEX, colorSchemes, colorModes, opacityScales, StatusHeatmapCtrl;
|
||||||
|
|
||||||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
||||||
|
|
||||||
@@ -32,7 +32,13 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
return {
|
return {
|
||||||
setters: [function (_lodash) {
|
setters: [function (_lodash) {
|
||||||
_ = _lodash.default;
|
_ = _lodash.default;
|
||||||
}, function (_color_legend) {}, function (_appCoreUtilsKbn) {
|
}, function (_color_legend) {}, function (_options_editor) {
|
||||||
|
optionsEditorCtrl = _options_editor.optionsEditorCtrl;
|
||||||
|
}, function (_tooltip_editor) {
|
||||||
|
tooltipEditorCtrl = _tooltip_editor.tooltipEditorCtrl;
|
||||||
|
}, function (_panel_config_migration) {
|
||||||
|
migratePanelConfig = _panel_config_migration.migratePanelConfig;
|
||||||
|
}, function (_appCoreUtilsKbn) {
|
||||||
kbn = _appCoreUtilsKbn.default;
|
kbn = _appCoreUtilsKbn.default;
|
||||||
}, function (_appPluginsSdk) {
|
}, function (_appPluginsSdk) {
|
||||||
loadPluginCss = _appPluginsSdk.loadPluginCss;
|
loadPluginCss = _appPluginsSdk.loadPluginCss;
|
||||||
@@ -42,13 +48,8 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
BucketMatrix = _statusmap_data.BucketMatrix;
|
BucketMatrix = _statusmap_data.BucketMatrix;
|
||||||
}, function (_rendering) {
|
}, function (_rendering) {
|
||||||
rendering = _rendering.default;
|
rendering = _rendering.default;
|
||||||
}, function (_options_editor) {
|
|
||||||
statusHeatmapOptionsEditor = _options_editor.statusHeatmapOptionsEditor;
|
|
||||||
}, function (_color_mode_discrete) {
|
}, function (_color_mode_discrete) {
|
||||||
ColorModeDiscrete = _color_mode_discrete.ColorModeDiscrete;
|
ColorModeDiscrete = _color_mode_discrete.ColorModeDiscrete;
|
||||||
}, function (_extra_series_format) {
|
|
||||||
ExtraSeriesFormat = _extra_series_format.ExtraSeriesFormat;
|
|
||||||
ExtraSeriesFormatValue = _extra_series_format.ExtraSeriesFormatValue;
|
|
||||||
}],
|
}],
|
||||||
execute: function () {
|
execute: function () {
|
||||||
VALUE_INDEX = 0;
|
VALUE_INDEX = 0;
|
||||||
@@ -163,6 +164,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
|
|
||||||
_this = _possibleConstructorReturn(this, _getPrototypeOf(StatusHeatmapCtrl).call(this, $scope, $injector));
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(StatusHeatmapCtrl).call(this, $scope, $injector));
|
||||||
_this.annotationsSrv = annotationsSrv;
|
_this.annotationsSrv = annotationsSrv;
|
||||||
|
_this.variableSrv = variableSrv;
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "data", void 0);
|
_defineProperty(_assertThisInitialized(_this), "data", void 0);
|
||||||
|
|
||||||
@@ -190,8 +192,6 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "discreteExtraSeries", void 0);
|
_defineProperty(_assertThisInitialized(_this), "discreteExtraSeries", void 0);
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "extraSeriesFormats", []);
|
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "annotations", []);
|
_defineProperty(_assertThisInitialized(_this), "annotations", []);
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "annotationsPromise", void 0);
|
_defineProperty(_assertThisInitialized(_this), "annotationsPromise", void 0);
|
||||||
@@ -219,8 +219,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
cardRound: null
|
cardRound: null
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
show: true,
|
show: true
|
||||||
labelFormat: '%a %m/%d'
|
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
show: true,
|
show: true,
|
||||||
@@ -228,88 +227,30 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
maxWidth: -1
|
maxWidth: -1
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true
|
show: true,
|
||||||
|
freezeOnClick: true,
|
||||||
|
showItems: false,
|
||||||
|
items: [] // see tooltip_editor.ts
|
||||||
|
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
data: {
|
|
||||||
unitFormat: 'short',
|
|
||||||
decimals: null
|
|
||||||
},
|
|
||||||
// how null points should be handled
|
// how null points should be handled
|
||||||
nullPointMode: 'as empty',
|
nullPointMode: 'as empty',
|
||||||
yAxisSort: 'metrics',
|
yAxisSort: 'metrics',
|
||||||
highlightCards: true,
|
highlightCards: true,
|
||||||
useMax: true,
|
useMax: true,
|
||||||
urls: [{
|
seriesFilterIndex: -1
|
||||||
tooltip: '',
|
|
||||||
label: '',
|
|
||||||
base_url: '',
|
|
||||||
useExtraSeries: false,
|
|
||||||
useseriesname: true,
|
|
||||||
forcelowercase: true,
|
|
||||||
icon_fa: 'external-link',
|
|
||||||
extraSeries: {
|
|
||||||
index: -1
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
seriesFilterIndex: -1,
|
|
||||||
usingUrl: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "onEditorAddUrl", function () {
|
migratePanelConfig(_this.panel);
|
||||||
_this.panel.urls.push({
|
|
||||||
label: '',
|
|
||||||
base_url: '',
|
|
||||||
useExtraSeries: false,
|
|
||||||
useseriesname: true,
|
|
||||||
forcelowercase: true,
|
|
||||||
icon_fa: 'external-link',
|
|
||||||
extraSeries: {
|
|
||||||
index: -1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_this.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "onEditorRemoveUrl", function (index) {
|
|
||||||
_this.panel.urls.splice(index, 1);
|
|
||||||
|
|
||||||
_this.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
_defineProperty(_assertThisInitialized(_this), "onEditorRemoveUrls", function () {
|
|
||||||
_this.panel.urls = [];
|
|
||||||
|
|
||||||
_this.render();
|
|
||||||
});
|
|
||||||
|
|
||||||
_.defaultsDeep(_this.panel, _this.panelDefaults);
|
_.defaultsDeep(_this.panel, _this.panelDefaults);
|
||||||
|
|
||||||
_this.opacityScales = opacityScales;
|
_this.opacityScales = opacityScales;
|
||||||
_this.colorModes = colorModes;
|
_this.colorModes = colorModes;
|
||||||
_this.colorSchemes = colorSchemes;
|
_this.colorSchemes = colorSchemes; // default graph width for discrete card width calculation
|
||||||
_this.variableSrv = variableSrv;
|
|
||||||
_this.extraSeriesFormats = ExtraSeriesFormat;
|
|
||||||
|
|
||||||
_this.renderLink = function (link, scopedVars, format) {
|
|
||||||
var scoped = {};
|
|
||||||
|
|
||||||
for (var key in scopedVars) {
|
|
||||||
scoped[key] = {
|
|
||||||
value: scopedVars[key]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
return _this.templateSrv.replace(link, scoped, format);
|
|
||||||
} else {
|
|
||||||
return _this.templateSrv.replace(link, scoped);
|
|
||||||
}
|
|
||||||
}; // default graph width for discrete card width calculation
|
|
||||||
|
|
||||||
|
|
||||||
_this.graph = {
|
_this.graph = {
|
||||||
"chartWidth": -1
|
"chartWidth": -1
|
||||||
@@ -350,8 +291,6 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
|
|
||||||
_this.events.on('render-complete', _this.onRenderComplete.bind(_assertThisInitialized(_this)));
|
_this.events.on('render-complete', _this.onRenderComplete.bind(_assertThisInitialized(_this)));
|
||||||
|
|
||||||
_this.events.on('onChangeType', _this.onChangeType.bind(_assertThisInitialized(_this)));
|
|
||||||
|
|
||||||
_this.onCardColorChange = _this.onCardColorChange.bind(_assertThisInitialized(_this));
|
_this.onCardColorChange = _this.onCardColorChange.bind(_assertThisInitialized(_this));
|
||||||
return _this;
|
return _this;
|
||||||
}
|
}
|
||||||
@@ -359,32 +298,8 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
_createClass(StatusHeatmapCtrl, [{
|
_createClass(StatusHeatmapCtrl, [{
|
||||||
key: "onRenderComplete",
|
key: "onRenderComplete",
|
||||||
value: function onRenderComplete(data) {
|
value: function onRenderComplete(data) {
|
||||||
// console.log({
|
|
||||||
// data: this.data,
|
|
||||||
// bucketMatrix: this.bucketMatrix,
|
|
||||||
// chartWidth: data.chartWidth,
|
|
||||||
// from: this.range.from.valueOf(),
|
|
||||||
// to: this.range.to.valueOf()
|
|
||||||
// })
|
|
||||||
this.graph.chartWidth = data.chartWidth;
|
this.graph.chartWidth = data.chartWidth;
|
||||||
this.renderingCompleted();
|
this.renderingCompleted();
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "onChangeType",
|
|
||||||
value: function onChangeType(url) {
|
|
||||||
switch (url.type) {
|
|
||||||
case ExtraSeriesFormat.Date:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Date;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ExtraSeriesFormat.Raw:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Raw;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Raw;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // getChartWidth returns an approximation of chart canvas width or
|
} // getChartWidth returns an approximation of chart canvas width or
|
||||||
// a saved value calculated during a render.
|
// a saved value calculated during a render.
|
||||||
|
|
||||||
@@ -408,6 +323,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
return chartWidth;
|
return chartWidth;
|
||||||
} // Quick workaround for 6.7 and 7.0+. There is no call to
|
} // Quick workaround for 6.7 and 7.0+. There is no call to
|
||||||
// calculateInterval in updateTimeRange in those versions.
|
// calculateInterval in updateTimeRange in those versions.
|
||||||
|
// TODO ts type has no argument for this method.
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
key: "updateTimeRange",
|
key: "updateTimeRange",
|
||||||
@@ -457,16 +373,8 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
var interval = kbn.secondsToHms(intervalMs / 1000);
|
var interval = kbn.secondsToHms(intervalMs / 1000);
|
||||||
this.intervalMs = intervalMs;
|
this.intervalMs = intervalMs;
|
||||||
this.interval = interval; // Get final buckets count after interval is adjusted
|
this.interval = interval; // Get final buckets count after interval is adjusted
|
||||||
|
// TODO is it needed?
|
||||||
//this.xBucketsCount = Math.floor(rangeMs / intervalMs);
|
//this.xBucketsCount = Math.floor(rangeMs / intervalMs);
|
||||||
// console.log("calculateInterval: ", {
|
|
||||||
// interval: this.interval,
|
|
||||||
// intervalMs: this.intervalMs,
|
|
||||||
// rangeMs: rangeMs,
|
|
||||||
// from: this.range.from.valueOf(),
|
|
||||||
// to: this.range.to.valueOf(),
|
|
||||||
// numIntervals: rangeMs/this.intervalMs,
|
|
||||||
// maxCardsCount: maxCardsCount,
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "issueQueries",
|
key: "issueQueries",
|
||||||
@@ -484,7 +392,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
* (but not wait for completion). This resolves
|
* (but not wait for completion). This resolves
|
||||||
* issue 11806.
|
* issue 11806.
|
||||||
*/
|
*/
|
||||||
// 5.x before 5.4 doesn't have datasourcePromises.
|
// 5.x before 5.4 doesn't have datasourcePromises.
|
||||||
|
|
||||||
if ("undefined" !== typeof this.annotationsSrv.datasourcePromises) {
|
if ("undefined" !== typeof this.annotationsSrv.datasourcePromises) {
|
||||||
return this.annotationsSrv.datasourcePromises.then(function (r) {
|
return this.annotationsSrv.datasourcePromises.then(function (r) {
|
||||||
@@ -549,7 +457,8 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
}, {
|
}, {
|
||||||
key: "onInitEditMode",
|
key: "onInitEditMode",
|
||||||
value: function onInitEditMode() {
|
value: function onInitEditMode() {
|
||||||
this.addEditorTab('Options', statusHeatmapOptionsEditor, 2);
|
this.addEditorTab('Options', optionsEditorCtrl, 2);
|
||||||
|
this.addEditorTab('Tooltip', tooltipEditorCtrl, 3);
|
||||||
this.unitFormats = kbn.getUnitFormats();
|
this.unitFormats = kbn.getUnitFormats();
|
||||||
} // onRender will be called before StatusmapRenderer.onRender.
|
} // onRender will be called before StatusmapRenderer.onRender.
|
||||||
// Decide if warning should be displayed over cards.
|
// Decide if warning should be displayed over cards.
|
||||||
@@ -588,8 +497,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
|
|
||||||
if (this.bucketMatrix) {
|
if (this.bucketMatrix) {
|
||||||
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
||||||
} //console.log(this);
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "onCardColorChange",
|
key: "onCardColorChange",
|
||||||
@@ -609,104 +517,17 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
value: function postRefresh() {
|
value: function postRefresh() {
|
||||||
this.noColorDefined = false;
|
this.noColorDefined = false;
|
||||||
}
|
}
|
||||||
}, {
|
|
||||||
key: "onEditorAddThreshold",
|
|
||||||
value: function onEditorAddThreshold() {
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: this.panel.defaultColor
|
|
||||||
});
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "onEditorRemoveThreshold",
|
|
||||||
value: function onEditorRemoveThreshold(index) {
|
|
||||||
this.panel.color.thresholds.splice(index, 1);
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "onEditorRemoveThresholds",
|
|
||||||
value: function onEditorRemoveThresholds() {
|
|
||||||
this.panel.color.thresholds = [];
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "onEditorAddThreeLights",
|
|
||||||
value: function onEditorAddThreeLights() {
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "red",
|
|
||||||
value: 2,
|
|
||||||
tooltip: "error"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "yellow",
|
|
||||||
value: 1,
|
|
||||||
tooltip: "warning"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "green",
|
|
||||||
value: 0,
|
|
||||||
tooltip: "ok"
|
|
||||||
});
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
/* https://ethanschoonover.com/solarized/ */
|
|
||||||
|
|
||||||
}, {
|
|
||||||
key: "onEditorAddSolarized",
|
|
||||||
value: function onEditorAddSolarized() {
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#b58900",
|
|
||||||
value: 0,
|
|
||||||
tooltip: "yellow"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#cb4b16",
|
|
||||||
value: 1,
|
|
||||||
tooltip: "orange"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#dc322f",
|
|
||||||
value: 2,
|
|
||||||
tooltip: "red"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#d33682",
|
|
||||||
value: 3,
|
|
||||||
tooltip: "magenta"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#6c71c4",
|
|
||||||
value: 4,
|
|
||||||
tooltip: "violet"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#268bd2",
|
|
||||||
value: 5,
|
|
||||||
tooltip: "blue"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#2aa198",
|
|
||||||
value: 6,
|
|
||||||
tooltip: "cyan"
|
|
||||||
});
|
|
||||||
this.panel.color.thresholds.push({
|
|
||||||
color: "#859900",
|
|
||||||
value: 7,
|
|
||||||
tooltip: "green"
|
|
||||||
});
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
key: "link",
|
key: "link",
|
||||||
value: function link(scope, elem, attrs, ctrl) {
|
value: function link(scope, elem, attrs, ctrl) {
|
||||||
rendering(scope, elem, attrs, ctrl);
|
rendering(scope, elem, attrs, ctrl);
|
||||||
}
|
} // Compatible with Grafana 7.0 overrides feature.
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
key: "retrieveTimeVar",
|
key: "retrieveTimeVar",
|
||||||
value: function retrieveTimeVar() {
|
value: function retrieveTimeVar() {
|
||||||
var time = this.timeSrv.timeRangeForUrl();
|
var time = this.timeSrv.timeRangeForUrl();
|
||||||
var var_time = '&from=' + time.from + '&to=' + time.to;
|
return 'from=' + time.from + '&to=' + time.to;
|
||||||
return var_time;
|
|
||||||
} // convertToBuckets groups values in data into buckets by target and timestamp.
|
} // convertToBuckets groups values in data into buckets by target and timestamp.
|
||||||
//
|
//
|
||||||
// data is a result from datasource. It is an array of timeseries and tables:
|
// data is a result from datasource. It is an array of timeseries and tables:
|
||||||
@@ -918,109 +739,6 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
|
|||||||
|
|
||||||
bucketMatrix.targets = targetKeys;
|
bucketMatrix.targets = targetKeys;
|
||||||
return bucketMatrix;
|
return bucketMatrix;
|
||||||
this.bucketMatrix = bucketMatrix; // Collect all values for each bucket from datapoints with similar target.
|
|
||||||
// TODO aggregate values into buckets over datapoint[TIME_INDEX] not over datapoint index (j).
|
|
||||||
// for(let i = 0; i < cardsData.targets.length; i++) {
|
|
||||||
// let target = cardsData.targets[i];
|
|
||||||
// for (let j = 0; j < cardsData.xBucketSize; j++) {
|
|
||||||
// let card = new Card();
|
|
||||||
// card.id = i*cardsData.xBucketSize + j;
|
|
||||||
// card.values = [];
|
|
||||||
// card.y = target;
|
|
||||||
// card.x = -1;
|
|
||||||
// // collect values from all timeseries with target
|
|
||||||
// for (let si = 0; si < cardsData.targetIndex[target].length; si++) {
|
|
||||||
// let s = data[cardsData.targetIndex[target][si]];
|
|
||||||
// if (s.datapoints.length <= j) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// let datapoint = s.datapoints[j];
|
|
||||||
// if (card.values.length === 0) {
|
|
||||||
// card.x = datapoint[TIME_INDEX];
|
|
||||||
// }
|
|
||||||
// card.values.push(datapoint[VALUE_INDEX]);
|
|
||||||
// }
|
|
||||||
// card.minValue = _.min(card.values);
|
|
||||||
// card.maxValue = _.max(card.values);
|
|
||||||
// if (card.values.length > 1) {
|
|
||||||
// cardsData.multipleValues = true;
|
|
||||||
// card.multipleValues = true;
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// } else {
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// }
|
|
||||||
// if (cardsData.maxValue < card.maxValue)
|
|
||||||
// cardsData.maxValue = card.maxValue;
|
|
||||||
// if (cardsData.minValue > card.minValue)
|
|
||||||
// cardsData.minValue = card.minValue;
|
|
||||||
// if (card.x != -1) {
|
|
||||||
// cardsData.cards.push(card);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// let cardsData = <CardsStorage> {
|
|
||||||
// cards: [],
|
|
||||||
// xBucketSize: 0,
|
|
||||||
// yBucketSize: 0,
|
|
||||||
// maxValue: 0,
|
|
||||||
// minValue: 0,
|
|
||||||
// multipleValues: false,
|
|
||||||
// noColorDefined: false,
|
|
||||||
// targets: [], // array of available unique targets
|
|
||||||
// targetIndex: {} // indices in data array for each of available unique targets
|
|
||||||
// };
|
|
||||||
// if (!data || data.length == 0) { return cardsData;}
|
|
||||||
// // Collect uniq timestamps from data and spread over targets and timestamps
|
|
||||||
// // collect uniq targets and their indices
|
|
||||||
// _.map(data, (d, i) => {
|
|
||||||
// cardsData.targetIndex[d.target] = _.concat(_.toArray(cardsData.targetIndex[d.target]), i)
|
|
||||||
// });
|
|
||||||
// // TODO add some logic for targets heirarchy
|
|
||||||
// cardsData.targets = _.keys(cardsData.targetIndex);
|
|
||||||
// cardsData.yBucketSize = cardsData.targets.length;
|
|
||||||
// // Maximum number of buckets over x axis
|
|
||||||
// cardsData.xBucketSize = _.max(_.map(data, d => d.datapoints.length));
|
|
||||||
// // Collect all values for each bucket from datapoints with similar target.
|
|
||||||
// // TODO aggregate values into buckets over datapoint[TIME_INDEX] not over datapoint index (j).
|
|
||||||
// for(let i = 0; i < cardsData.targets.length; i++) {
|
|
||||||
// let target = cardsData.targets[i];
|
|
||||||
// for (let j = 0; j < cardsData.xBucketSize; j++) {
|
|
||||||
// let card = new Card();
|
|
||||||
// card.id = i*cardsData.xBucketSize + j;
|
|
||||||
// card.values = [];
|
|
||||||
// card.y = target;
|
|
||||||
// card.x = -1;
|
|
||||||
// // collect values from all timeseries with target
|
|
||||||
// for (let si = 0; si < cardsData.targetIndex[target].length; si++) {
|
|
||||||
// let s = data[cardsData.targetIndex[target][si]];
|
|
||||||
// if (s.datapoints.length <= j) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// let datapoint = s.datapoints[j];
|
|
||||||
// if (card.values.length === 0) {
|
|
||||||
// card.x = datapoint[TIME_INDEX];
|
|
||||||
// }
|
|
||||||
// card.values.push(datapoint[VALUE_INDEX]);
|
|
||||||
// }
|
|
||||||
// card.minValue = _.min(card.values);
|
|
||||||
// card.maxValue = _.max(card.values);
|
|
||||||
// if (card.values.length > 1) {
|
|
||||||
// cardsData.multipleValues = true;
|
|
||||||
// card.multipleValues = true;
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// } else {
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// }
|
|
||||||
// if (cardsData.maxValue < card.maxValue)
|
|
||||||
// cardsData.maxValue = card.maxValue;
|
|
||||||
// if (cardsData.minValue > card.minValue)
|
|
||||||
// cardsData.minValue = card.minValue;
|
|
||||||
// if (card.x != -1) {
|
|
||||||
// cardsData.cards.push(card);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return cardsData;
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+98
-3
@@ -13,7 +13,8 @@ System.register(["app/core/utils/kbn"], function (_export, _context) {
|
|||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
|
|
||||||
function statusHeatmapOptionsEditor() {
|
/** @ngInject */
|
||||||
|
function optionsEditorCtrl() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -24,7 +25,7 @@ System.register(["app/core/utils/kbn"], function (_export, _context) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_export("statusHeatmapOptionsEditor", statusHeatmapOptionsEditor);
|
_export("optionsEditorCtrl", optionsEditorCtrl);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setters: [function (_appCoreUtilsKbn) {
|
setters: [function (_appCoreUtilsKbn) {
|
||||||
@@ -34,6 +35,9 @@ System.register(["app/core/utils/kbn"], function (_export, _context) {
|
|||||||
_export("StatusHeatmapOptionsEditorCtrl", StatusHeatmapOptionsEditorCtrl =
|
_export("StatusHeatmapOptionsEditorCtrl", StatusHeatmapOptionsEditorCtrl =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
function () {
|
function () {
|
||||||
|
StatusHeatmapOptionsEditorCtrl.$inject = ["$scope"];
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
function StatusHeatmapOptionsEditorCtrl($scope) {
|
function StatusHeatmapOptionsEditorCtrl($scope) {
|
||||||
_classCallCheck(this, StatusHeatmapOptionsEditorCtrl);
|
_classCallCheck(this, StatusHeatmapOptionsEditorCtrl);
|
||||||
|
|
||||||
@@ -47,7 +51,6 @@ System.register(["app/core/utils/kbn"], function (_export, _context) {
|
|||||||
this.panelCtrl = $scope.ctrl;
|
this.panelCtrl = $scope.ctrl;
|
||||||
this.panel = this.panelCtrl.panel;
|
this.panel = this.panelCtrl.panel;
|
||||||
this.unitFormats = kbn.getUnitFormats();
|
this.unitFormats = kbn.getUnitFormats();
|
||||||
this.panelCtrl.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createClass(StatusHeatmapOptionsEditorCtrl, [{
|
_createClass(StatusHeatmapOptionsEditorCtrl, [{
|
||||||
@@ -56,6 +59,98 @@ System.register(["app/core/utils/kbn"], function (_export, _context) {
|
|||||||
this.panel.data.unitFormat = subItem.value;
|
this.panel.data.unitFormat = subItem.value;
|
||||||
this.panelCtrl.render();
|
this.panelCtrl.render();
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "render",
|
||||||
|
value: function render() {
|
||||||
|
this.panelCtrl.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onAddThreshold",
|
||||||
|
value: function onAddThreshold() {
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: this.panel.defaultColor
|
||||||
|
});
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onRemoveThreshold",
|
||||||
|
value: function onRemoveThreshold(index) {
|
||||||
|
this.panel.color.thresholds.splice(index, 1);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onRemoveThresholds",
|
||||||
|
value: function onRemoveThresholds() {
|
||||||
|
this.panel.color.thresholds = [];
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onAddThreeLights",
|
||||||
|
value: function onAddThreeLights() {
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "red",
|
||||||
|
value: 2,
|
||||||
|
tooltip: "error"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "yellow",
|
||||||
|
value: 1,
|
||||||
|
tooltip: "warning"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "green",
|
||||||
|
value: 0,
|
||||||
|
tooltip: "ok"
|
||||||
|
});
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
/* https://ethanschoonover.com/solarized/ */
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: "onAddSolarized",
|
||||||
|
value: function onAddSolarized() {
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#b58900",
|
||||||
|
value: 0,
|
||||||
|
tooltip: "yellow"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#cb4b16",
|
||||||
|
value: 1,
|
||||||
|
tooltip: "orange"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#dc322f",
|
||||||
|
value: 2,
|
||||||
|
tooltip: "red"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#d33682",
|
||||||
|
value: 3,
|
||||||
|
tooltip: "magenta"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#6c71c4",
|
||||||
|
value: 4,
|
||||||
|
tooltip: "violet"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#268bd2",
|
||||||
|
value: 5,
|
||||||
|
tooltip: "blue"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#2aa198",
|
||||||
|
value: 6,
|
||||||
|
tooltip: "cyan"
|
||||||
|
});
|
||||||
|
this.panel.color.thresholds.push({
|
||||||
|
color: "#859900",
|
||||||
|
value: 7,
|
||||||
|
tooltip: "green"
|
||||||
|
});
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
return StatusHeatmapOptionsEditorCtrl;
|
return StatusHeatmapOptionsEditorCtrl;
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+165
@@ -0,0 +1,165 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
System.register(["lodash"], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var _;
|
||||||
|
|
||||||
|
function migrate_V0_V1(panel) {
|
||||||
|
// Remove unused fields.
|
||||||
|
if (_.has(panel, "xAxis.labelFormat")) {
|
||||||
|
delete panel.xAxis.labelFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(panel, "xAxis.minBucketWidthToShowWeekends")) {
|
||||||
|
delete panel.xAxis.minBucketWidthToShowWeekends;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(panel, "xAxis.showCrosshair")) {
|
||||||
|
delete panel.xAxis.showCrosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(panel, "xAxis.showWeekends")) {
|
||||||
|
delete panel.xAxis.showWeekends;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(panel, "yAxis.showCrosshair")) {
|
||||||
|
delete panel.yAxis.showCrosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(panel, "data.unitFormat")) {
|
||||||
|
delete panel.data;
|
||||||
|
} // Migrate cardSpacing value. Seems rare (update from version 0.0.2).
|
||||||
|
|
||||||
|
|
||||||
|
if (_.has(panel, "cards.cardSpacing")) {
|
||||||
|
if (!_.has(panel, "cards.cardVSpacing")) {
|
||||||
|
if (panel.cards.cardSpacing) {
|
||||||
|
panel.cards.cardVSpacing = panel.cards.cardSpacing;
|
||||||
|
panel.cards.cardHSpacing = panel.cards.cardSpacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete panel.cards.cardSpacing;
|
||||||
|
} // Migrate initial config for urls in tooltip (pull/86).
|
||||||
|
// 'usingUrl' was used to show tooltip with urls on click or not.
|
||||||
|
|
||||||
|
|
||||||
|
if (_.has(panel, "usingUrl")) {
|
||||||
|
if (!_.has(panel, "tooltip.freezeOnClick")) {
|
||||||
|
panel.tooltip.freezeOnClick = panel.usingUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete panel.usingUrl;
|
||||||
|
} // 'urls' array is now tooltip.items array. Also items are changed.
|
||||||
|
|
||||||
|
|
||||||
|
if (_.has(panel, "urls")) {
|
||||||
|
if (!_.has(panel, "tooltip.items")) {
|
||||||
|
panel.tooltip.items = [];
|
||||||
|
var hasRealItems = true;
|
||||||
|
|
||||||
|
if (panel.urls.length == 0) {
|
||||||
|
hasRealItems = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel.urls.length == 1) {
|
||||||
|
var url = panel.urls[0];
|
||||||
|
|
||||||
|
if (url.base_url === '' && url.label === '') {
|
||||||
|
hasRealItems = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasRealItems) {
|
||||||
|
panel.tooltip.showItems = true;
|
||||||
|
var _iteratorNormalCompletion = true;
|
||||||
|
var _didIteratorError = false;
|
||||||
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator = panel.urls[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
|
var _url = _step.value;
|
||||||
|
var item = {
|
||||||
|
urlTemplate: _.toString(_url.base_url),
|
||||||
|
urlText: _.toString(_url.label),
|
||||||
|
urlIcon: _.toString(_url.icon_fa),
|
||||||
|
urlToLowerCase: _url.forcelowercase,
|
||||||
|
valueDateFormat: ''
|
||||||
|
}; // replace $vars with new ${__vars} if url template is not empty
|
||||||
|
|
||||||
|
if (item.urlTemplate !== "") {
|
||||||
|
// $time was a graph time with prepended &
|
||||||
|
item.urlTemplate = _.replace(_url.base_url, /\$time/g, "&${__url_time_range}"); // $series_label was a y axis label
|
||||||
|
|
||||||
|
item.urlTemplate = _.replace(item.urlTemplate, /\$series_label/, "${__y_label}"); // $series_extra was a value from bucket. This value has format options and index.
|
||||||
|
|
||||||
|
var valueVar = "__value";
|
||||||
|
|
||||||
|
if (_url.useExtraSeries === true) {
|
||||||
|
// index?
|
||||||
|
if (_url.extraSeries.index > -1) {
|
||||||
|
valueVar += "_" + _url.extraSeries.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
var format = _.toString(_url.extraSeries.format);
|
||||||
|
|
||||||
|
if (format === 'YYYY/MM/DD/HH_mm_ss') {
|
||||||
|
valueVar += '_date';
|
||||||
|
item.valueDateFormat = format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.urlTemplate = _.replace(item.urlTemplate, /\$series_extra/, "${".concat(valueVar, "}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.tooltip.items.push(item);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError = true;
|
||||||
|
_iteratorError = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
|
||||||
|
_iterator["return"]();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError) {
|
||||||
|
throw _iteratorError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete panel.urls;
|
||||||
|
} // create statusmap metadata
|
||||||
|
|
||||||
|
|
||||||
|
panel.statusmap = {
|
||||||
|
"ConfigVersion": "v1"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function migratePanelConfig(panel) {
|
||||||
|
if (_.has(panel, "statusmap")) {
|
||||||
|
if (panel.statusmap.ConfigVersion == "v1") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
migrate_V0_V1(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_export("migratePanelConfig", migratePanelConfig);
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [function (_lodash) {
|
||||||
|
_ = _lodash.default;
|
||||||
|
}],
|
||||||
|
execute: function () {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=panel_config_migration.js.map
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+20
-117
@@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label">
|
<label class="gf-form-label">
|
||||||
<a class="pointer" tabindex="1" ng-click="ctrl.onEditorRemoveThreshold($index)">
|
<a class="pointer" tabindex="1" ng-click="editor.onRemoveThreshold($index)">
|
||||||
<i class="fa fa-trash"/>
|
<i class="fa fa-trash"/>
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
@@ -91,12 +91,12 @@
|
|||||||
<div class="gf-form-inline">
|
<div class="gf-form-inline">
|
||||||
<div class="gf-form"></div>
|
<div class="gf-form"></div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorAddThreshold()">
|
<button class="btn btn-inverse" ng-click="editor.onAddThreshold()">
|
||||||
<i class="fa fa-plus"></i> Add new status
|
<i class="fa fa-plus"></i> Add new status
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorRemoveThresholds()">
|
<button class="btn btn-inverse" ng-click="editor.onRemoveThresholds()">
|
||||||
<i class="fa fa-minus"></i> Remove all
|
<i class="fa fa-minus"></i> Remove all
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -108,12 +108,12 @@
|
|||||||
<label class="gf-form-label">Presets</label>
|
<label class="gf-form-label">Presets</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn" ng-click="ctrl.onEditorAddThreeLights()">
|
<button class="btn" ng-click="editor.onAddThreeLights()">
|
||||||
Red-Yellow-Green
|
Red-Yellow-Green
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn" ng-click="ctrl.onEditorAddSolarized()">
|
<button class="btn" ng-click="editor.onAddSolarized()">
|
||||||
Solarized
|
Solarized
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,10 +144,6 @@
|
|||||||
label="Show legend"
|
label="Show legend"
|
||||||
checked="ctrl.panel.legend.show" on-change="ctrl.render()">
|
checked="ctrl.panel.legend.show" on-change="ctrl.render()">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
|
||||||
label="Show tooltip"
|
|
||||||
checked="ctrl.panel.tooltip.show" on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
<gf-form-switch class="gf-form" label-class="width-8"
|
||||||
label="Show X axis"
|
label="Show X axis"
|
||||||
checked="ctrl.panel.xAxis.show" on-change="ctrl.render()">
|
checked="ctrl.panel.xAxis.show" on-change="ctrl.render()">
|
||||||
@@ -159,17 +155,12 @@
|
|||||||
|
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Min width</label>
|
<label class="gf-form-label width-8">Min width</label>
|
||||||
<input type="number" ng-model="ctrl.panel.xAxis.minWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="number" ng-model="ctrl.panel.yAxis.minWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Max width</label>
|
<label class="gf-form-label width-8">Max width</label>
|
||||||
<input type="number" ng-model="ctrl.panel.xAxis.maxWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="number" ng-model="ctrl.panel.yAxis.maxWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group">
|
|
||||||
<h5 class="section-heading">Buckets</h5>
|
|
||||||
|
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Rows sort</label>
|
<label class="gf-form-label width-8">Rows sort</label>
|
||||||
<div class="gf-form-select-wrapper">
|
<div class="gf-form-select-wrapper">
|
||||||
@@ -180,6 +171,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Buckets</h5>
|
||||||
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
<gf-form-switch class="gf-form" label-class="width-8"
|
||||||
label="Multiple values"
|
label="Multiple values"
|
||||||
checked="ctrl.panel.useMax" on-change="ctrl.render()">
|
checked="ctrl.panel.useMax" on-change="ctrl.render()">
|
||||||
@@ -187,6 +183,13 @@
|
|||||||
<div class="gf-form" ng-show="ctrl.panel.useMax">
|
<div class="gf-form" ng-show="ctrl.panel.useMax">
|
||||||
Color for bucket with multiple values is determined by color mode<br/>
|
Color for bucket with multiple values is determined by color mode<br/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-8">Values index</label>
|
||||||
|
<input type="number" class="gf-form-input width-5" placeholder="-1" data-placement="right"
|
||||||
|
bs-tooltip="'Display only values with this index in a bucket. Use -1 to display all values'"
|
||||||
|
ng-model="ctrl.panel.seriesFilterIndex" ng-change="ctrl.refresh()"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-8">Display nulls</label>
|
<label class="gf-form-label width-8">Display nulls</label>
|
||||||
@@ -194,6 +197,7 @@
|
|||||||
<select class="gf-form-input max-width-9" ng-model="ctrl.panel.nullPointMode" ng-options="f for f in ['as empty', 'as zero']" ng-change="ctrl.render()"></select>
|
<select class="gf-form-input max-width-9" ng-model="ctrl.panel.nullPointMode" ng-options="f for f in ['as empty', 'as zero']" ng-change="ctrl.render()"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-8">Min width</label>
|
<label class="gf-form-label width-8">Min width</label>
|
||||||
<input type="number" class="gf-form-input width-5" placeholder="5" data-placement="right" bs-tooltip="'Minimal card width for 1/1 resolution in pixels'" ng-model="ctrl.panel.cards.cardMinWidth" ng-change="ctrl.refresh()" ng-model-onblur>
|
<input type="number" class="gf-form-input width-5" placeholder="5" data-placement="right" bs-tooltip="'Minimal card width for 1/1 resolution in pixels'" ng-model="ctrl.panel.cards.cardMinWidth" ng-change="ctrl.refresh()" ng-model-onblur>
|
||||||
@@ -212,105 +216,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section gf-form-group width-30">
|
|
||||||
<h5 class="section-heading">Filtering</h5>
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-9">Show only serie with Index</label>
|
|
||||||
<input type="number" class="gf-form-input width-5" placeholder="2" data-placement="right"
|
|
||||||
bs-tooltip="'Filter with the serie index to show the value on graph. Use -1 to get all values'" ng-model="ctrl.panel.seriesFilterIndex" ng-change="ctrl.refresh()"
|
|
||||||
ng-model-onblur>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group">
|
|
||||||
<h5 class="section-heading">URL</h5>
|
|
||||||
|
|
||||||
<div class="gf-form">
|
|
||||||
Insert the url to navigate<br />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form">
|
|
||||||
<gf-form-switch class="gf-form" label="Show extraSeries Tooltip when clicking elements" label-class="width-12"
|
|
||||||
checked="ctrl.panel.usingUrl" on-change="ctrl.render()"></gf-form-switch>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group" ng-if="ctrl.panel.usingUrl">
|
|
||||||
<br>
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form"></div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorAddUrl()">
|
|
||||||
<i class="fa fa-plus"></i> Add new URL
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorRemoveUrls()">
|
|
||||||
<i class="fa fa-minus"></i> Remove all URLs
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form-block" ng-repeat="url in ctrl.panel.urls">
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-2">{{ $index }}</label>
|
|
||||||
<label class="gf-form-label width-2">
|
|
||||||
<a class="pointer" tabindex="1" ng-click="ctrl.onEditorRemoveUrl($index)">
|
|
||||||
<i class="fa fa-trash" />
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
<label class="gf-form-label width-4">Label: </label>
|
|
||||||
<input type="text" class="gf-form-input width-16" placeholder="My URL" data-placement="right"
|
|
||||||
ng-model="url.label" ng-change="ctrl.refresh()">
|
|
||||||
<label class="gf-form-label width-4">URL: </label>
|
|
||||||
<input type="text" class="gf-form-input width-c-50" placeholder="https://www.google.es" data-placement="right"
|
|
||||||
bs-tooltip="'This is the url to be shown when the user clicks on it'" ng-model="url.base_url"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
<info-popover mode="right-normal">
|
|
||||||
<p>Specify an URL (relative or absolute)</p>
|
|
||||||
<span>
|
|
||||||
Use special variables to specify cell values:
|
|
||||||
<br>
|
|
||||||
<em>$series_label</em> name of the serie
|
|
||||||
<br>
|
|
||||||
<em>$(template.name)</em> name of the templated to be replaced
|
|
||||||
<br>
|
|
||||||
<em>$time</em> append &from...&to on the URL
|
|
||||||
<br>
|
|
||||||
<em>$series_extra</em> use extraSeries value to use it on URL
|
|
||||||
</span>
|
|
||||||
</info-popover>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-4">Icon: </label>
|
|
||||||
<input type="text" class="gf-form-input width-12" placeholder="FA Icon" data-placement="right"
|
|
||||||
bs-tooltip="'The icon shown on URL'" ng-model="url.icon_fa" ng-change="ctrl.refresh()">
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8" label="Force lowercase" checked="url.forcelowercase"
|
|
||||||
on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-6" label="Use Extra Serie Data" checked="url.useExtraSeries"
|
|
||||||
on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<div class="gf-form" ng-if="url.useExtraSeries == true">
|
|
||||||
<label class="gf-form-label width-8">Extra Series Index: </label>
|
|
||||||
<input type="number" class="gf-form-input width-12" placeholder="0" ng-if="url.useExtraSeries == true"
|
|
||||||
data-placement="right" bs-tooltip="'Fields index to use its value on URL using $series_extra. Use -1 to disable it'" ng-model="url.extraSeries.index"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
|
|
||||||
<label class="gf-form-label width-9">Type</label>
|
|
||||||
<div class="gf-form-select-wrapper width-8">
|
|
||||||
<select class="input-small gf-form-input" ng-model="url.type" ng-options="s for s in ctrl.extraSeriesFormats" ng-change="ctrl.onChangeType(url)"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="url.type === 'Date'">
|
|
||||||
<label class="gf-form-label width-12">Extra Series Date Format: </label>
|
|
||||||
<input type="text" class="gf-form-input width-12" placeholder="YYYY/MM/DD/HH_mm_ss" ng-if="url.useExtraSeries == true"
|
|
||||||
data-placement="right" bs-tooltip="'Date format to transformat extraSeries'" ng-model="url.extraSeries.format"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Vendored
+120
@@ -0,0 +1,120 @@
|
|||||||
|
<div class="editor-row">
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Show tooltip"
|
||||||
|
tooltip="'Show tooltip when mouse is over the card'"
|
||||||
|
checked="ctrl.panel.tooltip.show" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Freeze on click"
|
||||||
|
tooltip="'Freeze tooltip copy when card is clicked'"
|
||||||
|
checked="ctrl.panel.tooltip.freezeOnClick" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Show items"
|
||||||
|
tooltip="'Show items (urls) in tooltip'"
|
||||||
|
checked="ctrl.panel.tooltip.showItems" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Items</h5>
|
||||||
|
|
||||||
|
<div class="gf-form" ng-show="ctrl.panel.tooltip.items.length == 0">
|
||||||
|
<label class="gf-form-label width-2">0</label>
|
||||||
|
<label class="gf-form-input width-30">No items defined.</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div ng-repeat="item in ctrl.panel.tooltip.items">
|
||||||
|
<div class="gf-form gf-form--grow">
|
||||||
|
<label class="gf-form-label width-6">
|
||||||
|
URL
|
||||||
|
<info-popover mode="left-normal">
|
||||||
|
<p>Specify an URL (relative or absolute)</p>
|
||||||
|
<span>
|
||||||
|
Use special variables:
|
||||||
|
<br>
|
||||||
|
<em>${__y_label}</em> name of the time series (alias or legend in the query editor).
|
||||||
|
<!-- <br>
|
||||||
|
<em>$(template.name)</em> name of the templated to be replaced -->
|
||||||
|
<br>
|
||||||
|
<em>${__bucket_range}</em> refers to bucket range in the form of '&from=...&to=...'.
|
||||||
|
<br>
|
||||||
|
<em>${__graph_range}</em> refers to graph range in the form of '&from=...&to=...'.
|
||||||
|
<br>
|
||||||
|
<em>${__value}</em> refers to current bucket value or max value if multiple values mode is on.
|
||||||
|
<br>
|
||||||
|
<em>${__value_N}</em> refers to Nth value in current bucket. Value indexes are started from 0. For instance,
|
||||||
|
<em>${__value_1}</em> refers to second value.
|
||||||
|
</span>
|
||||||
|
</info-popover>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="gf-form-input" placeholder="https://www.google.es" data-placement="top"
|
||||||
|
bs-tooltip="'This is the url to be shown when the user clicks on it'" ng-model="item.urlTemplate"
|
||||||
|
ng-change="ctrl.refresh()">
|
||||||
|
<label class="gf-form-label">
|
||||||
|
<i class="fa fa-trash pointer" ng-click="editor.onRemoveUrl($index)"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-4">Icon</label>
|
||||||
|
<label class="gf-form-label width-2">
|
||||||
|
<i class="fa fa-{{item.urlIcon}}"></i>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
class="gf-form-input width-10"
|
||||||
|
type="text"
|
||||||
|
ng-model="item.urlIcon"
|
||||||
|
bs-typeahead="editor.getFAIconClasses"
|
||||||
|
bs-tooltip="'The icon for URL link'"
|
||||||
|
data-placement="top"
|
||||||
|
ng-blur="ctrl.render()"
|
||||||
|
data-min-length="0"
|
||||||
|
data-items="100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-4">Label</label>
|
||||||
|
<input type="text" class="gf-form-input width-16" placeholder="My URL" data-placement="top"
|
||||||
|
bs-tooltip="'Text for URL link'"
|
||||||
|
ng-model="item.urlText" ng-change="ctrl.refresh()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-8" label="Lowercase link" checked="item.urlToLowerCase"
|
||||||
|
on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-8">Date format</label>
|
||||||
|
<input type="text" class="gf-form-input width-12" placeholder="YYYY/MM/DD/HH_mm_ss"
|
||||||
|
data-placement="top" bs-tooltip="'Date format for __value_date'"
|
||||||
|
bs-typeahead="editor.getValueDateFormats"
|
||||||
|
data-min-length="0"
|
||||||
|
data-items="100"
|
||||||
|
ng-model="item.valueDateFormat"
|
||||||
|
ng-blur="ctrl.render()">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form"></div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-click="editor.onAddUrl()">
|
||||||
|
<i class="fa fa-plus"></i> Add URL
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-click="editor.onRemoveUrls()">
|
||||||
|
<i class="fa fa-minus"></i> Remove all
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Vendored
-1
@@ -17,7 +17,6 @@
|
|||||||
"links": [
|
"links": [
|
||||||
{"name": "Github", "url": "https://github.com/flant/grafana-statusmap"},
|
{"name": "Github", "url": "https://github.com/flant/grafana-statusmap"},
|
||||||
{"name": "MIT Licence", "url": "https://github.com/flant/grafana-statusmap/blob/master/LICENSE"}
|
{"name": "MIT Licence", "url": "https://github.com/flant/grafana-statusmap/blob/master/LICENSE"}
|
||||||
|
|
||||||
],
|
],
|
||||||
"screenshots": [
|
"screenshots": [
|
||||||
{"name": "Panel with light theme", "path": "img/flant-statusmap-panel.png"},
|
{"name": "Panel with light theme", "path": "img/flant-statusmap-panel.png"},
|
||||||
|
|||||||
Vendored
+20
-33
@@ -1,9 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/core", "d3", "./libs/d3-scale-chromatic/index", "./tooltip", "./tooltipextraseries", "./annotations"], function (_export, _context) {
|
System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/core", "d3", "./libs/d3-scale-chromatic/index", "./tooltip", "./annotations"], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _, $, moment, kbn, appEvents, contextSrv, d3, d3ScaleChromatic, StatusmapTooltip, StatusHeatmapTooltipExtraSeries, AnnotationTooltip, MIN_CARD_SIZE, CARD_H_SPACING, CARD_V_SPACING, CARD_ROUND, DATA_RANGE_WIDING_FACTOR, DEFAULT_X_TICK_SIZE_PX, DEFAULT_Y_TICK_SIZE_PX, X_AXIS_TICK_PADDING, Y_AXIS_TICK_PADDING, MIN_SELECTION_WIDTH, Statusmap, StatusmapRenderer;
|
var _, $, moment, kbn, appEvents, contextSrv, d3, d3ScaleChromatic, StatusmapTooltip, AnnotationTooltip, MIN_CARD_SIZE, CARD_H_SPACING, CARD_V_SPACING, CARD_ROUND, DATA_RANGE_WIDING_FACTOR, DEFAULT_X_TICK_SIZE_PX, DEFAULT_Y_TICK_SIZE_PX, X_AXIS_TICK_PADDING, Y_AXIS_TICK_PADDING, MIN_SELECTION_WIDTH, Statusmap, StatusmapRenderer;
|
||||||
|
|
||||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||||||
|
|
||||||
@@ -66,8 +66,6 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
d3ScaleChromatic = _libsD3ScaleChromaticIndex;
|
d3ScaleChromatic = _libsD3ScaleChromaticIndex;
|
||||||
}, function (_tooltip) {
|
}, function (_tooltip) {
|
||||||
StatusmapTooltip = _tooltip.StatusmapTooltip;
|
StatusmapTooltip = _tooltip.StatusmapTooltip;
|
||||||
}, function (_tooltipextraseries) {
|
|
||||||
StatusHeatmapTooltipExtraSeries = _tooltipextraseries.StatusHeatmapTooltipExtraSeries;
|
|
||||||
}, function (_annotations) {
|
}, function (_annotations) {
|
||||||
AnnotationTooltip = _annotations.AnnotationTooltip;
|
AnnotationTooltip = _annotations.AnnotationTooltip;
|
||||||
}],
|
}],
|
||||||
@@ -156,8 +154,6 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
_defineProperty(this, "tooltip", void 0);
|
_defineProperty(this, "tooltip", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "tooltipExtraSeries", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "annotationTooltip", void 0);
|
_defineProperty(this, "annotationTooltip", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "heatmap", void 0);
|
_defineProperty(this, "heatmap", void 0);
|
||||||
@@ -177,7 +173,6 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
// $heatmap is JQuery object, but heatmap is D3
|
// $heatmap is JQuery object, but heatmap is D3
|
||||||
this.$heatmap = this.elem.find('.statusmap-panel');
|
this.$heatmap = this.elem.find('.statusmap-panel');
|
||||||
this.tooltip = new StatusmapTooltip(this.$heatmap, this.scope);
|
this.tooltip = new StatusmapTooltip(this.$heatmap, this.scope);
|
||||||
this.tooltipExtraSeries = new StatusHeatmapTooltipExtraSeries(this.$heatmap, this.scope);
|
|
||||||
this.annotationTooltip = new AnnotationTooltip(this.$heatmap, this.scope);
|
this.annotationTooltip = new AnnotationTooltip(this.$heatmap, this.scope);
|
||||||
this.yOffset = 0;
|
this.yOffset = 0;
|
||||||
this.selection = {
|
this.selection = {
|
||||||
@@ -410,9 +405,11 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
if (this.heatmap) {
|
if (this.heatmap) {
|
||||||
this.heatmap.remove();
|
this.heatmap.remove();
|
||||||
}
|
} // Insert svg as a first child into heatmap_elem
|
||||||
|
// as the frozen tooltip moving logiс assumes that tooltip is the last child.
|
||||||
|
|
||||||
this.heatmap = d3.select(heatmap_elem).append("svg").attr("width", this.width).attr("height", this.height);
|
|
||||||
|
this.heatmap = d3.select(heatmap_elem).insert("svg", ":first-child").attr("width", this.width).attr("height", this.height);
|
||||||
this.chartHeight = this.height - this.margin.top - this.margin.bottom;
|
this.chartHeight = this.height - this.margin.top - this.margin.bottom;
|
||||||
this.chartTop = this.margin.top;
|
this.chartTop = this.margin.top;
|
||||||
this.chartBottom = this.chartTop + this.chartHeight;
|
this.chartBottom = this.chartTop + this.chartHeight;
|
||||||
@@ -513,10 +510,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
|
|
||||||
var colorScheme = _.find(this.ctrl.colorSchemes, {
|
var colorScheme = _.find(this.ctrl.colorSchemes, {
|
||||||
value: this.panel.color.colorScheme
|
value: this.panel.color.colorScheme
|
||||||
}); // if (!colorScheme) {
|
});
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
var colorInterpolator = d3ScaleChromatic[colorScheme.value];
|
var colorInterpolator = d3ScaleChromatic[colorScheme.value];
|
||||||
var colorScaleInverted = colorScheme.invert === 'always' || colorScheme.invert === 'dark' && !contextSrv.user.lightTheme;
|
var colorScaleInverted = colorScheme.invert === 'always' || colorScheme.invert === 'dark' && !contextSrv.user.lightTheme;
|
||||||
@@ -618,28 +612,28 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "getCardColor",
|
key: "getCardColor",
|
||||||
value: function getCardColor(b) {
|
value: function getCardColor(bucket) {
|
||||||
if (this.panel.color.mode === 'opacity') {
|
if (this.panel.color.mode === 'opacity') {
|
||||||
return this.panel.color.cardColor;
|
return this.panel.color.cardColor;
|
||||||
} else if (this.panel.color.mode === 'spectrum') {
|
} else if (this.panel.color.mode === 'spectrum') {
|
||||||
return this.colorScale(b.value);
|
return this.colorScale(bucket.value);
|
||||||
} else if (this.panel.color.mode === 'discrete') {
|
} else if (this.panel.color.mode === 'discrete') {
|
||||||
if (this.panel.seriesFilterIndex != null && this.panel.seriesFilterIndex != -1) {
|
if (this.panel.seriesFilterIndex != null && this.panel.seriesFilterIndex != -1) {
|
||||||
return this.ctrl.discreteExtraSeries.getBucketColorSingle(d.values[this.panel.seriesFilterIndex]);
|
return this.ctrl.discreteExtraSeries.getBucketColorSingle(bucket.values[this.panel.seriesFilterIndex]);
|
||||||
} else {
|
} else {
|
||||||
return this.ctrl.discreteExtraSeries.getBucketColor(b.values);
|
return this.ctrl.discreteExtraSeries.getBucketColor(bucket.values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "getCardOpacity",
|
key: "getCardOpacity",
|
||||||
value: function getCardOpacity(b) {
|
value: function getCardOpacity(bucket) {
|
||||||
if (this.panel.nullPointMode === 'as empty' && b.value == null) {
|
if (this.panel.nullPointMode === 'as empty' && bucket.value == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.panel.color.mode === 'opacity') {
|
if (this.panel.color.mode === 'opacity') {
|
||||||
return this.opacityScale(b.value);
|
return this.opacityScale(bucket.value);
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -705,14 +699,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
key: "onMouseLeave",
|
key: "onMouseLeave",
|
||||||
value: function onMouseLeave(e) {
|
value: function onMouseLeave(e) {
|
||||||
appEvents.emit('graph-hover-clear');
|
appEvents.emit('graph-hover-clear');
|
||||||
this.clearCrosshair(); //annotationTooltip.destroy();
|
this.clearCrosshair();
|
||||||
|
|
||||||
if (e.relatedTarget) {
|
|
||||||
if (e.relatedTarget.className == "statusmap-tooltip-extraseries graph-tooltip grafana-tooltip" || e.relatedTarget.className == "graph-tooltip-time") {} else {
|
|
||||||
this.tooltipExtraSeries.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.annotationTooltip.destroy();
|
this.annotationTooltip.destroy();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -738,13 +725,13 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
|
|||||||
this.tooltip.show(event);
|
this.tooltip.show(event);
|
||||||
this.annotationTooltip.show(event);
|
this.annotationTooltip.show(event);
|
||||||
}
|
}
|
||||||
}
|
} // TODO emit an event and move logic to panelCtrl
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
key: "onMouseClick",
|
key: "onMouseClick",
|
||||||
value: function onMouseClick(event) {
|
value: function onMouseClick(e) {
|
||||||
this.tooltipExtraSeries.show(event);
|
if (this.ctrl.panel.tooltip.freezeOnClick) {
|
||||||
|
this.tooltip.showFrozen(e);
|
||||||
if (this.ctrl.panel.usingUrl) {
|
|
||||||
this.tooltip.destroy();
|
this.tooltip.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+166
@@ -0,0 +1,166 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
System.register(["../panel_config_migration"], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var migratePanelConfig;
|
||||||
|
return {
|
||||||
|
setters: [function (_panel_config_migration) {
|
||||||
|
migratePanelConfig = _panel_config_migration.migratePanelConfig;
|
||||||
|
}],
|
||||||
|
execute: function () {
|
||||||
|
describe('when migrate from config with urls', function () {
|
||||||
|
var panel;
|
||||||
|
describe('given full panel configuration', function () {
|
||||||
|
var panelConfig = {
|
||||||
|
"cards": {
|
||||||
|
"cardHSpacing": 2,
|
||||||
|
"cardMinWidth": 5,
|
||||||
|
"cardRound": null,
|
||||||
|
"cardVSpacing": 2
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"cardColor": "#b4ff00",
|
||||||
|
"colorScale": "sqrt",
|
||||||
|
"colorScheme": "interpolateGnYlRd",
|
||||||
|
"defaultColor": "#757575",
|
||||||
|
"exponent": 0.5,
|
||||||
|
"mode": "opacity",
|
||||||
|
"thresholds": []
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"decimals": null,
|
||||||
|
"unitFormat": "short"
|
||||||
|
},
|
||||||
|
"datasource": "TestData DB",
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"highlightCards": true,
|
||||||
|
"id": 4,
|
||||||
|
"legend": {
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"nullPointMode": "as empty",
|
||||||
|
"seriesFilterIndex": -1,
|
||||||
|
"targets": [{
|
||||||
|
"aggregation": "Last",
|
||||||
|
"csvWave": {
|
||||||
|
"timeStep": 60,
|
||||||
|
"valuesCSV": "0,0,2,2,1,1,3,3"
|
||||||
|
},
|
||||||
|
"decimals": 2,
|
||||||
|
"displayAliasType": "Warning / Critical",
|
||||||
|
"displayType": "Regular",
|
||||||
|
"displayValueWithAlias": "Never",
|
||||||
|
"refId": "A",
|
||||||
|
"scenarioId": "predictable_csv_wave",
|
||||||
|
"stringInput": "",
|
||||||
|
"units": "none",
|
||||||
|
"valueHandler": "Number Threshold"
|
||||||
|
}],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Panel Title",
|
||||||
|
"tooltip": {
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"type": "flant-statusmap-panel",
|
||||||
|
"urls": [{
|
||||||
|
"base_url": "",
|
||||||
|
"extraSeries": {
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "",
|
||||||
|
"tooltip": "",
|
||||||
|
"useExtraSeries": false,
|
||||||
|
"useseriesname": true
|
||||||
|
}],
|
||||||
|
"useMax": true,
|
||||||
|
"usingUrl": true,
|
||||||
|
"xAxis": {
|
||||||
|
"labelFormat": "%a %m/%d",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"yAxis": {
|
||||||
|
"maxWidth": -1,
|
||||||
|
"minWidth": -1,
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"yAxisSort": "metrics"
|
||||||
|
};
|
||||||
|
beforeEach(function () {
|
||||||
|
panel = Object.assign({}, panelConfig);
|
||||||
|
migratePanelConfig(panel);
|
||||||
|
});
|
||||||
|
it('should migrate usingUrls to tooltip.freezeOnClick', function () {
|
||||||
|
expect(panel.usingUrl).toBeUndefined();
|
||||||
|
expect(panel.tooltip).toHaveProperty("freezeOnClick", true);
|
||||||
|
expect(panel.tooltip.freezeOnClick).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should have no urls', function () {
|
||||||
|
expect(panel.urls).toBeUndefined();
|
||||||
|
});
|
||||||
|
it('should have empty items in tooltip', function () {
|
||||||
|
expect(panel.tooltip).toHaveProperty("items", []);
|
||||||
|
expect(panel.tooltip.items).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("given configuration with non-empty base_url", function () {
|
||||||
|
describe("with variables", function () {
|
||||||
|
var panelConfig = {
|
||||||
|
"tooltip": {
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"urls": [{
|
||||||
|
"base_url": "https://google.com/$series_label$time",
|
||||||
|
"extraSeries": {
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "google",
|
||||||
|
"tooltip": "",
|
||||||
|
"useExtraSeries": false,
|
||||||
|
"useseriesname": true
|
||||||
|
}, {
|
||||||
|
"base_url": "example.com/$series_extra",
|
||||||
|
"extraSeries": {
|
||||||
|
"format": "YYYY/MM/DD/HH_mm_ss",
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "DateLink",
|
||||||
|
"useExtraSeries": true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
beforeEach(function () {
|
||||||
|
panel = Object.assign({}, panelConfig);
|
||||||
|
migratePanelConfig(panel);
|
||||||
|
});
|
||||||
|
it("should have equal size of tooltip.items", function () {
|
||||||
|
expect(panel.tooltip).toHaveProperty("items");
|
||||||
|
expect(panel.tooltip.items).toHaveLength(panelConfig.urls.length);
|
||||||
|
});
|
||||||
|
it("should replace time variable with __url_time_range", function () {
|
||||||
|
expect(panel.tooltip.items[0].urlTemplate).toContain("${__url_time_range}");
|
||||||
|
});
|
||||||
|
it("should replace series_label variable with __y_label", function () {
|
||||||
|
expect(panel.tooltip.items[0].urlTemplate).toContain("${__y_label}");
|
||||||
|
});
|
||||||
|
it("should replace series_extra variable with __value_date", function () {
|
||||||
|
expect(panel.tooltip.items[1].urlTemplate).toContain("${__value_date}");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=panel_config_migration.js.map
|
||||||
+1
File diff suppressed because one or more lines are too long
Vendored
+200
-28
@@ -3,7 +3,7 @@
|
|||||||
System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var d3, $, _, TOOLTIP_PADDING_X, TOOLTIP_PADDING_Y, StatusmapTooltip;
|
var d3, $, _, TOOLTIP_PADDING_X, TOOLTIP_PADDING_Y, DefaultValueDateFormat, StatusmapTooltip;
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
@@ -23,7 +23,10 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
}],
|
}],
|
||||||
execute: function () {
|
execute: function () {
|
||||||
TOOLTIP_PADDING_X = 30;
|
TOOLTIP_PADDING_X = 30;
|
||||||
TOOLTIP_PADDING_Y = 5;
|
TOOLTIP_PADDING_Y = 5; // TODO rename file to tooltip_ctrl.ts
|
||||||
|
// TODO move DefaultValueDateFormat into tooltip.ts, as it used in several places (migration, partial and tooltip render)
|
||||||
|
|
||||||
|
DefaultValueDateFormat = 'YYYY/MM/DD/HH_mm_ss';
|
||||||
|
|
||||||
_export("StatusmapTooltip", StatusmapTooltip =
|
_export("StatusmapTooltip", StatusmapTooltip =
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
@@ -41,17 +44,21 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
|
|
||||||
_defineProperty(this, "panel", void 0);
|
_defineProperty(this, "panel", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "heatmapPanel", void 0);
|
_defineProperty(this, "panelElem", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "mouseOverBucket", void 0);
|
_defineProperty(this, "mouseOverBucket", void 0);
|
||||||
|
|
||||||
_defineProperty(this, "originalFillColor", void 0);
|
_defineProperty(this, "originalFillColor", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "tooltipWidth", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "tooltipFrozen", void 0);
|
||||||
|
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.dashboard = scope.ctrl.dashboard;
|
this.dashboard = scope.ctrl.dashboard;
|
||||||
this.panelCtrl = scope.ctrl;
|
this.panelCtrl = scope.ctrl;
|
||||||
this.panel = scope.ctrl.panel;
|
this.panel = scope.ctrl.panel;
|
||||||
this.heatmapPanel = elem;
|
this.panelElem = elem;
|
||||||
this.mouseOverBucket = false;
|
this.mouseOverBucket = false;
|
||||||
this.originalFillColor = null;
|
this.originalFillColor = null;
|
||||||
elem.on("mouseover", this.onMouseOver.bind(this));
|
elem.on("mouseover", this.onMouseOver.bind(this));
|
||||||
@@ -67,7 +74,7 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
|
|
||||||
if (!this.tooltip) {
|
if (!this.tooltip) {
|
||||||
this.add();
|
this.add();
|
||||||
this.move(e);
|
this.move(e, this.tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -82,12 +89,12 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.move(e);
|
this.move(e, this.tooltip);
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "add",
|
key: "add",
|
||||||
value: function add() {
|
value: function add() {
|
||||||
this.tooltip = d3.select("body").append("div").attr("class", "statusmap-tooltip graph-tooltip grafana-tooltip");
|
this.tooltip = d3.select("body").append("div").attr("class", "graph-tooltip statusmap-tooltip");
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "destroy",
|
key: "destroy",
|
||||||
@@ -98,6 +105,22 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
|
|
||||||
this.tooltip = null;
|
this.tooltip = null;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
key: "removeFrozen",
|
||||||
|
value: function removeFrozen() {
|
||||||
|
if (this.tooltipFrozen) {
|
||||||
|
this.tooltipFrozen.remove();
|
||||||
|
this.tooltipFrozen = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "showFrozen",
|
||||||
|
value: function showFrozen(pos) {
|
||||||
|
this.removeFrozen();
|
||||||
|
this.tooltipFrozen = d3.select(this.panelElem[0]).append("div").attr("class", "graph-tooltip statusmap-tooltip statusmap-tooltip-frozen");
|
||||||
|
this.displayTooltip(pos, this.tooltipFrozen, true);
|
||||||
|
this.moveRelative(pos, this.tooltipFrozen);
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
key: "show",
|
key: "show",
|
||||||
value: function show(pos) {
|
value: function show(pos) {
|
||||||
@@ -110,6 +133,13 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.displayTooltip(pos, this.tooltip, false);
|
||||||
|
this.move(pos, this.tooltip);
|
||||||
|
} // Retrieve bucket and create html content inside tooltip’s div element.
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: "displayTooltip",
|
||||||
|
value: function displayTooltip(pos, tooltip, frozen) {
|
||||||
var cardEl = d3.select(pos.target);
|
var cardEl = d3.select(pos.target);
|
||||||
var yid = cardEl.attr('yid');
|
var yid = cardEl.attr('yid');
|
||||||
var xid = cardEl.attr('xid');
|
var xid = cardEl.attr('xid');
|
||||||
@@ -121,41 +151,137 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var timestamp = bucket.to;
|
var timestamp = bucket.to;
|
||||||
var name = bucket.yLabel;
|
var yLabel = bucket.yLabel;
|
||||||
var value = bucket.value;
|
var value = bucket.value;
|
||||||
var values = bucket.values;
|
var values = bucket.values; // TODO create option for this formatting.
|
||||||
|
|
||||||
var tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';
|
var tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';
|
||||||
var time = this.dashboard.formatDate(+timestamp, tooltipTimeFormat);
|
var time = this.dashboard.formatDate(+timestamp, tooltipTimeFormat); // Close button for the frozen tooltip.
|
||||||
var tooltipHtml = "<div class=\"graph-tooltip-time\">".concat(time, "</div>\n <div class=\"statusmap-histogram\"></div>");
|
|
||||||
var statuses;
|
var tooltipClose = "";
|
||||||
|
|
||||||
|
if (frozen) {
|
||||||
|
tooltipClose = "\n<a class=\"pointer pull-right small tooltip-close\">\n <i class=\"fa fa-remove\"></i>\n</a>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
var tooltipHtml = "<div class=\"graph-tooltip-time\">".concat(time).concat(tooltipClose, "</div>");
|
||||||
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
if (this.panel.color.mode === 'discrete') {
|
||||||
|
var statuses;
|
||||||
|
|
||||||
if (this.panel.seriesFilterIndex >= 0) {
|
if (this.panel.seriesFilterIndex >= 0) {
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
||||||
} else {
|
} else {
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusesHtml = '';
|
var statusTitle = "status:";
|
||||||
|
|
||||||
if (statuses.length === 1) {
|
if (statuses.length > 1) {
|
||||||
statusesHtml = "status:";
|
statusTitle = "statuses:";
|
||||||
} else if (statuses.length > 1) {
|
|
||||||
statusesHtml = "statuses:";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltipHtml += "\n <div>\n name: <b>".concat(name, "</b> <br>\n ").concat(statusesHtml, "\n <ul>\n ").concat(_.join(_.map(statuses, function (v) {
|
tooltipHtml += "\n <div>\n name: <b>".concat(yLabel, "</b>\n <br>\n <span>").concat(statusTitle, "</span>\n <ul>\n ").concat(_.join(_.map(statuses, function (v) {
|
||||||
return "<li style=\"background-color: ".concat(v.color, "\" class=\"discrete-item\">").concat(v.tooltip, "</li>");
|
return "<li style=\"background-color: ".concat(v.color, "; text-align:center\" class=\"discrete-item\">").concat(v.tooltip, "</li>");
|
||||||
}), ""), "\n </ul>\n </div>");
|
}), ""), "\n </ul>\n </div>");
|
||||||
} else {
|
} else {
|
||||||
if (values.length === 1) {
|
if (values.length === 1) {
|
||||||
tooltipHtml += "<div> \n name: <b>".concat(name, "</b> <br>\n value: <b>").concat(value, "</b> <br>\n </div>");
|
tooltipHtml += "<div> \n name: <b>".concat(name, "</b> <br>\n value: <b>").concat(value, "</b> <br>\n </div>");
|
||||||
} else {
|
} else {
|
||||||
tooltipHtml += "<div>\n name: <b>".concat(name, "}</b> <br>\n values:\n <ul>\n ").concat(_.join(_.map(values, function (v) {
|
tooltipHtml += "<div>\n name: <b>".concat(name, "</b> <br>\n values:\n <ul>\n ").concat(_.join(_.map(values, function (v) {
|
||||||
return "<li>".concat(v, "</li>");
|
return "<li>".concat(v, "</li>");
|
||||||
}), ""), "\n </ul>\n </div>");
|
}), ""), "\n </ul>\n </div>");
|
||||||
}
|
}
|
||||||
} // "Ambiguous bucket state: Multiple values!";
|
}
|
||||||
|
|
||||||
|
tooltipHtml += "<div class=\"statusmap-histogram\"></div>";
|
||||||
|
|
||||||
|
if (this.panel.tooltip.showItems) {
|
||||||
|
// Additional information: urls, etc.
|
||||||
|
// Clone additional items
|
||||||
|
var items = JSON.parse(JSON.stringify(this.panel.tooltip.items));
|
||||||
|
var scopedVars = {};
|
||||||
|
var valueVar;
|
||||||
|
|
||||||
|
for (var i = 0; i < bucket.values.length; i++) {
|
||||||
|
valueVar = "__value_".concat(i);
|
||||||
|
scopedVars[valueVar] = {
|
||||||
|
value: bucket.values[i]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
scopedVars["__value"] = {
|
||||||
|
value: bucket.value
|
||||||
|
};
|
||||||
|
scopedVars["__y_label"] = {
|
||||||
|
value: yLabel
|
||||||
|
}; // Grafana 7.0 compatible
|
||||||
|
|
||||||
|
scopedVars["__url_time_range"] = {
|
||||||
|
value: this.panelCtrl.retrieveTimeVar()
|
||||||
|
};
|
||||||
|
var _iteratorNormalCompletion = true;
|
||||||
|
var _didIteratorError = false;
|
||||||
|
var _iteratorError = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (var _iterator = items[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||||
|
var item = _step.value;
|
||||||
|
|
||||||
|
if (_.isEmpty(item.urlTemplate)) {
|
||||||
|
item.link = "#";
|
||||||
|
} else {
|
||||||
|
var dateFormat = item.valueDateFormat;
|
||||||
|
|
||||||
|
if (dateFormat == '') {
|
||||||
|
dateFormat = DefaultValueDateFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
var valueDateVar = void 0;
|
||||||
|
|
||||||
|
for (var _i = 0; _i < bucket.values.length; _i++) {
|
||||||
|
valueDateVar = "__value_".concat(_i, "_date");
|
||||||
|
scopedVars[valueDateVar] = {
|
||||||
|
value: this.dashboard.formatDate(+bucket.values[_i], dateFormat)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
scopedVars["__value_date"] = {
|
||||||
|
value: this.dashboard.formatDate(+bucket.value, dateFormat)
|
||||||
|
};
|
||||||
|
item.link = this.panelCtrl.templateSrv.replace(item.urlTemplate, scopedVars); // Force lowercase for link
|
||||||
|
|
||||||
|
if (item.urlToLowerCase) {
|
||||||
|
item.link = item.link.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.label = item.urlText;
|
||||||
|
|
||||||
|
if (_.isEmpty(item.label)) {
|
||||||
|
item.label = _.isEmpty(item.urlTemplate) ? "Empty URL" : _.truncate(item.link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
_didIteratorError = true;
|
||||||
|
_iteratorError = err;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
|
||||||
|
_iterator["return"]();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (_didIteratorError) {
|
||||||
|
throw _iteratorError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltipHtml += _.join(_.map(items, function (v) {
|
||||||
|
return "\n <div>\n <a href=\"".concat(v.link, "\" target=\"_blank\">\n <div class=\"dashlist-item\">\n <p class=\"dashlist-link dashlist-link-dash-db\">\n <span style=\"word-wrap: break-word;\" class=\"dash-title\">").concat(v.label, "</span><span class=\"dashlist-star\">\n <i class=\"fa fa-").concat(v.urlIcon, "\"></i>\n </span></p> </div></a><div>");
|
||||||
|
}), "\n");
|
||||||
|
} // Ambiguous state: there multiple values in bucket!
|
||||||
|
// TODO rename useMax to expectMultipleValues
|
||||||
|
|
||||||
|
|
||||||
if (!this.panel.useMax && bucket.multipleValues) {
|
if (!this.panel.useMax && bucket.multipleValues) {
|
||||||
@@ -172,18 +298,32 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tooltip.html(tooltipHtml);
|
tooltip.html(tooltipHtml); // Assign mouse event handlers for "frozen" tooltip.
|
||||||
this.move(pos);
|
|
||||||
}
|
if (frozen) {
|
||||||
|
// Stop propagation mouse events up to parents to allow interaction with frozen tooltip’s elements.
|
||||||
|
tooltip.on("click", function () {
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
}).on("mousedown", function () {
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
}).on("mouseup", function () {
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
}); // Activate close button
|
||||||
|
|
||||||
|
tooltip.select("a.tooltip-close").on("click", this.removeFrozen.bind(this));
|
||||||
|
}
|
||||||
|
} // Move tooltip as absolute positioned element.
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
key: "move",
|
key: "move",
|
||||||
value: function move(pos) {
|
value: function move(pos, tooltip) {
|
||||||
if (!this.tooltip) {
|
if (!tooltip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var elem = $(this.tooltip.node())[0];
|
var elem = $(tooltip.node())[0];
|
||||||
var tooltipWidth = elem.clientWidth;
|
var tooltipWidth = elem.clientWidth;
|
||||||
|
this.tooltipWidth = tooltipWidth;
|
||||||
var tooltipHeight = elem.clientHeight;
|
var tooltipHeight = elem.clientHeight;
|
||||||
var left = pos.pageX + TOOLTIP_PADDING_X;
|
var left = pos.pageX + TOOLTIP_PADDING_X;
|
||||||
var top = pos.pageY + TOOLTIP_PADDING_Y;
|
var top = pos.pageY + TOOLTIP_PADDING_Y;
|
||||||
@@ -196,7 +336,39 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
|
|||||||
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tooltip.style("left", left + "px").style("top", top + "px");
|
return tooltip.style("left", left + "px").style("top", top + "px");
|
||||||
|
} // Move tooltip relative to svg element of panel.
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: "moveRelative",
|
||||||
|
value: function moveRelative(pos, tooltip) {
|
||||||
|
if (!tooltip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var panelX = pos.pageX - this.panelElem.offset().left;
|
||||||
|
var panelY = pos.pageY - this.panelElem.offset().top;
|
||||||
|
var panelWidth = this.panelElem.width();
|
||||||
|
var panelHeight = this.panelElem.height(); // 'position: relative' sets tooltip’s width to 100% of panel element.
|
||||||
|
// Restore width from floating tooltip and add more space for 'Close' button.
|
||||||
|
|
||||||
|
var tooltipWidth = this.tooltipWidth + 25; // Left property is clamped so tooltip stays inside panel bound box.
|
||||||
|
|
||||||
|
var tooltipLeft = panelX + TOOLTIP_PADDING_X;
|
||||||
|
|
||||||
|
if (tooltipLeft + tooltipWidth > panelWidth) {
|
||||||
|
tooltipLeft = panelWidth - tooltipWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tooltipLeft < 0) {
|
||||||
|
tooltipLeft = 0;
|
||||||
|
} // Frozen tooltip’s root element is appended next to panel’s svg element,
|
||||||
|
// so top property is adjusted to move tooltip’s root element
|
||||||
|
// up to the mouse pointer position.
|
||||||
|
|
||||||
|
|
||||||
|
var tooltipTop = -(panelHeight - panelY + TOOLTIP_PADDING_Y);
|
||||||
|
return tooltip.style("left", tooltipLeft + "px").style("top", tooltipTop + "px").style("width", tooltipWidth + "px");
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+95
@@ -0,0 +1,95 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
System.register([], function (_export, _context) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var emptyTooltipItem, TooltipEditorCtrl;
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
||||||
|
|
||||||
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
||||||
|
|
||||||
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
|
|
||||||
|
function tooltipEditorCtrl() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: true,
|
||||||
|
templateUrl: 'public/plugins/flant-statusmap-panel/partials/tooltip_editor.html',
|
||||||
|
controller: TooltipEditorCtrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_export("tooltipEditorCtrl", tooltipEditorCtrl);
|
||||||
|
|
||||||
|
return {
|
||||||
|
setters: [],
|
||||||
|
execute: function () {
|
||||||
|
emptyTooltipItem = {
|
||||||
|
urlText: '',
|
||||||
|
urlTemplate: '',
|
||||||
|
urlIcon: 'external-link',
|
||||||
|
urlToLowerCase: true,
|
||||||
|
valueDateFormat: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
_export("TooltipEditorCtrl", TooltipEditorCtrl =
|
||||||
|
/*#__PURE__*/
|
||||||
|
function () {
|
||||||
|
function TooltipEditorCtrl($scope) {
|
||||||
|
_classCallCheck(this, TooltipEditorCtrl);
|
||||||
|
|
||||||
|
_defineProperty(this, "panel", void 0);
|
||||||
|
|
||||||
|
_defineProperty(this, "panelCtrl", void 0);
|
||||||
|
|
||||||
|
$scope.editor = this;
|
||||||
|
this.panelCtrl = $scope.ctrl;
|
||||||
|
this.panel = this.panelCtrl.panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(TooltipEditorCtrl, [{
|
||||||
|
key: "render",
|
||||||
|
value: function render() {
|
||||||
|
this.panelCtrl.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onAddUrl",
|
||||||
|
value: function onAddUrl() {
|
||||||
|
this.panel.tooltip.items.push(Object.assign({}, emptyTooltipItem));
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onRemoveUrl",
|
||||||
|
value: function onRemoveUrl(index) {
|
||||||
|
this.panel.tooltip.items.splice(index, 1);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "onRemoveUrls",
|
||||||
|
value: function onRemoveUrls() {
|
||||||
|
this.panel.tooltip.items = [];
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "getFAIconClasses",
|
||||||
|
value: function getFAIconClasses() {
|
||||||
|
return ['external-link', 'plus', 'anchor', 'ban', 'globe', 'gear', 'cloud', 'download', 'cloud-download'];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: "getValueDateFormats",
|
||||||
|
value: function getValueDateFormats() {
|
||||||
|
return ['YYYY/MM/DD/HH_mm_ss', 'YYYYMMDDHHmmss', 'YYYY-MM-DD-HH-mm-ss'];
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return TooltipEditorCtrl;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=tooltip_editor.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../src/tooltip_editor.ts"],"names":["tooltipEditorCtrl","restrict","scope","templateUrl","controller","TooltipEditorCtrl","emptyTooltipItem","urlText","urlTemplate","urlIcon","urlToLowerCase","valueDateFormat","$scope","editor","panelCtrl","ctrl","panel","render","tooltip","items","push","Object","assign","index","splice"],"mappings":";;;;;;;;;;;;;;;AAoDO,WAASA,iBAAT,GAA6B;AAClC;;AACA,WAAO;AACLC,MAAAA,QAAQ,EAAE,GADL;AAELC,MAAAA,KAAK,EAAE,IAFF;AAGLC,MAAAA,WAAW,EAAE,mEAHR;AAILC,MAAAA,UAAU,EAAEC;AAJP,KAAP;AAMD;;+BAReL,iB;;;;;AAlDZM,MAAAA,gB,GAAmB;AACrBC,QAAAA,OAAO,EAAE,EADY;AAErBC,QAAAA,WAAW,EAAE,EAFQ;AAGrBC,QAAAA,OAAO,EAAE,eAHY;AAIrBC,QAAAA,cAAc,EAAE,IAJK;AAKrBC,QAAAA,eAAe,EAAE;AALI,O;;mCAQVN,iB;;;AAIX,mCAAYO,MAAZ,EAAyB;AAAA;;AAAA;;AAAA;;AACvBA,UAAAA,MAAM,CAACC,MAAP,GAAgB,IAAhB;AACA,eAAKC,SAAL,GAAiBF,MAAM,CAACG,IAAxB;AACA,eAAKC,KAAL,GAAa,KAAKF,SAAL,CAAeE,KAA5B;AACD;;;;mCAEQ;AACP,iBAAKF,SAAL,CAAeG,MAAf;AACD;;;qCAEU;AACT,iBAAKD,KAAL,CAAWE,OAAX,CAAmBC,KAAnB,CAAyBC,IAAzB,CAA8BC,MAAM,CAACC,MAAP,CAAc,EAAd,EAAkBhB,gBAAlB,CAA9B;AACA,iBAAKW,MAAL;AACD;;;sCAEWM,K,EAAe;AACzB,iBAAKP,KAAL,CAAWE,OAAX,CAAmBC,KAAnB,CAAyBK,MAAzB,CAAgCD,KAAhC,EAAuC,CAAvC;AACA,iBAAKN,MAAL;AACD;;;yCAEc;AACb,iBAAKD,KAAL,CAAWE,OAAX,CAAmBC,KAAnB,GAA2B,EAA3B;AACA,iBAAKF,MAAL;AACD;;;6CAEkB;AACjB,mBAAO,CAAC,eAAD,EAAkB,MAAlB,EAA0B,QAA1B,EAAoC,KAApC,EAA2C,OAA3C,EAAoD,MAApD,EAA4D,OAA5D,EAAqE,UAArE,EAAiF,gBAAjF,CAAP;AACD;;;gDAEqB;AACpB,mBAAO,CACH,qBADG,EAEH,gBAFG,EAGH,qBAHG,CAAP;AAKD","sourcesContent":["import { StatusHeatmapCtrl } from './module';\n\nlet emptyTooltipItem = {\n urlText: '',\n urlTemplate: '',\n urlIcon: 'external-link',\n urlToLowerCase: true,\n valueDateFormat: ''\n};\n\nexport class TooltipEditorCtrl {\n panel: any;\n panelCtrl: StatusHeatmapCtrl;\n\n constructor($scope: any) {\n $scope.editor = this;\n this.panelCtrl = $scope.ctrl as StatusHeatmapCtrl;\n this.panel = this.panelCtrl.panel;\n }\n\n render() {\n this.panelCtrl.render();\n }\n\n onAddUrl() {\n this.panel.tooltip.items.push(Object.assign({}, emptyTooltipItem));\n this.render();\n }\n\n onRemoveUrl(index: number) {\n this.panel.tooltip.items.splice(index, 1);\n this.render();\n }\n\n onRemoveUrls() {\n this.panel.tooltip.items = [];\n this.render();\n }\n\n getFAIconClasses() {\n return ['external-link', 'plus', 'anchor', 'ban', 'globe', 'gear', 'cloud', 'download', 'cloud-download'];\n }\n\n getValueDateFormats() {\n return [\n 'YYYY/MM/DD/HH_mm_ss',\n 'YYYYMMDDHHmmss',\n 'YYYY-MM-DD-HH-mm-ss'\n ];\n }\n}\n\nexport function tooltipEditorCtrl() {\n 'use strict';\n return {\n restrict: 'E',\n scope: true,\n templateUrl: 'public/plugins/flant-statusmap-panel/partials/tooltip_editor.html',\n controller: TooltipEditorCtrl,\n };\n}\n"],"file":"tooltip_editor.js"}
|
||||||
Vendored
-242
@@ -1,242 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
System.register(["d3", "lodash", "jquery", "./extra_series_format"], function (_export, _context) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var d3, _, $, ExtraSeriesFormatValue, TOOLTIP_PADDING_X, TOOLTIP_PADDING_Y, StatusHeatmapTooltipExtraSeries;
|
|
||||||
|
|
||||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
||||||
|
|
||||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
||||||
|
|
||||||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
||||||
|
|
||||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
||||||
|
|
||||||
return {
|
|
||||||
setters: [function (_d) {
|
|
||||||
d3 = _d.default;
|
|
||||||
}, function (_lodash) {
|
|
||||||
_ = _lodash.default;
|
|
||||||
}, function (_jquery) {
|
|
||||||
$ = _jquery.default;
|
|
||||||
}, function (_extra_series_format) {
|
|
||||||
ExtraSeriesFormatValue = _extra_series_format.ExtraSeriesFormatValue;
|
|
||||||
}],
|
|
||||||
execute: function () {
|
|
||||||
TOOLTIP_PADDING_X = -50;
|
|
||||||
TOOLTIP_PADDING_Y = 5;
|
|
||||||
|
|
||||||
_export("StatusHeatmapTooltipExtraSeries", StatusHeatmapTooltipExtraSeries =
|
|
||||||
/*#__PURE__*/
|
|
||||||
function () {
|
|
||||||
function StatusHeatmapTooltipExtraSeries(elem, scope) {
|
|
||||||
_classCallCheck(this, StatusHeatmapTooltipExtraSeries);
|
|
||||||
|
|
||||||
_defineProperty(this, "scope", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "dashboard", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "panelCtrl", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "panel", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "heatmapPanel", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "mouseOverBucket", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "originalFillColor", void 0);
|
|
||||||
|
|
||||||
_defineProperty(this, "tooltip", void 0);
|
|
||||||
|
|
||||||
this.scope = scope;
|
|
||||||
this.dashboard = scope.ctrl.dashboard;
|
|
||||||
this.panelCtrl = scope.ctrl;
|
|
||||||
this.panel = scope.ctrl.panel;
|
|
||||||
this.heatmapPanel = elem;
|
|
||||||
this.mouseOverBucket = false;
|
|
||||||
this.originalFillColor = null;
|
|
||||||
elem.on("mouseover", this.onMouseOver.bind(this));
|
|
||||||
elem.on("click", this.onMouseClick.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_createClass(StatusHeatmapTooltipExtraSeries, [{
|
|
||||||
key: "onMouseOver",
|
|
||||||
value: function onMouseOver(e) {
|
|
||||||
if (!this.panel.usingUrl || !this.scope.ctrl.data || _.isEmpty(this.scope.ctrl.data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "onMouseClick",
|
|
||||||
value: function onMouseClick(e) {
|
|
||||||
if (!this.panel.usingUrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.destroy();
|
|
||||||
this.add();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "add",
|
|
||||||
value: function add() {
|
|
||||||
this.tooltip = d3.select("body").append("div").attr("class", "statusmap-tooltip-extraseries graph-tooltip grafana-tooltip");
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "destroy",
|
|
||||||
value: function destroy() {
|
|
||||||
if (this.tooltip) {
|
|
||||||
this.tooltip.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tooltip = null;
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "show",
|
|
||||||
value: function show(pos) {
|
|
||||||
if (!this.panel.usingUrl || !this.tooltip) {
|
|
||||||
return;
|
|
||||||
} // shared tooltip mode
|
|
||||||
|
|
||||||
|
|
||||||
if (pos.panelRelY) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cardId = d3.select(pos.target).attr('cardId');
|
|
||||||
|
|
||||||
if (!cardId) {
|
|
||||||
this.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var card = this.panelCtrl.cardsData.cards[cardId];
|
|
||||||
|
|
||||||
if (!card) {
|
|
||||||
this.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (card.value == null) {
|
|
||||||
this.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var x = card.x;
|
|
||||||
var y = card.y;
|
|
||||||
var value = card.value;
|
|
||||||
var values = card.values;
|
|
||||||
var tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';
|
|
||||||
var time = this.dashboard.formatDate(+x, tooltipTimeFormat);
|
|
||||||
var tooltipHtml = "<div class=\"graph-tooltip-time\">".concat(time, "</div>");
|
|
||||||
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
|
||||||
var statuses = "";
|
|
||||||
|
|
||||||
if (this.panelCtrl.panel.seriesFilterIndex == -1) {
|
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
|
||||||
} else {
|
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltipHtml += "\n <div>\n name: <b>".concat(y, "</b>\n <div>\n <br>\n <span>status:</span>\n <ul>\n ").concat(_.join(_.map(statuses, function (v) {
|
|
||||||
return "<p style=\"background-color: ".concat(v.color, "; text-align:center\" class=\"discrete-item\">").concat(v.tooltip, "</p>");
|
|
||||||
}), ""), "\n </ul>\n </div> \n </div> <br>");
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltipHtml += "<div class=\"statusmap-histogram\"></div>";
|
|
||||||
var urls = this.panelCtrl.panel.urls;
|
|
||||||
var rtime = this.panelCtrl.retrieveTimeVar();
|
|
||||||
var curl = JSON.parse(JSON.stringify(urls));
|
|
||||||
|
|
||||||
for (var i = 0; i < curl.length; i++) {
|
|
||||||
//Change name var
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$series_label/g, y); //Set up extra series
|
|
||||||
|
|
||||||
if (curl[i].useExtraSeries == true) {
|
|
||||||
var tf = curl[i].extraSeries.format;
|
|
||||||
var vh = card.values[curl[i].extraSeries.index]; //let extraSeries: any = this.dashboard.formatDate(+vh, tf)
|
|
||||||
|
|
||||||
var series_extra = this.formatExtraSeries(vh, tf);
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$series_extra/g, series_extra);
|
|
||||||
} //Change time var
|
|
||||||
|
|
||||||
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$time/g, rtime); //Replace vars
|
|
||||||
|
|
||||||
curl[i].base_url = this.panelCtrl.renderLink(curl[i].base_url, this.panelCtrl.variableSrv.variables);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.panelCtrl.panel.usingUrl == true) {
|
|
||||||
tooltipHtml += "\n <div bs-tooltip='Settings' data-placement=\"right\">\n ".concat(_.join(_.map(curl, function (v) {
|
|
||||||
return "<div ><a href=\"".concat(v.forcelowercase ? v.base_url.toLowerCase() : v.base_url, "\" target=\"_blank\"><div class=\"dashlist-item\">\n <p class=\"dashlist-link dashlist-link-dash-db\"><span style=\"word-wrap: break-word;\" class=\"dash-title\">").concat(v.label ? v.label : v.base_url != "" ? _.truncate(v.base_url) : "Empty URL", "</span><span class=\"dashlist-star\">\n <i class=\"fa fa-").concat(v.icon_fa, "\"></i>\n </span></p> </div></a><div>");
|
|
||||||
}), ""), "\n </div> <br>");
|
|
||||||
} // "Ambiguous bucket state: Multiple values!";
|
|
||||||
|
|
||||||
|
|
||||||
if (!this.panel.useMax && card.multipleValues) {
|
|
||||||
tooltipHtml += "<div><b>Error:</b> ".concat(this.panelCtrl.dataWarnings.multipleValues.title, "</div>");
|
|
||||||
} // Discrete mode errors
|
|
||||||
|
|
||||||
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
|
||||||
if (card.noColorDefined) {
|
|
||||||
var badValues = this.panelCtrl.discreteExtraSeries.getNotColoredValues(values);
|
|
||||||
tooltipHtml += "<div><b>Error:</b> ".concat(this.panelCtrl.dataWarnings.noColorDefined.title, "\n <br>not colored values:\n <ul>\n ").concat(_.join(_.map(badValues, function (v) {
|
|
||||||
return "<li>".concat(v, "</li>");
|
|
||||||
}), ""), "\n </ul>\n </div>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tooltip.html(tooltipHtml);
|
|
||||||
this.move(pos);
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "formatExtraSeries",
|
|
||||||
value: function formatExtraSeries(value, type) {
|
|
||||||
var extraSeries = '';
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case ExtraSeriesFormatValue.Date:
|
|
||||||
extraSeries = this.dashboard.formatDate(+value, type);
|
|
||||||
return extraSeries;
|
|
||||||
|
|
||||||
case ExtraSeriesFormatValue.Raw:
|
|
||||||
extraSeries = value;
|
|
||||||
return extraSeries;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return extraSeries;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
key: "move",
|
|
||||||
value: function move(pos) {
|
|
||||||
if (!this.tooltip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var elem = $(this.tooltip.node())[0];
|
|
||||||
var tooltipWidth = elem.clientWidth;
|
|
||||||
var tooltipHeight = elem.clientHeight;
|
|
||||||
var left = pos.pageX + TOOLTIP_PADDING_X;
|
|
||||||
var top = pos.pageY + TOOLTIP_PADDING_Y;
|
|
||||||
|
|
||||||
if (pos.pageX + tooltipWidth + 40 > window.innerWidth) {
|
|
||||||
left = pos.pageX - tooltipWidth - TOOLTIP_PADDING_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos.pageY - window.pageYOffset + tooltipHeight + 20 > window.innerHeight) {
|
|
||||||
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tooltip.style("left", left + "px").style("top", top + "px");
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
return StatusHeatmapTooltipExtraSeries;
|
|
||||||
}());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=tooltipextraseries.js.map
|
|
||||||
Vendored
-1
File diff suppressed because one or more lines are too long
+14
-18
@@ -63,10 +63,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"data": {
|
|
||||||
"decimals": null,
|
|
||||||
"unitFormat": "short"
|
|
||||||
},
|
|
||||||
"datasource": "prometheus",
|
"datasource": "prometheus",
|
||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 16,
|
"h": 16,
|
||||||
@@ -130,21 +126,21 @@
|
|||||||
],
|
],
|
||||||
"title": "Pod Status",
|
"title": "Pod Status",
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"show": true
|
"show": true,
|
||||||
|
"freezeOnClick": false,
|
||||||
|
"showItems": false,
|
||||||
|
"items": []
|
||||||
},
|
},
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"type": "flant-statusmap-panel",
|
"type": "flant-statusmap-panel",
|
||||||
"useMax": true,
|
"useMax": true,
|
||||||
"xAxis": {
|
"xAxis": {
|
||||||
"labelFormat": "%a %m/%d",
|
"show": true
|
||||||
"minBucketWidthToShowWeekends": 4,
|
|
||||||
"show": true,
|
|
||||||
"showCrosshair": true,
|
|
||||||
"showWeekends": true
|
|
||||||
},
|
},
|
||||||
"yAxis": {
|
"yAxis": {
|
||||||
"show": true,
|
"show": true,
|
||||||
"showCrosshair": false
|
"minWidth": -1,
|
||||||
|
"maxWidth": -1
|
||||||
},
|
},
|
||||||
"yAxisSort": "a → z"
|
"yAxisSort": "a → z"
|
||||||
},
|
},
|
||||||
@@ -310,21 +306,21 @@
|
|||||||
],
|
],
|
||||||
"title": "Container Status",
|
"title": "Container Status",
|
||||||
"tooltip": {
|
"tooltip": {
|
||||||
"show": true
|
"show": true,
|
||||||
|
"freezeOnClick": true,
|
||||||
|
"showItems": false,
|
||||||
|
"items": []
|
||||||
},
|
},
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"type": "flant-statusmap-panel",
|
"type": "flant-statusmap-panel",
|
||||||
"useMax": true,
|
"useMax": true,
|
||||||
"xAxis": {
|
"xAxis": {
|
||||||
"labelFormat": "%a %m/%d",
|
"show": true
|
||||||
"minBucketWidthToShowWeekends": 4,
|
|
||||||
"show": true,
|
|
||||||
"showCrosshair": true,
|
|
||||||
"showWeekends": true
|
|
||||||
},
|
},
|
||||||
"yAxis": {
|
"yAxis": {
|
||||||
"show": true,
|
"show": true,
|
||||||
"showCrosshair": false
|
"minWidth": -1,
|
||||||
|
"maxWidth": -1
|
||||||
},
|
},
|
||||||
"yAxisSort": "a → z"
|
"yAxisSort": "a → z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
verbose: false,
|
||||||
|
transform: {
|
||||||
|
'^.+\\.(ts|tsx)$': 'ts-jest',
|
||||||
|
},
|
||||||
|
moduleDirectories: ['node_modules'],
|
||||||
|
roots: ['<rootDir>/src'],
|
||||||
|
testRegex: '(\\.|/)(test)\\.(jsx?|tsx?)$',
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||||
|
//setupFiles: ['jest-canvas-mock', './public/test/jest-shim.ts', './public/test/jest-setup.ts'],
|
||||||
|
//snapshotSerializers: ['enzyme-to-json/serializer'],
|
||||||
|
globals: { 'ts-jest': { isolatedModules: true } },
|
||||||
|
};
|
||||||
Generated
+2225
-1
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -5,7 +5,8 @@
|
|||||||
"main": "README.md",
|
"main": "README.md",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "grunt",
|
"build": "grunt",
|
||||||
"check-types": "node_modules/typescript/bin/tsc"
|
"check-types": "node_modules/typescript/bin/tsc",
|
||||||
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"author": "Flant JSC",
|
"author": "Flant JSC",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
"@types/d3-scale-chromatic": "1.3.1",
|
"@types/d3-scale-chromatic": "1.3.1",
|
||||||
"@types/angular": "1.6.56",
|
"@types/angular": "1.6.56",
|
||||||
"@types/grafana": "github:flant/types-grafana",
|
"@types/grafana": "github:flant/types-grafana",
|
||||||
|
"@types/jest": "24.0.13",
|
||||||
"@types/jquery": "1.10.35",
|
"@types/jquery": "1.10.35",
|
||||||
"@types/lodash": "4.14.123",
|
"@types/lodash": "4.14.123",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
@@ -43,8 +45,12 @@
|
|||||||
"grunt-contrib-uglify": "^3.0.1",
|
"grunt-contrib-uglify": "^3.0.1",
|
||||||
"grunt-contrib-watch": "^1.0.0",
|
"grunt-contrib-watch": "^1.0.0",
|
||||||
"grunt-notify": "^0.4.5",
|
"grunt-notify": "^0.4.5",
|
||||||
|
"jest": "24.8.0",
|
||||||
|
"jest-canvas-mock": "2.1.2",
|
||||||
|
"jest-date-mock": "1.0.7",
|
||||||
"load-grunt-tasks": "^3.5.2",
|
"load-grunt-tasks": "^3.5.2",
|
||||||
"typescript": "3.7.2",
|
"typescript": "3.7.2",
|
||||||
|
"ts-jest": "24.1.0",
|
||||||
"tslib": "1.10.0"
|
"tslib": "1.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ coreModule.directive('optionsColorLegend', function() {
|
|||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
template: '<div class="status-heatmap-color-legend"><svg width="16.8rem" height="24px"></svg></div>',
|
template: '<div class="status-heatmap-color-legend"><svg width="16.8rem" height="24px"></svg></div>',
|
||||||
link: function(scope, elem, attrs) {
|
link: function(scope: any, elem, attrs) {
|
||||||
let ctrl = scope.ctrl;
|
let ctrl = scope.ctrl;
|
||||||
let panel = scope.ctrl.panel;
|
let panel = scope.ctrl.panel;
|
||||||
|
|
||||||
|
|||||||
+16
-13
@@ -41,6 +41,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.statusmap-tooltip {
|
.statusmap-tooltip {
|
||||||
|
// from .grafana-tooltip
|
||||||
|
// '.grafana-tooltip a' makes links not readable for tooltip items.
|
||||||
|
position: absolute;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: 200;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-width: 800px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 14px;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
// more overrides
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
background-color: $graph-tooltip-bg;
|
background-color: $graph-tooltip-bg;
|
||||||
@@ -54,19 +67,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusmap-tooltip-extraseries {
|
.statusmap-tooltip-frozen {
|
||||||
white-space: nowrap;
|
position: relative;
|
||||||
font-size: $font-size-sm;
|
z-index: 1;
|
||||||
background-color: $graph-tooltip-bg;
|
|
||||||
color: $text-color;
|
|
||||||
|
|
||||||
.discrete-item {
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 1px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 0;
|
|
||||||
text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusmap-histogram rect {
|
.statusmap-histogram rect {
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
export enum ExtraSeriesFormat {
|
|
||||||
Date = 'Date',
|
|
||||||
Raw = 'Raw',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ExtraSeriesFormatValue {
|
|
||||||
Date = 'YYYY/MM/DD/HH_mm_ss',
|
|
||||||
Raw = '',
|
|
||||||
}
|
|
||||||
+21
-273
@@ -4,6 +4,9 @@ import { auto } from 'angular';
|
|||||||
|
|
||||||
// Components
|
// Components
|
||||||
import './color_legend';
|
import './color_legend';
|
||||||
|
import { optionsEditorCtrl } from './options_editor';
|
||||||
|
import { tooltipEditorCtrl } from './tooltip_editor';
|
||||||
|
import { migratePanelConfig } from './panel_config_migration';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import kbn from 'app/core/utils/kbn';
|
import kbn from 'app/core/utils/kbn';
|
||||||
@@ -14,12 +17,8 @@ import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
|||||||
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
|
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
|
||||||
import { Bucket, BucketMatrix } from './statusmap_data';
|
import { Bucket, BucketMatrix } from './statusmap_data';
|
||||||
import rendering from './rendering';
|
import rendering from './rendering';
|
||||||
// import aggregates, { aggregatesMap } from './aggregates';
|
|
||||||
// import fragments, { fragmentsMap } from './fragments';
|
|
||||||
// import { labelFormats } from './xAxisLabelFormats';
|
|
||||||
import {statusHeatmapOptionsEditor} from './options_editor';
|
|
||||||
import {ColorModeDiscrete} from "./color_mode_discrete";
|
import {ColorModeDiscrete} from "./color_mode_discrete";
|
||||||
import { ExtraSeriesFormat, ExtraSeriesFormatValue } from './extra_series_format';
|
|
||||||
|
|
||||||
const VALUE_INDEX = 0,
|
const VALUE_INDEX = 0,
|
||||||
TIME_INDEX = 1;
|
TIME_INDEX = 1;
|
||||||
@@ -56,7 +55,6 @@ const colorSchemes = [
|
|||||||
let colorModes = ['opacity', 'spectrum', 'discrete'];
|
let colorModes = ['opacity', 'spectrum', 'discrete'];
|
||||||
let opacityScales = ['linear', 'sqrt'];
|
let opacityScales = ['linear', 'sqrt'];
|
||||||
|
|
||||||
|
|
||||||
loadPluginCss({
|
loadPluginCss({
|
||||||
dark: 'plugins/flant-statusmap-panel/css/statusmap.dark.css',
|
dark: 'plugins/flant-statusmap-panel/css/statusmap.dark.css',
|
||||||
light: 'plugins/flant-statusmap-panel/css/statusmap.light.css'
|
light: 'plugins/flant-statusmap-panel/css/statusmap.light.css'
|
||||||
@@ -81,7 +79,6 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
noDatapoints: boolean;
|
noDatapoints: boolean;
|
||||||
|
|
||||||
discreteExtraSeries: ColorModeDiscrete;
|
discreteExtraSeries: ColorModeDiscrete;
|
||||||
extraSeriesFormats: any = [];
|
|
||||||
|
|
||||||
annotations: object[] = [];
|
annotations: object[] = [];
|
||||||
annotationsPromise: any;
|
annotationsPromise: any;
|
||||||
@@ -108,68 +105,41 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
cardRound: null
|
cardRound: null
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
show: true,
|
show: true
|
||||||
labelFormat: '%a %m/%d'
|
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
show: true,
|
show: true,
|
||||||
minWidth: -1,
|
minWidth: -1,
|
||||||
maxWidth: -1,
|
maxWidth: -1
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true
|
show: true,
|
||||||
|
freezeOnClick: true,
|
||||||
|
showItems: false,
|
||||||
|
items: [] // see tooltip_editor.ts
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
data: {
|
|
||||||
unitFormat: 'short',
|
|
||||||
decimals: null
|
|
||||||
},
|
|
||||||
// how null points should be handled
|
// how null points should be handled
|
||||||
nullPointMode: 'as empty',
|
nullPointMode: 'as empty',
|
||||||
yAxisSort: 'metrics',
|
yAxisSort: 'metrics',
|
||||||
highlightCards: true,
|
highlightCards: true,
|
||||||
useMax: true,
|
useMax: true,
|
||||||
urls: [{
|
|
||||||
tooltip: '',
|
seriesFilterIndex: -1
|
||||||
label: '',
|
|
||||||
base_url: '',
|
|
||||||
useExtraSeries: false,
|
|
||||||
useseriesname: true,
|
|
||||||
forcelowercase: true,
|
|
||||||
icon_fa: 'external-link',
|
|
||||||
extraSeries: {
|
|
||||||
index: -1
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
seriesFilterIndex: -1,
|
|
||||||
usingUrl: false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope: any, $injector: auto.IInjectorService, timeSrv, private annotationsSrv: AnnotationsSrv, $window, datasourceSrv, variableSrv, templateSrv) {
|
constructor($scope: any, $injector: auto.IInjectorService, timeSrv, private annotationsSrv: AnnotationsSrv, $window, datasourceSrv, public variableSrv: any, templateSrv) {
|
||||||
super($scope, $injector);
|
super($scope, $injector);
|
||||||
|
|
||||||
|
migratePanelConfig(this.panel);
|
||||||
_.defaultsDeep(this.panel, this.panelDefaults);
|
_.defaultsDeep(this.panel, this.panelDefaults);
|
||||||
|
|
||||||
this.opacityScales = opacityScales;
|
this.opacityScales = opacityScales;
|
||||||
this.colorModes = colorModes;
|
this.colorModes = colorModes;
|
||||||
this.colorSchemes = colorSchemes;
|
this.colorSchemes = colorSchemes;
|
||||||
this.variableSrv = variableSrv;
|
|
||||||
this.extraSeriesFormats = ExtraSeriesFormat;
|
|
||||||
|
|
||||||
this.renderLink = (link, scopedVars, format) => {
|
|
||||||
var scoped = {}
|
|
||||||
for (var key in scopedVars) {
|
|
||||||
scoped[key] = { value: scopedVars[key] }
|
|
||||||
}
|
|
||||||
if (format) {
|
|
||||||
return this.templateSrv.replace(link, scoped, format)
|
|
||||||
} else {
|
|
||||||
return this.templateSrv.replace(link, scoped)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// default graph width for discrete card width calculation
|
// default graph width for discrete card width calculation
|
||||||
this.graph = {
|
this.graph = {
|
||||||
@@ -209,38 +179,15 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
this.events.on('refresh', this.postRefresh.bind(this));
|
this.events.on('refresh', this.postRefresh.bind(this));
|
||||||
// custom event from rendering.js
|
// custom event from rendering.js
|
||||||
this.events.on('render-complete', this.onRenderComplete.bind(this));
|
this.events.on('render-complete', this.onRenderComplete.bind(this));
|
||||||
this.events.on('onChangeType', this.onChangeType.bind(this));
|
|
||||||
|
|
||||||
this.onCardColorChange = this.onCardColorChange.bind(this);
|
this.onCardColorChange = this.onCardColorChange.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onRenderComplete(data: any):void {
|
onRenderComplete(data: any):void {
|
||||||
// console.log({
|
|
||||||
// data: this.data,
|
|
||||||
// bucketMatrix: this.bucketMatrix,
|
|
||||||
// chartWidth: data.chartWidth,
|
|
||||||
// from: this.range.from.valueOf(),
|
|
||||||
// to: this.range.to.valueOf()
|
|
||||||
// })
|
|
||||||
|
|
||||||
this.graph.chartWidth = data.chartWidth;
|
this.graph.chartWidth = data.chartWidth;
|
||||||
this.renderingCompleted();
|
this.renderingCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeType(url): void {
|
|
||||||
switch (url.type) {
|
|
||||||
case ExtraSeriesFormat.Date:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Date;
|
|
||||||
break;
|
|
||||||
case ExtraSeriesFormat.Raw:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Raw;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
url.extraSeries.format = ExtraSeriesFormatValue.Raw;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getChartWidth returns an approximation of chart canvas width or
|
// getChartWidth returns an approximation of chart canvas width or
|
||||||
// a saved value calculated during a render.
|
// a saved value calculated during a render.
|
||||||
getChartWidth():number {
|
getChartWidth():number {
|
||||||
@@ -266,6 +213,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
// Quick workaround for 6.7 and 7.0+. There is no call to
|
// Quick workaround for 6.7 and 7.0+. There is no call to
|
||||||
// calculateInterval in updateTimeRange in those versions.
|
// calculateInterval in updateTimeRange in those versions.
|
||||||
|
// TODO ts type has no argument for this method.
|
||||||
updateTimeRange(datasource?: any) {
|
updateTimeRange(datasource?: any) {
|
||||||
let ret = super.updateTimeRange(datasource);
|
let ret = super.updateTimeRange(datasource);
|
||||||
this.calculateInterval();
|
this.calculateInterval();
|
||||||
@@ -316,17 +264,8 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
|
|
||||||
// Get final buckets count after interval is adjusted
|
// Get final buckets count after interval is adjusted
|
||||||
|
// TODO is it needed?
|
||||||
//this.xBucketsCount = Math.floor(rangeMs / intervalMs);
|
//this.xBucketsCount = Math.floor(rangeMs / intervalMs);
|
||||||
|
|
||||||
// console.log("calculateInterval: ", {
|
|
||||||
// interval: this.interval,
|
|
||||||
// intervalMs: this.intervalMs,
|
|
||||||
// rangeMs: rangeMs,
|
|
||||||
// from: this.range.from.valueOf(),
|
|
||||||
// to: this.range.to.valueOf(),
|
|
||||||
// numIntervals: rangeMs/this.intervalMs,
|
|
||||||
// maxCardsCount: maxCardsCount,
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
issueQueries(datasource: any) {
|
issueQueries(datasource: any) {
|
||||||
@@ -342,8 +281,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
* (but not wait for completion). This resolves
|
* (but not wait for completion). This resolves
|
||||||
* issue 11806.
|
* issue 11806.
|
||||||
*/
|
*/
|
||||||
// 5.x before 5.4 doesn't have datasourcePromises.
|
// 5.x before 5.4 doesn't have datasourcePromises.
|
||||||
|
|
||||||
if ("undefined" !== typeof(this.annotationsSrv.datasourcePromises)) {
|
if ("undefined" !== typeof(this.annotationsSrv.datasourcePromises)) {
|
||||||
return this.annotationsSrv.datasourcePromises.then(r => {
|
return this.annotationsSrv.datasourcePromises.then(r => {
|
||||||
return this.issueQueriesWithInterval(datasource, this.interval);
|
return this.issueQueriesWithInterval(datasource, this.interval);
|
||||||
@@ -364,7 +302,6 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onDataReceived(dataList: any) {
|
onDataReceived(dataList: any) {
|
||||||
this.data = dataList;
|
this.data = dataList;
|
||||||
// Quick workaround for 7.0+. There is no call to
|
// Quick workaround for 7.0+. There is no call to
|
||||||
@@ -401,7 +338,8 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onInitEditMode() {
|
onInitEditMode() {
|
||||||
this.addEditorTab('Options', statusHeatmapOptionsEditor, 2);
|
this.addEditorTab('Options', optionsEditorCtrl, 2);
|
||||||
|
this.addEditorTab('Tooltip', tooltipEditorCtrl, 3);
|
||||||
this.unitFormats = kbn.getUnitFormats();
|
this.unitFormats = kbn.getUnitFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,8 +374,6 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
if (this.bucketMatrix) {
|
if (this.bucketMatrix) {
|
||||||
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
this.noDatapoints = this.bucketMatrix.noDatapoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onCardColorChange(newColor) {
|
onCardColorChange(newColor) {
|
||||||
@@ -455,75 +391,14 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
this.noColorDefined = false;
|
this.noColorDefined = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditorAddThreshold() {
|
|
||||||
this.panel.color.thresholds.push({ color: this.panel.defaultColor });
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditorAddUrl = () => {
|
|
||||||
this.panel.urls.push({
|
|
||||||
label: '',
|
|
||||||
base_url: '',
|
|
||||||
useExtraSeries: false,
|
|
||||||
useseriesname: true,
|
|
||||||
forcelowercase: true,
|
|
||||||
icon_fa: 'external-link',
|
|
||||||
extraSeries: {
|
|
||||||
index: -1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditorRemoveUrl = (index) => {
|
|
||||||
this.panel.urls.splice(index, 1);
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditorRemoveThreshold(index:number) {
|
|
||||||
this.panel.color.thresholds.splice(index, 1);
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditorRemoveThresholds() {
|
|
||||||
this.panel.color.thresholds = [];
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onEditorRemoveUrls = () => {
|
|
||||||
this.panel.urls = [];
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditorAddThreeLights() {
|
|
||||||
this.panel.color.thresholds.push({color: "red", value: 2, tooltip: "error" });
|
|
||||||
this.panel.color.thresholds.push({color: "yellow", value: 1, tooltip: "warning" });
|
|
||||||
this.panel.color.thresholds.push({color: "green", value: 0, tooltip: "ok" });
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://ethanschoonover.com/solarized/ */
|
|
||||||
onEditorAddSolarized() {
|
|
||||||
this.panel.color.thresholds.push({color: "#b58900", value: 0, tooltip: "yellow" });
|
|
||||||
this.panel.color.thresholds.push({color: "#cb4b16", value: 1, tooltip: "orange" });
|
|
||||||
this.panel.color.thresholds.push({color: "#dc322f", value: 2, tooltip: "red" });
|
|
||||||
this.panel.color.thresholds.push({color: "#d33682", value: 3, tooltip: "magenta" });
|
|
||||||
this.panel.color.thresholds.push({color: "#6c71c4", value: 4, tooltip: "violet" });
|
|
||||||
this.panel.color.thresholds.push({color: "#268bd2", value: 5, tooltip: "blue" });
|
|
||||||
this.panel.color.thresholds.push({color: "#2aa198", value: 6, tooltip: "cyan" });
|
|
||||||
this.panel.color.thresholds.push({color: "#859900", value: 7, tooltip: "green" });
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
link(scope, elem, attrs, ctrl) {
|
link(scope, elem, attrs, ctrl) {
|
||||||
rendering(scope, elem, attrs, ctrl);
|
rendering(scope, elem, attrs, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compatible with Grafana 7.0 overrides feature.
|
||||||
retrieveTimeVar() {
|
retrieveTimeVar() {
|
||||||
var time = this.timeSrv.timeRangeForUrl();
|
var time = this.timeSrv.timeRangeForUrl();
|
||||||
var var_time = '&from=' + time.from + '&to=' + time.to;
|
return 'from=' + time.from + '&to=' + time.to;
|
||||||
return var_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertToBuckets groups values in data into buckets by target and timestamp.
|
// convertToBuckets groups values in data into buckets by target and timestamp.
|
||||||
@@ -737,133 +612,6 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
bucketMatrix.targets = targetKeys;
|
bucketMatrix.targets = targetKeys;
|
||||||
return bucketMatrix;
|
return bucketMatrix;
|
||||||
this.bucketMatrix = bucketMatrix;
|
|
||||||
|
|
||||||
// Collect all values for each bucket from datapoints with similar target.
|
|
||||||
// TODO aggregate values into buckets over datapoint[TIME_INDEX] not over datapoint index (j).
|
|
||||||
|
|
||||||
|
|
||||||
// for(let i = 0; i < cardsData.targets.length; i++) {
|
|
||||||
// let target = cardsData.targets[i];
|
|
||||||
|
|
||||||
// for (let j = 0; j < cardsData.xBucketSize; j++) {
|
|
||||||
// let card = new Card();
|
|
||||||
// card.id = i*cardsData.xBucketSize + j;
|
|
||||||
// card.values = [];
|
|
||||||
// card.y = target;
|
|
||||||
// card.x = -1;
|
|
||||||
|
|
||||||
// // collect values from all timeseries with target
|
|
||||||
// for (let si = 0; si < cardsData.targetIndex[target].length; si++) {
|
|
||||||
// let s = data[cardsData.targetIndex[target][si]];
|
|
||||||
// if (s.datapoints.length <= j) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// let datapoint = s.datapoints[j];
|
|
||||||
// if (card.values.length === 0) {
|
|
||||||
// card.x = datapoint[TIME_INDEX];
|
|
||||||
// }
|
|
||||||
// card.values.push(datapoint[VALUE_INDEX]);
|
|
||||||
// }
|
|
||||||
// card.minValue = _.min(card.values);
|
|
||||||
// card.maxValue = _.max(card.values);
|
|
||||||
// if (card.values.length > 1) {
|
|
||||||
// cardsData.multipleValues = true;
|
|
||||||
// card.multipleValues = true;
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// } else {
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (cardsData.maxValue < card.maxValue)
|
|
||||||
// cardsData.maxValue = card.maxValue;
|
|
||||||
|
|
||||||
// if (cardsData.minValue > card.minValue)
|
|
||||||
// cardsData.minValue = card.minValue;
|
|
||||||
|
|
||||||
// if (card.x != -1) {
|
|
||||||
// cardsData.cards.push(card);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let cardsData = <CardsStorage> {
|
|
||||||
// cards: [],
|
|
||||||
// xBucketSize: 0,
|
|
||||||
// yBucketSize: 0,
|
|
||||||
// maxValue: 0,
|
|
||||||
// minValue: 0,
|
|
||||||
// multipleValues: false,
|
|
||||||
// noColorDefined: false,
|
|
||||||
// targets: [], // array of available unique targets
|
|
||||||
// targetIndex: {} // indices in data array for each of available unique targets
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if (!data || data.length == 0) { return cardsData;}
|
|
||||||
|
|
||||||
// // Collect uniq timestamps from data and spread over targets and timestamps
|
|
||||||
|
|
||||||
// // collect uniq targets and their indices
|
|
||||||
// _.map(data, (d, i) => {
|
|
||||||
// cardsData.targetIndex[d.target] = _.concat(_.toArray(cardsData.targetIndex[d.target]), i)
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // TODO add some logic for targets heirarchy
|
|
||||||
// cardsData.targets = _.keys(cardsData.targetIndex);
|
|
||||||
// cardsData.yBucketSize = cardsData.targets.length;
|
|
||||||
// // Maximum number of buckets over x axis
|
|
||||||
// cardsData.xBucketSize = _.max(_.map(data, d => d.datapoints.length));
|
|
||||||
|
|
||||||
// // Collect all values for each bucket from datapoints with similar target.
|
|
||||||
// // TODO aggregate values into buckets over datapoint[TIME_INDEX] not over datapoint index (j).
|
|
||||||
// for(let i = 0; i < cardsData.targets.length; i++) {
|
|
||||||
// let target = cardsData.targets[i];
|
|
||||||
|
|
||||||
// for (let j = 0; j < cardsData.xBucketSize; j++) {
|
|
||||||
// let card = new Card();
|
|
||||||
// card.id = i*cardsData.xBucketSize + j;
|
|
||||||
// card.values = [];
|
|
||||||
// card.y = target;
|
|
||||||
// card.x = -1;
|
|
||||||
|
|
||||||
// // collect values from all timeseries with target
|
|
||||||
// for (let si = 0; si < cardsData.targetIndex[target].length; si++) {
|
|
||||||
// let s = data[cardsData.targetIndex[target][si]];
|
|
||||||
// if (s.datapoints.length <= j) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// let datapoint = s.datapoints[j];
|
|
||||||
// if (card.values.length === 0) {
|
|
||||||
// card.x = datapoint[TIME_INDEX];
|
|
||||||
// }
|
|
||||||
// card.values.push(datapoint[VALUE_INDEX]);
|
|
||||||
// }
|
|
||||||
// card.minValue = _.min(card.values);
|
|
||||||
// card.maxValue = _.max(card.values);
|
|
||||||
// if (card.values.length > 1) {
|
|
||||||
// cardsData.multipleValues = true;
|
|
||||||
// card.multipleValues = true;
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// } else {
|
|
||||||
// card.value = card.maxValue; // max value by default
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (cardsData.maxValue < card.maxValue)
|
|
||||||
// cardsData.maxValue = card.maxValue;
|
|
||||||
|
|
||||||
// if (cardsData.minValue > card.minValue)
|
|
||||||
// cardsData.minValue = card.minValue;
|
|
||||||
|
|
||||||
// if (card.x != -1) {
|
|
||||||
// cardsData.cards.push(card);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return cardsData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
-6
@@ -1,26 +1,68 @@
|
|||||||
import kbn from 'app/core/utils/kbn';
|
import kbn from 'app/core/utils/kbn';
|
||||||
|
import { StatusHeatmapCtrl } from './module';
|
||||||
|
|
||||||
export class StatusHeatmapOptionsEditorCtrl {
|
export class StatusHeatmapOptionsEditorCtrl {
|
||||||
panel: any;
|
panel: any;
|
||||||
panelCtrl: any;
|
panelCtrl: StatusHeatmapCtrl;
|
||||||
unitFormats: any;
|
unitFormats: any;
|
||||||
|
|
||||||
constructor($scope) {
|
/** @ngInject */
|
||||||
|
constructor($scope: any) {
|
||||||
$scope.editor = this;
|
$scope.editor = this;
|
||||||
this.panelCtrl = $scope.ctrl;
|
this.panelCtrl = $scope.ctrl as StatusHeatmapCtrl;
|
||||||
this.panel = this.panelCtrl.panel;
|
this.panel = this.panelCtrl.panel;
|
||||||
this.unitFormats = kbn.getUnitFormats();
|
|
||||||
|
|
||||||
this.panelCtrl.render();
|
this.unitFormats = kbn.getUnitFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
setUnitFormat(subItem) {
|
setUnitFormat(subItem) {
|
||||||
this.panel.data.unitFormat = subItem.value;
|
this.panel.data.unitFormat = subItem.value;
|
||||||
this.panelCtrl.render();
|
this.panelCtrl.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.panelCtrl.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddThreshold() {
|
||||||
|
this.panel.color.thresholds.push({ color: this.panel.defaultColor });
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveThreshold(index:number) {
|
||||||
|
this.panel.color.thresholds.splice(index, 1);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveThresholds() {
|
||||||
|
this.panel.color.thresholds = [];
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddThreeLights() {
|
||||||
|
this.panel.color.thresholds.push({color: "red", value: 2, tooltip: "error" });
|
||||||
|
this.panel.color.thresholds.push({color: "yellow", value: 1, tooltip: "warning" });
|
||||||
|
this.panel.color.thresholds.push({color: "green", value: 0, tooltip: "ok" });
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://ethanschoonover.com/solarized/ */
|
||||||
|
onAddSolarized() {
|
||||||
|
this.panel.color.thresholds.push({color: "#b58900", value: 0, tooltip: "yellow" });
|
||||||
|
this.panel.color.thresholds.push({color: "#cb4b16", value: 1, tooltip: "orange" });
|
||||||
|
this.panel.color.thresholds.push({color: "#dc322f", value: 2, tooltip: "red" });
|
||||||
|
this.panel.color.thresholds.push({color: "#d33682", value: 3, tooltip: "magenta" });
|
||||||
|
this.panel.color.thresholds.push({color: "#6c71c4", value: 4, tooltip: "violet" });
|
||||||
|
this.panel.color.thresholds.push({color: "#268bd2", value: 5, tooltip: "blue" });
|
||||||
|
this.panel.color.thresholds.push({color: "#2aa198", value: 6, tooltip: "cyan" });
|
||||||
|
this.panel.color.thresholds.push({color: "#859900", value: 7, tooltip: "green" });
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function statusHeatmapOptionsEditor() {
|
/** @ngInject */
|
||||||
|
export function optionsEditorCtrl() {
|
||||||
'use strict';
|
'use strict';
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
function migrate_V0_V1(panel: any) {
|
||||||
|
// Remove unused fields.
|
||||||
|
if (_.has(panel, "xAxis.labelFormat")) {
|
||||||
|
delete panel.xAxis.labelFormat;
|
||||||
|
}
|
||||||
|
if (_.has(panel, "xAxis.minBucketWidthToShowWeekends")) {
|
||||||
|
delete panel.xAxis.minBucketWidthToShowWeekends;
|
||||||
|
}
|
||||||
|
if (_.has(panel, "xAxis.showCrosshair")) {
|
||||||
|
delete panel.xAxis.showCrosshair;
|
||||||
|
}
|
||||||
|
if (_.has(panel, "xAxis.showWeekends")) {
|
||||||
|
delete panel.xAxis.showWeekends;
|
||||||
|
}
|
||||||
|
if (_.has(panel, "yAxis.showCrosshair")) {
|
||||||
|
delete panel.yAxis.showCrosshair;
|
||||||
|
}
|
||||||
|
if (_.has(panel, "data.unitFormat")) {
|
||||||
|
delete panel.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate cardSpacing value. Seems rare (update from version 0.0.2).
|
||||||
|
if (_.has(panel, "cards.cardSpacing")) {
|
||||||
|
if (!_.has(panel, "cards.cardVSpacing")) {
|
||||||
|
if (panel.cards.cardSpacing) {
|
||||||
|
panel.cards.cardVSpacing = panel.cards.cardSpacing
|
||||||
|
panel.cards.cardHSpacing = panel.cards.cardSpacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete panel.cards.cardSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate initial config for urls in tooltip (pull/86).
|
||||||
|
// 'usingUrl' was used to show tooltip with urls on click or not.
|
||||||
|
if (_.has(panel, "usingUrl")) {
|
||||||
|
if (!_.has(panel, "tooltip.freezeOnClick")) {
|
||||||
|
panel.tooltip.freezeOnClick = panel.usingUrl;
|
||||||
|
}
|
||||||
|
delete panel.usingUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'urls' array is now tooltip.items array. Also items are changed.
|
||||||
|
if (_.has(panel, "urls")) {
|
||||||
|
if (!_.has(panel, "tooltip.items")) {
|
||||||
|
panel.tooltip.items = [];
|
||||||
|
let hasRealItems = true;
|
||||||
|
if (panel.urls.length == 0) {
|
||||||
|
hasRealItems = false;
|
||||||
|
}
|
||||||
|
if (panel.urls.length == 1) {
|
||||||
|
let url = panel.urls[0];
|
||||||
|
if (url.base_url === '' && url.label === '') {
|
||||||
|
hasRealItems = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasRealItems) {
|
||||||
|
panel.tooltip.showItems = true;
|
||||||
|
for (let url of panel.urls) {
|
||||||
|
let item = {
|
||||||
|
urlTemplate: _.toString(url.base_url),
|
||||||
|
urlText: _.toString(url.label),
|
||||||
|
urlIcon: _.toString(url.icon_fa),
|
||||||
|
urlToLowerCase: url.forcelowercase,
|
||||||
|
valueDateFormat: '',
|
||||||
|
}
|
||||||
|
// replace $vars with new ${__vars} if url template is not empty
|
||||||
|
if (item.urlTemplate !== "") {
|
||||||
|
// $time was a graph time with prepended &
|
||||||
|
item.urlTemplate = _.replace(url.base_url, /\$time/g, "&${__url_time_range}");
|
||||||
|
// $series_label was a y axis label
|
||||||
|
item.urlTemplate = _.replace(item.urlTemplate, /\$series_label/, "${__y_label}");
|
||||||
|
// $series_extra was a value from bucket. This value has format options and index.
|
||||||
|
let valueVar = "__value";
|
||||||
|
if (url.useExtraSeries === true) {
|
||||||
|
// index?
|
||||||
|
if (url.extraSeries.index > -1) {
|
||||||
|
valueVar += "_" + url.extraSeries.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
let format = _.toString(url.extraSeries.format);
|
||||||
|
if (format === 'YYYY/MM/DD/HH_mm_ss') {
|
||||||
|
valueVar += '_date';
|
||||||
|
item.valueDateFormat = format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.urlTemplate = _.replace(item.urlTemplate, /\$series_extra/, `\${${valueVar}}`);
|
||||||
|
}
|
||||||
|
panel.tooltip.items.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete panel.urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create statusmap metadata
|
||||||
|
panel.statusmap = {
|
||||||
|
"ConfigVersion": "v1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function migratePanelConfig(panel: any) {
|
||||||
|
if (_.has(panel, "statusmap")) {
|
||||||
|
if (panel.statusmap.ConfigVersion == "v1") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
migrate_V0_V1(panel);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label">
|
<label class="gf-form-label">
|
||||||
<a class="pointer" tabindex="1" ng-click="ctrl.onEditorRemoveThreshold($index)">
|
<a class="pointer" tabindex="1" ng-click="editor.onRemoveThreshold($index)">
|
||||||
<i class="fa fa-trash"/>
|
<i class="fa fa-trash"/>
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
@@ -91,12 +91,12 @@
|
|||||||
<div class="gf-form-inline">
|
<div class="gf-form-inline">
|
||||||
<div class="gf-form"></div>
|
<div class="gf-form"></div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorAddThreshold()">
|
<button class="btn btn-inverse" ng-click="editor.onAddThreshold()">
|
||||||
<i class="fa fa-plus"></i> Add new status
|
<i class="fa fa-plus"></i> Add new status
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorRemoveThresholds()">
|
<button class="btn btn-inverse" ng-click="editor.onRemoveThresholds()">
|
||||||
<i class="fa fa-minus"></i> Remove all
|
<i class="fa fa-minus"></i> Remove all
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -108,12 +108,12 @@
|
|||||||
<label class="gf-form-label">Presets</label>
|
<label class="gf-form-label">Presets</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn" ng-click="ctrl.onEditorAddThreeLights()">
|
<button class="btn" ng-click="editor.onAddThreeLights()">
|
||||||
Red-Yellow-Green
|
Red-Yellow-Green
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<button class="btn" ng-click="ctrl.onEditorAddSolarized()">
|
<button class="btn" ng-click="editor.onAddSolarized()">
|
||||||
Solarized
|
Solarized
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,10 +144,6 @@
|
|||||||
label="Show legend"
|
label="Show legend"
|
||||||
checked="ctrl.panel.legend.show" on-change="ctrl.render()">
|
checked="ctrl.panel.legend.show" on-change="ctrl.render()">
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
|
||||||
label="Show tooltip"
|
|
||||||
checked="ctrl.panel.tooltip.show" on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
<gf-form-switch class="gf-form" label-class="width-8"
|
||||||
label="Show X axis"
|
label="Show X axis"
|
||||||
checked="ctrl.panel.xAxis.show" on-change="ctrl.render()">
|
checked="ctrl.panel.xAxis.show" on-change="ctrl.render()">
|
||||||
@@ -159,17 +155,12 @@
|
|||||||
|
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Min width</label>
|
<label class="gf-form-label width-8">Min width</label>
|
||||||
<input type="number" ng-model="ctrl.panel.xAxis.minWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="number" ng-model="ctrl.panel.yAxis.minWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Max width</label>
|
<label class="gf-form-label width-8">Max width</label>
|
||||||
<input type="number" ng-model="ctrl.panel.xAxis.maxWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
<input type="number" ng-model="ctrl.panel.yAxis.maxWidth" class="gf-form-input width-5" placeholder="auto" data-placement="right" bs-tooltip="''" ng-change="ctrl.render()" ng-model-onblur>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group">
|
|
||||||
<h5 class="section-heading">Buckets</h5>
|
|
||||||
|
|
||||||
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
<div class="gf-form" ng-show="ctrl.panel.yAxis.show">
|
||||||
<label class="gf-form-label width-8">Rows sort</label>
|
<label class="gf-form-label width-8">Rows sort</label>
|
||||||
<div class="gf-form-select-wrapper">
|
<div class="gf-form-select-wrapper">
|
||||||
@@ -180,6 +171,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Buckets</h5>
|
||||||
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8"
|
<gf-form-switch class="gf-form" label-class="width-8"
|
||||||
label="Multiple values"
|
label="Multiple values"
|
||||||
checked="ctrl.panel.useMax" on-change="ctrl.render()">
|
checked="ctrl.panel.useMax" on-change="ctrl.render()">
|
||||||
@@ -187,6 +183,13 @@
|
|||||||
<div class="gf-form" ng-show="ctrl.panel.useMax">
|
<div class="gf-form" ng-show="ctrl.panel.useMax">
|
||||||
Color for bucket with multiple values is determined by color mode<br/>
|
Color for bucket with multiple values is determined by color mode<br/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-8">Values index</label>
|
||||||
|
<input type="number" class="gf-form-input width-5" placeholder="-1" data-placement="right"
|
||||||
|
bs-tooltip="'Display only values with this index in a bucket. Use -1 to display all values'"
|
||||||
|
ng-model="ctrl.panel.seriesFilterIndex" ng-change="ctrl.refresh()"
|
||||||
|
ng-model-onblur>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-8">Display nulls</label>
|
<label class="gf-form-label width-8">Display nulls</label>
|
||||||
@@ -194,6 +197,7 @@
|
|||||||
<select class="gf-form-input max-width-9" ng-model="ctrl.panel.nullPointMode" ng-options="f for f in ['as empty', 'as zero']" ng-change="ctrl.render()"></select>
|
<select class="gf-form-input max-width-9" ng-model="ctrl.panel.nullPointMode" ng-options="f for f in ['as empty', 'as zero']" ng-change="ctrl.render()"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-8">Min width</label>
|
<label class="gf-form-label width-8">Min width</label>
|
||||||
<input type="number" class="gf-form-input width-5" placeholder="5" data-placement="right" bs-tooltip="'Minimal card width for 1/1 resolution in pixels'" ng-model="ctrl.panel.cards.cardMinWidth" ng-change="ctrl.refresh()" ng-model-onblur>
|
<input type="number" class="gf-form-input width-5" placeholder="5" data-placement="right" bs-tooltip="'Minimal card width for 1/1 resolution in pixels'" ng-model="ctrl.panel.cards.cardMinWidth" ng-change="ctrl.refresh()" ng-model-onblur>
|
||||||
@@ -212,105 +216,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section gf-form-group width-30">
|
|
||||||
<h5 class="section-heading">Filtering</h5>
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-9">Show only serie with Index</label>
|
|
||||||
<input type="number" class="gf-form-input width-5" placeholder="2" data-placement="right"
|
|
||||||
bs-tooltip="'Filter with the serie index to show the value on graph. Use -1 to get all values'" ng-model="ctrl.panel.seriesFilterIndex" ng-change="ctrl.refresh()"
|
|
||||||
ng-model-onblur>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group">
|
|
||||||
<h5 class="section-heading">URL</h5>
|
|
||||||
|
|
||||||
<div class="gf-form">
|
|
||||||
Insert the url to navigate<br />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form">
|
|
||||||
<gf-form-switch class="gf-form" label="Show extraSeries Tooltip when clicking elements" label-class="width-12"
|
|
||||||
checked="ctrl.panel.usingUrl" on-change="ctrl.render()"></gf-form-switch>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section gf-form-group" ng-if="ctrl.panel.usingUrl">
|
|
||||||
<br>
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form"></div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorAddUrl()">
|
|
||||||
<i class="fa fa-plus"></i> Add new URL
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<button class="btn btn-inverse" ng-click="ctrl.onEditorRemoveUrls()">
|
|
||||||
<i class="fa fa-minus"></i> Remove all URLs
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form-block" ng-repeat="url in ctrl.panel.urls">
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-2">{{ $index }}</label>
|
|
||||||
<label class="gf-form-label width-2">
|
|
||||||
<a class="pointer" tabindex="1" ng-click="ctrl.onEditorRemoveUrl($index)">
|
|
||||||
<i class="fa fa-trash" />
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
<label class="gf-form-label width-4">Label: </label>
|
|
||||||
<input type="text" class="gf-form-input width-16" placeholder="My URL" data-placement="right"
|
|
||||||
ng-model="url.label" ng-change="ctrl.refresh()">
|
|
||||||
<label class="gf-form-label width-4">URL: </label>
|
|
||||||
<input type="text" class="gf-form-input width-c-50" placeholder="https://www.google.es" data-placement="right"
|
|
||||||
bs-tooltip="'This is the url to be shown when the user clicks on it'" ng-model="url.base_url"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
<info-popover mode="right-normal">
|
|
||||||
<p>Specify an URL (relative or absolute)</p>
|
|
||||||
<span>
|
|
||||||
Use special variables to specify cell values:
|
|
||||||
<br>
|
|
||||||
<em>$series_label</em> name of the serie
|
|
||||||
<br>
|
|
||||||
<em>$(template.name)</em> name of the templated to be replaced
|
|
||||||
<br>
|
|
||||||
<em>$time</em> append &from...&to on the URL
|
|
||||||
<br>
|
|
||||||
<em>$series_extra</em> use extraSeries value to use it on URL
|
|
||||||
</span>
|
|
||||||
</info-popover>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-4">Icon: </label>
|
|
||||||
<input type="text" class="gf-form-input width-12" placeholder="FA Icon" data-placement="right"
|
|
||||||
bs-tooltip="'The icon shown on URL'" ng-model="url.icon_fa" ng-change="ctrl.refresh()">
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-8" label="Force lowercase" checked="url.forcelowercase"
|
|
||||||
on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<gf-form-switch class="gf-form" label-class="width-6" label="Use Extra Serie Data" checked="url.useExtraSeries"
|
|
||||||
on-change="ctrl.render()">
|
|
||||||
</gf-form-switch>
|
|
||||||
<div class="gf-form" ng-if="url.useExtraSeries == true">
|
|
||||||
<label class="gf-form-label width-8">Extra Series Index: </label>
|
|
||||||
<input type="number" class="gf-form-input width-12" placeholder="0" ng-if="url.useExtraSeries == true"
|
|
||||||
data-placement="right" bs-tooltip="'Fields index to use its value on URL using $series_extra. Use -1 to disable it'" ng-model="url.extraSeries.index"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
|
|
||||||
<label class="gf-form-label width-9">Type</label>
|
|
||||||
<div class="gf-form-select-wrapper width-8">
|
|
||||||
<select class="input-small gf-form-input" ng-model="url.type" ng-options="s for s in ctrl.extraSeriesFormats" ng-change="ctrl.onChangeType(url)"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="url.type === 'Date'">
|
|
||||||
<label class="gf-form-label width-12">Extra Series Date Format: </label>
|
|
||||||
<input type="text" class="gf-form-input width-12" placeholder="YYYY/MM/DD/HH_mm_ss" ng-if="url.useExtraSeries == true"
|
|
||||||
data-placement="right" bs-tooltip="'Date format to transformat extraSeries'" ng-model="url.extraSeries.format"
|
|
||||||
ng-change="ctrl.refresh()">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<div class="editor-row">
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Show tooltip"
|
||||||
|
tooltip="'Show tooltip when mouse is over the card'"
|
||||||
|
checked="ctrl.panel.tooltip.show" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Freeze on click"
|
||||||
|
tooltip="'Freeze tooltip copy when card is clicked'"
|
||||||
|
checked="ctrl.panel.tooltip.freezeOnClick" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-10"
|
||||||
|
label="Show items"
|
||||||
|
tooltip="'Show items (urls) in tooltip'"
|
||||||
|
checked="ctrl.panel.tooltip.showItems" on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section gf-form-group">
|
||||||
|
<h5 class="section-heading">Items</h5>
|
||||||
|
|
||||||
|
<div class="gf-form" ng-show="ctrl.panel.tooltip.items.length == 0">
|
||||||
|
<label class="gf-form-label width-2">0</label>
|
||||||
|
<label class="gf-form-input width-30">No items defined.</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div ng-repeat="item in ctrl.panel.tooltip.items">
|
||||||
|
<div class="gf-form gf-form--grow">
|
||||||
|
<label class="gf-form-label width-6">
|
||||||
|
URL
|
||||||
|
<info-popover mode="left-normal">
|
||||||
|
<p>Specify an URL (relative or absolute)</p>
|
||||||
|
<span>
|
||||||
|
Use special variables:
|
||||||
|
<br>
|
||||||
|
<em>${__y_label}</em> name of the time series (alias or legend in the query editor).
|
||||||
|
<!-- <br>
|
||||||
|
<em>$(template.name)</em> name of the templated to be replaced -->
|
||||||
|
<br>
|
||||||
|
<em>${__bucket_range}</em> refers to bucket range in the form of '&from=...&to=...'.
|
||||||
|
<br>
|
||||||
|
<em>${__graph_range}</em> refers to graph range in the form of '&from=...&to=...'.
|
||||||
|
<br>
|
||||||
|
<em>${__value}</em> refers to current bucket value or max value if multiple values mode is on.
|
||||||
|
<br>
|
||||||
|
<em>${__value_N}</em> refers to Nth value in current bucket. Value indexes are started from 0. For instance,
|
||||||
|
<em>${__value_1}</em> refers to second value.
|
||||||
|
</span>
|
||||||
|
</info-popover>
|
||||||
|
</label>
|
||||||
|
<input type="text" class="gf-form-input" placeholder="https://www.google.es" data-placement="top"
|
||||||
|
bs-tooltip="'This is the url to be shown when the user clicks on it'" ng-model="item.urlTemplate"
|
||||||
|
ng-change="ctrl.refresh()">
|
||||||
|
<label class="gf-form-label">
|
||||||
|
<i class="fa fa-trash pointer" ng-click="editor.onRemoveUrl($index)"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-4">Icon</label>
|
||||||
|
<label class="gf-form-label width-2">
|
||||||
|
<i class="fa fa-{{item.urlIcon}}"></i>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
class="gf-form-input width-10"
|
||||||
|
type="text"
|
||||||
|
ng-model="item.urlIcon"
|
||||||
|
bs-typeahead="editor.getFAIconClasses"
|
||||||
|
bs-tooltip="'The icon for URL link'"
|
||||||
|
data-placement="top"
|
||||||
|
ng-blur="ctrl.render()"
|
||||||
|
data-min-length="0"
|
||||||
|
data-items="100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-4">Label</label>
|
||||||
|
<input type="text" class="gf-form-input width-16" placeholder="My URL" data-placement="top"
|
||||||
|
bs-tooltip="'Text for URL link'"
|
||||||
|
ng-model="item.urlText" ng-change="ctrl.refresh()">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<gf-form-switch class="gf-form" label-class="width-8" label="Lowercase link" checked="item.urlToLowerCase"
|
||||||
|
on-change="ctrl.render()">
|
||||||
|
</gf-form-switch>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label width-8">Date format</label>
|
||||||
|
<input type="text" class="gf-form-input width-12" placeholder="YYYY/MM/DD/HH_mm_ss"
|
||||||
|
data-placement="top" bs-tooltip="'Date format for __value_date'"
|
||||||
|
bs-typeahead="editor.getValueDateFormats"
|
||||||
|
data-min-length="0"
|
||||||
|
data-items="100"
|
||||||
|
ng-model="item.valueDateFormat"
|
||||||
|
ng-blur="ctrl.render()">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline">
|
||||||
|
<div class="gf-form"></div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-click="editor.onAddUrl()">
|
||||||
|
<i class="fa fa-plus"></i> Add URL
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form">
|
||||||
|
<button class="btn btn-inverse" ng-click="editor.onRemoveUrls()">
|
||||||
|
<i class="fa fa-minus"></i> Remove all
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
"links": [
|
"links": [
|
||||||
{"name": "Github", "url": "https://github.com/flant/grafana-statusmap"},
|
{"name": "Github", "url": "https://github.com/flant/grafana-statusmap"},
|
||||||
{"name": "MIT Licence", "url": "https://github.com/flant/grafana-statusmap/blob/master/LICENSE"}
|
{"name": "MIT Licence", "url": "https://github.com/flant/grafana-statusmap/blob/master/LICENSE"}
|
||||||
|
|
||||||
],
|
],
|
||||||
"screenshots": [
|
"screenshots": [
|
||||||
{"name": "Panel with light theme", "path": "img/flant-statusmap-panel.png"},
|
{"name": "Panel with light theme", "path": "img/flant-statusmap-panel.png"},
|
||||||
|
|||||||
+16
-27
@@ -3,11 +3,9 @@ import $ from 'jquery';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import kbn from 'app/core/utils/kbn';
|
import kbn from 'app/core/utils/kbn';
|
||||||
import {appEvents, contextSrv} from 'app/core/core';
|
import {appEvents, contextSrv} from 'app/core/core';
|
||||||
import {tickStep, getScaledDecimals, getFlotTickSize} from 'app/core/utils/ticks';
|
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
import * as d3ScaleChromatic from './libs/d3-scale-chromatic/index';
|
import * as d3ScaleChromatic from './libs/d3-scale-chromatic/index';
|
||||||
import {StatusmapTooltip} from './tooltip';
|
import {StatusmapTooltip} from './tooltip';
|
||||||
import {StatusHeatmapTooltipExtraSeries} from './tooltipextraseries';
|
|
||||||
import {AnnotationTooltip} from './annotations';
|
import {AnnotationTooltip} from './annotations';
|
||||||
import { Bucket, BucketMatrix } from './statusmap_data';
|
import { Bucket, BucketMatrix } from './statusmap_data';
|
||||||
import { StatusHeatmapCtrl } from './module';
|
import { StatusHeatmapCtrl } from './module';
|
||||||
@@ -65,7 +63,6 @@ export class StatusmapRenderer {
|
|||||||
panel: any;
|
panel: any;
|
||||||
$heatmap: any;
|
$heatmap: any;
|
||||||
tooltip: StatusmapTooltip;
|
tooltip: StatusmapTooltip;
|
||||||
tooltipExtraSeries:StatusHeatmapTooltipExtraSeries;
|
|
||||||
annotationTooltip: AnnotationTooltip;
|
annotationTooltip: AnnotationTooltip;
|
||||||
heatmap: any;
|
heatmap: any;
|
||||||
timeRange: any;
|
timeRange: any;
|
||||||
@@ -80,7 +77,6 @@ export class StatusmapRenderer {
|
|||||||
// $heatmap is JQuery object, but heatmap is D3
|
// $heatmap is JQuery object, but heatmap is D3
|
||||||
this.$heatmap = this.elem.find('.statusmap-panel');
|
this.$heatmap = this.elem.find('.statusmap-panel');
|
||||||
this.tooltip = new StatusmapTooltip(this.$heatmap, this.scope);
|
this.tooltip = new StatusmapTooltip(this.$heatmap, this.scope);
|
||||||
this.tooltipExtraSeries = new StatusHeatmapTooltipExtraSeries(this.$heatmap, this.scope);
|
|
||||||
this.annotationTooltip = new AnnotationTooltip(this.$heatmap, this.scope);
|
this.annotationTooltip = new AnnotationTooltip(this.$heatmap, this.scope);
|
||||||
|
|
||||||
this.yOffset = 0;
|
this.yOffset = 0;
|
||||||
@@ -312,8 +308,10 @@ export class StatusmapRenderer {
|
|||||||
this.heatmap.remove();
|
this.heatmap.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert svg as a first child into heatmap_elem
|
||||||
|
// as the frozen tooltip moving logiс assumes that tooltip is the last child.
|
||||||
this.heatmap = d3.select(heatmap_elem)
|
this.heatmap = d3.select(heatmap_elem)
|
||||||
.append("svg")
|
.insert("svg",":first-child")
|
||||||
.attr("width", this.width)
|
.attr("width", this.width)
|
||||||
.attr("height", this.height);
|
.attr("height", this.height);
|
||||||
|
|
||||||
@@ -428,9 +426,6 @@ export class StatusmapRenderer {
|
|||||||
|
|
||||||
getColorScale(maxValue, minValue = 0) {
|
getColorScale(maxValue, minValue = 0) {
|
||||||
let colorScheme = _.find(this.ctrl.colorSchemes, {value: this.panel.color.colorScheme});
|
let colorScheme = _.find(this.ctrl.colorSchemes, {value: this.panel.color.colorScheme});
|
||||||
// if (!colorScheme) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
let colorInterpolator = d3ScaleChromatic[colorScheme.value];
|
let colorInterpolator = d3ScaleChromatic[colorScheme.value];
|
||||||
let colorScaleInverted = colorScheme.invert === 'always' ||
|
let colorScaleInverted = colorScheme.invert === 'always' ||
|
||||||
(colorScheme.invert === 'dark' && !contextSrv.user.lightTheme);
|
(colorScheme.invert === 'dark' && !contextSrv.user.lightTheme);
|
||||||
@@ -537,26 +532,26 @@ export class StatusmapRenderer {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCardColor(b: Bucket) {
|
getCardColor(bucket: Bucket) {
|
||||||
if (this.panel.color.mode === 'opacity') {
|
if (this.panel.color.mode === 'opacity') {
|
||||||
return this.panel.color.cardColor;
|
return this.panel.color.cardColor;
|
||||||
} else if (this.panel.color.mode === 'spectrum') {
|
} else if (this.panel.color.mode === 'spectrum') {
|
||||||
return this.colorScale(b.value);
|
return this.colorScale(bucket.value);
|
||||||
} else if (this.panel.color.mode === 'discrete') {
|
} else if (this.panel.color.mode === 'discrete') {
|
||||||
if (this.panel.seriesFilterIndex != null && this.panel.seriesFilterIndex != -1) {
|
if (this.panel.seriesFilterIndex != null && this.panel.seriesFilterIndex != -1) {
|
||||||
return this.ctrl.discreteExtraSeries.getBucketColorSingle(d.values[this.panel.seriesFilterIndex]);
|
return this.ctrl.discreteExtraSeries.getBucketColorSingle(bucket.values[this.panel.seriesFilterIndex]);
|
||||||
} else {
|
} else {
|
||||||
return this.ctrl.discreteExtraSeries.getBucketColor(b.values);
|
return this.ctrl.discreteExtraSeries.getBucketColor(bucket.values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCardOpacity(b: Bucket) {
|
getCardOpacity(bucket: Bucket) {
|
||||||
if (this.panel.nullPointMode === 'as empty' && b.value == null ) {
|
if (this.panel.nullPointMode === 'as empty' && bucket.value == null ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (this.panel.color.mode === 'opacity') {
|
if (this.panel.color.mode === 'opacity') {
|
||||||
return this.opacityScale(b.value);
|
return this.opacityScale(bucket.value);
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -615,17 +610,10 @@ export class StatusmapRenderer {
|
|||||||
onMouseLeave(e) {
|
onMouseLeave(e) {
|
||||||
appEvents.emit('graph-hover-clear');
|
appEvents.emit('graph-hover-clear');
|
||||||
this.clearCrosshair();
|
this.clearCrosshair();
|
||||||
//annotationTooltip.destroy();
|
this.annotationTooltip.destroy();
|
||||||
if (e.relatedTarget) {
|
|
||||||
if (e.relatedTarget.className == "statusmap-tooltip-extraseries graph-tooltip grafana-tooltip" || e.relatedTarget.className == "graph-tooltip-time" ) {
|
|
||||||
} else {
|
|
||||||
this.tooltipExtraSeries.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.annotationTooltip.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseMove(event) {
|
onMouseMove(event: MouseEvent) {
|
||||||
if (!this.heatmap) { return; }
|
if (!this.heatmap) { return; }
|
||||||
|
|
||||||
const offset = this.getEventOffset(event);
|
const offset = this.getEventOffset(event);
|
||||||
@@ -646,9 +634,10 @@ export class StatusmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public onMouseClick(event) {
|
// TODO emit an event and move logic to panelCtrl
|
||||||
this.tooltipExtraSeries.show(event)
|
public onMouseClick(e: MouseEvent) {
|
||||||
if (this.ctrl.panel.usingUrl) {
|
if (this.ctrl.panel.tooltip.freezeOnClick) {
|
||||||
|
this.tooltip.showFrozen(e);
|
||||||
this.tooltip.destroy();
|
this.tooltip.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
import { migratePanelConfig } from '../panel_config_migration';
|
||||||
|
|
||||||
|
describe('when migrate from config with urls', () => {
|
||||||
|
let panel: any;
|
||||||
|
|
||||||
|
describe('given full panel configuration', () => {
|
||||||
|
const panelConfig = {
|
||||||
|
"cards": {
|
||||||
|
"cardHSpacing": 2,
|
||||||
|
"cardMinWidth": 5,
|
||||||
|
"cardRound": null,
|
||||||
|
"cardVSpacing": 2
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"cardColor": "#b4ff00",
|
||||||
|
"colorScale": "sqrt",
|
||||||
|
"colorScheme": "interpolateGnYlRd",
|
||||||
|
"defaultColor": "#757575",
|
||||||
|
"exponent": 0.5,
|
||||||
|
"mode": "opacity",
|
||||||
|
"thresholds": []
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"decimals": null,
|
||||||
|
"unitFormat": "short"
|
||||||
|
},
|
||||||
|
"datasource": "TestData DB",
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"highlightCards": true,
|
||||||
|
"id": 4,
|
||||||
|
"legend": {
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
"nullPointMode": "as empty",
|
||||||
|
"seriesFilterIndex": -1,
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"aggregation": "Last",
|
||||||
|
"csvWave": {
|
||||||
|
"timeStep": 60,
|
||||||
|
"valuesCSV": "0,0,2,2,1,1,3,3"
|
||||||
|
},
|
||||||
|
"decimals": 2,
|
||||||
|
"displayAliasType": "Warning / Critical",
|
||||||
|
"displayType": "Regular",
|
||||||
|
"displayValueWithAlias": "Never",
|
||||||
|
"refId": "A",
|
||||||
|
"scenarioId": "predictable_csv_wave",
|
||||||
|
"stringInput": "",
|
||||||
|
"units": "none",
|
||||||
|
"valueHandler": "Number Threshold"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeFrom": null,
|
||||||
|
"timeShift": null,
|
||||||
|
"title": "Panel Title",
|
||||||
|
"tooltip": {
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"type": "flant-statusmap-panel",
|
||||||
|
"urls": [
|
||||||
|
{
|
||||||
|
"base_url": "",
|
||||||
|
"extraSeries": {
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "",
|
||||||
|
"tooltip": "",
|
||||||
|
"useExtraSeries": false,
|
||||||
|
"useseriesname": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"useMax": true,
|
||||||
|
"usingUrl": true,
|
||||||
|
"xAxis": {
|
||||||
|
"labelFormat": "%a %m/%d",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"yAxis": {
|
||||||
|
"maxWidth": -1,
|
||||||
|
"minWidth": -1,
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"yAxisSort": "metrics"
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
panel = Object.assign({}, panelConfig);
|
||||||
|
migratePanelConfig(panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should migrate usingUrls to tooltip.freezeOnClick', () => {
|
||||||
|
expect(panel.usingUrl).toBeUndefined();
|
||||||
|
expect(panel.tooltip).toHaveProperty("freezeOnClick", true);
|
||||||
|
expect(panel.tooltip.freezeOnClick).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have no urls', () => {
|
||||||
|
expect(panel.urls).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have empty items in tooltip', () => {
|
||||||
|
expect(panel.tooltip).toHaveProperty("items", []);
|
||||||
|
expect(panel.tooltip.items).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("given configuration with non-empty base_url", () => {
|
||||||
|
|
||||||
|
describe("with variables", () => {
|
||||||
|
const panelConfig = {
|
||||||
|
"tooltip": {
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
"urls": [
|
||||||
|
{
|
||||||
|
"base_url": "https://google.com/$series_label$time",
|
||||||
|
"extraSeries": {
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "google",
|
||||||
|
"tooltip": "",
|
||||||
|
"useExtraSeries": false,
|
||||||
|
"useseriesname": true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"base_url": "example.com/$series_extra",
|
||||||
|
"extraSeries": {
|
||||||
|
"format": "YYYY/MM/DD/HH_mm_ss",
|
||||||
|
"index": -1
|
||||||
|
},
|
||||||
|
"forcelowercase": true,
|
||||||
|
"icon_fa": "external-link",
|
||||||
|
"label": "DateLink",
|
||||||
|
"useExtraSeries": true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
beforeEach(() => {
|
||||||
|
panel = Object.assign({}, panelConfig);
|
||||||
|
migratePanelConfig(panel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have equal size of tooltip.items", () => {
|
||||||
|
expect(panel.tooltip).toHaveProperty("items");
|
||||||
|
expect(panel.tooltip.items).toHaveLength(panelConfig.urls.length);
|
||||||
|
});
|
||||||
|
it("should replace time variable with __url_time_range", () => {
|
||||||
|
expect(panel.tooltip.items[0].urlTemplate).toContain("${__url_time_range}");
|
||||||
|
});
|
||||||
|
it("should replace series_label variable with __y_label", () => {
|
||||||
|
expect(panel.tooltip.items[0].urlTemplate).toContain("${__y_label}");
|
||||||
|
});
|
||||||
|
it("should replace series_extra variable with __value_date", () => {
|
||||||
|
expect(panel.tooltip.items[1].urlTemplate).toContain("${__value_date}");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+176
-31
@@ -7,22 +7,29 @@ import { StatusHeatmapCtrl } from './module';
|
|||||||
let TOOLTIP_PADDING_X = 30;
|
let TOOLTIP_PADDING_X = 30;
|
||||||
let TOOLTIP_PADDING_Y = 5;
|
let TOOLTIP_PADDING_Y = 5;
|
||||||
|
|
||||||
|
// TODO rename file to tooltip_ctrl.ts
|
||||||
|
// TODO move DefaultValueDateFormat into tooltip.ts, as it used in several places (migration, partial and tooltip render)
|
||||||
|
let DefaultValueDateFormat = 'YYYY/MM/DD/HH_mm_ss';
|
||||||
|
|
||||||
export class StatusmapTooltip {
|
export class StatusmapTooltip {
|
||||||
tooltip: any;
|
tooltip: any;
|
||||||
scope: any;
|
scope: any;
|
||||||
dashboard: any;
|
dashboard: any;
|
||||||
panelCtrl: StatusHeatmapCtrl;
|
panelCtrl: StatusHeatmapCtrl;
|
||||||
panel: any;
|
panel: any;
|
||||||
heatmapPanel: any;
|
panelElem: any;
|
||||||
mouseOverBucket: any;
|
mouseOverBucket: any;
|
||||||
originalFillColor: any;
|
originalFillColor: any;
|
||||||
|
|
||||||
|
tooltipWidth: number;
|
||||||
|
tooltipFrozen: any;
|
||||||
|
|
||||||
constructor(elem: any, scope: any) {
|
constructor(elem: any, scope: any) {
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.dashboard = scope.ctrl.dashboard;
|
this.dashboard = scope.ctrl.dashboard;
|
||||||
this.panelCtrl = scope.ctrl;
|
this.panelCtrl = scope.ctrl;
|
||||||
this.panel = scope.ctrl.panel;
|
this.panel = scope.ctrl.panel;
|
||||||
this.heatmapPanel = elem;
|
this.panelElem = elem;
|
||||||
this.mouseOverBucket = false;
|
this.mouseOverBucket = false;
|
||||||
this.originalFillColor = null;
|
this.originalFillColor = null;
|
||||||
|
|
||||||
@@ -35,7 +42,7 @@ export class StatusmapTooltip {
|
|||||||
|
|
||||||
if (!this.tooltip) {
|
if (!this.tooltip) {
|
||||||
this.add();
|
this.add();
|
||||||
this.move(e);
|
this.move(e, this.tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,13 +53,13 @@ export class StatusmapTooltip {
|
|||||||
onMouseMove(e) {
|
onMouseMove(e) {
|
||||||
if (!this.panel.tooltip.show) { return; }
|
if (!this.panel.tooltip.show) { return; }
|
||||||
|
|
||||||
this.move(e);
|
this.move(e, this.tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
add() {
|
add() {
|
||||||
this.tooltip = d3.select("body")
|
this.tooltip = d3.select("body")
|
||||||
.append("div")
|
.append("div")
|
||||||
.attr("class", "statusmap-tooltip graph-tooltip grafana-tooltip");
|
.attr("class", "graph-tooltip statusmap-tooltip");
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
@@ -63,13 +70,37 @@ export class StatusmapTooltip {
|
|||||||
this.tooltip = null;
|
this.tooltip = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
show(pos) {
|
removeFrozen() {
|
||||||
|
if (this.tooltipFrozen) {
|
||||||
|
this.tooltipFrozen.remove();
|
||||||
|
this.tooltipFrozen = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showFrozen(pos: any) {
|
||||||
|
this.removeFrozen();
|
||||||
|
this.tooltipFrozen = d3.select(this.panelElem[0])
|
||||||
|
.append("div")
|
||||||
|
.attr("class", "graph-tooltip statusmap-tooltip statusmap-tooltip-frozen");
|
||||||
|
this.displayTooltip(pos, this.tooltipFrozen, true);
|
||||||
|
this.moveRelative(pos, this.tooltipFrozen);
|
||||||
|
}
|
||||||
|
|
||||||
|
show(pos: any) {
|
||||||
if (!this.panel.tooltip.show || !this.tooltip) { return; }
|
if (!this.panel.tooltip.show || !this.tooltip) { return; }
|
||||||
|
|
||||||
// TODO support for shared tooltip mode
|
// TODO support for shared tooltip mode
|
||||||
if (pos.panelRelY) {
|
if (pos.panelRelY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.displayTooltip(pos, this.tooltip, false);
|
||||||
|
|
||||||
|
this.move(pos, this.tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve bucket and create html content inside tooltip’s div element.
|
||||||
|
displayTooltip(pos: any, tooltip: any, frozen: boolean) {
|
||||||
let cardEl = d3.select(pos.target);
|
let cardEl = d3.select(pos.target);
|
||||||
let yid = cardEl.attr('yid');
|
let yid = cardEl.attr('yid');
|
||||||
let xid = cardEl.attr('xid');
|
let xid = cardEl.attr('xid');
|
||||||
@@ -80,36 +111,44 @@ export class StatusmapTooltip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let timestamp = bucket.to;
|
let timestamp = bucket.to;
|
||||||
let name = bucket.yLabel;
|
let yLabel = bucket.yLabel;
|
||||||
let value = bucket.value;
|
let value = bucket.value;
|
||||||
let values = bucket.values;
|
let values = bucket.values;
|
||||||
let tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';
|
// TODO create option for this formatting.
|
||||||
let time = this.dashboard.formatDate(+timestamp, tooltipTimeFormat);
|
let tooltipTimeFormat:string = 'YYYY-MM-DD HH:mm:ss';
|
||||||
|
let time: Date = this.dashboard.formatDate(+timestamp, tooltipTimeFormat);
|
||||||
|
|
||||||
let tooltipHtml = `<div class="graph-tooltip-time">${time}</div>
|
// Close button for the frozen tooltip.
|
||||||
<div class="statusmap-histogram"></div>`;
|
let tooltipClose:string = ``;
|
||||||
|
if (frozen) {
|
||||||
|
tooltipClose = `
|
||||||
|
<a class="pointer pull-right small tooltip-close">
|
||||||
|
<i class="fa fa-remove"></i>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
let statuses;
|
let tooltipHtml:string = `<div class="graph-tooltip-time">${time}${tooltipClose}</div>`;
|
||||||
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
if (this.panel.color.mode === 'discrete') {
|
||||||
|
let statuses;
|
||||||
if (this.panel.seriesFilterIndex >= 0) {
|
if (this.panel.seriesFilterIndex >= 0) {
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
||||||
} else {
|
} else {
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
let statusesHtml = '';
|
let statusTitle:string = "status:";
|
||||||
if (statuses.length === 1) {
|
if (statuses.length > 1) {
|
||||||
statusesHtml = "status:";
|
statusTitle = "statuses:";
|
||||||
} else if (statuses.length > 1) {
|
|
||||||
statusesHtml = "statuses:";
|
|
||||||
}
|
}
|
||||||
tooltipHtml += `
|
tooltipHtml += `
|
||||||
<div>
|
<div>
|
||||||
name: <b>${name}</b> <br>
|
name: <b>${yLabel}</b>
|
||||||
${statusesHtml}
|
<br>
|
||||||
|
<span>${statusTitle}</span>
|
||||||
<ul>
|
<ul>
|
||||||
${_.join(_.map(statuses, v => `<li style="background-color: ${v.color}" class="discrete-item">${v.tooltip}</li>`), "")}
|
${_.join(_.map(statuses, v => `<li style="background-color: ${v.color}; text-align:center" class="discrete-item">${v.tooltip}</li>`), "")}
|
||||||
</ul>
|
</ul>
|
||||||
</div>`;
|
</div>`;
|
||||||
} else {
|
} else {
|
||||||
@@ -120,7 +159,7 @@ export class StatusmapTooltip {
|
|||||||
</div>`;
|
</div>`;
|
||||||
} else {
|
} else {
|
||||||
tooltipHtml += `<div>
|
tooltipHtml += `<div>
|
||||||
name: <b>${name}}</b> <br>
|
name: <b>${name}</b> <br>
|
||||||
values:
|
values:
|
||||||
<ul>
|
<ul>
|
||||||
${_.join(_.map(values, v => `<li>${v}</li>`), "")}
|
${_.join(_.map(values, v => `<li>${v}</li>`), "")}
|
||||||
@@ -129,14 +168,73 @@ export class StatusmapTooltip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Ambiguous bucket state: Multiple values!";
|
tooltipHtml += `<div class="statusmap-histogram"></div>`;
|
||||||
|
|
||||||
|
if (this.panel.tooltip.showItems) {
|
||||||
|
// Additional information: urls, etc.
|
||||||
|
// Clone additional items
|
||||||
|
let items: any = JSON.parse(JSON.stringify(this.panel.tooltip.items));
|
||||||
|
|
||||||
|
let scopedVars = {};
|
||||||
|
|
||||||
|
let valueVar;
|
||||||
|
for (let i = 0; i < bucket.values.length; i++) {
|
||||||
|
valueVar = `__value_${i}`;
|
||||||
|
scopedVars[valueVar] = {value: bucket.values[i] };
|
||||||
|
}
|
||||||
|
scopedVars[`__value`] = {value: bucket.value};
|
||||||
|
scopedVars[`__y_label`] = {value: yLabel};
|
||||||
|
// Grafana 7.0 compatible
|
||||||
|
scopedVars[`__url_time_range`] = {value: this.panelCtrl.retrieveTimeVar()};
|
||||||
|
|
||||||
|
for (let item of items) {
|
||||||
|
if (_.isEmpty(item.urlTemplate)) {
|
||||||
|
item.link = "#";
|
||||||
|
} else {
|
||||||
|
let dateFormat = item.valueDateFormat;
|
||||||
|
if (dateFormat == '') {
|
||||||
|
dateFormat = DefaultValueDateFormat;
|
||||||
|
}
|
||||||
|
let valueDateVar;
|
||||||
|
for (let i = 0; i < bucket.values.length; i++) {
|
||||||
|
valueDateVar = `__value_${i}_date`;
|
||||||
|
scopedVars[valueDateVar] = {value: this.dashboard.formatDate(+bucket.values[i], dateFormat)};
|
||||||
|
}
|
||||||
|
scopedVars[`__value_date`] = {value: this.dashboard.formatDate(+bucket.value, dateFormat)};
|
||||||
|
|
||||||
|
item.link = this.panelCtrl.templateSrv.replace(item.urlTemplate, scopedVars)
|
||||||
|
|
||||||
|
// Force lowercase for link
|
||||||
|
if (item.urlToLowerCase) {
|
||||||
|
item.link = item.link.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.label = item.urlText;
|
||||||
|
if (_.isEmpty(item.label)) {
|
||||||
|
item.label = _.isEmpty(item.urlTemplate) ? "Empty URL" : _.truncate(item.link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltipHtml += _.join(_.map(items, v => `
|
||||||
|
<div>
|
||||||
|
<a href="${v.link}" target="_blank">
|
||||||
|
<div class="dashlist-item">
|
||||||
|
<p class="dashlist-link dashlist-link-dash-db">
|
||||||
|
<span style="word-wrap: break-word;" class="dash-title">${v.label}</span><span class="dashlist-star">
|
||||||
|
<i class="fa fa-${v.urlIcon}"></i>
|
||||||
|
</span></p> </div></a><div>`), "\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambiguous state: there multiple values in bucket!
|
||||||
|
// TODO rename useMax to expectMultipleValues
|
||||||
if (!this.panel.useMax && bucket.multipleValues) {
|
if (!this.panel.useMax && bucket.multipleValues) {
|
||||||
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.multipleValues.title}</div>`;
|
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.multipleValues.title}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discrete mode errors
|
// Discrete mode errors
|
||||||
if (this.panel.color.mode === 'discrete') {
|
if (this.panel.color.mode === 'discrete') {
|
||||||
|
|
||||||
if (bucket.noColorDefined) {
|
if (bucket.noColorDefined) {
|
||||||
let badValues = this.panelCtrl.discreteExtraSeries.getNotColoredValues(values);
|
let badValues = this.panelCtrl.discreteExtraSeries.getNotColoredValues(values);
|
||||||
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.noColorDefined.title}
|
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.noColorDefined.title}
|
||||||
@@ -145,20 +243,32 @@ export class StatusmapTooltip {
|
|||||||
${_.join(_.map(badValues, v => `<li>${v}</li>`), "")}
|
${_.join(_.map(badValues, v => `<li>${v}</li>`), "")}
|
||||||
</ul>
|
</ul>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tooltip.html(tooltipHtml);
|
tooltip.html(tooltipHtml);
|
||||||
|
|
||||||
this.move(pos);
|
// Assign mouse event handlers for "frozen" tooltip.
|
||||||
|
if (frozen) {
|
||||||
|
// Stop propagation mouse events up to parents to allow interaction with frozen tooltip’s elements.
|
||||||
|
tooltip
|
||||||
|
.on("click", function(){d3.event.stopPropagation(); })
|
||||||
|
.on("mousedown", function(){d3.event.stopPropagation(); })
|
||||||
|
.on("mouseup", function(){d3.event.stopPropagation(); });
|
||||||
|
|
||||||
|
// Activate close button
|
||||||
|
tooltip.select("a.tooltip-close")
|
||||||
|
.on("click", this.removeFrozen.bind(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
move(pos) {
|
// Move tooltip as absolute positioned element.
|
||||||
if (!this.tooltip) { return; }
|
move(pos, tooltip) {
|
||||||
|
if (!tooltip) { return; }
|
||||||
|
|
||||||
let elem = $(this.tooltip.node())[0];
|
let elem = $(tooltip.node())[0];
|
||||||
let tooltipWidth = elem.clientWidth;
|
let tooltipWidth = elem.clientWidth;
|
||||||
|
this.tooltipWidth = tooltipWidth;
|
||||||
let tooltipHeight = elem.clientHeight;
|
let tooltipHeight = elem.clientHeight;
|
||||||
|
|
||||||
let left = pos.pageX + TOOLTIP_PADDING_X;
|
let left = pos.pageX + TOOLTIP_PADDING_X;
|
||||||
@@ -172,8 +282,43 @@ export class StatusmapTooltip {
|
|||||||
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tooltip
|
return tooltip
|
||||||
.style("left", left + "px")
|
.style("left", left + "px")
|
||||||
.style("top", top + "px");
|
.style("top", top + "px");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move tooltip relative to svg element of panel.
|
||||||
|
moveRelative(pos, tooltip) {
|
||||||
|
if (!tooltip) { return; }
|
||||||
|
|
||||||
|
let panelX = pos.pageX - this.panelElem.offset().left;
|
||||||
|
let panelY = pos.pageY - this.panelElem.offset().top;
|
||||||
|
let panelWidth = this.panelElem.width();
|
||||||
|
let panelHeight = this.panelElem.height();
|
||||||
|
|
||||||
|
// 'position: relative' sets tooltip’s width to 100% of panel element.
|
||||||
|
// Restore width from floating tooltip and add more space for 'Close' button.
|
||||||
|
let tooltipWidth = this.tooltipWidth + 25;
|
||||||
|
|
||||||
|
// Left property is clamped so tooltip stays inside panel bound box.
|
||||||
|
let tooltipLeft = panelX + TOOLTIP_PADDING_X;
|
||||||
|
if (tooltipLeft + tooltipWidth > panelWidth) {
|
||||||
|
tooltipLeft = panelWidth - tooltipWidth;
|
||||||
|
}
|
||||||
|
if (tooltipLeft < 0 ) {
|
||||||
|
tooltipLeft = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frozen tooltip’s root element is appended next to panel’s svg element,
|
||||||
|
// so top property is adjusted to move tooltip’s root element
|
||||||
|
// up to the mouse pointer position.
|
||||||
|
let tooltipTop = -(panelHeight - panelY + TOOLTIP_PADDING_Y);
|
||||||
|
|
||||||
|
return tooltip
|
||||||
|
.style("left", tooltipLeft + "px")
|
||||||
|
.style("top", tooltipTop + "px")
|
||||||
|
.style("width", tooltipWidth + "px");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { StatusHeatmapCtrl } from './module';
|
||||||
|
|
||||||
|
let emptyTooltipItem = {
|
||||||
|
urlText: '',
|
||||||
|
urlTemplate: '',
|
||||||
|
urlIcon: 'external-link',
|
||||||
|
urlToLowerCase: true,
|
||||||
|
valueDateFormat: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
export class TooltipEditorCtrl {
|
||||||
|
panel: any;
|
||||||
|
panelCtrl: StatusHeatmapCtrl;
|
||||||
|
|
||||||
|
constructor($scope: any) {
|
||||||
|
$scope.editor = this;
|
||||||
|
this.panelCtrl = $scope.ctrl as StatusHeatmapCtrl;
|
||||||
|
this.panel = this.panelCtrl.panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.panelCtrl.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddUrl() {
|
||||||
|
this.panel.tooltip.items.push(Object.assign({}, emptyTooltipItem));
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveUrl(index: number) {
|
||||||
|
this.panel.tooltip.items.splice(index, 1);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoveUrls() {
|
||||||
|
this.panel.tooltip.items = [];
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
getFAIconClasses() {
|
||||||
|
return ['external-link', 'plus', 'anchor', 'ban', 'globe', 'gear', 'cloud', 'download', 'cloud-download'];
|
||||||
|
}
|
||||||
|
|
||||||
|
getValueDateFormats() {
|
||||||
|
return [
|
||||||
|
'YYYY/MM/DD/HH_mm_ss',
|
||||||
|
'YYYYMMDDHHmmss',
|
||||||
|
'YYYY-MM-DD-HH-mm-ss'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tooltipEditorCtrl() {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: true,
|
||||||
|
templateUrl: 'public/plugins/flant-statusmap-panel/partials/tooltip_editor.html',
|
||||||
|
controller: TooltipEditorCtrl,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
import d3 from 'd3';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import { ExtraSeriesFormatValue } from './extra_series_format';
|
|
||||||
|
|
||||||
const TOOLTIP_PADDING_X = -50;
|
|
||||||
const TOOLTIP_PADDING_Y = 5;
|
|
||||||
|
|
||||||
export class StatusHeatmapTooltipExtraSeries {
|
|
||||||
scope: any;
|
|
||||||
dashboard: any;
|
|
||||||
panelCtrl: any;
|
|
||||||
panel: any;
|
|
||||||
heatmapPanel: any;
|
|
||||||
mouseOverBucket: any;
|
|
||||||
originalFillColor: any;
|
|
||||||
tooltip: any;
|
|
||||||
|
|
||||||
constructor(elem: any, scope: any) {
|
|
||||||
this.scope = scope;
|
|
||||||
this.dashboard = scope.ctrl.dashboard;
|
|
||||||
this.panelCtrl = scope.ctrl;
|
|
||||||
this.panel = scope.ctrl.panel;
|
|
||||||
this.heatmapPanel = elem;
|
|
||||||
this.mouseOverBucket = false;
|
|
||||||
this.originalFillColor = null;
|
|
||||||
|
|
||||||
elem.on("mouseover", this.onMouseOver.bind(this));
|
|
||||||
elem.on("click", this.onMouseClick.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public onMouseOver(e: Event) {
|
|
||||||
if (!this.panel.usingUrl || !this.scope.ctrl.data || _.isEmpty(this.scope.ctrl.data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public onMouseClick(e: Event) {
|
|
||||||
if (!this.panel.usingUrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.destroy();
|
|
||||||
this.add();
|
|
||||||
}
|
|
||||||
|
|
||||||
public add() {
|
|
||||||
this.tooltip = d3.select("body")
|
|
||||||
.append("div")
|
|
||||||
.attr("class", "statusmap-tooltip-extraseries graph-tooltip grafana-tooltip");
|
|
||||||
}
|
|
||||||
|
|
||||||
public destroy() {
|
|
||||||
if (this.tooltip) {
|
|
||||||
this.tooltip.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tooltip = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public show(pos: any) {
|
|
||||||
if (!this.panel.usingUrl || !this.tooltip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shared tooltip mode
|
|
||||||
if (pos.panelRelY) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cardId: any = d3.select(pos.target).attr('cardId');
|
|
||||||
|
|
||||||
if (!cardId) {
|
|
||||||
this.destroy();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let card: any = this.panelCtrl.cardsData.cards[cardId];
|
|
||||||
|
|
||||||
if (!card) {
|
|
||||||
this.destroy();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (card.value == null) {
|
|
||||||
this.destroy();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let x: any = card.x;
|
|
||||||
let y: any = card.y;
|
|
||||||
let value: any = card.value;
|
|
||||||
let values: any = card.values;
|
|
||||||
let tooltipTimeFormat: string = 'YYYY-MM-DD HH:mm:ss';
|
|
||||||
let time: Date = this.dashboard.formatDate(+x, tooltipTimeFormat);
|
|
||||||
|
|
||||||
let tooltipHtml: string = `<div class="graph-tooltip-time">${time}</div>`
|
|
||||||
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
|
||||||
let statuses: any = "";
|
|
||||||
|
|
||||||
if (this.panelCtrl.panel.seriesFilterIndex == -1) {
|
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
|
|
||||||
} else {
|
|
||||||
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltipHtml += `
|
|
||||||
<div>
|
|
||||||
name: <b>${y}</b>
|
|
||||||
<div>
|
|
||||||
<br>
|
|
||||||
<span>status:</span>
|
|
||||||
<ul>
|
|
||||||
${_.join(_.map(statuses, v => `<p style="background-color: ${v.color}; text-align:center" class="discrete-item">${v.tooltip}</p>`), "")}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div> <br>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltipHtml += `<div class="statusmap-histogram"></div>`;
|
|
||||||
|
|
||||||
let urls: any = this.panelCtrl.panel.urls
|
|
||||||
let rtime: any = this.panelCtrl.retrieveTimeVar();
|
|
||||||
|
|
||||||
let curl: any = JSON.parse(JSON.stringify(urls));
|
|
||||||
|
|
||||||
for (let i = 0; i < curl.length; i++) {
|
|
||||||
//Change name var
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$series_label/g, y)
|
|
||||||
//Set up extra series
|
|
||||||
if (curl[i].useExtraSeries == true) {
|
|
||||||
let tf: any = curl[i].extraSeries.format
|
|
||||||
let vh: any = card.values[curl[i].extraSeries.index]
|
|
||||||
//let extraSeries: any = this.dashboard.formatDate(+vh, tf)
|
|
||||||
let series_extra: any = this.formatExtraSeries(vh,tf);
|
|
||||||
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$series_extra/g, series_extra)
|
|
||||||
}
|
|
||||||
//Change time var
|
|
||||||
curl[i].base_url = _.replace(curl[i].base_url, /\$time/g, rtime)
|
|
||||||
|
|
||||||
//Replace vars
|
|
||||||
curl[i].base_url = this.panelCtrl.renderLink(curl[i].base_url, this.panelCtrl.variableSrv.variables)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.panelCtrl.panel.usingUrl == true) {
|
|
||||||
tooltipHtml += `
|
|
||||||
<div bs-tooltip='Settings' data-placement="right">
|
|
||||||
${_.join(_.map(curl, v => `<div ><a href="${v.forcelowercase ? v.base_url.toLowerCase() : v.base_url}" target="_blank"><div class="dashlist-item">
|
|
||||||
<p class="dashlist-link dashlist-link-dash-db"><span style="word-wrap: break-word;" class="dash-title">${v.label ? v.label : (v.base_url != "" ? _.truncate(v.base_url) : "Empty URL" )}</span><span class="dashlist-star">
|
|
||||||
<i class="fa fa-${v.icon_fa}"></i>
|
|
||||||
</span></p> </div></a><div>`), "")}
|
|
||||||
</div> <br>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Ambiguous bucket state: Multiple values!";
|
|
||||||
if (!this.panel.useMax && card.multipleValues) {
|
|
||||||
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.multipleValues.title}</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Discrete mode errors
|
|
||||||
if (this.panel.color.mode === 'discrete') {
|
|
||||||
if (card.noColorDefined) {
|
|
||||||
let badValues: any = this.panelCtrl.discreteExtraSeries.getNotColoredValues(values);
|
|
||||||
tooltipHtml += `<div><b>Error:</b> ${this.panelCtrl.dataWarnings.noColorDefined.title}
|
|
||||||
<br>not colored values:
|
|
||||||
<ul>
|
|
||||||
${_.join(_.map(badValues, v => `<li>${v}</li>`), "")}
|
|
||||||
</ul>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tooltip.html(tooltipHtml);
|
|
||||||
|
|
||||||
this.move(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public formatExtraSeries (value: any, type: any) {
|
|
||||||
let extraSeries: any = '';
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case ExtraSeriesFormatValue.Date:
|
|
||||||
extraSeries = this.dashboard.formatDate(+value, type);
|
|
||||||
return extraSeries;
|
|
||||||
case ExtraSeriesFormatValue.Raw:
|
|
||||||
extraSeries = value;
|
|
||||||
return extraSeries;
|
|
||||||
default:
|
|
||||||
return extraSeries;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public move(pos: any) {
|
|
||||||
if (!this.tooltip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let elem: any = $(this.tooltip.node())[0];
|
|
||||||
let tooltipWidth = elem.clientWidth;
|
|
||||||
let tooltipHeight = elem.clientHeight;
|
|
||||||
|
|
||||||
let left = pos.pageX + TOOLTIP_PADDING_X;
|
|
||||||
let top = pos.pageY + TOOLTIP_PADDING_Y;
|
|
||||||
|
|
||||||
if (pos.pageX + tooltipWidth + 40 > window.innerWidth) {
|
|
||||||
left = pos.pageX - tooltipWidth - TOOLTIP_PADDING_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos.pageY - window.pageYOffset + tooltipHeight + 20 > window.innerHeight) {
|
|
||||||
top = pos.pageY - tooltipHeight - TOOLTIP_PADDING_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tooltip
|
|
||||||
.style("left", left + "px")
|
|
||||||
.style("top", top + "px");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user