Browse Source

Merge pull request #6545 from thingsboard/feature/widget-settings

[3.4] Advanced widget settings: replace auto-generated JSON forms with Angular components
pull/6555/head
Igor Kulikov 4 years ago
committed by GitHub
parent
commit
c5a7159499
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      application/src/main/data/json/system/widget_bundles/alarm_widgets.json
  2. 15
      application/src/main/data/json/system/widget_bundles/analogue_gauges.json
  3. 59
      application/src/main/data/json/system/widget_bundles/cards.json
  4. 36
      application/src/main/data/json/system/widget_bundles/charts.json
  5. 30
      application/src/main/data/json/system/widget_bundles/control_widgets.json
  6. 3
      application/src/main/data/json/system/widget_bundles/date.json
  7. 39
      application/src/main/data/json/system/widget_bundles/digital_gauges.json
  8. 5
      application/src/main/data/json/system/widget_bundles/edge_widgets.json
  9. 12
      application/src/main/data/json/system/widget_bundles/entity_admin_widgets.json
  10. 9
      application/src/main/data/json/system/widget_bundles/gateway_widgets.json
  11. 12
      application/src/main/data/json/system/widget_bundles/gpio_widgets.json
  12. 93
      application/src/main/data/json/system/widget_bundles/input_widgets.json
  13. 77
      application/src/main/data/json/system/widget_bundles/maps.json
  14. 8
      application/src/main/data/json/system/widget_bundles/navigation_widgets.json
  15. 3
      ui-ngx/.editorconfig
  16. 27
      ui-ngx/extra-webpack.config.js
  17. 1
      ui-ngx/package.json
  18. 6
      ui-ngx/src/app/core/api/entity-data-subscription.ts
  19. 2
      ui-ngx/src/app/core/http/rule-chain.service.ts
  20. 41
      ui-ngx/src/app/core/services/resources.service.ts
  21. 4
      ui-ngx/src/app/core/utils.ts
  22. 5
      ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html
  23. 5
      ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts
  24. 5
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html
  25. 5
      ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts
  26. 5
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  27. 2
      ui-ngx/src/app/modules/home/components/import-export/import-dialog-csv.component.html
  28. 2
      ui-ngx/src/app/modules/home/components/import-export/import-dialog.component.html
  29. 4
      ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.html
  30. 8
      ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.ts
  31. 7
      ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html
  32. 29
      ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts
  33. 2
      ui-ngx/src/app/modules/home/components/widget/data-keys.component.html
  34. 67
      ui-ngx/src/app/modules/home/components/widget/data-keys.component.scss
  35. 16
      ui-ngx/src/app/modules/home/components/widget/data-keys.component.ts
  36. 319
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-compass.models.ts
  37. 10
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-compass.ts
  38. 771
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-gauge.models.ts
  39. 64
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-linear-gauge.models.ts
  40. 9
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-linear-gauge.ts
  41. 31
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-radial-gauge.models.ts
  42. 10
      ui-ngx/src/app/modules/home/components/widget/lib/analogue-radial-gauge.ts
  43. 902
      ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts
  44. 7
      ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts
  45. 937
      ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.models.ts
  46. 28
      ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts
  47. 25
      ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts
  48. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts
  49. 110
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  50. 878
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts
  51. 70
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts
  52. 12
      ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
  53. 37
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts
  54. 47
      ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts
  55. 24
      ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts
  56. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts
  57. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts
  58. 11
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts
  59. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts
  60. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts
  61. 95
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.html
  62. 86
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts
  63. 110
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html
  64. 104
      ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts
  65. 65
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.html
  66. 99
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts
  67. 22
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.html
  68. 52
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts
  69. 74
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html
  70. 64
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.ts
  71. 95
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.html
  72. 86
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.ts
  73. 116
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html
  74. 118
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.ts
  75. 25
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.html
  76. 54
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts
  77. 73
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html
  78. 40
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.scss
  79. 113
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts
  80. 50
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.html
  81. 110
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts
  82. 36
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html
  83. 76
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts
  84. 37
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.html
  85. 74
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts
  86. 30
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.html
  87. 52
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts
  88. 69
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.html
  89. 80
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts
  90. 76
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.html
  91. 96
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts
  92. 96
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html
  93. 98
      ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts
  94. 25
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.html
  95. 52
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.ts
  96. 64
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.html
  97. 87
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/doughnut-chart-widget-settings.component.ts
  98. 24
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.html
  99. 61
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-key-settings.component.ts
  100. 23
      ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/flot-bar-widget-settings.component.html

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

@ -19,8 +19,10 @@
"templateHtml": "<tb-alarms-table-widget \n [ctx]=\"ctx\">\n</tb-alarms-table-widget>", "templateHtml": "<tb-alarms-table-widget \n [ctx]=\"ctx\">\n</tb-alarms-table-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.alarmsTableWidget.onDataUpdated();\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true,\n hasShowCondition: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.alarmsTableWidget.onDataUpdated();\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true,\n hasShowCondition: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableFilter\": {\n \"title\": \"Enable alarm filter\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStickyHeader\": {\n \"title\": \"Always display header\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStickyAction\": {\n \"title\": \"Always display actions column\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"reserveSpaceForHiddenAction\": {\n \"title\": \"Hidden cell button actions display mode\",\n \"type\": \"string\",\n \"default\": \"true\"\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"-createdTime\"\n },\n \"useRowStyleFunction\": {\n \"title\": \"Use row style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"rowStyleFunction\": {\n \"title\": \"Row style function: f(alarm, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableFilter\",\n \"enableStickyHeader\",\n \"enableStickyAction\",\n {\n \"key\": \"reserveSpaceForHiddenAction\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"true\",\n \"label\": \"Show empty space instead of hidden cell button action\"\n },\n {\n \"value\": \"false\",\n \"label\": \"Don't reserve space for hidden action buttons\"\n }\n ]\n },\n \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\",\n \"useRowStyleFunction\",\n {\n \"key\": \"rowStyleFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/alarm/row_style_fn\",\n \"condition\": \"model.useRowStyleFunction === true\"\n }\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value, alarm, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, alarm, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"defaultColumnVisibility\": {\n \"title\": \"Default column visibility\",\n \"type\": \"string\",\n \"default\": \"visible\"\n },\n \"columnSelectionToDisplay\": {\n \"title\": \"Column selection in 'Columns to Display'\",\n \"type\": \"string\",\n \"default\": \"enabled\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/alarm/cell_style_fn\",\n \"condition\": \"model.useCellStyleFunction === true\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\",\n \"helpId\": \"widget/lib/alarm/cell_content_fn\",\n \"condition\": \"model.useCellContentFunction === true\"\n },\n {\n \"key\": \"defaultColumnVisibility\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"visible\",\n \"label\": \"Visible\"\n },\n {\n \"value\": \"hidden\",\n \"label\": \"Hidden\"\n } \n ]\n },\n {\n \"key\": \"columnSelectionToDisplay\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"enabled\",\n \"label\": \"Enabled\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n } \n ]\n }\n ]\n}", "dataKeySettingsSchema": "",
"settingsDirective": "tb-alarms-table-widget-settings",
"dataKeySettingsDirective": "tb-alarms-table-key-settings",
"defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStickyAction\":false,\"enableFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{},\"alarmStatusList\":[],\"alarmSeverityList\":[],\"alarmTypeList\":[],\"searchPropagatedAlarms\":false}" "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStickyAction\":false,\"enableFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{},\"alarmStatusList\":[],\"alarmSeverityList\":[],\"alarmTypeList\":[],\"searchPropagatedAlarms\":false}"
} }
} }

15
application/src/main/data/json/system/widget_bundles/analogue_gauges.json

@ -18,9 +18,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"compass\"></canvas>", "templateHtml": "<canvas id=\"compass\"></canvas>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueCompass(self.ctx, 'compass');\n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueCompass.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueCompass(self.ctx, 'compass');\n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-analogue-compass-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"minorTicks\":22,\"needleCircleSize\":15,\"showBorder\":true,\"borderOuterWidth\":10,\"colorPlate\":\"#222\",\"colorMajorTicks\":\"#f5f5f5\",\"colorMinorTicks\":\"#ddd\",\"colorNeedle\":\"#f08080\",\"colorNeedleCircle\":\"#e8e8e8\",\"colorBorder\":\"#ccc\",\"majorTickFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ccc\"},\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"animationTarget\":\"needle\",\"majorTicks\":[\"N\",\"NE\",\"E\",\"SE\",\"S\",\"SW\",\"W\",\"NW\"]},\"title\":\"Compass\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"minorTicks\":22,\"needleCircleSize\":15,\"showBorder\":true,\"borderOuterWidth\":10,\"colorPlate\":\"#222\",\"colorMajorTicks\":\"#f5f5f5\",\"colorMinorTicks\":\"#ddd\",\"colorNeedle\":\"#f08080\",\"colorNeedleCircle\":\"#e8e8e8\",\"colorBorder\":\"#ccc\",\"majorTickFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ccc\"},\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"animationTarget\":\"needle\",\"majorTicks\":[\"N\",\"NE\",\"E\",\"SE\",\"S\",\"SW\",\"W\",\"NW\"]},\"title\":\"Compass\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -36,9 +37,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"linearGauge\"></canvas>\n", "templateHtml": "<canvas id=\"linearGauge\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueLinearGauge(self.ctx, 'linearGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueLinearGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueLinearGauge(self.ctx, 'linearGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-analogue-linear-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 30 - 15;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"defaultColor\":\"#e64a19\",\"barStrokeWidth\":2.5,\"colorBar\":\"rgba(255, 255, 255, 0.4)\",\"colorBarEnd\":\"rgba(221, 221, 221, 0.38)\",\"showUnitTitle\":true,\"minorTicks\":2,\"valueBox\":true,\"valueInt\":3,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"colorNeedleShadowUp\":\"rgba(2,255,255,0.2)\",\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"highlightsWidth\":10,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"showBorder\":false,\"majorTicksCount\":8,\"numbersFont\":{\"family\":\"Arial\",\"size\":18,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#78909c\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":26,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#37474f\"},\"valueFont\":{\"family\":\"Roboto\",\"size\":40,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#444\",\"shadowColor\":\"rgba(0,0,0,0.3)\"},\"minValue\":-60,\"highlights\":[{\"from\":-60,\"to\":-40,\"color\":\"#90caf9\"},{\"from\":-40,\"to\":-20,\"color\":\"rgba(144, 202, 249, 0.66)\"},{\"from\":-20,\"to\":0,\"color\":\"rgba(144, 202, 249, 0.33)\"},{\"from\":0,\"to\":20,\"color\":\"rgba(244, 67, 54, 0.2)\"},{\"from\":20,\"to\":40,\"color\":\"rgba(244, 67, 54, 0.4)\"},{\"from\":40,\"to\":60,\"color\":\"rgba(244, 67, 54, 0.6)\"},{\"from\":60,\"to\":80,\"color\":\"rgba(244, 67, 54, 0.8)\"},{\"from\":80,\"to\":100,\"color\":\"#f44336\"}],\"unitTitle\":\"Temperature\",\"units\":\"°C\",\"colorBarProgress\":\"#90caf9\",\"colorBarProgressEnd\":\"#f44336\",\"colorBarStroke\":\"#b0bec5\",\"valueDec\":1},\"title\":\"Thermometer scale\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 30 - 15;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"defaultColor\":\"#e64a19\",\"barStrokeWidth\":2.5,\"colorBar\":\"rgba(255, 255, 255, 0.4)\",\"colorBarEnd\":\"rgba(221, 221, 221, 0.38)\",\"showUnitTitle\":true,\"minorTicks\":2,\"valueBox\":true,\"valueInt\":3,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"colorNeedleShadowUp\":\"rgba(2,255,255,0.2)\",\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"highlightsWidth\":10,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"showBorder\":false,\"majorTicksCount\":8,\"numbersFont\":{\"family\":\"Arial\",\"size\":18,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#78909c\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":26,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#37474f\"},\"valueFont\":{\"family\":\"Roboto\",\"size\":40,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#444\",\"shadowColor\":\"rgba(0,0,0,0.3)\"},\"minValue\":-60,\"highlights\":[{\"from\":-60,\"to\":-40,\"color\":\"#90caf9\"},{\"from\":-40,\"to\":-20,\"color\":\"rgba(144, 202, 249, 0.66)\"},{\"from\":-20,\"to\":0,\"color\":\"rgba(144, 202, 249, 0.33)\"},{\"from\":0,\"to\":20,\"color\":\"rgba(244, 67, 54, 0.2)\"},{\"from\":20,\"to\":40,\"color\":\"rgba(244, 67, 54, 0.4)\"},{\"from\":40,\"to\":60,\"color\":\"rgba(244, 67, 54, 0.6)\"},{\"from\":60,\"to\":80,\"color\":\"rgba(244, 67, 54, 0.8)\"},{\"from\":80,\"to\":100,\"color\":\"#f44336\"}],\"unitTitle\":\"Temperature\",\"units\":\"°C\",\"colorBarProgress\":\"#90caf9\",\"colorBarProgressEnd\":\"#f44336\",\"colorBarStroke\":\"#b0bec5\",\"valueDec\":1},\"title\":\"Thermometer scale\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -54,9 +56,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"radialGauge\"></canvas>\n", "templateHtml": "<canvas id=\"radialGauge\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-analogue-radial-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":60,\"startAngle\":67.5,\"ticksAngle\":225,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":-60,\"to\":-50,\"color\":\"#42a5f5\"},{\"from\":-50,\"to\":-40,\"color\":\"rgba(66, 165, 245, 0.83)\"},{\"from\":-40,\"to\":-30,\"color\":\"rgba(66, 165, 245, 0.66)\"},{\"from\":-30,\"to\":-20,\"color\":\"rgba(66, 165, 245, 0.5)\"},{\"from\":-20,\"to\":-10,\"color\":\"rgba(66, 165, 245, 0.33)\"},{\"from\":-10,\"to\":0,\"color\":\"rgba(66, 165, 245, 0.16)\"},{\"from\":0,\"to\":10,\"color\":\"rgba(229, 115, 115, 0.16)\"},{\"from\":10,\"to\":20,\"color\":\"rgba(229, 115, 115, 0.33)\"},{\"from\":20,\"to\":30,\"color\":\"rgba(229, 115, 115, 0.5)\"},{\"from\":30,\"to\":40,\"color\":\"rgba(229, 115, 115, 0.66)\"},{\"from\":40,\"to\":50,\"color\":\"rgba(229, 115, 115, 0.83)\"},{\"from\":50,\"to\":60,\"color\":\"#e57373\"}],\"showUnitTitle\":true,\"colorPlate\":\"#cfd8dc\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"valueDec\":1,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1000,\"animationRule\":\"bounce\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"°C\",\"majorTicksCount\":12,\"numbersFont\":{\"family\":\"Roboto\",\"size\":20,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":30,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"unitTitle\":\"Temperature\",\"minValue\":-60},\"title\":\"Temperature radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":60,\"startAngle\":67.5,\"ticksAngle\":225,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":-60,\"to\":-50,\"color\":\"#42a5f5\"},{\"from\":-50,\"to\":-40,\"color\":\"rgba(66, 165, 245, 0.83)\"},{\"from\":-40,\"to\":-30,\"color\":\"rgba(66, 165, 245, 0.66)\"},{\"from\":-30,\"to\":-20,\"color\":\"rgba(66, 165, 245, 0.5)\"},{\"from\":-20,\"to\":-10,\"color\":\"rgba(66, 165, 245, 0.33)\"},{\"from\":-10,\"to\":0,\"color\":\"rgba(66, 165, 245, 0.16)\"},{\"from\":0,\"to\":10,\"color\":\"rgba(229, 115, 115, 0.16)\"},{\"from\":10,\"to\":20,\"color\":\"rgba(229, 115, 115, 0.33)\"},{\"from\":20,\"to\":30,\"color\":\"rgba(229, 115, 115, 0.5)\"},{\"from\":30,\"to\":40,\"color\":\"rgba(229, 115, 115, 0.66)\"},{\"from\":40,\"to\":50,\"color\":\"rgba(229, 115, 115, 0.83)\"},{\"from\":50,\"to\":60,\"color\":\"#e57373\"}],\"showUnitTitle\":true,\"colorPlate\":\"#cfd8dc\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"valueDec\":1,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1000,\"animationRule\":\"bounce\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"°C\",\"majorTicksCount\":12,\"numbersFont\":{\"family\":\"Roboto\",\"size\":20,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":30,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"unitTitle\":\"Temperature\",\"minValue\":-60},\"title\":\"Temperature radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -72,9 +75,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"radialGauge\"></canvas>\n", "templateHtml": "<canvas id=\"radialGauge\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-analogue-radial-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 220) {\\n\\tvalue = 220;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":180,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":false,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":80,\"to\":120,\"color\":\"#fdd835\"},{\"color\":\"#e57373\",\"from\":120,\"to\":180}],\"showUnitTitle\":false,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"minValue\":0,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"MPH\",\"majorTicksCount\":9,\"numbersFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"size\":32,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\",\"family\":\"Segment7Standard\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Speed gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 220) {\\n\\tvalue = 220;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":180,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":false,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":80,\"to\":120,\"color\":\"#fdd835\"},{\"color\":\"#e57373\",\"from\":120,\"to\":180}],\"showUnitTitle\":false,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"minValue\":0,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"MPH\",\"majorTicksCount\":9,\"numbersFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"size\":32,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\",\"family\":\"Segment7Standard\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Speed gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -90,9 +94,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"radialGauge\"></canvas>\n", "templateHtml": "<canvas id=\"radialGauge\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, 'radialGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-analogue-radial-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < -100) {\\n\\tvalue = -100;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":10,\"highlights\":[],\"showUnitTitle\":true,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":10,\"valueInt\":3,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"numbersFont\":{\"family\":\"Roboto\",\"size\":18,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":36,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"minValue\":-100,\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < -100) {\\n\\tvalue = -100;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":10,\"highlights\":[],\"showUnitTitle\":true,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":10,\"valueInt\":3,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"numbersFont\":{\"family\":\"Roboto\",\"size\":18,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":36,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"minValue\":-100,\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Radial gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
} }

59
application/src/main/data/json/system/widget_bundles/cards.json

File diff suppressed because one or more lines are too long

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

@ -23,8 +23,9 @@
"templateHtml": "<canvas id=\"barChart\"></canvas>\n", "templateHtml": "<canvas id=\"barChart\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var barData = {\n labels: [],\n datasets: []\n };\n \n for (var i = 0; i < self.ctx.datasources.length; i++) {\n var datasource = self.ctx.datasources[i];\n for (var d = 0; d < datasource.dataKeys.length; d++) {\n var dataKey = datasource.dataKeys[d];\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n var dataset = {\n label: dataKey.label + units,\n data: [0],\n backgroundColor: [dataKey.color],\n borderColor: [dataKey.color],\n borderWidth: 1\n }\n barData.datasets.push(dataset);\n }\n }\n\n var ctx = $('#barChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'bar',\n data: barData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scales: {\n yAxes: [{\n ticks: {\n beginAtZero:true\n }\n }]\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var c = 0;\n for (var i = 0; i < self.ctx.chart.data.datasets.length; i++) {\n var dataset = self.ctx.chart.data.datasets[i];\n var cellData = self.ctx.data[i]; \n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n dataset.data[0] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n", "controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var barData = {\n labels: [],\n datasets: []\n };\n \n for (var i = 0; i < self.ctx.datasources.length; i++) {\n var datasource = self.ctx.datasources[i];\n for (var d = 0; d < datasource.dataKeys.length; d++) {\n var dataKey = datasource.dataKeys[d];\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n var dataset = {\n label: dataKey.label + units,\n data: [0],\n backgroundColor: [dataKey.color],\n borderColor: [dataKey.color],\n borderWidth: 1\n }\n barData.datasets.push(dataset);\n }\n }\n\n var ctx = $('#barChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'bar',\n data: barData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scales: {\n yAxes: [{\n ticks: {\n beginAtZero:true\n }\n }]\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var c = 0;\n for (var i = 0; i < self.ctx.chart.data.datasets.length; i++) {\n var dataset = self.ctx.chart.data.datasets[i];\n var cellData = self.ctx.data[i]; \n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n dataset.data[0] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"showTooltip\": {\n \"title\": \"Show Tooltip\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTooltip\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-chart-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Bars\"}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Bars\"}"
} }
}, },
@ -45,8 +46,9 @@
"templateHtml": "<canvas id=\"pieChart\"></canvas>\n", "templateHtml": "<canvas id=\"pieChart\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n var borderColor = self.ctx.settings.borderColor || '#fff';\n var borderWidth = typeof self.ctx.settings.borderWidth !== 'undefined' ? self.ctx.settings.borderWidth : 5;\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push(borderColor);\n dataset.borderWidth.push(borderWidth);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var options = {\n responsive: false,\n maintainAspectRatio: false,\n legend: {\n display: true,\n labels: {\n fontColor: '#666'\n }\n },\n tooltips: {\n callbacks: {\n label: function(tooltipItem, data) {\n var label = data.labels[tooltipItem.index];\n var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n var content = label + ': ' + value;\n var units = self.ctx.settings.units ? self.ctx.settings.units : self.ctx.units;\n if (units) {\n content += ' ' + units;\n } \n return content;\n }\n }\n }\n };\n\n if (self.ctx.settings.legend) {\n options.legend.display = self.ctx.settings.legend.display !== false;\n options.legend.labels.fontColor = self.ctx.settings.legend.labelsFontColor || '#666';\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'doughnut',\n data: pieData,\n options: options\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n\n", "controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n var borderColor = self.ctx.settings.borderColor || '#fff';\n var borderWidth = typeof self.ctx.settings.borderWidth !== 'undefined' ? self.ctx.settings.borderWidth : 5;\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push(borderColor);\n dataset.borderWidth.push(borderWidth);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var options = {\n responsive: false,\n maintainAspectRatio: false,\n legend: {\n display: true,\n labels: {\n fontColor: '#666'\n }\n },\n tooltips: {\n callbacks: {\n label: function(tooltipItem, data) {\n var label = data.labels[tooltipItem.index];\n var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n var content = label + ': ' + value;\n var units = self.ctx.settings.units ? self.ctx.settings.units : self.ctx.units;\n if (units) {\n content += ' ' + units;\n } \n return content;\n }\n }\n }\n };\n\n if (self.ctx.settings.legend) {\n options.legend.display = self.ctx.settings.legend.display !== false;\n options.legend.labels.fontColor = self.ctx.settings.legend.labelsFontColor || '#666';\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'doughnut',\n data: pieData,\n options: options\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"showTooltip\": {\n \"title\": \"Show Tooltip\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"borderWidth\": {\n \"title\": \"Border width\",\n \"type\": \"number\",\n \"default\": 5\n },\n \"borderColor\": {\n \"title\": \"Border color\",\n \"type\": \"string\",\n \"default\": \"#fff\"\n },\n \"legend\": {\n \"title\": \"Legend settings\",\n \"type\": \"object\",\n \"properties\": {\n \"display\": {\n \"title\": \"Display legend\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"labelsFontColor\": {\n \"title\": \"Labels font color\",\n \"type\": \"string\",\n \"default\": \"#666\"\n }\n }\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTooltip\",\n \"borderWidth\", \n {\n \"key\": \"borderColor\",\n \"type\": \"color\"\n }, \n {\n \"key\": \"legend\",\n \"items\": [\n \"legend.display\",\n {\n \"key\": \"legend.labelsFontColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-doughnut-chart-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#26a69a\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#afb42b\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#673ab7\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"borderWidth\":5,\"borderColor\":\"#fff\",\"legend\":{\"display\":true,\"labelsFontColor\":\"#666666\"}},\"title\":\"Doughnut\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#26a69a\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#afb42b\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#673ab7\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"borderWidth\":5,\"borderColor\":\"#fff\",\"legend\":{\"display\":true,\"labelsFontColor\":\"#666666\"}},\"title\":\"Doughnut\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -62,10 +64,12 @@
"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.pie-label {\n font-size: 12px;\n font-family: 'Roboto';\n font-weight: bold;\n text-align: center;\n padding: 2px;\n color: white;\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.pie-label {\n font-size: 12px;\n font-family: 'Roboto';\n font-weight: bold;\n text-align: center;\n padding: 2px;\n color: white;\n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'pie'); \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.getSettingsSchema = function() {\n return TbFlot.pieSettingsSchema();\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.pieDatakeySettingsSchema();\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'pie'); \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.onDestroy = function() {\n self.ctx.flot.destroy();\n}\nself.actionSources = function() {\n return {\n 'sliceClick': {\n name: 'widget-action.pie-slice-click',\n multiple: false\n }\n };\n}\n",
"settingsSchema": "{}\n", "settingsSchema": "{}\n",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.6114638304362894,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.9955906536344441,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.9430835931647599,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"radius\":1,\"fontColor\":\"#545454\",\"fontSize\":10,\"decimals\":1,\"legend\":{\"show\":true,\"position\":\"nw\",\"labelBoxBorderColor\":\"#CCCCCC\",\"backgroundColor\":\"#F0F0F0\",\"backgroundOpacity\":0.85},\"innerRadius\":0,\"showLabels\":true,\"showPercentages\":true,\"stroke\":{\"width\":5},\"tilt\":1,\"animatedPie\":false},\"title\":\"Pie - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "settingsDirective": "tb-flot-pie-widget-settings",
"dataKeySettingsDirective": "tb-flot-pie-key-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.6114638304362894,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.9955906536344441,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.9430835931647599,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"radius\":1,\"fontColor\":\"#545454\",\"fontSize\":10,\"decimals\":1,\"legend\":{\"show\":true,\"position\":\"nw\",\"labelBoxBorderColor\":\"#CCCCCC\",\"backgroundColor\":\"#F0F0F0\",\"backgroundOpacity\":0.85},\"innerRadius\":0,\"showLabels\":true,\"showPercentages\":true,\"stroke\":{\"width\":5},\"tilt\":1,\"animatedPie\":false},\"title\":\"Pie- Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
{ {
@ -85,8 +89,9 @@
"templateHtml": "<canvas id=\"pieChart\"></canvas>\n", "templateHtml": "<canvas id=\"pieChart\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n var borderColor = tinycolor(dataKey.color).darken();\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push('#fff');\n dataset.borderWidth.push(5);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'pie',\n data: pieData,\n options: {\n responsive: false,\n maintainAspectRatio: false\n }\n }); \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n", "controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n var borderColor = tinycolor(dataKey.color).darken();\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push('#fff');\n dataset.borderWidth.push(5);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'pie',\n data: pieData,\n options: {\n responsive: false,\n maintainAspectRatio: false\n }\n }); \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"showTooltip\": {\n \"title\": \"Show Tooltip\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTooltip\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-chart-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Pie - Chart.js\"}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Pie - Chart.js\"}"
} }
}, },
@ -107,8 +112,9 @@
"templateHtml": "<canvas id=\"pieChart\"></canvas>\n", "templateHtml": "<canvas id=\"pieChart\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n\n pieData.datasets.push(dataset);\n \n for (var i = 0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n var borderColor = tinycolor(dataKey.color).darken();\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push('#fff');\n dataset.borderWidth.push(5);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n \n var floatingPoint;\n if (typeof self.ctx.decimals !== 'undefined' && self.ctx.decimals !== null) {\n floatingPoint = self.ctx.widget.config.decimals;\n } else {\n floatingPoint = 2;\n }\n\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'polarArea',\n data: pieData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scale: {\n ticks: {\n callback: function(tick) {\n \treturn tick.toFixed(floatingPoint);\n }\n }\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n if (self.ctx.height >= 70) {\n try {\n self.ctx.chart.resize();\n } catch (e) {}\n }\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n", "controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n\n pieData.datasets.push(dataset);\n \n for (var i = 0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n pieData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n var borderColor = tinycolor(dataKey.color).darken();\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push('#fff');\n dataset.borderWidth.push(5);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n \n var floatingPoint;\n if (typeof self.ctx.decimals !== 'undefined' && self.ctx.decimals !== null) {\n floatingPoint = self.ctx.widget.config.decimals;\n } else {\n floatingPoint = 2;\n }\n\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'polarArea',\n data: pieData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scale: {\n ticks: {\n callback: function(tick) {\n \treturn tick.toFixed(floatingPoint);\n }\n }\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n if (self.ctx.height >= 70) {\n try {\n self.ctx.chart.resize();\n } catch (e) {}\n }\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"showTooltip\": {\n \"title\": \"Show Tooltip\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTooltip\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-chart-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fifth\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.2074391823443591,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Polar Area\"}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fifth\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.2074391823443591,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Polar Area\"}"
} }
}, },
@ -129,8 +135,9 @@
"templateHtml": "<canvas id=\"radarChart\"></canvas>\n", "templateHtml": "<canvas id=\"radarChart\"></canvas>\n",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var barData = {\n labels: [],\n datasets: []\n };\n\n var backgroundColor = tinycolor(self.ctx.data[0].dataKey.color);\n backgroundColor.setAlpha(0.2);\n var borderColor = tinycolor(self.ctx.data[0].dataKey.color);\n borderColor.setAlpha(1);\n var dataset = {\n label: self.ctx.datasources[0].name,\n data: [],\n backgroundColor: backgroundColor.toRgbString(),\n borderColor: borderColor.toRgbString(),\n pointBackgroundColor: borderColor.toRgbString(),\n pointBorderColor: borderColor.darken().toRgbString(),\n borderWidth: 1\n }\n \n barData.datasets.push(dataset);\n \n for (var i = 0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n barData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n }\n \n var floatingPoint;\n if (typeof self.ctx.decimals !== 'undefined' && self.ctx.decimals !== null) {\n floatingPoint = self.ctx.widget.config.decimals;\n } else {\n floatingPoint = 2;\n }\n\n var ctx = $('#radarChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'radar',\n data: barData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scale: {\n ticks: {\n callback: function(tick) {\n \treturn tick.toFixed(floatingPoint);\n }\n }\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n } \n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n if (self.ctx.height >= 70) {\n self.ctx.chart.resize();\n }\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n", "controllerScript": "self.onInit = function() {\n $scope = self.ctx.$scope;\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showTooltip = utils.defaultValue(settings.showTooltip, true);\n \n Chart.defaults.global.tooltips.enabled = settings.showTooltip;\n \n var barData = {\n labels: [],\n datasets: []\n };\n\n var backgroundColor = tinycolor(self.ctx.data[0].dataKey.color);\n backgroundColor.setAlpha(0.2);\n var borderColor = tinycolor(self.ctx.data[0].dataKey.color);\n borderColor.setAlpha(1);\n var dataset = {\n label: self.ctx.datasources[0].name,\n data: [],\n backgroundColor: backgroundColor.toRgbString(),\n borderColor: borderColor.toRgbString(),\n pointBackgroundColor: borderColor.toRgbString(),\n pointBorderColor: borderColor.darken().toRgbString(),\n borderWidth: 1\n }\n \n barData.datasets.push(dataset);\n \n for (var i = 0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n var units = dataKey.units && dataKey.units.length ? dataKey.units : self.ctx.units;\n units = units ? (' (' + units + ')') : '';\n barData.labels.push(dataKey.label + units);\n dataset.data.push(0);\n }\n \n var floatingPoint;\n if (typeof self.ctx.decimals !== 'undefined' && self.ctx.decimals !== null) {\n floatingPoint = self.ctx.widget.config.decimals;\n } else {\n floatingPoint = 2;\n }\n\n var ctx = $('#radarChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'radar',\n data: barData,\n options: {\n responsive: false,\n maintainAspectRatio: false,\n scale: {\n ticks: {\n callback: function(tick) {\n \treturn tick.toFixed(floatingPoint);\n }\n }\n }\n }\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var decimals;\n if (typeof cellData.dataKey.decimals !== 'undefined' \n && cellData.dataKey.decimals !== null ) {\n decimals = cellData.dataKey.decimals; \n } else {\n decimals = self.ctx.decimals;\n }\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = self.ctx.utils.formatValue(tvPair[1], decimals);\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n } \n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n if (self.ctx.height >= 70) {\n self.ctx.chart.resize();\n }\n}\n\nself.onDestroy = function() {\n self.ctx.chart.destroy();\n self.ctx.chart = null;\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"showTooltip\": {\n \"title\": \"Show Tooltip\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTooltip\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-chart-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Radar\"}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Radar\"}"
} }
}, },
@ -146,9 +153,12 @@
"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.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}", "dataKeySettingsSchema": "{}",
"settingsDirective": "tb-flot-line-widget-settings",
"dataKeySettingsDirective": "tb-flot-line-key-settings",
"latestDataKeySettingsDirective": "tb-flot-latest-key-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 +174,13 @@
"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.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",
"dataKeySettingsDirective": "tb-flot-line-key-settings",
"latestDataKeySettingsDirective": "tb-flot-latest-key-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 +196,12 @@
"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.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",
"dataKeySettingsDirective": "tb-flot-bar-key-settings",
"latestDataKeySettingsDirective": "tb-flot-latest-key-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\":{}}"
} }
} }

30
application/src/main/data/json/system/widget_bundles/control_widgets.json

File diff suppressed because one or more lines are too long

3
application/src/main/data/json/system/widget_bundles/date.json

@ -19,8 +19,9 @@
"templateHtml": "<tb-date-range-navigator-widget [ctx]=\"ctx\"></tb-date-range-navigator-widget>", "templateHtml": "<tb-date-range-navigator-widget [ctx]=\"ctx\"></tb-date-range-navigator-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n}\n", "controllerScript": "self.onInit = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"hidePicker\": {\n \"title\": \"Hide date range picker\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"onePanel\": {\n \"title\": \"Date range picker one panel\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"autoConfirm\": {\n \"title\": \"Date range picker auto confirm\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"showTemplate\": {\n \"title\": \"Date range picker show template\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"firstDayOfWeek\": {\n \"title\": \"First day of the week\",\n \"type\": \"number\",\n \"default\": 1\n },\n \"hideInterval\": {\n \"title\": \"Hide interval\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"initialInterval\": {\n\t\t\t\t\"title\": \"Initial interval\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"week\"\n\t\t\t},\n \"hideStepSize\": {\n \"title\": \"Hide step size\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"stepSize\": {\n\t\t\t\t\"title\": \"Initial step size\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"day\"\n\t\t\t},\n \"hideLabels\": {\n \"title\": \"Hide labels\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"useSessionStorage\": {\n \"title\": \"Use session storage\",\n \"type\": \"boolean\",\n \"default\": true\n }\n }\n },\n \"form\": [\n \"hidePicker\",\n\t\t\"onePanel\",\n\t\t\"autoConfirm\",\n\t\t\"showTemplate\",\n\t\t\"firstDayOfWeek\",\n \"hideInterval\",\n {\n\t\t\t\"key\": \"initialInterval\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n \"hideStepSize\",\n {\n\t\t\t\"key\": \"stepSize\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t\"hideLabels\",\n\t\t\"useSessionStorage\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-date-range-navigator-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"defaultInterval\":\"week\",\"stepSize\":\"day\"},\"title\":\"Date-range-navigator\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"defaultInterval\":\"week\",\"stepSize\":\"day\"},\"title\":\"Date-range-navigator\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
} }

39
application/src/main/data/json/system/widget_bundles/digital_gauges.json

@ -18,9 +18,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":36,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"arc\"},\"title\":\"Gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":36,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"arc\"},\"title\":\"Gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -36,9 +37,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < -60) {\\n\\tvalue = 60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[\"#304ffe\",\"#7e57c2\",\"#ff4081\",\"#d32f2f\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"dashThickness\":1.5,\"minValue\":-60,\"gaugeColor\":\"#333333\",\"neonGlowBrightness\":35,\"gaugeType\":\"donut\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital thermometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < -60) {\\n\\tvalue = 60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[\"#304ffe\",\"#7e57c2\",\"#ff4081\",\"#d32f2f\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"dashThickness\":1.5,\"minValue\":-60,\"gaugeColor\":\"#333333\",\"neonGlowBrightness\":35,\"gaugeType\":\"donut\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital thermometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -54,9 +56,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 45) {\\n\\tvalue = 45;\\n} else if (value > 130) {\\n\\tvalue = 130;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"arc\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital speedometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 45) {\\n\\tvalue = 45;\\n} else if (value > 130) {\\n\\tvalue = 130;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"arc\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital speedometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -72,9 +75,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":70,\"dashThickness\":1,\"gaugeType\":\"arc\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Neon gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":70,\"dashThickness\":1,\"gaugeType\":\"arc\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Neon gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -90,9 +94,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 180) {\\n\\tvalue = 180;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"arc\"},\"title\":\"LCD gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 180) {\\n\\tvalue = 180;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"arc\"},\"title\":\"LCD gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -108,9 +113,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"400\",\"size\":16},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"verticalBar\",\"units\":\"%\"},\"title\":\"LCD bar gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"400\",\"size\":16},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"verticalBar\",\"units\":\"%\"},\"title\":\"LCD bar gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -126,9 +132,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#388e3c\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"gaugeType\":\"donut\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Simple neon gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#388e3c\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"gaugeType\":\"donut\",\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Simple neon gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -144,9 +151,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":12,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":1.5,\"gaugeColor\":\"#eeeeee\",\"showTitle\":false,\"gaugeType\":\"verticalBar\"},\"title\":\"Vertical bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":12,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":1.5,\"gaugeColor\":\"#eeeeee\",\"showTitle\":false,\"gaugeType\":\"verticalBar\"},\"title\":\"Vertical bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -162,9 +170,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>\n", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>\n",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "\nself.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "\nself.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#ef6c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"gaugeColor\":\"#eeeeee\",\"gaugeType\":\"donut\"},\"title\":\"Simple gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#ef6c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"gaugeColor\":\"#eeeeee\",\"gaugeType\":\"donut\"},\"title\":\"Simple gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -180,9 +189,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 80) {\\n\\tvalue = 80;\\n} else if (value > 160) {\\n\\tvalue = 160;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"horizontalBar\",\"showTitle\":false,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital horizontal bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 80) {\\n\\tvalue = 80;\\n} else if (value > 160) {\\n\\tvalue = 160;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"horizontalBar\",\"showTitle\":false,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital horizontal bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },
@ -198,9 +208,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#7cb342\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"roundedLineCap\":true,\"gaugeType\":\"donut\"},\"title\":\"Mini gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#7cb342\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"roundedLineCap\":true,\"gaugeType\":\"donut\"},\"title\":\"Mini gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -216,9 +227,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>\n", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>\n",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"horizontalBar\"},\"title\":\"Horizontal bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"horizontalBar\"},\"title\":\"Horizontal bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"
} }
}, },
@ -234,9 +246,10 @@
"resources": [], "resources": [],
"templateHtml": "<canvas id=\"digitalGauge\"></canvas>", "templateHtml": "<canvas id=\"digitalGauge\"></canvas>",
"templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n", "templateCss": "#gauge {\n text-align: center;\n /* margin-left: -100px;\n margin-right: -100px;*/\n /*margin-top: -50px;*/\n \n}\n",
"controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n", "controllerScript": "self.onInit = function() {\n self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, 'digitalGauge'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n self.ctx.gauge.resize();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n singleEntity: true\n };\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n self.ctx.gauge.destroy();\n}\n\n",
"settingsSchema": "{}", "settingsSchema": "{}",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-digital-gauge-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#3d5afe\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":14},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":8,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#cccccc\"},\"neonGlowBrightness\":20,\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"verticalBar\",\"showTitle\":false,\"minValue\":-60,\"dashThickness\":1.2,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital vertical bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#3d5afe\",\"#f44336\"],\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":14},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":8,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#cccccc\"},\"neonGlowBrightness\":20,\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"verticalBar\",\"showTitle\":false,\"minValue\":-60,\"dashThickness\":1.2,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"linear\"},\"title\":\"Digital vertical bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
} }

5
application/src/main/data/json/system/widget_bundles/edge_widgets.json

@ -19,10 +19,11 @@
"templateHtml": "<tb-edges-overview-widget \n [ctx]=\"ctx\">\n</tb-edges-overview-widget>", "templateHtml": "<tb-edges-overview-widget \n [ctx]=\"ctx\">\n</tb-edges-overview-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.onDestroy = function() {\n};\n", "controllerScript": "self.onInit = function() {\n};\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.onDestroy = function() {\n};\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EdgeOverviewSettings\",\n \"properties\": {\n \"enableDefaultTitle\": {\n \"title\": \"Display default title\",\n \"type\": \"boolean\",\n \"default\": true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"enableDefaultTitle\"\n ]\n}", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-edge-quick-overview-widget-settings",
"defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"showTitleIcon\":true,\"titleIcon\":\"router\",\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edge Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"widgetStyle\":{},\"actions\":{}}" "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"showTitleIcon\":true,\"titleIcon\":\"router\",\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{},\"title\":\"Edge Quick Overview\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"widgetStyle\":{},\"actions\":{}}"
} }
} }
] ]
} }

12
application/src/main/data/json/system/widget_bundles/entity_admin_widgets.json

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

12
application/src/main/data/json/system/widget_bundles/gpio_widgets.json

File diff suppressed because one or more lines are too long

93
application/src/main/data/json/system/widget_bundles/input_widgets.json

File diff suppressed because one or more lines are too long

77
application/src/main/data/json/system/widget_bundles/maps.json

File diff suppressed because one or more lines are too long

8
application/src/main/data/json/system/widget_bundles/navigation_widgets.json

@ -19,8 +19,9 @@
"templateHtml": "<tb-navigation-cards-widget [ctx]=\"ctx\"></tb-navigation-cards-widget>", "templateHtml": "<tb-navigation-cards-widget [ctx]=\"ctx\"></tb-navigation-cards-widget>",
"templateCss": "/*#widget-container {\n overflow-y: auto;\n box-sizing: content-box !important;\n cursor: auto;\n}*/\n\n#widget-container #container {\n overflow-y: auto;\n box-sizing: content-box;\n cursor: auto;\n}", "templateCss": "/*#widget-container {\n overflow-y: auto;\n box-sizing: content-box !important;\n cursor: auto;\n}*/\n\n#widget-container #container {\n overflow-y: auto;\n box-sizing: content-box;\n cursor: auto;\n}",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onResize = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onDestroy = function() {\n}\n", "controllerScript": "self.onInit = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onResize = function() {\n self.ctx.$scope.navigationCardsWidget.resize();\n}\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"filterType\": {\n \"title\": \"Filter type\",\n \"type\": \"string\",\n \"default\": \"all\"\n },\n \"filter\": {\n \"title\": \"Items\",\n \"type\": \"array\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"filterType\",\n \"type\": \"radios\",\n \"direction\": \"row\",\n \"titleMap\": [\n {\n \"value\": \"all\",\n \"name\": \"All items\"\n },\n {\n \"value\": \"include\",\n \"name\": \"Include items\"\n },\n {\n \"value\": \"exclude\",\n \"name\": \"Exclude items\"\n }\n ]\n },\n {\n \"key\": \"filter\",\n \"type\": \"rc-select\",\n \"condition\": \"model.filterType !== 'all'\",\n \"tags\": true,\n \"placeholder\": \"Enter urls to filter\",\n \"items\": [{\"value\": \"/devices\", \"label\": \"/devices\"}, {\"value\": \"/assets\", \"label\": \"/assets\"}, {\"value\": \"/deviceProfiles\", \"label\": \"/deviceProfiles\"}]\n }\n ]\n}\n", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-navigation-cards-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"rgba(255,255,255,0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"filterType\":\"all\"},\"title\":\"Navigation cards\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}" "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"rgba(255,255,255,0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"filterType\":\"all\"},\"title\":\"Navigation cards\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
} }
}, },
@ -37,10 +38,11 @@
"templateHtml": "<tb-navigation-card-widget [ctx]=\"ctx\"></tb-navigation-card-widget>", "templateHtml": "<tb-navigation-card-widget [ctx]=\"ctx\"></tb-navigation-card-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "self.onInit = function() {\n\n}\n\n\nself.onDestroy = function() {\n}\n", "controllerScript": "self.onInit = function() {\n\n}\n\n\nself.onDestroy = function() {\n}\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"name\": {\n \"title\": \"Title\",\n \"type\": \"string\",\n \"default\": \"{i18n:device.devices}\"\n },\n \"icon\": {\n \"title\": \"icon\",\n \"type\": \"string\",\n \"default\": \"devices_other\"\n },\n \"path\": {\n \"title\": \"Navigation path\",\n \"type\": \"string\",\n \"default\": \"/devices\"\n }\n },\n \"required\": [\"name\", \"icon\", \"path\"]\n },\n \"form\": [\n \"name\",\n {\n \"key\": \"icon\",\n \"type\": \"icon\"\n },\n \"path\"\n ]\n}\n", "settingsSchema": "",
"dataKeySettingsSchema": "{}\n", "dataKeySettingsSchema": "{}\n",
"settingsDirective": "tb-navigation-card-widget-settings",
"defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"rgba(255,255,255,0)\",\"color\":\"rgba(255,255,255,0.87)\",\"padding\":\"8px\",\"settings\":{\"name\":\"{i18n:device.devices}\",\"icon\":\"devices_other\",\"path\":\"/devices\"},\"title\":\"Navigation card\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}" "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"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\":false,\"backgroundColor\":\"rgba(255,255,255,0)\",\"color\":\"rgba(255,255,255,0.87)\",\"padding\":\"8px\",\"settings\":{\"name\":\"{i18n:device.devices}\",\"icon\":\"devices_other\",\"path\":\"/devices\"},\"title\":\"Navigation card\",\"dropShadow\":false,\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"showLegend\":false}"
} }
} }
] ]
} }

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

27
ui-ngx/extra-webpack.config.js

@ -18,6 +18,7 @@ const JavaScriptOptimizerPlugin = require("@angular-devkit/build-angular/src/web
const webpack = require("webpack"); const webpack = require("webpack");
const dirTree = require("directory-tree"); const dirTree = require("directory-tree");
const ngWebpack = require('@ngtools/webpack'); const ngWebpack = require('@ngtools/webpack');
const keysTransformer = require('ts-transformer-keys/transformer').default;
var langs = []; var langs = [];
@ -58,17 +59,37 @@ module.exports = (config, options) => {
}) })
); );
const index = config.plugins.findIndex(p => p instanceof ngWebpack.ivy.AngularWebpackPlugin || p instanceof ngWebpack.AngularWebpackPlugin);
let angularWebpackPlugin = config.plugins[index];
if (config.mode === 'production') { if (config.mode === 'production') {
const index = config.plugins.findIndex(p => p instanceof ngWebpack.ivy.AngularWebpackPlugin); const angularCompilerOptions = angularWebpackPlugin.pluginOptions;
const angularCompilerOptions = config.plugins[index].pluginOptions;
angularCompilerOptions.emitClassMetadata = true; angularCompilerOptions.emitClassMetadata = true;
angularCompilerOptions.emitNgModuleScope = true; angularCompilerOptions.emitNgModuleScope = true;
config.plugins.splice(index, 1); config.plugins.splice(index, 1);
config.plugins.push(new ngWebpack.ivy.AngularWebpackPlugin(angularCompilerOptions)); angularWebpackPlugin = new ngWebpack.ivy.AngularWebpackPlugin(angularCompilerOptions);
config.plugins.push(angularWebpackPlugin);
const javascriptOptimizerOptions = config.optimization.minimizer[1].options; const javascriptOptimizerOptions = config.optimization.minimizer[1].options;
delete javascriptOptimizerOptions.define.ngJitMode; delete javascriptOptimizerOptions.define.ngJitMode;
config.optimization.minimizer.splice(1, 1); config.optimization.minimizer.splice(1, 1);
config.optimization.minimizer.push(new JavaScriptOptimizerPlugin(javascriptOptimizerOptions)); config.optimization.minimizer.push(new JavaScriptOptimizerPlugin(javascriptOptimizerOptions));
} }
addTransformerToAngularWebpackPlugin(angularWebpackPlugin, keysTransformer);
return config; return config;
}; };
function addTransformerToAngularWebpackPlugin(plugin, transformer) {
const originalCreateFileEmitter = plugin.createFileEmitter; // private method
plugin.createFileEmitter = function (program, transformers, getExtraDependencies, onAfterEmit) {
if (!transformers) {
transformers = {};
}
if (!transformers.before) {
transformers = { before: [] };
}
transformers.before.push(transformer(program.getProgram()));
return originalCreateFileEmitter.apply(plugin, [program, transformers, getExtraDependencies, onAfterEmit]);
};
}

1
ui-ngx/package.json

@ -92,6 +92,7 @@
"systemjs": "6.11.0", "systemjs": "6.11.0",
"tinycolor2": "^1.4.2", "tinycolor2": "^1.4.2",
"tooltipster": "^4.2.8", "tooltipster": "^4.2.8",
"ts-transformer-keys": "^0.4.3",
"tslib": "^2.3.1", "tslib": "^2.3.1",
"tv4": "^1.3.0", "tv4": "^1.3.0",
"typeface-roboto": "^1.1.13", "typeface-roboto": "^1.1.13",

6
ui-ngx/src/app/core/api/entity-data-subscription.ts

@ -872,7 +872,11 @@ export class EntityDataSubscription {
} }
} }
if (tsDataKeys.length) { if (tsDataKeys.length) {
this.timeseriesTimer = setTimeout(this.onTimeseriesTick.bind(this, tsDataKeys, true), 0); if (this.history) {
this.onTimeseriesTick(tsDataKeys, true);
} else {
this.timeseriesTimer = setTimeout(this.onTimeseriesTick.bind(this, tsDataKeys, true), 0);
}
} }
if (latestDataKeys.length) { if (latestDataKeys.length) {
this.onLatestTick(latestDataKeys, detectChanges); this.onLatestTick(latestDataKeys, detectChanges);

2
ui-ngx/src/app/core/http/rule-chain.service.ts

@ -219,7 +219,7 @@ export class RuleChainService {
map((res) => { map((res) => {
if (nodeDefinition.configDirective && nodeDefinition.configDirective.length) { if (nodeDefinition.configDirective && nodeDefinition.configDirective.length) {
const selector = snakeCase(nodeDefinition.configDirective, '-'); const selector = snakeCase(nodeDefinition.configDirective, '-');
const componentFactory = res.find((factory) => const componentFactory = res.factories.find((factory) =>
factory.selector === selector); factory.selector === selector);
if (componentFactory) { if (componentFactory) {
this.ruleNodeConfigFactories[nodeDefinition.configDirective] = componentFactory; this.ruleNodeConfigFactories[nodeDefinition.configDirective] = componentFactory;

41
ui-ngx/src/app/core/services/resources.service.ts

@ -30,6 +30,11 @@ import { IModulesMap } from '@modules/common/modules-map.models';
declare const System; declare const System;
export interface ModulesWithFactories {
modules: Type<any>[];
factories: ComponentFactory<any>[];
}
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -37,7 +42,7 @@ export class ResourcesService {
private loadedResources: { [url: string]: ReplaySubject<any> } = {}; private loadedResources: { [url: string]: ReplaySubject<any> } = {};
private loadedModules: { [url: string]: ReplaySubject<Type<any>[]> } = {}; private loadedModules: { [url: string]: ReplaySubject<Type<any>[]> } = {};
private loadedFactories: { [url: string]: ReplaySubject<ComponentFactory<any>[]> } = {}; private loadedModulesAndFactories: { [url: string]: ReplaySubject<ModulesWithFactories> } = {};
private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0]; private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0];
@ -64,13 +69,13 @@ export class ResourcesService {
return this.loadResourceByType(fileType, url); return this.loadResourceByType(fileType, url);
} }
public loadFactories(url: string, modulesMap: IModulesMap): Observable<ComponentFactory<any>[]> { public loadFactories(url: string, modulesMap: IModulesMap): Observable<ModulesWithFactories> {
if (this.loadedFactories[url]) { if (this.loadedModulesAndFactories[url]) {
return this.loadedFactories[url].asObservable(); return this.loadedModulesAndFactories[url].asObservable();
} }
modulesMap.init(); modulesMap.init();
const subject = new ReplaySubject<ComponentFactory<any>[]>(); const subject = new ReplaySubject<ModulesWithFactories>();
this.loadedFactories[url] = subject; this.loadedModulesAndFactories[url] = subject;
import('@angular/compiler').then( import('@angular/compiler').then(
() => { () => {
System.import(url).then( System.import(url).then(
@ -88,25 +93,29 @@ export class ResourcesService {
c.ngModuleFactory.create(this.injector); c.ngModuleFactory.create(this.injector);
componentFactories.push(...c.componentFactories); componentFactories.push(...c.componentFactories);
} }
this.loadedFactories[url].next(componentFactories); const modulesWithFactories: ModulesWithFactories = {
this.loadedFactories[url].complete(); modules,
factories: componentFactories
};
this.loadedModulesAndFactories[url].next(modulesWithFactories);
this.loadedModulesAndFactories[url].complete();
} catch (e) { } catch (e) {
this.loadedFactories[url].error(new Error(`Unable to init module from url: ${url}`)); this.loadedModulesAndFactories[url].error(new Error(`Unable to init module from url: ${url}`));
delete this.loadedFactories[url]; delete this.loadedModulesAndFactories[url];
} }
}, },
(e) => { (e) => {
this.loadedFactories[url].error(new Error(`Unable to compile module from url: ${url}`)); this.loadedModulesAndFactories[url].error(new Error(`Unable to compile module from url: ${url}`));
delete this.loadedFactories[url]; delete this.loadedModulesAndFactories[url];
}); });
} else { } else {
this.loadedFactories[url].error(new Error(`Module '${url}' doesn't have default export!`)); this.loadedModulesAndFactories[url].error(new Error(`Module '${url}' doesn't have default export!`));
delete this.loadedFactories[url]; delete this.loadedModulesAndFactories[url];
} }
}, },
(e) => { (e) => {
this.loadedFactories[url].error(new Error(`Unable to load module from url: ${url}`)); this.loadedModulesAndFactories[url].error(new Error(`Unable to load module from url: ${url}`));
delete this.loadedFactories[url]; delete this.loadedModulesAndFactories[url];
} }
); );
} }

4
ui-ngx/src/app/core/utils.ts

@ -313,6 +313,10 @@ export function deepClone<T>(target: T, ignoreFields?: string[]): T {
return target; return target;
} }
export function extractType<T extends object>(target: any, keysOfProps: (keyof T)[]): T {
return _.pick(target, keysOfProps);
}
export function isEqual(a: any, b: any): boolean { export function isEqual(a: any, b: any): boolean {
return _.isEqual(a, b); return _.isEqual(a, b);
} }

5
ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.html

@ -33,9 +33,8 @@
<tb-widget-config <tb-widget-config
[aliasController]="aliasController" [aliasController]="aliasController"
[functionsOnly]="false" [functionsOnly]="false"
[entityAliases]="dashboard.configuration.entityAliases" [dashboard]="dashboard"
[filters]="dashboard.configuration.filters" [widget]="widget"
[dashboardStates]="dashboard.configuration.states"
formControlName="widgetConfig"> formControlName="widgetConfig">
</tb-widget-config> </tb-widget-config>
</fieldset> </fieldset>

5
ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts

@ -100,7 +100,10 @@ export class AddWidgetDialogComponent extends DialogComponent<AddWidgetDialogCom
isDataEnabled, isDataEnabled,
settingsSchema, settingsSchema,
dataKeySettingsSchema, dataKeySettingsSchema,
latestDataKeySettingsSchema latestDataKeySettingsSchema,
settingsDirective: widgetInfo.settingsDirective,
dataKeySettingsDirective: widgetInfo.dataKeySettingsDirective,
latestDataKeySettingsDirective: widgetInfo.latestDataKeySettingsDirective
}; };
this.widgetFormGroup = this.fb.group({ this.widgetFormGroup = this.fb.group({

5
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.html

@ -20,9 +20,8 @@
<tb-widget-config <tb-widget-config
[aliasController]="aliasController" [aliasController]="aliasController"
[functionsOnly]="widgetEditMode" [functionsOnly]="widgetEditMode"
[entityAliases]="dashboard.configuration.entityAliases" [dashboard]="dashboard"
[filters]="dashboard.configuration.filters" [widget]="widget"
[dashboardStates]="dashboard.configuration.states"
formControlName="widgetConfig"> formControlName="widgetConfig">
</tb-widget-config> </tb-widget-config>
</fieldset> </fieldset>

5
ui-ngx/src/app/modules/home/components/dashboard-page/edit-widget.component.ts

@ -121,7 +121,10 @@ export class EditWidgetComponent extends PageComponent implements OnInit, OnChan
isDataEnabled, isDataEnabled,
settingsSchema, settingsSchema,
dataKeySettingsSchema, dataKeySettingsSchema,
latestDataKeySettingsSchema latestDataKeySettingsSchema,
settingsDirective: widgetInfo.settingsDirective,
dataKeySettingsDirective: widgetInfo.dataKeySettingsDirective,
latestDataKeySettingsDirective: widgetInfo.latestDataKeySettingsDirective
}; };
this.widgetFormGroup.reset({widgetConfig: this.widgetConfig}); this.widgetFormGroup.reset({widgetConfig: this.widgetConfig});
} }

5
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -149,6 +149,8 @@ import {
} from '@home/components/tokens'; } from '@home/components/tokens';
import { DashboardStateComponent } from '@home/components/dashboard-page/dashboard-state.component'; import { DashboardStateComponent } from '@home/components/dashboard-page/dashboard-state.component';
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component'; import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
import { WidgetSettingsComponent } from '@home/components/widget/widget-settings.component';
@NgModule({ @NgModule({
declarations: declarations:
@ -183,6 +185,7 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
WidgetContainerComponent, WidgetContainerComponent,
WidgetComponent, WidgetComponent,
LegendComponent, LegendComponent,
WidgetSettingsComponent,
WidgetConfigComponent, WidgetConfigComponent,
EntityFilterViewComponent, EntityFilterViewComponent,
EntityFilterComponent, EntityFilterComponent,
@ -275,6 +278,7 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
CommonModule, CommonModule,
SharedModule, SharedModule,
SharedHomeComponentsModule, SharedHomeComponentsModule,
WidgetSettingsModule,
Lwm2mProfileComponentsModule, Lwm2mProfileComponentsModule,
SnmpDeviceProfileTransportModule, SnmpDeviceProfileTransportModule,
StatesControllerModule, StatesControllerModule,
@ -303,6 +307,7 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
WidgetContainerComponent, WidgetContainerComponent,
WidgetComponent, WidgetComponent,
LegendComponent, LegendComponent,
WidgetSettingsComponent,
WidgetConfigComponent, WidgetConfigComponent,
EntityFilterViewComponent, EntityFilterViewComponent,
EntityFilterComponent, EntityFilterComponent,

2
ui-ngx/src/app/modules/home/components/import-export/import-dialog-csv.component.html

@ -40,7 +40,7 @@
label="{{importFileLabel | translate}}" label="{{importFileLabel | translate}}"
[allowedExtensions]="'csv,txt'" [allowedExtensions]="'csv,txt'"
[accept]="'.csv,application/csv,text/csv,.txt,text/plain'" [accept]="'.csv,application/csv,text/csv,.txt,text/plain'"
dropLabel="{{'import.drop-file-csv' | translate}}"> dropLabel="{{'import.drop-file-csv-or' | translate}}">
</tb-file-input> </tb-file-input>
</fieldset> </fieldset>
</form> </form>

2
ui-ngx/src/app/modules/home/components/import-export/import-dialog.component.html

@ -35,7 +35,7 @@
formControlName="jsonContent" formControlName="jsonContent"
required required
label="{{importFileLabel | translate}}" label="{{importFileLabel | translate}}"
dropLabel="{{ 'import.drop-file' | translate }}" dropLabel="{{ 'import.drop-json-file-or' | translate }}"
accept=".json,application/json" accept=".json,application/json"
allowedExtensions="json"> allowedExtensions="json">
</tb-file-input> </tb-file-input>

4
ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.html

@ -31,7 +31,11 @@
<div mat-dialog-content> <div mat-dialog-content>
<tb-data-key-config #dataKeyConfig <tb-data-key-config #dataKeyConfig
[dataKeySettingsSchema]="data.dataKeySettingsSchema" [dataKeySettingsSchema]="data.dataKeySettingsSchema"
[dataKeySettingsDirective]="data.dataKeySettingsDirective"
[entityAliasId]="data.entityAliasId" [entityAliasId]="data.entityAliasId"
[dashboard]="data.dashboard"
[aliasController]="data.aliasController"
[widget]="data.widget"
[showPostProcessing]="data.showPostProcessing" [showPostProcessing]="data.showPostProcessing"
[callbacks]="data.callbacks" [callbacks]="data.callbacks"
formControlName="dataKey"> formControlName="dataKey">

8
ui-ngx/src/app/modules/home/components/widget/data-key-config-dialog.component.ts

@ -22,13 +22,19 @@ import { AppState } from '@core/core.state';
import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { DataKey } from '@shared/models/widget.models'; import { DataKey, Widget } from '@shared/models/widget.models';
import { DataKeysCallbacks } from './data-keys.component.models'; import { DataKeysCallbacks } from './data-keys.component.models';
import { DataKeyConfigComponent } from '@home/components/widget/data-key-config.component'; import { DataKeyConfigComponent } from '@home/components/widget/data-key-config.component';
import { Dashboard } from '@shared/models/dashboard.models';
import { IAliasController } from '@core/api/widget-api.models';
export interface DataKeyConfigDialogData { export interface DataKeyConfigDialogData {
dataKey: DataKey; dataKey: DataKey;
dataKeySettingsSchema: any; dataKeySettingsSchema: any;
dataKeySettingsDirective: string;
dashboard: Dashboard;
aliasController: IAliasController;
widget: Widget;
entityAliasId?: string; entityAliasId?: string;
showPostProcessing?: boolean; showPostProcessing?: boolean;
callbacks?: DataKeysCallbacks; callbacks?: DataKeysCallbacks;

7
ui-ngx/src/app/modules/home/components/widget/data-key-config.component.html

@ -98,9 +98,12 @@
</mat-tab> </mat-tab>
<mat-tab [formGroup]="dataKeySettingsFormGroup" label="{{ 'datakey.advanced' | translate }}" *ngIf="displayAdvanced"> <mat-tab [formGroup]="dataKeySettingsFormGroup" label="{{ 'datakey.advanced' | translate }}" *ngIf="displayAdvanced">
<div class="mat-padding" fxLayout="column"> <div class="mat-padding" fxLayout="column">
<tb-json-form <tb-widget-settings
[dashboard]="dashboard"
[aliasController]="aliasController"
[widget]="widget"
formControlName="settings"> formControlName="settings">
</tb-json-form> </tb-widget-settings>
</div> </div>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>

29
ui-ngx/src/app/modules/home/components/widget/data-key-config.component.ts

@ -18,7 +18,7 @@ import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@an
import { PageComponent } from '@shared/components/page.component'; import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { DataKey } from '@shared/models/widget.models'; import { DataKey, Widget } from '@shared/models/widget.models';
import { import {
ControlValueAccessor, ControlValueAccessor,
FormBuilder, FormBuilder,
@ -41,6 +41,8 @@ import { alarmFields } from '@shared/models/alarm.models';
import { JsFuncComponent } from '@shared/components/js-func.component'; import { JsFuncComponent } from '@shared/components/js-func.component';
import { JsonFormComponentData } from '@shared/components/json-form/json-form-component.models'; import { JsonFormComponentData } from '@shared/components/json-form/json-form-component.models';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { Dashboard } from '@shared/models/dashboard.models';
import { IAliasController } from '@core/api/widget-api.models';
@Component({ @Component({
selector: 'tb-data-key-config', selector: 'tb-data-key-config',
@ -69,9 +71,21 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con
@Input() @Input()
callbacks: DataKeysCallbacks; callbacks: DataKeysCallbacks;
@Input()
dashboard: Dashboard;
@Input()
aliasController: IAliasController;
@Input()
widget: Widget;
@Input() @Input()
dataKeySettingsSchema: any; dataKeySettingsSchema: any;
@Input()
dataKeySettingsDirective: string;
@Input() @Input()
showPostProcessing = true; showPostProcessing = true;
@ -121,11 +135,16 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con
type: DataKeyType.alarm type: DataKeyType.alarm
}); });
} }
if (this.dataKeySettingsSchema && this.dataKeySettingsSchema.schema) { if (this.dataKeySettingsSchema && this.dataKeySettingsSchema.schema ||
this.dataKeySettingsDirective && this.dataKeySettingsDirective.length) {
this.displayAdvanced = true; this.displayAdvanced = true;
this.dataKeySettingsData = { this.dataKeySettingsData = {
schema: this.dataKeySettingsSchema.schema, schema: this.dataKeySettingsSchema?.schema || {
form: this.dataKeySettingsSchema.form || ['*'] type: 'object',
properties: {}
},
form: this.dataKeySettingsSchema?.form || ['*'],
settingsDirective: this.dataKeySettingsDirective
}; };
this.dataKeySettingsFormGroup = this.fb.group({ this.dataKeySettingsFormGroup = this.fb.group({
settings: [null, []] settings: [null, []]
@ -273,7 +292,7 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con
} }
}; };
} }
if (this.displayAdvanced && !this.dataKeySettingsFormGroup.valid) { if (this.displayAdvanced && (!this.dataKeySettingsFormGroup.valid || !this.modelValue.settings)) {
return { return {
dataKeySettings: { dataKeySettings: {
valid: false valid: false

2
ui-ngx/src/app/modules/home/components/widget/data-keys.component.html

@ -17,7 +17,7 @@
--> -->
<mat-form-field appearance="standard" [formGroup]="keysListFormGroup" class="mat-block"> <mat-form-field appearance="standard" [formGroup]="keysListFormGroup" class="mat-block">
<mat-chip-list #chipList formControlName="keys" tb-chip-draggable (chipDrop)="onChipDrop($event)"> <mat-chip-list #chipList formControlName="keys" tb-chip-draggable (chipDrop)="onChipDrop($event)">
<mat-chip <mat-chip class="tb-datakey-chip"
*ngFor="let key of keys; let $index = index" *ngFor="let key of keys; let $index = index"
[selectable]="!disabled" [selectable]="!disabled"
[removable]="!disabled && !isEntityCountDatasource" [removable]="!disabled && !isEntityCountDatasource"

67
ui-ngx/src/app/modules/home/components/widget/data-keys.component.scss

@ -13,49 +13,48 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
:host {
.mat-chip.mat-standard-chip {
overflow: hidden;
.tb-attribute-chip { .mat-chip.mat-standard-chip.tb-datakey-chip {
max-width: 100%; overflow: hidden;
color: rgb(66, 66, 66);
font-weight: normal;
font-size: 16px;
.tb-chip-drag-handle { .tb-attribute-chip {
cursor: move; max-width: 100%;
color: rgb(66, 66, 66);
font-weight: normal;
font-size: 16px;
mat-icon { .tb-chip-drag-handle {
pointer-events: none; cursor: move;
}
}
.tb-chip-labels { mat-icon {
display: flex; pointer-events: none;
flex-direction: row; }
align-items: flex-end; }
min-width: 0;
.tb-chip-label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tb-chip-separator { .tb-chip-labels {
white-space: pre; display: flex;
} flex-direction: row;
align-items: flex-end;
min-width: 0;
.tb-chip-label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.mat-chip-remove.mat-icon { .tb-chip-separator {
width: 24px; white-space: pre;
height: 24px;
font-size: 24px;
margin-left: 0;
color: inherit;
opacity: inherit;
} }
} }
.mat-chip-remove.mat-icon {
width: 24px;
height: 24px;
font-size: 24px;
margin-left: 0;
color: inherit;
opacity: inherit;
}
} }
} }

16
ui-ngx/src/app/modules/home/components/widget/data-keys.component.ts

@ -46,7 +46,7 @@ import { MatAutocomplete } from '@angular/material/autocomplete';
import { MatChipInputEvent, MatChipList } from '@angular/material/chips'; import { MatChipInputEvent, MatChipList } from '@angular/material/chips';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { DataKey, DatasourceType, JsonSettingsSchema, widgetType } from '@shared/models/widget.models'; import { DataKey, DatasourceType, Widget, JsonSettingsSchema, widgetType } from '@shared/models/widget.models';
import { IAliasController } from '@core/api/widget-api.models'; import { IAliasController } from '@core/api/widget-api.models';
import { DataKeysCallbacks } from './data-keys.component.models'; import { DataKeysCallbacks } from './data-keys.component.models';
import { alarmFields } from '@shared/models/alarm.models'; import { alarmFields } from '@shared/models/alarm.models';
@ -61,6 +61,7 @@ import {
} from '@home/components/widget/data-key-config-dialog.component'; } from '@home/components/widget/data-key-config-dialog.component';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { MatChipDropEvent } from '@app/shared/components/mat-chip-draggable.directive'; import { MatChipDropEvent } from '@app/shared/components/mat-chip-draggable.directive';
import { Dashboard } from '@shared/models/dashboard.models';
@Component({ @Component({
selector: 'tb-data-keys', selector: 'tb-data-keys',
@ -113,6 +114,15 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, AfterVie
@Input() @Input()
datakeySettingsSchema: JsonSettingsSchema; datakeySettingsSchema: JsonSettingsSchema;
@Input()
dataKeySettingsDirective: string;
@Input()
dashboard: Dashboard;
@Input()
widget: Widget;
@Input() @Input()
callbacks: DataKeysCallbacks; callbacks: DataKeysCallbacks;
@ -410,6 +420,10 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, AfterVie
data: { data: {
dataKey: deepClone(key), dataKey: deepClone(key),
dataKeySettingsSchema: this.datakeySettingsSchema, dataKeySettingsSchema: this.datakeySettingsSchema,
dataKeySettingsDirective: this.dataKeySettingsDirective,
dashboard: this.dashboard,
aliasController: this.aliasController,
widget: this.widget,
entityAliasId: this.entityAliasId, entityAliasId: this.entityAliasId,
showPostProcessing: this.widgetType !== widgetType.alarm, showPostProcessing: this.widgetType !== widgetType.alarm,
callbacks: this.callbacks callbacks: this.callbacks

319
ui-ngx/src/app/modules/home/components/widget/lib/analogue-compass.models.ts

@ -14,7 +14,6 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { JsonSettingsSchema } from '@shared/models/widget.models';
import { FontSettings } from '@home/components/widget/lib/settings.models'; import { FontSettings } from '@home/components/widget/lib/settings.models';
import { AnimationRule, AnimationTarget } from '@home/components/widget/lib/analogue-gauge.models'; import { AnimationRule, AnimationTarget } from '@home/components/widget/lib/analogue-gauge.models';
@ -37,321 +36,3 @@ export interface AnalogueCompassSettings {
animationRule: AnimationRule; animationRule: AnimationRule;
animationTarget: AnimationTarget; animationTarget: AnimationTarget;
} }
export const analogueCompassSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
majorTicks: {
title: 'Major ticks names',
type: 'array',
items: {
title: 'Tick name',
type: 'string'
}
},
minorTicks: {
title: 'Minor ticks count',
type: 'number',
default: 22
},
showStrokeTicks: {
title: 'Show ticks stroke',
type: 'boolean',
default: false
},
needleCircleSize: {
title: 'Needle circle size',
type: 'number',
default: 15
},
showBorder: {
title: 'Show border',
type: 'boolean',
default: true
},
borderOuterWidth: {
title: 'Border width',
type: 'number',
default: 10
},
colorPlate: {
title: 'Plate color',
type: 'string',
default: '#222'
},
colorMajorTicks: {
title: 'Major ticks color',
type: 'string',
default: '#f5f5f5'
},
colorMinorTicks: {
title: 'Minor ticks color',
type: 'string',
default: '#ddd'
},
colorNeedle: {
title: 'Needle color',
type: 'string',
default: '#f08080'
},
colorNeedleCircle: {
title: 'Needle circle color',
type: 'string',
default: '#e8e8e8'
},
colorBorder: {
title: 'Border color',
type: 'string',
default: '#ccc'
},
majorTickFont: {
title: 'Major tick font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 20
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: '#ccc'
}
}
},
animation: {
title: 'Enable animation',
type: 'boolean',
default: true
},
animationDuration: {
title: 'Animation duration',
type: 'number',
default: 500
},
animationRule: {
title: 'Animation rule',
type: 'string',
default: 'cycle'
},
animationTarget: {
title: 'Animation target',
type: 'string',
default: 'needle'
}
},
required: []
},
form: [
{
key: 'majorTicks',
items: [
'majorTicks[]'
]
},
'minorTicks',
'showStrokeTicks',
'needleCircleSize',
'showBorder',
'borderOuterWidth',
{
key: 'colorPlate',
type: 'color'
},
{
key: 'colorMajorTicks',
type: 'color'
},
{
key: 'colorMinorTicks',
type: 'color'
},
{
key: 'colorNeedle',
type: 'color'
},
{
key: 'colorNeedleCircle',
type: 'color'
},
{
key: 'colorBorder',
type: 'color'
},
{
key: 'majorTickFont',
items: [
'majorTickFont.family',
'majorTickFont.size',
{
key: 'majorTickFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'majorTickFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'majorTickFont.color',
type: 'color'
}
]
},
'animation',
'animationDuration',
{
key: 'animationRule',
type: 'rc-select',
multiple: false,
items: [
{
value: 'linear',
label: 'Linear'
},
{
value: 'quad',
label: 'Quad'
},
{
value: 'quint',
label: 'Quint'
},
{
value: 'cycle',
label: 'Cycle'
},
{
value: 'bounce',
label: 'Bounce'
},
{
value: 'elastic',
label: 'Elastic'
},
{
value: 'dequad',
label: 'Dequad'
},
{
value: 'dequint',
label: 'Dequint'
},
{
value: 'decycle',
label: 'Decycle'
},
{
value: 'debounce',
label: 'Debounce'
},
{
value: 'delastic',
label: 'Delastic'
}
]
},
{
key: 'animationTarget',
type: 'rc-select',
multiple: false,
items: [
{
value: 'needle',
label: 'Needle'
},
{
value: 'plate',
label: 'Plate'
}
]
}
]
};

10
ui-ngx/src/app/modules/home/components/widget/lib/analogue-compass.ts

@ -17,26 +17,18 @@
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import * as CanvasGauges from 'canvas-gauges'; import * as CanvasGauges from 'canvas-gauges';
import { import {
AnalogueCompassSettings, AnalogueCompassSettings
analogueCompassSettingsSchema
} from '@home/components/widget/lib/analogue-compass.models'; } from '@home/components/widget/lib/analogue-compass.models';
import { deepClone, isDefined } from '@core/utils'; import { deepClone, isDefined } from '@core/utils';
import { JsonSettingsSchema } from '@shared/models/widget.models';
import { getFontFamily } from '@home/components/widget/lib/settings.models'; import { getFontFamily } from '@home/components/widget/lib/settings.models';
import { TbBaseGauge } from '@home/components/widget/lib/analogue-gauge.models'; import { TbBaseGauge } from '@home/components/widget/lib/analogue-gauge.models';
import RadialGaugeOptions = CanvasGauges.RadialGaugeOptions; import RadialGaugeOptions = CanvasGauges.RadialGaugeOptions;
import BaseGauge = CanvasGauges.BaseGauge; import BaseGauge = CanvasGauges.BaseGauge;
import RadialGauge = CanvasGauges.RadialGauge; import RadialGauge = CanvasGauges.RadialGauge;
const analogueCompassSettingsSchemaValue = analogueCompassSettingsSchema;
// @dynamic // @dynamic
export class TbAnalogueCompass extends TbBaseGauge<AnalogueCompassSettings, RadialGaugeOptions> { export class TbAnalogueCompass extends TbBaseGauge<AnalogueCompassSettings, RadialGaugeOptions> {
static get settingsSchema(): JsonSettingsSchema {
return analogueCompassSettingsSchemaValue;
}
constructor(ctx: WidgetContext, canvasId: string) { constructor(ctx: WidgetContext, canvasId: string) {
super(ctx, canvasId); super(ctx, canvasId);
} }

771
ui-ngx/src/app/modules/home/components/widget/lib/analogue-gauge.models.ts

@ -16,7 +16,6 @@
import * as CanvasGauges from 'canvas-gauges'; import * as CanvasGauges from 'canvas-gauges';
import { FontSettings, getFontFamily } from '@home/components/widget/lib/settings.models'; import { FontSettings, getFontFamily } from '@home/components/widget/lib/settings.models';
import { JsonSettingsSchema } from '@shared/models/widget.models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { isDefined } from '@core/utils'; import { isDefined } from '@core/utils';
import * as tinycolor_ from 'tinycolor2'; import * as tinycolor_ from 'tinycolor2';
@ -67,776 +66,6 @@ export interface AnalogueGaugeSettings {
animationRule: AnimationRule; animationRule: AnimationRule;
} }
export const analogueGaugeSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
minValue: {
title: 'Minimum value',
type: 'number',
default: 0
},
maxValue: {
title: 'Maximum value',
type: 'number',
default: 100
},
unitTitle: {
title: 'Unit title',
type: 'string',
default: null
},
showUnitTitle: {
title: 'Show unit title',
type: 'boolean',
default: true
},
majorTicksCount: {
title: 'Major ticks count',
type: 'number',
default: null
},
minorTicks: {
title: 'Minor ticks count',
type: 'number',
default: 2
},
valueBox: {
title: 'Show value box',
type: 'boolean',
default: true
},
valueInt: {
title: 'Digits count for integer part of value',
type: 'number',
default: 3
},
defaultColor: {
title: 'Default color',
type: 'string',
default: null
},
colorPlate: {
title: 'Plate color',
type: 'string',
default: '#fff'
},
colorMajorTicks: {
title: 'Major ticks color',
type: 'string',
default: '#444'
},
colorMinorTicks: {
title: 'Minor ticks color',
type: 'string',
default: '#666'
},
colorNeedle: {
title: 'Needle color',
type: 'string',
default: null
},
colorNeedleEnd: {
title: 'Needle color - end gradient',
type: 'string',
default: null
},
colorNeedleShadowUp: {
title: 'Upper half of the needle shadow color',
type: 'string',
default: 'rgba(2,255,255,0.2)'
},
colorNeedleShadowDown: {
title: 'Drop shadow needle color.',
type: 'string',
default: 'rgba(188,143,143,0.45)'
},
colorValueBoxRect: {
title: 'Value box rectangle stroke color',
type: 'string',
default: '#888'
},
colorValueBoxRectEnd: {
title: 'Value box rectangle stroke color - end gradient',
type: 'string',
default: '#666'
},
colorValueBoxBackground: {
title: 'Value box background color',
type: 'string',
default: '#babab2'
},
colorValueBoxShadow: {
title: 'Value box shadow color',
type: 'string',
default: 'rgba(0,0,0,1)'
},
highlights: {
title: 'Highlights',
type: 'array',
items: {
title: 'Highlight',
type: 'object',
properties: {
from: {
title: 'From',
type: 'number'
},
to: {
title: 'To',
type: 'number'
},
color: {
title: 'Color',
type: 'string'
}
}
}
},
highlightsWidth: {
title: 'Highlights width',
type: 'number',
default: 15
},
showBorder: {
title: 'Show border',
type: 'boolean',
default: true
},
numbersFont: {
title: 'Tick numbers font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 18
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: null
}
}
},
titleFont: {
title: 'Title text font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 24
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: '#888'
}
}
},
unitsFont: {
title: 'Units text font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 22
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: '#888'
}
}
},
valueFont: {
title: 'Value text font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 40
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: '#444'
},
shadowColor: {
title: 'Shadow color',
type: 'string',
default: 'rgba(0,0,0,0.3)'
}
}
},
animation: {
title: 'Enable animation',
type: 'boolean',
default: true
},
animationDuration: {
title: 'Animation duration',
type: 'number',
default: 500
},
animationRule: {
title: 'Animation rule',
type: 'string',
default: 'cycle'
}
},
required: []
},
form: [
'minValue',
'maxValue',
'unitTitle',
'showUnitTitle',
'majorTicksCount',
'minorTicks',
'valueBox',
'valueInt',
{
key: 'defaultColor',
type: 'color'
},
{
key: 'colorPlate',
type: 'color'
},
{
key: 'colorMajorTicks',
type: 'color'
},
{
key: 'colorMinorTicks',
type: 'color'
},
{
key: 'colorNeedle',
type: 'color'
},
{
key: 'colorNeedleEnd',
type: 'color'
},
{
key: 'colorNeedleShadowUp',
type: 'color'
},
{
key: 'colorNeedleShadowDown',
type: 'color'
},
{
key: 'colorValueBoxRect',
type: 'color'
},
{
key: 'colorValueBoxRectEnd',
type: 'color'
},
{
key: 'colorValueBoxBackground',
type: 'color'
},
{
key: 'colorValueBoxShadow',
type: 'color'
},
{
key: 'highlights',
items: [
'highlights[].from',
'highlights[].to',
{
key: 'highlights[].color',
type: 'color'
}
]
},
'highlightsWidth',
'showBorder',
{
key: 'numbersFont',
items: [
'numbersFont.family',
'numbersFont.size',
{
key: 'numbersFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'numbersFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'numbersFont.color',
type: 'color'
}
]
},
{
key: 'titleFont',
items: [
'titleFont.family',
'titleFont.size',
{
key: 'titleFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'titleFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'titleFont.color',
type: 'color'
}
]
},
{
key: 'unitsFont',
items: [
'unitsFont.family',
'unitsFont.size',
{
key: 'unitsFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'unitsFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'unitsFont.color',
type: 'color'
}
]
},
{
key: 'valueFont',
items: [
'valueFont.family',
'valueFont.size',
{
key: 'valueFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'valueFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'valueFont.color',
type: 'color'
},
{
key: 'valueFont.shadowColor',
type: 'color'
}
]
},
'animation',
'animationDuration',
{
key: 'animationRule',
type: 'rc-select',
multiple: false,
items: [
{
value: 'linear',
label: 'Linear'
},
{
value: 'quad',
label: 'Quad'
},
{
value: 'quint',
label: 'Quint'
},
{
value: 'cycle',
label: 'Cycle'
},
{
value: 'bounce',
label: 'Bounce'
},
{
value: 'elastic',
label: 'Elastic'
},
{
value: 'dequad',
label: 'Dequad'
},
{
value: 'dequint',
label: 'Dequint'
},
{
value: 'decycle',
label: 'Decycle'
},
{
value: 'debounce',
label: 'Debounce'
},
{
value: 'delastic',
label: 'Delastic'
}
]
}
]
};
export abstract class TbBaseGauge<S, O extends GenericOptions> { export abstract class TbBaseGauge<S, O extends GenericOptions> {
private gauge: BaseGauge; private gauge: BaseGauge;

64
ui-ngx/src/app/modules/home/components/widget/lib/analogue-linear-gauge.models.ts

@ -14,9 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { JsonSettingsSchema } from '@shared/models/widget.models'; import { AnalogueGaugeSettings } from '@home/components/widget/lib/analogue-gauge.models';
import { AnalogueGaugeSettings, analogueGaugeSettingsSchema } from '@home/components/widget/lib/analogue-gauge.models';
import { deepClone } from '@core/utils';
export interface AnalogueLinearGaugeSettings extends AnalogueGaugeSettings { export interface AnalogueLinearGaugeSettings extends AnalogueGaugeSettings {
barStrokeWidth: number; barStrokeWidth: number;
@ -26,63 +24,3 @@ export interface AnalogueLinearGaugeSettings extends AnalogueGaugeSettings {
colorBarProgress: string; colorBarProgress: string;
colorBarProgressEnd: string; colorBarProgressEnd: string;
} }
export function getAnalogueLinearGaugeSettingsSchema(): JsonSettingsSchema {
const analogueLinearGaugeSettingsSchema = deepClone(analogueGaugeSettingsSchema);
analogueLinearGaugeSettingsSchema.schema.properties =
{...analogueLinearGaugeSettingsSchema.schema.properties, ...{
barStrokeWidth: {
title: 'Bar stroke width',
type: 'number',
default: 2.5
},
colorBarStroke: {
title: 'Bar stroke color',
type: 'string',
default: null
},
colorBar: {
title: 'Bar background color',
type: 'string',
default: '#fff'
},
colorBarEnd: {
title: 'Bar background color - end gradient',
type: 'string',
default: '#ddd'
},
colorBarProgress: {
title: 'Progress bar color',
type: 'string',
default: null
},
colorBarProgressEnd: {
title: 'Progress bar color - end gradient',
type: 'string',
default: null
}}};
analogueLinearGaugeSettingsSchema.form.unshift(
'barStrokeWidth',
{
key: 'colorBarStroke',
type: 'color'
},
{
key: 'colorBar',
type: 'color'
},
{
key: 'colorBarEnd',
type: 'color'
},
{
key: 'colorBarProgress',
type: 'color'
},
{
key: 'colorBarProgressEnd',
type: 'color'
}
);
return analogueLinearGaugeSettingsSchema;
}

9
ui-ngx/src/app/modules/home/components/widget/lib/analogue-linear-gauge.ts

@ -19,8 +19,7 @@ import { JsonSettingsSchema } from '@shared/models/widget.models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { TbAnalogueGauge } from '@home/components/widget/lib/analogue-gauge.models'; import { TbAnalogueGauge } from '@home/components/widget/lib/analogue-gauge.models';
import { import {
AnalogueLinearGaugeSettings, AnalogueLinearGaugeSettings
getAnalogueLinearGaugeSettingsSchema
} from '@home/components/widget/lib/analogue-linear-gauge.models'; } from '@home/components/widget/lib/analogue-linear-gauge.models';
import { isDefined } from '@core/utils'; import { isDefined } from '@core/utils';
import * as tinycolor_ from 'tinycolor2'; import * as tinycolor_ from 'tinycolor2';
@ -30,15 +29,9 @@ import BaseGauge = CanvasGauges.BaseGauge;
const tinycolor = tinycolor_; const tinycolor = tinycolor_;
const analogueLinearGaugeSettingsSchemaValue = getAnalogueLinearGaugeSettingsSchema();
// @dynamic // @dynamic
export class TbAnalogueLinearGauge extends TbAnalogueGauge<AnalogueLinearGaugeSettings, LinearGaugeOptions>{ export class TbAnalogueLinearGauge extends TbAnalogueGauge<AnalogueLinearGaugeSettings, LinearGaugeOptions>{
static get settingsSchema(): JsonSettingsSchema {
return analogueLinearGaugeSettingsSchemaValue;
}
constructor(ctx: WidgetContext, canvasId: string) { constructor(ctx: WidgetContext, canvasId: string) {
super(ctx, canvasId); super(ctx, canvasId);
} }

31
ui-ngx/src/app/modules/home/components/widget/lib/analogue-radial-gauge.models.ts

@ -14,39 +14,10 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { JsonSettingsSchema } from '@shared/models/widget.models'; import { AnalogueGaugeSettings } from '@home/components/widget/lib/analogue-gauge.models';
import { AnalogueGaugeSettings, analogueGaugeSettingsSchema } from '@home/components/widget/lib/analogue-gauge.models';
import { deepClone } from '@core/utils';
export interface AnalogueRadialGaugeSettings extends AnalogueGaugeSettings { export interface AnalogueRadialGaugeSettings extends AnalogueGaugeSettings {
startAngle: number; startAngle: number;
ticksAngle: number; ticksAngle: number;
needleCircleSize: number; needleCircleSize: number;
} }
export function getAnalogueRadialGaugeSettingsSchema(): JsonSettingsSchema {
const analogueRadialGaugeSettingsSchema = deepClone(analogueGaugeSettingsSchema);
analogueRadialGaugeSettingsSchema.schema.properties =
{...analogueRadialGaugeSettingsSchema.schema.properties, ...{
startAngle: {
title: 'Start ticks angle',
type: 'number',
default: 45
},
ticksAngle: {
title: 'Ticks angle',
type: 'number',
default: 270
},
needleCircleSize: {
title: 'Needle circle size',
type: 'number',
default: 10
}}};
analogueRadialGaugeSettingsSchema.form.unshift(
'startAngle',
'ticksAngle',
'needleCircleSize'
);
return analogueRadialGaugeSettingsSchema;
}

10
ui-ngx/src/app/modules/home/components/widget/lib/analogue-radial-gauge.ts

@ -16,25 +16,17 @@
import * as CanvasGauges from 'canvas-gauges'; import * as CanvasGauges from 'canvas-gauges';
import { import {
AnalogueRadialGaugeSettings, AnalogueRadialGaugeSettings
getAnalogueRadialGaugeSettingsSchema
} from '@home/components/widget/lib/analogue-radial-gauge.models'; } from '@home/components/widget/lib/analogue-radial-gauge.models';
import { JsonSettingsSchema } from '@shared/models/widget.models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { TbAnalogueGauge } from '@home/components/widget/lib/analogue-gauge.models'; import { TbAnalogueGauge } from '@home/components/widget/lib/analogue-gauge.models';
import RadialGauge = CanvasGauges.RadialGauge; import RadialGauge = CanvasGauges.RadialGauge;
import RadialGaugeOptions = CanvasGauges.RadialGaugeOptions; import RadialGaugeOptions = CanvasGauges.RadialGaugeOptions;
import BaseGauge = CanvasGauges.BaseGauge; import BaseGauge = CanvasGauges.BaseGauge;
const analogueRadialGaugeSettingsSchemaValue = getAnalogueRadialGaugeSettingsSchema();
// @dynamic // @dynamic
export class TbAnalogueRadialGauge extends TbAnalogueGauge<AnalogueRadialGaugeSettings, RadialGaugeOptions>{ export class TbAnalogueRadialGauge extends TbAnalogueGauge<AnalogueRadialGaugeSettings, RadialGaugeOptions>{
static get settingsSchema(): JsonSettingsSchema {
return analogueRadialGaugeSettingsSchemaValue;
}
constructor(ctx: WidgetContext, canvasId: string) { constructor(ctx: WidgetContext, canvasId: string) {
super(ctx, canvasId); super(ctx, canvasId);
} }

902
ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.models.ts

@ -80,905 +80,3 @@ export interface DigitalGaugeSettings {
colorTicks?: string; colorTicks?: string;
tickWidth?: number; tickWidth?: number;
} }
export const digitalGaugeSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
minValue: {
title: 'Minimum value',
type: 'number',
default: 0
},
maxValue: {
title: 'Maximum value',
type: 'number',
default: 100
},
gaugeType: {
title: 'Gauge type',
type: 'string',
default: 'arc'
},
donutStartAngle: {
title: 'Angle to start from when in donut mode',
type: 'number',
default: 90
},
neonGlowBrightness: {
title: 'Neon glow effect brightness, (0-100), 0 - disable effect',
type: 'number',
default: 0
},
dashThickness: {
title: 'Thickness of the stripes, 0 - no stripes',
type: 'number',
default: 0
},
roundedLineCap: {
title: 'Display rounded line cap',
type: 'boolean',
default: false
},
title: {
title: 'Gauge title',
type: 'string',
default: null
},
showTitle: {
title: 'Show gauge title',
type: 'boolean',
default: false
},
unitTitle: {
title: 'Unit title',
type: 'string',
default: null
},
showUnitTitle: {
title: 'Show unit title',
type: 'boolean',
default: false
},
showTimestamp: {
title: 'Show value timestamp',
type: 'boolean',
default: false
},
timestampFormat: {
title: 'Timestamp format',
type: 'string',
default: 'yyyy-MM-dd HH:mm:ss'
},
showValue: {
title: 'Show value text',
type: 'boolean',
default: true
},
showMinMax: {
title: 'Show min and max values',
type: 'boolean',
default: true
},
gaugeWidthScale: {
title: 'Width of the gauge element',
type: 'number',
default: 0.75
},
defaultColor: {
title: 'Default color',
type: 'string',
default: null
},
gaugeColor: {
title: 'Background color of the gauge element',
type: 'string',
default: null
},
useFixedLevelColor: {
title: 'Use precise value for the color indicator',
type: 'boolean',
default: false
},
levelColors: {
title: 'Colors of indicator, from lower to upper',
type: 'array',
items: {
title: 'Color',
type: 'string'
}
},
fixedLevelColors: {
title: 'The colors for the indicator using boundary values',
type: 'array',
items: {
title: 'levelColor',
type: 'object',
properties: {
from: {
title: 'From',
type: 'object',
properties: {
valueSource: {
title: '[From] Value source',
type: 'string',
default: 'predefinedValue'
},
entityAlias: {
title: '[From] Source entity alias',
type: 'string'
},
attribute: {
title: '[From] Source entity attribute',
type: 'string'
},
value: {
title: '[From] Value (if predefined value is selected)',
type: 'number'
}
}
},
to: {
title: 'To',
type: 'object',
properties: {
valueSource: {
title: '[To] Value source',
type: 'string',
default: 'predefinedValue'
},
entityAlias: {
title: '[To] Source entity alias',
type: 'string'
},
attribute: {
title: '[To] Source entity attribute',
type: 'string'
},
value: {
title: '[To] Value (if predefined value is selected)',
type: 'number'
}
}
},
color: {
title: 'Color',
type: 'string'
}
},
required: ['color'],
}
},
showTicks: {
title: 'Show ticks',
type: 'boolean',
default: false
},
tickWidth: {
title: 'Width ticks',
type: 'number',
default: 4
},
colorTicks: {
title: 'Color ticks',
type: 'string',
default: '#666'
},
ticksValue: {
title: 'The ticks predefined value',
type: 'array',
items: {
title: 'tickValue',
type: 'object',
properties: {
valueSource: {
title: 'Value source',
type: 'string',
default: 'predefinedValue'
},
entityAlias: {
title: 'Source entity alias',
type: 'string'
},
attribute: {
title: 'Source entity attribute',
type: 'string'
},
value: {
title: 'Value (if predefined value is selected)',
type: 'number'
}
}
}
},
animation: {
title: 'Enable animation',
type: 'boolean',
default: true
},
animationDuration: {
title: 'Animation duration',
type: 'number',
default: 500
},
animationRule: {
title: 'Animation rule',
type: 'string',
default: 'linear'
},
titleFont: {
title: 'Gauge title font',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 12
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: null
}
}
},
labelFont: {
title: 'Font of label showing under value',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 8
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: null
}
}
},
valueFont: {
title: 'Font of label showing current value',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 18
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: null
}
}
},
minMaxFont: {
title: 'Font of minimum and maximum labels',
type: 'object',
properties: {
family: {
title: 'Font family',
type: 'string',
default: 'Roboto'
},
size: {
title: 'Size',
type: 'number',
default: 10
},
style: {
title: 'Style',
type: 'string',
default: 'normal'
},
weight: {
title: 'Weight',
type: 'string',
default: '500'
},
color: {
title: 'color',
type: 'string',
default: null
}
}
}
}
},
form: [
'minValue',
'maxValue',
{
key: 'gaugeType',
type: 'rc-select',
multiple: false,
items: [
{
value: 'arc',
label: 'Arc'
},
{
value: 'donut',
label: 'Donut'
},
{
value: 'horizontalBar',
label: 'Horizontal bar'
},
{
value: 'verticalBar',
label: 'Vertical bar'
}
]
},
'donutStartAngle',
'neonGlowBrightness',
'dashThickness',
'roundedLineCap',
'title',
'showTitle',
'unitTitle',
'showUnitTitle',
'showTimestamp',
'timestampFormat',
'showValue',
'showMinMax',
'gaugeWidthScale',
{
key: 'defaultColor',
type: 'color'
},
{
key: 'gaugeColor',
type: 'color'
},
'useFixedLevelColor',
{
key: 'levelColors',
condition: 'model.useFixedLevelColor !== true',
items: [
{
key: 'levelColors[]',
type: 'color'
}
]
},
{
key: 'fixedLevelColors',
condition: 'model.useFixedLevelColor === true',
items: [
{
key: 'fixedLevelColors[].from.valueSource',
type: 'rc-select',
multiple: false,
items: [
{
value: 'predefinedValue',
label: 'Predefined value (Default)'
},
{
value: 'entityAttribute',
label: 'Value taken from entity attribute'
}
]
},
'fixedLevelColors[].from.value',
'fixedLevelColors[].from.entityAlias',
'fixedLevelColors[].from.attribute',
{
key: 'fixedLevelColors[].to.valueSource',
type: 'rc-select',
multiple: false,
items: [
{
value: 'predefinedValue',
label: 'Predefined value (Default)'
},
{
value: 'entityAttribute',
label: 'Value taken from entity attribute'
}
]
},
'fixedLevelColors[].to.value',
'fixedLevelColors[].to.entityAlias',
'fixedLevelColors[].to.attribute',
{
key: 'fixedLevelColors[].color',
type: 'color'
}
]
},
'showTicks',
{
key: 'tickWidth',
condition: 'model.showTicks === true'
},
{
key: 'colorTicks',
condition: 'model.showTicks === true',
type: 'color'
},
{
key: 'ticksValue',
condition: 'model.showTicks === true',
items: [
{
key: 'ticksValue[].valueSource',
type: 'rc-select',
multiple: false,
items: [
{
value: 'predefinedValue',
label: 'Predefined value (Default)'
},
{
value: 'entityAttribute',
label: 'Value taken from entity attribute'
}
]
},
'ticksValue[].value',
'ticksValue[].entityAlias',
'ticksValue[].attribute'
]
},
'animation',
'animationDuration',
{
key: 'animationRule',
type: 'rc-select',
multiple: false,
items: [
{
value: 'linear',
label: 'Linear'
},
{
value: 'quad',
label: 'Quad'
},
{
value: 'quint',
label: 'Quint'
},
{
value: 'cycle',
label: 'Cycle'
},
{
value: 'bounce',
label: 'Bounce'
},
{
value: 'elastic',
label: 'Elastic'
},
{
value: 'dequad',
label: 'Dequad'
},
{
value: 'dequint',
label: 'Dequint'
},
{
value: 'decycle',
label: 'Decycle'
},
{
value: 'debounce',
label: 'Debounce'
},
{
value: 'delastic',
label: 'Delastic'
}
]
},
{
key: 'titleFont',
items: [
'titleFont.family',
'titleFont.size',
{
key: 'titleFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'titleFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'titleFont.color',
type: 'color'
}
]
},
{
key: 'labelFont',
items: [
'labelFont.family',
'labelFont.size',
{
key: 'labelFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'labelFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'labelFont.color',
type: 'color'
}
]
},
{
key: 'valueFont',
items: [
'valueFont.family',
'valueFont.size',
{
key: 'valueFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'valueFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'valueFont.color',
type: 'color'
}
]
},
{
key: 'minMaxFont',
items: [
'minMaxFont.family',
'minMaxFont.size',
{
key: 'minMaxFont.style',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'italic',
label: 'Italic'
},
{
value: 'oblique',
label: 'Oblique'
}
]
},
{
key: 'minMaxFont.weight',
type: 'rc-select',
multiple: false,
items: [
{
value: 'normal',
label: 'Normal'
},
{
value: 'bold',
label: 'Bold'
},
{
value: 'bolder',
label: 'Bolder'
},
{
value: 'lighter',
label: 'Lighter'
},
{
value: '100',
label: '100'
},
{
value: '200',
label: '200'
},
{
value: '300',
label: '300'
},
{
value: '400',
label: '400'
},
{
value: '500',
label: '500'
},
{
value: '600',
label: '600'
},
{
value: '700',
label: '700'
},
{
value: '800',
label: '800'
},
{
value: '900',
label: '900'
}
]
},
{
key: 'minMaxFont.color',
type: 'color'
}
]
}
]
};

7
ui-ngx/src/app/modules/home/components/widget/lib/digital-gauge.ts

@ -21,7 +21,6 @@ import {
AttributeSourceProperty, AttributeSourceProperty,
ColorLevelSetting, ColorLevelSetting,
DigitalGaugeSettings, DigitalGaugeSettings,
digitalGaugeSettingsSchema,
FixedLevelColors FixedLevelColors
} from '@home/components/widget/lib/digital-gauge.models'; } from '@home/components/widget/lib/digital-gauge.models';
import * as tinycolor_ from 'tinycolor2'; import * as tinycolor_ from 'tinycolor2';
@ -44,15 +43,9 @@ import GenericOptions = CanvasGauges.GenericOptions;
const tinycolor = tinycolor_; const tinycolor = tinycolor_;
const digitalGaugeSettingsSchemaValue = digitalGaugeSettingsSchema;
// @dynamic // @dynamic
export class TbCanvasDigitalGauge { export class TbCanvasDigitalGauge {
static get settingsSchema(): JsonSettingsSchema {
return digitalGaugeSettingsSchemaValue;
}
constructor(protected ctx: WidgetContext, canvasId: string) { constructor(protected ctx: WidgetContext, canvasId: string) {
const gaugeElement = $('#' + canvasId, ctx.$container)[0]; const gaugeElement = $('#' + canvasId, ctx.$container)[0];
const settings: DigitalGaugeSettings = ctx.settings; const settings: DigitalGaugeSettings = ctx.settings;

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

@ -18,7 +18,6 @@
/// <reference path="../../../../../../../src/typings/jquery.flot.typings.d.ts" /> /// <reference path="../../../../../../../src/typings/jquery.flot.typings.d.ts" />
import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models'; import { DataKey, Datasource, DatasourceData, JsonSettingsSchema } from '@shared/models/widget.models';
import * as moment_ from 'moment';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { ComparisonDuration } from '@shared/models/time/time.models'; import { ComparisonDuration } from '@shared/models/time/time.models';
@ -100,8 +99,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 {
@ -163,13 +162,15 @@ export interface TbFlotLabelPatternSettings {
settings?: any; settings?: any;
} }
export interface TbFlotGraphSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings { export interface TbFlotGraphSettings extends TbFlotBaseSettings,
TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
smoothLines: boolean; smoothLines: boolean;
} }
export declare type BarAlignment = 'left' | 'right' | 'center'; export declare type BarAlignment = 'left' | 'right' | 'center';
export interface TbFlotBarSettings extends TbFlotBaseSettings, TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings { export interface TbFlotBarSettings extends TbFlotBaseSettings,
TbFlotThresholdsSettings, TbFlotComparisonSettings, TbFlotCustomLegendSettings {
defaultBarWidth: number; defaultBarWidth: number;
barAlignment: BarAlignment; barAlignment: BarAlignment;
} }
@ -183,7 +184,7 @@ export interface TbFlotPieSettings {
color: string; color: string;
width: number; width: number;
}; };
showTooltip: boolean, showTooltip: boolean;
showLabels: boolean; showLabels: boolean;
fontColor: string; fontColor: string;
fontSize: number; fontSize: number;
@ -240,927 +241,3 @@ export interface TbFlotLatestKeySettings {
thresholdLineWidth: number; thresholdLineWidth: number;
thresholdColor: string; thresholdColor: string;
} }
export function flotSettingsSchema(chartType: ChartType): JsonSettingsSchema {
const schema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
}
}
};
const properties: any = schema.schema.properties;
properties.stack = {
title: 'Stacking',
type: 'boolean',
default: false
};
if (chartType === 'graph') {
properties.smoothLines = {
title: 'Display smooth (curved) lines',
type: 'boolean',
default: false
};
}
if (chartType === 'bar') {
properties.defaultBarWidth = {
title: 'Default bar width for non-aggregated data (milliseconds)',
type: 'number',
default: 600
};
properties.barAlignment = {
title: 'Bar alignment',
type: 'string',
default: 'left'
};
}
if (chartType === 'graph' || chartType === 'bar') {
properties.thresholdsLineWidth = {
title: 'Default line width for all thresholds',
type: 'number'
};
}
properties.shadowSize = {
title: 'Shadow size',
type: 'number',
default: 4
};
properties.fontColor = {
title: 'Font color',
type: 'string',
default: '#545454'
};
properties.fontSize = {
title: 'Font size',
type: 'number',
default: 10
};
properties.tooltipIndividual = {
title: 'Hover individual points',
type: 'boolean',
default: false
};
properties.tooltipCumulative = {
title: 'Show cumulative values in stacking mode',
type: 'boolean',
default: false
};
properties.tooltipValueFormatter = {
title: 'Tooltip value format function, f(value)',
type: 'string',
default: ''
};
properties.hideZeros = {
title: 'Hide zero/false values from tooltip',
type: 'boolean',
default: false
};
properties.showTooltip = {
title: 'Show tooltip',
type: 'boolean',
default: true
};
properties.grid = {
title: 'Grid settings',
type: 'object',
properties: {
color: {
title: 'Primary color',
type: 'string',
default: '#545454'
},
backgroundColor: {
title: 'Background color',
type: 'string',
default: null
},
tickColor: {
title: 'Ticks color',
type: 'string',
default: '#DDDDDD'
},
outlineWidth: {
title: 'Grid outline/border width (px)',
type: 'number',
default: 1
},
verticalLines: {
title: 'Show vertical lines',
type: 'boolean',
default: true
},
horizontalLines: {
title: 'Show horizontal lines',
type: 'boolean',
default: true
}
}
};
properties.xaxis = {
title: 'X axis settings',
type: 'object',
properties: {
showLabels: {
title: 'Show labels',
type: 'boolean',
default: true
},
title: {
title: 'Axis title',
type: 'string',
default: null
},
color: {
title: 'Ticks color',
type: 'string',
default: null
}
}
};
properties.yaxis = {
title: 'Y axis settings',
type: 'object',
properties: {
min: {
title: 'Minimum value on the scale',
type: 'number',
default: null
},
max: {
title: 'Maximum value on the scale',
type: 'number',
default: null
},
showLabels: {
title: 'Show labels',
type: 'boolean',
default: true
},
title: {
title: 'Axis title',
type: 'string',
default: null
},
color: {
title: 'Ticks color',
type: 'string',
default: null
},
ticksFormatter: {
title: 'Ticks formatter function, f(value)',
type: 'string',
default: ''
},
tickDecimals: {
title: 'The number of decimals to display',
type: 'number',
default: 0
},
tickSize: {
title: 'Step size between ticks',
type: 'number',
default: null
}
}
};
schema.schema.required = [];
schema.form = ['stack'];
if (chartType === 'graph') {
schema.form.push('smoothLines');
}
if (chartType === 'bar') {
schema.form.push('defaultBarWidth');
schema.form.push({
key: 'barAlignment',
type: 'rc-select',
multiple: false,
items: [
{
value: 'left',
label: 'Left'
},
{
value: 'right',
label: 'Right'
},
{
value: 'center',
label: 'Center'
}
]
});
}
if (chartType === 'graph' || chartType === 'bar') {
schema.form.push('thresholdsLineWidth');
}
schema.form.push('shadowSize');
schema.form.push({
key: 'fontColor',
type: 'color'
});
schema.form.push('fontSize');
schema.form.push('tooltipIndividual');
schema.form.push('tooltipCumulative');
schema.form.push({
key: 'tooltipValueFormatter',
type: 'javascript',
helpId: 'widget/lib/flot/tooltip_value_format_fn'
});
schema.form.push('hideZeros');
schema.form.push('showTooltip');
schema.form.push({
key: 'grid',
items: [
{
key: 'grid.color',
type: 'color'
},
{
key: 'grid.backgroundColor',
type: 'color'
},
{
key: 'grid.tickColor',
type: 'color'
},
'grid.outlineWidth',
'grid.verticalLines',
'grid.horizontalLines'
]
});
schema.form.push({
key: 'xaxis',
items: [
'xaxis.showLabels',
'xaxis.title',
{
key: 'xaxis.color',
type: 'color'
}
]
});
schema.form.push({
key: 'yaxis',
items: [
'yaxis.min',
'yaxis.max',
'yaxis.tickDecimals',
'yaxis.tickSize',
'yaxis.showLabels',
'yaxis.title',
{
key: 'yaxis.color',
type: 'color'
},
{
key: 'yaxis.ticksFormatter',
type: 'javascript',
helpId: 'widget/lib/flot/ticks_formatter_fn'
}
]
});
if (chartType === 'graph' || chartType === 'bar') {
schema.groupInfoes = [{
formIndex: 0,
GroupTitle: 'Common Settings'
}];
schema.form = [schema.form];
schema.schema.properties = {...schema.schema.properties, ...chartSettingsSchemaForComparison.schema.properties, ...chartSettingsSchemaForCustomLegend.schema.properties};
schema.schema.required = schema.schema.required.concat(chartSettingsSchemaForComparison.schema.required, chartSettingsSchemaForCustomLegend.schema.required);
schema.form.push(chartSettingsSchemaForComparison.form, chartSettingsSchemaForCustomLegend.form);
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle: 'Comparison Settings'
});
schema.groupInfoes.push({
formIndex: schema.groupInfoes.length,
GroupTitle: 'Custom Legend Settings'
});
}
return schema;
}
const chartSettingsSchemaForComparison: JsonSettingsSchema = {
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: 'previousInterval'
},
comparisonCustomIntervalValue: {
title: 'Custom interval value (ms)',
type: 'number',
default: 7200000
},
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: 'previousInterval',
label: 'Previous interval (default)'
},
{
value: 'days',
label: 'Day ago'
},
{
value: 'weeks',
label: 'Week ago'
},
{
value: 'months',
label: 'Month ago'
},
{
value: 'years',
label: 'Year ago'
},
{
value: 'customInterval',
label: 'Custom interval'
}
]
},
{
key: 'comparisonCustomIntervalValue',
condition: 'model.timeForComparison === "customInterval"'
},
{
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',
]
}
]
};
const chartSettingsSchemaForCustomLegend: JsonSettingsSchema = {
schema: {
title: 'Custom Legend Settings',
type: 'object',
properties: {
customLegendEnabled: {
title: 'Enable custom legend (this will allow you to use attribute/timeseries values in key labels)',
type: 'boolean',
default: false
},
dataKeysListForLabels: {
title: 'Datakeys list to use in labels',
type: 'array',
items: {
type: 'object',
properties: {
name: {
title: 'Key name',
type: 'string'
},
type: {
title: 'Key type',
type: 'string',
default: 'attribute'
}
},
required: [
'name'
]
}
}
},
required: []
},
form: [
'customLegendEnabled',
{
key: 'dataKeysListForLabels',
condition: 'model.customLegendEnabled === true',
items: [
{
key: 'dataKeysListForLabels[].type',
type: 'rc-select',
multiple: false,
items: [
{
value: 'attribute',
label: 'Attribute'
},
{
value: 'timeseries',
label: 'Timeseries'
}
]
},
'dataKeysListForLabels[].name'
]
}
]
};
export const flotPieSettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'Settings',
properties: {
radius: {
title: 'Radius',
type: 'number',
default: 1
},
innerRadius: {
title: 'Inner radius',
type: 'number',
default: 0
},
tilt: {
title: 'Tilt',
type: 'number',
default: 1
},
animatedPie: {
title: 'Enable pie animation (experimental)',
type: 'boolean',
default: false
},
stroke: {
title: 'Stroke',
type: 'object',
properties: {
color: {
title: 'Color',
type: 'string',
default: ''
},
width: {
title: 'Width (pixels)',
type: 'number',
default: 0
}
}
},
showTooltip: {
title: 'Show Tooltip',
type: 'boolean',
default: true,
},
showLabels: {
title: 'Show labels',
type: 'boolean',
default: false
},
fontColor: {
title: 'Font color',
type: 'string',
default: '#545454'
},
fontSize: {
title: 'Font size',
type: 'number',
default: 10
}
},
required: []
},
form: [
'radius',
'innerRadius',
'animatedPie',
'tilt',
{
key: 'stroke',
items: [
{
key: 'stroke.color',
type: 'color'
},
'stroke.width'
]
},
'showTooltip',
'showLabels',
{
key: 'fontColor',
type: 'color'
},
'fontSize'
]
};
export const flotPieDatakeySettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'DataKeySettings',
properties: {
hideDataByDefault: {
title: 'Data is hidden by default',
type: 'boolean',
default: false
},
disableDataHiding: {
title: 'Disable data hiding',
type: 'boolean',
default: false
},
removeFromLegend: {
title: 'Remove datakey from legend',
type: 'boolean',
default: false
}
},
required: []
},
form: [
'hideDataByDefault',
'disableDataHiding',
'removeFromLegend'
]
};
export function flotDatakeySettingsSchema(defaultShowLines: boolean, chartType: ChartType): JsonSettingsSchema {
const schema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'DataKeySettings',
properties: {
excludeFromStacking: {
title: 'Exclude from stacking(available in "Stacking" mode)',
type: 'boolean',
default: false
},
hideDataByDefault: {
title: 'Data is hidden by default',
type: 'boolean',
default: false
},
disableDataHiding: {
title: 'Disable data hiding',
type: 'boolean',
default: false
},
removeFromLegend: {
title: 'Remove datakey from legend',
type: 'boolean',
default: false
},
showLines: {
title: 'Show lines',
type: 'boolean',
default: defaultShowLines
},
fillLines: {
title: 'Fill lines',
type: 'boolean',
default: false
},
showPoints: {
title: 'Show points',
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',
default: 3
},
tooltipValueFormatter: {
title: 'Tooltip value format function, f(value)',
type: 'string',
default: ''
},
showSeparateAxis: {
title: 'Show separate axis',
type: 'boolean',
default: false
},
axisMin: {
title: 'Minimum value on the axis scale',
type: 'number',
default: null
},
axisMax: {
title: 'Maximum value on the axis scale',
type: 'number',
default: null
},
axisTitle: {
title: 'Axis title',
type: 'string',
default: ''
},
axisTickDecimals: {
title: 'Axis tick number of digits after floating point',
type: 'number',
default: null
},
axisTickSize: {
title: 'Axis step size between ticks',
type: 'number',
default: null
},
axisPosition: {
title: 'Axis position',
type: 'string',
default: 'left'
},
axisTicksFormatter: {
title: 'Ticks formatter function, f(value)',
type: 'string',
default: ''
}
},
required: ['showLines', 'fillLines', 'showPoints']
},
form: [
'hideDataByDefault',
'disableDataHiding',
'removeFromLegend',
'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',
helpId: 'widget/lib/flot/point_shape_format_fn'
},
'showPointsLineWidth',
'showPointsRadius',
{
key: 'tooltipValueFormatter',
type: 'javascript',
helpId: 'widget/lib/flot/tooltip_value_format_fn'
},
'showSeparateAxis',
'axisMin',
'axisMax',
'axisTitle',
'axisTickDecimals',
'axisTickSize',
{
key: 'axisPosition',
type: 'rc-select',
multiple: false,
items: [
{
value: 'left',
label: 'Left'
},
{
value: 'right',
label: 'Right'
}
]
},
{
key: 'axisTicksFormatter',
type: 'javascript',
helpId: 'widget/lib/flot/ticks_formatter_fn'
}
]
};
const properties = schema.schema.properties;
if (chartType === 'graph' || chartType === 'bar') {
properties.thresholds = {
title: 'Thresholds',
type: 'array',
items: {
title: 'Threshold',
type: 'object',
properties: {
thresholdValueSource: {
title: 'Threshold value source',
type: 'string',
default: 'predefinedValue'
},
thresholdEntityAlias: {
title: 'Thresholds source entity alias',
type: 'string'
},
thresholdAttribute: {
title: 'Threshold source entity attribute',
type: 'string'
},
thresholdValue: {
title: 'Threshold value (if predefined value is selected)',
type: 'number'
},
lineWidth: {
title: 'Line width',
type: 'number'
},
color: {
title: 'Color',
type: 'string'
}
}
},
required: []
};
schema.form.push({
key: 'thresholds',
items: [
{
key: 'thresholds[].thresholdValueSource',
type: 'rc-select',
multiple: false,
items: [
{
value: 'predefinedValue',
label: 'Predefined value (Default)'
},
{
value: 'entityAttribute',
label: 'Value taken from entity attribute'
}
]
},
'thresholds[].thresholdValue',
'thresholds[].thresholdEntityAlias',
'thresholds[].thresholdAttribute',
{
key: 'thresholds[].color',
type: 'color'
},
'thresholds[].lineWidth'
]
});
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;
}
export const flotLatestDatakeySettingsSchema: JsonSettingsSchema = {
schema: {
type: 'object',
title: 'LatestDataKeySettings',
properties: {
useAsThreshold: {
title: 'Use key value as threshold',
type: 'boolean',
default: false
},
thresholdLineWidth: {
title: 'Threshold line width',
type: 'number'
},
thresholdColor: {
title: 'Threshold color',
type: 'string'
}
}
},
form: [
'useAsThreshold',
{
key: 'thresholdLineWidth',
condition: 'model.useAsThreshold === true'
},
{
key: 'thresholdColor',
type: 'color',
condition: 'model.useAsThreshold === true'
},
]
};

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

@ -38,10 +38,6 @@ import {
} from '@app/shared/models/widget.models'; } from '@app/shared/models/widget.models';
import { import {
ChartType, ChartType,
flotDatakeySettingsSchema, flotLatestDatakeySettingsSchema,
flotPieDatakeySettingsSchema,
flotPieSettingsSchema,
flotSettingsSchema,
TbFlotAxisOptions, TbFlotAxisOptions,
TbFlotHoverInfo, TbFlotHoverInfo,
TbFlotKeySettings, TbFlotLatestKeySettings, TbFlotKeySettings, TbFlotLatestKeySettings,
@ -67,10 +63,6 @@ import Timeout = NodeJS.Timeout;
const tinycolor = tinycolor_; const tinycolor = tinycolor_;
const moment = moment_; const moment = moment_;
const flotPieSettingsSchemaValue = flotPieSettingsSchema;
const flotPieDatakeySettingsSchemaValue = flotPieDatakeySettingsSchema;
const latestDatakeySettingsSchemaValue = flotLatestDatakeySettingsSchema;
export class TbFlot { export class TbFlot {
private readonly utils: UtilsService; private readonly utils: UtilsService;
@ -133,26 +125,6 @@ export class TbFlot {
private pieAnimationLastTime: number; private pieAnimationLastTime: number;
private pieAnimationCaf: CancelAnimationFrame; private pieAnimationCaf: CancelAnimationFrame;
static pieSettingsSchema(): JsonSettingsSchema {
return flotPieSettingsSchemaValue;
}
static pieDatakeySettingsSchema(): JsonSettingsSchema {
return flotPieDatakeySettingsSchemaValue;
}
static settingsSchema(chartType: ChartType): JsonSettingsSchema {
return flotSettingsSchema(chartType);
}
static datakeySettingsSchema(defaultShowLines: boolean, chartType: ChartType): JsonSettingsSchema {
return flotDatakeySettingsSchema(defaultShowLines, chartType);
}
static latestDatakeySettingsSchema(): JsonSettingsSchema {
return latestDatakeySettingsSchemaValue;
}
constructor(private ctx: WidgetContext, private readonly chartType: ChartType) { constructor(private ctx: WidgetContext, private readonly chartType: ChartType) {
this.chartType = this.chartType || 'line'; this.chartType = this.chartType || 'line';
this.settings = ctx.settings as TbFlotSettings; this.settings = ctx.settings as TbFlotSettings;

25
ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts

@ -15,7 +15,7 @@
/// ///
import L, { LeafletMouseEvent } from 'leaflet'; import L, { LeafletMouseEvent } from 'leaflet';
import { CircleData, UnitedMapSettings } from '@home/components/widget/lib/maps/map-models'; import { CircleData, WidgetCircleSettings } from '@home/components/widget/lib/maps/map-models';
import { import {
functionValueCalculator, functionValueCalculator,
parseWithTranslation parseWithTranslation
@ -34,10 +34,11 @@ export class Circle {
tooltip: L.Popup; tooltip: L.Popup;
constructor(private map: LeafletMap, constructor(private map: LeafletMap,
public data: FormattedData, private data: FormattedData,
public dataSources: FormattedData[], private dataSources: FormattedData[],
private settings: UnitedMapSettings, private settings: Partial<WidgetCircleSettings>,
private onDragendListener?) { private onDragendListener?,
snappable = false) {
this.circleData = this.map.convertToCircleFormat(JSON.parse(data[this.settings.circleKeyName])); this.circleData = this.map.convertToCircleFormat(JSON.parse(data[this.settings.circleKeyName]));
const centerPosition = this.createCenterPosition(); const centerPosition = this.createCenterPosition();
const circleFillColor = this.getFillColor(); const circleFillColor = this.getFillColor();
@ -50,7 +51,7 @@ export class Circle {
fillOpacity: settings.circleFillColorOpacity, fillOpacity: settings.circleFillColorOpacity,
opacity: settings.circleStrokeOpacity, opacity: settings.circleStrokeOpacity,
pmIgnore: !settings.editableCircle, pmIgnore: !settings.editableCircle,
snapIgnore: !settings.snappable snapIgnore: !snappable
}).addTo(this.map.map); }).addTo(this.map.map);
if (settings.showCircleLabel) { if (settings.showCircleLabel) {
@ -93,12 +94,14 @@ export class Circle {
if (this.settings.showCircleLabel) { if (this.settings.showCircleLabel) {
if (!this.map.circleLabelText || this.settings.useCircleLabelFunction) { if (!this.map.circleLabelText || this.settings.useCircleLabelFunction) {
const pattern = this.settings.useCircleLabelFunction ? const pattern = this.settings.useCircleLabelFunction ?
safeExecute(this.settings.circleLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.circleLabel; safeExecute(this.settings.parsedCircleLabelFunction,
[this.data, this.dataSources, this.data.dsIndex]) : this.settings.circleLabel;
this.map.circleLabelText = parseWithTranslation.prepareProcessPattern(pattern, true); this.map.circleLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoTooltipCircle = processDataPattern(this.map.circleLabelText, this.data); this.map.replaceInfoTooltipCircle = processDataPattern(this.map.circleLabelText, this.data);
} }
const circleLabelText = fillDataPattern(this.map.circleLabelText, this.map.replaceInfoTooltipCircle, this.data); const circleLabelText = fillDataPattern(this.map.circleLabelText, this.map.replaceInfoTooltipCircle, this.data);
this.leafletCircle.bindTooltip(`<div style="color: ${this.settings.labelColor};"><b>${circleLabelText}</b></div>`, const labelColor = this.map.ctx.widgetConfig.color;
this.leafletCircle.bindTooltip(`<div style="color: ${labelColor};"><b>${circleLabelText}</b></div>`,
{ className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center'}) { className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center'})
.openTooltip(this.leafletCircle.getLatLng()); .openTooltip(this.leafletCircle.getLatLng());
} }
@ -106,7 +109,7 @@ export class Circle {
private updateTooltip() { private updateTooltip() {
const pattern = this.settings.useCircleTooltipFunction ? const pattern = this.settings.useCircleTooltipFunction ?
safeExecute(this.settings.circleTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : safeExecute(this.settings.parsedCircleTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
this.settings.circleTooltipPattern; this.settings.circleTooltipPattern;
this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, this.data, true)); this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, this.data, true));
} }
@ -151,12 +154,12 @@ export class Circle {
} }
private getFillColor(): string | null { private getFillColor(): string | null {
return functionValueCalculator(this.settings.useCircleFillColorFunction, this.settings.circleFillColorFunction, return functionValueCalculator(this.settings.useCircleFillColorFunction, this.settings.parsedCircleFillColorFunction,
[this.data, this.dataSources, this.data.dsIndex], this.settings.circleFillColor); [this.data, this.dataSources, this.data.dsIndex], this.settings.circleFillColor);
} }
private getStrokeColor(): string | null { private getStrokeColor(): string | null {
return functionValueCalculator(this.settings.useCircleStrokeColorFunction, this.settings.circleStrokeColorFunction, return functionValueCalculator(this.settings.useCircleStrokeColorFunction, this.settings.parsedCircleStrokeColorFunction,
[this.data, this.dataSources, this.data.dsIndex], this.settings.circleStrokeColor); [this.data, this.dataSources, this.data.dsIndex], this.settings.circleStrokeColor);
} }

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/common-maps-utils.ts

@ -76,9 +76,12 @@ export function findAngle(startPoint: FormattedData, endPoint: FormattedData, la
} }
export function getDefCenterPosition(position) { export function getDefCenterPosition(position): [number, number] {
if (typeof (position) === 'string') { if (typeof (position) === 'string') {
return position.split(','); const parts = position.split(',');
if (parts.length === 2) {
return [Number(parts[0]), Number(parts[1])];
}
} }
if (typeof (position) === 'object') { if (typeof (position) === 'object') {
return position; return position;

110
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts

@ -21,15 +21,11 @@ import { MarkerClusterGroup, MarkerClusterGroupOptions } from 'leaflet.markerclu
import '@geoman-io/leaflet-geoman-free'; import '@geoman-io/leaflet-geoman-free';
import { import {
CircleData, CircleData, defaultMapSettings,
defaultSettings, MarkerClusteringSettings,
MapSettings,
MarkerIconInfo, MarkerIconInfo,
MarkerImageInfo, MarkerImageInfo,
MarkerSettings, WidgetPolygonSettings, WidgetPolylineSettings, WidgetMarkersSettings, WidgetUnitedMapSettings
PolygonSettings,
PolylineSettings,
UnitedMapSettings
} from './map-models'; } from './map-models';
import { Marker } from './markers'; import { Marker } from './markers';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
@ -66,7 +62,7 @@ export default abstract class LeafletMap {
polygons: Map<string, Polygon> = new Map(); polygons: Map<string, Polygon> = new Map();
circles: Map<string, Circle> = new Map(); circles: Map<string, Circle> = new Map();
map: L.Map; map: L.Map;
options: UnitedMapSettings; options: WidgetUnitedMapSettings;
bounds: L.LatLngBounds; bounds: L.LatLngBounds;
datasources: FormattedData[]; datasources: FormattedData[];
markersCluster: MarkerClusterGroup; markersCluster: MarkerClusterGroup;
@ -86,12 +82,12 @@ export default abstract class LeafletMap {
replaceInfoTooltipCircle: Array<ReplaceInfo> = []; replaceInfoTooltipCircle: Array<ReplaceInfo> = [];
markerTooltipText: string; markerTooltipText: string;
drawRoutes: boolean; drawRoutes: boolean;
showPolygon: boolean;
updatePending = false; updatePending = false;
editPolygons = false; editPolygons = false;
editCircle = false; editCircle = false;
selectedEntity: FormattedData; selectedEntity: FormattedData;
ignoreUpdateBounds = false; ignoreUpdateBounds = false;
initDragModeIgnoreUpdateBoundsSet = false;
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180); southWest = new L.LatLng(-Projection.SphericalMercator['MAX_LATITUDE'], -180);
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
@ -104,37 +100,30 @@ export default abstract class LeafletMap {
protected constructor(public ctx: WidgetContext, protected constructor(public ctx: WidgetContext,
public $container: HTMLElement, public $container: HTMLElement,
options: UnitedMapSettings) { options: WidgetUnitedMapSettings) {
this.options = options; this.options = options;
this.options.tinyColor = tinycolor(this.options.color || defaultMapSettings.color);
this.editPolygons = options.showPolygon && options.editablePolygon; this.editPolygons = options.showPolygon && options.editablePolygon;
this.editCircle = options.showCircle && options.editableCircle; this.editCircle = options.showCircle && options.editableCircle;
L.Icon.Default.imagePath = '/'; L.Icon.Default.imagePath = '/';
this.translateService = this.ctx.$injector.get(TranslateService); this.translateService = this.ctx.$injector.get(TranslateService);
this.initMarkerClusterSettings();
} }
public initSettings(options: MapSettings) { private initMarkerClusterSettings() {
this.options.tinyColor = tinycolor(this.options.color || defaultSettings.color); const markerClusteringSettings: MarkerClusteringSettings = this.options;
const { useClusterMarkers, if (markerClusteringSettings.useClusterMarkers) {
zoomOnClick,
showCoverageOnHover,
removeOutsideVisibleBounds,
animate,
chunkedLoading,
spiderfyOnMaxZoom,
maxClusterRadius,
maxZoom }: MapSettings = options;
if (useClusterMarkers) {
// disabled marker cluster icon // disabled marker cluster icon
(L as any).MarkerCluster = (L as any).MarkerCluster.extend({ (L as any).MarkerCluster = (L as any).MarkerCluster.extend({
options: { pmIgnore: true, ...L.Icon.prototype.options } options: { pmIgnore: true, ...L.Icon.prototype.options }
}); });
const clusteringSettings: MarkerClusterGroupOptions = { const clusteringSettings: MarkerClusterGroupOptions = {
spiderfyOnMaxZoom, spiderfyOnMaxZoom: markerClusteringSettings.spiderfyOnMaxZoom,
zoomToBoundsOnClick: zoomOnClick, zoomToBoundsOnClick: markerClusteringSettings.zoomOnClick,
showCoverageOnHover, showCoverageOnHover: markerClusteringSettings.showCoverageOnHover,
removeOutsideVisibleBounds, removeOutsideVisibleBounds: markerClusteringSettings.removeOutsideVisibleBounds,
animate, animate: markerClusteringSettings.animate,
chunkedLoading, chunkedLoading: markerClusteringSettings.chunkedLoading,
pmIgnore: true, pmIgnore: true,
spiderLegPolylineOptions: { spiderLegPolylineOptions: {
pmIgnore: true pmIgnore: true
@ -143,11 +132,11 @@ export default abstract class LeafletMap {
pmIgnore: true pmIgnore: true
} }
}; };
if (maxClusterRadius && maxClusterRadius > 0) { if (markerClusteringSettings.maxClusterRadius && markerClusteringSettings.maxClusterRadius > 0) {
clusteringSettings.maxClusterRadius = Math.floor(maxClusterRadius); clusteringSettings.maxClusterRadius = Math.floor(markerClusteringSettings.maxClusterRadius);
} }
if (maxZoom && maxZoom >= 0 && maxZoom < 19) { if (markerClusteringSettings.maxZoom && markerClusteringSettings.maxZoom >= 0 && markerClusteringSettings.maxZoom < 19) {
clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom); clusteringSettings.disableClusteringAtZoom = Math.floor(markerClusteringSettings.maxZoom);
} }
this.markersCluster = new MarkerClusterGroup(clusteringSettings); this.markersCluster = new MarkerClusterGroup(clusteringSettings);
} }
@ -355,7 +344,6 @@ export default abstract class LeafletMap {
if (this.options.initDragMode) { if (this.options.initDragMode) {
this.map.pm.enableGlobalDragMode(); this.map.pm.enableGlobalDragMode();
this.ignoreUpdateBounds = true;
} }
this.map.on('pm:globaldrawmodetoggled', (e) => this.ignoreUpdateBounds = e.enabled); this.map.on('pm:globaldrawmodetoggled', (e) => this.ignoreUpdateBounds = e.enabled);
@ -468,7 +456,7 @@ export default abstract class LeafletMap {
}); });
}); });
if (this.options.useDefaultCenterPosition) { if (this.options.useDefaultCenterPosition) {
this.map.panTo(this.options.defaultCenterPosition); this.map.panTo(this.options.parsedDefaultCenterPosition);
this.bounds = map.getBounds(); this.bounds = map.getBounds();
} else { } else {
this.bounds = new L.LatLngBounds(null, null); this.bounds = new L.LatLngBounds(null, null);
@ -488,7 +476,7 @@ export default abstract class LeafletMap {
} }
if (this.updatePending) { if (this.updatePending) {
this.updatePending = false; this.updatePending = false;
this.updateData(this.drawRoutes, this.showPolygon); this.updateData(this.drawRoutes);
} }
this.createdControlButtonTooltip(); this.createdControlButtonTooltip();
} }
@ -565,7 +553,7 @@ export default abstract class LeafletMap {
if (!this.options.fitMapBounds && this.options.defaultZoomLevel) { if (!this.options.fitMapBounds && this.options.defaultZoomLevel) {
this.map.setZoom(this.options.defaultZoomLevel, { animate: false }); this.map.setZoom(this.options.defaultZoomLevel, { animate: false });
if (this.options.useDefaultCenterPosition) { if (this.options.useDefaultCenterPosition) {
this.map.panTo(this.options.defaultCenterPosition, { animate: false }); this.map.panTo(this.options.parsedDefaultCenterPosition, { animate: false });
} }
else { else {
this.map.panTo(this.bounds.getCenter()); this.map.panTo(this.bounds.getCenter());
@ -581,7 +569,7 @@ export default abstract class LeafletMap {
} }
}); });
if (this.options.useDefaultCenterPosition) { if (this.options.useDefaultCenterPosition) {
this.bounds = this.bounds.extend(this.options.defaultCenterPosition); this.bounds = this.bounds.extend(this.options.parsedDefaultCenterPosition);
} }
this.map.fitBounds(this.bounds, { padding: padding || [50, 50], animate: false }); this.map.fitBounds(this.bounds, { padding: padding || [50, 50], animate: false });
this.map.invalidateSize(); this.map.invalidateSize();
@ -643,7 +631,7 @@ export default abstract class LeafletMap {
}; };
} }
updateData(drawRoutes: boolean, showPolygon: boolean) { updateData(drawRoutes: boolean) {
const data = this.ctx.data; const data = this.ctx.data;
let formattedData = formattedDataFormDatasourceData(data); let formattedData = formattedDataFormDatasourceData(data);
if (this.ctx.latestData && this.ctx.latestData.length) { if (this.ctx.latestData && this.ctx.latestData.length) {
@ -654,18 +642,17 @@ export default abstract class LeafletMap {
if (drawRoutes) { if (drawRoutes) {
polyData = formattedDataArrayFromDatasourceData(data); polyData = formattedDataArrayFromDatasourceData(data);
} }
this.updateFromData(drawRoutes, showPolygon, formattedData, polyData); this.updateFromData(drawRoutes, formattedData, polyData);
} }
updateFromData(drawRoutes: boolean, showPolygon: boolean, formattedData: FormattedData[], updateFromData(drawRoutes: boolean, formattedData: FormattedData[],
polyData: FormattedData[][], markerClickCallback?: any) { polyData: FormattedData[][], markerClickCallback?: any) {
this.drawRoutes = drawRoutes; this.drawRoutes = drawRoutes;
this.showPolygon = showPolygon;
if (this.map) { if (this.map) {
if (drawRoutes) { if (drawRoutes) {
this.updatePolylines(polyData, formattedData, false); this.updatePolylines(polyData, formattedData, false);
} }
if (showPolygon) { if (this.options.showPolygon) {
this.updatePolygons(formattedData, false); this.updatePolygons(formattedData, false);
} }
if (this.options.showCircle) { if (this.options.showCircle) {
@ -776,7 +763,7 @@ export default abstract class LeafletMap {
bounds.extend(polyline.leafletPoly.getBounds()); bounds.extend(polyline.leafletPoly.getBounds());
}); });
} }
if (this.showPolygon) { if (this.options.showPolygon) {
this.polygons.forEach((polygon) => { this.polygons.forEach((polygon) => {
bounds.extend(polygon.leafletPoly.getBounds()); bounds.extend(polygon.leafletPoly.getBounds());
}); });
@ -786,7 +773,7 @@ export default abstract class LeafletMap {
bounds.extend(polygon.leafletCircle.getBounds()); bounds.extend(polygon.leafletCircle.getBounds());
}); });
} }
if ((this.options as MarkerSettings).useClusterMarkers && this.markersCluster.getBounds().isValid()) { if (this.options.useClusterMarkers && this.markersCluster.getBounds().isValid()) {
bounds.extend(this.markersCluster.getBounds()); bounds.extend(this.markersCluster.getBounds());
} else { } else {
this.markers.forEach((marker) => { this.markers.forEach((marker) => {
@ -802,6 +789,10 @@ export default abstract class LeafletMap {
this.fitBounds(bounds); this.fitBounds(bounds);
} }
} }
if (this.options.initDragMode && !this.initDragModeIgnoreUpdateBoundsSet) {
this.initDragModeIgnoreUpdateBoundsSet = true;
this.ignoreUpdateBounds = true;
}
} }
// Markers // Markers
@ -815,7 +806,7 @@ export default abstract class LeafletMap {
rawMarkers.forEach(data => { rawMarkers.forEach(data => {
if (data.rotationAngle || data.rotationAngle === 0) { if (data.rotationAngle || data.rotationAngle === 0) {
const currentImage: MarkerImageInfo = this.options.useMarkerImageFunction ? const currentImage: MarkerImageInfo = this.options.useMarkerImageFunction ?
safeExecute(this.options.markerImageFunction, safeExecute(this.options.parsedMarkerImageFunction,
[data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage; [data, this.options.markerImages, markersData, data.dsIndex]) : this.options.currentImage;
const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : ''; const style = currentImage ? 'background-image: url(' + currentImage.url + ');' : '';
this.options.icon = { icon: L.divIcon({ this.options.icon = { icon: L.divIcon({
@ -833,7 +824,7 @@ export default abstract class LeafletMap {
updatedMarkers.push(m); updatedMarkers.push(m);
} }
} else { } else {
m = this.createMarker(data.entityName, data, markersData, this.options, updateBounds, callback); m = this.createMarker(data.entityName, data, markersData, this.options, updateBounds, callback, this.options.snappable);
if (m) { if (m) {
createdMarkers.push(m); createdMarkers.push(m);
} }
@ -867,9 +858,9 @@ export default abstract class LeafletMap {
this.saveLocation(data, this.convertToCustomFormat(e.target._latlng)).subscribe(); this.saveLocation(data, this.convertToCustomFormat(e.target._latlng)).subscribe();
} }
private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: UnitedMapSettings, private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetMarkersSettings>,
updateBounds = true, callback?): Marker { updateBounds = true, callback?, snappable = false): Marker {
const newMarker = new Marker(this, this.convertPosition(data), settings, data, dataSources, this.dragMarker); const newMarker = new Marker(this, this.convertPosition(data), settings, data, dataSources, this.dragMarker, snappable);
if (callback) { if (callback) {
newMarker.leafletMarker.on('click', () => { newMarker.leafletMarker.on('click', () => {
callback(data, true); callback(data, true);
@ -885,7 +876,7 @@ export default abstract class LeafletMap {
return newMarker; return newMarker;
} }
private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings): Marker { private updateMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetMarkersSettings>): Marker {
const marker: Marker = this.markers.get(key); const marker: Marker = this.markers.get(key);
const location = this.convertPosition(data); const location = this.convertPosition(data);
marker.updateMarkerPosition(location); marker.updateMarkerPosition(location);
@ -933,7 +924,7 @@ export default abstract class LeafletMap {
if (!!this.convertPosition(pdata)) { if (!!this.convertPosition(pdata)) {
const dsData = pointsData.map(ds => ds[tsIndex]); const dsData = pointsData.map(ds => ds[tsIndex]);
if (this.options.useColorPointFunction) { if (this.options.useColorPointFunction) {
pointColor = safeExecute(this.options.colorPointFunction, [pdata, dsData, pdata.dsIndex]); pointColor = safeExecute(this.options.parsedColorPointFunction, [pdata, dsData, pdata.dsIndex]);
} }
const point = L.circleMarker(this.convertPosition(pdata), { const point = L.circleMarker(this.convertPosition(pdata), {
color: pointColor, color: pointColor,
@ -980,7 +971,8 @@ export default abstract class LeafletMap {
}); });
} }
createPolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[], settings: PolylineSettings, updateBounds = true) { createPolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[],
settings: Partial<WidgetPolylineSettings>, updateBounds = true) {
const poly = new Polyline(this.map, const poly = new Polyline(this.map,
tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings); tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings);
if (updateBounds) { if (updateBounds) {
@ -990,7 +982,8 @@ export default abstract class LeafletMap {
this.polylines.set(data.entityName, poly); this.polylines.set(data.entityName, poly);
} }
updatePolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[], settings: PolylineSettings, updateBounds = true) { updatePolyline(data: FormattedData, tsData: FormattedData[], dsData: FormattedData[],
settings: Partial<WidgetPolylineSettings>, updateBounds = true) {
const poly = this.polylines.get(data.entityName); const poly = this.polylines.get(data.entityName);
const oldBounds = poly.leafletPoly.getBounds(); const oldBounds = poly.leafletPoly.getBounds();
poly.updatePolyline(tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings); poly.updatePolyline(tsData.map(el => this.convertPosition(el)).filter(el => !!el), data, dsData, settings);
@ -1031,7 +1024,7 @@ export default abstract class LeafletMap {
if (this.polygons.get(data.entityName)) { if (this.polygons.get(data.entityName)) {
this.updatePolygon(data, polyData, this.options, updateBounds); this.updatePolygon(data, polyData, this.options, updateBounds);
} else { } else {
this.createPolygon(data, polyData, this.options, updateBounds); this.createPolygon(data, polyData, this.options, updateBounds, this.options.snappable);
} }
keys.push(data.entityName); keys.push(data.entityName);
} }
@ -1066,8 +1059,9 @@ export default abstract class LeafletMap {
this.saveLocation(data, this.convertPolygonToCustomFormat(coordinates)).subscribe(() => {}); this.saveLocation(data, this.convertPolygonToCustomFormat(coordinates)).subscribe(() => {});
} }
createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: UnitedMapSettings, updateBounds = true) { createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetPolygonSettings>,
const polygon = new Polygon(this.map, polyData, dataSources, settings, this.dragPolygonVertex); updateBounds = true, snappable = false) {
const polygon = new Polygon(this, polyData, dataSources, settings, this.dragPolygonVertex, snappable);
if (updateBounds) { if (updateBounds) {
const bounds = polygon.leafletPoly.getBounds(); const bounds = polygon.leafletPoly.getBounds();
this.fitBounds(bounds); this.fitBounds(bounds);
@ -1075,7 +1069,7 @@ export default abstract class LeafletMap {
this.polygons.set(polyData.entityName, polygon); this.polygons.set(polyData.entityName, polygon);
} }
updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) { updatePolygon(polyData: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetPolygonSettings>, updateBounds = true) {
const poly = this.polygons.get(polyData.entityName); const poly = this.polygons.get(polyData.entityName);
const oldBounds = poly.leafletPoly.getBounds(); const oldBounds = poly.leafletPoly.getBounds();
poly.updatePolygon(polyData, dataSources, settings); poly.updatePolygon(polyData, dataSources, settings);
@ -1167,7 +1161,7 @@ export default abstract class LeafletMap {
} }
createdCircle(data: FormattedData, dataSources: FormattedData[], updateBounds = true) { createdCircle(data: FormattedData, dataSources: FormattedData[], updateBounds = true) {
const circle = new Circle(this, data, dataSources, this.options, this.dragCircleVertex); const circle = new Circle(this, data, dataSources, this.options, this.dragCircleVertex, this.options.snappable);
if (updateBounds) { if (updateBounds) {
const bounds = circle.leafletCircle.getBounds(); const bounds = circle.leafletCircle.getBounds();
this.fitBounds(bounds); this.fitBounds(bounds);

878
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts

@ -17,138 +17,433 @@
import { Datasource, FormattedData } from '@app/shared/models/widget.models'; import { Datasource, FormattedData } from '@app/shared/models/widget.models';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { BaseIconOptions, Icon } from 'leaflet'; import { BaseIconOptions, Icon } from 'leaflet';
import { DeviceProfileType } from '@shared/models/device.models';
export const DEFAULT_MAP_PAGE_SIZE = 16384; export const DEFAULT_MAP_PAGE_SIZE = 16384;
export const DEFAULT_ZOOM_LEVEL = 8; export const DEFAULT_ZOOM_LEVEL = 8;
export type MarkerImageInfo = {
url: string;
size: number;
markerOffset?: [number, number];
tooltipOffset?: [number, number];
};
export type MarkerIconInfo = {
icon: Icon<BaseIconOptions>;
size: [number, number];
};
export interface MapImage {
imageUrl: string;
aspect: number;
update?: boolean;
}
export type actionsHandler = ($event: Event, datasource: Datasource) => void;
export interface CircleData {
latitude: number;
longitude: number;
radius: number;
}
export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => MarkerImageInfo; export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => MarkerImageInfo;
export type PosFuncton = (origXPos, origYPos) => { x, y }; export type PosFuncton = (origXPos, origYPos) => { x, y };
export type MarkerIconReadyFunction = (icon: MarkerIconInfo) => void; export type MarkerIconReadyFunction = (icon: MarkerIconInfo) => void;
export type MapSettings = { export enum GoogleMapType {
draggableMarker: boolean; roadmap = 'roadmap',
editablePolygon: boolean; satellite = 'satellite',
posFunction: PosFuncton; hybrid = 'hybrid',
defaultZoomLevel?: number; terrain = 'terrain'
disableScrollZooming?: boolean; }
disableZoomControl?: boolean;
minZoomLevel?: number; export const googleMapTypeProviderTranslationMap = new Map<GoogleMapType, string>(
useClusterMarkers: boolean; [
latKeyName?: string; [GoogleMapType.roadmap, 'widgets.maps.google-map-type-roadmap'],
lngKeyName?: string; [GoogleMapType.satellite, 'widgets.maps.google-map-type-satelite'],
xPosKeyName?: string; [GoogleMapType.hybrid, 'widgets.maps.google-map-type-hybrid'],
yPosKeyName?: string; [GoogleMapType.terrain, 'widgets.maps.google-map-type-terrain']
imageEntityAlias: string; ]
imageUrlAttribute: string; );
mapProvider: MapProviders;
mapProviderHere: string; export interface GoogleMapProviderSettings {
mapUrl?: string; gmApiKey: string;
mapImageUrl?: string; gmDefaultMapType: GoogleMapType;
provider?: MapProviders; }
credentials?: any; // declare credentials format
gmApiKey?: string; export const defaultGoogleMapProviderSettings: GoogleMapProviderSettings = {
defaultCenterPosition?: [number, number]; gmApiKey: 'AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q',
markerClusteringSetting?; gmDefaultMapType: GoogleMapType.roadmap
useDefaultCenterPosition?: boolean; };
gmDefaultMapType?: string;
useLabelFunction: boolean; export enum OpenStreetMapProvider {
zoomOnClick: boolean, openStreetMapnik = 'OpenStreetMap.Mapnik',
maxZoom: number, openStreetHot = 'OpenStreetMap.HOT',
showCoverageOnHover: boolean, esriWorldStreetMap = 'Esri.WorldStreetMap',
animate: boolean, esriWorldTopoMap = 'Esri.WorldTopoMap',
maxClusterRadius: number, cartoDbPositron = 'CartoDB.Positron',
spiderfyOnMaxZoom: boolean, cartoDbDarkMatter = 'CartoDB.DarkMatter'
chunkedLoading: boolean, }
removeOutsideVisibleBounds: boolean,
useCustomProvider: boolean, export const openStreetMapProviderTranslationMap = new Map<OpenStreetMapProvider, string>(
customProviderTileUrl: string; [
mapPageSize: number; [OpenStreetMapProvider.openStreetMapnik, 'widgets.maps.openstreet-provider-mapnik'],
[OpenStreetMapProvider.openStreetHot, 'widgets.maps.openstreet-provider-hot'],
[OpenStreetMapProvider.esriWorldStreetMap, 'widgets.maps.openstreet-provider-esri-street'],
[OpenStreetMapProvider.esriWorldTopoMap, 'widgets.maps.openstreet-provider-esri-topo'],
[OpenStreetMapProvider.cartoDbPositron, 'widgets.maps.openstreet-provider-cartodb-positron'],
[OpenStreetMapProvider.cartoDbDarkMatter, 'widgets.maps.openstreet-provider-cartodb-dark-matter']
]
);
export interface OpenStreetMapProviderSettings {
mapProvider: OpenStreetMapProvider;
useCustomProvider: boolean;
customProviderTileUrl?: string;
}
export const defaultOpenStreetMapProviderSettings: OpenStreetMapProviderSettings = {
mapProvider: OpenStreetMapProvider.openStreetMapnik,
useCustomProvider: false,
customProviderTileUrl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
};
export enum HereMapProvider {
hereNormalDay = 'HERE.normalDay',
hereNormalNight = 'HERE.normalNight',
hereHybridDay = 'HERE.hybridDay',
hereTerrainDay = 'HERE.terrainDay'
}
export const hereMapProviderTranslationMap = new Map<HereMapProvider, string>(
[
[HereMapProvider.hereNormalDay, 'widgets.maps.here-map-normal-day'],
[HereMapProvider.hereNormalNight, 'widgets.maps.here-map-normal-night'],
[HereMapProvider.hereHybridDay, 'widgets.maps.here-map-hybrid-day'],
[HereMapProvider.hereTerrainDay, 'widgets.maps.here-map-terrain-day']
]
);
export interface HereMapProviderSettings {
mapProviderHere: HereMapProvider;
credentials: {
app_id: string;
app_code: string;
};
}
export const defaultHereMapProviderSettings: HereMapProviderSettings = {
mapProviderHere: HereMapProvider.hereNormalDay,
credentials: {
app_id: 'AhM6TzD9ThyK78CT3ptx',
app_code: 'p6NPiITB3Vv0GMUFnkLOOg'
}
};
export interface ImageMapProviderSettings {
mapImageUrl?: string;
imageEntityAlias?: string;
imageUrlAttribute?: string;
}
export const defaultImageMapProviderSettings: ImageMapProviderSettings = {
mapImageUrl: 'data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==',
imageEntityAlias: '',
imageUrlAttribute: ''
};
export enum TencentMapType {
roadmap = 'roadmap',
satellite = 'satellite',
hybrid = 'hybrid'
}
export const tencentMapTypeProviderTranslationMap = new Map<TencentMapType, string>(
[
[TencentMapType.roadmap, 'widgets.maps.tencent-map-type-roadmap'],
[TencentMapType.satellite, 'widgets.maps.tencent-map-type-satelite'],
[TencentMapType.hybrid, 'widgets.maps.tencent-map-type-hybrid']
]
);
export interface TencentMapProviderSettings {
tmApiKey: string;
tmDefaultMapType: TencentMapType;
}
export const defaultTencentMapProviderSettings: TencentMapProviderSettings = {
tmApiKey: '84d6d83e0e51e481e50454ccbe8986b',
tmDefaultMapType: TencentMapType.roadmap
}; };
export enum MapProviders { export enum MapProviders {
google = 'google-map', google = 'google-map',
openstreet = 'openstreet-map', openstreet = 'openstreet-map',
here = 'here', here = 'here',
image = 'image-map', image = 'image-map',
tencent = 'tencent-map' tencent = 'tencent-map'
} }
export type MarkerImageInfo = { export const mapProviderTranslationMap = new Map<MapProviders, string>(
url: string; [
size: number; [MapProviders.google, 'widgets.maps.map-provider-google'],
markerOffset?: [number, number]; [MapProviders.openstreet, 'widgets.maps.map-provider-openstreet'],
tooltipOffset?: [number, number]; [MapProviders.here, 'widgets.maps.map-provider-here'],
[MapProviders.image, 'widgets.maps.map-provider-image'],
[MapProviders.tencent, 'widgets.maps.map-provider-tencent']
]
);
export interface MapProviderSettings extends GoogleMapProviderSettings, OpenStreetMapProviderSettings,
HereMapProviderSettings, ImageMapProviderSettings, TencentMapProviderSettings {
provider: MapProviders;
}
export const defaultMapProviderSettings: MapProviderSettings = {
provider: MapProviders.openstreet,
...defaultGoogleMapProviderSettings,
...defaultOpenStreetMapProviderSettings,
...defaultHereMapProviderSettings,
...defaultImageMapProviderSettings,
...defaultTencentMapProviderSettings
}; };
export type MarkerIconInfo = { export interface CommonMapSettings {
icon: Icon<BaseIconOptions>; latKeyName: string;
size: [number, number]; lngKeyName: string;
xPosKeyName: string;
yPosKeyName: string;
defaultZoomLevel: number;
defaultCenterPosition?: string;
disableScrollZooming: boolean;
disableZoomControl: boolean;
fitMapBounds: boolean;
useDefaultCenterPosition: boolean;
mapPageSize: number;
}
export interface WidgetCommonMapSettings extends CommonMapSettings {
parsedDefaultCenterPosition: [number, number];
minZoomLevel: number;
}
export interface WidgetToolipSettings {
tooltipAction: { [name: string]: actionsHandler };
}
export const defaultCommonMapSettings: CommonMapSettings = {
latKeyName: 'latitude',
lngKeyName: 'longitude',
xPosKeyName: 'xPos',
yPosKeyName: 'yPos',
defaultZoomLevel: null,
defaultCenterPosition: '0,0',
disableScrollZooming: false,
disableZoomControl: false,
fitMapBounds: true,
useDefaultCenterPosition: false,
mapPageSize: DEFAULT_MAP_PAGE_SIZE
};
export interface TripAnimationCommonSettings {
normalizationStep: number;
latKeyName: string;
lngKeyName: string;
showTooltip: boolean;
tooltipColor: string;
tooltipFontColor: string;
tooltipOpacity: number;
useTooltipFunction: boolean;
tooltipPattern?: string;
tooltipFunction?: string;
autocloseTooltip: boolean;
}
export interface WidgetTripAnimationCommonSettings extends TripAnimationCommonSettings {
parsedTooltipFunction: GenericFunction;
}
export const defaultTripAnimationCommonSettings: TripAnimationCommonSettings = {
normalizationStep: 1000,
latKeyName: 'latitude',
lngKeyName: 'longitude',
showTooltip: true,
tooltipColor: '#fff',
tooltipFontColor: '#000',
tooltipOpacity: 1,
useTooltipFunction: false,
tooltipPattern: '<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}',
tooltipFunction: null,
autocloseTooltip: true
}; };
export type MarkerSettings = { export enum ShowTooltipAction {
tooltipPattern?: any; click = 'click',
tooltipAction: { [name: string]: actionsHandler }; hover = 'hover'
icon?: MarkerIconInfo; }
showLabel?: boolean;
label: string; export const showTooltipActionTranslationMap = new Map<ShowTooltipAction, string>(
labelColor: string; [
labelText: string; [ShowTooltipAction.click, 'widgets.maps.show-tooltip-action-click'],
useLabelFunction: boolean; [ShowTooltipAction.hover, 'widgets.maps.show-tooltip-action-hover']
draggableMarker: boolean; ]
showTooltip?: boolean; );
useTooltipFunction: boolean;
useColorFunction: boolean; export interface MarkersSettings {
color?: string; markerOffsetX: number;
tinyColor?: tinycolor.Instance; markerOffsetY: number;
autocloseTooltip: boolean; posFunction?: string;
showTooltipAction: string; draggableMarker: boolean;
useClusterMarkers: boolean; showLabel: boolean;
currentImage?: MarkerImageInfo; useLabelFunction: boolean;
useMarkerImageFunction?: boolean; label?: string;
markerImages?: string[]; labelFunction?: string;
markerImageSize: number; showTooltip: boolean;
fitMapBounds: boolean; showTooltipAction: ShowTooltipAction;
markerImage: string; autocloseTooltip: boolean;
markerClick: { [name: string]: actionsHandler }; useTooltipFunction: boolean;
colorFunction: GenericFunction; tooltipPattern?: string;
tooltipFunction: GenericFunction; tooltipFunction?: string;
labelFunction: GenericFunction; tooltipOffsetX: number;
markerImageFunction?: MarkerImageFunction; tooltipOffsetY: number;
markerOffsetX: number; color?: string;
markerOffsetY: number; useColorFunction: boolean;
tooltipOffsetX: number; colorFunction?: string;
tooltipOffsetY: number; useMarkerImageFunction: boolean;
markerImage?: string;
markerImageSize?: number;
markerImageFunction?: string;
markerImages?: string[];
}
export interface WidgetMarkersSettings extends MarkersSettings, WidgetToolipSettings {
parsedLabelFunction: GenericFunction;
parsedTooltipFunction: GenericFunction;
parsedColorFunction: GenericFunction;
parsedMarkerImageFunction: MarkerImageFunction;
markerClick: { [name: string]: actionsHandler };
currentImage: MarkerImageInfo;
tinyColor: tinycolor.Instance;
icon: MarkerIconInfo;
}
export const defaultMarkersSettings: MarkersSettings = {
markerOffsetX: 0.5,
markerOffsetY: 1,
posFunction: 'return {x: origXPos, y: origYPos};',
draggableMarker: false,
showLabel: true,
useLabelFunction: false,
label: '${entityName}',
labelFunction: null,
showTooltip: true,
showTooltipAction: ShowTooltipAction.click,
autocloseTooltip: true,
useTooltipFunction: false,
tooltipPattern: '<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}',
tooltipFunction: null,
tooltipOffsetX: 0,
tooltipOffsetY: -1,
color: '#FE7569',
useColorFunction: false,
colorFunction: null,
useMarkerImageFunction: false,
markerImage: null,
markerImageSize: 34,
markerImageFunction: null,
markerImages: []
};
export interface TripAnimationMarkerSettings {
rotationAngle: number;
showLabel: boolean;
useLabelFunction: boolean;
label?: string;
labelFunction?: string;
useMarkerImageFunction: boolean;
markerImage?: string;
markerImageSize?: number;
markerImageFunction?: string;
markerImages?: string[];
}
export interface WidgetTripAnimationMarkerSettings extends TripAnimationMarkerSettings {
parsedLabelFunction: GenericFunction;
parsedMarkerImageFunction: MarkerImageFunction;
}
export const defaultTripAnimationMarkersSettings: TripAnimationMarkerSettings = {
rotationAngle: 0,
showLabel: true,
useLabelFunction: false,
label: '${entityName}',
labelFunction: null,
useMarkerImageFunction: false,
markerImage: null,
markerImageSize: 34,
markerImageFunction: null,
markerImages: []
}; };
export type PolygonSettings = { export interface PolygonSettings {
showPolygon: boolean; showPolygon: boolean;
polygonKeyName: string; polygonKeyName: string;
polKeyName: string; // deprecated editablePolygon: boolean;
polygonStrokeOpacity: number; showPolygonLabel: boolean;
polygonOpacity: number; usePolygonLabelFunction: boolean;
polygonStrokeWeight: number; polygonLabel?: string;
polygonStrokeColor: string; polygonLabelFunction?: string;
polygonColor: string; showPolygonTooltip: boolean;
showPolygonLabel?: boolean; showPolygonTooltipAction: ShowTooltipAction;
polygonLabel: string; autoClosePolygonTooltip: boolean;
polygonLabelColor: string; usePolygonTooltipFunction: boolean;
polygonLabelText: string; polygonTooltipPattern?: string;
usePolygonLabelFunction: boolean; polygonTooltipFunction?: string;
showPolygonTooltip: boolean; polygonColor?: string;
autoClosePolygonTooltip: boolean; polygonOpacity?: number;
showPolygonTooltipAction: string; usePolygonColorFunction: boolean;
tooltipAction: { [name: string]: actionsHandler }; polygonColorFunction?: string;
polygonTooltipPattern: string; polygonStrokeColor?: string;
usePolygonTooltipFunction: boolean; polygonStrokeOpacity?: number;
polygonClick: { [name: string]: actionsHandler }; polygonStrokeWeight?: number;
usePolygonColorFunction: boolean; usePolygonStrokeColorFunction: boolean;
usePolygonStrokeColorFunction: boolean; polygonStrokeColorFunction?: string;
polygonTooltipFunction: GenericFunction; }
polygonColorFunction?: GenericFunction;
polygonStrokeColorFunction?: GenericFunction; export interface WidgetPolygonSettings extends PolygonSettings, WidgetToolipSettings {
polygonLabelFunction?: GenericFunction; parsedPolygonLabelFunction: GenericFunction;
editablePolygon: boolean; parsedPolygonTooltipFunction: GenericFunction;
parsedPolygonColorFunction: GenericFunction;
parsedPolygonStrokeColorFunction: GenericFunction;
polygonClick: { [name: string]: actionsHandler };
}
export const defaultPolygonSettings: PolygonSettings = {
showPolygon: false,
polygonKeyName: 'perimeter',
editablePolygon: false,
showPolygonLabel: false,
usePolygonLabelFunction: false,
polygonLabel: '${entityName}',
polygonLabelFunction: null,
showPolygonTooltip: false,
showPolygonTooltipAction: ShowTooltipAction.click,
autoClosePolygonTooltip: true,
usePolygonTooltipFunction: false,
polygonTooltipPattern: '<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${ts:7}',
polygonTooltipFunction: null,
polygonColor: '#3388ff',
polygonOpacity: 0.2,
usePolygonColorFunction: false,
polygonColorFunction: null,
polygonStrokeColor: '#3388ff',
polygonStrokeOpacity: 1,
polygonStrokeWeight: 3,
usePolygonStrokeColorFunction: false,
polygonStrokeColorFunction: null
}; };
export interface CircleSettings { export interface CircleSettings {
@ -157,178 +452,221 @@ export interface CircleSettings {
editableCircle: boolean; editableCircle: boolean;
showCircleLabel: boolean; showCircleLabel: boolean;
useCircleLabelFunction: boolean; useCircleLabelFunction: boolean;
circleLabel: string; circleLabel?: string;
circleLabelFunction?: GenericFunction; circleLabelFunction?: string;
circleFillColor: string;
useCircleFillColorFunction: boolean;
circleFillColorFunction?: GenericFunction;
circleFillColorOpacity: number;
circleStrokeColor: string;
useCircleStrokeColorFunction: boolean;
circleStrokeColorFunction: GenericFunction;
circleStrokeOpacity: number;
circleStrokeWeight: number;
showCircleTooltip: boolean; showCircleTooltip: boolean;
showCircleTooltipAction: string; showCircleTooltipAction: ShowTooltipAction;
autoCloseCircleTooltip: boolean; autoCloseCircleTooltip: boolean;
useCircleTooltipFunction: boolean; useCircleTooltipFunction: boolean;
circleTooltipPattern: string; circleTooltipPattern?: string;
circleTooltipFunction?: GenericFunction; circleTooltipFunction?: string;
circleClick?: { [name: string]: actionsHandler }; circleFillColor?: string;
} circleFillColorOpacity?: number;
useCircleFillColorFunction: boolean;
export type PolylineSettings = { circleFillColorFunction?: string;
usePolylineDecorator: any; circleStrokeColor?: string;
autocloseTooltip: boolean; circleStrokeOpacity?: number;
showTooltipAction: string; circleStrokeWeight?: number;
useColorFunction: any; useCircleStrokeColorFunction: boolean;
tooltipAction: { [name: string]: actionsHandler }; circleStrokeColorFunction?: string;
color: string; }
useStrokeOpacityFunction: any;
strokeOpacity: number; export interface WidgetCircleSettings extends CircleSettings, WidgetToolipSettings {
useStrokeWeightFunction: any; parsedCircleLabelFunction: GenericFunction;
strokeWeight: number; parsedCircleTooltipFunction: GenericFunction;
decoratorOffset: string | number; parsedCircleFillColorFunction: GenericFunction;
endDecoratorOffset: string | number; parsedCircleStrokeColorFunction: GenericFunction;
decoratorRepeat: string | number; circleClick: { [name: string]: actionsHandler };
decoratorSymbol: any; }
decoratorSymbolSize: any;
useDecoratorCustomColor: any; export const defaultCircleSettings: CircleSettings = {
decoratorCustomColor: any; showCircle: false,
circleKeyName: 'perimeter',
editableCircle: false,
colorFunction: GenericFunction; showCircleLabel: false,
strokeOpacityFunction: GenericFunction; useCircleLabelFunction: false,
strokeWeightFunction: GenericFunction; circleLabel: '${entityName}',
circleLabelFunction: null,
showCircleTooltip: false,
showCircleTooltipAction: ShowTooltipAction.click,
autoCloseCircleTooltip: true,
useCircleTooltipFunction: false,
circleTooltipPattern: '<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${ts:7}',
circleTooltipFunction: null,
circleFillColor: '#3388ff',
circleFillColorOpacity: 0.2,
useCircleFillColorFunction: false,
circleFillColorFunction: null,
circleStrokeColor: '#3388ff',
circleStrokeOpacity: 1,
circleStrokeWeight: 3,
useCircleStrokeColorFunction: false,
circleStrokeColorFunction: null
}; };
export interface EditorSettings { export enum PolylineDecoratorSymbol {
snappable: boolean; arrowHead = 'arrowHead',
initDragMode: boolean; dash = 'dash'
hideAllControlButton: boolean;
hideDrawControlButton: boolean;
hideEditControlButton: boolean;
hideRemoveControlButton: boolean;
} }
export interface HistorySelectSettings { export const polylineDecoratorSymbolTranslationMap = new Map<PolylineDecoratorSymbol, string>(
buttonColor: string; [
[PolylineDecoratorSymbol.arrowHead, 'widgets.maps.decorator-symbol-arrow-head'],
[PolylineDecoratorSymbol.dash, 'widgets.maps.decorator-symbol-dash']
]
);
export interface PolylineSettings {
useStrokeWeightFunction?: boolean;
strokeWeight: number;
strokeWeightFunction?: string;
useStrokeOpacityFunction?: boolean;
strokeOpacity: number;
strokeOpacityFunction?: string;
useColorFunction?: boolean;
color?: string;
colorFunction?: string;
usePolylineDecorator?: boolean;
decoratorSymbol?: PolylineDecoratorSymbol;
decoratorSymbolSize?: number;
useDecoratorCustomColor?: boolean;
decoratorCustomColor?: string;
decoratorOffset?: string;
endDecoratorOffset?: string;
decoratorRepeat?: string;
} }
export interface MapImage { export interface WidgetPolylineSettings extends PolylineSettings {
imageUrl: string; parsedColorFunction: GenericFunction;
aspect: number; parsedStrokeOpacityFunction: GenericFunction;
update?: boolean; parsedStrokeWeightFunction: GenericFunction;
}
export interface TripAnimationSettings extends PolygonSettings, CircleSettings {
showPoints: boolean;
pointColor: string;
pointSize: number;
pointTooltipOnRightPanel: boolean;
usePointAsAnchor: boolean;
normalizationStep: number;
showPolygon: boolean;
showLabel: boolean;
showTooltip: boolean;
latKeyName: string;
lngKeyName: string;
rotationAngle: number;
label: string;
tooltipPattern: string;
tooltipColor: string;
tooltipOpacity: number;
tooltipFontColor: string;
useTooltipFunction: boolean;
useLabelFunction: boolean;
pointAsAnchorFunction: GenericFunction;
tooltipFunction: GenericFunction;
labelFunction: GenericFunction;
useColorPointFunction: boolean;
colorPointFunction: GenericFunction;
} }
export type actionsHandler = ($event: Event, datasource: Datasource) => void; export const defaultRouteMapSettings: PolylineSettings = {
strokeWeight: 2,
strokeOpacity: 1.0
};
export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings export const defaultTripAnimationPathSettings: PolylineSettings = {
& CircleSettings & TripAnimationSettings & EditorSettings; color: null,
strokeWeight: 2,
export const defaultSettings: Partial<UnitedMapSettings> = { strokeOpacity: 1,
xPosKeyName: 'xPos', useColorFunction: false,
yPosKeyName: 'yPos', colorFunction: null,
markerOffsetX: 0.5, usePolylineDecorator: false,
markerOffsetY: 1, decoratorSymbol: PolylineDecoratorSymbol.arrowHead,
tooltipOffsetX: 0, decoratorSymbolSize: 10,
tooltipOffsetY: -1, useDecoratorCustomColor: false,
latKeyName: 'latitude', decoratorCustomColor: '#000',
lngKeyName: 'longitude', decoratorOffset: '20px',
polygonKeyName: 'perimeter', endDecoratorOffset: '20px',
showLabel: false, decoratorRepeat: '20px'
label: '${entityName}',
showTooltip: false,
useDefaultCenterPosition: false,
showTooltipAction: 'click',
autocloseTooltip: false,
showPolygon: false,
labelColor: '#000000',
color: '#FE7569',
showPolygonLabel: false,
polygonColor: '#3388ff',
polygonStrokeColor: '#3388ff',
polygonLabelColor: '#000000',
polygonOpacity: 0.2,
polygonStrokeOpacity: 1,
polygonStrokeWeight: 3,
showPolygonTooltipAction: 'click',
autoClosePolygonTooltip: true,
useLabelFunction: false,
markerImages: [],
strokeWeight: 2,
strokeOpacity: 1.0,
disableScrollZooming: false,
minZoomLevel: 16,
credentials: '',
markerClusteringSetting: null,
draggableMarker: false,
editablePolygon: false,
fitMapBounds: true,
mapPageSize: DEFAULT_MAP_PAGE_SIZE,
snappable: false,
initDragMode: false,
hideAllControlButton: false,
hideDrawControlButton: false,
hideEditControlButton: false,
hideRemoveControlButton: false,
showCircle: true,
circleKeyName: 'perimeter',
editableCircle: false,
showCircleLabel: false,
useCircleLabelFunction: false,
circleLabel: '${entityName}',
circleFillColor: '#3388ff',
useCircleFillColorFunction: false,
circleFillColorOpacity: 0.2,
circleStrokeColor: '#3388ff',
useCircleStrokeColorFunction: false,
circleStrokeOpacity: 1,
circleStrokeWeight: 3,
showCircleTooltip: false,
showCircleTooltipAction: 'click',
autoCloseCircleTooltip: true,
useCircleTooltipFunction: false
}; };
export interface CircleData { export interface PointsSettings {
latitude: number; showPoints?: boolean;
longitude: number; pointColor?: string;
radius: number; useColorPointFunction?: false;
colorPointFunction?: string;
pointSize?: number;
usePointAsAnchor?: false;
pointAsAnchorFunction?: string;
pointTooltipOnRightPanel?: boolean;
}
export interface WidgetPointsSettings extends PointsSettings {
parsedColorPointFunction: GenericFunction;
parsedPointAsAnchorFunction: GenericFunction;
}
export const defaultTripAnimationPointSettings: PointsSettings = {
showPoints: false,
pointColor: null,
useColorPointFunction: false,
colorPointFunction: null,
pointSize: 10,
usePointAsAnchor: false,
pointAsAnchorFunction: null,
pointTooltipOnRightPanel: true
};
export interface MarkerClusteringSettings {
useClusterMarkers: boolean;
zoomOnClick: boolean;
maxZoom: number;
maxClusterRadius: number;
animate: boolean;
spiderfyOnMaxZoom: boolean;
showCoverageOnHover: boolean;
chunkedLoading: boolean;
removeOutsideVisibleBounds: boolean;
}
export const defaultMarkerClusteringSettings: MarkerClusteringSettings = {
useClusterMarkers: false,
zoomOnClick: true,
maxZoom: null,
maxClusterRadius: 80,
animate: true,
spiderfyOnMaxZoom: false,
showCoverageOnHover: true,
chunkedLoading: false,
removeOutsideVisibleBounds: true
};
export interface MapEditorSettings {
snappable: boolean;
initDragMode: boolean;
hideAllControlButton: boolean;
hideDrawControlButton: boolean;
hideEditControlButton: boolean;
hideRemoveControlButton: boolean;
}
export const defaultMapEditorSettings: MapEditorSettings = {
snappable: false,
initDragMode: false,
hideAllControlButton: false,
hideDrawControlButton: false,
hideEditControlButton: false,
hideRemoveControlButton: false
};
export type UnitedMapSettings = MapProviderSettings & CommonMapSettings & MarkersSettings &
PolygonSettings & CircleSettings & PolylineSettings & PointsSettings & MarkerClusteringSettings & MapEditorSettings;
export const defaultMapSettings: UnitedMapSettings = {
...defaultMapProviderSettings,
...defaultCommonMapSettings,
...defaultMarkersSettings,
...defaultPolygonSettings,
...defaultCircleSettings,
...defaultRouteMapSettings,
...defaultMarkerClusteringSettings,
...defaultMapEditorSettings
};
export type WidgetUnitedMapSettings = UnitedMapSettings & Partial<WidgetCommonMapSettings &
WidgetMarkersSettings & WidgetPolygonSettings & WidgetCircleSettings & WidgetPolylineSettings & WidgetPointsSettings>;
export type UnitedTripAnimationSettings = MapProviderSettings & TripAnimationCommonSettings & TripAnimationMarkerSettings &
PolylineSettings & PointsSettings & PolygonSettings & CircleSettings;
export const defaultTripAnimationSettings: UnitedTripAnimationSettings = {
...defaultMapProviderSettings,
...defaultTripAnimationCommonSettings,
...defaultTripAnimationMarkersSettings,
...defaultTripAnimationPathSettings,
...defaultTripAnimationPointSettings,
...defaultPolygonSettings,
...defaultCircleSettings,
};
export interface HistorySelectSettings {
buttonColor: string;
} }
export const circleDataKeys: Array<keyof CircleData> = ['latitude', 'longitude', 'radius']; export type WidgetUnitedTripAnimationSettings = UnitedTripAnimationSettings & HistorySelectSettings &
Partial<WidgetTripAnimationCommonSettings & WidgetTripAnimationMarkerSettings &
WidgetPolylineSettings & WidgetPointsSettings & WidgetPolygonSettings & WidgetCircleSettings>;
export const hereProviders = [
'HERE.normalDay',
'HERE.normalNight',
'HERE.hybridDay',
'HERE.terrainDay'
];

70
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts

@ -14,7 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { defaultSettings, hereProviders, MapProviders, UnitedMapSettings } from './map-models'; import {
defaultMapSettings,
MapProviders,
UnitedMapSettings,
WidgetUnitedMapSettings
} from './map-models';
import LeafletMap from './leaflet-map'; import LeafletMap from './leaflet-map';
import { import {
commonMapSettingsSchema, commonMapSettingsSchema,
@ -96,7 +101,7 @@ export class MapWidgetController implements MapWidgetInterface {
provider: MapProviders; provider: MapProviders;
schema: JsonSettingsSchema; schema: JsonSettingsSchema;
data: DatasourceData[]; data: DatasourceData[];
settings: UnitedMapSettings; settings: WidgetUnitedMapSettings;
pageLink: EntityDataPageLink; pageLink: EntityDataPageLink;
public static dataKeySettingsSchema(): object { public static dataKeySettingsSchema(): object {
@ -190,7 +195,7 @@ export class MapWidgetController implements MapWidgetInterface {
if (isDefined(lat) && isDefined(lng)) { if (isDefined(lat) && isDefined(lng)) {
const point = lat != null && lng !== null ? L.latLng(lat, lng) : null; const point = lat != null && lng !== null ? L.latLng(lat, lng) : null;
markerValue = this.map.convertToCustomFormat(point); markerValue = this.map.convertToCustomFormat(point);
} else if (this.settings.mapProvider !== MapProviders.image) { } else if (this.settings.provider !== MapProviders.image) {
markerValue = { markerValue = {
[this.settings.latKeyName]: e[this.settings.latKeyName], [this.settings.latKeyName]: e[this.settings.latKeyName],
[this.settings.lngKeyName]: e[this.settings.lngKeyName], [this.settings.lngKeyName]: e[this.settings.lngKeyName],
@ -269,60 +274,55 @@ export class MapWidgetController implements MapWidgetInterface {
} }
} }
initSettings(settings: UnitedMapSettings, isEditMap?: boolean): UnitedMapSettings { initSettings(settings: UnitedMapSettings, isEditMap?: boolean): WidgetUnitedMapSettings {
const functionParams = ['data', 'dsData', 'dsIndex']; const functionParams = ['data', 'dsData', 'dsIndex'];
this.provider = settings.provider || this.mapProvider; this.provider = settings.provider || this.mapProvider;
if (this.provider === MapProviders.here && !settings.mapProviderHere) { const parsedOptions: Partial<WidgetUnitedMapSettings> = {
if (settings.mapProvider && hereProviders.includes(settings.mapProvider)) {
settings.mapProviderHere = settings.mapProvider;
} else {
settings.mapProviderHere = hereProviders[0];
}
}
const customOptions: Partial<UnitedMapSettings> = {
provider: this.provider, provider: this.provider,
mapUrl: settings?.mapImageUrl, parsedLabelFunction: parseFunction(settings.labelFunction, functionParams),
labelFunction: parseFunction(settings.labelFunction, functionParams), parsedTooltipFunction: parseFunction(settings.tooltipFunction, functionParams),
tooltipFunction: parseFunction(settings.tooltipFunction, functionParams), parsedColorFunction: parseFunction(settings.colorFunction, functionParams),
colorFunction: parseFunction(settings.colorFunction, functionParams), parsedColorPointFunction: parseFunction(settings.colorPointFunction, functionParams),
colorPointFunction: parseFunction(settings.colorPointFunction, functionParams), parsedStrokeOpacityFunction: parseFunction(settings.strokeOpacityFunction, functionParams),
polygonLabelFunction: parseFunction(settings.polygonLabelFunction, functionParams), parsedStrokeWeightFunction: parseFunction(settings.strokeWeightFunction, functionParams),
polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams), parsedPolygonLabelFunction: parseFunction(settings.polygonLabelFunction, functionParams),
polygonStrokeColorFunction: parseFunction(settings.polygonStrokeColorFunction, functionParams), parsedPolygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams),
polygonTooltipFunction: parseFunction(settings.polygonTooltipFunction, functionParams), parsedPolygonStrokeColorFunction: parseFunction(settings.polygonStrokeColorFunction, functionParams),
circleLabelFunction: parseFunction(settings.circleLabelFunction, functionParams), parsedPolygonTooltipFunction: parseFunction(settings.polygonTooltipFunction, functionParams),
circleStrokeColorFunction: parseFunction(settings.circleStrokeColorFunction, functionParams), parsedCircleLabelFunction: parseFunction(settings.circleLabelFunction, functionParams),
circleFillColorFunction: parseFunction(settings.circleFillColorFunction, functionParams), parsedCircleStrokeColorFunction: parseFunction(settings.circleStrokeColorFunction, functionParams),
circleTooltipFunction: parseFunction(settings.circleTooltipFunction, functionParams), parsedCircleFillColorFunction: parseFunction(settings.circleFillColorFunction, functionParams),
markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), parsedCircleTooltipFunction: parseFunction(settings.circleTooltipFunction, functionParams),
labelColor: this.ctx.widgetConfig.color, parsedMarkerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']),
polygonLabelColor: this.ctx.widgetConfig.color, // labelColor: this.ctx.widgetConfig.color,
polygonKeyName: settings.polKeyName ? settings.polKeyName : settings.polygonKeyName, // polygonLabelColor: this.ctx.widgetConfig.color,
polygonKeyName: (settings as any).polKeyName ? (settings as any).polKeyName : settings.polygonKeyName,
tooltipPattern: settings.tooltipPattern || tooltipPattern: settings.tooltipPattern ||
'<b>${entityName}</b><br/><br/><b>Latitude:</b> ${' + '<b>${entityName}</b><br/><br/><b>Latitude:</b> ${' +
settings.latKeyName + ':7}<br/><b>Longitude:</b> ${' + settings.lngKeyName + ':7}', settings.latKeyName + ':7}<br/><b>Longitude:</b> ${' + settings.lngKeyName + ':7}',
defaultCenterPosition: getDefCenterPosition(settings?.defaultCenterPosition), parsedDefaultCenterPosition: getDefCenterPosition(settings?.defaultCenterPosition),
currentImage: (settings.markerImage?.length) ? { currentImage: (settings.markerImage?.length) ? {
url: settings.markerImage, url: settings.markerImage,
size: settings.markerImageSize || 34 size: settings.markerImageSize || 34
} : null } : null
}; };
if (isEditMap && !settings.hasOwnProperty('draggableMarker')) { if (isEditMap && !settings.hasOwnProperty('draggableMarker')) {
settings.draggableMarker = true; parsedOptions.draggableMarker = true;
} }
if (isEditMap && !settings.hasOwnProperty('editablePolygon')) { if (isEditMap && !settings.hasOwnProperty('editablePolygon')) {
settings.editablePolygon = true; parsedOptions.editablePolygon = true;
} }
return { ...defaultSettings, ...settings, ...customOptions, }; parsedOptions.minZoomLevel = 16;
return { ...defaultMapSettings, ...settings, ...parsedOptions };
} }
update() { update() {
this.map.updateData(this.drawRoutes, this.settings.showPolygon); this.map.updateData(this.drawRoutes);
this.map.setLoading(false); this.map.setLoading(false);
} }
latestDataUpdate() { latestDataUpdate() {
this.map.updateData(this.drawRoutes, this.settings.showPolygon); this.map.updateData(this.drawRoutes);
} }
resize() { resize() {

12
ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts

@ -15,20 +15,22 @@
/// ///
import L from 'leaflet'; import L from 'leaflet';
import { MarkerSettings, PolygonSettings, PolylineSettings } from './map-models'; import {
ShowTooltipAction, WidgetToolipSettings
} from './map-models';
import { Datasource } from '@app/shared/models/widget.models'; import { Datasource } from '@app/shared/models/widget.models';
export function createTooltip(target: L.Layer, export function createTooltip(target: L.Layer,
settings: MarkerSettings | PolylineSettings | PolygonSettings, settings: Partial<WidgetToolipSettings>,
datasource: Datasource, datasource: Datasource,
autoClose = false, autoClose = false,
showTooltipAction = 'click', showTooltipAction = ShowTooltipAction.click,
content?: string | HTMLElement content?: string | HTMLElement
): L.Popup { ): L.Popup {
const popup = L.popup(); const popup = L.popup();
popup.setContent(content); popup.setContent(content);
target.bindPopup(popup, { autoClose, closeOnClick: false }); target.bindPopup(popup, { autoClose, closeOnClick: false });
if (showTooltipAction === 'hover') { if (showTooltipAction === ShowTooltipAction.hover) {
target.off('click'); target.off('click');
target.on('mouseover', () => { target.on('mouseover', () => {
target.openPopup(); target.openPopup();
@ -47,7 +49,7 @@ export function createTooltip(target: L.Layer,
return popup; return popup;
} }
export function bindPopupActions(popup: L.Popup, settings: MarkerSettings | PolylineSettings | PolygonSettings, export function bindPopupActions(popup: L.Popup, settings: Partial<WidgetToolipSettings>,
datasource: Datasource) { datasource: Datasource) {
const actions = popup.getElement().getElementsByClassName('tb-custom-action'); const actions = popup.getElement().getElementsByClassName('tb-custom-action');
Array.from(actions).forEach( Array.from(actions).forEach(

37
ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts

@ -18,9 +18,7 @@ import L, { LeafletMouseEvent } from 'leaflet';
import { import {
MarkerIconInfo, MarkerIconInfo,
MarkerIconReadyFunction, MarkerIconReadyFunction,
MarkerImageInfo, MarkerImageInfo, WidgetMarkersSettings,
MarkerSettings,
UnitedMapSettings
} from './map-models'; } from './map-models';
import { bindPopupActions, createTooltip } from './maps-utils'; import { bindPopupActions, createTooltip } from './maps-utils';
import { aspectCache, parseWithTranslation } from './common-maps-utils'; import { aspectCache, parseWithTranslation } from './common-maps-utils';
@ -38,15 +36,17 @@ export class Marker {
tooltipOffset: L.LatLngTuple; tooltipOffset: L.LatLngTuple;
markerOffset: L.LatLngTuple; markerOffset: L.LatLngTuple;
tooltip: L.Popup; tooltip: L.Popup;
data: FormattedData;
dataSources: FormattedData[];
constructor(private map: LeafletMap, private location: L.LatLng, public settings: UnitedMapSettings, constructor(private map: LeafletMap,
data?: FormattedData, dataSources?, onDragendListener?) { private location: L.LatLng,
this.setDataSources(data, dataSources); private settings: Partial<WidgetMarkersSettings>,
private data?: FormattedData,
private dataSources?,
private onDragendListener?,
snappable = false) {
this.leafletMarker = L.marker(location, { this.leafletMarker = L.marker(location, {
pmIgnore: !settings.draggableMarker, pmIgnore: !settings.draggableMarker,
snapIgnore: !settings.snappable snapIgnore: !snappable
}); });
this.markerOffset = [ this.markerOffset = [
@ -59,7 +59,7 @@ export class Marker {
isDefined(settings.tooltipOffsetY) ? settings.tooltipOffsetY : -1, isDefined(settings.tooltipOffsetY) ? settings.tooltipOffsetY : -1,
]; ];
this.updateMarkerIcon(settings); this.updateMarkerIcon(this.settings);
if (settings.showTooltip) { if (settings.showTooltip) {
this.tooltip = createTooltip(this.leafletMarker, settings, data.$datasource, this.tooltip = createTooltip(this.leafletMarker, settings, data.$datasource,
@ -100,7 +100,7 @@ export class Marker {
updateMarkerTooltip(data: FormattedData) { updateMarkerTooltip(data: FormattedData) {
if (!this.map.markerTooltipText || this.settings.useTooltipFunction) { if (!this.map.markerTooltipText || this.settings.useTooltipFunction) {
const pattern = this.settings.useTooltipFunction ? const pattern = this.settings.useTooltipFunction ?
safeExecute(this.settings.tooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern; safeExecute(this.settings.parsedTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : this.settings.tooltipPattern;
this.map.markerTooltipText = parseWithTranslation.prepareProcessPattern(pattern, true); this.map.markerTooltipText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoTooltipMarker = processDataPattern(this.map.markerTooltipText, data); this.map.replaceInfoTooltipMarker = processDataPattern(this.map.markerTooltipText, data);
} }
@ -117,17 +117,18 @@ export class Marker {
} }
} }
updateMarkerLabel(settings: MarkerSettings) { updateMarkerLabel(settings: Partial<WidgetMarkersSettings>) {
this.leafletMarker.unbindTooltip(); this.leafletMarker.unbindTooltip();
if (settings.showLabel) { if (settings.showLabel) {
if (!this.map.markerLabelText || settings.useLabelFunction) { if (!this.map.markerLabelText || settings.useLabelFunction) {
const pattern = settings.useLabelFunction ? const pattern = settings.useLabelFunction ?
safeExecute(settings.labelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.label; safeExecute(settings.parsedLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.label;
this.map.markerLabelText = parseWithTranslation.prepareProcessPattern(pattern, true); this.map.markerLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoLabelMarker = processDataPattern(this.map.markerLabelText, this.data); this.map.replaceInfoLabelMarker = processDataPattern(this.map.markerLabelText, this.data);
} }
settings.labelText = fillDataPattern(this.map.markerLabelText, this.map.replaceInfoLabelMarker, this.data); const labelText = fillDataPattern(this.map.markerLabelText, this.map.replaceInfoLabelMarker, this.data);
this.leafletMarker.bindTooltip(`<div style="color: ${settings.labelColor};"><b>${settings.labelText}</b></div>`, const labelColor = this.map.ctx.widgetConfig.color;
this.leafletMarker.bindTooltip(`<div style="color: ${labelColor};"><b>${labelText}</b></div>`,
{ className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.labelOffset }); { className: 'tb-marker-label', permanent: true, direction: 'top', offset: this.labelOffset });
} }
} }
@ -138,7 +139,7 @@ export class Marker {
}); });
} }
updateMarkerIcon(settings: MarkerSettings) { updateMarkerIcon(settings: Partial<WidgetMarkersSettings>) {
this.createMarkerIcon((iconInfo) => { this.createMarkerIcon((iconInfo) => {
this.leafletMarker.setIcon(iconInfo.icon); this.leafletMarker.setIcon(iconInfo.icon);
const anchor = iconInfo.icon.options.iconAnchor; const anchor = iconInfo.icon.options.iconAnchor;
@ -157,11 +158,11 @@ export class Marker {
return; return;
} }
const currentImage: MarkerImageInfo = this.settings.useMarkerImageFunction ? const currentImage: MarkerImageInfo = this.settings.useMarkerImageFunction ?
safeExecute(this.settings.markerImageFunction, safeExecute(this.settings.parsedMarkerImageFunction,
[this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage; [this.data, this.settings.markerImages, this.dataSources, this.data.dsIndex]) : this.settings.currentImage;
let currentColor = this.settings.tinyColor; let currentColor = this.settings.tinyColor;
if (this.settings.useColorFunction) { if (this.settings.useColorFunction) {
const functionColor = safeExecute(this.settings.colorFunction, const functionColor = safeExecute(this.settings.parsedColorFunction,
[this.data, this.dataSources, this.data.dsIndex]); [this.data, this.dataSources, this.data.dsIndex]);
if (isDefinedAndNotNull(functionColor)) { if (isDefinedAndNotNull(functionColor)) {
currentColor = tinycolor(functionColor); currentColor = tinycolor(functionColor);

47
ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts

@ -20,9 +20,10 @@ import {
functionValueCalculator, functionValueCalculator,
parseWithTranslation parseWithTranslation
} from './common-maps-utils'; } from './common-maps-utils';
import { PolygonSettings, UnitedMapSettings } from './map-models'; import { WidgetPolygonSettings } from './map-models';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import { fillDataPattern, processDataPattern, safeExecute } from '@core/utils'; import { fillDataPattern, processDataPattern, safeExecute } from '@core/utils';
import LeafletMap from '@home/components/widget/lib/maps/leaflet-map';
export class Polygon { export class Polygon {
@ -30,13 +31,13 @@ export class Polygon {
leafletPoly: L.Polygon; leafletPoly: L.Polygon;
tooltip: L.Popup; tooltip: L.Popup;
data: FormattedData;
dataSources: FormattedData[];
constructor(public map, data: FormattedData, dataSources: FormattedData[], private settings: UnitedMapSettings, constructor(private map: LeafletMap,
private onDragendListener?) { private data: FormattedData,
this.dataSources = dataSources; private dataSources: FormattedData[],
this.data = data; private settings: Partial<WidgetPolygonSettings>,
private onDragendListener?,
snappable = false) {
const polygonColor = this.getPolygonColor(settings); const polygonColor = this.getPolygonColor(settings);
const polygonStrokeColor = this.getPolygonStrokeColor(settings); const polygonStrokeColor = this.getPolygonStrokeColor(settings);
const polyData = data[this.settings.polygonKeyName]; const polyData = data[this.settings.polygonKeyName];
@ -49,8 +50,8 @@ export class Polygon {
fillOpacity: settings.polygonOpacity, fillOpacity: settings.polygonOpacity,
opacity: settings.polygonStrokeOpacity, opacity: settings.polygonStrokeOpacity,
pmIgnore: !settings.editablePolygon, pmIgnore: !settings.editablePolygon,
snapIgnore: !settings.snappable snapIgnore: !snappable
}).addTo(this.map); }).addTo(this.map.map);
if (settings.showPolygonLabel) { if (settings.showPolygonLabel) {
this.updateLabel(settings); this.updateLabel(settings);
@ -91,28 +92,30 @@ export class Polygon {
updateTooltip(data: FormattedData) { updateTooltip(data: FormattedData) {
const pattern = this.settings.usePolygonTooltipFunction ? const pattern = this.settings.usePolygonTooltipFunction ?
safeExecute(this.settings.polygonTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) : safeExecute(this.settings.parsedPolygonTooltipFunction, [this.data, this.dataSources, this.data.dsIndex]) :
this.settings.polygonTooltipPattern; this.settings.polygonTooltipPattern;
this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true)); this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true));
} }
updateLabel(settings: PolygonSettings) { updateLabel(settings: Partial<WidgetPolygonSettings>) {
this.leafletPoly.unbindTooltip(); this.leafletPoly.unbindTooltip();
if (settings.showPolygonLabel) { if (settings.showPolygonLabel) {
if (!this.map.polygonLabelText || settings.usePolygonLabelFunction) { if (!this.map.polygonLabelText || settings.usePolygonLabelFunction) {
const pattern = settings.usePolygonLabelFunction ? const pattern = settings.usePolygonLabelFunction ?
safeExecute(settings.polygonLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.polygonLabel; safeExecute(settings.parsedPolygonLabelFunction,
[this.data, this.dataSources, this.data.dsIndex]) : settings.polygonLabel;
this.map.polygonLabelText = parseWithTranslation.prepareProcessPattern(pattern, true); this.map.polygonLabelText = parseWithTranslation.prepareProcessPattern(pattern, true);
this.map.replaceInfoLabelPolygon = processDataPattern(this.map.polygonLabelText, this.data); this.map.replaceInfoLabelPolygon = processDataPattern(this.map.polygonLabelText, this.data);
} }
const polygonLabelText = fillDataPattern(this.map.polygonLabelText, this.map.replaceInfoLabelPolygon, this.data); const polygonLabelText = fillDataPattern(this.map.polygonLabelText, this.map.replaceInfoLabelPolygon, this.data);
this.leafletPoly.bindTooltip(`<div style="color: ${settings.polygonLabelColor};"><b>${polygonLabelText}</b></div>`, const labelColor = this.map.ctx.widgetConfig.color;
this.leafletPoly.bindTooltip(`<div style="color: ${labelColor};"><b>${polygonLabelText}</b></div>`,
{ className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center' }) { className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center' })
.openTooltip(this.leafletPoly.getBounds().getCenter()); .openTooltip(this.leafletPoly.getBounds().getCenter());
} }
} }
updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetPolygonSettings>) {
if (this.editing) { if (this.editing) {
return; return;
} }
@ -121,7 +124,7 @@ export class Polygon {
const polyData = data[this.settings.polygonKeyName]; const polyData = data[this.settings.polygonKeyName];
if (isCutPolygon(polyData) || polyData.length !== 2) { if (isCutPolygon(polyData) || polyData.length !== 2) {
if (this.leafletPoly instanceof L.Rectangle) { if (this.leafletPoly instanceof L.Rectangle) {
this.map.removeLayer(this.leafletPoly); this.map.map.removeLayer(this.leafletPoly);
const polygonColor = this.getPolygonColor(settings); const polygonColor = this.getPolygonColor(settings);
const polygonStrokeColor = this.getPolygonStrokeColor(settings); const polygonStrokeColor = this.getPolygonStrokeColor(settings);
this.leafletPoly = L.polygon(polyData, { this.leafletPoly = L.polygon(polyData, {
@ -132,7 +135,7 @@ export class Polygon {
fillOpacity: settings.polygonOpacity, fillOpacity: settings.polygonOpacity,
opacity: settings.polygonStrokeOpacity, opacity: settings.polygonStrokeOpacity,
pmIgnore: !settings.editablePolygon pmIgnore: !settings.editablePolygon
}).addTo(this.map); }).addTo(this.map.map);
if (settings.showPolygonTooltip) { if (settings.showPolygonTooltip) {
this.tooltip = createTooltip(this.leafletPoly, settings, data.$datasource, this.tooltip = createTooltip(this.leafletPoly, settings, data.$datasource,
settings.autoClosePolygonTooltip, settings.showPolygonTooltipAction); settings.autoClosePolygonTooltip, settings.showPolygonTooltipAction);
@ -156,10 +159,10 @@ export class Polygon {
} }
removePolygon() { removePolygon() {
this.map.removeLayer(this.leafletPoly); this.map.map.removeLayer(this.leafletPoly);
} }
updatePolygonColor(settings: PolygonSettings) { updatePolygonColor(settings: Partial<WidgetPolygonSettings>) {
const polygonColor = this.getPolygonColor(settings); const polygonColor = this.getPolygonColor(settings);
const polygonStrokeColor = this.getPolygonStrokeColor(settings); const polygonStrokeColor = this.getPolygonStrokeColor(settings);
const style: L.PathOptions = { const style: L.PathOptions = {
@ -178,13 +181,13 @@ export class Polygon {
this.leafletPoly.redraw(); this.leafletPoly.redraw();
} }
private getPolygonColor(settings: PolygonSettings): string | null { private getPolygonColor(settings: Partial<WidgetPolygonSettings>): string | null {
return functionValueCalculator(settings.usePolygonColorFunction, settings.polygonColorFunction, return functionValueCalculator(settings.usePolygonColorFunction, settings.parsedPolygonColorFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.polygonColor); [this.data, this.dataSources, this.data.dsIndex], settings.polygonColor);
} }
private getPolygonStrokeColor(settings: PolygonSettings): string | null { private getPolygonStrokeColor(settings: Partial<WidgetPolygonSettings>): string | null {
return functionValueCalculator(settings.usePolygonStrokeColorFunction, settings.polygonStrokeColorFunction, return functionValueCalculator(settings.usePolygonStrokeColorFunction, settings.parsedPolygonStrokeColorFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.polygonStrokeColor); [this.data, this.dataSources, this.data.dsIndex], settings.polygonStrokeColor);
} }
} }

24
ui-ngx/src/app/modules/home/components/widget/lib/maps/polyline.ts

@ -18,7 +18,7 @@
import L, { PolylineDecorator, PolylineDecoratorOptions, Symbol } from 'leaflet'; import L, { PolylineDecorator, PolylineDecoratorOptions, Symbol } from 'leaflet';
import 'leaflet-polylinedecorator'; import 'leaflet-polylinedecorator';
import { PolylineSettings } from './map-models'; import { WidgetPolylineSettings } from './map-models';
import { functionValueCalculator } from '@home/components/widget/lib/maps/common-maps-utils'; import { functionValueCalculator } from '@home/components/widget/lib/maps/common-maps-utils';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
@ -26,12 +26,12 @@ export class Polyline {
leafletPoly: L.Polyline; leafletPoly: L.Polyline;
polylineDecorator: PolylineDecorator; polylineDecorator: PolylineDecorator;
dataSources: FormattedData[];
data: FormattedData;
constructor(private map: L.Map, locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { constructor(private map: L.Map,
this.dataSources = dataSources; locations: L.LatLng[],
this.data = data; private data: FormattedData,
private dataSources: FormattedData[],
settings: Partial<WidgetPolylineSettings>) {
this.leafletPoly = L.polyline(locations, this.leafletPoly = L.polyline(locations,
this.getPolyStyle(settings) this.getPolyStyle(settings)
@ -42,7 +42,7 @@ export class Polyline {
} }
} }
getDecoratorSettings(settings: PolylineSettings): PolylineDecoratorOptions { getDecoratorSettings(settings: Partial<WidgetPolylineSettings>): PolylineDecoratorOptions {
return { return {
patterns: [ patterns: [
{ {
@ -62,7 +62,7 @@ export class Polyline {
}; };
} }
updatePolyline(locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: PolylineSettings) { updatePolyline(locations: L.LatLng[], data: FormattedData, dataSources: FormattedData[], settings: Partial<WidgetPolylineSettings>) {
this.data = data; this.data = data;
this.dataSources = dataSources; this.dataSources = dataSources;
this.leafletPoly.setLatLngs(locations); this.leafletPoly.setLatLngs(locations);
@ -72,14 +72,14 @@ export class Polyline {
} }
} }
getPolyStyle(settings: PolylineSettings): L.PolylineOptions { getPolyStyle(settings: Partial<WidgetPolylineSettings>): L.PolylineOptions {
return { return {
interactive: false, interactive: false,
color: functionValueCalculator(settings.useColorFunction, settings.colorFunction, color: functionValueCalculator(settings.useColorFunction, settings.parsedColorFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.color), [this.data, this.dataSources, this.data.dsIndex], settings.color),
opacity: functionValueCalculator(settings.useStrokeOpacityFunction, settings.strokeOpacityFunction, opacity: functionValueCalculator(settings.useStrokeOpacityFunction, settings.parsedStrokeOpacityFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.strokeOpacity), [this.data, this.dataSources, this.data.dsIndex], settings.strokeOpacity),
weight: functionValueCalculator(settings.useStrokeWeightFunction, settings.strokeWeightFunction, weight: functionValueCalculator(settings.useStrokeWeightFunction, settings.parsedStrokeWeightFunction,
[this.data, this.dataSources, this.data.dsIndex], settings.strokeWeight), [this.data, this.dataSources, this.data.dsIndex], settings.strokeWeight),
pmIgnore: true pmIgnore: true
}; };

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/google-map.ts

@ -17,7 +17,7 @@
import L from 'leaflet'; import L from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models'; import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import 'leaflet.gridlayer.googlemutant'; import 'leaflet.gridlayer.googlemutant';
import { ResourcesService } from '@core/services/resources.service'; import { ResourcesService } from '@core/services/resources.service';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
@ -31,16 +31,15 @@ interface GmGlobal {
export class GoogleMap extends LeafletMap { export class GoogleMap extends LeafletMap {
private resource: ResourcesService; private resource: ResourcesService;
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
this.resource = ctx.$injector.get(ResourcesService); this.resource = ctx.$injector.get(ResourcesService);
super.initSettings(options);
this.loadGoogle(() => { this.loadGoogle(() => {
const map = L.map($container, { const map = L.map($container, {
attributionControl: false, attributionControl: false,
zoomControl: !this.options.disableZoomControl, zoomControl: !this.options.disableZoomControl,
tap: L.Browser.safari && L.Browser.mobile tap: L.Browser.safari && L.Browser.mobile
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL); }).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
(L.gridLayer as any).googleMutant({ (L.gridLayer as any).googleMutant({
type: options?.gmDefaultMapType || 'roadmap' type: options?.gmDefaultMapType || 'roadmap'
}).addTo(map); }).addTo(map);

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/here-map.ts

@ -16,19 +16,18 @@
import L from 'leaflet'; import L from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models'; import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
export class HEREMap extends LeafletMap { export class HEREMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const map = L.map($container, { const map = L.map($container, {
tap: L.Browser.safari && L.Browser.mobile, tap: L.Browser.safari && L.Browser.mobile,
zoomControl: !this.options.disableZoomControl zoomControl: !this.options.disableZoomControl
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL); }).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials); const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
tileLayer.addTo(map); tileLayer.addTo(map);
super.initSettings(options);
super.setMap(map); super.setMap(map);
} }
} }

11
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts

@ -16,7 +16,7 @@
import L, { LatLngBounds, LatLngLiteral, LatLngTuple } from 'leaflet'; import L, { LatLngBounds, LatLngLiteral, LatLngTuple } from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { CircleData, MapImage, PosFuncton, UnitedMapSettings } from '../map-models'; import { CircleData, MapImage, PosFuncton, WidgetUnitedMapSettings } from '../map-models';
import { Observable, ReplaySubject } from 'rxjs'; import { Observable, ReplaySubject } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators'; import { map, mergeMap } from 'rxjs/operators';
import { import {
@ -41,7 +41,7 @@ export class ImageMap extends LeafletMap {
imageUrl: string; imageUrl: string;
posFunction: PosFuncton; posFunction: PosFuncton;
constructor(ctx: WidgetContext, $container: HTMLElement, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container: HTMLElement, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
this.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as PosFuncton; this.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as PosFuncton;
this.mapImage(options).subscribe((mapImage) => { this.mapImage(options).subscribe((mapImage) => {
@ -51,21 +51,20 @@ export class ImageMap extends LeafletMap {
this.onResize(true); this.onResize(true);
} else { } else {
this.onResize(); this.onResize();
super.initSettings(options);
super.setMap(this.map); super.setMap(this.map);
} }
}); });
} }
private mapImage(options: UnitedMapSettings): Observable<MapImage> { private mapImage(options: WidgetUnitedMapSettings): Observable<MapImage> {
const imageEntityAlias = options.imageEntityAlias; const imageEntityAlias = options.imageEntityAlias;
const imageUrlAttribute = options.imageUrlAttribute; const imageUrlAttribute = options.imageUrlAttribute;
if (!imageEntityAlias || !imageUrlAttribute) { if (!imageEntityAlias || !imageUrlAttribute) {
return this.imageFromUrl(options.mapUrl); return this.imageFromUrl(options.mapImageUrl);
} }
const entityAliasId = this.ctx.aliasController.getEntityAliasId(imageEntityAlias); const entityAliasId = this.ctx.aliasController.getEntityAliasId(imageEntityAlias);
if (!entityAliasId) { if (!entityAliasId) {
return this.imageFromUrl(options.mapUrl); return this.imageFromUrl(options.mapImageUrl);
} }
const datasources = [ const datasources = [
{ {

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/openstreet-map.ts

@ -16,16 +16,16 @@
import L from 'leaflet'; import L from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models'; import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
export class OpenStreetMap extends LeafletMap { export class OpenStreetMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const map = L.map($container, { const map = L.map($container, {
zoomControl: !this.options.disableZoomControl, zoomControl: !this.options.disableZoomControl,
tap: L.Browser.safari && L.Browser.mobile tap: L.Browser.safari && L.Browser.mobile
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL); }).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
let tileLayer; let tileLayer;
if (options.useCustomProvider) { if (options.useCustomProvider) {
tileLayer = L.tileLayer(options.customProviderTileUrl); tileLayer = L.tileLayer(options.customProviderTileUrl);
@ -33,7 +33,6 @@ export class OpenStreetMap extends LeafletMap {
tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik'); tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
} }
tileLayer.addTo(map); tileLayer.addTo(map);
super.initSettings(options);
super.setMap(map); super.setMap(map);
} }
} }

7
ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/tencent-map.ts

@ -17,24 +17,23 @@
import L from 'leaflet'; import L from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { DEFAULT_ZOOM_LEVEL, UnitedMapSettings } from '../map-models'; import { DEFAULT_ZOOM_LEVEL, WidgetUnitedMapSettings } from '../map-models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
export class TencentMap extends LeafletMap { export class TencentMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: WidgetUnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0';
const map = L.map($container, { const map = L.map($container, {
zoomControl: !this.options.disableZoomControl, zoomControl: !this.options.disableZoomControl,
tap: L.Browser.safari && L.Browser.mobile tap: L.Browser.safari && L.Browser.mobile
}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL); }).setView(options?.parsedDefaultCenterPosition, options?.defaultZoomLevel || DEFAULT_ZOOM_LEVEL);
const txLayer = L.tileLayer(txUrl, { const txLayer = L.tileLayer(txUrl, {
subdomains: '0123', subdomains: '0123',
tms: true, tms: true,
attribution: '&copy;2021 Tencent - GS(2020)2236号- Data&copy; NavInfo' attribution: '&copy;2021 Tencent - GS(2020)2236号- Data&copy; NavInfo'
}).addTo(map); }).addTo(map);
txLayer.addTo(map); txLayer.addTo(map);
super.initSettings(options);
super.setMap(map); super.setMap(map);
} }
} }

95
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.html

@ -0,0 +1,95 @@
<!--
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]="alarmsTableKeySettingsForm" fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.column-width</mat-label>
<input matInput formControlName="columnWidth">
</mat-form-field>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="alarmsTableKeySettingsForm.get('useCellStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-style-function' | 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-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'alarm', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
helpId="widget/lib/alarm/cell_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-content</legend>
<mat-expansion-panel class="tb-settings" [expanded]="alarmsTableKeySettingsForm.get('useCellContentFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-content-function' | 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-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'alarm', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"
helpId="widget/lib/alarm/cell_content_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-column-visibility</mat-label>
<mat-select formControlName="defaultColumnVisibility">
<mat-option [value]="'visible'">
{{ 'widgets.table.column-visibility-visible' | translate }}
</mat-option>
<mat-option [value]="'hidden'">
{{ 'widgets.table.column-visibility-hidden' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.column-selection-to-display</mat-label>
<mat-select formControlName="columnSelectionToDisplay">
<mat-option [value]="'enabled'">
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
</mat-option>
<mat-option [value]="'disabled'">
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>

86
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-key-settings.component.ts

@ -0,0 +1,86 @@
///
/// 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';
@Component({
selector: 'tb-alarms-table-key-settings',
templateUrl: './alarms-table-key-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class AlarmsTableKeySettingsComponent extends WidgetSettingsComponent {
alarmsTableKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.alarmsTableKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
columnWidth: '0px',
useCellStyleFunction: false,
cellStyleFunction: '',
useCellContentFunction: false,
cellContentFunction: '',
defaultColumnVisibility: 'visible',
columnSelectionToDisplay: 'enabled'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.alarmsTableKeySettingsForm = this.fb.group({
columnWidth: [settings.columnWidth, []],
useCellStyleFunction: [settings.useCellStyleFunction, []],
cellStyleFunction: [settings.cellStyleFunction, [Validators.required]],
useCellContentFunction: [settings.useCellContentFunction, []],
cellContentFunction: [settings.cellContentFunction, [Validators.required]],
defaultColumnVisibility: [settings.defaultColumnVisibility, []],
columnSelectionToDisplay: [settings.columnSelectionToDisplay, []],
});
}
protected validatorTriggers(): string[] {
return ['useCellStyleFunction', 'useCellContentFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useCellStyleFunction: boolean = this.alarmsTableKeySettingsForm.get('useCellStyleFunction').value;
const useCellContentFunction: boolean = this.alarmsTableKeySettingsForm.get('useCellContentFunction').value;
if (useCellStyleFunction) {
this.alarmsTableKeySettingsForm.get('cellStyleFunction').enable();
} else {
this.alarmsTableKeySettingsForm.get('cellStyleFunction').disable();
}
if (useCellContentFunction) {
this.alarmsTableKeySettingsForm.get('cellContentFunction').enable();
} else {
this.alarmsTableKeySettingsForm.get('cellContentFunction').disable();
}
this.alarmsTableKeySettingsForm.get('cellStyleFunction').updateValueAndValidity({emitEvent});
this.alarmsTableKeySettingsForm.get('cellContentFunction').updateValueAndValidity({emitEvent});
}
}

110
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.html

@ -0,0 +1,110 @@
<!--
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]="alarmsTableWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.table.common-table-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.alarms-table-title</mat-label>
<input matInput formControlName="alarmsTitle">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableSelection" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-alarms-selection' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableSearch" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-alarms-search' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableSelectColumnDisplay" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-select-column-display' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableFilter" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-alarm-filter' | translate }}
</mat-checkbox>
</section>
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableStickyHeader" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-header' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableStickyAction" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-action' | translate }}
</mat-checkbox>
</section>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.hidden-cell-button-display-mode</mat-label>
<mat-select formControlName="reserveSpaceForHiddenAction">
<mat-option [value]="'true'">
{{ 'widgets.table.show-empty-space-hidden-action' | translate }}
</mat-option>
<mat-option [value]="'false'">
{{ 'widgets.table.dont-reserve-space-hidden-action' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<section fxLayout="column" fxLayoutGap="8px">
<mat-slide-toggle fxFlex formControlName="displayDetails">
{{ 'widgets.table.display-alarm-details' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="allowAcknowledgment">
{{ 'widgets.table.allow-alarms-ack' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="allowClear">
{{ 'widgets.table.allow-alarms-clear' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayPagination">
{{ 'widgets.table.display-pagination' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-page-size</mat-label>
<input matInput type="number" min="1" step="1" formControlName="defaultPageSize">
</mat-form-field>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-sort-order</mat-label>
<input matInput formControlName="defaultSortOrder">
</mat-form-field>
</section>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.row-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="alarmsTableWidgetSettingsForm.get('useRowStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useRowStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-row-style-function' | 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-js-func required
formControlName="rowStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['alarm', 'ctx']"
functionTitle="{{ 'widgets.table.row-style-function' | translate }}"
helpId="widget/lib/alarm/row_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

104
ui-ngx/src/app/modules/home/components/widget/lib/settings/alarm/alarms-table-widget-settings.component.ts

@ -0,0 +1,104 @@
///
/// 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';
@Component({
selector: 'tb-alarms-table-widget-settings',
templateUrl: './alarms-table-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class AlarmsTableWidgetSettingsComponent extends WidgetSettingsComponent {
alarmsTableWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.alarmsTableWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
alarmsTitle: '',
enableSelection: true,
enableSearch: true,
enableSelectColumnDisplay: true,
enableFilter: true,
enableStickyHeader: true,
enableStickyAction: true,
reserveSpaceForHiddenAction: 'true',
displayDetails: true,
allowAcknowledgment: true,
allowClear: true,
displayPagination: true,
defaultPageSize: 10,
defaultSortOrder: '-createdTime',
useRowStyleFunction: false,
rowStyleFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.alarmsTableWidgetSettingsForm = this.fb.group({
alarmsTitle: [settings.alarmsTitle, []],
enableSelection: [settings.enableSelection, []],
enableSearch: [settings.enableSearch, []],
enableSelectColumnDisplay: [settings.enableSelectColumnDisplay, []],
enableFilter: [settings.enableFilter, []],
enableStickyHeader: [settings.enableStickyHeader, []],
enableStickyAction: [settings.enableStickyAction, []],
reserveSpaceForHiddenAction: [settings.reserveSpaceForHiddenAction, []],
displayDetails: [settings.displayDetails, []],
allowAcknowledgment: [settings.allowAcknowledgment, []],
allowClear: [settings.allowClear, []],
displayPagination: [settings.displayPagination, []],
defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]],
defaultSortOrder: [settings.defaultSortOrder, []],
useRowStyleFunction: [settings.useRowStyleFunction, []],
rowStyleFunction: [settings.rowStyleFunction, [Validators.required]]
});
}
protected validatorTriggers(): string[] {
return ['useRowStyleFunction', 'displayPagination'];
}
protected updateValidators(emitEvent: boolean) {
const useRowStyleFunction: boolean = this.alarmsTableWidgetSettingsForm.get('useRowStyleFunction').value;
const displayPagination: boolean = this.alarmsTableWidgetSettingsForm.get('displayPagination').value;
if (useRowStyleFunction) {
this.alarmsTableWidgetSettingsForm.get('rowStyleFunction').enable();
} else {
this.alarmsTableWidgetSettingsForm.get('rowStyleFunction').disable();
}
if (displayPagination) {
this.alarmsTableWidgetSettingsForm.get('defaultPageSize').enable();
} else {
this.alarmsTableWidgetSettingsForm.get('defaultPageSize').disable();
}
this.alarmsTableWidgetSettingsForm.get('rowStyleFunction').updateValueAndValidity({emitEvent});
this.alarmsTableWidgetSettingsForm.get('defaultPageSize').updateValueAndValidity({emitEvent});
}
}

65
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.html

@ -0,0 +1,65 @@
<!--
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]="dashboardStateWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.dashboard-state.dashboard-state-settings</legend>
<mat-form-field class="mat-block">
<input matInput type="text" placeholder="{{ 'widgets.dashboard-state.dashboard-state' | translate }}"
#dashboardStateInput
formControlName="stateId"
[matAutocomplete]="dashboardStateAutocomplete">
<button *ngIf="dashboardStateWidgetSettingsForm.get('stateId').value"
type="button"
matSuffix mat-icon-button aria-label="Clear"
(click)="clearDashboardState()">
<mat-icon class="material-icons">close</mat-icon>
</button>
<mat-autocomplete
class="tb-autocomplete"
#dashboardStateAutocomplete="matAutocomplete">
<mat-option *ngFor="let state of filteredDashboardStates | async" [value]="state">
<span [innerHTML]="state | highlight:dashboardStateSearchText"></span>
</mat-option>
</mat-autocomplete>
</mat-form-field>
<mat-expansion-panel class="tb-settings">
<mat-expansion-panel-header>
<mat-panel-description fxLayoutAlign="end" translate>
widget-config.advanced-settings
</mat-panel-description>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<mat-slide-toggle class="mat-slide" formControlName="defaultAutofillLayout">
{{ 'widgets.dashboard-state.autofill-state-layout' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.dashboard-state.default-margin</mat-label>
<input matInput type="number" min="0" step="1" formControlName="defaultMargin">
</mat-form-field>
<tb-color-input
formControlName="defaultBackgroundColor"
icon="format_color_fill"
label="{{ 'widgets.dashboard-state.default-background-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<mat-slide-toggle class="mat-slide" formControlName="syncParentStateParams">
{{ 'widgets.dashboard-state.sync-parent-state-params' | translate }}
</mat-slide-toggle>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

99
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/dashboard-state-widget-settings.component.ts

@ -0,0 +1,99 @@
///
/// 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, ElementRef, ViewChild } from '@angular/core';
import { WidgetActionType, 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 { Observable, of } from 'rxjs';
import { map, mergeMap, startWith } from 'rxjs/operators';
@Component({
selector: 'tb-dashboard-state-widget-settings',
templateUrl: './dashboard-state-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class DashboardStateWidgetSettingsComponent extends WidgetSettingsComponent {
@ViewChild('dashboardStateInput') dashboardStateInput: ElementRef;
dashboardStateWidgetSettingsForm: FormGroup;
filteredDashboardStates: Observable<Array<string>>;
dashboardStateSearchText = '';
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.dashboardStateWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
stateId: '',
defaultAutofillLayout: true,
defaultMargin: 0,
defaultBackgroundColor: '#fff',
syncParentStateParams: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.dashboardStateWidgetSettingsForm = this.fb.group({
stateId: [settings.stateId, []],
defaultAutofillLayout: [settings.defaultAutofillLayout, []],
defaultMargin: [settings.defaultMargin, [Validators.min(0)]],
defaultBackgroundColor: [settings.defaultBackgroundColor, []],
syncParentStateParams: [settings.syncParentStateParams, []]
});
this.dashboardStateSearchText = '';
this.filteredDashboardStates = this.dashboardStateWidgetSettingsForm.get('stateId').valueChanges
.pipe(
startWith(''),
map(value => value ? value : ''),
mergeMap(name => this.fetchDashboardStates(name) )
);
}
public clearDashboardState(value: string = '') {
this.dashboardStateInput.nativeElement.value = value;
this.dashboardStateWidgetSettingsForm.get('stateId').patchValue(value, {emitEvent: true});
setTimeout(() => {
this.dashboardStateInput.nativeElement.blur();
this.dashboardStateInput.nativeElement.focus();
}, 0);
}
private fetchDashboardStates(searchText?: string): Observable<Array<string>> {
this.dashboardStateSearchText = searchText;
const stateIds = Object.keys(this.dashboard.configuration.states);
const result = searchText ? stateIds.filter(this.createFilterForDashboardState(searchText)) : stateIds;
if (result && result.length) {
return of(result);
} else {
return of([searchText]);
}
}
private createFilterForDashboardState(query: string): (stateId: string) => boolean {
const lowercaseQuery = query.toLowerCase();
return stateId => stateId.toLowerCase().indexOf(lowercaseQuery) === 0;
}
}

22
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.html

@ -0,0 +1,22 @@
<!--
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]="edgeQuickOverviewWidgetSettingsForm" fxLayout="column">
<mat-slide-toggle class="mat-slide" formControlName="enableDefaultTitle">
{{ 'widgets.edge.display-default-title' | translate }}
</mat-slide-toggle>
</section>

52
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/edge-quick-overview-widget-settings.component.ts

@ -0,0 +1,52 @@
///
/// 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 } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-edge-quick-overview-widget-settings',
templateUrl: './edge-quick-overview-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class EdgeQuickOverviewWidgetSettingsComponent extends WidgetSettingsComponent {
edgeQuickOverviewWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.edgeQuickOverviewWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
enableDefaultTitle: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.edgeQuickOverviewWidgetSettingsForm = this.fb.group({
enableDefaultTitle: [settings.enableDefaultTitle, []]
});
}
}

74
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html

@ -0,0 +1,74 @@
<!--
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]="entitiesHierarchyWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.entities-hierarchy.hierarchy-data-settings</legend>
<tb-js-func formControlName="nodeRelationQueryFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.relations-query-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_relation_query_fn">
</tb-js-func>
<tb-js-func formControlName="nodeHasChildrenFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.has-children-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_has_children_fn">
</tb-js-func>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.entities-hierarchy.node-state-settings</legend>
<tb-js-func formControlName="nodeOpenedFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.node-opened-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_opened_fn">
</tb-js-func>
<tb-js-func formControlName="nodeDisabledFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.node-disabled-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_disabled_fn">
</tb-js-func>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.entities-hierarchy.display-settings</legend>
<tb-js-func formControlName="nodeIconFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.node-icon-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_icon_fn">
</tb-js-func>
<tb-js-func formControlName="nodeTextFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx']"
functionTitle="{{ 'widgets.entities-hierarchy.node-text-function' | translate }}"
helpId="widget/lib/entities_hierarchy/node_text_fn">
</tb-js-func>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.entities-hierarchy.sort-settings</legend>
<tb-js-func formControlName="nodesSortFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['nodeCtx1', 'nodeCtx2']"
functionTitle="{{ 'widgets.entities-hierarchy.nodes-sort-function' | translate }}"
helpId="widget/lib/entities_hierarchy/nodes_sort_fn">
</tb-js-func>
</fieldset>
</section>

64
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.ts

@ -0,0 +1,64 @@
///
/// 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 } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
@Component({
selector: 'tb-entities-hierarchy-widget-settings',
templateUrl: './entities-hierarchy-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class EntitiesHierarchyWidgetSettingsComponent extends WidgetSettingsComponent {
entitiesHierarchyWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.entitiesHierarchyWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
nodeRelationQueryFunction: '',
nodeHasChildrenFunction: '',
nodeOpenedFunction: '',
nodeDisabledFunction: '',
nodeIconFunction: '',
nodeTextFunction: '',
nodesSortFunction: '',
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.entitiesHierarchyWidgetSettingsForm = this.fb.group({
nodeRelationQueryFunction: [settings.nodeRelationQueryFunction, []],
nodeHasChildrenFunction: [settings.nodeHasChildrenFunction, []],
nodeOpenedFunction: [settings.nodeOpenedFunction, []],
nodeDisabledFunction: [settings.nodeDisabledFunction, []],
nodeIconFunction: [settings.nodeIconFunction, []],
nodeTextFunction: [settings.nodeTextFunction, []],
nodesSortFunction: [settings.nodesSortFunction, []]
});
}
}

95
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.html

@ -0,0 +1,95 @@
<!--
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]="entitiesTableKeySettingsForm" fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.column-width</mat-label>
<input matInput formControlName="columnWidth">
</mat-form-field>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="entitiesTableKeySettingsForm.get('useCellStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-style-function' | 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-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'entity', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
helpId="widget/lib/entity/cell_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-content</legend>
<mat-expansion-panel class="tb-settings" [expanded]="entitiesTableKeySettingsForm.get('useCellContentFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-content-function' | 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-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'entity', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"
helpId="widget/lib/entity/cell_content_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-column-visibility</mat-label>
<mat-select formControlName="defaultColumnVisibility">
<mat-option [value]="'visible'">
{{ 'widgets.table.column-visibility-visible' | translate }}
</mat-option>
<mat-option [value]="'hidden'">
{{ 'widgets.table.column-visibility-hidden' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.column-selection-to-display</mat-label>
<mat-select formControlName="columnSelectionToDisplay">
<mat-option [value]="'enabled'">
{{ 'widgets.table.column-selection-to-display-enabled' | translate }}
</mat-option>
<mat-option [value]="'disabled'">
{{ 'widgets.table.column-selection-to-display-disabled' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>

86
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-key-settings.component.ts

@ -0,0 +1,86 @@
///
/// 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';
@Component({
selector: 'tb-entities-table-key-settings',
templateUrl: './entities-table-key-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class EntitiesTableKeySettingsComponent extends WidgetSettingsComponent {
entitiesTableKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.entitiesTableKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
columnWidth: '0px',
useCellStyleFunction: false,
cellStyleFunction: '',
useCellContentFunction: false,
cellContentFunction: '',
defaultColumnVisibility: 'visible',
columnSelectionToDisplay: 'enabled'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.entitiesTableKeySettingsForm = this.fb.group({
columnWidth: [settings.columnWidth, []],
useCellStyleFunction: [settings.useCellStyleFunction, []],
cellStyleFunction: [settings.cellStyleFunction, [Validators.required]],
useCellContentFunction: [settings.useCellContentFunction, []],
cellContentFunction: [settings.cellContentFunction, [Validators.required]],
defaultColumnVisibility: [settings.defaultColumnVisibility, []],
columnSelectionToDisplay: [settings.columnSelectionToDisplay, []],
});
}
protected validatorTriggers(): string[] {
return ['useCellStyleFunction', 'useCellContentFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useCellStyleFunction: boolean = this.entitiesTableKeySettingsForm.get('useCellStyleFunction').value;
const useCellContentFunction: boolean = this.entitiesTableKeySettingsForm.get('useCellContentFunction').value;
if (useCellStyleFunction) {
this.entitiesTableKeySettingsForm.get('cellStyleFunction').enable();
} else {
this.entitiesTableKeySettingsForm.get('cellStyleFunction').disable();
}
if (useCellContentFunction) {
this.entitiesTableKeySettingsForm.get('cellContentFunction').enable();
} else {
this.entitiesTableKeySettingsForm.get('cellContentFunction').disable();
}
this.entitiesTableKeySettingsForm.get('cellStyleFunction').updateValueAndValidity({emitEvent});
this.entitiesTableKeySettingsForm.get('cellContentFunction').updateValueAndValidity({emitEvent});
}
}

116
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.html

@ -0,0 +1,116 @@
<!--
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]="entitiesTableWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.table.common-table-settings</legend>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entities-table-title</mat-label>
<input matInput formControlName="entitiesTitle">
</mat-form-field>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableSearch" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-search' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableSelectColumnDisplay" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-select-column-display' | translate }}
</mat-checkbox>
</section>
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableStickyHeader" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-header' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableStickyAction" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-action' | translate }}
</mat-checkbox>
</section>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.hidden-cell-button-display-mode</mat-label>
<mat-select formControlName="reserveSpaceForHiddenAction">
<mat-option [value]="'true'">
{{ 'widgets.table.show-empty-space-hidden-action' | translate }}
</mat-option>
<mat-option [value]="'false'">
{{ 'widgets.table.dont-reserve-space-hidden-action' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<section fxLayout="column" fxLayoutGap="8px">
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayEntityName">
{{ 'widgets.table.display-entity-name' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entity-name-column-title</mat-label>
<input matInput formControlName="entityNameColumnTitle">
</mat-form-field>
</section>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayEntityLabel">
{{ 'widgets.table.display-entity-label' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.entity-label-column-title</mat-label>
<input matInput formControlName="entityLabelColumnTitle">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="displayEntityType">
{{ 'widgets.table.display-entity-type' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayPagination">
{{ 'widgets.table.display-pagination' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-page-size</mat-label>
<input matInput type="number" min="1" step="1" formControlName="defaultPageSize">
</mat-form-field>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-sort-order</mat-label>
<input matInput formControlName="defaultSortOrder">
</mat-form-field>
</section>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.row-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="entitiesTableWidgetSettingsForm.get('useRowStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useRowStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-row-style-function' | 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-js-func required
formControlName="rowStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['entity', 'ctx']"
functionTitle="{{ 'widgets.table.row-style-function' | translate }}"
helpId="widget/lib/entity/row_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

118
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-table-widget-settings.component.ts

@ -0,0 +1,118 @@
///
/// 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';
@Component({
selector: 'tb-entities-table-widget-settings',
templateUrl: './entities-table-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class EntitiesTableWidgetSettingsComponent extends WidgetSettingsComponent {
entitiesTableWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.entitiesTableWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
entitiesTitle: '',
enableSearch: true,
enableSelectColumnDisplay: true,
enableStickyHeader: true,
enableStickyAction: true,
reserveSpaceForHiddenAction: 'true',
displayEntityName: true,
entityNameColumnTitle: '',
displayEntityLabel: false,
entityLabelColumnTitle: '',
displayEntityType: true,
displayPagination: true,
defaultPageSize: 10,
defaultSortOrder: 'entityName',
useRowStyleFunction: false,
rowStyleFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.entitiesTableWidgetSettingsForm = this.fb.group({
entitiesTitle: [settings.entitiesTitle, []],
enableSearch: [settings.enableSearch, []],
enableSelectColumnDisplay: [settings.enableSelectColumnDisplay, []],
enableStickyHeader: [settings.enableStickyHeader, []],
enableStickyAction: [settings.enableStickyAction, []],
reserveSpaceForHiddenAction: [settings.reserveSpaceForHiddenAction, []],
displayEntityName: [settings.displayEntityName, []],
entityNameColumnTitle: [settings.entityNameColumnTitle, []],
displayEntityLabel: [settings.displayEntityLabel, []],
entityLabelColumnTitle: [settings.entityLabelColumnTitle, []],
displayEntityType: [settings.displayEntityType, []],
displayPagination: [settings.displayPagination, []],
defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]],
defaultSortOrder: [settings.defaultSortOrder, []],
useRowStyleFunction: [settings.useRowStyleFunction, []],
rowStyleFunction: [settings.rowStyleFunction, [Validators.required]]
});
}
protected validatorTriggers(): string[] {
return ['useRowStyleFunction', 'displayPagination', 'displayEntityName', 'displayEntityLabel'];
}
protected updateValidators(emitEvent: boolean) {
const useRowStyleFunction: boolean = this.entitiesTableWidgetSettingsForm.get('useRowStyleFunction').value;
const displayPagination: boolean = this.entitiesTableWidgetSettingsForm.get('displayPagination').value;
const displayEntityName: boolean = this.entitiesTableWidgetSettingsForm.get('displayEntityName').value;
const displayEntityLabel: boolean = this.entitiesTableWidgetSettingsForm.get('displayEntityLabel').value;
if (useRowStyleFunction) {
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').disable();
}
if (displayPagination) {
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').disable();
}
if (displayEntityName) {
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').disable();
}
if (displayEntityLabel) {
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').enable();
} else {
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').disable();
}
this.entitiesTableWidgetSettingsForm.get('rowStyleFunction').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('defaultPageSize').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('entityNameColumnTitle').updateValueAndValidity({emitEvent});
this.entitiesTableWidgetSettingsForm.get('entityLabelColumnTitle').updateValueAndValidity({emitEvent});
}
}

25
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.html

@ -0,0 +1,25 @@
<!--
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]="htmlCardWidgetSettingsForm" fxLayout="column">
<tb-html formControlName="cardHtml" required
label="{{ 'widgets.html-card.html' | translate }}">
</tb-html>
<tb-css formControlName="cardCss"
label="{{ 'widgets.html-card.css' | translate }}">
</tb-css>
</section>

54
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/html-card-widget-settings.component.ts

@ -0,0 +1,54 @@
///
/// 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';
@Component({
selector: 'tb-html-card-widget-settings',
templateUrl: './html-card-widget-settings.component.html',
styleUrls: []
})
export class HtmlCardWidgetSettingsComponent extends WidgetSettingsComponent {
htmlCardWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.htmlCardWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
cardHtml: '<div class=\'card\'>HTML code here</div>',
cardCss: '.card {\n font-weight: bold; \n}'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.htmlCardWidgetSettingsForm = this.fb.group({
cardHtml: [settings.cardHtml, [Validators.required]],
cardCss: [settings.cardCss, []]
});
}
}

73
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.html

@ -0,0 +1,73 @@
<!--
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-widget-label" fxFlex [formGroup]="labelWidgetLabelFormGroup" [(expanded)]="expanded">
<mat-expansion-panel-header>
<div fxFlex fxLayout="row" fxLayoutAlign="start center">
<mat-panel-title>
<div fxLayout="row" fxFlex fxLayoutAlign="start center">
{{ labelWidgetLabelFormGroup.get('pattern').value }}
</div>
</mat-panel-title>
<span fxFlex></span>
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;"
type="button"
(click)="removeLabel.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">
<mat-form-field style="padding-bottom: 16px;">
<mat-label translate>widgets.label-widget.label-pattern</mat-label>
<input required matInput formControlName="pattern">
<mat-error *ngIf="labelWidgetLabelFormGroup.get('pattern').hasError('required')">
{{ 'widgets.label-widget.label-pattern-required' | translate }}
</mat-error>
<mat-hint [innerHTML]="'widgets.label-widget.label-pattern-hint' | translate | safe: 'html'"></mat-hint>
</mat-form-field>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.label-widget.label-position</legend>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex>
<mat-label translate>widgets.label-widget.x-pos</mat-label>
<input matInput type="number" min="0" max="100" formControlName="x">
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>widgets.label-widget.y-pos</mat-label>
<input matInput type="number" min="0" max="100" formControlName="y">
</mat-form-field>
</section>
</fieldset>
<tb-color-input
formControlName="backgroundColor"
icon="format_color_fill"
label="{{ 'widgets.label-widget.background-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.label-widget.font-settings</legend>
<tb-widget-font formControlName="font" sizeTitle="widgets.widget-font.relative-font-size"></tb-widget-font>
</fieldset>
</section>
</div>
</ng-template>
</mat-expansion-panel>

40
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.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-widget-label {
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-widget-label {
.mat-expansion-panel-body {
padding: 0 8px 8px;
}
}
}
}

113
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-label.component.ts

@ -0,0 +1,113 @@
///
/// 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 { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, 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 { WidgetFont } from '@home/components/widget/lib/settings/common/widget-font.component';
export interface LabelWidgetLabel {
pattern: string;
x: number;
y: number;
backgroundColor: string;
font: WidgetFont;
}
@Component({
selector: 'tb-label-widget-label',
templateUrl: './label-widget-label.component.html',
styleUrls: ['./label-widget-label.component.scss', './../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => LabelWidgetLabelComponent),
multi: true
}
]
})
export class LabelWidgetLabelComponent extends PageComponent implements OnInit, ControlValueAccessor {
@Input()
disabled: boolean;
@Input()
expanded = false;
@Output()
removeLabel = new EventEmitter();
private modelValue: LabelWidgetLabel;
private propagateChange = null;
public labelWidgetLabelFormGroup: FormGroup;
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private fb: FormBuilder) {
super(store);
}
ngOnInit(): void {
this.labelWidgetLabelFormGroup = this.fb.group({
pattern: [null, [Validators.required]],
x: [null, [Validators.min(0), Validators.max(100)]],
y: [null, [Validators.min(0), Validators.max(100)]],
backgroundColor: [null, []],
font: [null, []]
});
this.labelWidgetLabelFormGroup.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.labelWidgetLabelFormGroup.disable({emitEvent: false});
} else {
this.labelWidgetLabelFormGroup.enable({emitEvent: false});
}
}
writeValue(value: LabelWidgetLabel): void {
this.modelValue = value;
this.labelWidgetLabelFormGroup.patchValue(
value, {emitEvent: false}
);
}
private updateModel() {
const value: LabelWidgetLabel = this.labelWidgetLabelFormGroup.value;
this.modelValue = value;
if (this.labelWidgetLabelFormGroup.valid) {
this.propagateChange(this.modelValue);
} else {
this.propagateChange(null);
}
}
}

50
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.html

@ -0,0 +1,50 @@
<!--
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]="labelWidgetSettingsForm" fxLayout="column">
<tb-image-input required
label="{{ 'widgets.label-widget.background-image' | translate }}"
formControlName="backgroundImageUrl">
</tb-image-input>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.label-widget.labels</legend>
<div fxLayout="column">
<div class="tb-control-list tb-drop-list" cdkDropList cdkDropListOrientation="vertical"
(cdkDropListDropped)="labelDrop($event)">
<div cdkDrag class="tb-draggable" *ngFor="let labelControl of labelsFormArray().controls; trackBy: trackByLabelControl;
let $index = index; last as isLast;"
fxLayout="column" [ngStyle]="!isLast ? {paddingBottom: '8px'} : {}">
<tb-label-widget-label [formControl]="labelControl"
[expanded]="labelControl.new"
(removeLabel)="removeLabel($index)">
</tb-label-widget-label>
</div>
</div>
<div *ngIf="!labelsFormArray().controls.length">
<span translate fxLayoutAlign="center center"
class="tb-prompt">widgets.label-widget.no-labels</span>
</div>
<div style="padding-top: 16px;">
<button mat-raised-button color="primary"
type="button"
(click)="addLabel()">
<span translate>widgets.label-widget.add-label</span>
</button>
</div>
</div>
</fieldset>
</section>

110
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts

@ -0,0 +1,110 @@
///
/// 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 { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { LabelWidgetLabel } from '@home/components/widget/lib/settings/cards/label-widget-label.component';
import { CdkDragDrop } from '@angular/cdk/drag-drop';
@Component({
selector: 'tb-label-widget-settings',
templateUrl: './label-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class LabelWidgetSettingsComponent extends WidgetSettingsComponent {
labelWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.labelWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
backgroundImageUrl: 'data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==',
labels: []
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.labelWidgetSettingsForm = this.fb.group({
backgroundImageUrl: [settings.backgroundImageUrl, [Validators.required]],
labels: this.prepareLabelsFormArray(settings.labels)
});
}
protected doUpdateSettings(settingsForm: FormGroup, settings: WidgetSettings) {
settingsForm.setControl('labels', this.prepareLabelsFormArray(settings.labels), {emitEvent: false});
}
private prepareLabelsFormArray(labels: LabelWidgetLabel[] | undefined): FormArray {
const labelsControls: Array<AbstractControl> = [];
if (labels) {
labels.forEach((label) => {
labelsControls.push(this.fb.control(label, [Validators.required]));
});
}
return this.fb.array(labelsControls);
}
labelsFormArray(): FormArray {
return this.labelWidgetSettingsForm.get('labels') as FormArray;
}
public trackByLabelControl(index: number, labelControl: AbstractControl): any {
return labelControl;
}
public removeLabel(index: number) {
(this.labelWidgetSettingsForm.get('labels') as FormArray).removeAt(index);
}
public addLabel() {
const label: LabelWidgetLabel = {
pattern: '${#0}',
x: 50,
y: 50,
backgroundColor: 'rgba(0,0,0,0)',
font: {
family: 'Roboto',
size: 6,
style: 'normal',
weight: '500',
color: '#fff'
}
};
const labelsArray = this.labelWidgetSettingsForm.get('labels') as FormArray;
const labelControl = this.fb.control(label, [Validators.required]);
(labelControl as any).new = true;
labelsArray.push(labelControl);
this.labelWidgetSettingsForm.updateValueAndValidity();
}
labelDrop(event: CdkDragDrop<string[]>) {
const labelsArray = this.labelWidgetSettingsForm.get('labels') as FormArray;
const label = labelsArray.at(event.previousIndex);
labelsArray.removeAt(event.previousIndex);
labelsArray.insert(event.currentIndex, label);
}
}

36
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html

@ -0,0 +1,36 @@
<!--
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]="markdownWidgetSettingsForm" fxLayout="column">
<mat-slide-toggle class="mat-slide" formControlName="useMarkdownTextFunction">
{{ 'widgets.markdown.use-markdown-text-function' | translate }}
</mat-slide-toggle>
<tb-js-func [fxShow]="markdownWidgetSettingsForm.get('useMarkdownTextFunction').value"
formControlName="markdownTextFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['data']"
functionTitle="{{ 'widgets.markdown.markdown-text-function' | translate }}"
helpId="widget/lib/markdown/markdown_text_fn">
</tb-js-func>
<tb-markdown-editor [fxShow]="!markdownWidgetSettingsForm.get('useMarkdownTextFunction').value"
formControlName="markdownTextPattern"
label="{{ 'widgets.markdown.markdown-text-pattern' | translate }}">
</tb-markdown-editor>
<tb-css formControlName="markdownCss"
label="{{ 'widgets.markdown.markdown-css' | translate }}">
</tb-css>
</section>

76
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts

@ -0,0 +1,76 @@
///
/// 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';
@Component({
selector: 'tb-markdown-widget-settings',
templateUrl: './markdown-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class MarkdownWidgetSettingsComponent extends WidgetSettingsComponent {
markdownWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.markdownWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
useMarkdownTextFunction: false,
markdownTextPattern: '# Markdown/HTML card \\n - **Current entity**: **${entityName}**. \\n - **Current value**: **${Random}**.',
markdownTextFunction: 'return \'# Some title\\\\n - Entity name: \' + data[0][\'entityName\'];',
markdownCss: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.markdownWidgetSettingsForm = this.fb.group({
useMarkdownTextFunction: [settings.useMarkdownTextFunction, []],
markdownTextPattern: [settings.markdownTextPattern, []],
markdownTextFunction: [settings.qrCodeTextFunction, []],
markdownCss: [settings.markdownCss, []]
});
}
protected validatorTriggers(): string[] {
return ['useMarkdownTextFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useMarkdownTextFunction: boolean = this.markdownWidgetSettingsForm.get('useMarkdownTextFunction').value;
if (useMarkdownTextFunction) {
this.markdownWidgetSettingsForm.get('markdownTextPattern').disable();
this.markdownWidgetSettingsForm.get('markdownTextFunction').enable();
} else {
this.markdownWidgetSettingsForm.get('markdownTextPattern').enable();
this.markdownWidgetSettingsForm.get('markdownTextFunction').disable();
}
this.markdownWidgetSettingsForm.get('markdownTextPattern').updateValueAndValidity({emitEvent});
this.markdownWidgetSettingsForm.get('markdownTextFunction').updateValueAndValidity({emitEvent});
}
}

37
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.html

@ -0,0 +1,37 @@
<!--
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]="qrCodeWidgetSettingsForm" fxLayout="column">
<mat-slide-toggle class="mat-slide" formControlName="useQrCodeTextFunction">
{{ 'widgets.qr-code.use-qr-code-text-function' | translate }}
</mat-slide-toggle>
<mat-form-field [fxShow]="!qrCodeWidgetSettingsForm.get('useQrCodeTextFunction').value">
<mat-label translate>widgets.qr-code.qr-code-text-pattern</mat-label>
<input required matInput formControlName="qrCodeTextPattern">
<mat-error *ngIf="qrCodeWidgetSettingsForm.get('qrCodeTextPattern').hasError('required')">
{{ 'widgets.qr-code.qr-code-text-pattern-required' | translate }}
</mat-error>
</mat-form-field>
<tb-js-func required
[fxShow]="qrCodeWidgetSettingsForm.get('useQrCodeTextFunction').value"
formControlName="qrCodeTextFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['data']"
functionTitle="{{ 'widgets.qr-code.qr-code-text-function' | translate }}"
helpId="widget/lib/qrcode/qrcode_text_fn">
</tb-js-func>
</section>

74
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/qrcode-widget-settings.component.ts

@ -0,0 +1,74 @@
///
/// 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';
@Component({
selector: 'tb-qrcode-widget-settings',
templateUrl: './qrcode-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class QrCodeWidgetSettingsComponent extends WidgetSettingsComponent {
qrCodeWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.qrCodeWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
qrCodeTextPattern: '${entityName}',
useQrCodeTextFunction: false,
qrCodeTextFunction: 'return data[0][\'entityName\'];'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.qrCodeWidgetSettingsForm = this.fb.group({
qrCodeTextPattern: [settings.qrCodeTextPattern, [Validators.required]],
useQrCodeTextFunction: [settings.useQrCodeTextFunction, [Validators.required]],
qrCodeTextFunction: [settings.qrCodeTextFunction, [Validators.required]]
});
}
protected validatorTriggers(): string[] {
return ['useQrCodeTextFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useQrCodeTextFunction: boolean = this.qrCodeWidgetSettingsForm.get('useQrCodeTextFunction').value;
if (useQrCodeTextFunction) {
this.qrCodeWidgetSettingsForm.get('qrCodeTextPattern').disable();
this.qrCodeWidgetSettingsForm.get('qrCodeTextFunction').enable();
} else {
this.qrCodeWidgetSettingsForm.get('qrCodeTextPattern').enable();
this.qrCodeWidgetSettingsForm.get('qrCodeTextFunction').disable();
}
this.qrCodeWidgetSettingsForm.get('qrCodeTextPattern').updateValueAndValidity({emitEvent});
this.qrCodeWidgetSettingsForm.get('qrCodeTextFunction').updateValueAndValidity({emitEvent});
}
}

30
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.html

@ -0,0 +1,30 @@
<!--
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]="simpleCardWidgetSettingsForm" fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.simple-card.label-position</mat-label>
<mat-select formControlName="labelPosition">
<mat-option [value]="'left'">
{{ 'widgets.simple-card.label-position-left' | translate }}
</mat-option>
<mat-option [value]="'top'">
{{ 'widgets.simple-card.label-position-top' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>

52
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/simple-card-widget-settings.component.ts

@ -0,0 +1,52 @@
///
/// 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';
@Component({
selector: 'tb-simple-card-widget-settings',
templateUrl: './simple-card-widget-settings.component.html',
styleUrls: []
})
export class SimpleCardWidgetSettingsComponent extends WidgetSettingsComponent {
simpleCardWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.simpleCardWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
labelPosition: 'left'
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.simpleCardWidgetSettingsForm = this.fb.group({
labelPosition: [settings.labelPosition, []]
});
}
}

69
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.html

@ -0,0 +1,69 @@
<!--
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]="timeseriesTableKeySettingsForm" fxLayout="column">
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableKeySettingsForm.get('useCellStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-style-function' | 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-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
helpId="widget/lib/timeseries/cell_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-content</legend>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableKeySettingsForm.get('useCellContentFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-content-function' | 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-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"
helpId="widget/lib/timeseries/cell_content_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

80
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-key-settings.component.ts

@ -0,0 +1,80 @@
///
/// 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';
@Component({
selector: 'tb-timeseries-table-key-settings',
templateUrl: './timeseries-table-key-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class TimeseriesTableKeySettingsComponent extends WidgetSettingsComponent {
timeseriesTableKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.timeseriesTableKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
useCellStyleFunction: false,
cellStyleFunction: '',
useCellContentFunction: false,
cellContentFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.timeseriesTableKeySettingsForm = this.fb.group({
useCellStyleFunction: [settings.useCellStyleFunction, []],
cellStyleFunction: [settings.cellStyleFunction, [Validators.required]],
useCellContentFunction: [settings.useCellContentFunction, []],
cellContentFunction: [settings.cellContentFunction, [Validators.required]],
});
}
protected validatorTriggers(): string[] {
return ['useCellStyleFunction', 'useCellContentFunction'];
}
protected updateValidators(emitEvent: boolean) {
const useCellStyleFunction: boolean = this.timeseriesTableKeySettingsForm.get('useCellStyleFunction').value;
const useCellContentFunction: boolean = this.timeseriesTableKeySettingsForm.get('useCellContentFunction').value;
if (useCellStyleFunction) {
this.timeseriesTableKeySettingsForm.get('cellStyleFunction').enable();
} else {
this.timeseriesTableKeySettingsForm.get('cellStyleFunction').disable();
}
if (useCellContentFunction) {
this.timeseriesTableKeySettingsForm.get('cellContentFunction').enable();
} else {
this.timeseriesTableKeySettingsForm.get('cellContentFunction').disable();
}
this.timeseriesTableKeySettingsForm.get('cellStyleFunction').updateValueAndValidity({emitEvent});
this.timeseriesTableKeySettingsForm.get('cellContentFunction').updateValueAndValidity({emitEvent});
}
}

76
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.html

@ -0,0 +1,76 @@
<!--
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]="timeseriesTableLatestKeySettingsForm" fxLayout="column">
<mat-slide-toggle class="mat-slide" formControlName="show">
{{ 'widgets.table.show-latest-data-column' | translate }}
</mat-slide-toggle>
<mat-form-field [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" fxFlex class="mat-block">
<mat-label translate>widgets.table.latest-data-column-order</mat-label>
<input matInput type="number" step="1" formControlName="order">
</mat-form-field>
<fieldset [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableLatestKeySettingsForm.get('useCellStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-style-function' | 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-js-func required
formControlName="cellStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-style-function' | translate }}"
helpId="widget/lib/timeseries/cell_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
<fieldset [fxShow]="timeseriesTableLatestKeySettingsForm.get('show').value" class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.cell-content</legend>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableLatestKeySettingsForm.get('useCellContentFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useCellContentFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-cell-content-function' | 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-js-func required
formControlName="cellContentFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['value', 'rowData', 'ctx']"
functionTitle="{{ 'widgets.table.cell-content-function' | translate }}"
helpId="widget/lib/timeseries/cell_content_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

96
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-latest-key-settings.component.ts

@ -0,0 +1,96 @@
///
/// 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';
@Component({
selector: 'tb-timeseries-table-latest-key-settings',
templateUrl: './timeseries-table-latest-key-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class TimeseriesTableLatestKeySettingsComponent extends WidgetSettingsComponent {
timeseriesTableLatestKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.timeseriesTableLatestKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
show: true,
useCellStyleFunction: false,
cellStyleFunction: '',
useCellContentFunction: false,
cellContentFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.timeseriesTableLatestKeySettingsForm = this.fb.group({
show: [settings.show, []],
order: [settings.order, []],
useCellStyleFunction: [settings.useCellStyleFunction, []],
cellStyleFunction: [settings.cellStyleFunction, [Validators.required]],
useCellContentFunction: [settings.useCellContentFunction, []],
cellContentFunction: [settings.cellContentFunction, [Validators.required]],
});
}
protected validatorTriggers(): string[] {
return ['show', 'useCellStyleFunction', 'useCellContentFunction'];
}
protected updateValidators(emitEvent: boolean) {
const show: boolean = this.timeseriesTableLatestKeySettingsForm.get('show').value;
if (show) {
this.timeseriesTableLatestKeySettingsForm.get('order').enable();
this.timeseriesTableLatestKeySettingsForm.get('useCellStyleFunction').enable({emitEvent: false});
this.timeseriesTableLatestKeySettingsForm.get('useCellContentFunction').enable({emitEvent: false});
const useCellStyleFunction: boolean = this.timeseriesTableLatestKeySettingsForm.get('useCellStyleFunction').value;
const useCellContentFunction: boolean = this.timeseriesTableLatestKeySettingsForm.get('useCellContentFunction').value;
if (useCellStyleFunction) {
this.timeseriesTableLatestKeySettingsForm.get('cellStyleFunction').enable();
} else {
this.timeseriesTableLatestKeySettingsForm.get('cellStyleFunction').disable();
}
if (useCellContentFunction) {
this.timeseriesTableLatestKeySettingsForm.get('cellContentFunction').enable();
} else {
this.timeseriesTableLatestKeySettingsForm.get('cellContentFunction').disable();
}
} else {
this.timeseriesTableLatestKeySettingsForm.get('order').disable();
this.timeseriesTableLatestKeySettingsForm.get('useCellStyleFunction').disable({emitEvent: false});
this.timeseriesTableLatestKeySettingsForm.get('cellStyleFunction').disable();
this.timeseriesTableLatestKeySettingsForm.get('useCellContentFunction').disable({emitEvent: false});
this.timeseriesTableLatestKeySettingsForm.get('cellContentFunction').disable();
}
this.timeseriesTableLatestKeySettingsForm.get('order').updateValueAndValidity({emitEvent});
this.timeseriesTableLatestKeySettingsForm.get('cellStyleFunction').updateValueAndValidity({emitEvent});
this.timeseriesTableLatestKeySettingsForm.get('cellContentFunction').updateValueAndValidity({emitEvent});
}
}

96
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.html

@ -0,0 +1,96 @@
<!--
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]="timeseriesTableWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.table.common-table-settings</legend>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableSearch" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-search' | translate }}
</mat-checkbox>
</section>
<section fxLayout="column" fxFlex>
<mat-checkbox formControlName="enableStickyHeader" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-header' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="enableStickyAction" style="margin-bottom: 16px;">
{{ 'widgets.table.enable-sticky-action' | translate }}
</mat-checkbox>
</section>
</section>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.hidden-cell-button-display-mode</mat-label>
<mat-select formControlName="reserveSpaceForHiddenAction">
<mat-option [value]="'true'">
{{ 'widgets.table.show-empty-space-hidden-action' | translate }}
</mat-option>
<mat-option [value]="'false'">
{{ 'widgets.table.dont-reserve-space-hidden-action' | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<section fxLayout="column" fxLayoutGap="8px">
<mat-slide-toggle formControlName="showTimestamp">
{{ 'widgets.table.display-timestamp' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="showMilliseconds">
{{ 'widgets.table.display-milliseconds' | translate }}
</mat-slide-toggle>
<section fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start center">
<mat-slide-toggle fxFlex formControlName="displayPagination">
{{ 'widgets.table.display-pagination' | translate }}
</mat-slide-toggle>
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.table.default-page-size</mat-label>
<input matInput type="number" min="1" step="1" formControlName="defaultPageSize">
</mat-form-field>
</section>
<mat-slide-toggle formControlName="useEntityLabel">
{{ 'widgets.table.use-entity-label-tab-name' | translate }}
</mat-slide-toggle>
<mat-slide-toggle formControlName="hideEmptyLines">
{{ 'widgets.table.hide-empty-lines' | translate }}
</mat-slide-toggle>
</section>
</fieldset>
<fieldset class="fields-group fields-group-slider">
<legend class="group-title" translate>widgets.table.row-style</legend>
<mat-expansion-panel class="tb-settings" [expanded]="timeseriesTableWidgetSettingsForm.get('useRowStyleFunction').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="useRowStyleFunction" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.table.use-row-style-function' | 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-js-func required
formControlName="rowStyleFunction"
[globalVariables]="functionScopeVariables"
[functionArgs]="['rowData', 'ctx']"
functionTitle="{{ 'widgets.table.row-style-function' | translate }}"
helpId="widget/lib/timeseries/row_style_fn">
</tb-js-func>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

98
ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/timeseries-table-widget-settings.component.ts

@ -0,0 +1,98 @@
///
/// 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';
@Component({
selector: 'tb-timeseries-table-widget-settings',
templateUrl: './timeseries-table-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class TimeseriesTableWidgetSettingsComponent extends WidgetSettingsComponent {
timeseriesTableWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.timeseriesTableWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
enableSearch: true,
enableStickyHeader: true,
enableStickyAction: true,
reserveSpaceForHiddenAction: 'true',
showTimestamp: true,
showMilliseconds: false,
displayPagination: true,
useEntityLabel: false,
defaultPageSize: 10,
hideEmptyLines: false,
disableStickyHeader: false,
useRowStyleFunction: false,
rowStyleFunction: ''
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.timeseriesTableWidgetSettingsForm = this.fb.group({
enableSearch: [settings.enableSearch, []],
enableStickyHeader: [settings.enableStickyHeader, []],
enableStickyAction: [settings.enableStickyAction, []],
reserveSpaceForHiddenAction: [settings.reserveSpaceForHiddenAction, []],
showTimestamp: [settings.showTimestamp, []],
showMilliseconds: [settings.showMilliseconds, []],
displayPagination: [settings.displayPagination, []],
useEntityLabel: [settings.useEntityLabel, []],
defaultPageSize: [settings.defaultPageSize, [Validators.min(1)]],
hideEmptyLines: [settings.hideEmptyLines, []],
disableStickyHeader: [settings.disableStickyHeader, []],
useRowStyleFunction: [settings.useRowStyleFunction, []],
rowStyleFunction: [settings.rowStyleFunction, [Validators.required]]
});
}
protected validatorTriggers(): string[] {
return ['useRowStyleFunction', 'displayPagination'];
}
protected updateValidators(emitEvent: boolean) {
const useRowStyleFunction: boolean = this.timeseriesTableWidgetSettingsForm.get('useRowStyleFunction').value;
const displayPagination: boolean = this.timeseriesTableWidgetSettingsForm.get('displayPagination').value;
if (useRowStyleFunction) {
this.timeseriesTableWidgetSettingsForm.get('rowStyleFunction').enable();
} else {
this.timeseriesTableWidgetSettingsForm.get('rowStyleFunction').disable();
}
if (displayPagination) {
this.timeseriesTableWidgetSettingsForm.get('defaultPageSize').enable();
} else {
this.timeseriesTableWidgetSettingsForm.get('defaultPageSize').disable();
}
this.timeseriesTableWidgetSettingsForm.get('rowStyleFunction').updateValueAndValidity({emitEvent});
this.timeseriesTableWidgetSettingsForm.get('defaultPageSize').updateValueAndValidity({emitEvent});
}
}

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

@ -0,0 +1,25 @@
<!--
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]="chartWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.chart.common-settings</legend>
<mat-slide-toggle formControlName="showTooltip" class="slide-block">
{{ 'widgets.chart.show-tooltip' | translate }}
</mat-slide-toggle>
</fieldset>
</section>

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

@ -0,0 +1,52 @@
///
/// 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';
@Component({
selector: 'tb-chart-widget-settings',
templateUrl: './chart-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class ChartWidgetSettingsComponent extends WidgetSettingsComponent {
chartWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.chartWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
showTooltip: true
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.chartWidgetSettingsForm = this.fb.group({
showTooltip: [settings.showTooltip, []]
});
}
}

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

@ -0,0 +1,64 @@
<!--
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]="doughnutChartWidgetSettingsForm" fxLayout="column">
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.chart.common-settings</legend>
<mat-slide-toggle formControlName="showTooltip" class="slide-block">
{{ 'widgets.chart.show-tooltip' | translate }}
</mat-slide-toggle>
</fieldset>
<fieldset class="fields-group">
<legend class="group-title" translate>widgets.chart.border-settings</legend>
<section fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="8px">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>widgets.chart.border-width</mat-label>
<input matInput type="number" min="0" formControlName="borderWidth">
</mat-form-field>
<tb-color-input fxFlex
formControlName="borderColor"
icon="format_color_fill"
label="{{ 'widgets.chart.border-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</section>
</fieldset>
<fieldset class="fields-group fields-group-slider" formGroupName="legend">
<legend class="group-title" translate>widgets.chart.legend-settings</legend>
<mat-expansion-panel class="tb-settings" [expanded]="doughnutChartWidgetSettingsForm.get('legend.display').value">
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<mat-slide-toggle formControlName="display" (click)="$event.stopPropagation()"
fxLayoutAlign="center">
{{ 'widgets.chart.display-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>
<section fxLayout="column">
<tb-color-input fxFlex
formControlName="labelsFontColor"
icon="format_color_fill"
label="{{ 'widgets.chart.labels-font-color' | translate }}" openOnInput colorClearButton>
</tb-color-input>
</section>
</ng-template>
</mat-expansion-panel>
</fieldset>
</section>

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

@ -0,0 +1,87 @@
///
/// 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';
@Component({
selector: 'tb-doughnut-chart-widget-settings',
templateUrl: './doughnut-chart-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss']
})
export class DoughnutChartWidgetSettingsComponent extends WidgetSettingsComponent {
doughnutChartWidgetSettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.doughnutChartWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
showTooltip: true,
borderWidth: 5,
borderColor: '#fff',
legend: {
display: true,
labelsFontColor: '#666'
}
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.doughnutChartWidgetSettingsForm = this.fb.group({
// Common settings
showTooltip: [settings.showTooltip, []],
// Border settings
borderWidth: [settings.borderWidth, [Validators.min(0)]],
borderColor: [settings.borderColor, []],
// Legend settings
legend: this.fb.group({
display: [settings.legend?.display, []],
labelsFontColor: [settings.legend?.labelsFontColor, []]
})
});
}
protected validatorTriggers(): string[] {
return ['legend.display'];
}
protected updateValidators(emitEvent: boolean) {
const displayLegend: boolean = this.doughnutChartWidgetSettingsForm.get('legend.display').value;
if (displayLegend) {
this.doughnutChartWidgetSettingsForm.get('legend.labelsFontColor').enable();
} else {
this.doughnutChartWidgetSettingsForm.get('legend.labelsFontColor').disable();
}
this.doughnutChartWidgetSettingsForm.get('legend.labelsFontColor').updateValueAndValidity({emitEvent});
}
}

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

@ -0,0 +1,24 @@
<!--
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]="flotBarKeySettingsForm" fxLayout="column">
<tb-flot-key-settings formControlName="flotKeySettings"
[aliasController]="aliasController"
[chartType]="'bar'">
</tb-flot-key-settings>
</section>

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

@ -0,0 +1,61 @@
///
/// 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 { flotDataKeyDefaultSettings } from '@home/components/widget/lib/settings/chart/flot-key-settings.component';
@Component({
selector: 'tb-flot-bar-key-settings',
templateUrl: './flot-bar-key-settings.component.html',
styleUrls: []
})
export class FlotBarKeySettingsComponent extends WidgetSettingsComponent {
flotBarKeySettingsForm: FormGroup;
constructor(protected store: Store<AppState>,
private fb: FormBuilder) {
super(store);
}
protected settingsForm(): FormGroup {
return this.flotBarKeySettingsForm;
}
protected defaultSettings(): WidgetSettings {
return flotDataKeyDefaultSettings('bar');
}
protected onSettingsSet(settings: WidgetSettings) {
this.flotBarKeySettingsForm = this.fb.group({
flotKeySettings: [settings.flotKeySettings, []]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
return {
flotKeySettings: settings
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return settings.flotKeySettings;
}
}

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>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save