Browse Source

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 09b73d5afc.

* 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
pull/2105/head
Chantsova Ekaterina 7 years ago
committed by Igor Kulikov
parent
commit
467d7b5c3c
  1. 6
      application/src/main/data/json/system/widget_bundles/charts.json
  2. 100
      ui/src/app/api/subscription.js
  3. 23
      ui/src/app/api/time.service.js
  4. 22
      ui/src/app/common/utils.service.js
  5. 6
      ui/src/app/components/widget/widget.controller.js
  6. 8
      ui/src/app/locale/locale.constant-en_US.json
  7. 8
      ui/src/app/locale/locale.constant-ru_RU.json
  8. 8
      ui/src/app/locale/locale.constant-uk_UA.json
  9. 539
      ui/src/app/widget/lib/flot-widget.js

6
application/src/main/data/json/system/widget_bundles/charts.json

@ -35,7 +35,7 @@
"resources": [],
"templateHtml": "",
"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",
"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",
"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",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"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 @@
"resources": [],
"templateHtml": "",
"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",
"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",
"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",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"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 @@
"resources": [],
"templateHtml": "",
"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",
"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",
"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",
"settingsSchema": "{}",
"dataKeySettingsSchema": "{}",
"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}}"

100
ui/src/app/api/subscription.js

@ -132,6 +132,13 @@ export default class Subscription {
}
this.subscriptionTimewindow = null;
this.comparisonEnabled = options.comparisonEnabled;
if (this.comparisonEnabled) {
this.timeForComparison = options.timeForComparison;
this.comparisonTimeWindow = {};
this.timewindowForComparison = null;
}
this.units = options.units || '';
this.decimals = angular.isDefined(options.decimals) ? options.decimals : 2;
@ -311,13 +318,28 @@ export default class Subscription {
}
configureData() {
var additionalDatasources = [];
var dataIndex = 0;
var additionalKeysNumber = 0;
for (var i = 0; i < this.datasources.length; i++) {
var datasource = this.datasources[i];
var additionalDataKeys = [];
let datasourceAdditionalKeysNumber = 0;
for (var a = 0; a < datasource.dataKeys.length; a++) {
var dataKey = datasource.dataKeys[a];
dataKey.hidden = false;
dataKey.pattern = angular.copy(dataKey.label);
if (this.comparisonEnabled && dataKey.settings.comparisonSettings && dataKey.settings.comparisonSettings.showValuesForComparison) {
datasourceAdditionalKeysNumber++;
additionalKeysNumber++;
let additionalDataKey = this.ctx.utils.createAdditionalDataKey(dataKey,datasource, this.timeForComparison,this.datasources,additionalKeysNumber);
dataKey.settings.comparisonSettings.color = additionalDataKey.color;
additionalDataKeys.push(additionalDataKey);
}
var datasourceData = {
datasource: datasource,
dataKey: dataKey,
@ -341,8 +363,46 @@ export default class Subscription {
this.legendData.data.push(legendKeyData);
}
}
if (datasourceAdditionalKeysNumber > 0) {
let additionalDatasource = angular.copy(datasource);
additionalDatasource.dataKeys = additionalDataKeys;
additionalDatasource.isAdditional = true;
additionalDatasources.push(additionalDatasource);
}
}
for (var j=0; j < additionalDatasources.length; j++) {
let additionalDatasource = additionalDatasources[j];
for (var k=0; k < additionalDatasource.dataKeys.length; k++) {
let additionalDataKey = additionalDatasource.dataKeys[k];
var additionalDatasourceData = {
datasource: additionalDatasource,
dataKey: additionalDataKey,
data: []
};
this.data.push(additionalDatasourceData);
this.hiddenData.push({data: []});
if (this.displayLegend) {
var additionalLegendKey = {
dataKey: additionalDataKey,
dataIndex: dataIndex++
};
this.legendData.keys.push(additionalLegendKey);
var additionalLegendKeyData = {
min: null,
max: null,
avg: null,
total: null,
hidden: false
};
this.legendData.data.push(additionalLegendKeyData);
}
}
}
this.datasources = this.datasources.concat(additionalDatasources);
var subscription = this;
var registration;
@ -638,7 +698,7 @@ export default class Subscription {
updateTimewindow() {
this.timeWindow.interval = this.subscriptionTimewindow.aggregation.interval || 1000;
if (this.subscriptionTimewindow.realtimeWindowMs) {
this.timeWindow.maxTime = (new Date).getTime() + this.timeWindow.stDiff;
this.timeWindow.maxTime = (moment()).valueOf() + this.timeWindow.stDiff;//eslint-disable-line
this.timeWindow.minTime = this.timeWindow.maxTime - this.subscriptionTimewindow.realtimeWindowMs;
} else if (this.subscriptionTimewindow.fixedWindow) {
this.timeWindow.maxTime = this.subscriptionTimewindow.fixedWindow.endTimeMs;
@ -659,6 +719,26 @@ export default class Subscription {
return this.subscriptionTimewindow;
}
updateComparisonTimewindow() {
this.comparisonTimeWindow.interval = this.timewindowForComparison.aggregation.interval || 1000;
if (this.timewindowForComparison.realtimeWindowMs) {
this.comparisonTimeWindow.maxTime = moment(this.timeWindow.maxTime).subtract(1, this.timeForComparison).valueOf(); //eslint-disable-line
this.comparisonTimeWindow.minTime = this.comparisonTimeWindow.maxTime - this.timewindowForComparison.realtimeWindowMs;
} else if (this.timewindowForComparison.fixedWindow) {
this.comparisonTimeWindow.maxTime = this.timewindowForComparison.fixedWindow.endTimeMs;
this.comparisonTimeWindow.minTime = this.timewindowForComparison.fixedWindow.startTimeMs;
}
}
updateSubscriptionForComparison() {
if (!this.subscriptionTimewindow) {
this.subscriptionTimewindow = this.updateRealtimeSubscription();
}
this.timewindowForComparison = this.ctx.timeService.createTimewindowForComparison(this.subscriptionTimewindow, this.timeForComparison);
this.updateComparisonTimewindow();
return this.timewindowForComparison;
}
dataUpdated(sourceData, datasourceIndex, dataKeyIndex, apply) {
for (var x = 0; x < this.datasourceListeners.length; x++) {
this.datasources[x].dataReceived = this.datasources[x].dataReceived === true;
@ -689,6 +769,9 @@ export default class Subscription {
if (update) {
if (this.subscriptionTimewindow && this.subscriptionTimewindow.realtimeWindowMs) {
this.updateTimewindow();
if (this.timewindowForComparison && this.timewindowForComparison.realtimeWindowMs) {
this.updateComparisonTimewindow();
}
}
currentData.data = sourceData.data;
if (this.caulculateLegendData) {
@ -745,6 +828,9 @@ export default class Subscription {
this.notifyDataLoading();
if (this.type === this.ctx.types.widgetType.timeseries.value && this.timeWindowConfig) {
this.updateRealtimeSubscription();
if (this.comparisonEnabled) {
this.updateSubscriptionForComparison();
}
if (this.subscriptionTimewindow.fixedWindow) {
this.onDataUpdated();
}
@ -776,6 +862,17 @@ export default class Subscription {
datasourceIndex: index
};
if (this.comparisonEnabled && datasource.isAdditional) {
listener.subscriptionTimewindow = this.timewindowForComparison;
listener.updateRealtimeSubscription = function () {
this.subscriptionTimewindow = subscription.updateSubscriptionForComparison();
return this.subscriptionTimewindow;
};
listener.setRealtimeSubscription = function () {
subscription.updateSubscriptionForComparison();
};
}
for (var a = 0; a < datasource.dataKeys.length; a++) {
this.data[index + a].data = [];
}
@ -908,7 +1005,6 @@ export default class Subscription {
});
this.registrations = [];
}
}
function calculateMin(data) {

23
ui/src/app/api/time.service.js

@ -47,6 +47,7 @@ function TimeService($translate, $http, $q, types) {
defaultTimewindow: defaultTimewindow,
toHistoryTimewindow: toHistoryTimewindow,
createSubscriptionTimewindow: createSubscriptionTimewindow,
createTimewindowForComparison: createTimewindowForComparison,
getMaxDatapointsLimit: function () {
return maxDatapointsLimit;
},
@ -383,5 +384,27 @@ function TimeService($translate, $http, $q, types) {
}
}
function createTimewindowForComparison(subscriptionTimewindow, timeUnit) {
var timewindowForComparison = {
fixedWindow: null,
realtimeWindowMs: null,
aggregation: subscriptionTimewindow.aggregation
};
if (subscriptionTimewindow.realtimeWindowMs) {
timewindowForComparison.startTs = moment(subscriptionTimewindow.startTs).subtract(1, timeUnit).valueOf(); //eslint-disable-line
timewindowForComparison.realtimeWindowMs = subscriptionTimewindow.realtimeWindowMs;
} else if (subscriptionTimewindow.fixedWindow) {
var timeInterval = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
var endTimeMs = moment(subscriptionTimewindow.fixedWindow.endTimeMs).subtract(1, timeUnit).valueOf(); //eslint-disable-line
timewindowForComparison.startTs = endTimeMs - timeInterval;
timewindowForComparison.fixedWindow = {
startTimeMs: timewindowForComparison.startTs,
endTimeMs: endTimeMs
};
}
return timewindowForComparison;
}
}

22
ui/src/app/common/utils.service.js

@ -144,6 +144,7 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
isLocalUrl: isLocalUrl,
validateDatasources: validateDatasources,
createKey: createKey,
createAdditionalDataKey: createAdditionalDataKey,
createLabelFromDatasource: createLabelFromDatasource,
insertVariable: insertVariable,
customTranslation: customTranslation,
@ -411,8 +412,8 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
return copy;
}
function genNextColor(datasources) {
var index = 0;
function genNextColor(datasources, initialIndex) {
var index = initialIndex || 0;
if (datasources) {
for (var i = 0; i < datasources.length; i++) {
var datasource = datasources[i];
@ -491,6 +492,23 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
return dataKey;
}
function createAdditionalDataKey(dataKey, datasource, timeUnit, datasources, additionalKeysNumber) {
let additionalDataKey = angular.copy(dataKey);
if (dataKey.settings.comparisonSettings.comparisonValuesLabel) {
additionalDataKey.label = createLabelFromDatasource(datasource, dataKey.settings.comparisonSettings.comparisonValuesLabel);
} else {
additionalDataKey.label = dataKey.label + ' ' + $translate.instant('legend.comparison-time-ago.'+timeUnit);
}
additionalDataKey.pattern = additionalDataKey.label;
if (dataKey.settings.comparisonSettings.color) {
additionalDataKey.color = dataKey.settings.comparisonSettings.color;
} else {
additionalDataKey.color = genNextColor(datasources, additionalKeysNumber);
}
additionalDataKey._hash = Math.random();
return additionalDataKey;
}
function createLabelFromDatasource(datasource, pattern) {
var label = angular.copy(pattern);
var match = varsRegex.exec(pattern);

6
ui/src/app/components/widget/widget.controller.js

@ -357,8 +357,10 @@ export default function WidgetController($scope, $state, $timeout, $window, $ocL
if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) {
options = {
type: widget.type,
stateData: vm.typeParameters.stateData
}
stateData: vm.typeParameters.stateData,
comparisonEnabled: widgetContext.settings.comparisonEnabled,
timeForComparison: widgetContext.settings.timeForComparison
};
if (widget.type == types.widgetType.alarm.value) {
options.alarmSource = angular.copy(widget.config.alarmSource);
options.alarmSearchStatus = angular.isDefined(widget.config.alarmSearchStatus) ?

8
ui/src/app/locale/locale.constant-en_US.json

@ -1195,7 +1195,13 @@
"min": "min",
"max": "max",
"avg": "avg",
"total": "total"
"total": "total",
"comparison-time-ago": {
"days": "(day ago)",
"weeks": "(week ago)",
"months": "(month ago)",
"years": "(year ago)"
}
},
"login": {
"login": "Login",

8
ui/src/app/locale/locale.constant-ru_RU.json

@ -1169,7 +1169,13 @@
"min": "Мин",
"max": "Макс",
"avg": "Среднее",
"total": "Сумма"
"total": "Сумма",
"comparison-time-ago": {
"days": "(день назад)",
"weeks": "(неделю назад)",
"months": "(месяц назад)",
"years": "(год назад)"
}
},
"login": {
"login": "Войти",

8
ui/src/app/locale/locale.constant-uk_UA.json

@ -1584,7 +1584,13 @@
"min": "мін",
"max": "макс",
"avg": "середнє",
"total": "Сума"
"total": "Сума",
"comparison-time-ago": {
"days": "(день тому)",
"weeks": "(тиждень тому)",
"months": "(місяць тому)",
"years": "(рік тому)"
}
},
"login": {
"login": "Вхід",

539
ui/src/app/widget/lib/flot-widget.js

@ -23,6 +23,7 @@ import 'flot/src/plugins/jquery.flot.selection';
import 'flot/src/plugins/jquery.flot.pie';
import 'flot/src/plugins/jquery.flot.crosshair';
import 'flot/src/plugins/jquery.flot.stack';
import 'flot/src/plugins/jquery.flot.symbol';
import 'flot.curvedlines/curvedLines';
/* eslint-disable angular/angularelement */
@ -32,6 +33,7 @@ export default class TbFlot {
this.ctx = ctx;
this.chartType = chartType || 'line';
var settings = ctx.settings;
var utils = this.ctx.$scope.$injector.get('utils');
ctx.tooltip = $('#flot-series-tooltip');
if (ctx.tooltip.length === 0) {
@ -59,7 +61,7 @@ export default class TbFlot {
divElement.css({
display: "flex",
alignItems: "center",
justifyContent: "flex-start"
justifyContent: "space-between"
});
var lineSpan = $('<span></span>');
lineSpan.css({
@ -125,55 +127,99 @@ export default class TbFlot {
} else {
ctx.tooltipFormatter = function(hoverInfo, seriesIndex) {
var content = '';
var timestamp = parseInt(hoverInfo.time);
var date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss');
var dateDiv = $('<div>' + date + '</div>');
dateDiv.css({
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "4px",
fontWeight: "700"
});
content += dateDiv.prop('outerHTML');
if (tbFlot.ctx.tooltipIndividual) {
var found = hoverInfo.seriesHover.filter((seriesHover) => {
var seriesHoverArray;
if (hoverInfo[1] && hoverInfo[1].seriesHover.length) {
seriesHoverArray = hoverInfo[0].seriesHover.concat(hoverInfo[1].seriesHover);
} else {
seriesHoverArray = hoverInfo[0].seriesHover;
}
var found = seriesHoverArray.filter((seriesHover) => {
return seriesHover.index === seriesIndex;
});
if (found && found.length) {
let timestamp;
if (!angular.isNumber(hoverInfo[0].time) || (found[0].time < hoverInfo[0].time)) {
timestamp = parseInt(hoverInfo[1].time);
} else {
timestamp = parseInt(hoverInfo[0].time);
}
let date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss');
let dateDiv = $('<div>' + date + '</div>');
dateDiv.css({
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "4px",
fontWeight: "700"
});
content += dateDiv.prop('outerHTML');
content += seriesInfoDivFromInfo(found[0], seriesIndex);
}
} else {
var seriesDiv = $('<div></div>');
seriesDiv.css({
display: "flex",
flexDirection: "row"
});
const maxRows = 15;
var columns = Math.ceil(hoverInfo.seriesHover.length / maxRows);
var columnsContent = '';
for (var c = 0; c < columns; c++) {
var columnDiv = $('<div></div>');
columnDiv.css({
display: "flex",
flexDirection: "column"
});
var columnContent = '';
for (var i = c*maxRows; i < (c+1)*maxRows; i++) {
if (i == hoverInfo.seriesHover.length) {
break;
var maxRows;
if (hoverInfo[1] && hoverInfo[1].seriesHover.length) {
maxRows = 5;
} else {
maxRows = 15;
}
var columns = 0;
if (hoverInfo[1] && (hoverInfo[1].seriesHover.length > hoverInfo[0].seriesHover.length)) {
columns = Math.ceil(hoverInfo[1].seriesHover.length / maxRows);
} else {
columns = Math.ceil(hoverInfo[0].seriesHover.length / maxRows);
}
for (var j = 0; j < hoverInfo.length; j++) {
var hoverData = hoverInfo[j];
if (angular.isNumber(hoverData.time)) {
var columnsContent = '';
let timestamp = parseInt(hoverData.time);
let date = moment(timestamp).format('YYYY-MM-DD HH:mm:ss');
let dateDiv = $('<div>' + date + '</div>');
dateDiv.css({
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "4px",
fontWeight: "700"
});
content += dateDiv.prop('outerHTML');
var seriesDiv = $('<div></div>');
seriesDiv.css({
display: "flex",
flexDirection: "row"
});
for (var c = 0; c < columns; c++) {
var columnDiv = $('<div></div>');
columnDiv.css({
display: "flex",
flexDirection: "column",
flex: "1"
});
var columnContent = '';
for (var i = c*maxRows; i < (c+1)*maxRows; i++) {
if (i >= hoverData.seriesHover.length) {
break;
}
var seriesHoverInfo = hoverData.seriesHover[i];
columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex);
}
columnDiv.html(columnContent);
if (columnContent) {
if (c > 0) {
columnsContent += '<span style="min-width: 20px;"></span>';
}
columnsContent += columnDiv.prop('outerHTML');
}
}
var seriesHoverInfo = hoverInfo.seriesHover[i];
columnContent += seriesInfoDivFromInfo(seriesHoverInfo, seriesIndex);
}
columnDiv.html(columnContent);
if (c > 0) {
columnsContent += '<span style="width: 20px;"></span>';
seriesDiv.html(columnsContent);
content += seriesDiv.prop('outerHTML');
}
columnsContent += columnDiv.prop('outerHTML');
}
seriesDiv.html(columnsContent);
content += seriesDiv.prop('outerHTML');
}
return content;
};
@ -185,6 +231,7 @@ export default class TbFlot {
ctx.tooltipIndividual = this.chartType === 'pie' || (angular.isDefined(settings.tooltipIndividual) ? settings.tooltipIndividual : false);
ctx.tooltipCumulative = angular.isDefined(settings.tooltipCumulative) ? settings.tooltipCumulative : false;
ctx.hideZeros = angular.isDefined(settings.hideZeros) ? settings.hideZeros : false;
var font = {
color: settings.fontColor || "#545454",
@ -209,7 +256,8 @@ export default class TbFlot {
};
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') {
options.xaxis = {
options.xaxes = [];
this.xaxis = {
mode: 'time',
timezone: 'browser',
font: angular.copy(font),
@ -220,16 +268,11 @@ export default class TbFlot {
labelFont: angular.copy(font)
};
if (settings.xaxis) {
if (settings.xaxis.showLabels === false) {
options.xaxis.tickFormatter = function() {
return '';
};
}
options.xaxis.font.color = settings.xaxis.color || options.xaxis.font.color;
options.xaxis.label = settings.xaxis.title || null;
options.xaxis.labelFont.color = options.xaxis.font.color;
options.xaxis.labelFont.size = options.xaxis.font.size+2;
options.xaxis.labelFont.weight = "bold";
this.xaxis.font.color = settings.xaxis.color || this.xaxis.font.color;
this.xaxis.label = utils.customTranslation(settings.xaxis.title, settings.xaxis.title) || null;
this.xaxis.labelFont.color = this.xaxis.font.color;
this.xaxis.labelFont.size = this.xaxis.font.size+2;
this.xaxis.labelFont.weight = "bold";
}
ctx.yAxisTickFormatter = function(value/*, axis*/) {
@ -263,7 +306,7 @@ export default class TbFlot {
this.yaxis.font.color = settings.yaxis.color || this.yaxis.font.color;
this.yaxis.min = angular.isDefined(settings.yaxis.min) ? settings.yaxis.min : null;
this.yaxis.max = angular.isDefined(settings.yaxis.max) ? settings.yaxis.max : null;
this.yaxis.label = settings.yaxis.title || null;
this.yaxis.label = utils.customTranslation(settings.yaxis.title, settings.yaxis.title) || null;
this.yaxis.labelFont.color = this.yaxis.font.color;
this.yaxis.labelFont.size = this.yaxis.font.size+2;
this.yaxis.labelFont.weight = "bold";
@ -296,7 +339,7 @@ export default class TbFlot {
options.grid.borderWidth = angular.isDefined(settings.grid.outlineWidth) ?
settings.grid.outlineWidth : 1;
if (settings.grid.verticalLines === false) {
options.xaxis.tickLength = 0;
this.xaxis.tickLength = 0;
}
if (settings.grid.horizontalLines === false) {
this.yaxis.tickLength = 0;
@ -309,14 +352,42 @@ export default class TbFlot {
}
}
options.crosshair = {
mode: 'x'
options.xaxes[0] = angular.copy(this.xaxis);
if (settings.xaxis && settings.xaxis.showLabels === false) {
options.xaxes[0].tickFormatter = function() {
return '';
};
}
options.series = {
stack: settings.stack === true
if (settings.comparisonEnabled) {
var xaxis = angular.copy(this.xaxis);
xaxis.position = 'top';
if (settings.xaxisSecond) {
if (settings.xaxisSecond.showLabels === false) {
xaxis.tickFormatter = function() {
return '';
};
}
xaxis.label = utils.customTranslation(settings.xaxisSecond.title, settings.xaxisSecond.title) || null;
xaxis.position = settings.xaxisSecond.axisPosition;
}
xaxis.tickLength = 0;
options.xaxes.push(xaxis);
options.series = {
stack: false
};
} else {
options.series = {
stack: settings.stack === true
};
}
options.crosshair = {
mode: 'x'
};
if (this.chartType === 'line' && settings.smoothLines) {
options.series.curvedLines = {
active: true,
@ -429,6 +500,13 @@ export default class TbFlot {
series.lines = {
fill: keySettings.fillLines === true
};
if (this.ctx.settings.stack && !this.ctx.settings.comparisonEnabled) {
series.stack = !keySettings.excludeFromStacking;
} else {
series.stack = false;
}
if (this.chartType === 'line' || this.chartType === 'state') {
series.lines.show = keySettings.showLines !== false
} else {
@ -445,14 +523,23 @@ export default class TbFlot {
};
if (keySettings.showPoints === true) {
series.points.show = true;
series.points.lineWidth = 5;
series.points.lineWidth = angular.isDefined(keySettings.showPointsLineWidth) ? keySettings.showPointsLineWidth : 5;
series.points.radius = angular.isDefined(keySettings.showPointsRadius) ? keySettings.showPointsRadius : 3;
series.points.symbol = angular.isDefined(keySettings.showPointShape) ? keySettings.showPointShape : 'circle';
if (series.points.symbol == 'custom' && keySettings.pointShapeFormatter) {
try {
series.points.symbol = new Function('ctx, x, y, radius, shadow', keySettings.pointShapeFormatter);
} catch (e) {
series.points.symbol = 'circle';
}
}
}
if (this.chartType === 'line' && this.ctx.settings.smoothLines && !series.points.show) {
series.curvedLines = {
apply: true
}
};
}
var lineColor = tinycolor(series.dataKey.color);
@ -460,6 +547,15 @@ export default class TbFlot {
series.highlightColor = lineColor.toRgbString();
if (series.datasource.isAdditional) {
series.xaxisIndex = 1;
series.xaxis = 2;
} else {
series.xaxisIndex = 0;
series.xaxis = 1;
}
if (this.yaxis) {
var units = series.dataKey.units && series.dataKey.units.length ? series.dataKey.units : this.ctx.trackUnits;
var yaxis;
@ -477,7 +573,7 @@ export default class TbFlot {
series.yaxisIndex = this.yaxes.indexOf(yaxis);
series.yaxis = series.yaxisIndex+1;
yaxis.keysInfo[i] = {hidden: false};
yaxis.hidden = false;
yaxis.show = true;
}
}
@ -491,8 +587,12 @@ export default class TbFlot {
this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
}
}
this.options.xaxis.min = this.subscription.timeWindow.minTime;
this.options.xaxis.max = this.subscription.timeWindow.maxTime;
this.options.xaxes[0].min = this.subscription.timeWindow.minTime;
this.options.xaxes[0].max = this.subscription.timeWindow.maxTime;
if (this.ctx.settings.comparisonEnabled) {
this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime;
this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime;
}
}
this.checkMouseEvents();
@ -500,6 +600,7 @@ export default class TbFlot {
if (this.ctx.plot) {
this.ctx.plot.destroy();
}
if (this.chartType === 'pie' && this.ctx.animatedPie) {
this.ctx.pieDataAnimationDuration = 250;
this.pieData = angular.copy(this.subscription.data);
@ -608,8 +709,12 @@ export default class TbFlot {
}
}
this.options.xaxis.min = this.subscription.timeWindow.minTime;
this.options.xaxis.max = this.subscription.timeWindow.maxTime;
this.options.xaxes[0].min = this.subscription.timeWindow.minTime;
this.options.xaxes[0].max = this.subscription.timeWindow.maxTime;
if (this.ctx.settings.comparisonEnabled) {
this.options.xaxes[1].min = this.subscription.comparisonTimeWindow.minTime;
this.options.xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime;
}
if (this.chartType === 'bar') {
if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') {
this.options.series.bars.barWidth = this.ctx.defaultBarWidth;
@ -623,6 +728,10 @@ export default class TbFlot {
} else {
this.ctx.plot.getOptions().xaxes[0].min = this.subscription.timeWindow.minTime;
this.ctx.plot.getOptions().xaxes[0].max = this.subscription.timeWindow.maxTime;
if (this.ctx.settings.comparisonEnabled) {
this.ctx.plot.getOptions().xaxes[1].min = this.subscription.comparisonTimeWindow.minTime;
this.ctx.plot.getOptions().xaxes[1].max = this.subscription.comparisonTimeWindow.maxTime;
}
if (this.chartType === 'bar') {
if (this.subscription.timeWindowConfig.aggregation && this.subscription.timeWindowConfig.aggregation.type === 'NONE') {
this.ctx.plot.getOptions().series.bars.barWidth = this.ctx.defaultBarWidth;
@ -902,6 +1011,11 @@ export default class TbFlot {
"type": "string",
"default": ""
};
properties["hideZeros"] = {
"title": "Hide zero/false values from tooltip",
"type": "boolean",
"default": false
};
properties["grid"] = {
"title": "Grid settings",
@ -1029,6 +1143,7 @@ export default class TbFlot {
"key": "tooltipValueFormatter",
"type": "javascript"
});
schema["form"].push("hideZeros");
schema["form"].push({
"key": "grid",
"items": [
@ -1079,6 +1194,21 @@ export default class TbFlot {
}
]
});
if (chartType === 'graph' || chartType === 'bar') {
schema.groupInfoes = [{
"formIndex":0,
"GroupTitle":"Common Settings"
}];
schema.form = [schema.form];
angular.merge(schema.schema.properties, chartSettingsSchemaForComparison.schema.properties);
schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required);
schema.form.push(chartSettingsSchemaForComparison.form);
schema.groupInfoes.push({
"formIndex":schema.groupInfoes.length,
"GroupTitle":"Comparison Settings"
});
}
return schema;
}
@ -1086,12 +1216,18 @@ export default class TbFlot {
return {}
}
static datakeySettingsSchema(defaultShowLines) {
return {
static datakeySettingsSchema(defaultShowLines, chartType) {
var schema = {
"schema": {
"type": "object",
"title": "DataKeySettings",
"properties": {
"excludeFromStacking": {
"title": "Exclude from stacking(available in \"Stacking\" mode)",
"type": "boolean",
"default": false
},
"showLines": {
"title": "Show lines",
"type": "boolean",
@ -1107,6 +1243,25 @@ export default class TbFlot {
"type": "boolean",
"default": false
},
"showPointShape": {
"title": "Select point shape:",
"type": "string",
"default": "circle"
},
"pointShapeFormatter": {
"title": "Point shape format function, f(ctx, x, y, radius, shadow)",
"type": "string",
"default": "var size = radius * Math.sqrt(Math.PI) / 2;\n" +
"ctx.moveTo(x - size, y - size);\n" +
"ctx.lineTo(x + size, y + size);\n" +
"ctx.moveTo(x - size, y + size);\n" +
"ctx.lineTo(x + size, y - size);"
},
"showPointsLineWidth": {
"title": "Line width of points",
"type": "number",
"default": 5
},
"showPointsRadius": {
"title": "Radius of points",
"type": "number",
@ -1161,9 +1316,46 @@ export default class TbFlot {
"required": ["showLines", "fillLines", "showPoints"]
},
"form": [
"excludeFromStacking",
"showLines",
"fillLines",
"showPoints",
{
"key": "showPointShape",
"type": "rc-select",
"multiple": false,
"items": [
{
"value": "circle",
"label": "Circle"
},
{
"value": "cross",
"label": "Cross"
},
{
"value": "diamond",
"label": "Diamond"
},
{
"value": "square",
"label": "Square"
},
{
"value": "triangle",
"label": "Triangle"
},
{
"value": "custom",
"label": "Custom function"
}
]
},
{
"key": "pointShapeFormatter",
"type": "javascript"
},
"showPointsLineWidth",
"showPointsRadius",
{
"key": "tooltipValueFormatter",
@ -1195,7 +1387,47 @@ export default class TbFlot {
"type": "javascript"
}
]
};
var properties = schema["schema"]["properties"];
if (chartType === 'graph' || chartType === 'bar') {
properties["comparisonSettings"] = {
"title": "Comparison Settings",
"type": "object",
"properties": {
"showValuesForComparison": {
"title": "Show historical values for comparison",
"type": "boolean",
"default": true
},
"comparisonValuesLabel": {
"title": "Historical values label",
"type": "string",
"default": ""
},
"color": {
"title": "Color",
"type": "string",
"default": ""
}
},
"required": ["showValuesForComparison"]
};
schema["form"].push({
"key": "comparisonSettings",
"items": [
"comparisonSettings.showValuesForComparison",
"comparisonSettings.comparisonValuesLabel",
{
"key": "comparisonSettings.color",
"type": "color"
}
]
});
}
return schema;
}
enableMouseEvents() {
@ -1227,10 +1459,15 @@ export default class TbFlot {
tooltipHtml = tbFlot.ctx.tooltipFormatter(item);
} else {
var hoverInfo = tbFlot.getHoverInfo(tbFlot.ctx.plot.getData(), pos);
if (angular.isNumber(hoverInfo.time)) {
hoverInfo.seriesHover.sort(function (a, b) {
if (angular.isNumber(hoverInfo[0].time) || (hoverInfo[1] && angular.isNumber(hoverInfo[1].time))) {
hoverInfo[0].seriesHover.sort(function (a, b) {
return b.value - a.value;
});
if (hoverInfo[1] && hoverInfo[1].seriesHover.length) {
hoverInfo[1].seriesHover.sort(function (a, b) {
return b.value - a.value;
});
}
tooltipHtml = tbFlot.ctx.tooltipFormatter(hoverInfo, item ? item.seriesIndex : -1);
}
}
@ -1258,9 +1495,11 @@ export default class TbFlot {
});
if (multipleModeTooltip) {
for (var i = 0; i < hoverInfo.seriesHover.length; i++) {
var seriesHoverInfo = hoverInfo.seriesHover[i];
tbFlot.ctx.plot.highlight(seriesHoverInfo.index, seriesHoverInfo.hoverIndex);
for (var j = 0; j < hoverInfo.length; j++) {
for (var i = 0; i < hoverInfo[j].seriesHover.length; i++) {
var seriesHoverInfo = hoverInfo[j].seriesHover[i];
tbFlot.ctx.plot.highlight(seriesHoverInfo.index, seriesHoverInfo.hoverIndex);
}
}
}
}
@ -1399,19 +1638,38 @@ export default class TbFlot {
getHoverInfo (seriesList, pos) {
var i, series, value, hoverIndex, hoverDistance, pointTime, minDistance, minTime;
var i, series, value, hoverIndex, hoverDistance, pointTime, minDistance, minTime, hoverData;
var last_value = 0;
var results = {
var results = [{
seriesHover: []
};
}];
if (this.ctx.settings.comparisonEnabled) {
results.push({
seriesHover: []
});
var minDistanceHistorical, minTimeHistorical;
}
for (i = 0; i < seriesList.length; i++) {
series = seriesList[i];
hoverIndex = this.findHoverIndexFromData(pos.x, series);
var posx;
if (series.datasource.isAdditional) {
posx = pos.x2;
} else {
posx = pos.x;
}
hoverIndex = this.findHoverIndexFromData(posx, series);
if (series.data[hoverIndex] && series.data[hoverIndex][0]) {
hoverDistance = pos.x - series.data[hoverIndex][0];
hoverDistance = posx - series.data[hoverIndex][0];
pointTime = series.data[hoverIndex][0];
if (!minDistance
if (series.datasource.isAdditional) {
if (!minDistanceHistorical
|| (hoverDistance >= 0 && (hoverDistance < minDistanceHistorical || minDistanceHistorical < 0))
|| (hoverDistance < 0 && hoverDistance > minDistanceHistorical)) {
minDistanceHistorical = hoverDistance;
minTimeHistorical = pointTime;
}
} else if (!minDistance
|| (hoverDistance >= 0 && (hoverDistance < minDistance || minDistance < 0))
|| (hoverDistance < 0 && hoverDistance > minDistance)) {
minDistance = hoverDistance;
@ -1429,23 +1687,33 @@ export default class TbFlot {
}
if (series.stack || (series.curvedLines && series.curvedLines.apply)) {
hoverIndex = this.findHoverIndexFromDataPoints(pos.x, series, hoverIndex);
hoverIndex = this.findHoverIndexFromDataPoints(posx, series, hoverIndex);
}
if (!this.ctx.hideZeros || value) {
hoverData = {
value: value,
hoverIndex: hoverIndex,
color: series.dataKey.color,
label: series.dataKey.label,
units: series.dataKey.units,
decimals: series.dataKey.decimals,
tooltipValueFormatFunction: series.dataKey.tooltipValueFormatFunction,
time: pointTime,
distance: hoverDistance,
index: i
};
if (series.datasource.isAdditional) {
results[1].seriesHover.push(hoverData);
} else {
results[0].seriesHover.push(hoverData);
}
}
results.seriesHover.push({
value: value,
hoverIndex: hoverIndex,
color: series.dataKey.color,
label: series.dataKey.label,
units: series.dataKey.units,
decimals: series.dataKey.decimals,
tooltipValueFormatFunction: series.dataKey.tooltipValueFormatFunction,
time: pointTime,
distance: hoverDistance,
index: i
});
}
}
results.time = minTime;
if (results[1] && results[1].seriesHover.length) {
results[1].time = minTimeHistorical;
}
results[0].time = minTime;
return results;
}
@ -1524,4 +1792,93 @@ export default class TbFlot {
}
}
const chartSettingsSchemaForComparison = {
"schema": {
"title": "Comparison Settings",
"type": "object",
"properties": {
"comparisonEnabled": {
"title": "Enable comparison",
"type": "boolean",
"default": false
},
"timeForComparison": {
"title": "Time to show historical data",
"type": "string",
"default": "months"
},
"xaxisSecond": {
"title": "Second X axis",
"type": "object",
"properties": {
"axisPosition": {
"title": "Axis position",
"type": "string",
"default": "top"
},
"showLabels": {
"title": "Show labels",
"type": "boolean",
"default": true
},
"title": {
"title": "Axis title",
"type": "string",
"default": null
}
}
}
},
"required": []
},
"form": [
"comparisonEnabled",
{
"key": "timeForComparison",
"type": "rc-select",
"multiple": false,
"items": [
{
"value": "days",
"label": "Day ago"
},
{
"value": "weeks",
"label": "Week ago"
},
{
"value": "months",
"label": "Month ago (default)"
},
{
"value": "years",
"label": "Year ago"
}
]
},
{
"key": "xaxisSecond",
"items": [
{
"key": "xaxisSecond.axisPosition",
"type": "rc-select",
"multiple": false,
"items": [
{
"value": "top",
"label": "Top (default)"
},
{
"value": "bottom",
"label": "Bottom"
}
]
},
"xaxisSecond.showLabels",
"xaxisSecond.title",
]
}
]
};
/* eslint-enable angular/angularelement */

Loading…
Cancel
Save