Browse Source

UI: Add settings forms for flot chart widgets.

pull/6545/head
Igor Kulikov 5 years ago
parent
commit
83da5520fc
  1. 9
      application/src/main/data/json/system/widget_bundles/charts.json
  2. 3
      ui-ngx/.editorconfig
  3. 4
      ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts
  4. 23
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.html
  5. 55
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts
  6. 23
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.html
  7. 55
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts
  8. 327
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html
  9. 411
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts
  10. 63
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html
  11. 40
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.scss
  12. 132
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts
  13. 24
      ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts
  14. 8
      ui-ngx/src/app/shared/models/widget.models.ts
  15. 498
      ui-ngx/src/assets/locale/locale.constant-en_US.json

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

@ -146,9 +146,10 @@
"resources": [], "resources": [],
"templateHtml": "", "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", "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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n hasAdditionalLatestDataKeys: true\n };\n}\n\nself.onEditModeChanged = 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.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true,\n hasAdditionalLatestDataKeys: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}", "dataKeySettingsSchema": "{}",
"settingsDirective": "tb-flot-line-widget-settings",
"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\":{\"direction\":\"column\",\",position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}" "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\":{\"direction\":\"column\",\",position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}"
} }
}, },
@ -164,10 +165,11 @@
"resources": [], "resources": [],
"templateHtml": "", "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", "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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = 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.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasAdditionalLatestDataKeys: true\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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true, 'graph');\n}\n\nself.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasAdditionalLatestDataKeys: true\n };\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}", "dataKeySettingsSchema": "{}",
"latestDataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}",
"settingsDirective": "tb-flot-line-widget-settings",
"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 Line Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}" "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 Line Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}"
} }
}, },
@ -183,9 +185,10 @@
"resources": [], "resources": [],
"templateHtml": "", "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", "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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = 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.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasAdditionalLatestDataKeys: true\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.onLatestDataUpdated = function() {\n self.ctx.flot.latestDataUpdate();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(false, 'bar');\n}\n\nself.getLatestDataKeySettingsSchema = function() {\n return TbFlot.latestDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasAdditionalLatestDataKeys: true\n };\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}", "dataKeySettingsSchema": "{}",
"settingsDirective": "tb-flot-bar-widget-settings",
"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 Bar Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{}}" "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 Bar Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{}}"
} }
} }

3
ui-ngx/.editorconfig

@ -24,6 +24,9 @@ indent_size = 2
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.json]
indent_size = 4
[*.md] [*.md]
max_line_length = off max_line_length = off
trim_trailing_whitespace = false trim_trailing_whitespace = false

4
ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts

@ -100,8 +100,8 @@ export interface TbFlotGridSettings {
outlineWidth: number; outlineWidth: number;
verticalLines: boolean; verticalLines: boolean;
horizontalLines: boolean; horizontalLines: boolean;
minBorderMargin: number; minBorderMargin?: number;
margin: number; margin?: number;
} }
export interface TbFlotXAxisSettings { export interface TbFlotXAxisSettings {

23
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.html

@ -0,0 +1,23 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section [formGroup]="flotBarWidgetSettingsForm" fxLayout="column">
<tb-flot-widget-settings formControlName="flotSettings"
[chartType]="'bar'">
</tb-flot-widget-settings>
</section>

55
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.ts

@ -0,0 +1,55 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { flotDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-widget-settings.component';
@Component({
selector: 'tb-flot-bar-widget-settings',
templateUrl: './flot-bar-widget-settings.component.html',
styleUrls: []
})
export class FlotBarWidgetSettingsComponent extends WidgetSettingsComponent {
flotBarWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.flotBarWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return flotDefaultSettings('bar');
}
protected onSettingsSet(settings: WidgetSettings) {
this.flotBarWidgetSettingsForm = this.fb.group({
flotSettings: [settings, []]
});
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return settings.flotSettings;
}
}

23
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.html

@ -0,0 +1,23 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section [formGroup]="flotLineWidgetSettingsForm" fxLayout="column">
<tb-flot-widget-settings formControlName="flotSettings"
[chartType]="'graph'">
</tb-flot-widget-settings>
</section>

55
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-line-widget-settings.component.ts

@ -0,0 +1,55 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component } from '@angular/core';
import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { flotDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-widget-settings.component';
@Component({
selector: 'tb-flot-line-widget-settings',
templateUrl: './flot-line-widget-settings.component.html',
styleUrls: []
})
export class FlotLineWidgetSettingsComponent extends WidgetSettingsComponent {
flotLineWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.flotLineWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return flotDefaultSettings('graph');
}
protected onSettingsSet(settings: WidgetSettings) {
this.flotLineWidgetSettingsForm = this.fb.group({
flotSettings: [settings, []]
});
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return settings.flotSettings;
}
}

327
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.html

@ -0,0 +1,327 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<section class="tb-widget-settings" [formGroup]="flotSettingsFormGroup" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.chart.common-settings</legend>
<mat-checkbox formControlName="stack" style="margin-bottom: 16px;">
{{ 'widgets.chart.enable-stacking-mode' | translate }}
</mat-checkbox>
<section *ngIf="chartType === 'graph'" fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.line-shadow-size</mat-label>
<input matInput type="number" min="0" formControlName="shadowSize">
</mat-form-field>
<mat-checkbox fxFlex formControlName="smoothLines" style="margin-bottom: 16px;">
{{ 'widgets.chart.display-smooth-lines' | translate }}
</mat-checkbox>
</section>
<section *ngIf="chartType === 'bar'" fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.default-bar-width</mat-label>
<input matInput type="number" min="0" formControlName="defaultBarWidth">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.bar-alignment</mat-label>
<mat-select formControlName="barAlignment">
<mat-option [value]="'left'">
{{ 'widgets.chart.bar-alignment-left' | translate }}
</mat-option>
<mat-option [value]="'right'">
{{ 'widgets.chart.bar-alignment-right' | translate }}
</mat-option>
<mat-option [value]="'center'">
{{ 'widgets.chart.bar-alignment-center' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.default-font-size</mat-label>
<input matInput type="number" min="0" formControlName="fontSize">
</mat-form-field>
<tb-color-input fxFlex
formControlName="fontColor"
label="{{ 'widgets.chart.default-font-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</section>
<mat-form-field *ngIf="chartType === 'graph' || chartType === 'bar'" fxFlex class="mat-block">
<mat-label translate>widgets.chart.thresholds-line-width</mat-label>
<input matInput type="number" min="0" formControlName="thresholdsLineWidth">
</mat-form-field>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.tooltip-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('showTooltip').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showTooltip" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.show-tooltip' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<section fxLayout="column">
<mat-slide-toggle formControlName="tooltipIndividual" class="slide-block">
{{ 'widgets.chart.hover-individual-points' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="tooltipCumulative" class="slide-block">
{{ 'widgets.chart.show-cumulative-values' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="hideZeros" class="slide-block">
{{ 'widgets.chart.hide-zero-false-values' | translate }}
</mat-slide-toggle>
<tb-js-func
formControlName="tooltipValueFormatter"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value']"
functionTitle="{{ 'widgets.chart.tooltip-value-format-function' | translate }}"
helpId="widget/lib/flot/tooltip_value_format_fn">
</tb-js-func>
</section>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset class="fields-group" formGroupName="grid">
<legend class="group-title" translate>widgets.chart.grid-settings</legend>
<mat-checkbox formControlName="verticalLines" style="margin-bottom: 16px;">
{{ 'widgets.chart.show-vertical-lines' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="horizontalLines" style="margin-bottom: 16px;">
{{ 'widgets.chart.show-horizontal-lines' | translate }}
</mat-checkbox>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.grid-outline-border-width</mat-label>
<input matInput type="number" min="0" formControlName="outlineWidth">
</mat-form-field>
<tb-color-input fxFlex
formControlName="color"
label="{{ 'widgets.chart.primary-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<tb-color-input fxFlex
formControlName="backgroundColor"
label="{{ 'widgets.chart.background-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<tb-color-input fxFlex
formControlName="tickColor"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</fieldset>
<fieldset class="fields-group" formGroupName="xaxis">
<legend class="group-title" translate>widgets.chart.xaxis-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-title</mat-label>
<input matInput formControlName="title">
</mat-form-field>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.xaxis-tick-labels-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('xaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-color-input fxFlex
formControlName="color"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</ng-template>
</mat-expansion-panel>
</fieldset>
</fieldset>
<fieldset class="fields-group" formGroupName="yaxis">
<legend class="group-title" translate>widgets.chart.yaxis-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-title</mat-label>
<input matInput formControlName="title">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.min-scale-value</mat-label>
<input matInput type="number" formControlName="min">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.max-scale-value</mat-label>
<input matInput type="number" formControlName="max">
</mat-form-field>
</section>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.yaxis-tick-labels-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('yaxis.showLabels').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="showLabels" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-color-input fxFlex
formControlName="color"
label="{{ 'widgets.chart.ticks-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.tick-step-size</mat-label>
<input matInput type="number" formControlName="tickSize">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.number-of-decimals</mat-label>
<input matInput type="number" min="0" formControlName="tickDecimals">
</mat-form-field>
</section>
<tb-js-func
formControlName="ticksFormatter"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value']"
functionTitle="{{ 'widgets.chart.ticks-formatter-function' | translate }}"
helpId="widget/lib/flot/ticks_formatter_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</fieldset>
<fieldset *ngIf="chartType === 'graph' || chartType === 'bar'" class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.comparison-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('comparisonEnabled').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="comparisonEnabled" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.enable-comparison' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<section fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.time-for-comparison</mat-label>
<mat-select formControlName="timeForComparison">
<mat-option [value]="'previousInterval'">
{{ 'widgets.chart.time-for-comparison-previous-interval' | translate }}
</mat-option>
<mat-option [value]="'days'">
{{ 'widgets.chart.time-for-comparison-days' | translate }}
</mat-option>
<mat-option [value]="'weeks'">
{{ 'widgets.chart.time-for-comparison-weeks' | translate }}
</mat-option>
<mat-option [value]="'months'">
{{ 'widgets.chart.time-for-comparison-months' | translate }}
</mat-option>
<mat-option [value]="'years'">
{{ 'widgets.chart.time-for-comparison-years' | translate }}
</mat-option>
<mat-option [value]="'customInterval'">
{{ 'widgets.chart.time-for-comparison-custom-interval' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field [fxShow]="flotSettingsFormGroup.get('timeForComparison').value === 'customInterval'" fxFlex class="mat-block">
<mat-label translate>widgets.chart.custom-interval-value</mat-label>
<input matInput type="number" min="0" formControlName="comparisonCustomIntervalValue">
</mat-form-field>
<fieldset class="fields-group" formGroupName="xaxisSecond">
<legend class="group-title" translate>widgets.chart.comparison-x-axis-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-title</mat-label>
<input matInput formControlName="title">
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.axis-position</mat-label>
<mat-select formControlName="axisPosition">
<mat-option [value]="'top'">
{{ 'widgets.chart.axis-position-top' | translate }}
</mat-option>
<mat-option [value]="'bottom'">
{{ 'widgets.chart.axis-position-bottom' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-slide-toggle formControlName="showLabels" class="slide-block">
{{ 'widgets.chart.show-tick-labels' | translate }}
</mat-slide-toggle>
</fieldset>
</section>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset *ngIf="chartType === 'graph' || chartType === 'bar'" class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.chart.custom-legend-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="flotSettingsFormGroup.get('customLegendEnabled').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="customLegendEnabled" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.enable-custom-legend' | translate }}
</mat-slide-toggle>
</mat-panel-title>
<mat-panel-description fxLayoutAlign="end center" fxHide.xs translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<fieldset [fxShow]="flotSettingsFormGroup.get('customLegendEnabled').value" class="fields-group">
<legend class="group-title" translate>widgets.chart.label-keys-list</legend>
<div fxLayout="column">
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
(cdkDropListDropped)="labelDataKeyDrop($event)">
<div cdkDrag class="tb-draggable" *ngFor="let labelDataKeyControl of dataKeysListForLabelsFormArray().controls; trackBy: trackByLabelDataKey;
let $index = index; last as isLast;"
fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}">
<tb-label-data-key [formControl]="labelDataKeyControl"
[expanded]="labelDataKeyControl.new"
(removeLabelDataKey)="removeLabelDataKey($index)">
</tb-label-data-key>
</div>
</div>
<div *ngIf="!dataKeysListForLabelsFormArray().controls.length">
<span translate fxLayoutAlign="center center"
class="tb-prompt">widgets.chart.no-label-keys</span>
</div>
<div style="padding-top: 16px;">
<button mat-raised-button color="primary"
type="button"
(click)="addLabelDataKey()">
<span translate>widgets.chart.add-label-key</span>
</button>
</div>
</div>
</fieldset>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

411
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-widget-settings.component.ts

@ -0,0 +1,411 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
FormArray,
FormBuilder,
FormControl,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator,
Validators
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { ChartType, TbFlotSettings } from '@home/components/widget/lib/flot-widget.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { ComparisonDuration } from '@shared/models/time/time.models';
import { WidgetService } from '@core/http/widget.service';
import { fixedColorLevelValidator } from '@home/components/widget/lib/settings/gauge/fixed-color-level.component';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import {
LabelDataKey,
labelDataKeyValidator
} from '@home/components/widget/lib/settings/chart/label-data-key.component';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
export function flotDefaultSettings(chartType: ChartType): Partial<TbFlotSettings> {
const settings: Partial<TbFlotSettings> = {
stack: false,
fontColor: '#545454',
fontSize: 10,
showTooltip: true,
tooltipIndividual: false,
tooltipCumulative: false,
hideZeros: false,
tooltipValueFormatter: '',
grid: {
verticalLines: true,
horizontalLines: true,
outlineWidth: 1,
color: '#545454',
backgroundColor: null,
tickColor: '#DDDDDD'
},
xaxis: {
title: null,
showLabels: true,
color: null
},
yaxis: {
min: null,
max: null,
title: null,
showLabels: true,
color: null,
tickSize: null,
tickDecimals: 0,
ticksFormatter: ''
}
};
if (chartType === 'graph') {
settings.smoothLines = false;
settings.shadowSize = 4;
}
if (chartType === 'bar') {
settings.defaultBarWidth = 600;
settings.barAlignment = 'left';
}
if (chartType === 'graph' || chartType === 'bar') {
settings.thresholdsLineWidth = null;
settings.comparisonEnabled = false;
settings.timeForComparison = 'previousInterval';
settings.comparisonCustomIntervalValue = 7200000;
settings.xaxisSecond = {
title: null,
axisPosition: 'top',
showLabels: true
};
settings.customLegendEnabled = false;
settings.dataKeysListForLabels = [];
}
return settings;
}
@Component({
selector: 'tb-flot-widget-settings',
templateUrl: './flot-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FlotWidgetSettingsComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => FlotWidgetSettingsComponent),
multi: true,
}
]
})
export class FlotWidgetSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator {
@Input()
disabled: boolean;
@Input()
chartType: ChartType;
functionScopeVariables = this.widgetService.getWidgetScopeVariables();
private modelValue: TbFlotSettings;
private propagateChange = null;
public flotSettingsFormGroup: FormGroup;
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private widgetService: WidgetService,
private fb: FormBuilder) {
super(store);
}
ngOnInit(): void {
this.flotSettingsFormGroup = this.fb.group({
// Common settings
stack: [false, []],
fontSize: [10, [Validators.min(0)]],
fontColor: ['#545454', []],
// Tooltip settings
showTooltip: [true, []],
tooltipIndividual: [false, []],
tooltipCumulative: [false, []],
hideZeros: [false, []],
tooltipValueFormatter: ['', []],
// Grid settings
grid: this.fb.group({
verticalLines: [true, []],
horizontalLines: [true, []],
outlineWidth: [1, [Validators.min(0)]],
color: ['#545454', []],
backgroundColor: [null, []],
tickColor: ['#DDDDDD', []]
}),
// X axis settings
xaxis: this.fb.group({
title: [null, []],
// --> X axis tick labels settings
showLabels: [true, []],
color: [null, []],
}),
// Y axis settings
yaxis: this.fb.group({
min: [null, []],
max: [null, []],
title: [null, []],
// --> Y axis tick labels settings
showLabels: [true, []],
color: [null, []],
tickSize: [null, [Validators.min(0)]],
tickDecimals: [0, [Validators.min(0)]],
ticksFormatter: ['', []]
})
});
if (this.chartType === 'graph') {
// Common settings
this.flotSettingsFormGroup.addControl('shadowSize', this.fb.control(4, [Validators.min(0)]));
this.flotSettingsFormGroup.addControl('smoothLines', this.fb.control(false, []));
} else if (this.chartType === 'bar') {
// Common settings
this.flotSettingsFormGroup.addControl('defaultBarWidth', this.fb.control(600, [Validators.min(0)]));
this.flotSettingsFormGroup.addControl('barAlignment', this.fb.control('left', []));
}
if (this.chartType === 'graph' || this.chartType === 'bar') {
// Common settings
this.flotSettingsFormGroup.addControl('thresholdsLineWidth', this.fb.control(null, [Validators.min(0)]));
// Comparison settings
this.flotSettingsFormGroup.addControl('comparisonEnabled', this.fb.control(false, []));
this.flotSettingsFormGroup.addControl('timeForComparison', this.fb.control('previousInterval', []));
this.flotSettingsFormGroup.addControl('comparisonCustomIntervalValue', this.fb.control(7200000, [Validators.min(0)]));
// --> Comparison X axis settings
this.flotSettingsFormGroup.addControl('xaxisSecond', this.fb.group({
axisPosition: ['top', []],
title: [null, []],
showLabels: [true, []]
}));
// Custom legend settings
this.flotSettingsFormGroup.addControl('customLegendEnabled', this.fb.control(false, []));
this.flotSettingsFormGroup.addControl('dataKeysListForLabels', this.fb.control(this.fb.array([]), []));
}
this.flotSettingsFormGroup.get('showTooltip').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.flotSettingsFormGroup.get('xaxis.showLabels').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.flotSettingsFormGroup.get('yaxis.showLabels').valueChanges.subscribe(() => {
this.updateValidators(true);
});
if (this.chartType === 'graph' || this.chartType === 'bar') {
this.flotSettingsFormGroup.get('comparisonEnabled').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.flotSettingsFormGroup.get('timeForComparison').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.flotSettingsFormGroup.get('customLegendEnabled').valueChanges.subscribe(() => {
this.updateValidators(true);
});
}
this.flotSettingsFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateValidators(false);
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
this.flotSettingsFormGroup.disable({emitEvent: false});
} else {
this.flotSettingsFormGroup.enable({emitEvent: false});
}
}
writeValue(value: TbFlotSettings): void {
const dataKeysListForLabels = value?.dataKeysListForLabels;
this.modelValue = value;
this.flotSettingsFormGroup.patchValue(
value, {emitEvent: false}
);
const dataKeysListForLabelsControls: Array<AbstractControl> = [];
if (dataKeysListForLabels && dataKeysListForLabels.length) {
dataKeysListForLabels.forEach((labelDataKey) => {
dataKeysListForLabelsControls.push(this.fb.control(labelDataKey, [labelDataKeyValidator]));
});
}
this.flotSettingsFormGroup.setControl('dataKeysListForLabels', this.fb.array(dataKeysListForLabelsControls), {emitEvent: false});
this.updateValidators(false);
}
validate(c: FormControl) {
return (this.flotSettingsFormGroup.valid) ? null : {
flotSettings: {
valid: false,
},
};
}
private updateModel() {
const value: TbFlotSettings = this.flotSettingsFormGroup.value;
this.modelValue = value;
this.propagateChange(this.modelValue);
}
private updateValidators(emitEvent?: boolean): void {
const showTooltip: boolean = this.flotSettingsFormGroup.get('showTooltip').value;
const xaxisShowLabels: boolean = this.flotSettingsFormGroup.get('xaxis.showLabels').value;
const yaxisShowLabels: boolean = this.flotSettingsFormGroup.get('yaxis.showLabels').value;
if (showTooltip) {
this.flotSettingsFormGroup.get('tooltipIndividual').enable({emitEvent});
this.flotSettingsFormGroup.get('tooltipCumulative').enable({emitEvent});
this.flotSettingsFormGroup.get('hideZeros').enable({emitEvent});
this.flotSettingsFormGroup.get('tooltipValueFormatter').enable({emitEvent});
} else {
this.flotSettingsFormGroup.get('tooltipIndividual').disable({emitEvent});
this.flotSettingsFormGroup.get('tooltipCumulative').disable({emitEvent});
this.flotSettingsFormGroup.get('hideZeros').disable({emitEvent});
this.flotSettingsFormGroup.get('tooltipValueFormatter').disable({emitEvent});
}
if (xaxisShowLabels) {
this.flotSettingsFormGroup.get('xaxis.color').enable({emitEvent});
} else {
this.flotSettingsFormGroup.get('xaxis.color').disable({emitEvent});
}
if (yaxisShowLabels) {
this.flotSettingsFormGroup.get('yaxis.color').enable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.tickSize').enable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.tickDecimals').enable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.ticksFormatter').enable({emitEvent});
} else {
this.flotSettingsFormGroup.get('yaxis.color').disable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.tickSize').disable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.tickDecimals').disable({emitEvent});
this.flotSettingsFormGroup.get('yaxis.ticksFormatter').disable({emitEvent});
}
this.flotSettingsFormGroup.get('tooltipIndividual').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('tooltipCumulative').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('hideZeros').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('tooltipValueFormatter').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('xaxis.color').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('yaxis.color').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('yaxis.tickSize').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('yaxis.tickDecimals').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('yaxis.ticksFormatter').updateValueAndValidity({emitEvent: false});
if (this.chartType === 'graph' || this.chartType === 'bar') {
const comparisonEnabled: boolean = this.flotSettingsFormGroup.get('comparisonEnabled').value;
const timeForComparison: ComparisonDuration = this.flotSettingsFormGroup.get('timeForComparison').value;
const customLegendEnabled: boolean = this.flotSettingsFormGroup.get('customLegendEnabled').value;
if (comparisonEnabled) {
this.flotSettingsFormGroup.get('timeForComparison').enable({emitEvent: false});
if (timeForComparison === 'customInterval') {
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').enable({emitEvent});
} else {
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent});
}
} else {
this.flotSettingsFormGroup.get('timeForComparison').disable({emitEvent: false});
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').disable({emitEvent});
}
if (customLegendEnabled) {
this.flotSettingsFormGroup.get('dataKeysListForLabels').enable({emitEvent});
} else {
this.flotSettingsFormGroup.get('dataKeysListForLabels').disable({emitEvent});
}
this.flotSettingsFormGroup.get('timeForComparison').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('comparisonCustomIntervalValue').updateValueAndValidity({emitEvent: false});
this.flotSettingsFormGroup.get('dataKeysListForLabels').updateValueAndValidity({emitEvent: false});
}
}
dataKeysListForLabelsFormArray(): FormArray {
return this.flotSettingsFormGroup.get('dataKeysListForLabels') as FormArray;
}
public trackByLabelDataKey(index: number, labelDataKeyControl: AbstractControl): any {
return labelDataKeyControl;
}
public removeLabelDataKey(index: number) {
(this.flotSettingsFormGroup.get('dataKeysListForLabels') as FormArray).removeAt(index);
}
public addLabelDataKey() {
const labelDataKey: LabelDataKey = {
name: null,
type: DataKeyType.attribute
};
const dataKeysListForLabelsArray = this.flotSettingsFormGroup.get('dataKeysListForLabels') as FormArray;
const labelDataKeyControl = this.fb.control(labelDataKey, [labelDataKeyValidator]);
(labelDataKeyControl as any).new = true;
dataKeysListForLabelsArray.push(labelDataKeyControl);
this.flotSettingsFormGroup.updateValueAndValidity();
}
labelDataKeyDrop(event: CdkDragDrop<string[]>) {
const dataKeysListForLabelsArray = this.flotSettingsFormGroup.get('dataKeysListForLabels') as FormArray;
const labelDataKey = dataKeysListForLabelsArray.at(event.previousIndex);
dataKeysListForLabelsArray.removeAt(event.previousIndex);
dataKeysListForLabelsArray.insert(event.currentIndex, labelDataKey);
}
}

63
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.html

@ -0,0 +1,63 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<mat-expansion-panel class="label-data-key" fxFlex [formGroup]="labelDataKeyFormGroup" [(expanded)]="expanded">
<mat-expansion-panel-header>
<div fxFlex fxLayout="row" fxLayoutAlign="start center">
<mat-panel-title>
<div fxLayout="row" fxFlex fxLayoutAlign="start center">
{{ labelDataKeyText() }}
</div>
</mat-panel-title>
<span fxFlex></span>
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;"
type="button"
(click)="removeLabelDataKey.emit()"
matTooltip="{{ 'action.remove' | translate }}"
matTooltipPosition="above">
<mat-icon>delete</mat-icon>
</button>
</div>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<div fxLayout="column" fxLayoutGap="0.5em">
<mat-divider></mat-divider>
<section class="tb-widget-settings" fxLayout="column">
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.key-name</mat-label>
<input required matInput formControlName="name">
<mat-error *ngIf="labelDataKeyFormGroup.get('name').hasError('required')">
{{ 'widgets.chart.key-name-required' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.key-type</mat-label>
<mat-select formControlName="type">
<mat-option [value]="'attribute'">
{{ 'widgets.chart.key-type-attribute' | translate }}
</mat-option>
<mat-option [value]="'timeseries'">
{{ 'widgets.chart.key-type-timeseries' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>
</section>
</div>
</ng-template>
</mat-expansion-panel>

40
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.scss

@ -0,0 +1,40 @@
/**
* Copyright © 2016-2022 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
:host {
display: block;
.mat-expansion-panel {
box-shadow: none;
&.label-data-key {
border: 1px groove rgba(0, 0, 0, .25);
.mat-expansion-panel-header {
padding: 0 24px 0 8px;
&.mat-expanded {
height: 48px;
}
}
}
}
}
:host ::ng-deep {
.mat-expansion-panel {
&.label-data-key {
.mat-expansion-panel-body {
padding: 0 8px 8px;
}
}
}
}

132
ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/label-data-key.component.ts

@ -0,0 +1,132 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALUE_ACCESSOR, ValidationErrors,
Validators
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
export interface LabelDataKey {
name: string;
type: DataKeyType;
}
export function labelDataKeyValidator(control: AbstractControl): ValidationErrors | null {
const labelDataKey: LabelDataKey = control.value;
if (!labelDataKey || !labelDataKey.name) {
return {
labelDataKey: true
};
}
return null;
}
@Component({
selector: 'tb-label-data-key',
templateUrl: './label-data-key.component.html',
styleUrls: ['./label-data-key.component.scss', './../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => LabelDataKeyComponent),
multi: true
}
]
})
export class LabelDataKeyComponent extends PageComponent implements OnInit, ControlValueAccessor {
@Input()
disabled: boolean;
@Input()
expanded = false;
@Output()
removeLabelDataKey = new EventEmitter();
private modelValue: LabelDataKey;
private propagateChange = null;
public labelDataKeyFormGroup: FormGroup;
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private fb: FormBuilder) {
super(store);
}
ngOnInit(): void {
this.labelDataKeyFormGroup = this.fb.group({
name: [null, [Validators.required]],
type: [DataKeyType.attribute, [Validators.required]]
});
this.labelDataKeyFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
this.labelDataKeyFormGroup.disable({emitEvent: false});
} else {
this.labelDataKeyFormGroup.enable({emitEvent: false});
}
}
writeValue(value: LabelDataKey): void {
this.modelValue = value;
this.labelDataKeyFormGroup.patchValue(
value, {emitEvent: false}
);
}
labelDataKeyText(): string {
const name: string = this.labelDataKeyFormGroup.get('name').value || '';
const type: DataKeyType = this.labelDataKeyFormGroup.get('type').value;
let typeStr: string;
if (type === DataKeyType.attribute) {
typeStr = this.translate.instant('widgets.chart.key-type-attribute');
} else if (type === DataKeyType.timeseries) {
typeStr = this.translate.instant('widgets.chart.key-type-timeseries');
}
return `${name} (${typeStr})`;
}
private updateModel() {
const value: LabelDataKey = this.labelDataKeyFormGroup.value;
this.modelValue = value;
this.propagateChange(this.modelValue);
}
}

24
ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts

@ -75,6 +75,14 @@ import {
import { ValueSourceComponent } from '@home/components/widget/lib/settings/common/value-source.component'; import { ValueSourceComponent } from '@home/components/widget/lib/settings/common/value-source.component';
import { FixedColorLevelComponent } from '@home/components/widget/lib/settings/gauge/fixed-color-level.component'; import { FixedColorLevelComponent } from '@home/components/widget/lib/settings/gauge/fixed-color-level.component';
import { TickValueComponent } from '@home/components/widget/lib/settings/gauge/tick-value.component'; import { TickValueComponent } from '@home/components/widget/lib/settings/gauge/tick-value.component';
import { FlotWidgetSettingsComponent } from '@home/components/widget/lib/settings/chart/flot-widget-settings.component';
import {
FlotLineWidgetSettingsComponent
} from '@home/components/widget/lib/settings/chart/flot-line-widget-settings.component';
import { LabelDataKeyComponent } from '@home/components/widget/lib/settings/chart/label-data-key.component';
import {
FlotBarWidgetSettingsComponent
} from '@home/components/widget/lib/settings/chart/flot-bar-widget-settings.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -101,7 +109,11 @@ import { TickValueComponent } from '@home/components/widget/lib/settings/gauge/t
DigitalGaugeWidgetSettingsComponent, DigitalGaugeWidgetSettingsComponent,
ValueSourceComponent, ValueSourceComponent,
FixedColorLevelComponent, FixedColorLevelComponent,
TickValueComponent TickValueComponent,
FlotWidgetSettingsComponent,
LabelDataKeyComponent,
FlotLineWidgetSettingsComponent,
FlotBarWidgetSettingsComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -132,7 +144,11 @@ import { TickValueComponent } from '@home/components/widget/lib/settings/gauge/t
DigitalGaugeWidgetSettingsComponent, DigitalGaugeWidgetSettingsComponent,
ValueSourceComponent, ValueSourceComponent,
FixedColorLevelComponent, FixedColorLevelComponent,
TickValueComponent TickValueComponent,
FlotWidgetSettingsComponent,
LabelDataKeyComponent,
FlotLineWidgetSettingsComponent,
FlotBarWidgetSettingsComponent
] ]
}) })
export class WidgetSettingsModule { export class WidgetSettingsModule {
@ -156,5 +172,7 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-analogue-radial-gauge-widget-settings': AnalogueRadialGaugeWidgetSettingsComponent, 'tb-analogue-radial-gauge-widget-settings': AnalogueRadialGaugeWidgetSettingsComponent,
'tb-analogue-linear-gauge-widget-settings': AnalogueLinearGaugeWidgetSettingsComponent, 'tb-analogue-linear-gauge-widget-settings': AnalogueLinearGaugeWidgetSettingsComponent,
'tb-analogue-compass-widget-settings': AnalogueCompassWidgetSettingsComponent, 'tb-analogue-compass-widget-settings': AnalogueCompassWidgetSettingsComponent,
'tb-digital-gauge-widget-settings': DigitalGaugeWidgetSettingsComponent 'tb-digital-gauge-widget-settings': DigitalGaugeWidgetSettingsComponent,
'tb-flot-line-widget-settings': FlotLineWidgetSettingsComponent,
'tb-flot-bar-widget-settings': FlotBarWidgetSettingsComponent
}; };

8
ui-ngx/src/app/shared/models/widget.models.ts

@ -693,8 +693,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
this.updateValidators(true, trigger); this.updateValidators(true, trigger);
}); });
} }
this.settingsForm().valueChanges.subscribe((updated: WidgetSettings) => { this.settingsForm().valueChanges.subscribe((updated: any) => {
this.onSettingsChanged(updated); this.onSettingsChanged(this.prepareOutputSettings(updated));
}); });
} }
@ -713,7 +713,7 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
protected onSettingsChanged(updated: WidgetSettings) { protected onSettingsChanged(updated: WidgetSettings) {
this.settingsValue = updated; this.settingsValue = updated;
if (this.validateSettings()) { if (this.validateSettings()) {
this.settingsChangedEmitter.emit(this.prepareOutputSettings(updated)); this.settingsChangedEmitter.emit(updated);
} else { } else {
this.settingsChangedEmitter.emit(null); this.settingsChangedEmitter.emit(null);
} }
@ -723,7 +723,7 @@ export abstract class WidgetSettingsComponent extends PageComponent implements
return settings; return settings;
} }
protected prepareOutputSettings(settings: WidgetSettings): WidgetSettings { protected prepareOutputSettings(settings: any): WidgetSettings {
return settings; return settings;
} }

498
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -3182,13 +3182,75 @@
"invalid-widget-type-file-error": "Unable to import widget type: Invalid widget type data structure." "invalid-widget-type-file-error": "Unable to import widget type: Invalid widget type data structure."
}, },
"widgets": { "widgets": {
"chart": {
"common-settings": "Common settings",
"enable-stacking-mode": "Enable stacking mode",
"line-shadow-size": "Line shadow size",
"display-smooth-lines": "Display smooth (curved) lines",
"default-bar-width": "Default bar width for non-aggregated data (milliseconds)",
"bar-alignment": "Bar alignment",
"bar-alignment-left": "Left",
"bar-alignment-right": "Right",
"bar-alignment-center": "Center",
"default-font-size": "Default font size",
"default-font-color": "Default font color",
"thresholds-line-width": "Default line width for all thresholds",
"tooltip-settings": "Tooltip settings",
"show-tooltip": "Show tooltip",
"hover-individual-points": "Hover individual points",
"show-cumulative-values": "Show cumulative values in stacking mode",
"hide-zero-false-values": "Hide zero/false values from tooltip",
"tooltip-value-format-function": "Tooltip value format function",
"grid-settings": "Grid settings",
"show-vertical-lines": "Show vertical lines",
"show-horizontal-lines": "Show horizontal lines",
"grid-outline-border-width": "Grid outline/border width (px)",
"primary-color": "Primary color",
"background-color": "Background color",
"ticks-color": "Ticks color",
"xaxis-settings": "X axis settings",
"axis-title": "Axis title",
"xaxis-tick-labels-settings": "X axis tick labels settings",
"show-tick-labels": "Show axis tick labels",
"yaxis-settings": "Y axis settings",
"min-scale-value": "Minimum value on the scale",
"max-scale-value": "Maximum value on the scale",
"yaxis-tick-labels-settings": "Y axis tick labels settings",
"tick-step-size": "Step size between ticks",
"number-of-decimals": "The number of decimals to display",
"ticks-formatter-function": "Ticks formatter function",
"comparison-settings": "Comparison settings",
"enable-comparison": "Enable comparison",
"time-for-comparison": "Comparison period",
"time-for-comparison-previous-interval": "Previous interval (default)",
"time-for-comparison-days": "Day ago",
"time-for-comparison-weeks": "Week ago",
"time-for-comparison-months": "Month ago",
"time-for-comparison-years": "Year ago",
"time-for-comparison-custom-interval": "Custom interval",
"custom-interval-value": "Custom interval value (ms)",
"comparison-x-axis-settings": "Comparison X axis settings",
"axis-position": "Axis position",
"axis-position-top": "Top (default)",
"axis-position-bottom": "Bottom",
"custom-legend-settings": "Custom legend settings",
"enable-custom-legend": "Enable custom legend (this will allow you to use attribute/timeseries values in key labels)",
"key-name": "Key name",
"key-name-required": "Key name is required",
"key-type": "Key type",
"key-type-attribute": "Attribute",
"key-type-timeseries": "Timeseries",
"label-keys-list": "Keys list to use in labels",
"no-label-keys": "No keys configured",
"add-label-key": "Add new key"
},
"dashboard-state": { "dashboard-state": {
"dashboard-state-settings": "Dashboard state settings", "dashboard-state-settings": "Dashboard state settings",
"dashboard-state": "Dashboard state id", "dashboard-state": "Dashboard state id",
"autofill-state-layout": "Autofill state layout height by default", "autofill-state-layout": "Autofill state layout height by default",
"default-margin": "Default widgets margin", "default-margin": "Default widgets margin",
"default-background-color": "Default background color", "default-background-color": "Default background color",
"sync-parent-state-params": "Sync state params with parent dashboard" "sync-parent-state-params": "Sync state params with parent dashboard"
}, },
"date-range-navigator": { "date-range-navigator": {
"localizationMap": { "localizationMap": {
@ -3248,137 +3310,137 @@
} }
}, },
"entities-hierarchy": { "entities-hierarchy": {
"hierarchy-data-settings": "Hierarchy data settings", "hierarchy-data-settings": "Hierarchy data settings",
"relations-query-function": "Node relations query function", "relations-query-function": "Node relations query function",
"has-children-function": "Node has children function", "has-children-function": "Node has children function",
"node-state-settings": "Node state settings", "node-state-settings": "Node state settings",
"node-opened-function": "Default node opened function", "node-opened-function": "Default node opened function",
"node-disabled-function": "Node disabled function", "node-disabled-function": "Node disabled function",
"display-settings": "Display settings", "display-settings": "Display settings",
"node-icon-function": "Node icon function", "node-icon-function": "Node icon function",
"node-text-function": "Node text function", "node-text-function": "Node text function",
"sort-settings": "Sort settings", "sort-settings": "Sort settings",
"nodes-sort-function": "Nodes sort function" "nodes-sort-function": "Nodes sort function"
}, },
"gauge": { "gauge": {
"default-color": "Default color", "default-color": "Default color",
"radial-gauge-settings": "Radial gauge settings", "radial-gauge-settings": "Radial gauge settings",
"ticks-settings": "Ticks settings", "ticks-settings": "Ticks settings",
"min-value": "Minimum value", "min-value": "Minimum value",
"max-value": "Maximum value", "max-value": "Maximum value",
"start-ticks-angle": "Start ticks angle", "start-ticks-angle": "Start ticks angle",
"ticks-angle": "Ticks angle", "ticks-angle": "Ticks angle",
"major-ticks-count": "Major ticks count", "major-ticks-count": "Major ticks count",
"major-ticks-color": "Major ticks color", "major-ticks-color": "Major ticks color",
"minor-ticks-count": "Minor ticks count", "minor-ticks-count": "Minor ticks count",
"minor-ticks-color": "Minor ticks color", "minor-ticks-color": "Minor ticks color",
"tick-numbers-font": "Tick numbers font", "tick-numbers-font": "Tick numbers font",
"unit-title-settings": "Unit title settings", "unit-title-settings": "Unit title settings",
"show-unit-title": "Show unit title", "show-unit-title": "Show unit title",
"unit-title": "Unit title", "unit-title": "Unit title",
"title-font": "Title text font", "title-font": "Title text font",
"units-settings": "Units settings", "units-settings": "Units settings",
"units-font": "Units text font", "units-font": "Units text font",
"value-box-settings": "Value box settings", "value-box-settings": "Value box settings",
"show-value-box": "Show value box", "show-value-box": "Show value box",
"value-int": "Digits count for integer part of value", "value-int": "Digits count for integer part of value",
"value-font": "Value text font", "value-font": "Value text font",
"value-box-rect-stroke-color": "Value box rectangle stroke color", "value-box-rect-stroke-color": "Value box rectangle stroke color",
"value-box-rect-stroke-color-end": "Value box rectangle stroke color - end gradient", "value-box-rect-stroke-color-end": "Value box rectangle stroke color - end gradient",
"value-box-background-color": "Value box background color", "value-box-background-color": "Value box background color",
"value-box-shadow-color": "Value box shadow color", "value-box-shadow-color": "Value box shadow color",
"plate-settings": "Plate settings", "plate-settings": "Plate settings",
"show-plate-border": "Show plate border", "show-plate-border": "Show plate border",
"plate-color": "Plate color", "plate-color": "Plate color",
"needle-settings": "Needle settings", "needle-settings": "Needle settings",
"needle-circle-size": "Needle circle size", "needle-circle-size": "Needle circle size",
"needle-color": "Needle color", "needle-color": "Needle color",
"needle-color-end": "Needle color - end gradient", "needle-color-end": "Needle color - end gradient",
"needle-color-shadow-up": "Upper half of the needle shadow color", "needle-color-shadow-up": "Upper half of the needle shadow color",
"needle-color-shadow-down": "Drop shadow needle color", "needle-color-shadow-down": "Drop shadow needle color",
"highlights-settings": "Highlights settings", "highlights-settings": "Highlights settings",
"highlights-width": "Highlights width", "highlights-width": "Highlights width",
"highlights": "Highlights", "highlights": "Highlights",
"highlight-from": "From", "highlight-from": "From",
"highlight-to": "To", "highlight-to": "To",
"highlight-color": "Color", "highlight-color": "Color",
"no-highlights": "No highlights configured", "no-highlights": "No highlights configured",
"add-highlight": "Add highlight", "add-highlight": "Add highlight",
"animation-settings": "Animation settings", "animation-settings": "Animation settings",
"enable-animation": "Enable animation", "enable-animation": "Enable animation",
"animation-duration": "Animation duration", "animation-duration": "Animation duration",
"animation-rule": "Animation rule", "animation-rule": "Animation rule",
"animation-linear": "Linear", "animation-linear": "Linear",
"animation-quad": "Quad", "animation-quad": "Quad",
"animation-quint": "Quint", "animation-quint": "Quint",
"animation-cycle": "Cycle", "animation-cycle": "Cycle",
"animation-bounce": "Bounce", "animation-bounce": "Bounce",
"animation-elastic": "Elastic", "animation-elastic": "Elastic",
"animation-dequad": "Dequad", "animation-dequad": "Dequad",
"animation-dequint": "Dequint", "animation-dequint": "Dequint",
"animation-decycle": "Decycle", "animation-decycle": "Decycle",
"animation-debounce": "Debounce", "animation-debounce": "Debounce",
"animation-delastic": "Delastic", "animation-delastic": "Delastic",
"linear-gauge-settings": "Linear gauge settings", "linear-gauge-settings": "Linear gauge settings",
"bar-stroke-width": "Bar stroke width", "bar-stroke-width": "Bar stroke width",
"bar-stroke-color": "Bar stroke color", "bar-stroke-color": "Bar stroke color",
"bar-background-color": "Gauge bar background color", "bar-background-color": "Gauge bar background color",
"bar-background-color-end": "Bar background color - end gradient", "bar-background-color-end": "Bar background color - end gradient",
"progress-bar-color": "Progress bar color", "progress-bar-color": "Progress bar color",
"progress-bar-color-end": "Progress bar color - end gradient", "progress-bar-color-end": "Progress bar color - end gradient",
"major-ticks-names": "Major ticks names", "major-ticks-names": "Major ticks names",
"show-stroke-ticks": "Show ticks stroke", "show-stroke-ticks": "Show ticks stroke",
"major-ticks-font": "Major ticks font", "major-ticks-font": "Major ticks font",
"border-color": "Border color", "border-color": "Border color",
"border-width": "Border width", "border-width": "Border width",
"needle-circle-color": "Needle circle color", "needle-circle-color": "Needle circle color",
"animation-target": "Animation target", "animation-target": "Animation target",
"animation-target-needle": "Needle", "animation-target-needle": "Needle",
"animation-target-plate": "Plate", "animation-target-plate": "Plate",
"common-settings": "Common gauge settings", "common-settings": "Common gauge settings",
"gauge-type": "Gauge type", "gauge-type": "Gauge type",
"gauge-type-arc": "Arc", "gauge-type-arc": "Arc",
"gauge-type-donut": "Donut", "gauge-type-donut": "Donut",
"gauge-type-horizontal-bar": "Horizontal bar", "gauge-type-horizontal-bar": "Horizontal bar",
"gauge-type-vertical-bar": "Vertical bar", "gauge-type-vertical-bar": "Vertical bar",
"donut-start-angle": "Angle to start from", "donut-start-angle": "Angle to start from",
"bar-settings": "Gauge bar settings", "bar-settings": "Gauge bar settings",
"relative-bar-width": "Relative bar width", "relative-bar-width": "Relative bar width",
"neon-glow-brightness": "Neon glow effect brightness, (0-100), 0 - disable effect", "neon-glow-brightness": "Neon glow effect brightness, (0-100), 0 - disable effect",
"stripes-thickness": "Thickness of the stripes, 0 - no stripes", "stripes-thickness": "Thickness of the stripes, 0 - no stripes",
"rounded-line-cap": "Display rounded line cap", "rounded-line-cap": "Display rounded line cap",
"bar-color-settings": "Bar color settings", "bar-color-settings": "Bar color settings",
"use-precise-level-color-values": "Use precise color levels", "use-precise-level-color-values": "Use precise color levels",
"bar-colors": "Bar colors, from lower to upper", "bar-colors": "Bar colors, from lower to upper",
"color": "Color", "color": "Color",
"no-bar-colors": "No bar colors configured", "no-bar-colors": "No bar colors configured",
"add-bar-color": "Add bar color", "add-bar-color": "Add bar color",
"from": "From", "from": "From",
"to": "To", "to": "To",
"fixed-level-colors": "Bar colors using boundary values", "fixed-level-colors": "Bar colors using boundary values",
"gauge-title-settings": "Gauge title settings", "gauge-title-settings": "Gauge title settings",
"show-gauge-title": "Show gauge title", "show-gauge-title": "Show gauge title",
"gauge-title": "Gauge title", "gauge-title": "Gauge title",
"gauge-title-font": "Gauge title font", "gauge-title-font": "Gauge title font",
"unit-title-and-timestamp-settings": "Unit title and timestamp settings", "unit-title-and-timestamp-settings": "Unit title and timestamp settings",
"show-timestamp": "Show value timestamp", "show-timestamp": "Show value timestamp",
"timestamp-format": "Timestamp format", "timestamp-format": "Timestamp format",
"label-font": "Font of label showing under value", "label-font": "Font of label showing under value",
"value-settings": "Value settings", "value-settings": "Value settings",
"show-value": "Show value text", "show-value": "Show value text",
"min-max-settings": "Minimum/maximum labels settings", "min-max-settings": "Minimum/maximum labels settings",
"show-min-max": "Show min and max values", "show-min-max": "Show min and max values",
"min-max-font": "Font of minimum and maximum labels", "min-max-font": "Font of minimum and maximum labels",
"show-ticks": "Show ticks", "show-ticks": "Show ticks",
"tick-width": "Tick width", "tick-width": "Tick width",
"tick-color": "Tick color", "tick-color": "Tick color",
"tick-values": "Tick values", "tick-values": "Tick values",
"no-tick-values": "No tick values configured", "no-tick-values": "No tick values configured",
"add-tick-value": "Add tick value" "add-tick-value": "Add tick value"
}, },
"html-card": { "html-card": {
"html": "HTML", "html": "HTML",
"css": "CSS" "css": "CSS"
}, },
"input-widgets": { "input-widgets": {
"attribute-not-allowed": "Attribute parameter cannot be used in this widget", "attribute-not-allowed": "Attribute parameter cannot be used in this widget",
@ -3434,18 +3496,18 @@
"qr-code-text-function": "QR code text function" "qr-code-text-function": "QR code text function"
}, },
"label-widget": { "label-widget": {
"label-pattern": "Pattern", "label-pattern": "Pattern",
"label-pattern-hint": "Hint: for ex. 'Text <code><span style=\"color: #000;\">$&#123;</span>keyName<span style=\"color: #000;\">&#125;</span></code> units.' or <code><span style=\"color: #000;\">$&#123;</span>#&lt;key index&gt;<span style=\"color: #000;\">&#125;</span></code> units'", "label-pattern-hint": "Hint: for ex. 'Text <code><span style=\"color: #000;\">$&#123;</span>keyName<span style=\"color: #000;\">&#125;</span></code> units.' or <code><span style=\"color: #000;\">$&#123;</span>#&lt;key index&gt;<span style=\"color: #000;\">&#125;</span></code> units'",
"label-pattern-required": "Pattern is required", "label-pattern-required": "Pattern is required",
"label-position": "Position (Percentage relative to background)", "label-position": "Position (Percentage relative to background)",
"x-pos": "X", "x-pos": "X",
"y-pos": "Y", "y-pos": "Y",
"background-color": "Background color", "background-color": "Background color",
"font-settings": "Font settings", "font-settings": "Font settings",
"background-image": "Background image", "background-image": "Background image",
"labels": "Labels", "labels": "Labels",
"no-labels": "No labels configured", "no-labels": "No labels configured",
"add-label": "Add label" "add-label": "Add label"
}, },
"persistent-table": { "persistent-table": {
"rpc-id": "RPC ID", "rpc-id": "RPC ID",
@ -3526,87 +3588,87 @@
} }
}, },
"markdown": { "markdown": {
"use-markdown-text-function": "Use markdown/HTML value function", "use-markdown-text-function": "Use markdown/HTML value function",
"markdown-text-function": "Markdown/HTML value function", "markdown-text-function": "Markdown/HTML value function",
"markdown-text-pattern": "Markdown/HTML pattern (markdown or HTML with variables, for ex. '${entityName} or ${keyName} - some text.')", "markdown-text-pattern": "Markdown/HTML pattern (markdown or HTML with variables, for ex. '${entityName} or ${keyName} - some text.')",
"markdown-css": "Markdown/HTML CSS" "markdown-css": "Markdown/HTML CSS"
}, },
"simple-card": { "simple-card": {
"label-position": "Label position", "label-position": "Label position",
"label-position-left": "Left", "label-position-left": "Left",
"label-position-top": "Top" "label-position-top": "Top"
}, },
"table": { "table": {
"common-table-settings": "Common Table Settings", "common-table-settings": "Common Table Settings",
"enable-search": "Enable search", "enable-search": "Enable search",
"enable-sticky-header": "Always display header", "enable-sticky-header": "Always display header",
"enable-sticky-action": "Always display actions column", "enable-sticky-action": "Always display actions column",
"hidden-cell-button-display-mode": "Hidden cell button actions display mode", "hidden-cell-button-display-mode": "Hidden cell button actions display mode",
"show-empty-space-hidden-action": "Show empty space instead of hidden cell button action", "show-empty-space-hidden-action": "Show empty space instead of hidden cell button action",
"dont-reserve-space-hidden-action": "Don't reserve space for hidden action buttons", "dont-reserve-space-hidden-action": "Don't reserve space for hidden action buttons",
"display-timestamp": "Display timestamp column", "display-timestamp": "Display timestamp column",
"display-milliseconds": "Display timestamp milliseconds", "display-milliseconds": "Display timestamp milliseconds",
"display-pagination": "Display pagination", "display-pagination": "Display pagination",
"default-page-size": "Default page size", "default-page-size": "Default page size",
"use-entity-label-tab-name": "Use entity label in tab name", "use-entity-label-tab-name": "Use entity label in tab name",
"hide-empty-lines": "Hide empty lines", "hide-empty-lines": "Hide empty lines",
"row-style": "Row style", "row-style": "Row style",
"use-row-style-function": "Use row style function", "use-row-style-function": "Use row style function",
"row-style-function": "Row style function", "row-style-function": "Row style function",
"cell-style": "Cell style", "cell-style": "Cell style",
"use-cell-style-function": "Use cell style function", "use-cell-style-function": "Use cell style function",
"cell-style-function": "Cell style function", "cell-style-function": "Cell style function",
"cell-content": "Cell content", "cell-content": "Cell content",
"use-cell-content-function": "Use cell content function", "use-cell-content-function": "Use cell content function",
"cell-content-function": "Cell content function", "cell-content-function": "Cell content function",
"show-latest-data-column": "Show latest data column", "show-latest-data-column": "Show latest data column",
"latest-data-column-order": "Latest data column order", "latest-data-column-order": "Latest data column order",
"entities-table-title": "Entities table title", "entities-table-title": "Entities table title",
"enable-select-column-display": "Enable select columns to display", "enable-select-column-display": "Enable select columns to display",
"display-entity-name": "Display entity name column", "display-entity-name": "Display entity name column",
"entity-name-column-title": "Entity name column title", "entity-name-column-title": "Entity name column title",
"display-entity-label": "Display entity label column", "display-entity-label": "Display entity label column",
"entity-label-column-title": "Entity label column title", "entity-label-column-title": "Entity label column title",
"display-entity-type": "Display entity type column", "display-entity-type": "Display entity type column",
"default-sort-order": "Default sort order", "default-sort-order": "Default sort order",
"column-width": "Column width (px or %)", "column-width": "Column width (px or %)",
"default-column-visibility": "Default column visibility", "default-column-visibility": "Default column visibility",
"column-visibility-visible": "Visible", "column-visibility-visible": "Visible",
"column-visibility-hidden": "Hidden", "column-visibility-hidden": "Hidden",
"column-selection-to-display": "Column selection in 'Columns to Display'", "column-selection-to-display": "Column selection in 'Columns to Display'",
"column-selection-to-display-enabled": "Enabled", "column-selection-to-display-enabled": "Enabled",
"column-selection-to-display-disabled": "Disabled", "column-selection-to-display-disabled": "Disabled",
"alarms-table-title": "Alarms table title", "alarms-table-title": "Alarms table title",
"enable-alarms-selection": "Enable alarms selection", "enable-alarms-selection": "Enable alarms selection",
"enable-alarms-search": "Enable alarms search", "enable-alarms-search": "Enable alarms search",
"enable-alarm-filter": "Enable alarm filter", "enable-alarm-filter": "Enable alarm filter",
"display-alarm-details": "Display alarm details", "display-alarm-details": "Display alarm details",
"allow-alarms-ack": "Allow alarms acknowledgment", "allow-alarms-ack": "Allow alarms acknowledgment",
"allow-alarms-clear": "Allow alarms clear" "allow-alarms-clear": "Allow alarms clear"
}, },
"value-source": { "value-source": {
"value-source": "Value source", "value-source": "Value source",
"predefined-value": "Predefined value", "predefined-value": "Predefined value",
"entity-attribute": "Value taken from entity attribute", "entity-attribute": "Value taken from entity attribute",
"value": "Value", "value": "Value",
"source-entity-alias": "Source entity alias", "source-entity-alias": "Source entity alias",
"source-entity-attribute": "Source entity attribute" "source-entity-attribute": "Source entity attribute"
}, },
"widget-font": { "widget-font": {
"font-family": "Font family", "font-family": "Font family",
"size": "Size", "size": "Size",
"relative-font-size": "Relative font size (percents)", "relative-font-size": "Relative font size (percents)",
"font-style": "Style", "font-style": "Style",
"font-style-normal": "Normal", "font-style-normal": "Normal",
"font-style-italic": "Italic", "font-style-italic": "Italic",
"font-style-oblique": "Oblique", "font-style-oblique": "Oblique",
"font-weight": "Weight", "font-weight": "Weight",
"font-weight-normal": "Normal", "font-weight-normal": "Normal",
"font-weight-bold": "Bold", "font-weight-bold": "Bold",
"font-weight-bolder": "Bolder", "font-weight-bolder": "Bolder",
"font-weight-lighter": "Lighter", "font-weight-lighter": "Lighter",
"color": "Color", "color": "Color",
"shadow-color": "Shadow color" "shadow-color": "Shadow color"
} }
}, },
"icon": { "icon": {

Loading…
Cancel
Save