Merge pull request #86 from JoaquinJimenezGarcia/tooltip_with_urls

Created a new tooltip when click in a value to have different external links
This commit is contained in:
Ivan Mikheykin
2020-03-04 17:16:40 +03:00
committed by GitHub
38 changed files with 1241 additions and 63 deletions
+28
View File
@@ -182,6 +182,34 @@ __Show tooltip__ toggles tooltip display on mouse over buckets.
__Y axis sort__ can be used to sort labels on Y axis. Metrics — sort y labels as they are defined on Metrics tab. a→z and z→a sort labels descending or ascending in a [natural](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) order. __Y axis sort__ can be used to sort labels on Y axis. Metrics — sort y labels as they are defined on Metrics tab. a→z and z→a sort labels descending or ascending in a [natural](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) order.
#### Tooltip with external link
![Tooltip with external link](src/img/tooltip-url.png)
A new tooltip that will appear when mouse click in a value showing one or more links to navigate. It can be configured in the options editor. Also it can be disabled to not appear.
#### Tooltip editor
![Tooltip options](src/img/tooltip-editor.png)
__Show Extra Series Tooltip when clicking elements__ toggles tooltip with links display on mouse click.
__Add new URL__ creates a new form to add a new link
__Remove all URLs__ removes all the urls created before
__Label__ name to show in the link instead of the URL
__URL__ URL to navigate
__Icon__ icon to show next to the url
__Force lowercase__ forces the url to be lowercase even if it is written in capital letters
__Extra Series Completer__ toggles extra series to write the URL
__Extra Series Index__ fields index to use its value on URL using $series_extra. Use -1 to disable it
__Extra Series Date Format__ date format to transform extra herlper when its type is Date
## Development ## Development
To test and improve the plugin you can run Grafana instance in Docker using following command (in To test and improve the plugin you can run Grafana instance in Docker using following command (in
+28
View File
@@ -182,6 +182,34 @@ __Show tooltip__ toggles tooltip display on mouse over buckets.
__Y axis sort__ can be used to sort labels on Y axis. Metrics — sort y labels as they are defined on Metrics tab. a→z and z→a sort labels descending or ascending in a [natural](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) order. __Y axis sort__ can be used to sort labels on Y axis. Metrics — sort y labels as they are defined on Metrics tab. a→z and z→a sort labels descending or ascending in a [natural](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) order.
#### Tooltip with external link
![Tooltip with external link](src/img/tooltip-url.png)
A new tooltip that will appear when mouse click in a value showing one or more links to navigate. It can be configured in the options editor. Also it can be disabled to not appear.
#### Tooltip editor
![Tooltip options](src/img/tooltip-editor.png)
__Show Extra Series Tooltip when clicking elements__ toggles tooltip with links display on mouse click.
__Add new URL__ creates a new form to add a new link
__Remove all URLs__ removes all the urls created before
__Label__ name to show in the link instead of the URL
__URL__ URL to navigate
__Icon__ icon to show next to the url
__Force lowercase__ forces the url to be lowercase even if it is written in capital letters
__Extra Series Completer__ toggles extra series to write the URL
__Extra Series Index__ fields index to use its value on URL using $series_extra. Use -1 to disable it
__Extra Series Date Format__ date format to transform extra herlper when its type is Date
## Development ## Development
To test and improve the plugin you can run Grafana instance in Docker using following command (in To test and improve the plugin you can run Grafana instance in Docker using following command (in
+3 -3
View File
@@ -53,7 +53,7 @@ System.register(["lodash", "jquery", "d3", "./libs/d3-scale-chromatic/index", "a
drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth); drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth);
} }
function drawDiscreteColorLegend(elem, colorOptions, discreteHelper) { function drawDiscreteColorLegend(elem, colorOptions, discreteExtraSeries) {
var legendElem = $(elem).find('svg'); var legendElem = $(elem).find('svg');
var legend = d3.select(legendElem.get(0)); var legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
@@ -87,7 +87,7 @@ System.register(["lodash", "jquery", "d3", "./libs/d3-scale-chromatic/index", "a
return d * itemWidth; return d * itemWidth;
}).attr("y", 0).attr("width", itemWidth + 1) // Overlap rectangles to prevent gaps }).attr("y", 0).attr("width", itemWidth + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) { .attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) {
return discreteHelper.getDiscreteColor(d); return discreteExtraSeries.getDiscreteColor(d);
}); });
drawDiscreteLegendValues(elem, colorOptions, legendWidth); drawDiscreteLegendValues(elem, colorOptions, legendWidth);
} }
@@ -378,7 +378,7 @@ System.register(["lodash", "jquery", "d3", "./libs/d3-scale-chromatic/index", "a
drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue); drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue);
} else if (panel.color.mode === 'discrete') { } else if (panel.color.mode === 'discrete') {
var _colorOptions = panel.color; var _colorOptions = panel.color;
drawDiscreteColorLegend(elem, _colorOptions, ctrl.discreteHelper); drawDiscreteColorLegend(elem, _colorOptions, ctrl.discreteExtraSeries);
} }
} }
} }
+1 -1
View File
File diff suppressed because one or more lines are too long
+57 -1
View File
@@ -16,7 +16,7 @@ System.register([], function (_export, _context) {
return { return {
setters: [], setters: [],
execute: function () { execute: function () {
// Helper methods to handle discrete color mode // Extra Series methods to handle discrete color mode
_export("ColorModeDiscrete", ColorModeDiscrete = _export("ColorModeDiscrete", ColorModeDiscrete =
/*#__PURE__*/ /*#__PURE__*/
function () { function () {
@@ -55,6 +55,24 @@ System.register([], function (_export, _context) {
return tooltips; return tooltips;
} }
}, { }, {
key: "convertValueToTooltips",
value: function convertValueToTooltips(values) {
var thresholds = this.panel.color.thresholds;
var tooltips = [];
for (var i = 0; i < thresholds.length; i++) {
//for (let j = 0; j < values.length; j++) {
if (values == thresholds[i].value) {
tooltips.push({
"tooltip": thresholds[i].tooltip ? thresholds[i].tooltip : values,
"color": thresholds[i].color
}); //}
}
}
return tooltips;
}
}, {
key: "getNotMatchedValues", key: "getNotMatchedValues",
value: function getNotMatchedValues(values) { value: function getNotMatchedValues(values) {
var notMatched = []; var notMatched = [];
@@ -92,6 +110,23 @@ System.register([], function (_export, _context) {
} }
return color; return color;
}
}, {
key: "getBucketColorSingle",
value: function getBucketColorSingle(value) {
//let thresholds = this.panel.color.thresholds;
if (value == null) {
// treat as null value
return 'rgba(0,0,0,1)'; //return this.getMatchedThreshold(null).color;
}
var threshold = this.getMatchedThreshold(value);
if (!threshold || !threshold.color || threshold.color == "") {
return 'rgba(0,0,0,1)';
} else {
return threshold.color;
}
} // returns color from first matched thresold in order from 0 to thresholds.length } // returns color from first matched thresold in order from 0 to thresholds.length
}, { }, {
@@ -136,6 +171,27 @@ System.register([], function (_export, _context) {
return 'rgba(0,0,0,1)'; return 'rgba(0,0,0,1)';
} }
}, {
key: "updateCardsValuesHasColorInfoSingle",
value: function updateCardsValuesHasColorInfoSingle() {
if (!this.panelCtrl.cardsData) {
return;
}
this.panelCtrl.cardsData.noColorDefined = false;
var cards = this.panelCtrl.cardsData.cards;
for (var i = 0; i < cards.length; i++) {
cards[i].noColorDefined = false;
var values = cards[i].value;
var threshold = this.getMatchedThreshold(values);
if (!threshold || !threshold.color || threshold.color == "") {
cards[i].noColorDefined = true;
this.panelCtrl.cardsData.noColorDefined = true;
}
}
}
}, { }, {
key: "updateCardsValuesHasColorInfo", key: "updateCardsValuesHasColorInfo",
value: function updateCardsValuesHasColorInfo() { value: function updateCardsValuesHasColorInfo() {
+1 -1
View File
File diff suppressed because one or more lines are too long
+26 -2
View File
@@ -27,10 +27,22 @@
background-color: #141414; background-color: #141414;
color: #d8d9da; } color: #d8d9da; }
.statusmap-tooltip .discrete-item { .statusmap-tooltip .discrete-item {
color: #52545c; color: #ffffff;
padding: 1px; padding: 1px;
font-weight: bold; font-weight: bold;
text-shadow: 0 0 0.2em #FFF, 0 0 0.2em #FFF, 0 0 0.2em #FFF; } text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
.statusmap-tooltip-extraseries {
white-space: nowrap;
font-size: 12px;
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; }
@@ -44,6 +56,18 @@
fill: rgba(102, 102, 102, 0.4); fill: rgba(102, 102, 102, 0.4);
stroke: rgba(102, 102, 102, 0.8); } stroke: rgba(102, 102, 102, 0.8); }
.width-c-40 {
width: 40rem !important; }
.width-c-50 {
width: 50rem !important; }
.width-c-60 {
width: 60rem !important; }
.width-c-70 {
width: 70rem !important; }
.status-heatmap-legend-wrapper { .status-heatmap-legend-wrapper {
margin: 0 10px; } margin: 0 10px; }
.status-heatmap-legend-wrapper svg { .status-heatmap-legend-wrapper svg {
+1 -1
View File
@@ -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,qBAAsB;EACpB,QAAQ,EAAE,QAAQ;EAGhB,sCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,sCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,yBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,8BAAK;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,8CAA8C;;AAI/D,yBAA0B;EACxB,IAAI,ECvDY,OAAO;;AD2DvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAIlC,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,EC7FG,OAAO;ID8Fd,KAAK,EC9FE,OAAO;ID+Fd,SAAS,EE/FE,IAAI;EFkGjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECnGM,OAAO;EDsGrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECxGM,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,qBAAsB;EACpB,QAAQ,EAAE,QAAQ;EAGhB,sCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,sCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,yBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,8BAAK;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",
"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"
+26 -2
View File
@@ -27,10 +27,22 @@
background-color: #dde4ed; background-color: #dde4ed;
color: #52545c; } color: #52545c; }
.statusmap-tooltip .discrete-item { .statusmap-tooltip .discrete-item {
color: #52545c; color: #ffffff;
padding: 1px; padding: 1px;
font-weight: bold; font-weight: bold;
text-shadow: 0 0 0.2em #FFF, 0 0 0.2em #FFF, 0 0 0.2em #FFF; } text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124; }
.statusmap-tooltip-extraseries {
white-space: nowrap;
font-size: 12px;
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; }
@@ -44,6 +56,18 @@
fill: rgba(102, 102, 102, 0.4); fill: rgba(102, 102, 102, 0.4);
stroke: rgba(102, 102, 102, 0.8); } stroke: rgba(102, 102, 102, 0.8); }
.width-c-40 {
width: 40rem !important; }
.width-c-50 {
width: 50rem !important; }
.width-c-60 {
width: 60rem !important; }
.width-c-70 {
width: 70rem !important; }
.status-heatmap-legend-wrapper { .status-heatmap-legend-wrapper {
margin: 0 10px; } margin: 0 10px; }
.status-heatmap-legend-wrapper svg { .status-heatmap-legend-wrapper svg {
+1 -1
View File
@@ -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,qBAAsB;EACpB,QAAQ,EAAE,QAAQ;EAGhB,sCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,sCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,yBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,8BAAK;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,8CAA8C;;AAI/D,yBAA0B;EACxB,IAAI,ECvDY,OAAO;;AD2DvB,8BAAK;EACH,MAAM,EAAE,OAAgB;EACxB,YAAY,EAAE,CAAC;;AAInB,yBAA0B;EACxB,YAAY,EAAE,CAAC;EACf,IAAI,EAAE,wBAAwB;EAC9B,MAAM,EAAE,wBAAwB;;AAIlC,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,EC7FG,OAAO;ID8Fd,KAAK,EC9FE,OAAO;ID+Fd,SAAS,EE/FE,IAAI;EFkGjB,+CAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,ECnGM,OAAO;EDsGrB,kDAAQ;IACN,OAAO,EAAE,GAAG;IACZ,MAAM,ECxGM,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,qBAAsB;EACpB,QAAQ,EAAE,QAAQ;EAGhB,sCAAK;IACH,IAAI,ECpBG,OAAO;IDqBd,KAAK,ECrBE,OAAO;IDsBd,SAAS,EEtBE,IAAI;EFyBjB,sCAAK;IACH,OAAO,EAAE,GAAG;IACZ,MAAM,EC1BM,OAAO;ED+BvB,yBAAI;IACF,cAAc,EAAE,IAAI;IAEpB,8BAAK;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",
"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"
+28
View File
@@ -0,0 +1,28 @@
"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
+1
View File
@@ -0,0 +1 @@
{"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"}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+112 -15
View File
@@ -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"], function (_export, _context) { 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) {
"use strict"; "use strict";
var _, kbn, loadPluginCss, MetricsPanelCtrl, Card, rendering, statusHeatmapOptionsEditor, ColorModeDiscrete, CANVAS, SVG, VALUE_INDEX, TIME_INDEX, renderer, colorSchemes, colorModes, opacityScales, StatusHeatmapCtrl; var _, kbn, loadPluginCss, MetricsPanelCtrl, Card, rendering, statusHeatmapOptionsEditor, ColorModeDiscrete, ExtraSeriesFormat, ExtraSeriesFormatValue, CANVAS, SVG, VALUE_INDEX, TIME_INDEX, renderer, 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); }
@@ -45,6 +45,9 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
statusHeatmapOptionsEditor = _options_editor.statusHeatmapOptionsEditor; 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 () {
CANVAS = 'CANVAS'; CANVAS = 'CANVAS';
@@ -150,12 +153,12 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
_export("PanelCtrl", _export("StatusHeatmapCtrl", StatusHeatmapCtrl = _export("PanelCtrl", _export("StatusHeatmapCtrl", StatusHeatmapCtrl =
/*#__PURE__*/ /*#__PURE__*/
function (_MetricsPanelCtrl) { function (_MetricsPanelCtrl) {
StatusHeatmapCtrl.$inject = ["$scope", "$injector", "annotationsSrv"]; StatusHeatmapCtrl.$inject = ["$scope", "$injector", "timeSrv", "annotationsSrv", "$window", "datasourceSrv", "variableSrv", "templateSrv"];
_inherits(StatusHeatmapCtrl, _MetricsPanelCtrl); _inherits(StatusHeatmapCtrl, _MetricsPanelCtrl);
/** @ngInject */ /** @ngInject */
function StatusHeatmapCtrl($scope, $injector, annotationsSrv) { function StatusHeatmapCtrl($scope, $injector, timeSrv, annotationsSrv, $window, datasourceSrv, variableSrv, templateSrv) {
var _this; var _this;
_classCallCheck(this, StatusHeatmapCtrl); _classCallCheck(this, StatusHeatmapCtrl);
@@ -181,10 +184,12 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
_defineProperty(_assertThisInitialized(_this), "noColorDefined", void 0); _defineProperty(_assertThisInitialized(_this), "noColorDefined", void 0);
_defineProperty(_assertThisInitialized(_this), "discreteHelper", void 0); _defineProperty(_assertThisInitialized(_this), "discreteExtraSeries", void 0);
_defineProperty(_assertThisInitialized(_this), "dataWarnings", void 0); _defineProperty(_assertThisInitialized(_this), "dataWarnings", 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);
@@ -236,21 +241,82 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
nullPointMode: 'as empty', nullPointMode: 'as empty',
yAxisSort: 'metrics', yAxisSort: 'metrics',
highlightCards: true, highlightCards: true,
useMax: true useMax: true,
urls: [{
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 () {
_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; // default graph width for discrete card width calculation _this.colorSchemes = colorSchemes;
_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
}; };
_this.multipleValues = false; _this.multipleValues = false;
_this.noColorDefined = false; _this.noColorDefined = false;
_this.discreteHelper = new ColorModeDiscrete($scope); _this.discreteExtraSeries = new ColorModeDiscrete($scope);
_this.dataWarnings = { _this.dataWarnings = {
"noColorDefined": { "noColorDefined": {
title: 'Data has value with undefined color', title: 'Data has value with undefined color',
@@ -262,6 +328,8 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
} }
}; };
_this.annotations = []; _this.annotations = [];
_this.annotationsSrv = annotationsSrv;
_this.timeSrv = timeSrv;
_this.events.on('render', _this.onRender.bind(_assertThisInitialized(_this))); _this.events.on('render', _this.onRender.bind(_assertThisInitialized(_this)));
@@ -278,6 +346,8 @@ 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)));
return _this; return _this;
} }
@@ -287,6 +357,23 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
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;
}
}
}, { }, {
key: "getChartWidth", key: "getChartWidth",
value: function getChartWidth() { value: function getChartWidth() {
@@ -310,7 +397,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
var intervalMs; var intervalMs;
var rangeMs = this.range.to.valueOf() - this.range.from.valueOf(); // this is minimal interval! kbn.round_interval will lower it. var rangeMs = this.range.to.valueOf() - this.range.from.valueOf(); // this is minimal interval! kbn.round_interval will lower it.
intervalMs = this.discreteHelper.roundIntervalCeil(rangeMs / maxCardsCount); // Calculate low limit of interval intervalMs = this.discreteExtraSeries.roundIntervalCeil(rangeMs / maxCardsCount); // Calculate low limit of interval
var lowLimitMs = 1; // 1 millisecond default low limit var lowLimitMs = 1; // 1 millisecond default low limit
@@ -385,7 +472,6 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
this.data = dataList; this.data = dataList;
this.cardsData = this.convertToCards(this.data); this.cardsData = this.convertToCards(this.data);
console.log("OnDataReceived");
this.annotationsPromise.then(function (result) { this.annotationsPromise.then(function (result) {
_this3.loading = false; //this.alertState = result.alertState; _this3.loading = false; //this.alertState = result.alertState;
@@ -395,13 +481,10 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
_this3.annotations = []; _this3.annotations = [];
} }
console.log("annotationsPromise result " + _this3.annotations.length + " annotations");
_this3.render(); _this3.render();
}, function () { }, function () {
_this3.loading = false; _this3.loading = false;
_this3.annotations = []; _this3.annotations = [];
console.log("annotationsPromise onrejected");
_this3.render(); _this3.render();
}); //this.render(); }); //this.render();
@@ -430,7 +513,11 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
this.noColorDefined = false; this.noColorDefined = false;
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
this.discreteHelper.updateCardsValuesHasColorInfo(); if (this.panel.seriesFilterIndex == -1) {
this.discreteExtraSeries.updateCardsValuesHasColorInfo();
} else {
this.discreteExtraSeries.updateCardsValuesHasColorInfoSingle();
}
if (this.cardsData) { if (this.cardsData) {
this.noColorDefined = this.cardsData.noColorDefined; this.noColorDefined = this.cardsData.noColorDefined;
@@ -546,6 +633,13 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
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);
}
}, {
key: "retrieveTimeVar",
value: function retrieveTimeVar() {
var time = this.timeSrv.timeRangeForUrl();
var var_time = '&from=' + time.from + '&to=' + time.to;
return var_time;
} // group values into buckets by target } // group values into buckets by target
}, { }, {
@@ -591,6 +685,9 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
var card = new Card(); var card = new Card();
card.id = i * cardsData.xBucketSize + j; card.id = i * cardsData.xBucketSize + j;
card.values = []; card.values = [];
card.columns = [];
card.multipleValues = false;
card.noColorDefined = false;
card.y = target; card.y = target;
card.x = -1; // collect values from all timeseries with target card.x = -1; // collect values from all timeseries with target
@@ -616,7 +713,7 @@ System.register(["lodash", "./color_legend", "app/core/utils/kbn", "app/plugins/
if (card.values.length > 1) { if (card.values.length > 1) {
cardsData.multipleValues = true; cardsData.multipleValues = true;
card.multipleValues = true; card.multipleValues = true;
card.value = card.maxValue; // max value by default card.value = this.panel.seriesFilterIndex != -1 ? card.values[this.panel.seriesFilterIndex] : card.maxValue;
} else { } else {
card.value = card.maxValue; // max value by default card.value = card.maxValue; // max value by default
} }
+1 -1
View File
File diff suppressed because one or more lines are too long
+97 -1
View File
@@ -194,9 +194,105 @@
</div> </div>
</div> </div>
<div class="section gf-form-group"> <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>
<div class="section gf-form-group"> <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> </div>
+32 -5
View File
@@ -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", "./annotations"], function (_export, _context) { System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/core", "d3", "./libs/d3-scale-chromatic/index", "./tooltip", "./tooltipextraseries", "./annotations"], function (_export, _context) {
"use strict"; "use strict";
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, StatusmapRenderer; 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, StatusmapRenderer;
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"); } }
@@ -66,6 +66,8 @@ 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;
}], }],
@@ -141,6 +143,8 @@ 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);
@@ -160,6 +164,7 @@ 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('.status-heatmap-panel'); this.$heatmap = this.elem.find('.status-heatmap-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 = {
@@ -191,6 +196,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
this.$heatmap.on('mousedown', this.onMouseDown.bind(this)); this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
this.$heatmap.on('mousemove', this.onMouseMove.bind(this)); this.$heatmap.on('mousemove', this.onMouseMove.bind(this));
this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this)); this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this));
this.$heatmap.on('click', this.onMouseClick.bind(this));
} }
_createClass(StatusmapRenderer, [{ _createClass(StatusmapRenderer, [{
@@ -588,7 +594,11 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
} else if (this.panel.color.mode === 'spectrum') { } else if (this.panel.color.mode === 'spectrum') {
return this.colorScale(d.value); return this.colorScale(d.value);
} else if (this.panel.color.mode === 'discrete') { } else if (this.panel.color.mode === 'discrete') {
return this.ctrl.discreteHelper.getBucketColor(d.values); if (this.panel.seriesFilterIndex != -1 || this.panel.seriesFilterIndex != null) {
return this.ctrl.discreteExtraSeries.getBucketColorSingle(d.values[this.panel.seriesFilterIndex]);
} else {
return this.ctrl.discreteExtraSeries.getBucketColor(d.values);
}
} }
} }
}, { }, {
@@ -663,9 +673,17 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
} }
}, { }, {
key: "onMouseLeave", key: "onMouseLeave",
value: function onMouseLeave() { value: function onMouseLeave(e) {
appEvents.emit('graph-hover-clear'); appEvents.emit('graph-hover-clear');
this.clearCrosshair(); //annotationTooltip.destroy(); this.clearCrosshair(); //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();
} }
}, { }, {
key: "onMouseMove", key: "onMouseMove",
@@ -692,6 +710,15 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
this.annotationTooltip.show(event); this.annotationTooltip.show(event);
} }
} }
}, {
key: "onMouseClick",
value: function onMouseClick(event) {
this.tooltipExtraSeries.show(event);
if (this.ctrl.panel.usingUrl) {
this.tooltip.destroy();
}
}
}, { }, {
key: "getEventPos", key: "getEventPos",
value: function getEventPos(event, offset) { value: function getEventPos(event, offset) {
@@ -832,7 +859,7 @@ System.register(["lodash", "jquery", "moment", "app/core/utils/kbn", "app/core/c
"id": i, "id": i,
"anno": d.source "anno": d.source
}; };
}); //console.log({"ctrl_annotations": this.ctrl.annotations, "annoData": annoData}); }); //({"ctrl_annotations": this.ctrl.annotations, "annoData": annoData});
var anno = this.heatmap.append("g").attr("class", "statusmap-annotations").attr("transform", "translate(0.5,0)").selectAll(".statusmap-annotations").data(annoData).enter().append("g"); var anno = this.heatmap.append("g").attr("class", "statusmap-annotations").attr("transform", "translate(0.5,0)").selectAll(".statusmap-annotations").data(annoData).enter().append("g");
+1 -1
View File
File diff suppressed because one or more lines are too long
+2
View File
@@ -27,6 +27,8 @@ System.register([], function (_export, _context) {
_defineProperty(this, "values", []); _defineProperty(this, "values", []);
_defineProperty(this, "columns", []);
_defineProperty(this, "multipleValues", false); _defineProperty(this, "multipleValues", false);
_defineProperty(this, "noColorDefined", false); _defineProperty(this, "noColorDefined", false);
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["../src/statusmap_data.ts"],"names":["Card","CardsStorage","maxValue","minValue"],"mappings":";;;;;;;;;;;;;;AAEA;sBACMA,I,GACF;AAEA;AAEA;AAEA;AAEA;AAEA;AAEA;AAKA,sBAAc;AAAA;;AAAA,oCAhBD,CAgBC;;AAAA,wCAdE,EAcF;;AAAA,gDAZY,KAYZ;;AAAA,gDAVY,KAUZ;;AAAA,mCARF,EAQE;;AAAA,mCANF,CAME;;AAAA,0CAJK,CAIL;;AAAA,0CAHK,CAGL;;AAAA,uCAFE,CAEF;AAEb,O;;8BAGCC,Y,GAWF,wBAAc;AAAA;;AAAA,uCAVE,EAUF;;AAAA,6CATQ,CASR;;AAAA,6CARQ,CAQR;;AAAA;;AAAA;;AAAA,gDALY,KAKZ;;AAAA,gDAJY,KAIZ;;AAAA,yCAHM,EAGN;;AAAA;;AACV,aAAKC,QAAL,GAAgB,CAAhB;AACA,aAAKC,QAAL,GAAgB,CAAhB;AAEH,O","sourcesContent":["\n\n// A holder of values\nclass Card {\n // uniq\n id: number = 0;\n // Array of values in this bucket\n values: any[] = [];\n // card has multiple values\n multipleValues: boolean = false;\n // card has values that has no color\n noColorDefined: boolean = false;\n //\n y: string = \"\";\n //\n x: number = 0;\n //\n minValue: number = 0;\n maxValue: number = 0;\n value: number = 0;\n \n constructor() {\n\n }\n }\n \nclass CardsStorage {\n cards: Card[] = [];\n xBucketSize: number = 0;\n yBucketSize: number = 0;\n maxValue: number;\n minValue: number;\n multipleValues: boolean = false;\n noColorDefined: boolean = false;\n targets: string[] = [];\n targetIndex: any;\n\n constructor() {\n this.maxValue = 0;\n this.minValue = 0;\n\n }\n }\n\nexport {CardsStorage, Card};"],"file":"statusmap_data.js"} {"version":3,"sources":["../src/statusmap_data.ts"],"names":["Card","CardsStorage","maxValue","minValue"],"mappings":";;;;;;;;;;;;;;AAEA;sBACMA,I,GACF;AAEA;AAGA;AAEA;AAEA;AAEA;AAEA;AAKA,sBAAc;AAAA;;AAAA,oCAjBD,CAiBC;;AAAA,wCAfE,EAeF;;AAAA,yCAdG,EAcH;;AAAA,gDAZY,KAYZ;;AAAA,gDAVY,KAUZ;;AAAA,mCARF,EAQE;;AAAA,mCANF,CAME;;AAAA,0CAJK,CAIL;;AAAA,0CAHK,CAGL;;AAAA,uCAFE,CAEF;AAEb,O;;8BAGCC,Y,GAWF,wBAAc;AAAA;;AAAA,uCAVE,EAUF;;AAAA,6CATQ,CASR;;AAAA,6CARQ,CAQR;;AAAA;;AAAA;;AAAA,gDALY,KAKZ;;AAAA,gDAJY,KAIZ;;AAAA,yCAHM,EAGN;;AAAA;;AACV,aAAKC,QAAL,GAAgB,CAAhB;AACA,aAAKC,QAAL,GAAgB,CAAhB;AAEH,O","sourcesContent":["\n\n// A holder of values\nclass Card {\n // uniq\n id: number = 0;\n // Array of values in this bucket\n values: any[] = [];\n columns: any[] = [];\n // card has multiple values\n multipleValues: boolean = false;\n // card has values that has no color\n noColorDefined: boolean = false;\n //\n y: string = \"\";\n //\n x: number = 0;\n //\n minValue: number = 0;\n maxValue: number = 0;\n value: number = 0;\n \n constructor() {\n\n }\n }\n \nclass CardsStorage {\n cards: Card[] = [];\n xBucketSize: number = 0;\n yBucketSize: number = 0;\n maxValue: number;\n minValue: number;\n multipleValues: boolean = false;\n noColorDefined: boolean = false;\n targets: string[] = [];\n targetIndex: any;\n\n constructor() {\n this.maxValue = 0;\n this.minValue = 0;\n\n }\n }\n\nexport {CardsStorage, Card};"],"file":"statusmap_data.js"}
+8 -2
View File
@@ -131,9 +131,15 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
var tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss'; var tooltipTimeFormat = 'YYYY-MM-DD HH:mm:ss';
var time = this.dashboard.formatDate(+x, tooltipTimeFormat); var time = this.dashboard.formatDate(+x, tooltipTimeFormat);
var tooltipHtml = "<div class=\"graph-tooltip-time\">".concat(time, "</div>\n <div class=\"statusmap-histogram\"></div>"); var tooltipHtml = "<div class=\"graph-tooltip-time\">".concat(time, "</div>\n <div class=\"statusmap-histogram\"></div>");
var statuses;
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
var statuses = this.panelCtrl.discreteHelper.convertValuesToTooltips(values); if (this.panel.seriesFilterIndex > 0) {
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
} else {
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
}
var statusesHtml = ''; var statusesHtml = '';
if (statuses.length === 1) { if (statuses.length === 1) {
@@ -163,7 +169,7 @@ System.register(["d3", "jquery", "lodash"], function (_export, _context) {
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
if (card.noColorDefined) { if (card.noColorDefined) {
var badValues = this.panelCtrl.discreteHelper.getNotColoredValues(values); 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) { 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>"); return "<li>".concat(v, "</li>");
}), ""), "\n </ul>\n </div>"); }), ""), "\n </ul>\n </div>");
+1 -1
View File
File diff suppressed because one or more lines are too long
+242
View File
@@ -0,0 +1,242 @@
"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
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -77,7 +77,7 @@ coreModule.directive('statusHeatmapLegend', function() {
drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue); drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue);
} else if (panel.color.mode === 'discrete') { } else if (panel.color.mode === 'discrete') {
let colorOptions = panel.color; let colorOptions = panel.color;
drawDiscreteColorLegend(elem, colorOptions, ctrl.discreteHelper); drawDiscreteColorLegend(elem, colorOptions, ctrl.discreteExtraSeries);
} }
} }
} }
@@ -148,7 +148,7 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue
drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth); drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth);
} }
function drawDiscreteColorLegend(elem, colorOptions, discreteHelper) { function drawDiscreteColorLegend(elem, colorOptions, discreteExtraSeries) {
let legendElem = $(elem).find('svg'); let legendElem = $(elem).find('svg');
let legend = d3.select(legendElem.get(0)); let legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
@@ -196,7 +196,7 @@ function drawDiscreteColorLegend(elem, colorOptions, discreteHelper) {
.attr("width", itemWidth + 1) // Overlap rectangles to prevent gaps .attr("width", itemWidth + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", d => discreteHelper.getDiscreteColor(d)); .attr("fill", d => discreteExtraSeries.getDiscreteColor(d));
drawDiscreteLegendValues(elem, colorOptions, legendWidth); drawDiscreteLegendValues(elem, colorOptions, legendWidth);
} }
+52 -1
View File
@@ -12,7 +12,7 @@ declare class DiscreteColorThreshold {
tooltip: string; tooltip: string;
} }
// Helper methods to handle discrete color mode // Extra Series methods to handle discrete color mode
export class ColorModeDiscrete { export class ColorModeDiscrete {
scope: any; scope: any;
panelCtrl: StatusHeatmapCtrl; panelCtrl: StatusHeatmapCtrl;
@@ -42,6 +42,23 @@ export class ColorModeDiscrete {
return tooltips; return tooltips;
} }
convertValueToTooltips(values) {
let thresholds = this.panel.color.thresholds;
let tooltips = [];
for (let i = 0; i < thresholds.length; i++) {
//for (let j = 0; j < values.length; j++) {
if (values == thresholds[i].value) {
tooltips.push({
"tooltip": thresholds[i].tooltip?thresholds[i].tooltip:values,
"color": thresholds[i].color
});
//}
}
}
return tooltips;
}
getNotMatchedValues(values:any[]) { getNotMatchedValues(values:any[]) {
let notMatched:any[] = []; let notMatched:any[] = [];
for (let j = 0; j < values.length; j++) { for (let j = 0; j < values.length; j++) {
@@ -71,6 +88,22 @@ export class ColorModeDiscrete {
return color; return color;
} }
getBucketColorSingle(value) {
//let thresholds = this.panel.color.thresholds;
if (value == null) {
// treat as null value
return 'rgba(0,0,0,1)';
//return this.getMatchedThreshold(null).color;
}
let threshold = this.getMatchedThreshold(value);
if (!threshold || !threshold.color || threshold.color == "") {
return 'rgba(0,0,0,1)';
} else {
return threshold.color;
}
}
// returns color from first matched thresold in order from 0 to thresholds.length // returns color from first matched thresold in order from 0 to thresholds.length
getBucketColor(values) { getBucketColor(values) {
let thresholds = this.panel.color.thresholds; let thresholds = this.panel.color.thresholds;
@@ -109,6 +142,24 @@ export class ColorModeDiscrete {
return 'rgba(0,0,0,1)'; return 'rgba(0,0,0,1)';
} }
updateCardsValuesHasColorInfoSingle() {
if (!this.panelCtrl.cardsData) {
return;
}
this.panelCtrl.cardsData.noColorDefined = false;
var cards = this.panelCtrl.cardsData.cards;
for (var i = 0; i < cards.length; i++) {
cards[i].noColorDefined = false;
var values = cards[i].value;
var threshold = this.getMatchedThreshold(values);
if (!threshold || !threshold.color || threshold.color == "") {
cards[i].noColorDefined = true;
this.panelCtrl.cardsData.noColorDefined = true;
}
}
}
updateCardsValuesHasColorInfo() { updateCardsValuesHasColorInfo() {
if (!this.panelCtrl.cardsData) { if (!this.panelCtrl.cardsData) {
return return
+29 -2
View File
@@ -47,10 +47,25 @@
color: $text-color; color: $text-color;
.discrete-item { .discrete-item {
color: #52545c; color: #ffffff;
padding: 1px; padding: 1px;
font-weight: bold; font-weight: bold;
text-shadow: 0 0 0.2em #FFF, 0 0 0.2em #FFF, 0 0 0.2em #FFF; text-shadow: 0 0 0.2em #212124, 0 0 0.2em #212124, 0 0 0.2em #212124;
}
}
.statusmap-tooltip-extraseries {
white-space: nowrap;
font-size: $font-size-sm;
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;
} }
} }
@@ -71,6 +86,18 @@
stroke: rgba(102, 102, 102, 0.8); stroke: rgba(102, 102, 102, 0.8);
} }
.width-c-40 {
width: 40.0rem!important
}
.width-c-50 {
width: 50.0rem!important
}
.width-c-60 {
width: 60.0rem!important
}
.width-c-70 {
width: 70.0rem!important
}
.status-heatmap-legend-wrapper { .status-heatmap-legend-wrapper {
margin: 0 10px; margin: 0 10px;
+9
View File
@@ -0,0 +1,9 @@
export enum ExtraSeriesFormat {
Date = 'Date',
Raw = 'Raw',
}
export enum ExtraSeriesFormatValue {
Date = 'YYYY/MM/DD/HH_mm_ss',
Raw = '',
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+94 -11
View File
@@ -19,6 +19,7 @@ import rendering from './rendering';
// import { labelFormats } from './xAxisLabelFormats'; // import { labelFormats } from './xAxisLabelFormats';
import {statusHeatmapOptionsEditor} from './options_editor'; 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 CANVAS = 'CANVAS'; const CANVAS = 'CANVAS';
const SVG = 'SVG'; const SVG = 'SVG';
@@ -93,8 +94,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
graph: any; graph: any;
multipleValues: boolean; multipleValues: boolean;
noColorDefined: boolean; noColorDefined: boolean;
discreteHelper: ColorModeDiscrete; discreteExtraSeries: ColorModeDiscrete;
dataWarnings: DataWarnings; dataWarnings: DataWarnings;
extraSeriesFormats: any = [];
annotations: object[] = []; annotations: object[] = [];
annotationsPromise: any; annotationsPromise: any;
@@ -145,11 +147,25 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
nullPointMode: 'as empty', nullPointMode: 'as empty',
yAxisSort: 'metrics', yAxisSort: 'metrics',
highlightCards: true, highlightCards: true,
useMax: true useMax: true,
urls: [{
tooltip: '',
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, private annotationsSrv: AnnotationsSrv) { constructor($scope: any, $injector: auto.IInjectorService, timeSrv, private annotationsSrv: AnnotationsSrv, $window, datasourceSrv, variableSrv, templateSrv) {
super($scope, $injector); super($scope, $injector);
_.defaultsDeep(this.panel, this.panelDefaults); _.defaultsDeep(this.panel, this.panelDefaults);
@@ -157,6 +173,20 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
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 = {
@@ -166,7 +196,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
this.multipleValues = false; this.multipleValues = false;
this.noColorDefined = false; this.noColorDefined = false;
this.discreteHelper = new ColorModeDiscrete($scope); this.discreteExtraSeries = new ColorModeDiscrete($scope);
this.dataWarnings = { this.dataWarnings = {
"noColorDefined": { "noColorDefined": {
@@ -180,6 +210,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
}; };
this.annotations = []; this.annotations = [];
this.annotationsSrv = annotationsSrv;
this.timeSrv = timeSrv;
this.events.on('render', this.onRender.bind(this)); this.events.on('render', this.onRender.bind(this));
this.events.on('data-received', this.onDataReceived.bind(this)); this.events.on('data-received', this.onDataReceived.bind(this));
@@ -189,6 +222,7 @@ 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));
} }
onRenderComplete(data):void { onRenderComplete(data):void {
@@ -196,6 +230,20 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
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():number { getChartWidth():number {
const wndWidth = $(window).width(); const wndWidth = $(window).width();
// gripPos.w is a width in grid's measurements. Grid size in Grafana is 24. // gripPos.w is a width in grid's measurements. Grid size in Grafana is 24.
@@ -222,7 +270,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
let rangeMs = this.range.to.valueOf() - this.range.from.valueOf(); let rangeMs = this.range.to.valueOf() - this.range.from.valueOf();
// this is minimal interval! kbn.round_interval will lower it. // this is minimal interval! kbn.round_interval will lower it.
intervalMs = this.discreteHelper.roundIntervalCeil(rangeMs / maxCardsCount); intervalMs = this.discreteExtraSeries.roundIntervalCeil(rangeMs / maxCardsCount);
// Calculate low limit of interval // Calculate low limit of interval
let lowLimitMs = 1; // 1 millisecond default low limit let lowLimitMs = 1; // 1 millisecond default low limit
@@ -292,8 +340,6 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
this.data = dataList; this.data = dataList;
this.cardsData = this.convertToCards(this.data); this.cardsData = this.convertToCards(this.data);
console.log("OnDataReceived");
this.annotationsPromise.then( this.annotationsPromise.then(
(result: { alertState: any; annotations: any }) => { (result: { alertState: any; annotations: any }) => {
this.loading = false; this.loading = false;
@@ -303,13 +349,11 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
} else { } else {
this.annotations = []; this.annotations = [];
} }
console.log("annotationsPromise result " + this.annotations.length + " annotations");
this.render(); this.render();
}, },
() => { () => {
this.loading = false; this.loading = false;
this.annotations = []; this.annotations = [];
console.log("annotationsPromise onrejected");
this.render(); this.render();
} }
); );
@@ -334,7 +378,11 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
this.noColorDefined = false; this.noColorDefined = false;
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
this.discreteHelper.updateCardsValuesHasColorInfo(); if (this.panel.seriesFilterIndex == -1) {
this.discreteExtraSeries.updateCardsValuesHasColorInfo();
} else {
this.discreteExtraSeries.updateCardsValuesHasColorInfoSingle();
}
if (this.cardsData) { if (this.cardsData) {
this.noColorDefined = this.cardsData.noColorDefined; this.noColorDefined = this.cardsData.noColorDefined;
} }
@@ -361,6 +409,26 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
this.render(); 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) { onEditorRemoveThreshold(index:number) {
this.panel.color.thresholds.splice(index, 1); this.panel.color.thresholds.splice(index, 1);
this.render(); this.render();
@@ -371,6 +439,12 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
this.render(); this.render();
} }
onEditorRemoveUrls = () => {
this.panel.urls = [];
this.render();
}
onEditorAddThreeLights() { onEditorAddThreeLights() {
this.panel.color.thresholds.push({color: "red", value: 2, tooltip: "error" }); 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: "yellow", value: 1, tooltip: "warning" });
@@ -395,6 +469,12 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
rendering(scope, elem, attrs, ctrl); rendering(scope, elem, attrs, ctrl);
} }
retrieveTimeVar() {
var time = this.timeSrv.timeRangeForUrl();
var var_time = '&from=' + time.from + '&to=' + time.to;
return var_time;
}
// group values into buckets by target // group values into buckets by target
convertToCards(data) { convertToCards(data) {
let cardsData = <CardsStorage> { let cardsData = <CardsStorage> {
@@ -433,6 +513,9 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
let card = new Card(); let card = new Card();
card.id = i*cardsData.xBucketSize + j; card.id = i*cardsData.xBucketSize + j;
card.values = []; card.values = [];
card.columns = [];
card.multipleValues = false;
card.noColorDefined = false;
card.y = target; card.y = target;
card.x = -1; card.x = -1;
@@ -453,7 +536,7 @@ class StatusHeatmapCtrl extends MetricsPanelCtrl {
if (card.values.length > 1) { if (card.values.length > 1) {
cardsData.multipleValues = true; cardsData.multipleValues = true;
card.multipleValues = true; card.multipleValues = true;
card.value = card.maxValue; // max value by default card.value = this.panel.seriesFilterIndex != -1 ? card.values[this.panel.seriesFilterIndex] : card.maxValue;
} else { } else {
card.value = card.maxValue; // max value by default card.value = card.maxValue; // max value by default
} }
+97 -1
View File
@@ -194,9 +194,105 @@
</div> </div>
</div> </div>
<div class="section gf-form-group"> <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>
<div class="section gf-form-group"> <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> </div>
+25 -3
View File
@@ -7,6 +7,7 @@ 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';
let MIN_CARD_SIZE = 5, let MIN_CARD_SIZE = 5,
@@ -50,6 +51,7 @@ 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;
@@ -64,6 +66,7 @@ export class StatusmapRenderer {
// $heatmap is JQuery object, but heatmap is D3 // $heatmap is JQuery object, but heatmap is D3
this.$heatmap = this.elem.find('.status-heatmap-panel'); this.$heatmap = this.elem.find('.status-heatmap-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;
@@ -94,6 +97,7 @@ export class StatusmapRenderer {
this.$heatmap.on('mousedown', this.onMouseDown.bind(this)); this.$heatmap.on('mousedown', this.onMouseDown.bind(this));
this.$heatmap.on('mousemove', this.onMouseMove.bind(this)); this.$heatmap.on('mousemove', this.onMouseMove.bind(this));
this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this)); this.$heatmap.on('mouseleave', this.onMouseLeave.bind(this));
this.$heatmap.on('click', this.onMouseClick.bind(this));
} }
onGraphHoverClear() { onGraphHoverClear() {
@@ -507,7 +511,11 @@ export class StatusmapRenderer {
} else if (this.panel.color.mode === 'spectrum') { } else if (this.panel.color.mode === 'spectrum') {
return this.colorScale(d.value); return this.colorScale(d.value);
} else if (this.panel.color.mode === 'discrete') { } else if (this.panel.color.mode === 'discrete') {
return this.ctrl.discreteHelper.getBucketColor(d.values); if (this.panel.seriesFilterIndex != -1 || this.panel.seriesFilterIndex != null) {
return this.ctrl.discreteExtraSeries.getBucketColorSingle(d.values[this.panel.seriesFilterIndex]);
} else {
return this.ctrl.discreteExtraSeries.getBucketColor(d.values);
}
} }
} }
@@ -572,10 +580,17 @@ export class StatusmapRenderer {
this.clearSelection(); this.clearSelection();
} }
onMouseLeave() { onMouseLeave(e) {
appEvents.emit('graph-hover-clear'); appEvents.emit('graph-hover-clear');
this.clearCrosshair(); this.clearCrosshair();
//annotationTooltip.destroy(); //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) {
@@ -599,6 +614,13 @@ export class StatusmapRenderer {
} }
} }
public onMouseClick(event) {
this.tooltipExtraSeries.show(event)
if (this.ctrl.panel.usingUrl) {
this.tooltip.destroy();
}
}
getEventPos(event, offset) { getEventPos(event, offset) {
const x = this.xScale.invert(offset.x - this.yAxisWidth).valueOf(); const x = this.xScale.invert(offset.x - this.yAxisWidth).valueOf();
const y = this.yScale.invert(offset.y - this.chartTop); const y = this.yScale.invert(offset.y - this.chartTop);
@@ -739,7 +761,7 @@ export class StatusmapRenderer {
let annoData = _.map(this.ctrl.annotations, (d,i) => ({"x": Math.floor(this.yAxisWidth + this.xScale(d.time)), "id":i, "anno": d.source})); let annoData = _.map(this.ctrl.annotations, (d,i) => ({"x": Math.floor(this.yAxisWidth + this.xScale(d.time)), "id":i, "anno": d.source}));
//console.log({"ctrl_annotations": this.ctrl.annotations, "annoData": annoData}); //({"ctrl_annotations": this.ctrl.annotations, "annoData": annoData});
let anno = this.heatmap let anno = this.heatmap
.append("g") .append("g")
+1
View File
@@ -6,6 +6,7 @@ class Card {
id: number = 0; id: number = 0;
// Array of values in this bucket // Array of values in this bucket
values: any[] = []; values: any[] = [];
columns: any[] = [];
// card has multiple values // card has multiple values
multipleValues: boolean = false; multipleValues: boolean = false;
// card has values that has no color // card has values that has no color
+9 -2
View File
@@ -89,8 +89,15 @@ export class StatusmapTooltip {
let tooltipHtml = `<div class="graph-tooltip-time">${time}</div> let tooltipHtml = `<div class="graph-tooltip-time">${time}</div>
<div class="statusmap-histogram"></div>`; <div class="statusmap-histogram"></div>`;
let statuses;
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
let statuses = this.panelCtrl.discreteHelper.convertValuesToTooltips(values); if (this.panel.seriesFilterIndex > 0) {
statuses = this.panelCtrl.discreteExtraSeries.convertValueToTooltips(value);
} else {
statuses = this.panelCtrl.discreteExtraSeries.convertValuesToTooltips(values);
}
let statusesHtml = ''; let statusesHtml = '';
if (statuses.length === 1) { if (statuses.length === 1) {
statusesHtml = "status:"; statusesHtml = "status:";
@@ -130,7 +137,7 @@ export class StatusmapTooltip {
// Discrete mode errors // Discrete mode errors
if (this.panel.color.mode === 'discrete') { if (this.panel.color.mode === 'discrete') {
if (card.noColorDefined) { if (card.noColorDefined) {
let badValues = this.panelCtrl.discreteHelper.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}
<br>not colored values: <br>not colored values:
<ul> <ul>
+222
View File
@@ -0,0 +1,222 @@
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");
}
}
+1 -1
View File
@@ -30,7 +30,7 @@
"noImplicitReturns": true, "noImplicitReturns": true,
"noImplicitThis": true, "noImplicitThis": true,
"noImplicitUseStrict": false, "noImplicitUseStrict": false,
"noImplicitAny": true, "noImplicitAny": false,
"noEmitOnError": false, "noEmitOnError": false,
"downlevelIteration": true, "downlevelIteration": true,
"noUnusedLocals": true, "noUnusedLocals": true,