Commit 467d7b5c3c5d9dce13b82e3c2da4dc15fcc0999f
Committed by
Igor Kulikov
1 parent
14c2d2e5
Flots comparison option (#2079)
* Add new hidden widget cards for latest and timeseries value * Revert "Add new hidden widget cards for latest and timeseries value" This reverts commit 09b73d5afcc66baf942a776f83a0295700f83d22. * Allow hiding of zero/false dataKey values from tbFlot widgets tooltips * comparison option draft * Added dataKey setting for excluding from Stacking mode in chart widgets. * Flot comparison option (draft) * Flot comparison option (draft) * Fix color generation for additional keys * Add new time options for comparison * Add ability to define points symbol and line width in 'line' flot charts * Change history timeinterval calculation, translations definition
Showing
9 changed files
with
617 additions
and
103 deletions
@@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
35 | "resources": [], | 35 | "resources": [], |
36 | "templateHtml": "", | 36 | "templateHtml": "", |
37 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 37 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
38 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 38 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
39 | "settingsSchema": "{}", | 39 | "settingsSchema": "{}", |
40 | "dataKeySettingsSchema": "{}", | 40 | "dataKeySettingsSchema": "{}", |
41 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":false,\"tooltipIndividual\":false},\"title\":\"Timeseries - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" | 41 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":false,\"tooltipIndividual\":false},\"title\":\"Timeseries - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" |
@@ -147,7 +147,7 @@ | @@ -147,7 +147,7 @@ | ||
147 | "resources": [], | 147 | "resources": [], |
148 | "templateHtml": "", | 148 | "templateHtml": "", |
149 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 149 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
150 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'bar'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('bar');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(false);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 150 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'bar'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('bar');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(false, 'bar');\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
151 | "settingsSchema": "{}", | 151 | "settingsSchema": "{}", |
152 | "dataKeySettingsSchema": "{}", | 152 | "dataKeySettingsSchema": "{}", |
153 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":true,\"tooltipIndividual\":false,\"defaultBarWidth\":600},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{}}" | 153 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":true,\"tooltipIndividual\":false,\"defaultBarWidth\":600},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{}}" |
@@ -163,7 +163,7 @@ | @@ -163,7 +163,7 @@ | ||
163 | "resources": [], | 163 | "resources": [], |
164 | "templateHtml": "", | 164 | "templateHtml": "", |
165 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", | 165 | "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", |
166 | - "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", | 166 | + "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema('graph');\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n", |
167 | "settingsSchema": "{}", | 167 | "settingsSchema": "{}", |
168 | "dataKeySettingsSchema": "{}", | 168 | "dataKeySettingsSchema": "{}", |
169 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" | 169 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" |
@@ -132,6 +132,13 @@ export default class Subscription { | @@ -132,6 +132,13 @@ export default class Subscription { | ||
132 | } | 132 | } |
133 | 133 | ||
134 | this.subscriptionTimewindow = null; | 134 | this.subscriptionTimewindow = null; |
135 | + this.comparisonEnabled = options.comparisonEnabled; | ||
136 | + if (this.comparisonEnabled) { | ||
137 | + this.timeForComparison = options.timeForComparison; | ||
138 | + | ||
139 | + this.comparisonTimeWindow = {}; | ||
140 | + this.timewindowForComparison = null; | ||
141 | + } | ||
135 | 142 | ||
136 | this.units = options.units || ''; | 143 | this.units = options.units || ''; |
137 | this.decimals = angular.isDefined(options.decimals) ? options.decimals : 2; | 144 | this.decimals = angular.isDefined(options.decimals) ? options.decimals : 2; |
@@ -311,13 +318,28 @@ export default class Subscription { | @@ -311,13 +318,28 @@ export default class Subscription { | ||
311 | } | 318 | } |
312 | 319 | ||
313 | configureData() { | 320 | configureData() { |
321 | + var additionalDatasources = []; | ||
314 | var dataIndex = 0; | 322 | var dataIndex = 0; |
323 | + var additionalKeysNumber = 0; | ||
315 | for (var i = 0; i < this.datasources.length; i++) { | 324 | for (var i = 0; i < this.datasources.length; i++) { |
316 | var datasource = this.datasources[i]; | 325 | var datasource = this.datasources[i]; |
326 | + var additionalDataKeys = []; | ||
327 | + let datasourceAdditionalKeysNumber = 0; | ||
328 | + | ||
317 | for (var a = 0; a < datasource.dataKeys.length; a++) { | 329 | for (var a = 0; a < datasource.dataKeys.length; a++) { |
318 | var dataKey = datasource.dataKeys[a]; | 330 | var dataKey = datasource.dataKeys[a]; |
319 | dataKey.hidden = false; | 331 | dataKey.hidden = false; |
320 | dataKey.pattern = angular.copy(dataKey.label); | 332 | dataKey.pattern = angular.copy(dataKey.label); |
333 | + | ||
334 | + if (this.comparisonEnabled && dataKey.settings.comparisonSettings && dataKey.settings.comparisonSettings.showValuesForComparison) { | ||
335 | + datasourceAdditionalKeysNumber++; | ||
336 | + additionalKeysNumber++; | ||
337 | + let additionalDataKey = this.ctx.utils.createAdditionalDataKey(dataKey,datasource, this.timeForComparison,this.datasources,additionalKeysNumber); | ||
338 | + dataKey.settings.comparisonSettings.color = additionalDataKey.color; | ||
339 | + | ||
340 | + additionalDataKeys.push(additionalDataKey); | ||
341 | + } | ||
342 | + | ||
321 | var datasourceData = { | 343 | var datasourceData = { |
322 | datasource: datasource, | 344 | datasource: datasource, |
323 | dataKey: dataKey, | 345 | dataKey: dataKey, |
@@ -341,8 +363,46 @@ export default class Subscription { | @@ -341,8 +363,46 @@ export default class Subscription { | ||
341 | this.legendData.data.push(legendKeyData); | 363 | this.legendData.data.push(legendKeyData); |
342 | } | 364 | } |
343 | } | 365 | } |
366 | + | ||
367 | + if (datasourceAdditionalKeysNumber > 0) { | ||
368 | + let additionalDatasource = angular.copy(datasource); | ||
369 | + additionalDatasource.dataKeys = additionalDataKeys; | ||
370 | + additionalDatasource.isAdditional = true; | ||
371 | + additionalDatasources.push(additionalDatasource); | ||
372 | + } | ||
373 | + } | ||
374 | + | ||
375 | + for (var j=0; j < additionalDatasources.length; j++) { | ||
376 | + let additionalDatasource = additionalDatasources[j]; | ||
377 | + for (var k=0; k < additionalDatasource.dataKeys.length; k++) { | ||
378 | + let additionalDataKey = additionalDatasource.dataKeys[k]; | ||
379 | + var additionalDatasourceData = { | ||
380 | + datasource: additionalDatasource, | ||
381 | + dataKey: additionalDataKey, | ||
382 | + data: [] | ||
383 | + }; | ||
384 | + this.data.push(additionalDatasourceData); | ||
385 | + this.hiddenData.push({data: []}); | ||
386 | + if (this.displayLegend) { | ||
387 | + var additionalLegendKey = { | ||
388 | + dataKey: additionalDataKey, | ||
389 | + dataIndex: dataIndex++ | ||
390 | + }; | ||
391 | + this.legendData.keys.push(additionalLegendKey); | ||
392 | + var additionalLegendKeyData = { | ||
393 | + min: null, | ||
394 | + max: null, | ||
395 | + avg: null, | ||
396 | + total: null, | ||
397 | + hidden: false | ||
398 | + }; | ||
399 | + this.legendData.data.push(additionalLegendKeyData); | ||
400 | + } | ||
401 | + } | ||
344 | } | 402 | } |
345 | 403 | ||
404 | + this.datasources = this.datasources.concat(additionalDatasources); | ||
405 | + | ||
346 | var subscription = this; | 406 | var subscription = this; |
347 | var registration; | 407 | var registration; |
348 | 408 | ||
@@ -638,7 +698,7 @@ export default class Subscription { | @@ -638,7 +698,7 @@ export default class Subscription { | ||
638 | updateTimewindow() { | 698 | updateTimewindow() { |
639 | this.timeWindow.interval = this.subscriptionTimewindow.aggregation.interval || 1000; | 699 | this.timeWindow.interval = this.subscriptionTimewindow.aggregation.interval || 1000; |
640 | if (this.subscriptionTimewindow.realtimeWindowMs) { | 700 | if (this.subscriptionTimewindow.realtimeWindowMs) { |
641 | - this.timeWindow.maxTime = (new Date).getTime() + this.timeWindow.stDiff; | 701 | + this.timeWindow.maxTime = (moment()).valueOf() + this.timeWindow.stDiff;//eslint-disable-line |
642 | this.timeWindow.minTime = this.timeWindow.maxTime - this.subscriptionTimewindow.realtimeWindowMs; | 702 | this.timeWindow.minTime = this.timeWindow.maxTime - this.subscriptionTimewindow.realtimeWindowMs; |
643 | } else if (this.subscriptionTimewindow.fixedWindow) { | 703 | } else if (this.subscriptionTimewindow.fixedWindow) { |
644 | this.timeWindow.maxTime = this.subscriptionTimewindow.fixedWindow.endTimeMs; | 704 | this.timeWindow.maxTime = this.subscriptionTimewindow.fixedWindow.endTimeMs; |
@@ -659,6 +719,26 @@ export default class Subscription { | @@ -659,6 +719,26 @@ export default class Subscription { | ||
659 | return this.subscriptionTimewindow; | 719 | return this.subscriptionTimewindow; |
660 | } | 720 | } |
661 | 721 | ||
722 | + updateComparisonTimewindow() { | ||
723 | + this.comparisonTimeWindow.interval = this.timewindowForComparison.aggregation.interval || 1000; | ||
724 | + if (this.timewindowForComparison.realtimeWindowMs) { | ||
725 | + this.comparisonTimeWindow.maxTime = moment(this.timeWindow.maxTime).subtract(1, this.timeForComparison).valueOf(); //eslint-disable-line | ||
726 | + this.comparisonTimeWindow.minTime = this.comparisonTimeWindow.maxTime - this.timewindowForComparison.realtimeWindowMs; | ||
727 | + } else if (this.timewindowForComparison.fixedWindow) { | ||
728 | + this.comparisonTimeWindow.maxTime = this.timewindowForComparison.fixedWindow.endTimeMs; | ||
729 | + this.comparisonTimeWindow.minTime = this.timewindowForComparison.fixedWindow.startTimeMs; | ||
730 | + } | ||
731 | + } | ||
732 | + | ||
733 | + updateSubscriptionForComparison() { | ||
734 | + if (!this.subscriptionTimewindow) { | ||
735 | + this.subscriptionTimewindow = this.updateRealtimeSubscription(); | ||
736 | + } | ||
737 | + this.timewindowForComparison = this.ctx.timeService.createTimewindowForComparison(this.subscriptionTimewindow, this.timeForComparison); | ||
738 | + this.updateComparisonTimewindow(); | ||
739 | + return this.timewindowForComparison; | ||
740 | + } | ||
741 | + | ||
662 | dataUpdated(sourceData, datasourceIndex, dataKeyIndex, apply) { | 742 | dataUpdated(sourceData, datasourceIndex, dataKeyIndex, apply) { |
663 | for (var x = 0; x < this.datasourceListeners.length; x++) { | 743 | for (var x = 0; x < this.datasourceListeners.length; x++) { |
664 | this.datasources[x].dataReceived = this.datasources[x].dataReceived === true; | 744 | this.datasources[x].dataReceived = this.datasources[x].dataReceived === true; |
@@ -689,6 +769,9 @@ export default class Subscription { | @@ -689,6 +769,9 @@ export default class Subscription { | ||
689 | if (update) { | 769 | if (update) { |
690 | if (this.subscriptionTimewindow && this.subscriptionTimewindow.realtimeWindowMs) { | 770 | if (this.subscriptionTimewindow && this.subscriptionTimewindow.realtimeWindowMs) { |
691 | this.updateTimewindow(); | 771 | this.updateTimewindow(); |
772 | + if (this.timewindowForComparison && this.timewindowForComparison.realtimeWindowMs) { | ||
773 | + this.updateComparisonTimewindow(); | ||
774 | + } | ||
692 | } | 775 | } |
693 | currentData.data = sourceData.data; | 776 | currentData.data = sourceData.data; |
694 | if (this.caulculateLegendData) { | 777 | if (this.caulculateLegendData) { |
@@ -745,6 +828,9 @@ export default class Subscription { | @@ -745,6 +828,9 @@ export default class Subscription { | ||
745 | this.notifyDataLoading(); | 828 | this.notifyDataLoading(); |
746 | if (this.type === this.ctx.types.widgetType.timeseries.value && this.timeWindowConfig) { | 829 | if (this.type === this.ctx.types.widgetType.timeseries.value && this.timeWindowConfig) { |
747 | this.updateRealtimeSubscription(); | 830 | this.updateRealtimeSubscription(); |
831 | + if (this.comparisonEnabled) { | ||
832 | + this.updateSubscriptionForComparison(); | ||
833 | + } | ||
748 | if (this.subscriptionTimewindow.fixedWindow) { | 834 | if (this.subscriptionTimewindow.fixedWindow) { |
749 | this.onDataUpdated(); | 835 | this.onDataUpdated(); |
750 | } | 836 | } |
@@ -776,6 +862,17 @@ export default class Subscription { | @@ -776,6 +862,17 @@ export default class Subscription { | ||
776 | datasourceIndex: index | 862 | datasourceIndex: index |
777 | }; | 863 | }; |
778 | 864 | ||
865 | + if (this.comparisonEnabled && datasource.isAdditional) { | ||
866 | + listener.subscriptionTimewindow = this.timewindowForComparison; | ||
867 | + listener.updateRealtimeSubscription = function () { | ||
868 | + this.subscriptionTimewindow = subscription.updateSubscriptionForComparison(); | ||
869 | + return this.subscriptionTimewindow; | ||
870 | + }; | ||
871 | + listener.setRealtimeSubscription = function () { | ||
872 | + subscription.updateSubscriptionForComparison(); | ||
873 | + }; | ||
874 | + } | ||
875 | + | ||
779 | for (var a = 0; a < datasource.dataKeys.length; a++) { | 876 | for (var a = 0; a < datasource.dataKeys.length; a++) { |
780 | this.data[index + a].data = []; | 877 | this.data[index + a].data = []; |
781 | } | 878 | } |
@@ -908,7 +1005,6 @@ export default class Subscription { | @@ -908,7 +1005,6 @@ export default class Subscription { | ||
908 | }); | 1005 | }); |
909 | this.registrations = []; | 1006 | this.registrations = []; |
910 | } | 1007 | } |
911 | - | ||
912 | } | 1008 | } |
913 | 1009 | ||
914 | function calculateMin(data) { | 1010 | function calculateMin(data) { |
@@ -47,6 +47,7 @@ function TimeService($translate, $http, $q, types) { | @@ -47,6 +47,7 @@ function TimeService($translate, $http, $q, types) { | ||
47 | defaultTimewindow: defaultTimewindow, | 47 | defaultTimewindow: defaultTimewindow, |
48 | toHistoryTimewindow: toHistoryTimewindow, | 48 | toHistoryTimewindow: toHistoryTimewindow, |
49 | createSubscriptionTimewindow: createSubscriptionTimewindow, | 49 | createSubscriptionTimewindow: createSubscriptionTimewindow, |
50 | + createTimewindowForComparison: createTimewindowForComparison, | ||
50 | getMaxDatapointsLimit: function () { | 51 | getMaxDatapointsLimit: function () { |
51 | return maxDatapointsLimit; | 52 | return maxDatapointsLimit; |
52 | }, | 53 | }, |
@@ -383,5 +384,27 @@ function TimeService($translate, $http, $q, types) { | @@ -383,5 +384,27 @@ function TimeService($translate, $http, $q, types) { | ||
383 | } | 384 | } |
384 | } | 385 | } |
385 | 386 | ||
387 | + function createTimewindowForComparison(subscriptionTimewindow, timeUnit) { | ||
388 | + var timewindowForComparison = { | ||
389 | + fixedWindow: null, | ||
390 | + realtimeWindowMs: null, | ||
391 | + aggregation: subscriptionTimewindow.aggregation | ||
392 | + }; | ||
393 | + | ||
394 | + if (subscriptionTimewindow.realtimeWindowMs) { | ||
395 | + timewindowForComparison.startTs = moment(subscriptionTimewindow.startTs).subtract(1, timeUnit).valueOf(); //eslint-disable-line | ||
396 | + timewindowForComparison.realtimeWindowMs = subscriptionTimewindow.realtimeWindowMs; | ||
397 | + } else if (subscriptionTimewindow.fixedWindow) { | ||
398 | + var timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs; | ||
399 | + var endTimeMs = moment(subscriptionTimewindow.fixedWindow.endTimeMs).subtract(1, timeUnit).valueOf(); //eslint-disable-line | ||
386 | 400 | ||
401 | + timewindowForComparison.startTs = endTimeMs - timeInterval; | ||
402 | + timewindowForComparison.fixedWindow = { | ||
403 | + startTimeMs: timewindowForComparison.startTs, | ||
404 | + endTimeMs: endTimeMs | ||
405 | + }; | ||
406 | + } | ||
407 | + | ||
408 | + return timewindowForComparison; | ||
409 | + } | ||
387 | } | 410 | } |
@@ -144,6 +144,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -144,6 +144,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
144 | isLocalUrl: isLocalUrl, | 144 | isLocalUrl: isLocalUrl, |
145 | validateDatasources: validateDatasources, | 145 | validateDatasources: validateDatasources, |
146 | createKey: createKey, | 146 | createKey: createKey, |
147 | + createAdditionalDataKey: createAdditionalDataKey, | ||
147 | createLabelFromDatasource: createLabelFromDatasource, | 148 | createLabelFromDatasource: createLabelFromDatasource, |
148 | insertVariable: insertVariable, | 149 | insertVariable: insertVariable, |
149 | customTranslation: customTranslation, | 150 | customTranslation: customTranslation, |
@@ -411,8 +412,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -411,8 +412,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
411 | return copy; | 412 | return copy; |
412 | } | 413 | } |
413 | 414 | ||
414 | - function genNextColor(datasources) { | ||
415 | - var index = 0; | 415 | + function genNextColor(datasources, initialIndex) { |
416 | + var index = initialIndex || 0; | ||
416 | if (datasources) { | 417 | if (datasources) { |
417 | for (var i = 0; i < datasources.length; i++) { | 418 | for (var i = 0; i < datasources.length; i++) { |
418 | var datasource = datasources[i]; | 419 | var datasource = datasources[i]; |
@@ -491,6 +492,23 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | @@ -491,6 +492,23 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t | ||
491 | return dataKey; | 492 | return dataKey; |
492 | } | 493 | } |
493 | 494 | ||
495 | + function createAdditionalDataKey(dataKey, datasource, timeUnit, datasources, additionalKeysNumber) { | ||
496 | + let additionalDataKey = angular.copy(dataKey); | ||
497 | + if (dataKey.settings.comparisonSettings.comparisonValuesLabel) { | ||
498 | + additionalDataKey.label = createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel); | ||
499 | + } else { | ||
500 | + additionalDataKey.label = dataKey.label + ' ' + $translate.instant('legend.comparison-time-ago.'+timeUnit); | ||
501 | + } | ||
502 | + additionalDataKey.pattern = additionalDataKey.label; | ||
503 | + if (dataKey.settings.comparisonSettings.color) { | ||
504 | + additionalDataKey.color = dataKey.settings.comparisonSettings.color; | ||
505 | + } else { | ||
506 | + additionalDataKey.color = genNextColor(datasources, additionalKeysNumber); | ||
507 | + } | ||
508 | + additionalDataKey._hash = Math.random(); | ||
509 | + return additionalDataKey; | ||
510 | + } | ||
511 | + | ||
494 | function createLabelFromDatasource(datasource, pattern) { | 512 | function createLabelFromDatasource(datasource, pattern) { |
495 | var label = angular.copy(pattern); | 513 | var label = angular.copy(pattern); |
496 | var match = varsRegex.exec(pattern); | 514 | var match = varsRegex.exec(pattern); |
@@ -357,8 +357,10 @@ export default function WidgetController($scope, $state, $timeout, $window, $ocL | @@ -357,8 +357,10 @@ export default function WidgetController($scope, $state, $timeout, $window, $ocL | ||
357 | if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) { | 357 | if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) { |
358 | options = { | 358 | options = { |
359 | type: widget.type, | 359 | type: widget.type, |
360 | - stateData: vm.typeParameters.stateData | ||
361 | - } | 360 | + stateData: vm.typeParameters.stateData, |
361 | + comparisonEnabled: widgetContext.settings.comparisonEnabled, | ||
362 | + timeForComparison: widgetContext.settings.timeForComparison | ||
363 | + }; | ||
362 | if (widget.type == types.widgetType.alarm.value) { | 364 | if (widget.type == types.widgetType.alarm.value) { |
363 | options.alarmSource = angular.copy(widget.config.alarmSource); | 365 | options.alarmSource = angular.copy(widget.config.alarmSource); |
364 | options.alarmSearchStatus = angular.isDefined(widget.config.alarmSearchStatus) ? | 366 | options.alarmSearchStatus = angular.isDefined(widget.config.alarmSearchStatus) ? |
@@ -1195,7 +1195,13 @@ | @@ -1195,7 +1195,13 @@ | ||
1195 | "min": "min", | 1195 | "min": "min", |
1196 | "max": "max", | 1196 | "max": "max", |
1197 | "avg": "avg", | 1197 | "avg": "avg", |
1198 | - "total": "total" | 1198 | + "total": "total", |
1199 | + "comparison-time-ago": { | ||
1200 | + "days": "(day ago)", | ||
1201 | + "weeks": "(week ago)", | ||
1202 | + "months": "(month ago)", | ||
1203 | + "years": "(year ago)" | ||
1204 | + } | ||
1199 | }, | 1205 | }, |
1200 | "login": { | 1206 | "login": { |
1201 | "login": "Login", | 1207 | "login": "Login", |
@@ -1169,7 +1169,13 @@ | @@ -1169,7 +1169,13 @@ | ||
1169 | "min": "Мин", | 1169 | "min": "Мин", |
1170 | "max": "Макс", | 1170 | "max": "Макс", |
1171 | "avg": "Среднее", | 1171 | "avg": "Среднее", |
1172 | - "total": "Сумма" | 1172 | + "total": "Сумма", |
1173 | + "comparison-time-ago": { | ||
1174 | + "days": "(день назад)", | ||
1175 | + "weeks": "(неделю назад)", | ||
1176 | + "months": "(месяц назад)", | ||
1177 | + "years": "(год назад)" | ||
1178 | + } | ||
1173 | }, | 1179 | }, |
1174 | "login": { | 1180 | "login": { |
1175 | "login": "Войти", | 1181 | "login": "Войти", |
@@ -1584,7 +1584,13 @@ | @@ -1584,7 +1584,13 @@ | ||
1584 | "min": "мін", | 1584 | "min": "мін", |
1585 | "max": "макс", | 1585 | "max": "макс", |
1586 | "avg": "середнє", | 1586 | "avg": "середнє", |
1587 | - "total": "Сума" | 1587 | + "total": "Сума", |
1588 | + "comparison-time-ago": { | ||
1589 | + "days": "(день тому)", | ||
1590 | + "weeks": "(тиждень тому)", | ||
1591 | + "months": "(місяць тому)", | ||
1592 | + "years": "(рік тому)" | ||
1593 | + } | ||
1588 | }, | 1594 | }, |
1589 | "login": { | 1595 | "login": { |
1590 | "login": "Вхід", | 1596 | "login": "Вхід", |
@@ -23,6 +23,7 @@ import 'flot/src/plugins/jquery.flot.selection'; | @@ -23,6 +23,7 @@ import 'flot/src/plugins/jquery.flot.selection'; | ||
23 | import 'flot/src/plugins/jquery.flot.pie'; | 23 | import 'flot/src/plugins/jquery.flot.pie'; |
24 | import 'flot/src/plugins/jquery.flot.crosshair'; | 24 | import 'flot/src/plugins/jquery.flot.crosshair'; |
25 | import 'flot/src/plugins/jquery.flot.stack'; | 25 | import 'flot/src/plugins/jquery.flot.stack'; |
26 | +import 'flot/src/plugins/jquery.flot.symbol'; | ||
26 | import 'flot.curvedlines/curvedLines'; | 27 | import 'flot.curvedlines/curvedLines'; |
27 | 28 | ||
28 | /* eslint-disable angular/angularelement */ | 29 | /* eslint-disable angular/angularelement */ |
@@ -32,6 +33,7 @@ export default class TbFlot { | @@ -32,6 +33,7 @@ export default class TbFlot { | ||
32 | this.ctx = ctx; | 33 | this.ctx = ctx; |
33 | this.chartType = chartType || 'line'; | 34 | this.chartType = chartType || 'line'; |
34 | var settings = ctx.settings; | 35 | var settings = ctx.settings; |
36 | + var utils = this.ctx.$scope.$injector.get('utils'); | ||
35 | 37 | ||
36 | ctx.tooltip = $('#flot-series-tooltip'); | 38 | ctx.tooltip = $('#flot-series-tooltip'); |
37 | if (ctx.tooltip.length === 0) { | 39 | if (ctx.tooltip.length === 0) { |
@@ -59,7 +61,7 @@ export default class TbFlot { | @@ -59,7 +61,7 @@ export default class TbFlot { | ||
59 | divElement.css({ | 61 | divElement.css({ |
60 | display: "flex", | 62 | display: "flex", |
61 | alignItems: "center", | 63 | alignItems: "center", |
62 | - justifyContent: "flex-start" | 64 | + justifyContent: "space-between" |
63 | }); | 65 | }); |
64 | var lineSpan = $('<span></span>'); | 66 | var lineSpan = $('<span></span>'); |
65 | lineSpan.css({ | 67 | lineSpan.css({ |
@@ -125,55 +127,99 @@ export default class TbFlot { | @@ -125,55 +127,99 @@ export default class TbFlot { | ||
125 | } else { | 127 | } else { |
126 | ctx.tooltipFormatter = function(hoverInfo, seriesIndex) { | 128 | ctx.tooltipFormatter = function(hoverInfo, seriesIndex) { |
127 | var content = ''; | 129 | var content = ''; |
128 | - var timestamp = parseInt(hoverInfo.time); | ||
129 | - var date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss'); | ||
130 | - var dateDiv = $('<div>' + date + '</div>'); | ||
131 | - dateDiv.css({ | ||
132 | - display: "flex", | ||
133 | - alignItems: "center", | ||
134 | - justifyContent: "center", | ||
135 | - padding: "4px", | ||
136 | - fontWeight: "700" | ||
137 | - }); | ||
138 | - content += dateDiv.prop('outerHTML'); | 130 | + |
139 | if (tbFlot.ctx.tooltipIndividual) { | 131 | if (tbFlot.ctx.tooltipIndividual) { |
140 | - var found = hoverInfo.seriesHover.filter((seriesHover) => { | 132 | + var seriesHoverArray; |
133 | + if (hoverInfo[1] && hoverInfo[1].seriesHover.length) { | ||
134 | + seriesHoverArray = hoverInfo[0].seriesHover.concat(hoverInfo[1].seriesHover); | ||
135 | + } else { | ||
136 | + seriesHoverArray = hoverInfo[0].seriesHover; | ||
137 | + } | ||
138 | + var found = seriesHoverArray.filter((seriesHover) => { | ||
141 | return seriesHover.index === seriesIndex; | 139 | return seriesHover.index === seriesIndex; |
142 | }); | 140 | }); |
143 | if (found && found.length) { | 141 | if (found && found.length) { |
142 | + let timestamp; | ||
143 | + if (!angular.isNumber(hoverInfo[0].time) || (found[0].time < hoverInfo[0].time)) { | ||
144 | + timestamp = parseInt(hoverInfo[1].time); | ||
145 | + } else { | ||
146 | + timestamp = parseInt(hoverInfo[0].time); | ||
147 | + } | ||
148 | + let date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss'); | ||
149 | + let dateDiv = $('<div>' + date + '</div>'); | ||
150 | + dateDiv.css({ | ||
151 | + display: "flex", | ||
152 | + alignItems: "center", | ||
153 | + justifyContent: "center", | ||
154 | + padding: "4px", | ||
155 | + fontWeight: "700" | ||
156 | + }); | ||
157 | + content += dateDiv.prop('outerHTML'); | ||
144 | content += seriesInfoDivFromInfo(found[0], seriesIndex); | 158 | content += seriesInfoDivFromInfo(found[0], seriesIndex); |
145 | } | 159 | } |
146 | } else { | 160 | } else { |
147 | - var seriesDiv = $('<div></div>'); | ||
148 | - seriesDiv.css({ | ||
149 | - display: "flex", | ||
150 | - flexDirection: "row" | ||
151 | - }); | ||
152 | - const maxRows = 15; | ||
153 | - var columns = Math.ceil(hoverInfo.seriesHover.length / maxRows); | ||
154 | - var columnsContent = ''; | ||
155 | - for (var c = 0; c < columns; c++) { | ||
156 | - var columnDiv = $('<div></div>'); | ||
157 | - columnDiv.css({ | ||
158 | - display: "flex", | ||
159 | - flexDirection: "column" | ||
160 | - }); | ||
161 | - var columnContent = ''; | ||
162 | - for (var i = c*maxRows; i < (c+1)*maxRows; i++) { | ||
163 | - if (i == hoverInfo.seriesHover.length) { | ||
164 | - break; | 161 | + var maxRows; |
162 | + if (hoverInfo[1] && hoverInfo[1].seriesHover.length) { | ||
163 | + maxRows = 5; | ||
164 | + } else { | ||
165 | + maxRows = 15; | ||
166 | + } | ||
167 | + var columns = 0; | ||
168 | + if (hoverInfo[1] && (hoverInfo[1].seriesHover.length > hoverInfo[0].seriesHover.length)) { | ||
169 | + columns = Math.ceil(hoverInfo[1].seriesHover.length / maxRows); | ||
170 | + } else { | ||
171 | + columns = Math.ceil(hoverInfo[0].seriesHover.length / maxRows); | ||
172 | + } | ||
173 | + | ||
174 | + for (var j = 0; j < hoverInfo.length; j++) { | ||
175 | + var hoverData = hoverInfo[j]; | ||
176 | + if (angular.isNumber(hoverData.time)) { | ||
177 | + var columnsContent = ''; | ||
178 | + let timestamp = parseInt(hoverData.time); | ||
179 | + let date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss'); | ||
180 | + let dateDiv = $('<div>' + date + '</div>'); | ||
181 | + dateDiv.css({ | ||
182 | + display: "flex", | ||
183 | + alignItems: "center", | ||
184 | + justifyContent: "center", | ||
185 | + padding: "4px", | ||
186 | + fontWeight: "700" | ||
187 | + }); | ||
188 | + content += dateDiv.prop('outerHTML'); | ||
189 | + | ||
190 | + var seriesDiv = $('<div></div>'); | ||
191 | + seriesDiv.css({ | ||
192 | + display: "flex", | ||
193 | + flexDirection: "row" | ||
194 | + }); | ||
195 | + for (var c = 0; c < columns; c++) { | ||
196 | + var columnDiv = $('<div></div>'); | ||
197 | + columnDiv.css({ | ||
198 | + display: "flex", | ||
199 | + flexDirection: "column", | ||
200 | + flex: "1" | ||
201 | + }); | ||
202 | + var columnContent = ''; | ||
203 | + for (var i = c*maxRows; i < (c+1)*maxRows; i++) { | ||
204 | + if (i >= hoverData.seriesHover.length) { | ||
205 | + break; | ||
206 | + } | ||
207 | + var seriesHoverInfo = hoverData.seriesHover[i]; | ||
208 | + columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex); | ||
209 | + } | ||
210 | + columnDiv.html(columnContent); | ||
211 | + | ||
212 | + if (columnContent) { | ||
213 | + if (c > 0) { | ||
214 | + columnsContent += '<span style="min-width: 20px;"></span>'; | ||
215 | + } | ||
216 | + columnsContent += columnDiv.prop('outerHTML'); | ||
217 | + } | ||
165 | } | 218 | } |
166 | - var seriesHoverInfo = hoverInfo.seriesHover[i]; | ||
167 | - columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex); | ||
168 | - } | ||
169 | - columnDiv.html(columnContent); | ||
170 | - if (c > 0) { | ||
171 | - columnsContent += '<span style="width: 20px;"></span>'; | 219 | + seriesDiv.html(columnsContent); |
220 | + content += seriesDiv.prop('outerHTML'); | ||
172 | } | 221 | } |
173 | - columnsContent += columnDiv.prop('outerHTML'); | ||
174 | } | 222 | } |
175 | - seriesDiv.html(columnsContent); | ||
176 | - content += seriesDiv.prop('outerHTML'); | ||
177 | } | 223 | } |
178 | return content; | 224 | return content; |
179 | }; | 225 | }; |
@@ -185,6 +231,7 @@ export default class TbFlot { | @@ -185,6 +231,7 @@ export default class TbFlot { | ||
185 | 231 | ||
186 | ctx.tooltipIndividual = this.chartType === 'pie' || (angular.isDefined(settings.tooltipIndividual) ? settings.tooltipIndividual : false); | 232 | ctx.tooltipIndividual = this.chartType === 'pie' || (angular.isDefined(settings.tooltipIndividual) ? settings.tooltipIndividual : false); |
187 | ctx.tooltipCumulative = angular.isDefined(settings.tooltipCumulative) ? settings.tooltipCumulative : false; | 233 | ctx.tooltipCumulative = angular.isDefined(settings.tooltipCumulative) ? settings.tooltipCumulative : false; |
234 | + ctx.hideZeros = angular.isDefined(settings.hideZeros) ? settings.hideZeros : false; | ||
188 | 235 | ||
189 | var font = { | 236 | var font = { |
190 | color: settings.fontColor || "#545454", | 237 | color: settings.fontColor || "#545454", |
@@ -209,7 +256,8 @@ export default class TbFlot { | @@ -209,7 +256,8 @@ export default class TbFlot { | ||
209 | }; | 256 | }; |
210 | 257 | ||
211 | if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') { | 258 | if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') { |
212 | - options.xaxis = { | 259 | + options.xaxes = []; |
260 | + this.xaxis = { | ||
213 | mode: 'time', | 261 | mode: 'time', |
214 | timezone: 'browser', | 262 | timezone: 'browser', |
215 | font: angular.copy(font), | 263 | font: angular.copy(font), |
@@ -220,16 +268,11 @@ export default class TbFlot { | @@ -220,16 +268,11 @@ export default class TbFlot { | ||
220 | labelFont: angular.copy(font) | 268 | labelFont: angular.copy(font) |
221 | }; | 269 | }; |
222 | if (settings.xaxis) { | 270 | if (settings.xaxis) { |
223 | - if (settings.xaxis.showLabels === false) { | ||
224 | - options.xaxis.tickFormatter = function() { | ||
225 | - return ''; | ||
226 | - }; | ||
227 | - } | ||
228 | - options.xaxis.font.color = settings.xaxis.color || options.xaxis.font.color; | ||
229 | - options.xaxis.label = settings.xaxis.title || null; | ||
230 | - options.xaxis.labelFont.color = options.xaxis.font.color; | ||
231 | - options.xaxis.labelFont.size = options.xaxis.font.size+2; | ||
232 | - options.xaxis.labelFont.weight = "bold"; | 271 | + this.xaxis.font.color = settings.xaxis.color || this.xaxis.font.color; |
272 | + this.xaxis.label = utils.customTranslation(settings.xaxis.title, settings.xaxis.title) || null; | ||
273 | + this.xaxis.labelFont.color = this.xaxis.font.color; | ||
274 | + this.xaxis.labelFont.size = this.xaxis.font.size+2; | ||
275 | + this.xaxis.labelFont.weight = "bold"; | ||
233 | } | 276 | } |
234 | 277 | ||
235 | ctx.yAxisTickFormatter = function(value/*, axis*/) { | 278 | ctx.yAxisTickFormatter = function(value/*, axis*/) { |
@@ -263,7 +306,7 @@ export default class TbFlot { | @@ -263,7 +306,7 @@ export default class TbFlot { | ||
263 | this.yaxis.font.color = settings.yaxis.color || this.yaxis.font.color; | 306 | this.yaxis.font.color = settings.yaxis.color || this.yaxis.font.color; |
264 | this.yaxis.min = angular.isDefined(settings.yaxis.min) ? settings.yaxis.min : null; | 307 | this.yaxis.min = angular.isDefined(settings.yaxis.min) ? settings.yaxis.min : null; |
265 | this.yaxis.max = angular.isDefined(settings.yaxis.max) ? settings.yaxis.max : null; | 308 | this.yaxis.max = angular.isDefined(settings.yaxis.max) ? settings.yaxis.max : null; |
266 | - this.yaxis.label = settings.yaxis.title || null; | 309 | + this.yaxis.label = utils.customTranslation(settings.yaxis.title, settings.yaxis.title) || null; |
267 | this.yaxis.labelFont.color = this.yaxis.font.color; | 310 | this.yaxis.labelFont.color = this.yaxis.font.color; |
268 | this.yaxis.labelFont.size = this.yaxis.font.size+2; | 311 | this.yaxis.labelFont.size = this.yaxis.font.size+2; |
269 | this.yaxis.labelFont.weight = "bold"; | 312 | this.yaxis.labelFont.weight = "bold"; |
@@ -296,7 +339,7 @@ export default class TbFlot { | @@ -296,7 +339,7 @@ export default class TbFlot { | ||
296 | options.grid.borderWidth = angular.isDefined(settings.grid.outlineWidth) ? | 339 | options.grid.borderWidth = angular.isDefined(settings.grid.outlineWidth) ? |
297 | settings.grid.outlineWidth : 1; | 340 | settings.grid.outlineWidth : 1; |
298 | if (settings.grid.verticalLines === false) { | 341 | if (settings.grid.verticalLines === false) { |
299 | - options.xaxis.tickLength = 0; | 342 | + this.xaxis.tickLength = 0; |
300 | } | 343 | } |
301 | if (settings.grid.horizontalLines === false) { | 344 | if (settings.grid.horizontalLines === false) { |
302 | this.yaxis.tickLength = 0; | 345 | this.yaxis.tickLength = 0; |
@@ -309,14 +352,42 @@ export default class TbFlot { | @@ -309,14 +352,42 @@ export default class TbFlot { | ||
309 | } | 352 | } |
310 | } | 353 | } |
311 | 354 | ||
312 | - options.crosshair = { | ||
313 | - mode: 'x' | 355 | + options.xaxes[0] = angular.copy(this.xaxis); |
356 | + | ||
357 | + if (settings.xaxis && settings.xaxis.showLabels === false) { | ||
358 | + options.xaxes[0].tickFormatter = function() { | ||
359 | + return ''; | ||
360 | + }; | ||
314 | } | 361 | } |
315 | 362 | ||
316 | - options.series = { | ||
317 | - stack: settings.stack === true | 363 | + if (settings.comparisonEnabled) { |
364 | + var xaxis = angular.copy(this.xaxis); | ||
365 | + xaxis.position = 'top'; | ||
366 | + if (settings.xaxisSecond) { | ||
367 | + if (settings.xaxisSecond.showLabels === false) { | ||
368 | + xaxis.tickFormatter = function() { | ||
369 | + return ''; | ||
370 | + }; | ||
371 | + } | ||
372 | + xaxis.label = utils.customTranslation(settings.xaxisSecond.title, settings.xaxisSecond.title) || null; | ||
373 | + xaxis.position = settings.xaxisSecond.axisPosition; | ||
374 | + } | ||
375 | + xaxis.tickLength = 0; | ||
376 | + options.xaxes.push(xaxis); | ||
377 | + | ||
378 | + options.series = { | ||
379 | + stack: false | ||
380 | + }; | ||
381 | + } else { | ||
382 | + options.series = { | ||
383 | + stack: settings.stack === true | ||
384 | + }; | ||
318 | } | 385 | } |
319 | 386 | ||
387 | + options.crosshair = { | ||
388 | + mode: 'x' | ||
389 | + }; | ||
390 | + | ||
320 | if (this.chartType === 'line' && settings.smoothLines) { | 391 | if (this.chartType === 'line' && settings.smoothLines) { |
321 | options.series.curvedLines = { | 392 | options.series.curvedLines = { |
322 | active: true, | 393 | active: true, |
@@ -429,6 +500,13 @@ export default class TbFlot { | @@ -429,6 +500,13 @@ export default class TbFlot { | ||
429 | series.lines = { | 500 | series.lines = { |
430 | fill: keySettings.fillLines === true | 501 | fill: keySettings.fillLines === true |
431 | }; | 502 | }; |
503 | + | ||
504 | + if (this.ctx.settings.stack && !this.ctx.settings.comparisonEnabled) { | ||
505 | + series.stack = !keySettings.excludeFromStacking; | ||
506 | + } else { | ||
507 | + series.stack = false; | ||
508 | + } | ||
509 | + | ||
432 | if (this.chartType === 'line' || this.chartType === 'state') { | 510 | if (this.chartType === 'line' || this.chartType === 'state') { |
433 | series.lines.show = keySettings.showLines !== false | 511 | series.lines.show = keySettings.showLines !== false |
434 | } else { | 512 | } else { |
@@ -445,14 +523,23 @@ export default class TbFlot { | @@ -445,14 +523,23 @@ export default class TbFlot { | ||
445 | }; | 523 | }; |
446 | if (keySettings.showPoints === true) { | 524 | if (keySettings.showPoints === true) { |
447 | series.points.show = true; | 525 | series.points.show = true; |
448 | - series.points.lineWidth = 5; | 526 | + series.points.lineWidth = angular.isDefined(keySettings.showPointsLineWidth) ? keySettings.showPointsLineWidth : 5; |
449 | series.points.radius = angular.isDefined(keySettings.showPointsRadius) ? keySettings.showPointsRadius : 3; | 527 | series.points.radius = angular.isDefined(keySettings.showPointsRadius) ? keySettings.showPointsRadius : 3; |
528 | + series.points.symbol = angular.isDefined(keySettings.showPointShape) ? keySettings.showPointShape : 'circle'; | ||
529 | + if (series.points.symbol == 'custom' && keySettings.pointShapeFormatter) { | ||
530 | + try { | ||
531 | + series.points.symbol = new Function('ctx, x, y, radius, shadow', keySettings.pointShapeFormatter); | ||
532 | + } catch (e) { | ||
533 | + series.points.symbol = 'circle'; | ||
534 | + } | ||
535 | + } | ||
536 | + | ||
450 | } | 537 | } |
451 | 538 | ||
452 | if (this.chartType === 'line' && this.ctx.settings.smoothLines && !series.points.show) { | 539 | if (this.chartType === 'line' && this.ctx.settings.smoothLines && !series.points.show) { |
453 | series.curvedLines = { | 540 | series.curvedLines = { |
454 | apply: true | 541 | apply: true |
455 | - } | 542 | + }; |
456 | } | 543 | } |
457 | 544 | ||
458 | var lineColor = tinycolor(series.dataKey.color); | 545 | var lineColor = tinycolor(series.dataKey.color); |
@@ -460,6 +547,15 @@ export default class TbFlot { | @@ -460,6 +547,15 @@ export default class TbFlot { | ||
460 | 547 | ||
461 | series.highlightColor = lineColor.toRgbString(); | 548 | series.highlightColor = lineColor.toRgbString(); |
462 | 549 | ||
550 | + if (series.datasource.isAdditional) { | ||
551 | + series.xaxisIndex = 1; | ||
552 | + series.xaxis = 2; | ||
553 | + } else { | ||
554 | + series.xaxisIndex = 0; | ||
555 | + series.xaxis = 1; | ||
556 | + } | ||
557 | + | ||
558 | + | ||
463 | if (this.yaxis) { | 559 | if (this.yaxis) { |
464 | var units = series.dataKey.units && series.dataKey.units.length ? series.dataKey.units : this.ctx.trackUnits; | 560 | var units = series.dataKey.units && series.dataKey.units.length ? series.dataKey.units : this.ctx.trackUnits; |
465 | var yaxis; | 561 | var yaxis; |
@@ -477,7 +573,7 @@ export default class TbFlot { | @@ -477,7 +573,7 @@ export default class TbFlot { | ||
477 | series.yaxisIndex = this.yaxes.indexOf(yaxis); | 573 | series.yaxisIndex = this.yaxes.indexOf(yaxis); |
478 | series.yaxis = series.yaxisIndex+1; | 574 | series.yaxis = series.yaxisIndex+1; |
479 | yaxis.keysInfo[i] = {hidden: false}; | 575 | yaxis.keysInfo[i] = {hidden: false}; |
480 | - yaxis.hidden = false; | 576 | + yaxis.show = true; |
481 | } | 577 | } |
482 | } | 578 | } |
483 | 579 | ||
@@ -491,8 +587,12 @@ export default class TbFlot { | @@ -491,8 +587,12 @@ export default class TbFlot { | ||
491 | this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; | 587 | this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6; |
492 | } | 588 | } |
493 | } | 589 | } |
494 | - this.options.xaxis.min = this.subscription.timeWindow.minTime; | ||
495 | - this.options.xaxis.max = this.subscription.timeWindow.maxTime; | 590 | + this.options.xaxes[0].min = this.subscription.timeWindow.minTime; |
591 | + this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; | ||
592 | + if (this.ctx.settings.comparisonEnabled) { | ||
593 | + this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | ||
594 | + this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | ||
595 | + } | ||
496 | } | 596 | } |
497 | 597 | ||
498 | this.checkMouseEvents(); | 598 | this.checkMouseEvents(); |
@@ -500,6 +600,7 @@ export default class TbFlot { | @@ -500,6 +600,7 @@ export default class TbFlot { | ||
500 | if (this.ctx.plot) { | 600 | if (this.ctx.plot) { |
501 | this.ctx.plot.destroy(); | 601 | this.ctx.plot.destroy(); |
502 | } | 602 | } |
603 | + | ||
503 | if (this.chartType === 'pie' && this.ctx.animatedPie) { | 604 | if (this.chartType === 'pie' && this.ctx.animatedPie) { |
504 | this.ctx.pieDataAnimationDuration = 250; | 605 | this.ctx.pieDataAnimationDuration = 250; |
505 | this.pieData = angular.copy(this.subscription.data); | 606 | this.pieData = angular.copy(this.subscription.data); |
@@ -608,8 +709,12 @@ export default class TbFlot { | @@ -608,8 +709,12 @@ export default class TbFlot { | ||
608 | } | 709 | } |
609 | } | 710 | } |
610 | 711 | ||
611 | - this.options.xaxis.min = this.subscription.timeWindow.minTime; | ||
612 | - this.options.xaxis.max = this.subscription.timeWindow.maxTime; | 712 | + this.options.xaxes[0].min = this.subscription.timeWindow.minTime; |
713 | + this.options.xaxes[0].max = this.subscription.timeWindow.maxTime; | ||
714 | + if (this.ctx.settings.comparisonEnabled) { | ||
715 | + this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | ||
716 | + this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | ||
717 | + } | ||
613 | if (this.chartType === 'bar') { | 718 | if (this.chartType === 'bar') { |
614 | if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') { | 719 | if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') { |
615 | this.options.series.bars.barWidth = this.ctx.defaultBarWidth; | 720 | this.options.series.bars.barWidth = this.ctx.defaultBarWidth; |
@@ -623,6 +728,10 @@ export default class TbFlot { | @@ -623,6 +728,10 @@ export default class TbFlot { | ||
623 | } else { | 728 | } else { |
624 | this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; | 729 | this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime; |
625 | this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; | 730 | this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime; |
731 | + if (this.ctx.settings.comparisonEnabled) { | ||
732 | + this.ctx.plot.getOptions().xaxes[1].min = this.subscription.comparisonTimeWindow.minTime; | ||
733 | + this.ctx.plot.getOptions().xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime; | ||
734 | + } | ||
626 | if (this.chartType === 'bar') { | 735 | if (this.chartType === 'bar') { |
627 | if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') { | 736 | if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') { |
628 | this.ctx.plot.getOptions().series.bars.barWidth = this.ctx.defaultBarWidth; | 737 | this.ctx.plot.getOptions().series.bars.barWidth = this.ctx.defaultBarWidth; |
@@ -902,6 +1011,11 @@ export default class TbFlot { | @@ -902,6 +1011,11 @@ export default class TbFlot { | ||
902 | "type": "string", | 1011 | "type": "string", |
903 | "default": "" | 1012 | "default": "" |
904 | }; | 1013 | }; |
1014 | + properties["hideZeros"] = { | ||
1015 | + "title": "Hide zero/false values from tooltip", | ||
1016 | + "type": "boolean", | ||
1017 | + "default": false | ||
1018 | + }; | ||
905 | 1019 | ||
906 | properties["grid"] = { | 1020 | properties["grid"] = { |
907 | "title": "Grid settings", | 1021 | "title": "Grid settings", |
@@ -1029,6 +1143,7 @@ export default class TbFlot { | @@ -1029,6 +1143,7 @@ export default class TbFlot { | ||
1029 | "key": "tooltipValueFormatter", | 1143 | "key": "tooltipValueFormatter", |
1030 | "type": "javascript" | 1144 | "type": "javascript" |
1031 | }); | 1145 | }); |
1146 | + schema["form"].push("hideZeros"); | ||
1032 | schema["form"].push({ | 1147 | schema["form"].push({ |
1033 | "key": "grid", | 1148 | "key": "grid", |
1034 | "items": [ | 1149 | "items": [ |
@@ -1079,6 +1194,21 @@ export default class TbFlot { | @@ -1079,6 +1194,21 @@ export default class TbFlot { | ||
1079 | } | 1194 | } |
1080 | ] | 1195 | ] |
1081 | }); | 1196 | }); |
1197 | + if (chartType === 'graph' || chartType === 'bar') { | ||
1198 | + schema.groupInfoes = [{ | ||
1199 | + "formIndex":0, | ||
1200 | + "GroupTitle":"Common Settings" | ||
1201 | + }]; | ||
1202 | + schema.form = [schema.form]; | ||
1203 | + angular.merge(schema.schema.properties, chartSettingsSchemaForComparison.schema.properties); | ||
1204 | + schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required); | ||
1205 | + schema.form.push(chartSettingsSchemaForComparison.form); | ||
1206 | + schema.groupInfoes.push({ | ||
1207 | + "formIndex":schema.groupInfoes.length, | ||
1208 | + "GroupTitle":"Comparison Settings" | ||
1209 | + }); | ||
1210 | + } | ||
1211 | + | ||
1082 | return schema; | 1212 | return schema; |
1083 | } | 1213 | } |
1084 | 1214 | ||
@@ -1086,12 +1216,18 @@ export default class TbFlot { | @@ -1086,12 +1216,18 @@ export default class TbFlot { | ||
1086 | return {} | 1216 | return {} |
1087 | } | 1217 | } |
1088 | 1218 | ||
1089 | - static datakeySettingsSchema(defaultShowLines) { | ||
1090 | - return { | 1219 | + static datakeySettingsSchema(defaultShowLines, chartType) { |
1220 | + | ||
1221 | + var schema = { | ||
1091 | "schema": { | 1222 | "schema": { |
1092 | "type": "object", | 1223 | "type": "object", |
1093 | "title": "DataKeySettings", | 1224 | "title": "DataKeySettings", |
1094 | "properties": { | 1225 | "properties": { |
1226 | + "excludeFromStacking": { | ||
1227 | + "title": "Exclude from stacking(available in \"Stacking\" mode)", | ||
1228 | + "type": "boolean", | ||
1229 | + "default": false | ||
1230 | + }, | ||
1095 | "showLines": { | 1231 | "showLines": { |
1096 | "title": "Show lines", | 1232 | "title": "Show lines", |
1097 | "type": "boolean", | 1233 | "type": "boolean", |
@@ -1107,6 +1243,25 @@ export default class TbFlot { | @@ -1107,6 +1243,25 @@ export default class TbFlot { | ||
1107 | "type": "boolean", | 1243 | "type": "boolean", |
1108 | "default": false | 1244 | "default": false |
1109 | }, | 1245 | }, |
1246 | + "showPointShape": { | ||
1247 | + "title": "Select point shape:", | ||
1248 | + "type": "string", | ||
1249 | + "default": "circle" | ||
1250 | + }, | ||
1251 | + "pointShapeFormatter": { | ||
1252 | + "title": "Point shape format function, f(ctx, x, y, radius, shadow)", | ||
1253 | + "type": "string", | ||
1254 | + "default": "var size = radius * Math.sqrt(Math.PI) / 2;\n" + | ||
1255 | + "ctx.moveTo(x - size, y - size);\n" + | ||
1256 | + "ctx.lineTo(x + size, y + size);\n" + | ||
1257 | + "ctx.moveTo(x - size, y + size);\n" + | ||
1258 | + "ctx.lineTo(x + size, y - size);" | ||
1259 | + }, | ||
1260 | + "showPointsLineWidth": { | ||
1261 | + "title": "Line width of points", | ||
1262 | + "type": "number", | ||
1263 | + "default": 5 | ||
1264 | + }, | ||
1110 | "showPointsRadius": { | 1265 | "showPointsRadius": { |
1111 | "title": "Radius of points", | 1266 | "title": "Radius of points", |
1112 | "type": "number", | 1267 | "type": "number", |
@@ -1161,9 +1316,46 @@ export default class TbFlot { | @@ -1161,9 +1316,46 @@ export default class TbFlot { | ||
1161 | "required": ["showLines", "fillLines", "showPoints"] | 1316 | "required": ["showLines", "fillLines", "showPoints"] |
1162 | }, | 1317 | }, |
1163 | "form": [ | 1318 | "form": [ |
1319 | + "excludeFromStacking", | ||
1164 | "showLines", | 1320 | "showLines", |
1165 | "fillLines", | 1321 | "fillLines", |
1166 | "showPoints", | 1322 | "showPoints", |
1323 | + { | ||
1324 | + "key": "showPointShape", | ||
1325 | + "type": "rc-select", | ||
1326 | + "multiple": false, | ||
1327 | + "items": [ | ||
1328 | + { | ||
1329 | + "value": "circle", | ||
1330 | + "label": "Circle" | ||
1331 | + }, | ||
1332 | + { | ||
1333 | + "value": "cross", | ||
1334 | + "label": "Cross" | ||
1335 | + }, | ||
1336 | + { | ||
1337 | + "value": "diamond", | ||
1338 | + "label": "Diamond" | ||
1339 | + }, | ||
1340 | + { | ||
1341 | + "value": "square", | ||
1342 | + "label": "Square" | ||
1343 | + }, | ||
1344 | + { | ||
1345 | + "value": "triangle", | ||
1346 | + "label": "Triangle" | ||
1347 | + }, | ||
1348 | + { | ||
1349 | + "value": "custom", | ||
1350 | + "label": "Custom function" | ||
1351 | + } | ||
1352 | + ] | ||
1353 | + }, | ||
1354 | + { | ||
1355 | + "key": "pointShapeFormatter", | ||
1356 | + "type": "javascript" | ||
1357 | + }, | ||
1358 | + "showPointsLineWidth", | ||
1167 | "showPointsRadius", | 1359 | "showPointsRadius", |
1168 | { | 1360 | { |
1169 | "key": "tooltipValueFormatter", | 1361 | "key": "tooltipValueFormatter", |
@@ -1195,7 +1387,47 @@ export default class TbFlot { | @@ -1195,7 +1387,47 @@ export default class TbFlot { | ||
1195 | "type": "javascript" | 1387 | "type": "javascript" |
1196 | } | 1388 | } |
1197 | ] | 1389 | ] |
1390 | + }; | ||
1391 | + | ||
1392 | + var properties = schema["schema"]["properties"]; | ||
1393 | + if (chartType === 'graph' || chartType === 'bar') { | ||
1394 | + properties["comparisonSettings"] = { | ||
1395 | + "title": "Comparison Settings", | ||
1396 | + "type": "object", | ||
1397 | + "properties": { | ||
1398 | + "showValuesForComparison": { | ||
1399 | + "title": "Show historical values for comparison", | ||
1400 | + "type": "boolean", | ||
1401 | + "default": true | ||
1402 | + }, | ||
1403 | + "comparisonValuesLabel": { | ||
1404 | + "title": "Historical values label", | ||
1405 | + "type": "string", | ||
1406 | + "default": "" | ||
1407 | + }, | ||
1408 | + "color": { | ||
1409 | + "title": "Color", | ||
1410 | + "type": "string", | ||
1411 | + "default": "" | ||
1412 | + } | ||
1413 | + }, | ||
1414 | + "required": ["showValuesForComparison"] | ||
1415 | + }; | ||
1416 | + schema["form"].push({ | ||
1417 | + "key": "comparisonSettings", | ||
1418 | + "items": [ | ||
1419 | + "comparisonSettings.showValuesForComparison", | ||
1420 | + "comparisonSettings.comparisonValuesLabel", | ||
1421 | + { | ||
1422 | + "key": "comparisonSettings.color", | ||
1423 | + "type": "color" | ||
1424 | + } | ||
1425 | + ] | ||
1426 | + }); | ||
1427 | + | ||
1198 | } | 1428 | } |
1429 | + | ||
1430 | + return schema; | ||
1199 | } | 1431 | } |
1200 | 1432 | ||
1201 | enableMouseEvents() { | 1433 | enableMouseEvents() { |
@@ -1227,10 +1459,15 @@ export default class TbFlot { | @@ -1227,10 +1459,15 @@ export default class TbFlot { | ||
1227 | tooltipHtml = tbFlot.ctx.tooltipFormatter(item); | 1459 | tooltipHtml = tbFlot.ctx.tooltipFormatter(item); |
1228 | } else { | 1460 | } else { |
1229 | var hoverInfo = tbFlot.getHoverInfo(tbFlot.ctx.plot.getData(), pos); | 1461 | var hoverInfo = tbFlot.getHoverInfo(tbFlot.ctx.plot.getData(), pos); |
1230 | - if (angular.isNumber(hoverInfo.time)) { | ||
1231 | - hoverInfo.seriesHover.sort(function (a, b) { | 1462 | + if (angular.isNumber(hoverInfo[0].time) || (hoverInfo[1] && angular.isNumber(hoverInfo[1].time))) { |
1463 | + hoverInfo[0].seriesHover.sort(function (a, b) { | ||
1232 | return b.value - a.value; | 1464 | return b.value - a.value; |
1233 | }); | 1465 | }); |
1466 | + if (hoverInfo[1] && hoverInfo[1].seriesHover.length) { | ||
1467 | + hoverInfo[1].seriesHover.sort(function (a, b) { | ||
1468 | + return b.value - a.value; | ||
1469 | + }); | ||
1470 | + } | ||
1234 | tooltipHtml = tbFlot.ctx.tooltipFormatter(hoverInfo, item ? item.seriesIndex : -1); | 1471 | tooltipHtml = tbFlot.ctx.tooltipFormatter(hoverInfo, item ? item.seriesIndex : -1); |
1235 | } | 1472 | } |
1236 | } | 1473 | } |
@@ -1258,9 +1495,11 @@ export default class TbFlot { | @@ -1258,9 +1495,11 @@ export default class TbFlot { | ||
1258 | }); | 1495 | }); |
1259 | 1496 | ||
1260 | if (multipleModeTooltip) { | 1497 | if (multipleModeTooltip) { |
1261 | - for (var i = 0; i < hoverInfo.seriesHover.length; i++) { | ||
1262 | - var seriesHoverInfo = hoverInfo.seriesHover[i]; | ||
1263 | - tbFlot.ctx.plot.highlight(seriesHoverInfo.index, seriesHoverInfo.hoverIndex); | 1498 | + for (var j = 0; j < hoverInfo.length; j++) { |
1499 | + for (var i = 0; i < hoverInfo[j].seriesHover.length; i++) { | ||
1500 | + var seriesHoverInfo = hoverInfo[j].seriesHover[i]; | ||
1501 | + tbFlot.ctx.plot.highlight(seriesHoverInfo.index, seriesHoverInfo.hoverIndex); | ||
1502 | + } | ||
1264 | } | 1503 | } |
1265 | } | 1504 | } |
1266 | } | 1505 | } |
@@ -1399,19 +1638,38 @@ export default class TbFlot { | @@ -1399,19 +1638,38 @@ export default class TbFlot { | ||
1399 | 1638 | ||
1400 | 1639 | ||
1401 | getHoverInfo (seriesList, pos) { | 1640 | getHoverInfo (seriesList, pos) { |
1402 | - var i, series, value, hoverIndex, hoverDistance, pointTime, minDistance, minTime; | 1641 | + var i, series, value, hoverIndex, hoverDistance, pointTime, minDistance, minTime, hoverData; |
1403 | var last_value = 0; | 1642 | var last_value = 0; |
1404 | - var results = { | 1643 | + var results = [{ |
1405 | seriesHover: [] | 1644 | seriesHover: [] |
1406 | - }; | 1645 | + }]; |
1646 | + if (this.ctx.settings.comparisonEnabled) { | ||
1647 | + results.push({ | ||
1648 | + seriesHover: [] | ||
1649 | + }); | ||
1650 | + var minDistanceHistorical, minTimeHistorical; | ||
1651 | + } | ||
1407 | for (i = 0; i < seriesList.length; i++) { | 1652 | for (i = 0; i < seriesList.length; i++) { |
1408 | series = seriesList[i]; | 1653 | series = seriesList[i]; |
1409 | - hoverIndex = this.findHoverIndexFromData(pos.x, series); | 1654 | + var posx; |
1655 | + if (series.datasource.isAdditional) { | ||
1656 | + posx = pos.x2; | ||
1657 | + } else { | ||
1658 | + posx = pos.x; | ||
1659 | + } | ||
1660 | + hoverIndex = this.findHoverIndexFromData(posx, series); | ||
1410 | if (series.data[hoverIndex] && series.data[hoverIndex][0]) { | 1661 | if (series.data[hoverIndex] && series.data[hoverIndex][0]) { |
1411 | - hoverDistance = pos.x - series.data[hoverIndex][0]; | 1662 | + hoverDistance = posx - series.data[hoverIndex][0]; |
1412 | pointTime = series.data[hoverIndex][0]; | 1663 | pointTime = series.data[hoverIndex][0]; |
1413 | 1664 | ||
1414 | - if (!minDistance | 1665 | + if (series.datasource.isAdditional) { |
1666 | + if (!minDistanceHistorical | ||
1667 | + || (hoverDistance >= 0 && (hoverDistance < minDistanceHistorical || minDistanceHistorical < 0)) | ||
1668 | + || (hoverDistance < 0 && hoverDistance > minDistanceHistorical)) { | ||
1669 | + minDistanceHistorical = hoverDistance; | ||
1670 | + minTimeHistorical = pointTime; | ||
1671 | + } | ||
1672 | + } else if (!minDistance | ||
1415 | || (hoverDistance >= 0 && (hoverDistance < minDistance || minDistance < 0)) | 1673 | || (hoverDistance >= 0 && (hoverDistance < minDistance || minDistance < 0)) |
1416 | || (hoverDistance < 0 && hoverDistance > minDistance)) { | 1674 | || (hoverDistance < 0 && hoverDistance > minDistance)) { |
1417 | minDistance = hoverDistance; | 1675 | minDistance = hoverDistance; |
@@ -1429,23 +1687,33 @@ export default class TbFlot { | @@ -1429,23 +1687,33 @@ export default class TbFlot { | ||
1429 | } | 1687 | } |
1430 | 1688 | ||
1431 | if (series.stack || (series.curvedLines && series.curvedLines.apply)) { | 1689 | if (series.stack || (series.curvedLines && series.curvedLines.apply)) { |
1432 | - hoverIndex = this.findHoverIndexFromDataPoints(pos.x, series, hoverIndex); | 1690 | + hoverIndex = this.findHoverIndexFromDataPoints(posx, series, hoverIndex); |
1691 | + } | ||
1692 | + if (!this.ctx.hideZeros || value) { | ||
1693 | + hoverData = { | ||
1694 | + value: value, | ||
1695 | + hoverIndex: hoverIndex, | ||
1696 | + color: series.dataKey.color, | ||
1697 | + label: series.dataKey.label, | ||
1698 | + units: series.dataKey.units, | ||
1699 | + decimals: series.dataKey.decimals, | ||
1700 | + tooltipValueFormatFunction: series.dataKey.tooltipValueFormatFunction, | ||
1701 | + time: pointTime, | ||
1702 | + distance: hoverDistance, | ||
1703 | + index: i | ||
1704 | + }; | ||
1705 | + if (series.datasource.isAdditional) { | ||
1706 | + results[1].seriesHover.push(hoverData); | ||
1707 | + } else { | ||
1708 | + results[0].seriesHover.push(hoverData); | ||
1709 | + } | ||
1433 | } | 1710 | } |
1434 | - results.seriesHover.push({ | ||
1435 | - value: value, | ||
1436 | - hoverIndex: hoverIndex, | ||
1437 | - color: series.dataKey.color, | ||
1438 | - label: series.dataKey.label, | ||
1439 | - units: series.dataKey.units, | ||
1440 | - decimals: series.dataKey.decimals, | ||
1441 | - tooltipValueFormatFunction: series.dataKey.tooltipValueFormatFunction, | ||
1442 | - time: pointTime, | ||
1443 | - distance: hoverDistance, | ||
1444 | - index: i | ||
1445 | - }); | ||
1446 | } | 1711 | } |
1447 | } | 1712 | } |
1448 | - results.time = minTime; | 1713 | + if (results[1] && results[1].seriesHover.length) { |
1714 | + results[1].time = minTimeHistorical; | ||
1715 | + } | ||
1716 | + results[0].time = minTime; | ||
1449 | return results; | 1717 | return results; |
1450 | } | 1718 | } |
1451 | 1719 | ||
@@ -1524,4 +1792,93 @@ export default class TbFlot { | @@ -1524,4 +1792,93 @@ export default class TbFlot { | ||
1524 | } | 1792 | } |
1525 | } | 1793 | } |
1526 | 1794 | ||
1795 | +const chartSettingsSchemaForComparison = { | ||
1796 | + "schema": { | ||
1797 | + "title": "Comparison Settings", | ||
1798 | + "type": "object", | ||
1799 | + "properties": { | ||
1800 | + "comparisonEnabled": { | ||
1801 | + "title": "Enable comparison", | ||
1802 | + "type": "boolean", | ||
1803 | + "default": false | ||
1804 | + }, | ||
1805 | + "timeForComparison": { | ||
1806 | + "title": "Time to show historical data", | ||
1807 | + "type": "string", | ||
1808 | + "default": "months" | ||
1809 | + }, | ||
1810 | + "xaxisSecond": { | ||
1811 | + "title": "Second X axis", | ||
1812 | + "type": "object", | ||
1813 | + "properties": { | ||
1814 | + "axisPosition": { | ||
1815 | + "title": "Axis position", | ||
1816 | + "type": "string", | ||
1817 | + "default": "top" | ||
1818 | + }, | ||
1819 | + "showLabels": { | ||
1820 | + "title": "Show labels", | ||
1821 | + "type": "boolean", | ||
1822 | + "default": true | ||
1823 | + }, | ||
1824 | + "title": { | ||
1825 | + "title": "Axis title", | ||
1826 | + "type": "string", | ||
1827 | + "default": null | ||
1828 | + } | ||
1829 | + } | ||
1830 | + } | ||
1831 | + }, | ||
1832 | + "required": [] | ||
1833 | + }, | ||
1834 | + "form": [ | ||
1835 | + "comparisonEnabled", | ||
1836 | + { | ||
1837 | + "key": "timeForComparison", | ||
1838 | + "type": "rc-select", | ||
1839 | + "multiple": false, | ||
1840 | + "items": [ | ||
1841 | + { | ||
1842 | + "value": "days", | ||
1843 | + "label": "Day ago" | ||
1844 | + }, | ||
1845 | + { | ||
1846 | + "value": "weeks", | ||
1847 | + "label": "Week ago" | ||
1848 | + }, | ||
1849 | + { | ||
1850 | + "value": "months", | ||
1851 | + "label": "Month ago (default)" | ||
1852 | + }, | ||
1853 | + { | ||
1854 | + "value": "years", | ||
1855 | + "label": "Year ago" | ||
1856 | + } | ||
1857 | + ] | ||
1858 | + }, | ||
1859 | + { | ||
1860 | + "key": "xaxisSecond", | ||
1861 | + "items": [ | ||
1862 | + { | ||
1863 | + "key": "xaxisSecond.axisPosition", | ||
1864 | + "type": "rc-select", | ||
1865 | + "multiple": false, | ||
1866 | + "items": [ | ||
1867 | + { | ||
1868 | + "value": "top", | ||
1869 | + "label": "Top (default)" | ||
1870 | + }, | ||
1871 | + { | ||
1872 | + "value": "bottom", | ||
1873 | + "label": "Bottom" | ||
1874 | + } | ||
1875 | + ] | ||
1876 | + }, | ||
1877 | + "xaxisSecond.showLabels", | ||
1878 | + "xaxisSecond.title", | ||
1879 | + ] | ||
1880 | + } | ||
1881 | + ] | ||
1882 | +}; | ||
1883 | + | ||
1527 | /* eslint-enable angular/angularelement */ | 1884 | /* eslint-enable angular/angularelement */ |