Browse Source

UI: Implement initial Map V3 settings.

pull/12723/head
Igor Kulikov 2 years ago
parent
commit
0d4d82100e
  1. 5
      application/src/main/data/json/system/widget_bundles/maps.json
  2. 4
      application/src/main/data/json/system/widget_types/google_map.json
  3. 4
      application/src/main/data/json/system/widget_types/here_map.json
  4. 4
      application/src/main/data/json/system/widget_types/image_map.json
  5. 25
      application/src/main/data/json/system/widget_types/map.json
  6. 4
      application/src/main/data/json/system/widget_types/markers_placement___google_maps.json
  7. 4
      application/src/main/data/json/system/widget_types/markers_placement___image_map.json
  8. 4
      application/src/main/data/json/system/widget_types/markers_placement___openstreetmap.json
  9. 4
      application/src/main/data/json/system/widget_types/openstreet_map.json
  10. 2
      application/src/main/data/json/system/widget_types/route_map___google.json
  11. 2
      application/src/main/data/json/system/widget_types/route_map___openstreet.json
  12. 2
      application/src/main/data/json/system/widget_types/route_map___tencent.json
  13. 4
      application/src/main/data/json/system/widget_types/tencent_map.json
  14. 2
      application/src/main/data/json/system/widget_types/trip_animation.json
  15. 10
      ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts
  16. 91
      ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.html
  17. 150
      ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts
  18. 61
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet/leaflet-tb.ts
  19. 179
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-layer.ts
  20. 72
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map.models.ts
  21. 3
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss
  22. 11
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts
  23. 43
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.html
  24. 141
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts
  25. 7
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts
  26. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.html
  27. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts
  28. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.html
  29. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts
  30. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.html
  31. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts
  32. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.html
  33. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts
  34. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.html
  35. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts
  36. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.html
  37. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts
  38. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.html
  39. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts
  40. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.html
  41. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts
  42. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.html
  43. 12
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts
  44. 24
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.html
  45. 63
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts
  46. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.html
  47. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts
  48. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.html
  49. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts
  50. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.html
  51. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts
  52. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.html
  53. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts
  54. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.html
  55. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts
  56. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.html
  57. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts
  58. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.html
  59. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts
  60. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.html
  61. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts
  62. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.html
  63. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts
  64. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.html
  65. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts
  66. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.html
  67. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts
  68. 0
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.html
  69. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts
  70. 24
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.html
  71. 19
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts
  72. 64
      ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts
  73. 3
      ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
  74. 2
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  75. 6
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
  76. 1
      ui-ngx/src/app/shared/models/widget.models.ts
  77. 11
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  78. 28
      ui-ngx/src/typings/leaflet-extend-tb.d.ts

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

File diff suppressed because one or more lines are too long

4
application/src/main/data/json/system/widget_types/google_map.json

File diff suppressed because one or more lines are too long

4
application/src/main/data/json/system/widget_types/here_map.json

File diff suppressed because one or more lines are too long

4
application/src/main/data/json/system/widget_types/image_map.json

File diff suppressed because one or more lines are too long

25
application/src/main/data/json/system/widget_types/map.json

@ -0,0 +1,25 @@
{
"fqn": "map",
"name": "Map",
"deprecated": false,
"image": null,
"description": null,
"descriptor": {
"type": "latest",
"sizeX": 7.5,
"sizeY": 5.5,
"resources": [],
"templateHtml": "<tb-map-widget \n [ctx]=\"ctx\"\n [widgetTitlePanel]=\"widgetTitlePanel\">\n</tb-map-widget>",
"templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}",
"controllerScript": "self.onInit = function() {\n self.ctx.$scope.mapWidget.onInit();\n};\n\nself.typeParameters = function() {\n return {\n hideDataTab: true,\n hideDataSettings: true,\n previewWidth: '80%',\n embedTitlePanel: true,\n datasourcesOptional: true\n };\n}\n",
"settingsForm": [],
"dataKeySettingsForm": [],
"settingsDirective": "tb-map-widget-settings",
"hasBasicMode": true,
"basicModeDirective": "tb-map-basic-config",
"defaultConfig": "{\"datasources\":[],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"mapType\":\"geoMap\",\"layers\":[{\"provider\":\"openstreet-map\",\"layerType\":\"openStreetMapnik\"},{\"provider\":\"openstreet-map\",\"layerType\":\"openStreetHot\"},{\"provider\":\"openstreet-map\",\"layerType\":\"esriWorldStreetMap\"},{\"provider\":\"openstreet-map\",\"layerType\":\"esriWorldTopoMap\"},{\"provider\":\"openstreet-map\",\"layerType\":\"esriWorldImagery\"},{\"provider\":\"openstreet-map\",\"layerType\":\"cartoDbPositron\"},{\"provider\":\"openstreet-map\",\"layerType\":\"cartoDbDarkMatter\"},{\"provider\":\"google-map\",\"layerType\":\"roadmap\",\"apiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\"},{\"provider\":\"google-map\",\"layerType\":\"satellite\",\"apiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\"},{\"provider\":\"google-map\",\"layerType\":\"hybrid\",\"apiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\"},{\"provider\":\"google-map\",\"layerType\":\"terrain\",\"apiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\"},{\"provider\":\"tencent-map\",\"layerType\":\"tencentNormal\"},{\"provider\":\"tencent-map\",\"layerType\":\"tencentSatellite\"},{\"provider\":\"tencent-map\",\"layerType\":\"tencentTerrain\"},{\"provider\":\"here\",\"layerType\":\"hereNormalDay\",\"apiKey\":\"kVXykxAfZ6LS4EbCTO02soFVfjA7HoBzNVVH9u7nzoE\"},{\"provider\":\"here\",\"layerType\":\"hereNormalNight\",\"apiKey\":\"kVXykxAfZ6LS4EbCTO02soFVfjA7HoBzNVVH9u7nzoE\"},{\"provider\":\"here\",\"layerType\":\"hereHybridDay\",\"apiKey\":\"kVXykxAfZ6LS4EbCTO02soFVfjA7HoBzNVVH9u7nzoE\"},{\"provider\":\"here\",\"layerType\":\"hereTerrainDay\",\"apiKey\":\"kVXykxAfZ6LS4EbCTO02soFVfjA7HoBzNVVH9u7nzoE\"},{\"provider\":\"custom\",\"tileUrl\":\"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\"label\":\"Custom 1\"},{\"provider\":\"custom\",\"tileUrl\":\"http://a.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png\",\"label\":\"Custom 2\"},{\"provider\":\"custom\",\"tileUrl\":\"http://b.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png\",\"label\":\"Custom 3\"}],\"markers\":[],\"polygons\":[],\"circles\":[],\"additionalDataSources\":[],\"controlsPosition\":\"topleft\",\"zoomActions\":[\"scroll\",\"doubleClick\",\"controlButtons\"],\"fitMapBounds\":true,\"useDefaultCenterPosition\":false,\"defaultCenterPosition\":\"0,0\",\"defaultZoomLevel\":null,\"mapPageSize\":16384,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"padding\":\"12px\"},\"title\":\"Map\",\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showTitleIcon\":false,\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"widgetCss\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"noDataDisplayMessage\":\"\",\"configMode\":\"basic\",\"titleFont\":null,\"titleColor\":null,\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"24px\",\"titleIcon\":\"map\",\"iconColor\":\"#1F6BDD\",\"actions\":{}}"
},
"resources": [],
"scada": false,
"tags": null
}

4
application/src/main/data/json/system/widget_types/markers_placement___google_maps.json

@ -1,7 +1,7 @@
{ {
"fqn": "input_widgets.markers_placement_google_maps", "fqn": "input_widgets.markers_placement_google_maps",
"name": "Markers Placement - Google Maps", "name": "Markers Placement - Google Maps",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/markers_placement_google_maps_system_widget_image.png", "image": "tb-image;/api/images/system/markers_placement_google_maps_system_widget_image.png",
"description": "Allows configuring the location of the selected entities on Google Maps. By default, store the location using 'latitude' and 'longitude' server-side attributes.", "description": "Allows configuring the location of the selected entities on Google Maps. By default, store the location using 'latitude' and 'longitude' server-side attributes.",
"descriptor": { "descriptor": {
@ -14,7 +14,7 @@
"controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('google-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}", "controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('google-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}",
"settingsSchema": "", "settingsSchema": "",
"dataKeySettingsSchema": "", "dataKeySettingsSchema": "",
"settingsDirective": "tb-map-widget-settings", "settingsDirective": "tb-map-widget-settings-legacy",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"gmDefaultMapType\":\"roadmap\",\"gmApiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\",\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"colorFunction\":\"\\n\",\"color\":\"#fe7569\",\"showTooltip\":true,\"autocloseTooltip\":true,\"defaultCenterPosition\":\"0,0\",\"showTooltipAction\":\"click\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"zoomOnClick\":true,\"defaultZoomLevel\":5,\"provider\":\"google-map\",\"showCoverageOnHover\":true,\"animate\":true,\"maxClusterRadius\":80,\"removeOutsideVisibleBounds\":true,\"mapProvider\":\"HERE.normalDay\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete_polygon'>Delete</link-act>\",\"showPolygonTooltip\":false},\"title\":\"Markers Placement - Google Maps\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"8d3c0156-0a14-7a6f-0ddd-0ec16b9ffc91\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"46bf69cd-8906-234c-a879-e2e4c92f5b67\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"gmDefaultMapType\":\"roadmap\",\"gmApiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\",\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"colorFunction\":\"\\n\",\"color\":\"#fe7569\",\"showTooltip\":true,\"autocloseTooltip\":true,\"defaultCenterPosition\":\"0,0\",\"showTooltipAction\":\"click\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"zoomOnClick\":true,\"defaultZoomLevel\":5,\"provider\":\"google-map\",\"showCoverageOnHover\":true,\"animate\":true,\"maxClusterRadius\":80,\"removeOutsideVisibleBounds\":true,\"mapProvider\":\"HERE.normalDay\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete_polygon'>Delete</link-act>\",\"showPolygonTooltip\":false},\"title\":\"Markers Placement - Google Maps\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"8d3c0156-0a14-7a6f-0ddd-0ec16b9ffc91\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"46bf69cd-8906-234c-a879-e2e4c92f5b67\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}"
}, },
"tags": [ "tags": [

4
application/src/main/data/json/system/widget_types/markers_placement___image_map.json

@ -1,7 +1,7 @@
{ {
"fqn": "input_widgets.markers_placement_image_map", "fqn": "input_widgets.markers_placement_image_map",
"name": "Markers Placement - Image Map", "name": "Markers Placement - Image Map",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/markers_placement_image_map_system_widget_image.png", "image": "tb-image;/api/images/system/markers_placement_image_map_system_widget_image.png",
"description": "Allows configuring the location of the selected entities on the Image map. By default, store the location using 'xPos' and 'yPos' server-side attributes with values of 0.0 to 1.0.", "description": "Allows configuring the location of the selected entities on the Image map. By default, store the location using 'xPos' and 'yPos' server-side attributes with values of 0.0 to 1.0.",
"descriptor": { "descriptor": {
@ -14,7 +14,7 @@
"controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('image-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}", "controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('image-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}",
"settingsSchema": "", "settingsSchema": "",
"dataKeySettingsSchema": "", "dataKeySettingsSchema": "",
"settingsDirective": "tb-map-widget-settings", "settingsDirective": "tb-map-widget-settings-legacy",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"xPos\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 0.2;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"yPos\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || 0.3;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"xPos\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 0.6;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"yPos\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || 0.7;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>X Pos:</b> ${xPos:2}<br/><b>Y Pos:</b> ${yPos:2}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"color\":\"#fe7569\",\"mapImageUrl\":\"tb-image;/api/images/system/markers_placement_image_map_system_widget_map_image.svg\",\"xPosKeyName\":\"xPos\",\"yPosKeyName\":\"yPos\",\"posFunction\":\"return {x: origXPos, y: origYPos};\",\"markerOffsetX\":0.5,\"markerOffsetY\":1,\"showTooltip\":true,\"autocloseTooltip\":true,\"showTooltipAction\":\"click\",\"defaultCenterPosition\":\"0,0\",\"provider\":\"image-map\",\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"mapProvider\":\"HERE.normalDay\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete_polygon'>Delete</link-act>\"},\"title\":\"Markers Placement - Image Map\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"c39f512a-21c6-6b06-3aa1-715262c6553d\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"94bf5ffd-b526-c6c3-ae3b-ab42191217d9\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"xPos\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 0.2;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"yPos\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || 0.3;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"xPos\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 0.6;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"yPos\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || 0.7;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>X Pos:</b> ${xPos:2}<br/><b>Y Pos:</b> ${yPos:2}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"color\":\"#fe7569\",\"mapImageUrl\":\"tb-image;/api/images/system/markers_placement_image_map_system_widget_map_image.svg\",\"xPosKeyName\":\"xPos\",\"yPosKeyName\":\"yPos\",\"posFunction\":\"return {x: origXPos, y: origYPos};\",\"markerOffsetX\":0.5,\"markerOffsetY\":1,\"showTooltip\":true,\"autocloseTooltip\":true,\"showTooltipAction\":\"click\",\"defaultCenterPosition\":\"0,0\",\"provider\":\"image-map\",\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"mapProvider\":\"HERE.normalDay\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete_polygon'>Delete</link-act>\"},\"title\":\"Markers Placement - Image Map\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"c39f512a-21c6-6b06-3aa1-715262c6553d\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"94bf5ffd-b526-c6c3-ae3b-ab42191217d9\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}"
}, },
"tags": [ "tags": [

4
application/src/main/data/json/system/widget_types/markers_placement___openstreetmap.json

@ -1,7 +1,7 @@
{ {
"fqn": "input_widgets.markers_placement_openstreetmap", "fqn": "input_widgets.markers_placement_openstreetmap",
"name": "Markers Placement - OpenStreetMap", "name": "Markers Placement - OpenStreetMap",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/markers_placement_openstreetmap_system_widget_image.png", "image": "tb-image;/api/images/system/markers_placement_openstreetmap_system_widget_image.png",
"description": "Allows configuring the location of the selected entities on OpenStreetMap. By default, store the location using 'latitude' and 'longitude' server-side attributes.", "description": "Allows configuring the location of the selected entities on OpenStreetMap. By default, store the location using 'latitude' and 'longitude' server-side attributes.",
"descriptor": { "descriptor": {
@ -14,7 +14,7 @@
"controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('openstreet-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}", "controllerScript": "self.onInit = function() {\n self.ctx.map = new TbMapWidgetV2('openstreet-map', false, self.ctx, null, true);\n}\n\nself.onDataUpdated = function() {\n self.ctx.map.update();\n}\n\nself.onResize = function() {\n self.ctx.map.resize();\n}\n\nself.actionSources = function() {\n return TbMapWidgetV2.actionSources();\n}\n\nself.onDestroy = function() {\n self.ctx.map.destroy();\n}\n\nself.typeParameters = function() {\n return {\n hasDataPageLink: true\n };\n}",
"settingsSchema": "", "settingsSchema": "",
"dataKeySettingsSchema": "", "dataKeySettingsSchema": "",
"settingsDirective": "tb-map-widget-settings", "settingsDirective": "tb-map-widget-settings-legacy",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.7867521952070078,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#9c27b0\",\"settings\":{},\"_hash\":0.7040053227577256,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"color\":\"#fe7569\",\"mapProvider\":\"OpenStreetMap.Mapnik\",\"showTooltip\":true,\"autocloseTooltip\":true,\"defaultCenterPosition\":\"0,0\",\"customProviderTileUrl\":\"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\"showTooltipAction\":\"click\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"zoomOnClick\":true,\"showCoverageOnHover\":true,\"animate\":true,\"maxClusterRadius\":80,\"removeOutsideVisibleBounds\":true,\"defaultZoomLevel\":5,\"provider\":\"openstreet-map\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete'>Delete</link-act>\"},\"title\":\"Markers Placement - OpenStreetMap\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"54c293c4-9ca6-e34f-dc6a-0271944c1c66\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"6beb7bed-dfd8-388d-b60c-82988ab52f06\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"First point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"Second point\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.7867521952070078,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#9c27b0\",\"settings\":{},\"_hash\":0.7040053227577256,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"fitMapBounds\":true,\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"label\":\"${entityName}\",\"tooltipPattern\":\"<b>${entityName}</b><br/><br/><b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><br/><link-act name='delete'>Delete</link-act>\",\"markerImageSize\":34,\"useColorFunction\":false,\"markerImages\":[],\"useMarkerImageFunction\":false,\"color\":\"#fe7569\",\"mapProvider\":\"OpenStreetMap.Mapnik\",\"showTooltip\":true,\"autocloseTooltip\":true,\"defaultCenterPosition\":\"0,0\",\"customProviderTileUrl\":\"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\"showTooltipAction\":\"click\",\"polygonKeyName\":\"coordinates\",\"polygonOpacity\":0.5,\"polygonStrokeOpacity\":1,\"polygonStrokeWeight\":1,\"zoomOnClick\":true,\"showCoverageOnHover\":true,\"animate\":true,\"maxClusterRadius\":80,\"removeOutsideVisibleBounds\":true,\"defaultZoomLevel\":5,\"provider\":\"openstreet-map\",\"draggableMarker\":true,\"editablePolygon\":true,\"mapPageSize\":16384,\"showPolygon\":false,\"polygonTooltipPattern\":\"<b>${entityName}</b><br/><br/><b>TimeStamp:</b> ${coordinates|ts:7}<br/><br/><link-act name='delete'>Delete</link-act>\"},\"title\":\"Markers Placement - OpenStreetMap\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{\"tooltipAction\":[{\"name\":\"delete\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id;\\n });\\n\\nwidgetContext.map.setMarkerLocation(entityDatasource[0], null, null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"54c293c4-9ca6-e34f-dc6a-0271944c1c66\"},{\"name\":\"delete_polygon\",\"icon\":\"more_horiz\",\"type\":\"custom\",\"customFunction\":\"var entityDatasource = widgetContext.map.map.datasources.filter(\\n function(entity) {\\n return entity.entityId === entityId.id\\n });\\n\\nwidgetContext.map.savePolygonLocation(entityDatasource[0], null).subscribe(() => widgetContext.updateAliases());\",\"id\":\"6beb7bed-dfd8-388d-b60c-82988ab52f06\"}]},\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"displayTimewindow\":true}"
}, },
"tags": [ "tags": [

4
application/src/main/data/json/system/widget_types/openstreet_map.json

File diff suppressed because one or more lines are too long

2
application/src/main/data/json/system/widget_types/route_map___google.json

@ -1,7 +1,7 @@
{ {
"fqn": "maps_v2.route_map", "fqn": "maps_v2.route_map",
"name": "Route Map - Google", "name": "Route Map - Google",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/route_map_google_system_widget_image.png", "image": "tb-image;/api/images/system/route_map_google_system_widget_image.png",
"description": "Visualize the entity trip on Google Maps. Allows to visualize location history. Use the Trip Animation widget for advanced features.", "description": "Visualize the entity trip on Google Maps. Allows to visualize location history. Use the Trip Animation widget for advanced features.",
"descriptor": { "descriptor": {

2
application/src/main/data/json/system/widget_types/route_map___openstreet.json

@ -1,7 +1,7 @@
{ {
"fqn": "maps_v2.route_map_openstreetmap", "fqn": "maps_v2.route_map_openstreetmap",
"name": "Route Map - OpenStreet", "name": "Route Map - OpenStreet",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/route_map_openstreet_system_widget_image.png", "image": "tb-image;/api/images/system/route_map_openstreet_system_widget_image.png",
"description": "Visualize the entity trip on OpenStreetMap. Allows to visualize location history. Use the Trip Animation widget for advanced features.", "description": "Visualize the entity trip on OpenStreetMap. Allows to visualize location history. Use the Trip Animation widget for advanced features.",
"descriptor": { "descriptor": {

2
application/src/main/data/json/system/widget_types/route_map___tencent.json

@ -1,7 +1,7 @@
{ {
"fqn": "maps_v2.route_map_tencent_maps", "fqn": "maps_v2.route_map_tencent_maps",
"name": "Route Map - Tencent", "name": "Route Map - Tencent",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/route_map_tencent_system_widget_image.png", "image": "tb-image;/api/images/system/route_map_tencent_system_widget_image.png",
"description": "Visualize the entity trip on Tencent Maps. Allows to visualize location history. Use the Trip Animation widget for advanced features.", "description": "Visualize the entity trip on Tencent Maps. Allows to visualize location history. Use the Trip Animation widget for advanced features.",
"descriptor": { "descriptor": {

4
application/src/main/data/json/system/widget_types/tencent_map.json

File diff suppressed because one or more lines are too long

2
application/src/main/data/json/system/widget_types/trip_animation.json

@ -1,7 +1,7 @@
{ {
"fqn": "maps_v2.test", "fqn": "maps_v2.test",
"name": "Trip Animation", "name": "Trip Animation",
"deprecated": false, "deprecated": true,
"image": "tb-image;/api/images/system/trip_animation_system_widget_image.png", "image": "tb-image;/api/images/system/trip_animation_system_widget_image.png",
"description": "Displays the trip of the entity on the OpenStreetMap or other map providers. Allows to scroll and animate the movement of the entity. Highly customizable via custom markers, marker tooltips, and widget actions.", "description": "Displays the trip of the entity on the OpenStreetMap or other map providers. Allows to scroll and animate the movement of the entity. Highly customizable via custom markers, marker tooltips, and widget actions.",
"descriptor": { "descriptor": {

10
ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts

@ -146,6 +146,7 @@ import { ScadaSymbolBasicConfigComponent } from '@home/components/widget/config/
import { import {
SegmentedButtonBasicConfigComponent SegmentedButtonBasicConfigComponent
} from '@home/components/widget/config/basic/button/segmented-button-basic-config.component'; } from '@home/components/widget/config/basic/button/segmented-button-basic-config.component';
import { MapBasicConfigComponent } from '@home/components/widget/config/basic/map/map-basic-config.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -195,7 +196,8 @@ import {
LabelCardBasicConfigComponent, LabelCardBasicConfigComponent,
LabelValueCardBasicConfigComponent, LabelValueCardBasicConfigComponent,
UnreadNotificationBasicConfigComponent, UnreadNotificationBasicConfigComponent,
ScadaSymbolBasicConfigComponent ScadaSymbolBasicConfigComponent,
MapBasicConfigComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -247,7 +249,8 @@ import {
MobileAppQrCodeBasicConfigComponent, MobileAppQrCodeBasicConfigComponent,
LabelCardBasicConfigComponent, LabelCardBasicConfigComponent,
LabelValueCardBasicConfigComponent, LabelValueCardBasicConfigComponent,
UnreadNotificationBasicConfigComponent UnreadNotificationBasicConfigComponent,
MapBasicConfigComponent
] ]
}) })
export class BasicWidgetConfigModule { export class BasicWidgetConfigModule {
@ -293,5 +296,6 @@ export const basicWidgetConfigComponentsMap: {[key: string]: Type<IBasicWidgetCo
'tb-label-card-basic-config': LabelCardBasicConfigComponent, 'tb-label-card-basic-config': LabelCardBasicConfigComponent,
'tb-label-value-card-basic-config': LabelValueCardBasicConfigComponent, 'tb-label-value-card-basic-config': LabelValueCardBasicConfigComponent,
'tb-unread-notification-basic-config': UnreadNotificationBasicConfigComponent, 'tb-unread-notification-basic-config': UnreadNotificationBasicConfigComponent,
'tb-scada-symbol-basic-config': ScadaSymbolBasicConfigComponent 'tb-scada-symbol-basic-config': ScadaSymbolBasicConfigComponent,
'tb-map-basic-config': MapBasicConfigComponent
}; };

91
ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.html

@ -0,0 +1,91 @@
<!--
Copyright © 2016-2024 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.
-->
<ng-container [formGroup]="mapWidgetConfigForm">
<tb-map-settings formControlName="mapSettings"></tb-map-settings>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.appearance</div>
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showTitle">
{{ 'widget-config.title' | translate }}
</mat-slide-toggle>
<div class="flex flex-1 flex-row items-center justify-start gap-2">
<mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="title" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-font-settings formControlName="titleFont"
clearButton
[previewText]="mapWidgetConfigForm.get('title').value"
[initialPreviewStyle]="widgetConfig.config.titleStyle">
</tb-font-settings>
<tb-color-input asBoxInput
colorClearButton
formControlName="titleColor">
</tb-color-input>
</div>
</div>
<div class="tb-form-row column-xs">
<mat-slide-toggle class="mat-slide fixed-title-width" formControlName="showIcon">
{{ 'widget-config.card-icon' | translate }}
</mat-slide-toggle>
<div class="flex flex-1 flex-row items-center justify-start gap-2">
<mat-form-field appearance="outline" class="number flex" subscriptSizing="dynamic">
<input matInput type="number" min="0" formControlName="iconSize" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
<tb-css-unit-select class="flex-1" formControlName="iconSizeUnit"></tb-css-unit-select>
<tb-material-icon-select asBoxInput
iconClearButton
[color]="mapWidgetConfigForm.get('iconColor').value"
formControlName="icon">
</tb-material-icon-select>
<tb-color-input asBoxInput
colorClearButton
formControlName="iconColor">
</tb-color-input>
</div>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
<div class="tb-form-row space-between">
<div>{{ 'widgets.background.background' | translate }}</div>
<tb-background-settings formControlName="background">
</tb-background-settings>
</div>
<div class="tb-form-row space-between column-lt-md">
<div translate>widget-config.show-card-buttons</div>
<mat-chip-listbox multiple formControlName="cardButtons">
<mat-chip-option value="fullscreen">{{ 'fullscreen.fullscreen' | translate }}</mat-chip-option>
</mat-chip-listbox>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.card-border-radius' | translate }}</div>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.card-padding' | translate }}</div>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
</div>
<tb-widget-actions-panel
formControlName="actions">
</tb-widget-actions-panel>
</ng-container>

150
ui-ngx/src/app/modules/home/components/widget/config/basic/map/map-basic-config.component.ts

@ -0,0 +1,150 @@
///
/// Copyright © 2016-2024 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, Injector } from '@angular/core';
import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { WidgetConfigComponent } from '@home/components/widget/widget-config.component';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { WidgetConfigComponentData } from '@home/models/widget-component.models';
import { isUndefined, mergeDeep } from '@core/utils';
import { mapWidgetDefaultSettings, MapWidgetSettings } from '@home/components/widget/lib/maps/map-widget.models';
import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models';
import { WidgetConfig } from '@shared/models/widget.models';
@Component({
selector: 'tb-map-basic-config',
templateUrl: './map-basic-config.component.html',
styleUrls: ['../basic-config.scss']
})
export class MapBasicConfigComponent extends BasicWidgetConfigComponent {
mapWidgetConfigForm: UntypedFormGroup;
constructor(protected store: Store<AppState>,
protected widgetConfigComponent: WidgetConfigComponent,
private $injector: Injector,
private fb: UntypedFormBuilder) {
super(store, widgetConfigComponent);
}
protected configForm(): UntypedFormGroup {
return this.mapWidgetConfigForm;
}
protected onConfigSet(configData: WidgetConfigComponentData) {
const settings: MapWidgetSettings = mergeDeep<MapWidgetSettings>({} as MapWidgetSettings,
mapWidgetDefaultSettings, configData.config.settings as MapWidgetSettings);
const iconSize = resolveCssSize(configData.config.iconSize);
this.mapWidgetConfigForm = this.fb.group({
mapSettings: [settings, []],
showTitle: [configData.config.showTitle, []],
title: [configData.config.title, []],
titleFont: [configData.config.titleFont, []],
titleColor: [configData.config.titleColor, []],
showIcon: [configData.config.showTitleIcon, []],
iconSize: [iconSize[0], [Validators.min(0)]],
iconSizeUnit: [iconSize[1], []],
icon: [configData.config.titleIcon, []],
iconColor: [configData.config.iconColor, []],
background: [settings.background, []],
cardButtons: [this.getCardButtons(configData.config), []],
borderRadius: [configData.config.borderRadius, []],
padding: [settings.padding, []],
actions: [configData.config.actions || {}, []]
});
}
protected prepareOutputConfig(config: any): WidgetConfigComponentData {
this.widgetConfig.config.settings = config.mapSettings || {};
this.widgetConfig.config.showTitle = config.showTitle;
this.widgetConfig.config.title = config.title;
this.widgetConfig.config.titleFont = config.titleFont;
this.widgetConfig.config.titleColor = config.titleColor;
this.widgetConfig.config.showTitleIcon = config.showIcon;
this.widgetConfig.config.iconSize = cssSizeToStrSize(config.iconSize, config.iconSizeUnit);
this.widgetConfig.config.titleIcon = config.icon;
this.widgetConfig.config.iconColor = config.iconColor;
this.widgetConfig.config.settings.background = config.background;
this.setCardButtons(config.cardButtons, this.widgetConfig.config);
this.widgetConfig.config.borderRadius = config.borderRadius;
this.widgetConfig.config.settings.padding = config.padding;
this.widgetConfig.config.actions = config.actions;
return this.widgetConfig;
}
protected validatorTriggers(): string[] {
return ['showTitle', 'showIcon'];
}
protected updateValidators(emitEvent: boolean, trigger?: string) {
const showTitle: boolean = this.mapWidgetConfigForm.get('showTitle').value;
const showIcon: boolean = this.mapWidgetConfigForm.get('showIcon').value;
if (showTitle) {
this.mapWidgetConfigForm.get('title').enable();
this.mapWidgetConfigForm.get('titleFont').enable();
this.mapWidgetConfigForm.get('titleColor').enable();
this.mapWidgetConfigForm.get('showIcon').enable({emitEvent: false});
if (showIcon) {
this.mapWidgetConfigForm.get('iconSize').enable();
this.mapWidgetConfigForm.get('iconSizeUnit').enable();
this.mapWidgetConfigForm.get('icon').enable();
this.mapWidgetConfigForm.get('iconColor').enable();
} else {
this.mapWidgetConfigForm.get('iconSize').disable();
this.mapWidgetConfigForm.get('iconSizeUnit').disable();
this.mapWidgetConfigForm.get('icon').disable();
this.mapWidgetConfigForm.get('iconColor').disable();
}
} else {
this.mapWidgetConfigForm.get('title').disable();
this.mapWidgetConfigForm.get('titleFont').disable();
this.mapWidgetConfigForm.get('titleColor').disable();
this.mapWidgetConfigForm.get('showIcon').disable({emitEvent: false});
this.mapWidgetConfigForm.get('iconSize').disable();
this.mapWidgetConfigForm.get('iconSizeUnit').disable();
this.mapWidgetConfigForm.get('icon').disable();
this.mapWidgetConfigForm.get('iconColor').disable();
}
}
private getCardButtons(config: WidgetConfig): string[] {
const buttons: string[] = [];
if (isUndefined(config.enableFullscreen) || config.enableFullscreen) {
buttons.push('fullscreen');
}
return buttons;
}
private setCardButtons(buttons: string[], config: WidgetConfig) {
config.enableFullscreen = buttons.includes('fullscreen');
}
}

61
ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet/leaflet-tb.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { TB } from 'leaflet'; import L, { Coords, TB, TileLayerOptions } from 'leaflet';
class SidebarControl extends L.Control<TB.SidebarControlOptions> { class SidebarControl extends L.Control<TB.SidebarControlOptions> {
@ -195,6 +195,7 @@ class LayersControl extends SidebarPaneControl<TB.LayersControlOptions> {
layers.forEach((other) => { layers.forEach((other) => {
if (other.layer === layerData.layer) { if (other.layer === layerData.layer) {
map.addLayer(other.layer); map.addLayer(other.layer);
map.attributionControl.setPrefix(other.attributionPrefix);
} else { } else {
map.removeLayer(other.layer); map.removeLayer(other.layer);
} }
@ -225,11 +226,67 @@ const layers = (options: TB.LayersControlOptions): LayersControl => {
return new LayersControl(options); return new LayersControl(options);
} }
class ChinaProvider extends L.TileLayer {
static chinaProviders: L.TB.TileLayer.ChinaProvidersData = {
Tencent: {
Normal: "//rt{s}.map.gtimg.com/tile?z={z}&x={x}&y={-y}&type=vector&styleid=3",
Satellite: "//p{s}.map.gtimg.com/sateTiles/{z}/{sx}/{sy}/{x}_{-y}.jpg",
Terrain: "//p{s}.map.gtimg.com/demTiles/{z}/{sx}/{sy}/{x}_{-y}.jpg",
Subdomains: '0123',
}
};
constructor(type: string, options?: TileLayerOptions) {
options = options || {};
const parts = type.split('.');
const providerName = parts[0];
const mapName = parts[1];
const url = ChinaProvider.chinaProviders[providerName][mapName];
options.subdomains = ChinaProvider.chinaProviders[providerName].Subdomains;
super(url, options);
}
getTileUrl(coords: Coords): string {
const data = {
s: this._getSubdomain(coords),
x: coords.x,
y: coords.y,
z: this._getZoomForUrl(),
sx: null,
sy: null
};
if (this._map && !this._map.options.crs.infinite) {
const invertedY = this._globalTileRange.max.y - coords.y;
if (this.options.tms) {
data['y'] = invertedY;
}
data['-y'] = invertedY;
}
data.sx = data.x >> 4;
data.sy = (( 1 << data.z) - data.y) >> 4;
return L.Util.template(this._url, L.Util.extend(data, this.options));
}
}
const chinaProvider = (type: string, options?: TileLayerOptions): ChinaProvider => {
return new ChinaProvider(type, options);
}
L.TB = L.TB || { L.TB = L.TB || {
SidebarControl, SidebarControl,
SidebarPaneControl, SidebarPaneControl,
LayersControl, LayersControl,
sidebar, sidebar,
sidebarPane, sidebarPane,
layers layers,
TileLayer: {
ChinaProvider
},
tileLayer: {
chinaProvider
}
} }

179
ui-ngx/src/app/modules/home/components/widget/lib/maps/map-layer.ts

@ -15,10 +15,21 @@
/// ///
import { import {
CustomMapLayerSettings, defaultCustomMapLayerSettings,
defaultGoogleMapLayerSettings, defaultHereMapLayerSettings,
defaultOpenStreetMapLayerSettings, defaultOpenStreetMapLayerSettings,
defaultTencentMapLayerSettings,
GoogleLayerType,
GoogleMapLayerSettings,
googleMapLayerTranslationMap, hereLayerTranslationMap, HereLayerType, HereMapLayerSettings,
MapLayerSettings, MapLayerSettings,
MapProvider, OpenStreetLayerType, MapProvider,
OpenStreetMapLayerSettings, openStreetMapLayerTranslationMap OpenStreetLayerType,
OpenStreetMapLayerSettings,
openStreetMapLayerTranslationMap,
tencentLayerTranslationMap,
TencentLayerType,
TencentMapLayerSettings
} from '@home/components/widget/lib/maps/map.models'; } from '@home/components/widget/lib/maps/map.models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { DeepPartial } from '@shared/models/common'; import { DeepPartial } from '@shared/models/common';
@ -26,7 +37,8 @@ import { mergeDeep } from '@core/utils';
import { Observable, of, switchMap } from 'rxjs'; import { Observable, of, switchMap } from 'rxjs';
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
import L from 'leaflet'; import L from 'leaflet';
import { map } from 'rxjs/operators'; import { catchError, map } from 'rxjs/operators';
import { ResourcesService } from '@core/services/resources.service';
export abstract class TbMapLayer<S extends MapLayerSettings> { export abstract class TbMapLayer<S extends MapLayerSettings> {
@ -35,15 +47,15 @@ export abstract class TbMapLayer<S extends MapLayerSettings> {
switch (inputSettings.provider) { switch (inputSettings.provider) {
case MapProvider.google: case MapProvider.google:
break; return new TbGoogleMapLayer(ctx, inputSettings);
case MapProvider.openstreet: case MapProvider.openstreet:
return new TbOpenStreetMapLayer(ctx, inputSettings); return new TbOpenStreetMapLayer(ctx, inputSettings);
case MapProvider.tencent: case MapProvider.tencent:
break; return new TbTencentMapLayer(ctx, inputSettings);
case MapProvider.here: case MapProvider.here:
break; return new TbHereMapLayer(ctx, inputSettings);
case MapProvider.custom: case MapProvider.custom:
break; return new TbCustomMapLayer(ctx, inputSettings);
} }
} }
@ -69,22 +81,85 @@ export abstract class TbMapLayer<S extends MapLayerSettings> {
protected abstract createLayer(): Observable<L.Layer>; protected abstract createLayer(): Observable<L.Layer>;
public loadLayer(): Observable<L.TB.LayerData> { public loadLayer(theMap: L.Map): Observable<L.TB.LayerData> {
return this.createLayer().pipe( return this.createLayer().pipe(
switchMap((layer) => { switchMap((layer) => {
return this.createLayer().pipe( if (layer) {
map((mini) => { return this.createLayer().pipe(
return { map((mini) => {
title: this.title(), if (mini) {
layer, const attribution = layer.getAttribution();
mini const attributionPrefix = attribution ? theMap.attributionControl.options.prefix as string : null;
}; return {
}) title: this.title(),
); attributionPrefix: attributionPrefix,
layer,
mini
};
} else {
return null;
}
})
);
} else {
return of(null);
}
})
);
}
}
class TbGoogleMapLayer extends TbMapLayer<GoogleMapLayerSettings> {
static loadedApiKeysGlobal: {[key: string]: boolean} = {};
constructor(protected ctx: WidgetContext,
protected inputSettings: DeepPartial<MapLayerSettings>) {
super(ctx, inputSettings);
}
protected defaultSettings(): GoogleMapLayerSettings {
return defaultGoogleMapLayerSettings;
}
protected generateTitle(): string {
const layerType = GoogleLayerType[this.settings.layerType];
return this.ctx.translate.instant(googleMapLayerTranslationMap.get(layerType));
}
protected createLayer(): Observable<L.Layer> {
return this.loadGoogle().pipe(
map((loaded) => {
if (loaded) {
return (L.gridLayer as any).googleMutant({
type: this.settings.layerType
});
} else {
return null;
}
}) })
); );
} }
private loadGoogle(): Observable<boolean> {
const apiKey = this.settings.apiKey;
if (TbGoogleMapLayer.loadedApiKeysGlobal[apiKey]) {
return of(true);
} else {
const resourceService = this.ctx.$injector.get(ResourcesService);
return resourceService.loadResource(`https://maps.googleapis.com/maps/api/js?key=${apiKey}`).pipe(
map(() => {
TbGoogleMapLayer.loadedApiKeysGlobal[apiKey] = true;
return true;
}),
catchError((e) => {
TbGoogleMapLayer.loadedApiKeysGlobal[apiKey] = false;
console.error(`Google map api load failed!`, e);
return of(false);
})
);
}
}
} }
class TbOpenStreetMapLayer extends TbMapLayer<OpenStreetMapLayerSettings> { class TbOpenStreetMapLayer extends TbMapLayer<OpenStreetMapLayerSettings> {
@ -109,3 +184,73 @@ class TbOpenStreetMapLayer extends TbMapLayer<OpenStreetMapLayerSettings> {
} }
} }
class TbTencentMapLayer extends TbMapLayer<TencentMapLayerSettings> {
constructor(protected ctx: WidgetContext,
protected inputSettings: DeepPartial<MapLayerSettings>) {
super(ctx, inputSettings);
}
protected defaultSettings(): TencentMapLayerSettings {
return defaultTencentMapLayerSettings;
}
protected generateTitle(): string {
const layerType = TencentLayerType[this.settings.layerType];
return this.ctx.translate.instant(tencentLayerTranslationMap.get(layerType));
}
protected createLayer(): Observable<L.Layer> {
const layer = L.TB.tileLayer.chinaProvider(TencentLayerType[this.settings.layerType], {
attribution: '&copy;2024 Tencent - GS(2023)1171号'
});
return of(layer);
}
}
class TbHereMapLayer extends TbMapLayer<HereMapLayerSettings> {
constructor(protected ctx: WidgetContext,
protected inputSettings: DeepPartial<MapLayerSettings>) {
super(ctx, inputSettings);
}
protected defaultSettings(): HereMapLayerSettings {
return defaultHereMapLayerSettings;
}
protected generateTitle(): string {
const layerType = HereLayerType[this.settings.layerType];
return this.ctx.translate.instant(hereLayerTranslationMap.get(layerType));
}
protected createLayer(): Observable<L.Layer> {
const layer = L.tileLayer.provider(HereLayerType[this.settings.layerType], {useV3: true, apiKey: this.settings.apiKey} as any);
return of(layer);
}
}
class TbCustomMapLayer extends TbMapLayer<CustomMapLayerSettings> {
constructor(protected ctx: WidgetContext,
protected inputSettings: DeepPartial<MapLayerSettings>) {
super(ctx, inputSettings);
}
protected defaultSettings(): CustomMapLayerSettings {
return defaultCustomMapLayerSettings;
}
protected generateTitle(): string {
return this.ctx.translate.instant('widgets.maps.custom');
}
protected createLayer(): Observable<L.Layer> {
const layer = L.tileLayer(this.settings.tileUrl);
return of(layer);
}
}

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

@ -152,6 +152,15 @@ export enum GoogleLayerType {
terrain = 'terrain' terrain = 'terrain'
} }
export const googleMapLayerTranslationMap = new Map<GoogleLayerType, string>(
[
[GoogleLayerType.roadmap, 'widgets.maps.google-map-type-roadmap'],
[GoogleLayerType.satellite, 'widgets.maps.google-map-type-satelite'],
[GoogleLayerType.hybrid, 'widgets.maps.google-map-type-hybrid'],
[GoogleLayerType.terrain, 'widgets.maps.google-map-type-terrain']
]
);
export interface GoogleMapLayerSettings extends MapLayerSettings { export interface GoogleMapLayerSettings extends MapLayerSettings {
provider: MapProvider.google; provider: MapProvider.google;
layerType: GoogleLayerType; layerType: GoogleLayerType;
@ -197,12 +206,21 @@ export const defaultOpenStreetMapLayerSettings: OpenStreetMapLayerSettings = {
} }
export enum HereLayerType { export enum HereLayerType {
hereNormalDay = 'HERE.normalDay', hereNormalDay = 'HEREv3.normalDay',
hereNormalNight = 'HERE.normalNight', hereNormalNight = 'HEREv3.normalNight',
hereHybridDay = 'HERE.hybridDay', hereHybridDay = 'HEREv3.hybridDay',
hereTerrainDay = 'HERE.terrainDay' hereTerrainDay = 'HEREv3.terrainDay'
} }
export const hereLayerTranslationMap = new Map<HereLayerType, string>(
[
[HereLayerType.hereNormalDay, 'widgets.maps.here-map-normal-day'],
[HereLayerType.hereNormalNight, 'widgets.maps.here-map-normal-night'],
[HereLayerType.hereHybridDay, 'widgets.maps.here-map-hybrid-day'],
[HereLayerType.hereTerrainDay, 'widgets.maps.here-map-terrain-day']
]
);
export interface HereMapLayerSettings extends MapLayerSettings { export interface HereMapLayerSettings extends MapLayerSettings {
provider: MapProvider.here; provider: MapProvider.here;
layerType: HereLayerType; layerType: HereLayerType;
@ -216,21 +234,27 @@ export const defaultHereMapLayerSettings: HereMapLayerSettings = {
} }
export enum TencentLayerType { export enum TencentLayerType {
roadmap = 'roadmap', tencentNormal = 'Tencent.Normal',
satellite = 'satellite', tencentSatellite = 'Tencent.Satellite',
hybrid = 'hybrid' tencentTerrain = 'Tencent.Terrain'
} }
export const tencentLayerTranslationMap = new Map<TencentLayerType, string>(
[
[TencentLayerType.tencentNormal, 'widgets.maps.tencent-provider-normal'],
[TencentLayerType.tencentSatellite, 'widgets.maps.tencent-provider-satellite'],
[TencentLayerType.tencentTerrain, 'widgets.maps.tencent-provider-terrain']
]
);
export interface TencentMapLayerSettings extends MapLayerSettings { export interface TencentMapLayerSettings extends MapLayerSettings {
provider: MapProvider.tencent; provider: MapProvider.tencent;
layerType: TencentLayerType layerType: TencentLayerType
apiKey: string;
} }
export const defaultTencentMapLayerSettings: TencentMapLayerSettings = { export const defaultTencentMapLayerSettings: TencentMapLayerSettings = {
provider: MapProvider.tencent, provider: MapProvider.tencent,
layerType: TencentLayerType.roadmap, layerType: TencentLayerType.tencentNormal
apiKey: '84d6d83e0e51e481e50454ccbe8986b'
} }
export interface CustomMapLayerSettings extends MapLayerSettings { export interface CustomMapLayerSettings extends MapLayerSettings {
@ -261,7 +285,33 @@ export const defaultMapLayerSettings = (provider: MapProvider): MapLayerSettings
export const defaultMapLayers: MapLayerSettings[] = (Object.keys(OpenStreetLayerType) as OpenStreetLayerType[]).map(type => ({ export const defaultMapLayers: MapLayerSettings[] = (Object.keys(OpenStreetLayerType) as OpenStreetLayerType[]).map(type => ({
provider: MapProvider.openstreet, provider: MapProvider.openstreet,
layerType: type layerType: type
})); } as MapLayerSettings)).concat((Object.keys(GoogleLayerType) as GoogleLayerType[]).map(type =>
mergeDeep({} as MapLayerSettings, defaultGoogleMapLayerSettings, {layerType: type} as GoogleMapLayerSettings)).concat(
(Object.keys(TencentLayerType) as TencentLayerType[]).map(type => ({
provider: MapProvider.tencent,
layerType: type
} as MapLayerSettings))
)).concat(
(Object.keys(HereLayerType) as HereLayerType[]).map(type =>
mergeDeep({} as MapLayerSettings, defaultHereMapLayerSettings, {layerType: type} as HereMapLayerSettings))
).concat([
mergeDeep({} as MapLayerSettings, defaultCustomMapLayerSettings, {label: 'Custom 1'} as CustomMapLayerSettings),
mergeDeep({} as MapLayerSettings, defaultCustomMapLayerSettings, {
tileUrl: 'http://a.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png',
label: 'Custom 2'
} as CustomMapLayerSettings),
mergeDeep({} as MapLayerSettings, defaultCustomMapLayerSettings, {
tileUrl: 'http://b.tile2.opencyclemap.org/transport/{z}/{x}/{y}.png',
label: 'Custom 3'
} as CustomMapLayerSettings)
]);
/*
(Object.keys(OpenStreetLayerType) as OpenStreetLayerType[]).map(type => ({
provider: MapProvider.openstreet,
layerType: type
} as MapLayerSettings)).concat(
(Object.keys(GoogleLayerType) as GoogleLayerType[]).map(type =>
mergeDeep({} as GoogleMapLayerSettings, defaultGoogleMapLayerSettings, {layerType: type} as GoogleMapLayerSettings)));*/
export interface GeoMapSettings extends BaseMapSettings { export interface GeoMapSettings extends BaseMapSettings {
layers?: MapLayerSettings[]; layers?: MapLayerSettings[];

3
ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss

@ -96,6 +96,9 @@
inset: 2px; inset: 2px;
border-radius: 2px; border-radius: 2px;
z-index: 0; z-index: 0;
.leaflet-control-attribution {
display: none;
}
} }
input.tb-layer-button { input.tb-layer-button {
position: absolute; position: absolute;

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

@ -32,7 +32,7 @@ import { DeepPartial } from '@shared/models/common';
import L from 'leaflet'; import L from 'leaflet';
import { forkJoin, Observable, of } from 'rxjs'; import { forkJoin, Observable, of } from 'rxjs';
import { TbMapLayer } from '@home/components/widget/lib/maps/map-layer'; import { TbMapLayer } from '@home/components/widget/lib/maps/map-layer';
import { switchMap, tap } from 'rxjs/operators'; import { map, switchMap, tap } from 'rxjs/operators';
import '@home/components/widget/lib/maps/leaflet/leaflet-tb'; import '@home/components/widget/lib/maps/leaflet/leaflet-tb';
export abstract class TbMap<S extends BaseMapSettings> { export abstract class TbMap<S extends BaseMapSettings> {
@ -165,10 +165,11 @@ class TbGeoMap extends TbMap<GeoMapSettings> {
protected doSetupControls(): Observable<any> { protected doSetupControls(): Observable<any> {
return this.loadLayers().pipe( return this.loadLayers().pipe(
tap((layers) => { tap((layers: L.TB.LayerData[]) => {
if (layers.length) { if (layers.length) {
const layer = layers[0]; const layer = layers[0];
layer.layer.addTo(this.map); layer.layer.addTo(this.map);
this.map.attributionControl.setPrefix(layer.attributionPrefix);
if (layers.length > 1) { if (layers.length > 1) {
const sidebar = L.TB.sidebar({ const sidebar = L.TB.sidebar({
container: $(this.containerElement), container: $(this.containerElement),
@ -192,7 +193,11 @@ class TbGeoMap extends TbMap<GeoMapSettings> {
private loadLayers(): Observable<L.TB.LayerData[]> { private loadLayers(): Observable<L.TB.LayerData[]> {
const layers = this.settings.layers.map(settings => TbMapLayer.fromSettings(this.ctx, settings)); const layers = this.settings.layers.map(settings => TbMapLayer.fromSettings(this.ctx, settings));
return forkJoin(layers.map(layer => layer.loadLayer())); return forkJoin(layers.map(layer => layer.loadLayer(this.map))).pipe(
map((layersData) => {
return layersData.filter(l => l !== null);
})
);
} }

43
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.html

@ -0,0 +1,43 @@
<!--
Copyright © 2016-2024 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.
-->
<ng-container [formGroup]="mapSettingsFormGroup">
<div class="tb-form-panel">
<div class="flex flex-row items-center justify-between">
<div class="tb-form-panel-title">
{{ 'widgets.maps.map-type' | translate }}
</div>
<tb-toggle-select formControlName="mapType">
<tb-toggle-option [value]="MapType.geoMap">{{ 'widgets.maps.map-type-map' | translate }}</tb-toggle-option>
<tb-toggle-option [value]="MapType.image">{{ 'widgets.maps.map-type-image' | translate }}</tb-toggle-option>
</tb-toggle-select>
</div>
</div>
<div class="tb-form-panel">
<div class="flex flex-row items-center justify-between">
<div class="tb-form-panel-title">
{{ 'widgets.maps.overlays' | translate }}
</div>
<tb-toggle-select [(ngModel)]="overlaysMode"
[ngModelOptions]="{ standalone: true }">
<tb-toggle-option value="markers">{{ 'widgets.maps.markers' | translate }}</tb-toggle-option>
<tb-toggle-option value="polygons">{{ 'widgets.maps.polygons' | translate }}</tb-toggle-option>
<tb-toggle-option value="circles">{{ 'widgets.maps.circles' | translate }}</tb-toggle-option>
</tb-toggle-select>
</div>
</div>
</ng-container>

141
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts

@ -0,0 +1,141 @@
///
/// Copyright © 2016-2024 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, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { ImageSourceType, MapSetting, MapType } from '@home/components/widget/lib/maps/map.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { merge } from 'rxjs';
@Component({
selector: 'tb-map-settings',
templateUrl: './map-settings.component.html',
styleUrls: ['./../../widget-settings.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MapSettingsComponent),
multi: true
}
]
})
export class MapSettingsComponent implements OnInit, ControlValueAccessor {
MapType = MapType;
@Input()
disabled: boolean;
private modelValue: MapSetting;
private propagateChange = null;
public mapSettingsFormGroup: UntypedFormGroup;
overlaysMode: 'markers' | 'polygons' | 'circles' = 'markers';
constructor(private fb: UntypedFormBuilder,
private destroyRef: DestroyRef) {
}
ngOnInit(): void {
this.mapSettingsFormGroup = this.fb.group({
mapType: [null, []],
layers: [null, []],
imageSourceType: [null, []],
imageUrl: [null, []],
imageEntityAlias: [null, []],
imageUrlAttribute: [null, []],
markers: [null, []],
polygons: [null, []],
circles: [null, []],
additionalDataSources: [null, []],
controlsPosition: [null, []],
zoomActions: [null, []],
fitMapBounds: [null, []],
useDefaultCenterPosition: [null, []],
defaultCenterPosition: [null, []],
defaultZoomLevel: [null, []],
mapPageSize: [null, []]
});
this.mapSettingsFormGroup.valueChanges.pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe(() => {
this.updateModel();
});
merge(this.mapSettingsFormGroup.get('mapType').valueChanges,
this.mapSettingsFormGroup.get('imageSourceType').valueChanges
).pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe(() => {
this.updateValidators();
});
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(_fn: any): void {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (isDisabled) {
this.mapSettingsFormGroup.disable({emitEvent: false});
} else {
this.mapSettingsFormGroup.enable({emitEvent: false});
this.updateValidators();
}
}
writeValue(value: MapSetting): void {
this.modelValue = value;
this.mapSettingsFormGroup.patchValue(
value, {emitEvent: false}
);
this.updateValidators();
}
private updateValidators() {
const mapType: MapType = this.mapSettingsFormGroup.get('mapType').value;
const imageSourceType: ImageSourceType = this.mapSettingsFormGroup.get('imageSourceType').value;
if (mapType === MapType.geoMap) {
this.mapSettingsFormGroup.get('layers').enable({emitEvent: false});
this.mapSettingsFormGroup.get('imageSourceType').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageUrl').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageEntityAlias').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageUrlAttribute').disable({emitEvent: false});
} else {
this.mapSettingsFormGroup.get('layers').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageSourceType').enable({emitEvent: false});
if (imageSourceType === ImageSourceType.image) {
this.mapSettingsFormGroup.get('imageUrl').enable({emitEvent: false});
this.mapSettingsFormGroup.get('imageEntityAlias').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageUrlAttribute').disable({emitEvent: false});
} else {
this.mapSettingsFormGroup.get('imageUrl').disable({emitEvent: false});
this.mapSettingsFormGroup.get('imageEntityAlias').enable({emitEvent: false});
this.mapSettingsFormGroup.get('imageUrlAttribute').enable({emitEvent: false});
}
}
}
private updateModel() {
this.modelValue = this.mapSettingsFormGroup.getRawValue();
this.propagateChange(this.modelValue);
}
}

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

@ -183,6 +183,7 @@ import {
import { import {
DynamicFormArrayComponent DynamicFormArrayComponent
} from '@home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component'; } from '@home/components/widget/lib/settings/common/dynamic-form/dynamic-form-array.component';
import { MapSettingsComponent } from '@home/components/widget/lib/settings/common/map/map-settings.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -252,7 +253,8 @@ import {
DynamicFormSelectItemsComponent, DynamicFormSelectItemsComponent,
DynamicFormSelectItemRowComponent, DynamicFormSelectItemRowComponent,
DynamicFormComponent, DynamicFormComponent,
DynamicFormArrayComponent DynamicFormArrayComponent,
MapSettingsComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -326,7 +328,8 @@ import {
DynamicFormSelectItemsComponent, DynamicFormSelectItemsComponent,
DynamicFormSelectItemRowComponent, DynamicFormSelectItemRowComponent,
DynamicFormComponent, DynamicFormComponent,
DynamicFormArrayComponent DynamicFormArrayComponent,
MapSettingsComponent
], ],
providers: [ providers: [
ColorSettingsComponentService, ColorSettingsComponentService,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/circle-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.ts

@ -41,7 +41,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-circle-settings', selector: 'tb-circle-settings',
templateUrl: './circle-settings.component.html', templateUrl: './circle-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/common-map-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/common-map-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/common-map-settings.component.ts

@ -36,7 +36,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-common-map-settings', selector: 'tb-common-map-settings',
templateUrl: './common-map-settings.component.html', templateUrl: './common-map-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/datasources-key-autocomplete.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.html

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/datasources-key-autocomplete.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component.ts

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/google-map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/google-map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component.ts

@ -39,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-google-map-provider-settings', selector: 'tb-google-map-provider-settings',
templateUrl: './google-map-provider-settings.component.html', templateUrl: './google-map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/here-map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/here-map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component.ts

@ -40,7 +40,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-here-map-provider-settings', selector: 'tb-here-map-provider-settings',
templateUrl: './here-map-provider-settings.component.html', templateUrl: './here-map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component.ts

@ -40,7 +40,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-image-map-provider-settings', selector: 'tb-image-map-provider-settings',
templateUrl: './image-map-provider-settings.component.html', templateUrl: './image-map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-editor-settings.component.ts

@ -35,7 +35,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-map-editor-settings', selector: 'tb-map-editor-settings',
templateUrl: './map-editor-settings.component.html', templateUrl: './map-editor-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-provider-settings.component.ts

@ -49,7 +49,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-map-provider-settings', selector: 'tb-map-provider-settings',
templateUrl: './map-provider-settings.component.html', templateUrl: './map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.html

12
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-settings-legacy.component.ts

@ -53,23 +53,23 @@ import { Widget } from '@shared/models/widget.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-map-settings', selector: 'tb-map-settings-legacy',
templateUrl: './map-settings.component.html', templateUrl: './map-settings-legacy.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MapSettingsComponent), useExisting: forwardRef(() => MapSettingsLegacyComponent),
multi: true multi: true
}, },
{ {
provide: NG_VALIDATORS, provide: NG_VALIDATORS,
useExisting: forwardRef(() => MapSettingsComponent), useExisting: forwardRef(() => MapSettingsLegacyComponent),
multi: true multi: true
} }
] ]
}) })
export class MapSettingsComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator { export class MapSettingsLegacyComponent extends PageComponent implements OnInit, ControlValueAccessor, Validator {
@Input() @Input()
disabled: boolean; disabled: boolean;

24
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.html

@ -0,0 +1,24 @@
<!--
Copyright © 2016-2024 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]="mapWidgetSettingsForm">
<tb-map-settings-legacy [routeMap]="false"
[aliasController]="aliasController"
[widget]="widget"
formControlName="mapSettings">
</tb-map-settings-legacy>
</section>

63
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component.ts

@ -0,0 +1,63 @@
///
/// Copyright © 2016-2024 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { defaultMapSettings } from 'src/app/modules/home/components/widget/lib/maps-legacy/map-models';
@Component({
selector: 'tb-map-widget-settings-legacy',
templateUrl: './map-widget-settings-legacy.component.html',
styleUrls: ['./../../widget-settings.scss']
})
export class MapWidgetSettingsLegacyComponent extends WidgetSettingsComponent {
mapWidgetSettingsForm: UntypedFormGroup;
constructor(protected store: Store<AppState>,
private fb: UntypedFormBuilder) {
super(store);
}
protected settingsForm(): UntypedFormGroup {
return this.mapWidgetSettingsForm;
}
protected defaultSettings(): WidgetSettings {
return {
...defaultMapSettings
};
}
protected onSettingsSet(settings: WidgetSettings) {
this.mapWidgetSettingsForm = this.fb.group({
mapSettings: [settings.mapSettings, []]
});
}
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
return {
mapSettings: settings
};
}
protected prepareOutputSettings(settings: any): WidgetSettings {
return settings.mapSettings;
}
}

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/marker-clustering-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.ts

@ -36,7 +36,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-marker-clustering-settings', selector: 'tb-marker-clustering-settings',
templateUrl: './marker-clustering-settings.component.html', templateUrl: './marker-clustering-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/markers-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.ts

@ -38,7 +38,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-markers-settings', selector: 'tb-markers-settings',
templateUrl: './markers-settings.component.html', templateUrl: './markers-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/openstreet-map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/openstreet-map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component.ts

@ -39,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-openstreet-map-provider-settings', selector: 'tb-openstreet-map-provider-settings',
templateUrl: './openstreet-map-provider-settings.component.html', templateUrl: './openstreet-map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/polygon-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.ts

@ -41,7 +41,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-polygon-settings', selector: 'tb-polygon-settings',
templateUrl: './polygon-settings.component.html', templateUrl: './polygon-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/route-map-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/route-map-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-settings.component.ts

@ -35,7 +35,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-route-map-settings', selector: 'tb-route-map-settings',
templateUrl: './route-map-settings.component.html', templateUrl: './route-map-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

4
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/route-map-widget-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.html

@ -16,9 +16,9 @@
--> -->
<section class="tb-widget-settings" [formGroup]="routeMapWidgetSettingsForm"> <section class="tb-widget-settings" [formGroup]="routeMapWidgetSettingsForm">
<tb-map-settings [routeMap]="true" <tb-map-settings-legacy [routeMap]="true"
[aliasController]="aliasController" [aliasController]="aliasController"
[widget]="widget" [widget]="widget"
formControlName="mapSettings"> formControlName="mapSettings">
</tb-map-settings> </tb-map-settings-legacy>
</section> </section>

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/route-map-widget-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component.ts

@ -24,7 +24,7 @@ import { defaultMapSettings } from 'src/app/modules/home/components/widget/lib/m
@Component({ @Component({
selector: 'tb-route-map-widget-settings', selector: 'tb-route-map-widget-settings',
templateUrl: './route-map-widget-settings.component.html', templateUrl: './route-map-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss'] styleUrls: ['./../../widget-settings.scss']
}) })
export class RouteMapWidgetSettingsComponent extends WidgetSettingsComponent { export class RouteMapWidgetSettingsComponent extends WidgetSettingsComponent {

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/tencent-map-provider-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/tencent-map-provider-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component.ts

@ -39,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-tencent-map-provider-settings', selector: 'tb-tencent-map-provider-settings',
templateUrl: './tencent-map-provider-settings.component.html', templateUrl: './tencent-map-provider-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-common-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-common-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.ts

@ -37,7 +37,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-trip-animation-common-settings', selector: 'tb-trip-animation-common-settings',
templateUrl: './trip-animation-common-settings.component.html', templateUrl: './trip-animation-common-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-marker-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.ts

@ -36,7 +36,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-trip-animation-marker-settings', selector: 'tb-trip-animation-marker-settings',
templateUrl: './trip-animation-marker-settings.component.html', templateUrl: './trip-animation-marker-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-path-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-path-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.ts

@ -39,7 +39,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-trip-animation-path-settings', selector: 'tb-trip-animation-path-settings',
templateUrl: './trip-animation-path-settings.component.html', templateUrl: './trip-animation-path-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-point-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.ts

@ -40,7 +40,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
selector: 'tb-trip-animation-point-settings', selector: 'tb-trip-animation-point-settings',
templateUrl: './trip-animation-point-settings.component.html', templateUrl: './trip-animation-point-settings.component.html',
styleUrls: ['./../widget-settings.scss'], styleUrls: ['./../../widget-settings.scss'],
providers: [ providers: [
{ {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,

0
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-widget-settings.component.html → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.html

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/trip-animation-widget-settings.component.ts → ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component.ts

@ -41,7 +41,7 @@ import { extractType } from '@core/utils';
@Component({ @Component({
selector: 'tb-trip-animation-widget-settings', selector: 'tb-trip-animation-widget-settings',
templateUrl: './trip-animation-widget-settings.component.html', templateUrl: './trip-animation-widget-settings.component.html',
styleUrls: ['./../widget-settings.scss'] styleUrls: ['./../../widget-settings.scss']
}) })
export class TripAnimationWidgetSettingsComponent extends WidgetSettingsComponent { export class TripAnimationWidgetSettingsComponent extends WidgetSettingsComponent {

24
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.html

@ -15,10 +15,20 @@
limitations under the License. limitations under the License.
--> -->
<section class="tb-widget-settings" [formGroup]="mapWidgetSettingsForm"> <ng-container [formGroup]="mapWidgetSettingsForm">
<tb-map-settings [routeMap]="false" <tb-map-settings formControlName="mapSettings"></tb-map-settings>
[aliasController]="aliasController" <div class="tb-form-panel">
[widget]="widget" <div class="tb-form-panel-title" translate>widget-config.card-appearance</div>
formControlName="mapSettings"> <div class="tb-form-row space-between">
</tb-map-settings> <div>{{ 'widgets.background.background' | translate }}</div>
</section> <tb-background-settings formControlName="background">
</tb-background-settings>
</div>
<div class="tb-form-row space-between">
<div>{{ 'widget-config.card-padding' | translate }}</div>
<mat-form-field appearance="outline" subscriptSizing="dynamic">
<input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}">
</mat-form-field>
</div>
</div>
</ng-container>

19
ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts

@ -19,7 +19,8 @@ import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.m
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { defaultMapSettings } from 'src/app/modules/home/components/widget/lib/maps-legacy/map-models'; import { mergeDeep } from '@core/utils';
import { mapWidgetDefaultSettings, MapWidgetSettings } from '@home/components/widget/lib/maps/map-widget.models';
@Component({ @Component({
selector: 'tb-map-widget-settings', selector: 'tb-map-widget-settings',
@ -40,24 +41,18 @@ export class MapWidgetSettingsComponent extends WidgetSettingsComponent {
} }
protected defaultSettings(): WidgetSettings { protected defaultSettings(): WidgetSettings {
return { return mergeDeep<MapWidgetSettings>({} as MapWidgetSettings, mapWidgetDefaultSettings);
...defaultMapSettings
};
} }
protected onSettingsSet(settings: WidgetSettings) { protected onSettingsSet(settings: WidgetSettings) {
this.mapWidgetSettingsForm = this.fb.group({ this.mapWidgetSettingsForm = this.fb.group({
mapSettings: [settings.mapSettings, []] mapSettings: [settings, []],
background: [settings.background, []],
padding: [settings.padding, []]
}); });
} }
protected prepareInputSettings(settings: WidgetSettings): WidgetSettings {
return {
mapSettings: settings
};
}
protected prepareOutputSettings(settings: any): WidgetSettings { protected prepareOutputSettings(settings: any): WidgetSettings {
return settings.mapSettings; return {...settings.mapSettings, background: settings.background, padding: settings.padding};
} }
} }

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

@ -210,52 +210,52 @@ import {
} from '@home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component'; } from '@home/components/widget/lib/settings/input/update-multiple-attributes-key-settings.component';
import { import {
OpenStreetMapProviderSettingsComponent OpenStreetMapProviderSettingsComponent
} from '@home/components/widget/lib/settings/map/openstreet-map-provider-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/openstreet-map-provider-settings.component';
import { MapProviderSettingsComponent } from '@home/components/widget/lib/settings/map/map-provider-settings.component'; import { MapProviderSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/map-provider-settings.component';
import { MapSettingsComponent } from '@home/components/widget/lib/settings/map/map-settings.component'; import { MapSettingsLegacyComponent } from '@home/components/widget/lib/settings/map/legacy/map-settings-legacy.component';
import { MapWidgetSettingsComponent } from '@home/components/widget/lib/settings/map/map-widget-settings.component'; import { MapWidgetSettingsLegacyComponent } from '@home/components/widget/lib/settings/map/legacy/map-widget-settings-legacy.component';
import { import {
GoogleMapProviderSettingsComponent GoogleMapProviderSettingsComponent
} from '@home/components/widget/lib/settings/map/google-map-provider-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/google-map-provider-settings.component';
import { import {
HereMapProviderSettingsComponent HereMapProviderSettingsComponent
} from '@home/components/widget/lib/settings/map/here-map-provider-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/here-map-provider-settings.component';
import { import {
TencentMapProviderSettingsComponent TencentMapProviderSettingsComponent
} from '@home/components/widget/lib/settings/map/tencent-map-provider-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/tencent-map-provider-settings.component';
import { import {
ImageMapProviderSettingsComponent ImageMapProviderSettingsComponent
} from '@home/components/widget/lib/settings/map/image-map-provider-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/image-map-provider-settings.component';
import { import {
DatasourcesKeyAutocompleteComponent DatasourcesKeyAutocompleteComponent
} from '@home/components/widget/lib/settings/map/datasources-key-autocomplete.component'; } from '@home/components/widget/lib/settings/map/legacy/datasources-key-autocomplete.component';
import { CommonMapSettingsComponent } from '@home/components/widget/lib/settings/map/common-map-settings.component'; import { CommonMapSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/common-map-settings.component';
import { MarkersSettingsComponent } from '@home/components/widget/lib/settings/map/markers-settings.component'; import { MarkersSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/markers-settings.component';
import { PolygonSettingsComponent } from '@home/components/widget/lib/settings/map/polygon-settings.component'; import { PolygonSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/polygon-settings.component';
import { CircleSettingsComponent } from '@home/components/widget/lib/settings/map/circle-settings.component'; import { CircleSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/circle-settings.component';
import { import {
MarkerClusteringSettingsComponent MarkerClusteringSettingsComponent
} from '@home/components/widget/lib/settings/map/marker-clustering-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component';
import { MapEditorSettingsComponent } from '@home/components/widget/lib/settings/map/map-editor-settings.component'; import { MapEditorSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/map-editor-settings.component';
import { RouteMapSettingsComponent } from '@home/components/widget/lib/settings/map/route-map-settings.component'; import { RouteMapSettingsComponent } from '@home/components/widget/lib/settings/map/legacy/route-map-settings.component';
import { import {
RouteMapWidgetSettingsComponent RouteMapWidgetSettingsComponent
} from '@home/components/widget/lib/settings/map/route-map-widget-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/route-map-widget-settings.component';
import { import {
TripAnimationWidgetSettingsComponent TripAnimationWidgetSettingsComponent
} from '@home/components/widget/lib/settings/map/trip-animation-widget-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/trip-animation-widget-settings.component';
import { import {
TripAnimationCommonSettingsComponent TripAnimationCommonSettingsComponent
} from '@home/components/widget/lib/settings/map/trip-animation-common-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component';
import { import {
TripAnimationMarkerSettingsComponent TripAnimationMarkerSettingsComponent
} from '@home/components/widget/lib/settings/map/trip-animation-marker-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component';
import { import {
TripAnimationPathSettingsComponent TripAnimationPathSettingsComponent
} from '@home/components/widget/lib/settings/map/trip-animation-path-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component';
import { import {
TripAnimationPointSettingsComponent TripAnimationPointSettingsComponent
} from '@home/components/widget/lib/settings/map/trip-animation-point-settings.component'; } from '@home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component';
import { import {
GatewayLogsSettingsComponent GatewayLogsSettingsComponent
} from '@home/components/widget/lib/settings/gateway/gateway-logs-settings.component'; } from '@home/components/widget/lib/settings/gateway/gateway-logs-settings.component';
@ -371,6 +371,7 @@ ScadaSymbolWidgetSettingsComponent
import { import {
SegmentedButtonWidgetSettingsComponent SegmentedButtonWidgetSettingsComponent
} from '@home/components/widget/lib/settings/button/segmented-button-widget-settings.component'; } from '@home/components/widget/lib/settings/button/segmented-button-widget-settings.component';
import { MapWidgetSettingsComponent } from '@home/components/widget/lib/settings/map/map-widget-settings.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -458,12 +459,12 @@ import {
MarkerClusteringSettingsComponent, MarkerClusteringSettingsComponent,
MapEditorSettingsComponent, MapEditorSettingsComponent,
RouteMapSettingsComponent, RouteMapSettingsComponent,
MapSettingsComponent, MapSettingsLegacyComponent,
TripAnimationCommonSettingsComponent, TripAnimationCommonSettingsComponent,
TripAnimationMarkerSettingsComponent, TripAnimationMarkerSettingsComponent,
TripAnimationPathSettingsComponent, TripAnimationPathSettingsComponent,
TripAnimationPointSettingsComponent, TripAnimationPointSettingsComponent,
MapWidgetSettingsComponent, MapWidgetSettingsLegacyComponent,
RouteMapWidgetSettingsComponent, RouteMapWidgetSettingsComponent,
GatewayLogsSettingsComponent, GatewayLogsSettingsComponent,
GatewayServiceRPCSettingsComponent, GatewayServiceRPCSettingsComponent,
@ -502,7 +503,8 @@ import {
LabelCardWidgetSettingsComponent, LabelCardWidgetSettingsComponent,
LabelValueCardWidgetSettingsComponent, LabelValueCardWidgetSettingsComponent,
UnreadNotificationWidgetSettingsComponent, UnreadNotificationWidgetSettingsComponent,
ScadaSymbolWidgetSettingsComponent ScadaSymbolWidgetSettingsComponent,
MapWidgetSettingsComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -595,12 +597,12 @@ import {
MarkerClusteringSettingsComponent, MarkerClusteringSettingsComponent,
MapEditorSettingsComponent, MapEditorSettingsComponent,
RouteMapSettingsComponent, RouteMapSettingsComponent,
MapSettingsComponent, MapSettingsLegacyComponent,
TripAnimationCommonSettingsComponent, TripAnimationCommonSettingsComponent,
TripAnimationMarkerSettingsComponent, TripAnimationMarkerSettingsComponent,
TripAnimationPathSettingsComponent, TripAnimationPathSettingsComponent,
TripAnimationPointSettingsComponent, TripAnimationPointSettingsComponent,
MapWidgetSettingsComponent, MapWidgetSettingsLegacyComponent,
RouteMapWidgetSettingsComponent, RouteMapWidgetSettingsComponent,
GatewayLogsSettingsComponent, GatewayLogsSettingsComponent,
GatewayServiceRPCSettingsComponent, GatewayServiceRPCSettingsComponent,
@ -639,7 +641,8 @@ import {
LabelCardWidgetSettingsComponent, LabelCardWidgetSettingsComponent,
LabelValueCardWidgetSettingsComponent, LabelValueCardWidgetSettingsComponent,
UnreadNotificationWidgetSettingsComponent, UnreadNotificationWidgetSettingsComponent,
ScadaSymbolWidgetSettingsComponent ScadaSymbolWidgetSettingsComponent,
MapWidgetSettingsComponent
] ]
}) })
export class WidgetSettingsModule { export class WidgetSettingsModule {
@ -705,7 +708,7 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-photo-camera-input-widget-settings': PhotoCameraInputWidgetSettingsComponent, 'tb-photo-camera-input-widget-settings': PhotoCameraInputWidgetSettingsComponent,
'tb-update-multiple-attributes-widget-settings': UpdateMultipleAttributesWidgetSettingsComponent, 'tb-update-multiple-attributes-widget-settings': UpdateMultipleAttributesWidgetSettingsComponent,
'tb-update-multiple-attributes-key-settings': UpdateMultipleAttributesKeySettingsComponent, 'tb-update-multiple-attributes-key-settings': UpdateMultipleAttributesKeySettingsComponent,
'tb-map-widget-settings': MapWidgetSettingsComponent, 'tb-map-widget-settings-legacy': MapWidgetSettingsLegacyComponent,
'tb-route-map-widget-settings': RouteMapWidgetSettingsComponent, 'tb-route-map-widget-settings': RouteMapWidgetSettingsComponent,
'tb-trip-animation-widget-settings': TripAnimationWidgetSettingsComponent, 'tb-trip-animation-widget-settings': TripAnimationWidgetSettingsComponent,
'tb-gateway-logs-settings': GatewayLogsSettingsComponent, 'tb-gateway-logs-settings': GatewayLogsSettingsComponent,
@ -743,5 +746,6 @@ export const widgetSettingsComponentsMap: {[key: string]: Type<IWidgetSettingsCo
'tb-label-card-widget-settings': LabelCardWidgetSettingsComponent, 'tb-label-card-widget-settings': LabelCardWidgetSettingsComponent,
'tb-label-value-card-widget-settings': LabelValueCardWidgetSettingsComponent, 'tb-label-value-card-widget-settings': LabelValueCardWidgetSettingsComponent,
'tb-unread-notification-widget-settings': UnreadNotificationWidgetSettingsComponent, 'tb-unread-notification-widget-settings': UnreadNotificationWidgetSettingsComponent,
'tb-scada-symbol-widget-settings': ScadaSymbolWidgetSettingsComponent 'tb-scada-symbol-widget-settings': ScadaSymbolWidgetSettingsComponent,
'tb-map-widget-settings': MapWidgetSettingsComponent
}; };

3
ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts

@ -634,6 +634,9 @@ export class WidgetComponentService {
if (isUndefined(result.typeParameters.overflowVisible)) { if (isUndefined(result.typeParameters.overflowVisible)) {
result.typeParameters.overflowVisible = false; result.typeParameters.overflowVisible = false;
} }
if (isUndefined(result.typeParameters.hideDataTab)) {
result.typeParameters.hideDataTab = false;
}
if (isUndefined(result.typeParameters.hideDataSettings)) { if (isUndefined(result.typeParameters.hideDataSettings)) {
result.typeParameters.hideDataSettings = false; result.typeParameters.hideDataSettings = false;
} }

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

@ -26,7 +26,7 @@
</div> </div>
</div> </div>
<div *ngIf="widgetConfigMode === widgetConfigModes.advanced; else basicMode" class="tb-widget-config-content"> <div *ngIf="widgetConfigMode === widgetConfigModes.advanced; else basicMode" class="tb-widget-config-content">
<div *ngIf="widgetType !== widgetTypes.static" [class.!hidden]="selectedOption !== 'data'" class="mat-content"> <div *ngIf="displayData" [class.!hidden]="selectedOption !== 'data'" class="mat-content">
<ng-container *ngTemplateOutlet="data"></ng-container> <ng-container *ngTemplateOutlet="data"></ng-container>
</div> </div>
<div [class.!hidden]="selectedOption !== 'appearance'" class="mat-content"> <div [class.!hidden]="selectedOption !== 'appearance'" class="mat-content">

6
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts

@ -322,7 +322,7 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
private buildHeader() { private buildHeader() {
this.headerOptions.length = 0; this.headerOptions.length = 0;
if (this.widgetType !== widgetType.static) { if (this.displayData) {
this.headerOptions.push( this.headerOptions.push(
{ {
name: this.translate.instant('widget-config.data'), name: this.translate.instant('widget-config.data'),
@ -710,6 +710,10 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
return this.modelValue?.basicModeDirective?.length && !this.basicModeDirectiveError; return this.modelValue?.basicModeDirective?.length && !this.basicModeDirectiveError;
} }
public get displayData(): boolean {
return !this.modelValue?.typeParameters?.hideDataTab && this.widgetType !== widgetType.static;
}
public get displayAppearance(): boolean { public get displayAppearance(): boolean {
return this.displayAppearanceDataSettings || this.displayAdvancedAppearance; return this.displayAppearanceDataSettings || this.displayAdvancedAppearance;
} }

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

@ -185,6 +185,7 @@ export interface WidgetTypeParameters {
previewHeight?: string; previewHeight?: string;
embedTitlePanel?: boolean; embedTitlePanel?: boolean;
overflowVisible?: boolean; overflowVisible?: boolean;
hideDataTab?: boolean;
hideDataSettings?: boolean; hideDataSettings?: boolean;
defaultDataKeysFunction?: (configComponent: any, configData: any) => DataKey[]; defaultDataKeysFunction?: (configComponent: any, configData: any) => DataKey[];
defaultLatestDataKeysFunction?: (configComponent: any, configData: any) => DataKey[]; defaultLatestDataKeysFunction?: (configComponent: any, configData: any) => DataKey[];

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

@ -6803,8 +6803,19 @@
"max-value": "Maximum value" "max-value": "Maximum value"
}, },
"maps": { "maps": {
"map-type": "Map type",
"map-type-map": "Map",
"map-type-image": "Image",
"overlays": "Overlays",
"markers": "Markers",
"polygons": "Polygons",
"circles": "Circles",
"layers": "Layers", "layers": "Layers",
"map-layers": "Map layers", "map-layers": "Map layers",
"tencent-provider-normal": "Tencent.Normal",
"tencent-provider-satellite": "Tencent.Satellite",
"tencent-provider-terrain": "Tencent.Terrain",
"custom": "Custom",
"select-entity": "Select entity", "select-entity": "Select entity",
"select-entity-hint": "Hint: after selection click at the map to set position", "select-entity-hint": "Hint: after selection click at the map to set position",
"tooltips": { "tooltips": {

28
ui-ngx/src/typings/leaflet-extend-tb.d.ts

@ -15,12 +15,21 @@
/// ///
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import L from 'leaflet';
import { TileLayerOptions } from 'leaflet';
// redeclare module, maintains compatibility with @types/leaflet // redeclare module, maintains compatibility with @types/leaflet
declare module 'leaflet' { declare module 'leaflet' {
interface MarkerOptions { interface MarkerOptions {
tbMarkerData?: FormattedData; tbMarkerData?: FormattedData;
} }
interface TileLayer {
_url: string;
_getSubdomain(tilePoint: L.Coords): string;
_globalTileRange: L.Bounds;
}
namespace TB { namespace TB {
interface SidebarControlOptions extends ControlOptions { interface SidebarControlOptions extends ControlOptions {
@ -48,6 +57,7 @@ declare module 'leaflet' {
interface LayerData { interface LayerData {
title: string; title: string;
attributionPrefix?: string;
layer: Layer; layer: Layer;
mini: Layer; mini: Layer;
} }
@ -65,5 +75,23 @@ declare module 'leaflet' {
function sidebarPane<O extends SidebarPaneControlOptions>(options: O): SidebarPaneControl<O>; function sidebarPane<O extends SidebarPaneControlOptions>(options: O): SidebarPaneControl<O>;
function layers(options: LayersControlOptions): LayersControl; function layers(options: LayersControlOptions): LayersControl;
namespace TileLayer {
interface ChinaProvidersData {
[provider: string]: {
[type: string]: string;
Subdomains: string;
};
}
class ChinaProvider extends L.TileLayer {
constructor(type: string, options?: TileLayerOptions);
}
}
namespace tileLayer {
function chinaProvider(type: string, options?: TileLayerOptions): TileLayer.ChinaProvider;
}
} }
} }

Loading…
Cancel
Save