Browse Source

UI: Improve map widget import/export. Add help assets for new maps.

pull/12866/head
Igor Kulikov 2 years ago
parent
commit
e5b8a24598
  1. 154
      ui-ngx/src/app/core/services/item-buffer.service.ts
  2. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/circles-data-layer.ts
  3. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts
  4. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/latest-map-data-layer.ts
  5. 7
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts
  6. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts
  7. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polygons-data-layer.ts
  8. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts
  9. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts
  10. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/geo-map.ts
  11. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/image-map.ts
  12. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-layer.ts
  13. 5
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.component.ts
  14. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget.models.ts
  15. 6
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts
  16. 2
      ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts
  17. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html
  18. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts
  19. 6
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts
  20. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html
  21. 5
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts
  22. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/image-map-source-settings.component.ts
  23. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts
  24. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-buttons-settings.component.ts
  25. 11
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html
  26. 32
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts
  27. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts
  28. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layers.component.ts
  29. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts
  30. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-sources.component.ts
  31. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-row.component.ts
  32. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layer-settings-panel.component.ts
  33. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-layers.component.ts
  34. 3
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-settings.component.ts
  35. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-clustering-settings.component.ts
  36. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts
  37. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings.component.ts
  38. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.html
  39. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shape-settings.component.ts
  40. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-shapes.component.ts
  41. 13
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/trip-timeline-settings.component.ts
  42. 8
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/circle-settings.component.html
  43. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/marker-clustering-settings.component.html
  44. 10
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/markers-settings.component.html
  45. 8
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/polygon-settings.component.html
  46. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-common-settings.component.html
  47. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-marker-settings.component.html
  48. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-path-settings.component.html
  49. 4
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/legacy/trip-animation-point-settings.component.html
  50. 2
      ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-widget-settings.component.ts
  51. 12
      ui-ngx/src/app/shared/import-export/import-export.service.ts
  52. 39
      ui-ngx/src/app/shared/models/alias.models.ts
  53. 40
      ui-ngx/src/app/shared/models/query/query.models.ts
  54. 151
      ui-ngx/src/app/shared/models/widget/maps/map-export.models.ts
  55. 2
      ui-ngx/src/app/shared/models/widget/maps/map.models.ts
  56. 2
      ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts
  57. 35
      ui-ngx/src/app/shared/models/widget/widget-export.models.ts
  58. 65
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/clustering_color_fn.md
  59. 42
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/color_fn.md
  60. 40
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/label_fn.md
  61. 10
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/map_fn_args.md
  62. 62
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/marker_image_fn.md
  63. 42
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/path_color_fn.md
  64. 43
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/path_point_color_fn.md
  65. 2
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/polygon_color_fn.md
  66. 40
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/polygon_tooltip_fn.md
  67. 65
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/position_fn.md
  68. 40
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/tooltip_fn.md
  69. 34
      ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/trip_point_as_anchor_fn.md
  70. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/circle_fill_color_fn.md
  71. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/circle_label_fn.md
  72. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/circle_stroke_color_fn.md
  73. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/circle_tooltip_fn.md
  74. 6
      ui-ngx/src/assets/help/en_US/widget/lib/map/clustering_color_fn.md
  75. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/color_fn.md
  76. 19
      ui-ngx/src/assets/help/en_US/widget/lib/map/color_fn_examples.md
  77. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/label_fn.md
  78. 19
      ui-ngx/src/assets/help/en_US/widget/lib/map/label_fn_examples.md
  79. 12
      ui-ngx/src/assets/help/en_US/widget/lib/map/map_fn_args.md
  80. 18
      ui-ngx/src/assets/help/en_US/widget/lib/map/marker_image_fn.md
  81. 10
      ui-ngx/src/assets/help/en_US/widget/lib/map/marker_image_fn_args.md
  82. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/path_color_fn.md
  83. 25
      ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md
  84. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md
  85. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_fill_color_fn.md
  86. 22
      ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_label_fn.md
  87. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_stroke_color_fn.md
  88. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_tooltip_fn.md
  89. 6
      ui-ngx/src/assets/help/en_US/widget/lib/map/position_fn.md
  90. 24
      ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn.md
  91. 19
      ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn_examples.md
  92. 4
      ui-ngx/src/assets/help/en_US/widget/lib/map/trip_point_as_anchor_fn.md
  93. 4
      ui-ngx/src/typings/leaflet-extend-tb.d.ts

154
ui-ngx/src/app/core/services/item-buffer.service.ts

@ -16,7 +16,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BreakpointId, Dashboard, DashboardLayoutId } from '@app/shared/models/dashboard.models'; import { BreakpointId, Dashboard, DashboardLayoutId } from '@app/shared/models/dashboard.models';
import { AliasesInfo, EntityAlias, EntityAliases, EntityAliasInfo } from '@shared/models/alias.models'; import { AliasesInfo, EntityAlias, EntityAliases, EntityAliasInfo, getEntityAliasId } from '@shared/models/alias.models';
import { import {
Datasource, Datasource,
DatasourceType, DatasourceType,
@ -34,7 +34,8 @@ import { map } from 'rxjs/operators';
import { FcRuleNode, ruleNodeTypeDescriptors } from '@shared/models/rule-node.models'; import { FcRuleNode, ruleNodeTypeDescriptors } from '@shared/models/rule-node.models';
import { RuleChainService } from '@core/http/rule-chain.service'; import { RuleChainService } from '@core/http/rule-chain.service';
import { RuleChainImport } from '@shared/models/rule-chain.models'; import { RuleChainImport } from '@shared/models/rule-chain.models';
import { Filter, FilterInfo, Filters, FiltersInfo } from '@shared/models/query/query.models'; import { Filter, FilterInfo, Filters, FiltersInfo, getFilterId } from '@shared/models/query/query.models';
import { getWidgetExportDefinition } from '@shared/models/widget/widget-export.models';
const WIDGET_ITEM = 'widget_item'; const WIDGET_ITEM = 'widget_item';
const WIDGET_REFERENCE = 'widget_reference'; const WIDGET_REFERENCE = 'widget_reference';
@ -47,6 +48,7 @@ export interface WidgetItem {
filtersInfo: FiltersInfo; filtersInfo: FiltersInfo;
originalSize: WidgetSize; originalSize: WidgetSize;
originalColumns: number; originalColumns: number;
widgetExportInfo?: any;
} }
export interface WidgetReference { export interface WidgetReference {
@ -139,12 +141,18 @@ export class ItemBufferService {
} }
} }
} }
let widgetExportInfo: any;
const exportDefinition = getWidgetExportDefinition(widget);
if (exportDefinition) {
widgetExportInfo = exportDefinition.prepareExportInfo(dashboard, widget);
}
return { return {
widget, widget,
aliasesInfo, aliasesInfo,
filtersInfo, filtersInfo,
originalSize, originalSize,
originalColumns originalColumns,
widgetExportInfo
}; };
} }
@ -189,6 +197,7 @@ export class ItemBufferService {
const filtersInfo = widgetItem.filtersInfo; const filtersInfo = widgetItem.filtersInfo;
const originalColumns = widgetItem.originalColumns; const originalColumns = widgetItem.originalColumns;
const originalSize = widgetItem.originalSize; const originalSize = widgetItem.originalSize;
const widgetExportInfo = widgetItem.widgetExportInfo;
let targetRow = -1; let targetRow = -1;
let targetColumn = -1; let targetColumn = -1;
if (position) { if (position) {
@ -199,7 +208,7 @@ export class ItemBufferService {
return this.addWidgetToDashboard(targetDashboard, targetState, return this.addWidgetToDashboard(targetDashboard, targetState,
targetLayout, widget, aliasesInfo, filtersInfo, targetLayout, widget, aliasesInfo, filtersInfo,
onAliasesUpdateFunction, onFiltersUpdateFunction, onAliasesUpdateFunction, onFiltersUpdateFunction,
originalColumns, originalSize, targetRow, targetColumn, breakpoint).pipe( originalColumns, originalSize, targetRow, targetColumn, breakpoint, widgetExportInfo).pipe(
map(() => widget) map(() => widget)
); );
} else { } else {
@ -248,7 +257,8 @@ export class ItemBufferService {
originalSize: WidgetSize, originalSize: WidgetSize,
row: number, row: number,
column: number, column: number,
breakpoint = 'default'): Observable<Dashboard> { breakpoint = 'default',
widgetExportInfo?: any): Observable<Dashboard> {
let theDashboard: Dashboard; let theDashboard: Dashboard;
if (dashboard) { if (dashboard) {
theDashboard = dashboard; theDashboard = dashboard;
@ -258,26 +268,39 @@ export class ItemBufferService {
theDashboard = this.dashboardUtils.validateAndUpdateDashboard(theDashboard); theDashboard = this.dashboardUtils.validateAndUpdateDashboard(theDashboard);
let callAliasUpdateFunction = false; let callAliasUpdateFunction = false;
let callFilterUpdateFunction = false; let callFilterUpdateFunction = false;
let newEntityAliases: EntityAliases;
let newFilters: Filters;
const exportDefinition = getWidgetExportDefinition(widget);
if (exportDefinition && widgetExportInfo || aliasesInfo) {
newEntityAliases = deepClone(dashboard.configuration.entityAliases);
}
if (exportDefinition && widgetExportInfo || filtersInfo) {
newFilters = deepClone(dashboard.configuration.filters);
}
if (aliasesInfo) { if (aliasesInfo) {
const newEntityAliases = this.updateAliases(theDashboard, widget, aliasesInfo); this.updateAliases(widget, newEntityAliases, aliasesInfo);
const aliasesUpdated = !isEqual(newEntityAliases, theDashboard.configuration.entityAliases);
if (aliasesUpdated) {
theDashboard.configuration.entityAliases = newEntityAliases;
if (onAliasesUpdateFunction) {
callAliasUpdateFunction = true;
}
}
} }
if (filtersInfo) { if (filtersInfo) {
const newFilters = this.updateFilters(theDashboard, widget, filtersInfo); this.updateFilters(widget, newFilters, filtersInfo);
const filtersUpdated = !isEqual(newFilters, theDashboard.configuration.filters); }
if (filtersUpdated) { if (exportDefinition && widgetExportInfo) {
theDashboard.configuration.filters = newFilters; exportDefinition.updateFromExportInfo(widget, newEntityAliases, newFilters, widgetExportInfo);
if (onFiltersUpdateFunction) { }
callFilterUpdateFunction = true; const aliasesUpdated = newEntityAliases && !isEqual(newEntityAliases, theDashboard.configuration.entityAliases);
} if (aliasesUpdated) {
theDashboard.configuration.entityAliases = newEntityAliases;
if (onAliasesUpdateFunction) {
callAliasUpdateFunction = true;
} }
} }
const filtersUpdated = newFilters && !isEqual(newFilters, theDashboard.configuration.filters);
if (filtersUpdated) {
theDashboard.configuration.filters = newFilters;
if (onFiltersUpdateFunction) {
callFilterUpdateFunction = true;
}
}
this.dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget, this.dashboardUtils.addWidgetToLayout(theDashboard, targetState, targetLayout, widget,
originalColumns, originalSize, row, column, breakpoint); originalColumns, originalSize, row, column, breakpoint);
if (callAliasUpdateFunction) { if (callAliasUpdateFunction) {
@ -430,14 +453,13 @@ export class ItemBufferService {
}; };
} }
private updateAliases(dashboard: Dashboard, widget: Widget, aliasesInfo: AliasesInfo): EntityAliases { private updateAliases(widget: Widget, entityAliases: EntityAliases, aliasesInfo: AliasesInfo): void {
const entityAliases = deepClone(dashboard.configuration.entityAliases);
let aliasInfo: EntityAliasInfo; let aliasInfo: EntityAliasInfo;
let newAliasId: string; let newAliasId: string;
for (const datasourceIndexStr of Object.keys(aliasesInfo.datasourceAliases)) { for (const datasourceIndexStr of Object.keys(aliasesInfo.datasourceAliases)) {
const datasourceIndex = Number(datasourceIndexStr); const datasourceIndex = Number(datasourceIndexStr);
aliasInfo = aliasesInfo.datasourceAliases[datasourceIndex]; aliasInfo = aliasesInfo.datasourceAliases[datasourceIndex];
newAliasId = this.getEntityAliasId(entityAliases, aliasInfo); newAliasId = getEntityAliasId(entityAliases, aliasInfo);
if (widget.type === widgetType.alarm) { if (widget.type === widgetType.alarm) {
widget.config.alarmSource.entityAliasId = newAliasId; widget.config.alarmSource.entityAliasId = newAliasId;
} else { } else {
@ -446,7 +468,7 @@ export class ItemBufferService {
} }
if (aliasesInfo.targetDeviceAlias) { if (aliasesInfo.targetDeviceAlias) {
aliasInfo = aliasesInfo.targetDeviceAlias; aliasInfo = aliasesInfo.targetDeviceAlias;
newAliasId = this.getEntityAliasId(entityAliases, aliasInfo); newAliasId = getEntityAliasId(entityAliases, aliasInfo);
if (widget.config.targetDevice?.type !== TargetDeviceType.entity) { if (widget.config.targetDevice?.type !== TargetDeviceType.entity) {
widget.config.targetDevice = { widget.config.targetDevice = {
type: TargetDeviceType.entity type: TargetDeviceType.entity
@ -454,101 +476,21 @@ export class ItemBufferService {
} }
widget.config.targetDevice.entityAliasId = newAliasId; widget.config.targetDevice.entityAliasId = newAliasId;
} }
return entityAliases;
} }
private updateFilters(dashboard: Dashboard, widget: Widget, filtersInfo: FiltersInfo): Filters { private updateFilters(widget: Widget, filters: Filters, filtersInfo: FiltersInfo): void {
const filters = deepClone(dashboard.configuration.filters);
let filterInfo: FilterInfo; let filterInfo: FilterInfo;
let newFilterId: string; let newFilterId: string;
for (const datasourceIndexStr of Object.keys(filtersInfo.datasourceFilters)) { for (const datasourceIndexStr of Object.keys(filtersInfo.datasourceFilters)) {
const datasourceIndex = Number(datasourceIndexStr); const datasourceIndex = Number(datasourceIndexStr);
filterInfo = filtersInfo.datasourceFilters[datasourceIndex]; filterInfo = filtersInfo.datasourceFilters[datasourceIndex];
newFilterId = this.getFilterId(filters, filterInfo); newFilterId = getFilterId(filters, filterInfo);
if (widget.type === widgetType.alarm) { if (widget.type === widgetType.alarm) {
widget.config.alarmSource.filterId = newFilterId; widget.config.alarmSource.filterId = newFilterId;
} else { } else {
widget.config.datasources[datasourceIndex].filterId = newFilterId; widget.config.datasources[datasourceIndex].filterId = newFilterId;
} }
} }
return filters;
}
private isEntityAliasEqual(alias1: EntityAliasInfo, alias2: EntityAliasInfo): boolean {
return isEqual(alias1.filter, alias2.filter);
}
private getEntityAliasId(entityAliases: EntityAliases, aliasInfo: EntityAliasInfo): string {
let newAliasId: string;
for (const aliasId of Object.keys(entityAliases)) {
if (this.isEntityAliasEqual(entityAliases[aliasId], aliasInfo)) {
newAliasId = aliasId;
break;
}
}
if (!newAliasId) {
const newAliasName = this.createEntityAliasName(entityAliases, aliasInfo.alias);
newAliasId = this.utils.guid();
entityAliases[newAliasId] = {id: newAliasId, alias: newAliasName, filter: aliasInfo.filter};
}
return newAliasId;
}
private createEntityAliasName(entityAliases: EntityAliases, alias: string): string {
let c = 0;
let newAlias = alias;
let unique = false;
while (!unique) {
unique = true;
for (const entAliasId of Object.keys(entityAliases)) {
const entAlias = entityAliases[entAliasId];
if (newAlias === entAlias.alias) {
c++;
newAlias = alias + c;
unique = false;
}
}
}
return newAlias;
}
private isFilterEqual(filter1: FilterInfo, filter2: FilterInfo): boolean {
return isEqual(filter1.keyFilters, filter2.keyFilters);
}
private getFilterId(filters: Filters, filterInfo: FilterInfo): string {
let newFilterId: string;
for (const filterId of Object.keys(filters)) {
if (this.isFilterEqual(filters[filterId], filterInfo)) {
newFilterId = filterId;
break;
}
}
if (!newFilterId) {
const newFilterName = this.createFilterName(filters, filterInfo.filter);
newFilterId = this.utils.guid();
filters[newFilterId] = {id: newFilterId, filter: newFilterName,
keyFilters: filterInfo.keyFilters, editable: filterInfo.editable};
}
return newFilterId;
}
private createFilterName(filters: Filters, filter: string): string {
let c = 0;
let newFilter = filter;
let unique = false;
while (!unique) {
unique = true;
for (const entFilterId of Object.keys(filters)) {
const entFilter = filters[entFilterId];
if (newFilter === entFilter.filter) {
c++;
newFilter = filter + c;
unique = false;
}
}
}
return newFilter;
} }
private storeSet(key: string, elem: any) { private storeSet(key: string, elem: any) {

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/circles-data-layer.ts

@ -20,7 +20,7 @@ import {
isJSON, MapDataLayerType, isJSON, MapDataLayerType,
TbCircleData, TbCircleData,
TbMapDatasource TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import L from 'leaflet'; import L from 'leaflet';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import { TbShapesDataLayer } from '@home/components/widget/lib/maps/data-layer/shapes-data-layer'; import { TbShapesDataLayer } from '@home/components/widget/lib/maps/data-layer/shapes-data-layer';

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/data-layer-utils.ts

@ -18,7 +18,7 @@ import {
DataLayerTooltipSettings, DataLayerTooltipSettings,
DataLayerTooltipTrigger, processTooltipTemplate, DataLayerTooltipTrigger, processTooltipTemplate,
TbMapDatasource TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { TbMap } from '@home/components/widget/lib/maps/map'; import { TbMap } from '@home/components/widget/lib/maps/map';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import L from 'leaflet'; import L from 'leaflet';

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

@ -18,7 +18,7 @@ import {
DataLayerEditAction, DataLayerEditAction,
MapDataLayerSettings, MapDataLayerSettings,
TbMapDatasource TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { TbMap } from '@home/components/widget/lib/maps/map'; import { TbMap } from '@home/components/widget/lib/maps/map';
import { FormattedData, WidgetActionType } from '@shared/models/widget.models'; import { FormattedData, WidgetActionType } from '@shared/models/widget.models';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';

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

@ -20,7 +20,7 @@ import {
MapDataLayerSettings, MapDataLayerType, mapDataSourceSettingsToDatasource, MapDataLayerSettings, MapDataLayerType, mapDataSourceSettingsToDatasource,
MapStringFunction, MapType, MapStringFunction, MapType,
TbMapDatasource TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { import {
createLabelFromPattern, createLabelFromPattern,
guid, isDefined, guid, isDefined,
@ -82,6 +82,7 @@ export class DataLayerColorProcessor {
private settings: DataLayerColorSettings) {} private settings: DataLayerColorSettings) {}
public setup(): Observable<void> { public setup(): Observable<void> {
this.color = this.settings.color;
if (this.settings.type === DataLayerColorType.function) { if (this.settings.type === DataLayerColorType.function) {
return parseTbFunction<MapStringFunction>(this.dataLayer.getCtx().http, this.settings.colorFunction, ['data', 'dsData']).pipe( return parseTbFunction<MapStringFunction>(this.dataLayer.getCtx().http, this.settings.colorFunction, ['data', 'dsData']).pipe(
map((parsed) => { map((parsed) => {
@ -90,7 +91,6 @@ export class DataLayerColorProcessor {
}) })
); );
} else { } else {
this.color = this.settings.color;
return of(null) return of(null)
} }
} }
@ -99,6 +99,9 @@ export class DataLayerColorProcessor {
let color: string; let color: string;
if (this.settings.type === DataLayerColorType.function) { if (this.settings.type === DataLayerColorType.function) {
color = safeExecuteTbFunction(this.colorFunction, [data, dsData]); color = safeExecuteTbFunction(this.colorFunction, [data, dsData]);
if (!color) {
color = this.color;
}
} else { } else {
color = this.color; color = this.color;
} }

4
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts

@ -34,7 +34,7 @@ import {
MarkerShapeSettings, MarkerShapeSettings,
MarkerType, MarkerType,
TbMapDatasource TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import L, { FeatureGroup } from 'leaflet'; import L, { FeatureGroup } from 'leaflet';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import { forkJoin, Observable, of } from 'rxjs'; import { forkJoin, Observable, of } from 'rxjs';
@ -55,7 +55,7 @@ import {
createColorMarkerIconElement, createColorMarkerIconElement,
createColorMarkerShapeURI, createColorMarkerShapeURI,
MarkerShape MarkerShape
} from '@home/components/widget/lib/maps/models/marker-shape.models'; } from '@shared/models/widget/maps/marker-shape.models';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { import {

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polygons-data-layer.ts

@ -19,7 +19,7 @@ import {
isCutPolygon, isJSON, MapDataLayerType, isCutPolygon, isJSON, MapDataLayerType,
PolygonsDataLayerSettings, PolygonsDataLayerSettings,
TbMapDatasource, TbPolyData, TbPolygonCoordinates, TbPolygonRawCoordinates TbMapDatasource, TbPolyData, TbPolygonCoordinates, TbPolygonRawCoordinates
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import L from 'leaflet'; import L from 'leaflet';
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import { TbShapesDataLayer } from '@home/components/widget/lib/maps/data-layer/shapes-data-layer'; import { TbShapesDataLayer } from '@home/components/widget/lib/maps/data-layer/shapes-data-layer';

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { ShapeDataLayerSettings, TbMapDatasource } from '@home/components/widget/lib/maps/models/map.models'; import { ShapeDataLayerSettings, TbMapDatasource } from '@shared/models/widget/maps/map.models';
import L from 'leaflet'; import L from 'leaflet';
import { TbMap } from '@home/components/widget/lib/maps/map'; import { TbMap } from '@home/components/widget/lib/maps/map';
import { forkJoin, Observable } from 'rxjs'; import { forkJoin, Observable } from 'rxjs';

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts

@ -23,7 +23,7 @@ import {
MapDataLayerType, MapDataLayerType,
TbMapDatasource, TbMapDatasource,
TripsDataLayerSettings TripsDataLayerSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { forkJoin, Observable } from 'rxjs'; import { forkJoin, Observable } from 'rxjs';
import { FormattedData, WidgetActionType } from '@shared/models/widget.models'; import { FormattedData, WidgetActionType } from '@shared/models/widget.models';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';

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

@ -25,7 +25,7 @@ import {
TbPolygonCoordinates, TbPolygonCoordinates,
TbPolygonRawCoordinate, TbPolygonRawCoordinate,
TbPolygonRawCoordinates TbPolygonRawCoordinates
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/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';
import { forkJoin, Observable, of } from 'rxjs'; import { forkJoin, Observable, of } from 'rxjs';

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

@ -24,7 +24,7 @@ import {
loadImageWithAspect, loadImageWithAspect,
MapZoomAction, MapZoomAction,
TbCircleData, TbPolygonCoordinate, TbPolygonCoordinates, TbPolygonRawCoordinate, TbPolygonRawCoordinates TbCircleData, TbPolygonCoordinate, TbPolygonCoordinates, TbPolygonRawCoordinate, TbPolygonRawCoordinates
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/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';
import { Observable, of, ReplaySubject, switchMap } from 'rxjs'; import { Observable, of, ReplaySubject, switchMap } from 'rxjs';

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

@ -28,7 +28,7 @@ import {
MapProvider, MapProvider,
OpenStreetMapLayerSettings, OpenStreetMapLayerSettings,
TencentMapLayerSettings TencentMapLayerSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/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';
import { mergeDeep } from '@core/utils'; import { mergeDeep } from '@core/utils';

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

@ -15,14 +15,12 @@
/// ///
import { import {
AfterViewInit,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef, ElementRef,
Input, Input,
OnDestroy, OnDestroy,
OnInit, OnInit,
Renderer2,
TemplateRef, TemplateRef,
ViewChild, ViewChild,
ViewEncapsulation ViewEncapsulation
@ -36,7 +34,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models'; import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models';
import { TbMap } from '@home/components/widget/lib/maps/map'; import { TbMap } from '@home/components/widget/lib/maps/map';
import { MapSetting } from '@home/components/widget/lib/maps/models/map.models'; import { MapSetting } from '@shared/models/widget/maps/map.models';
import { WidgetComponent } from '@home/components/widget/widget.component'; import { WidgetComponent } from '@home/components/widget/widget.component';
import { ImagePipe } from '@shared/pipe/image.pipe'; import { ImagePipe } from '@shared/pipe/image.pipe';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
@ -69,7 +67,6 @@ export class MapWidgetComponent implements OnInit, OnDestroy {
constructor(public widgetComponent: WidgetComponent, constructor(public widgetComponent: WidgetComponent,
private imagePipe: ImagePipe, private imagePipe: ImagePipe,
private sanitizer: DomSanitizer, private sanitizer: DomSanitizer,
private renderer: Renderer2,
private cd: ChangeDetectorRef) { private cd: ChangeDetectorRef) {
} }

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

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { defaultMapSettings, MapSetting, MapType } from '@home/components/widget/lib/maps/models/map.models'; import { defaultMapSettings, MapSetting, MapType } from '@shared/models/widget/maps/map.models';
import { BackgroundSettings, BackgroundType } from '@shared/models/widget-settings.models'; import { BackgroundSettings, BackgroundType } from '@shared/models/widget-settings.models';
import { mergeDeep } from '@core/utils'; import { mergeDeep } from '@core/utils';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';

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

@ -27,7 +27,7 @@ import {
TbMapDatasource, TbMapDatasource,
TbPolygonCoordinates, TbPolygonCoordinates,
TbPolygonRawCoordinates TbPolygonRawCoordinates
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { import {
formattedDataArrayFromDatasourceData, formattedDataArrayFromDatasourceData,
@ -63,7 +63,7 @@ import {
SelectMapEntityPanelComponent SelectMapEntityPanelComponent
} from '@home/components/widget/lib/maps/panels/select-map-entity-panel.component'; } from '@home/components/widget/lib/maps/panels/select-map-entity-panel.component';
import { TbPopoverComponent } from '@shared/components/popover.component'; import { TbPopoverComponent } from '@shared/components/popover.component';
import { createPlaceItemIcon } from '@home/components/widget/lib/maps/models/marker-shape.models'; import { createPlaceItemIcon } from '@shared/models/widget/maps/marker-shape.models';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { MapTimelinePanelComponent } from '@home/components/widget/lib/maps/panels/map-timeline-panel.component'; import { MapTimelinePanelComponent } from '@home/components/widget/lib/maps/panels/map-timeline-panel.component';
@ -464,7 +464,7 @@ export abstract class TbMap<S extends BaseMapSettings> {
} }
} }
private toggleDragMode(e: MouseEvent, button: L.TB.ToolbarButton): void { private toggleDragMode(_e: MouseEvent, button: L.TB.ToolbarButton): void {
if (this.dragMode) { if (this.dragMode) {
this.disableDragMode(); this.disableDragMode();
} else { } else {

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/panels/map-timeline-panel.component.ts

@ -25,7 +25,7 @@ import {
Output, Output,
ViewEncapsulation ViewEncapsulation
} from '@angular/core'; } from '@angular/core';
import { TripTimelineSettings } from '@home/components/widget/lib/maps/models/map.models'; import { TripTimelineSettings } from '@shared/models/widget/maps/map.models';
import { DateFormatProcessor } from '@shared/models/widget-settings.models'; import { DateFormatProcessor } from '@shared/models/widget-settings.models';
import { interval, Subscription } from 'rxjs'; import { interval, Subscription } from 'rxjs';
import { filter } from 'rxjs/operators'; import { filter } from 'rxjs/operators';

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.html

@ -63,7 +63,7 @@
[functionArgs]="['data', 'dsData']" [functionArgs]="['data', 'dsData']"
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
functionTitle="{{ 'widgets.maps.data-layer.color-function' | translate }}" functionTitle="{{ 'widgets.maps.data-layer.color-function' | translate }}"
helpId="widget/lib/map/color_fn"> [helpId]="helpId">
</tb-js-func> </tb-js-func>
</div> </div>
</ng-template> </ng-template>

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component.ts

@ -22,7 +22,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DataLayerColorSettings, DataLayerColorType } from '@home/components/widget/lib/maps/models/map.models'; import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widget/maps/map.models';
@Component({ @Component({
selector: 'tb-data-layer-color-settings-panel', selector: 'tb-data-layer-color-settings-panel',
@ -36,6 +36,9 @@ export class DataLayerColorSettingsPanelComponent extends PageComponent implemen
@Input() @Input()
colorSettings: DataLayerColorSettings; colorSettings: DataLayerColorSettings;
@Input()
helpId = 'widget/lib/map/color_fn';
@Input() @Input()
popover: TbPopoverComponent<DataLayerColorSettingsPanelComponent>; popover: TbPopoverComponent<DataLayerColorSettingsPanelComponent>;

6
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-color-settings.component.ts

@ -19,7 +19,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ComponentStyle } from '@shared/models/widget-settings.models'; import { ComponentStyle } from '@shared/models/widget-settings.models';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service'; import { TbPopoverService } from '@shared/components/popover.service';
import { DataLayerColorSettings, DataLayerColorType } from '@home/components/widget/lib/maps/models/map.models'; import { DataLayerColorSettings, DataLayerColorType } from '@shared/models/widget/maps/map.models';
import { import {
DataLayerColorSettingsPanelComponent DataLayerColorSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component'; } from '@home/components/widget/lib/settings/common/map/data-layer-color-settings-panel.component';
@ -41,6 +41,9 @@ export class DataLayerColorSettingsComponent implements ControlValueAccessor {
@Input() @Input()
disabled: boolean; disabled: boolean;
@Input()
helpId = 'widget/lib/map/color_fn';
DataLayerColorType = DataLayerColorType; DataLayerColorType = DataLayerColorType;
modelValue: DataLayerColorSettings; modelValue: DataLayerColorSettings;
@ -82,6 +85,7 @@ export class DataLayerColorSettingsComponent implements ControlValueAccessor {
} else { } else {
const ctx: any = { const ctx: any = {
colorSettings: this.modelValue, colorSettings: this.modelValue,
helpId: this.helpId
}; };
const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, const colorSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, DataLayerColorSettingsPanelComponent, 'left', true, null, this.viewContainerRef, DataLayerColorSettingsPanelComponent, 'left', true, null,

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.html

@ -46,7 +46,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData']" [functionArgs]="['data', 'dsData']"
functionTitle="{{ (patternType === 'label' ? 'widgets.maps.data-layer.label-function' : 'widgets.maps.data-layer.tooltip-function') | translate }}" functionTitle="{{ (patternType === 'label' ? 'widgets.maps.data-layer.label-function' : 'widgets.maps.data-layer.tooltip-function') | translate }}"
helpId="{{ patternType === 'label' ? 'widget/lib/map/label_fn' : 'widget/lib/map/tooltip_fn' }}"> [helpId]="helpId">
</tb-js-func> </tb-js-func>
<ng-container *ngIf="patternType === 'tooltip'"> <ng-container *ngIf="patternType === 'tooltip'">
<div class="tb-form-row space-between column-xs"> <div class="tb-form-row space-between column-xs">

5
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/data-layer-pattern-settings.component.ts

@ -32,7 +32,7 @@ import {
DataLayerPatternSettings, DataLayerPatternSettings,
DataLayerPatternType, DataLayerPatternType,
DataLayerTooltipSettings, dataLayerTooltipTriggers, dataLayerTooltipTriggerTranslationMap DataLayerTooltipSettings, dataLayerTooltipTriggers, dataLayerTooltipTriggerTranslationMap
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
@ -71,6 +71,9 @@ export class DataLayerPatternSettingsComponent implements OnInit, ControlValueAc
@Input() @Input()
patternType: 'label' | 'tooltip' = 'label'; patternType: 'label' | 'tooltip' = 'label';
@Input()
helpId = 'widget/lib/map/label_fn';
@Input() @Input()
patternTitle: string; patternTitle: string;

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

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, DestroyRef, forwardRef, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core';
import { import {
ControlValueAccessor, ControlValueAccessor,
NG_VALIDATORS, NG_VALIDATORS,
@ -26,7 +26,7 @@ import {
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ImageMapSourceSettings, ImageSourceType } from '@home/components/widget/lib/maps/models/map.models'; import { ImageMapSourceSettings, ImageSourceType } from '@shared/models/widget/maps/map.models';
import { DataKey, DatasourceType, widgetType } from '@shared/models/widget.models'; import { DataKey, DatasourceType, widgetType } from '@shared/models/widget.models';
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-action-button-row.component.ts

@ -24,7 +24,7 @@ import {
ValidationErrors, ValidationErrors,
Validator Validator
} from '@angular/forms'; } from '@angular/forms';
import { MapActionButtonSettings } from '@home/components/widget/lib/maps/models/map.models'; import { MapActionButtonSettings } from '@shared/models/widget/maps/map.models';
import { WidgetAction, WidgetActionType, widgetType } from '@shared/models/widget.models'; import { WidgetAction, WidgetActionType, widgetType } from '@shared/models/widget.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { isEmptyStr } from '@core/utils'; import { isEmptyStr } from '@core/utils';

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

@ -26,7 +26,7 @@ import {
import { import {
defaultMapActionButtonSettings, defaultMapActionButtonSettings,
MapActionButtonSettings MapActionButtonSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { CdkDragDrop } from '@angular/cdk/drag-drop';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

11
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html

@ -256,7 +256,7 @@
<input matInput type="number" min="0" formControlName="pathStrokeWeight" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" min="0" formControlName="pathStrokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
<span matSuffix>px</span> <span matSuffix>px</span>
</mat-form-field> </mat-form-field>
<tb-data-layer-color-settings formControlName="pathStrokeColor"></tb-data-layer-color-settings> <tb-data-layer-color-settings helpId="widget/lib/map/path_color_fn" formControlName="pathStrokeColor"></tb-data-layer-color-settings>
</div> </div>
</div> </div>
<div class="tb-form-panel tb-slide-toggle stroked"> <div class="tb-form-panel tb-slide-toggle stroked">
@ -334,13 +334,14 @@
<input matInput type="number" min="0" formControlName="pointSize" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" min="0" formControlName="pointSize" placeholder="{{ 'widget-config.set' | translate }}">
<span matSuffix>px</span> <span matSuffix>px</span>
</mat-form-field> </mat-form-field>
<tb-data-layer-color-settings formControlName="pointColor"></tb-data-layer-color-settings> <tb-data-layer-color-settings helpId="widget/lib/map/path_point_color_fn" formControlName="pointColor"></tb-data-layer-color-settings>
</div> </div>
</div> </div>
<tb-data-layer-pattern-settings <tb-data-layer-pattern-settings
patternType="tooltip" patternType="tooltip"
patternTitle="{{ 'widgets.maps.data-layer.points.point-tooltip' | translate }}" patternTitle="{{ 'widgets.maps.data-layer.points.point-tooltip' | translate }}"
[context]="context" [context]="context"
helpId="widget/lib/map/path_point_tooltip_fn"
formControlName="pointTooltip"> formControlName="pointTooltip">
</tb-data-layer-pattern-settings> </tb-data-layer-pattern-settings>
</ng-template> </ng-template>
@ -350,7 +351,7 @@
<ng-container *ngIf="['polygons', 'circles'].includes(dataLayerType)"> <ng-container *ngIf="['polygons', 'circles'].includes(dataLayerType)">
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div translate>widgets.maps.data-layer.fill-color</div> <div translate>widgets.maps.data-layer.fill-color</div>
<tb-data-layer-color-settings formControlName="fillColor"></tb-data-layer-color-settings> <tb-data-layer-color-settings helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_fill_color_fn' : 'widget/lib/map/circle_fill_color_fn' }}" formControlName="fillColor"></tb-data-layer-color-settings>
</div> </div>
<div class="tb-form-row space-between"> <div class="tb-form-row space-between">
<div translate>widgets.maps.data-layer.stroke</div> <div translate>widgets.maps.data-layer.stroke</div>
@ -359,18 +360,20 @@
<input matInput type="number" min="0" formControlName="strokeWeight" placeholder="{{ 'widget-config.set' | translate }}"> <input matInput type="number" min="0" formControlName="strokeWeight" placeholder="{{ 'widget-config.set' | translate }}">
<span matSuffix>px</span> <span matSuffix>px</span>
</mat-form-field> </mat-form-field>
<tb-data-layer-color-settings formControlName="strokeColor"></tb-data-layer-color-settings> <tb-data-layer-color-settings helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_stroke_color_fn' : 'widget/lib/map/circle_stroke_color_fn' }}" formControlName="strokeColor"></tb-data-layer-color-settings>
</div> </div>
</div> </div>
</ng-container> </ng-container>
<tb-data-layer-pattern-settings <tb-data-layer-pattern-settings
patternType="label" patternType="label"
[context]="context" [context]="context"
[helpId]="labelHelpId"
formControlName="label"> formControlName="label">
</tb-data-layer-pattern-settings> </tb-data-layer-pattern-settings>
<tb-data-layer-pattern-settings <tb-data-layer-pattern-settings
patternType="tooltip" patternType="tooltip"
[context]="context" [context]="context"
[helpId]="tooltipHelpId"
[hasTooltipOffset]="['trips', 'markers'].includes(dataLayerType)" [hasTooltipOffset]="['trips', 'markers'].includes(dataLayerType)"
formControlName="tooltip"> formControlName="tooltip">
</tb-data-layer-pattern-settings> </tb-data-layer-pattern-settings>

32
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts

@ -29,7 +29,7 @@ import {
MarkerType, pathDecoratorSymbols, pathDecoratorSymbolTranslationMap, MarkerType, pathDecoratorSymbols, pathDecoratorSymbolTranslationMap,
PolygonsDataLayerSettings, PolygonsDataLayerSettings,
ShapeDataLayerSettings, TripsDataLayerSettings ShapeDataLayerSettings, TripsDataLayerSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@ -94,6 +94,36 @@ export class MapDataLayerDialogComponent extends DialogComponent<MapDataLayerDia
dialogTitle: string; dialogTitle: string;
get labelHelpId(): string {
switch (this.dataLayerType) {
case 'trips':
return 'widget/lib/map/label_fn';
case 'markers':
return 'widget/lib/map/label_fn';
case 'polygons':
return 'widget/lib/map/polygon_label_fn';
case 'circles':
return 'widget/lib/map/circle_label_fn';
default:
return 'widget/lib/map/label_fn';
}
}
get tooltipHelpId(): string {
switch (this.dataLayerType) {
case 'trips':
return 'widget/lib/map/tooltip_fn';
case 'markers':
return 'widget/lib/map/tooltip_fn';
case 'polygons':
return 'widget/lib/map/polygon_tooltip_fn';
case 'circles':
return 'widget/lib/map/circle_tooltip_fn';
default:
return 'widget/lib/map/tooltip_fn';
}
}
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: MapDataLayerDialogData, @Inject(MAT_DIALOG_DATA) public data: MapDataLayerDialogData,

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-row.component.ts

@ -42,7 +42,7 @@ import {
MarkersDataLayerSettings, MarkersDataLayerSettings,
PolygonsDataLayerSettings, PolygonsDataLayerSettings,
TripsDataLayerSettings TripsDataLayerSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { DataKey, DatasourceType, datasourceTypeTranslationMap, widgetType } from '@shared/models/widget.models'; import { DataKey, DatasourceType, datasourceTypeTranslationMap, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';

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

@ -35,7 +35,7 @@ import {
mapDataLayerValid, mapDataLayerValid,
mapDataLayerValidator, mapDataLayerValidator,
MapType MapType
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { MapSettingsComponent } from '@home/components/widget/lib/settings/common/map/map-settings.component'; import { MapSettingsComponent } from '@home/components/widget/lib/settings/common/map/map-settings.component';
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-source-row.component.ts

@ -33,7 +33,7 @@ import {
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AdditionalMapDataSourceSettings } from '@home/components/widget/lib/maps/models/map.models'; import { AdditionalMapDataSourceSettings } from '@shared/models/widget/maps/map.models';
import { DataKey, DatasourceType, datasourceTypeTranslationMap, widgetType } from '@shared/models/widget.models'; import { DataKey, DatasourceType, datasourceTypeTranslationMap, widgetType } from '@shared/models/widget.models';
import { EntityType } from '@shared/models/entity-type.models'; import { EntityType } from '@shared/models/entity-type.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';

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

@ -33,7 +33,7 @@ import {
additionalMapDataSourceValid, additionalMapDataSourceValid,
additionalMapDataSourceValidator, additionalMapDataSourceValidator,
defaultAdditionalMapDataSourceSettings defaultAdditionalMapDataSourceSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models'; import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
@Component({ @Component({

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

@ -53,7 +53,7 @@ import {
openStreetMapLayerTranslationMap, openStreetMapLayerTranslationMap,
tencentLayerTranslationMap, tencentLayerTranslationMap,
tencentLayerTypes tencentLayerTypes
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { deepClone } from '@core/utils'; import { deepClone } from '@core/utils';
import { import {
MapLayerSettingsPanelComponent MapLayerSettingsPanelComponent

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

@ -33,7 +33,7 @@ import {
openStreetMapLayerTranslationMap, openStreetMapLayerTranslationMap,
tencentLayerTranslationMap, tencentLayerTranslationMap,
tencentLayerTypes tencentLayerTypes
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({

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

@ -35,7 +35,7 @@ import {
mapLayerValid, mapLayerValid,
mapLayerValidator, mapLayerValidator,
MapProvider MapProvider
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
@Component({ @Component({
selector: 'tb-map-layers', selector: 'tb-map-layers',

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

@ -38,7 +38,7 @@ import {
MapType, MapType,
mapZoomActions, mapZoomActions,
mapZoomActionTranslationMap mapZoomActionTranslationMap
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { merge, Observable } from 'rxjs'; import { merge, Observable } from 'rxjs';
import { coerceBoolean } from '@shared/decorators/coercion'; import { coerceBoolean } from '@shared/decorators/coercion';
@ -254,7 +254,6 @@ export class MapSettingsComponent implements OnInit, ControlValueAccessor, Valid
private updateDragButtonModeSettings() { private updateDragButtonModeSettings() {
const markers: MapDataLayerSettings[] = this.mapSettingsFormGroup.get('markers').value; const markers: MapDataLayerSettings[] = this.mapSettingsFormGroup.get('markers').value;
const circles: MapDataLayerSettings[] = this.mapSettingsFormGroup.get('circles').value;
let dragModeButtonSettingsEnabled = markers.some(d => d.edit && d.edit.enabledActions && d.edit.enabledActions.includes(DataLayerEditAction.move)); let dragModeButtonSettingsEnabled = markers.some(d => d.edit && d.edit.enabledActions && d.edit.enabledActions.includes(DataLayerEditAction.move));
if (!dragModeButtonSettingsEnabled) { if (!dragModeButtonSettingsEnabled) {
const polygons: MapDataLayerSettings[] = this.mapSettingsFormGroup.get('polygons').value; const polygons: MapDataLayerSettings[] = this.mapSettingsFormGroup.get('polygons').value;

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

@ -27,7 +27,7 @@ import {
} from '@angular/forms'; } from '@angular/forms';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MarkerClusteringSettings } from '@home/components/widget/lib/maps/models/map.models'; import { MarkerClusteringSettings } from '@shared/models/widget/maps/map.models';
import { merge } from 'rxjs'; import { merge } from 'rxjs';
@Component({ @Component({

2
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/marker-image-settings-panel.component.ts

@ -22,7 +22,7 @@ import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MarkerImageSettings, MarkerImageType } from '@home/components/widget/lib/maps/models/map.models'; import { MarkerImageSettings, MarkerImageType } from '@shared/models/widget/maps/map.models';
@Component({ @Component({
selector: 'tb-marker-image-settings-panel', selector: 'tb-marker-image-settings-panel',

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

@ -18,7 +18,7 @@ import { ChangeDetectorRef, Component, forwardRef, Input, Renderer2, ViewContain
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service'; import { TbPopoverService } from '@shared/components/popover.service';
import { MarkerImageSettings, MarkerImageType } from '@home/components/widget/lib/maps/models/map.models'; import { MarkerImageSettings, MarkerImageType } from '@shared/models/widget/maps/map.models';
import { import {
MarkerImageSettingsPanelComponent MarkerImageSettingsPanelComponent
} from '@home/components/widget/lib/settings/common/map/marker-image-settings-panel.component'; } from '@home/components/widget/lib/settings/common/map/marker-image-settings-panel.component';

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

@ -30,5 +30,5 @@
<div *ngIf="markerType === MarkerType.icon" matButtonIcon style="object-fit: contain; width: 24px; height: 24px;" [innerHTML]="iconPreview$ | async" [class.disabled]="disabled"> <div *ngIf="markerType === MarkerType.icon" matButtonIcon style="object-fit: contain; width: 24px; height: 24px;" [innerHTML]="iconPreview$ | async" [class.disabled]="disabled">
</div> </div>
</button> </button>
<tb-data-layer-color-settings formControlName="color"></tb-data-layer-color-settings> <tb-data-layer-color-settings helpId="widget/lib/map/color_fn" formControlName="color"></tb-data-layer-color-settings>
</div> </div>

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

@ -33,7 +33,7 @@ import {
} from '@angular/forms'; } from '@angular/forms';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
import { TbPopoverService } from '@shared/components/popover.service'; import { TbPopoverService } from '@shared/components/popover.service';
import { MarkerIconSettings, MarkerShapeSettings, MarkerType } from '@home/components/widget/lib/maps/models/map.models'; import { MarkerIconSettings, MarkerShapeSettings, MarkerType } from '@shared/models/widget/maps/map.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { DomSanitizer, SafeHtml, SafeUrl } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml, SafeUrl } from '@angular/platform-browser';
@ -41,7 +41,7 @@ import { MatIconRegistry } from '@angular/material/icon';
import { import {
createColorMarkerIconElement, createColorMarkerIconElement,
createColorMarkerShapeURI createColorMarkerShapeURI
} from '@home/components/widget/lib/maps/models/marker-shape.models'; } from '@shared/models/widget/maps/marker-shape.models';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { map, share } from 'rxjs/operators'; import { map, share } from 'rxjs/operators';
import { MarkerShapesComponent } from '@home/components/widget/lib/settings/common/map/marker-shapes.component'; import { MarkerShapesComponent } from '@home/components/widget/lib/settings/common/map/marker-shapes.component';

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

@ -23,7 +23,7 @@ import {
createColorMarkerShapeURI, createColorMarkerShapeURI,
MarkerShape, markerShapes, MarkerShape, markerShapes,
tripMarkerShapes tripMarkerShapes
} from '@home/components/widget/lib/maps/models/marker-shape.models'; } from '@shared/models/widget/maps/marker-shape.models';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';

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

@ -29,16 +29,8 @@ import { merge } from 'rxjs';
import { WidgetService } from '@core/http/widget.service'; import { WidgetService } from '@core/http/widget.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { import {
DataLayerPatternSettings,
DataLayerPatternType,
DataLayerTooltipSettings,
dataLayerTooltipTriggers,
dataLayerTooltipTriggerTranslationMap,
pathDecoratorSymbols, pathDecoratorSymbolTranslationMap,
TripTimelineSettings TripTimelineSettings
} from '@home/components/widget/lib/maps/models/map.models'; } from '@shared/models/widget/maps/map.models';
import { coerceBoolean } from '@shared/decorators/coercion';
import { MapSettingsContext } from '@home/components/widget/lib/settings/common/map/map-settings.component.models';
@Component({ @Component({
selector: 'tb-trip-timeline-settings', selector: 'tb-trip-timeline-settings',
@ -166,7 +158,4 @@ export class TripTimelineSettingsComponent implements OnInit, ControlValueAccess
this.modelValue = this.tripTimelineSettingsFormGroup.getRawValue(); this.modelValue = this.tripTimelineSettingsFormGroup.getRawValue();
this.propagateChange(this.modelValue); this.propagateChange(this.modelValue);
} }
protected readonly pathDecoratorSymbols = pathDecoratorSymbols;
protected readonly pathDecoratorSymbolTranslationMap = pathDecoratorSymbolTranslationMap;
} }

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

@ -66,7 +66,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-label-function' | translate }}" functionTitle="{{ 'widgets.maps.circle-label-function' | translate }}"
helpId="widget/lib/map/label_fn"> helpId="widget/lib/map-legacy/label_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -110,7 +110,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-tooltip-function' | translate }}" functionTitle="{{ 'widgets.maps.circle-tooltip-function' | translate }}"
helpId="widget/lib/map/polygon_tooltip_fn"> helpId="widget/lib/map-legacy/polygon_tooltip_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -146,7 +146,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-fill-color-function' | translate }}" functionTitle="{{ 'widgets.maps.circle-fill-color-function' | translate }}"
helpId="widget/lib/map/polygon_color_fn"> helpId="widget/lib/map-legacy/polygon_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -186,7 +186,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.circle-stroke-color-function' | translate }}" functionTitle="{{ 'widgets.maps.circle-stroke-color-function' | translate }}"
helpId="widget/lib/map/polygon_color_fn"> helpId="widget/lib/map-legacy/polygon_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -82,7 +82,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'childCount']" [functionArgs]="['data', 'childCount']"
functionTitle="{{ 'widgets.maps.marker-color-function' | translate }}" functionTitle="{{ 'widgets.maps.marker-color-function' | translate }}"
helpId="widget/lib/map/clustering_color_fn"> helpId="widget/lib/map-legacy/clustering_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -35,7 +35,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['origXPos', 'origYPos', 'data', 'dsData', 'dsIndex', 'aspect']" [functionArgs]="['origXPos', 'origYPos', 'data', 'dsData', 'dsIndex', 'aspect']"
functionTitle="{{ 'widgets.maps.position-function' | translate }}" functionTitle="{{ 'widgets.maps.position-function' | translate }}"
helpId="widget/lib/map/position_fn"> helpId="widget/lib/map-legacy/position_fn">
</tb-js-func> </tb-js-func>
<mat-checkbox formControlName="draggableMarker"> <mat-checkbox formControlName="draggableMarker">
{{ 'widgets.maps.draggable-marker' | translate }} {{ 'widgets.maps.draggable-marker' | translate }}
@ -68,7 +68,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.label-function' | translate }}" functionTitle="{{ 'widgets.maps.label-function' | translate }}"
helpId="widget/lib/map/label_fn"> helpId="widget/lib/map-legacy/label_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -112,7 +112,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}" functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}"
helpId="widget/lib/map/tooltip_fn"> helpId="widget/lib/map-legacy/tooltip_fn">
</tb-js-func> </tb-js-func>
<section class="flex flex-row xs:flex-col gt-xs:gap-2"> <section class="flex flex-row xs:flex-col gt-xs:gap-2">
<mat-form-field class="flex-1"> <mat-form-field class="flex-1">
@ -151,7 +151,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.color-function' | translate }}" functionTitle="{{ 'widgets.maps.color-function' | translate }}"
helpId="widget/lib/map/color_fn"> helpId="widget/lib/map-legacy/color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -185,7 +185,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'images', 'dsData', 'dsIndex']" [functionArgs]="['data', 'images', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}" functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}"
helpId="widget/lib/map/marker_image_fn"> helpId="widget/lib/map-legacy/marker_image_fn">
</tb-js-func> </tb-js-func>
<tb-multiple-gallery-image-input [class.!hidden]="!markersSettingsFormGroup.get('useMarkerImageFunction').value" <tb-multiple-gallery-image-input [class.!hidden]="!markersSettingsFormGroup.get('useMarkerImageFunction').value"
label="{{ 'widgets.maps.marker-images' | translate }}" label="{{ 'widgets.maps.marker-images' | translate }}"

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

@ -66,7 +66,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-label-function' | translate }}" functionTitle="{{ 'widgets.maps.polygon-label-function' | translate }}"
helpId="widget/lib/map/label_fn"> helpId="widget/lib/map-legacy/label_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -110,7 +110,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-tooltip-function' | translate }}" functionTitle="{{ 'widgets.maps.polygon-tooltip-function' | translate }}"
helpId="widget/lib/map/polygon_tooltip_fn"> helpId="widget/lib/map-legacy/polygon_tooltip_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -146,7 +146,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-color-function' | translate }}" functionTitle="{{ 'widgets.maps.polygon-color-function' | translate }}"
helpId="widget/lib/map/polygon_color_fn"> helpId="widget/lib/map-legacy/polygon_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -186,7 +186,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.polygon-stroke-color-function' | translate }}" functionTitle="{{ 'widgets.maps.polygon-stroke-color-function' | translate }}"
helpId="widget/lib/map/polygon_color_fn"> helpId="widget/lib/map-legacy/polygon_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -85,7 +85,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}" functionTitle="{{ 'widgets.maps.tooltip-function' | translate }}"
helpId="widget/lib/map/tooltip_fn"> helpId="widget/lib/map-legacy/tooltip_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -50,7 +50,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.label-function' | translate }}" functionTitle="{{ 'widgets.maps.label-function' | translate }}"
helpId="widget/lib/map/label_fn"> helpId="widget/lib/map-legacy/label_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -84,7 +84,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'images', 'dsData', 'dsIndex']" [functionArgs]="['data', 'images', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}" functionTitle="{{ 'widgets.maps.marker-image-function' | translate }}"
helpId="widget/lib/map/marker_image_fn"> helpId="widget/lib/map-legacy/marker_image_fn">
</tb-js-func> </tb-js-func>
<tb-multiple-gallery-image-input [class.!hidden]="!tripAnimationMarkerSettingsFormGroup.get('useMarkerImageFunction').value" <tb-multiple-gallery-image-input [class.!hidden]="!tripAnimationMarkerSettingsFormGroup.get('useMarkerImageFunction').value"
label="{{ 'widgets.maps.marker-images' | translate }}" label="{{ 'widgets.maps.marker-images' | translate }}"

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

@ -51,7 +51,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.path-color-function' | translate }}" functionTitle="{{ 'widgets.maps.path-color-function' | translate }}"
helpId="widget/lib/map/path_color_fn"> helpId="widget/lib/map-legacy/path_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -59,7 +59,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.point-color-function' | translate }}" functionTitle="{{ 'widgets.maps.point-color-function' | translate }}"
helpId="widget/lib/map/path_point_color_fn"> helpId="widget/lib/map-legacy/path_point_color_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>
@ -80,7 +80,7 @@
[globalVariables]="functionScopeVariables" [globalVariables]="functionScopeVariables"
[functionArgs]="['data', 'dsData', 'dsIndex']" [functionArgs]="['data', 'dsData', 'dsIndex']"
functionTitle="{{ 'widgets.maps.point-as-anchor-function' | translate }}" functionTitle="{{ 'widgets.maps.point-as-anchor-function' | translate }}"
helpId="widget/lib/map/trip_point_as_anchor_fn"> helpId="widget/lib/map-legacy/trip_point_as_anchor_fn">
</tb-js-func> </tb-js-func>
</ng-template> </ng-template>
</mat-expansion-panel> </mat-expansion-panel>

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

@ -19,7 +19,7 @@ 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 { isDefinedAndNotNull, mergeDeep, mergeDeepIgnoreArray } from '@core/utils'; import { isDefinedAndNotNull, mergeDeepIgnoreArray } from '@core/utils';
import { mapWidgetDefaultSettings, MapWidgetSettings } from '@home/components/widget/lib/maps/map-widget.models'; import { mapWidgetDefaultSettings, MapWidgetSettings } from '@home/components/widget/lib/maps/map-widget.models';
import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models';

12
ui-ngx/src/app/shared/import-export/import-export.service.ts

@ -307,23 +307,23 @@ export class ImportExportService {
} }
} }
return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget, return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget,
aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize); aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize, widgetItem.widgetExportInfo);
} }
)); ));
} else { } else {
return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget, return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget,
aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize); aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize, widgetItem.widgetExportInfo);
} }
} }
) )
); );
} else { } else {
return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget, return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget,
aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize); aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize, widgetItem.widgetExportInfo);
} }
} else { } else {
return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget, return this.addImportedWidget(dashboard, targetState, targetLayoutFunction, widget,
aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize); aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, originalColumns, originalSize, widgetItem.widgetExportInfo);
} }
} }
}), }),
@ -1033,11 +1033,11 @@ export class ImportExportService {
filtersInfo: FiltersInfo, filtersInfo: FiltersInfo,
onAliasesUpdateFunction: () => void, onAliasesUpdateFunction: () => void,
onFiltersUpdateFunction: () => void, onFiltersUpdateFunction: () => void,
originalColumns: number, originalSize: WidgetSize): Observable<ImportWidgetResult> { originalColumns: number, originalSize: WidgetSize, widgetExportInfo: any): Observable<ImportWidgetResult> {
return targetLayoutFunction().pipe( return targetLayoutFunction().pipe(
mergeMap((targetLayout) => this.itembuffer.addWidgetToDashboard(dashboard, targetState, targetLayout, mergeMap((targetLayout) => this.itembuffer.addWidgetToDashboard(dashboard, targetState, targetLayout,
widget, aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction, widget, aliasesInfo, filtersInfo, onAliasesUpdateFunction, onFiltersUpdateFunction,
originalColumns, originalSize, -1, -1).pipe( originalColumns, originalSize, -1, -1, 'default', widgetExportInfo).pipe(
map(() => ({widget, layoutId: targetLayout} as ImportWidgetResult)) map(() => ({widget, layoutId: targetLayout} as ImportWidgetResult))
) )
)); ));

39
ui-ngx/src/app/shared/models/alias.models.ts

@ -18,6 +18,7 @@ import { EntityType } from '@shared/models/entity-type.models';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { EntitySearchDirection, RelationEntityTypeFilter } from '@shared/models/relation.models'; import { EntitySearchDirection, RelationEntityTypeFilter } from '@shared/models/relation.models';
import { EntityFilter } from '@shared/models/query/query.models'; import { EntityFilter } from '@shared/models/query/query.models';
import { guid, isEqual } from '@core/utils';
export enum AliasFilterType { export enum AliasFilterType {
singleEntity = 'singleEntity', singleEntity = 'singleEntity',
@ -210,3 +211,41 @@ export interface EntityAliasFilterResult {
entityFilter: EntityFilter; entityFilter: EntityFilter;
entityParamName?: string; entityParamName?: string;
} }
export const getEntityAliasId = (entityAliases: EntityAliases, aliasInfo: EntityAliasInfo): string => {
let newAliasId: string;
for (const aliasId of Object.keys(entityAliases)) {
if (isEntityAliasEqual(entityAliases[aliasId], aliasInfo)) {
newAliasId = aliasId;
break;
}
}
if (!newAliasId) {
const newAliasName = createEntityAliasName(entityAliases, aliasInfo.alias);
newAliasId = guid();
entityAliases[newAliasId] = {id: newAliasId, alias: newAliasName, filter: aliasInfo.filter};
}
return newAliasId;
}
const isEntityAliasEqual = (alias1: EntityAliasInfo, alias2: EntityAliasInfo): boolean => {
return isEqual(alias1.filter, alias2.filter);
}
const createEntityAliasName = (entityAliases: EntityAliases, alias: string): string => {
let c = 0;
let newAlias = alias;
let unique = false;
while (!unique) {
unique = true;
for (const entAliasId of Object.keys(entityAliases)) {
const entAlias = entityAliases[entAliasId];
if (newAlias === entAlias.alias) {
c++;
newAlias = alias + c;
unique = false;
}
}
}
return newAlias;
}

40
ui-ngx/src/app/shared/models/query/query.models.ts

@ -23,6 +23,7 @@ import { EntityType } from '@shared/models/entity-type.models';
import { DataKey, Datasource, DatasourceType } from '@shared/models/widget.models'; import { DataKey, Datasource, DatasourceType } from '@shared/models/widget.models';
import { PageData } from '@shared/models/page/page-data'; import { PageData } from '@shared/models/page/page-data';
import { import {
guid,
isArraysEqualIgnoreUndefined, isArraysEqualIgnoreUndefined,
isDefined, isDefined,
isDefinedAndNotNull, isDefinedAndNotNull,
@ -921,3 +922,42 @@ export function updateDatasourceFromEntityInfo(datasource: Datasource, entity: E
} }
} }
} }
export const getFilterId = (filters: Filters, filterInfo: FilterInfo): string => {
let newFilterId: string;
for (const filterId of Object.keys(filters)) {
if (isFilterEqual(filters[filterId], filterInfo)) {
newFilterId = filterId;
break;
}
}
if (!newFilterId) {
const newFilterName = createFilterName(filters, filterInfo.filter);
newFilterId = guid();
filters[newFilterId] = {id: newFilterId, filter: newFilterName,
keyFilters: filterInfo.keyFilters, editable: filterInfo.editable};
}
return newFilterId;
}
const isFilterEqual = (filter1: FilterInfo, filter2: FilterInfo): boolean => {
return isEqual(filter1.keyFilters, filter2.keyFilters);
}
const createFilterName = (filters: Filters, filter: string): string => {
let c = 0;
let newFilter = filter;
let unique = false;
while (!unique) {
unique = true;
for (const entFilterId of Object.keys(filters)) {
const entFilter = filters[entFilterId];
if (newFilter === entFilter.filter) {
c++;
newFilter = filter + c;
unique = false;
}
}
}
return newFilter;
}

151
ui-ngx/src/app/shared/models/widget/maps/map-export.models.ts

@ -0,0 +1,151 @@
///
/// Copyright © 2016-2025 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 { EntityAliases, EntityAliasInfo, getEntityAliasId } from '@shared/models/alias.models';
import { FilterInfo, Filters, getFilterId } from '@shared/models/query/query.models';
import { Dashboard } from '@shared/models/dashboard.models';
import { DatasourceType, Widget } from '@shared/models/widget.models';
import { BaseMapSettings, MapDataSourceSettings, MapType } from '@shared/models/widget/maps/map.models';
import { WidgetExportDefinition } from '@shared/models/widget/widget-export.models';
interface ExportDataSourceInfo {
aliases: {[dataLayerIndex: number]: EntityAliasInfo};
filters: {[dataLayerIndex: number]: FilterInfo};
}
interface MapDatasourcesInfo {
trips?: ExportDataSourceInfo;
markers?: ExportDataSourceInfo;
polygons?: ExportDataSourceInfo;
circles?: ExportDataSourceInfo;
additionalDataSources?: ExportDataSourceInfo;
}
export const MapExportDefinition: WidgetExportDefinition<MapDatasourcesInfo> = {
testWidget(widget: Widget): boolean {
if (widget?.config?.settings) {
const settings = widget.config.settings;
if (settings.mapType && [MapType.image, MapType.geoMap].includes(settings.mapType)) {
if (settings.trips && Array.isArray(settings.trips)) {
return true;
}
if (settings.markers && Array.isArray(settings.markers)) {
return true;
}
if (settings.polygons && Array.isArray(settings.polygons)) {
return true;
}
if (settings.circles && Array.isArray(settings.circles)) {
return true;
}
}
}
return false;
},
prepareExportInfo(dashboard: Dashboard, widget: Widget): MapDatasourcesInfo {
const settings: BaseMapSettings = widget.config.settings as BaseMapSettings;
const info: MapDatasourcesInfo = {};
if (settings.trips?.length) {
info.trips = prepareExportDataSourcesInfo(dashboard, settings.trips);
}
if (settings.markers?.length) {
info.markers = prepareExportDataSourcesInfo(dashboard, settings.markers);
}
if (settings.polygons?.length) {
info.polygons = prepareExportDataSourcesInfo(dashboard, settings.polygons);
}
if (settings.circles?.length) {
info.circles = prepareExportDataSourcesInfo(dashboard, settings.circles);
}
if (settings.additionalDataSources?.length) {
info.additionalDataSources = prepareExportDataSourcesInfo(dashboard, settings.additionalDataSources);
}
return info;
},
updateFromExportInfo(widget: Widget, entityAliases: EntityAliases, filters: Filters, info: MapDatasourcesInfo): void {
const settings: BaseMapSettings = widget.config.settings as BaseMapSettings;
if (info?.trips) {
updateMapDatasourceFromExportInfo(entityAliases, filters, settings.trips, info.trips);
}
if (info?.markers) {
updateMapDatasourceFromExportInfo(entityAliases, filters, settings.markers, info.markers);
}
if (info?.polygons) {
updateMapDatasourceFromExportInfo(entityAliases, filters, settings.polygons, info.polygons);
}
if (info?.circles) {
updateMapDatasourceFromExportInfo(entityAliases, filters, settings.circles, info.circles);
}
if (info?.additionalDataSources) {
updateMapDatasourceFromExportInfo(entityAliases, filters, settings.additionalDataSources, info.additionalDataSources);
}
}
};
const updateMapDatasourceFromExportInfo = (entityAliases: EntityAliases,
filters: Filters, settings: MapDataSourceSettings[], info: ExportDataSourceInfo): void => {
if (info.aliases) {
for (const dsIndexStr of Object.keys(info.aliases)) {
const dsIndex = Number(dsIndexStr);
if (settings[dsIndex] && settings[dsIndex].dsType === DatasourceType.entity) {
const aliasInfo = info.aliases[dsIndex];
settings[dsIndex].dsEntityAliasId = getEntityAliasId(entityAliases, aliasInfo);
}
}
}
if (info.filters) {
for (const dsIndexStr of Object.keys(info.filters)) {
const dsIndex = Number(dsIndexStr);
if (settings[dsIndex] && settings[dsIndex].dsType === DatasourceType.entity) {
const filterInfo = info.filters[dsIndex];
settings[dsIndex].dsFilterId = getFilterId(filters, filterInfo);
}
}
}
}
const prepareExportDataSourcesInfo = (dashboard: Dashboard, settings: MapDataSourceSettings[]): ExportDataSourceInfo => {
const info: ExportDataSourceInfo = {
aliases: {},
filters: {}
};
settings.forEach((dsSettings, index) => {
prepareExportDataSourceInfo(dashboard, info, dsSettings, index);
});
return info;
}
const prepareExportDataSourceInfo = (dashboard: Dashboard, info: ExportDataSourceInfo, settings: MapDataSourceSettings, index: number): void => {
if (settings.dsType === DatasourceType.entity) {
const entityAlias = dashboard.configuration.entityAliases[settings.dsEntityAliasId];
if (entityAlias) {
info.aliases[index] = {
alias: entityAlias.alias,
filter: entityAlias.filter
};
}
if (settings.dsFilterId && dashboard.configuration.filters) {
const filter = dashboard.configuration.filters[settings.dsFilterId];
if (filter) {
info.filters[index] = {
filter: filter.filter,
keyFilters: filter.keyFilters,
editable: filter.editable
};
}
}
}
}

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

@ -39,7 +39,7 @@ import { TbFunction } from '@shared/models/js-function.models';
import { Observable, Observer, of, switchMap } from 'rxjs'; import { Observable, Observer, of, switchMap } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ImagePipe } from '@shared/pipe/image.pipe'; import { ImagePipe } from '@shared/pipe/image.pipe';
import { MarkerShape } from '@home/components/widget/lib/maps/models/marker-shape.models'; import { MarkerShape } from '@shared/models/widget/maps/marker-shape.models';
import { DateFormatSettings, simpleDateFormat } from '@shared/models/widget-settings.models'; import { DateFormatSettings, simpleDateFormat } from '@shared/models/widget-settings.models';
export enum MapType { export enum MapType {

2
ui-ngx/src/app/modules/home/components/widget/lib/maps/models/marker-shape.models.ts → ui-ngx/src/app/shared/models/widget/maps/marker-shape.models.ts

@ -205,7 +205,7 @@ export const createColorMarkerIconElement = (iconRegistry: MatIconRegistry, domS
let placeItemIconURI$: Observable<string>; let placeItemIconURI$: Observable<string>;
export const createPlaceItemIcon= (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer): Observable<string> => { export const createPlaceItemIcon = (iconRegistry: MatIconRegistry, domSanitizer: DomSanitizer): Observable<string> => {
if (placeItemIconURI$) { if (placeItemIconURI$) {
return placeItemIconURI$; return placeItemIconURI$;
} }

35
ui-ngx/src/app/shared/models/widget/widget-export.models.ts

@ -0,0 +1,35 @@
///
/// Copyright © 2016-2025 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 { Widget } from '@shared/models/widget.models';
import { Dashboard } from '@shared/models/dashboard.models';
import { EntityAliases } from '@shared/models/alias.models';
import { Filters } from '@shared/models/query/query.models';
import { MapExportDefinition } from '@shared/models/widget/maps/map-export.models';
export interface WidgetExportDefinition<T = any> {
testWidget(widget: Widget): boolean;
prepareExportInfo(dashboard: Dashboard, widget: Widget): T;
updateFromExportInfo(widget: Widget, entityAliases: EntityAliases, filters: Filters, info: T): void;
}
const widgetExportDefinitions: WidgetExportDefinition[] = [
MapExportDefinition
];
export const getWidgetExportDefinition = (widget: Widget): WidgetExportDefinition => {
return widgetExportDefinitions.find(def => def.testWidget(widget));
}

65
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/clustering_color_fn.md

@ -0,0 +1,65 @@
#### Clustering marker function
<div class="divider"></div>
<br/>
*function (data, childCount): string*
A JavaScript function used to compute clustering marker color.
**Parameters:**
<ul>
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code>
- the array of total markers contained within each cluster.<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>childCount:</b> <code>number</code> - the total number of markers contained within that cluster
</li>
</ul>
**Returns:**
Should return string value presenting color of the marker.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
##### Examples
<ul>
<li>
Calculate color depending on temperature telemetry value:
</li>
```javascript
let customColor;
for (let markerData of data) {
if (markerData.temperature > 40) {
customColor = 'red'
}
}
return customColor ? customColor : 'green';
{:copy-code}
```
<li>
Calculate color depending on childCount:
</li>
```javascript
if (childCount < 10) {
return 'green';
} else if (childCount < 100) {
return 'yellow';
} else {
return 'red';
}
{:copy-code}
```
</ul>
<br>
<br>

42
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/color_fn.md

@ -0,0 +1,42 @@
#### Marker color function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute color of the marker.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting color of the marker.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
##### Examples
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

40
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/label_fn.md

@ -0,0 +1,40 @@
#### Marker label function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code of the marker label.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML of the marker label.
<div class="divider"></div>
##### Examples
* Display styled label with corresponding latest telemetry data for `energy meter` or `thermometer` device types:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<span style="color:orange;">${entityName}, ${energy:2} kWt</span>';
} else if (deviceType == "thermometer") {
return '<span style="color:blue;">${entityName}, ${temperature:2} °C</span>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

10
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/map_fn_args.md

@ -0,0 +1,10 @@
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a></code> - A <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> object associated with marker or data point of the route.<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code> - All available data associated with markers or routes data points as array of <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> objects<br/>
resolved from configured datasources. Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>
and provides access to other entity attributes/timeseries declared in widget datasource configuration.
</li>
<li><b>dsIndex</b> <code>number</code> - index of the current marker data or route data point in <code>dsData</code> array.<br>
<strong>Note: </strong> The <code>data</code> argument is equivalent to <code>dsData[dsIndex]</code> expression.
</li>

62
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/marker_image_fn.md

@ -0,0 +1,62 @@
#### Marker image function
<div class="divider"></div>
<br/>
*function (data, images, dsData, dsIndex): {url: string, size: number}*
A JavaScript function used to compute marker image.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return marker image data having the following structure:
```typescript
{
url: string,
size: number
}
```
- *url* - marker image url;
- *size* - marker image size;
In case no data is returned, default marker image will be used.
<div class="divider"></div>
##### Examples
<ul>
<li>
Calculate image url depending on <code>temperature</code> telemetry value for <code>thermometer</code> device type.<br>
Let's assume 4 images are defined in <b>Marker images</b> section. Each image corresponds to particular temperature level:
</li>
</ul>
```javascript
var type = data['Type'];
if (type == 'thermometer') {
var res = {
url: images[0],
size: 40
}
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120;
var index = Math.min(3, Math.floor(4 * percent));
res.url = images[index];
}
return res;
}
{:copy-code}
```
<br>
<br>

42
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/path_color_fn.md

@ -0,0 +1,42 @@
#### Path color function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute color of the trip path.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting color of the trip path.
In case no data is returned, color value from **Path color** settings field will be used.
<div class="divider"></div>
##### Examples
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

43
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/path_point_color_fn.md

@ -0,0 +1,43 @@
#### Path point color function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute color of the trip path point.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting color of the trip path point.
In case no data is returned, color value from **Point color** settings field will be used.
<div class="divider"></div>
##### Examples
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

2
ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_color_fn.md → ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/polygon_color_fn.md

@ -10,7 +10,7 @@ A JavaScript function used to compute color of the polygon.
**Parameters:** **Parameters:**
<ul> <ul>
{% include widget/lib/map/map_fn_args %} {% include widget/lib/map-legacy/map_fn_args %}
</ul> </ul>
**Returns:** **Returns:**

40
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/polygon_tooltip_fn.md

@ -0,0 +1,40 @@
#### Polygon tooltip function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code to be displayed in the polygon tooltip.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML for the polygon tooltip.
<div class="divider"></div>
##### Examples
* Display details with corresponding telemetry data for `energy meter` or `thermostat` device types:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermostat") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

65
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/position_fn.md

@ -0,0 +1,65 @@
#### Position conversion function
<div class="divider"></div>
<br/>
*function (origXPos, origYPos, data, dsData, dsIndex, aspect): {x: number, y: number}*
A JavaScript function used to convert original relative x, y coordinates of the marker.
**Parameters:**
<ul>
<li><b>origXPos:</b> <code>number</code> - original relative x coordinate as double from 0 to 1.</li>
<li><b>origYPos:</b> <code>number</code> - original relative y coordinate as double from 0 to 1.</li>
{% include widget/lib/map-legacy/map_fn_args %}
<li><b>aspect:</b> <code>number</code> - image map aspect ratio.</li>
</ul>
**Returns:**
Should return position data having the following structure:
```typescript
{
x: number,
y: number
}
```
- *x* - new relative x coordinate as double from 0 to 1;
- *y* - new relative y coordinate as double from 0 to 1;
<div class="divider"></div>
##### Examples
* Scale the coordinates to half the original:
```javascript
return {x: origXPos / 2, y: origYPos / 2};
{:copy-code}
```
* Detect markers with same positions and place them with minimum overlap:
```javascript
var xPos = data.xPos;
var yPos = data.yPos;
var locationGroup = dsData.filter((item) => item.xPos === xPos && item.yPos === yPos);
if (locationGroup.length > 1) {
const count = locationGroup.length;
const index = locationGroup.indexOf(data);
const radius = 0.035;
const angle = (360 / count) * index - 45;
const x = xPos + radius * Math.sin(angle*Math.PI/180) / aspect;
const y = yPos + radius * Math.cos(angle*Math.PI/180);
return {x: x, y: y};
} else {
return {x: xPos, y: yPos};
}
{:copy-code}
```
<br>
<br>

40
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/tooltip_fn.md

@ -0,0 +1,40 @@
#### Marker tooltip function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): string*
A JavaScript function used to compute text or HTML code to be displayed in the marker, point or polygon tooltip.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div>
##### Examples
* Display details with corresponding telemetry data for `thermostat` device type:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermometer") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

34
ui-ngx/src/assets/help/en_US/widget/lib/map-legacy/trip_point_as_anchor_fn.md

@ -0,0 +1,34 @@
#### Point as anchor function
<div class="divider"></div>
<br/>
*function (data, dsData, dsIndex): boolean*
A JavaScript function evaluating whether to use trip point as time anchor used in time selector.
**Parameters:**
<ul>
{% include widget/lib/map-legacy/map_fn_args %}
</ul>
**Returns:**
`true` if the point should be decided as anchor, `false` otherwise.
In case no data is returned, the point is not used as anchor.
<div class="divider"></div>
##### Examples
* Make anchors with 5 seconds step interval:
```javascript
return data.time % 5000 < 1000;
{:copy-code}
```
<br>
<br>

24
ui-ngx/src/assets/help/en_US/widget/lib/map/circle_fill_color_fn.md

@ -0,0 +1,24 @@
#### Circle fill color function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute fill color of the circle.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting fill color of the circle.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
{% include widget/lib/map/color_fn_examples %}

22
ui-ngx/src/assets/help/en_US/widget/lib/map/circle_label_fn.md

@ -0,0 +1,22 @@
#### Circle label function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute text or HTML code of the circle label.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML of the circle label.
<div class="divider"></div>
{% include widget/lib/map/label_fn_examples %}

24
ui-ngx/src/assets/help/en_US/widget/lib/map/circle_stroke_color_fn.md

@ -0,0 +1,24 @@
#### Circle stroke color function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute stroke color of the circle.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting stroke color of the circle.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
{% include widget/lib/map/color_fn_examples %}

22
ui-ngx/src/assets/help/en_US/widget/lib/map/circle_tooltip_fn.md

@ -0,0 +1,22 @@
#### Circle tooltip function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute text or HTML code to be displayed in the circle tooltip.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div>
{% include widget/lib/map/tooltip_fn_examples %}

6
ui-ngx/src/assets/help/en_US/widget/lib/map/clustering_color_fn.md

@ -10,9 +10,9 @@ A JavaScript function used to compute clustering marker color.
**Parameters:** **Parameters:**
<ul> <ul>
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code> <li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData[]</a></code>
- the array of total markers contained within each cluster.<br/> - the array of total markers contained within each cluster.<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration. Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in datasource of the data layer configuration.
</li> </li>
<li><b>childCount:</b> <code>number</code> - the total number of markers contained within that cluster <li><b>childCount:</b> <code>number</code> - the total number of markers contained within that cluster
</li> </li>
@ -22,7 +22,7 @@ A JavaScript function used to compute clustering marker color.
Should return string value presenting color of the marker. Should return string value presenting color of the marker.
In case no data is returned, color value from **Color** settings field will be used. In case no data is returned, default colors will be used depending on number of markers within that cluster.
<div class="divider"></div> <div class="divider"></div>

22
ui-ngx/src/assets/help/en_US/widget/lib/map/color_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute color of the marker. A JavaScript function used to compute color of the marker.
@ -21,22 +21,4 @@ In case no data is returned, color value from **Color** settings field will be u
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/color_fn_examples %}
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

19
ui-ngx/src/assets/help/en_US/widget/lib/map/color_fn_examples.md

@ -0,0 +1,19 @@
##### Examples
* Calculate color depending on `temperature` telemetry value for `thermostat` device type:
```javascript
var type = data.Type;
if (type == 'thermostat') {
var temperature = data.temperature;
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

22
ui-ngx/src/assets/help/en_US/widget/lib/map/label_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute text or HTML code of the marker label. A JavaScript function used to compute text or HTML code of the marker label.
@ -19,22 +19,4 @@ Should return string value presenting text or HTML of the marker label.
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/label_fn_examples %}
* Display styled label with corresponding latest telemetry data for `energy meter` or `thermometer` device types:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<span style="color:orange;">${entityName}, ${energy:2} kWt</span>';
} else if (deviceType == "thermometer") {
return '<span style="color:blue;">${entityName}, ${temperature:2} °C</span>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

19
ui-ngx/src/assets/help/en_US/widget/lib/map/label_fn_examples.md

@ -0,0 +1,19 @@
##### Examples
* Display styled label with corresponding latest telemetry data for `energy meter` or `thermometer` device types:
```javascript
var deviceType = data.Type;
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<span style="color:orange;">${entityName}, ${energy:2} kWt</span>';
} else if (deviceType == "thermometer") {
return '<span style="color:blue;">${entityName}, ${temperature:2} °C</span>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

12
ui-ngx/src/assets/help/en_US/widget/lib/map/map_fn_args.md

@ -1,10 +1,8 @@
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a></code> - A <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> object associated with marker or data point of the route.<br/> <li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData</a></code> object associated with data layer (markers/polygons/circles) or data point of the route (trips data layer).<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in widget datasource configuration. Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in datasource of the data layer configuration.
</li> </li>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData[]</a></code> - All available data associated with markers or routes data points as array of <a href="https://github.com/thingsboard/thingsboard/blob/5bb6403407aa4898084832d6698aa9ea6d484889/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts#L108" target="_blank">FormattedData</a> objects<br/> <li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData[]</a></code> - All available data associated with data layers including additional datasources as array of <a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData</a> objects<br/>
resolved from configured datasources. Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/> resolved from configured datasources. Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>
and provides access to other entity attributes/timeseries declared in widget datasource configuration. and provides access to other entity attributes/timeseries declared in datasources of data layers configuration including additional datasources of the map configuration.
</li>
<li><b>dsIndex</b> <code>number</code> - index of the current marker data or route data point in <code>dsData</code> array.<br>
<strong>Note: </strong> The <code>data</code> argument is equivalent to <code>dsData[dsIndex]</code> expression.
</li> </li>

18
ui-ngx/src/assets/help/en_US/widget/lib/map/marker_image_fn.md

@ -3,14 +3,14 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, images, dsData, dsIndex): {url: string, size: number}* *function (data, images, dsData): {url: string, size: number}*
A JavaScript function used to compute marker image. A JavaScript function used to compute marker image.
**Parameters:** **Parameters:**
<ul> <ul>
{% include widget/lib/map/map_fn_args %} {% include widget/lib/map/marker_image_fn_args %}
</ul> </ul>
**Returns:** **Returns:**
@ -18,14 +18,18 @@ A JavaScript function used to compute marker image.
Should return marker image data having the following structure: Should return marker image data having the following structure:
```typescript ```typescript
{ {
url: string, url: string;
size: number size: number;
markerOffset?: [number, number];
tooltipOffset?: [number, number];
} }
``` ```
- *url* - marker image url; - *url* - marker image url;
- *size* - marker image size; - *size* - marker image size;
- *markerOffset* - optional array of two numbers presenting relative horizontal and vertical offset of the marker image;
- *tooltipOffset* - optional array of two numbers presenting relative horizontal and vertical offset of the marker image tooltip;
In case no data is returned, default marker image will be used. In case no data is returned, default marker image will be used.
@ -41,13 +45,13 @@ Let's assume 4 images are defined in <b>Marker images</b> section. Each image co
</ul> </ul>
```javascript ```javascript
var type = data['Type']; var type = data.Type;
if (type == 'thermometer') { if (type == 'thermometer') {
var res = { var res = {
url: images[0], url: images[0],
size: 40 size: 40
} }
var temperature = data['temperature']; var temperature = data.temperature;
if (typeof temperature !== undefined) { if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120; var percent = (temperature + 60)/120;
var index = Math.min(3, Math.floor(4 * percent)); var index = Math.min(3, Math.floor(4 * percent));

10
ui-ngx/src/assets/help/en_US/widget/lib/map/marker_image_fn_args.md

@ -0,0 +1,10 @@
<li><b>data:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData</a></code> object associated with data layer (markers/polygons/circles) or data point of the route (trips data layer).<br/>
Represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>and provides access to other entity attributes/timeseries declared in datasource of the data layer configuration.
</li>
<li><b>images:</b> <code>string[]</code> - array of image urls configured in the <b>Marker images</b> section.
</li>
<li><b>dsData:</b> <code><a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData[]</a></code> - All available data associated with data layers including additional datasources as array of <a href="https://github.com/thingsboard/thingsboard/blob/b881f1c2985399f9665e033e2479549e97da1f36/ui-ngx/src/app/shared/models/widget.models.ts#L513" target="_blank">FormattedData</a> objects<br/>
resolved from configured datasources. Each object represents basic entity properties (ex. <code>entityId</code>, <code>entityName</code>)<br/>
and provides access to other entity attributes/timeseries declared in datasources of data layers configuration including additional datasources of the map configuration.
</li>

24
ui-ngx/src/assets/help/en_US/widget/lib/map/path_color_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute color of the trip path. A JavaScript function used to compute color of the trip path.
@ -17,26 +17,8 @@ A JavaScript function used to compute color of the trip path.
Should return string value presenting color of the trip path. Should return string value presenting color of the trip path.
In case no data is returned, color value from **Path color** settings field will be used. In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/color_fn_examples %}
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

25
ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute color of the trip path point. A JavaScript function used to compute color of the trip path point.
@ -17,27 +17,8 @@ A JavaScript function used to compute color of the trip path point.
Should return string value presenting color of the trip path point. Should return string value presenting color of the trip path point.
In case no data is returned, color value from **Point color** settings field will be used. In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/color_fn_examples %}
* Calculate color depending on `temperature` telemetry value for `colorpin` device type:
```javascript
var type = data['Type'];
if (type == 'colorpin') {
var temperature = data['temperature'];
if (typeof temperature !== undefined) {
var percent = (temperature + 60)/120 * 100;
return tinycolor.mix('blue', 'red', percent).toHexString();
}
return 'blue';
}
{:copy-code}
```
<br>
<br>

22
ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md

@ -0,0 +1,22 @@
#### Path point tooltip function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute text or HTML code to be displayed in the trip path point tooltip.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div>
{% include widget/lib/map/tooltip_fn_examples %}

24
ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_fill_color_fn.md

@ -0,0 +1,24 @@
#### Polygon fill color function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute fill color of the polygon.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting fill color of the polygon.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
{% include widget/lib/map/color_fn_examples %}

22
ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_label_fn.md

@ -0,0 +1,22 @@
#### Polygon label function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute text or HTML code of the polygon label.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting text or HTML of the polygon label.
<div class="divider"></div>
{% include widget/lib/map/label_fn_examples %}

24
ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_stroke_color_fn.md

@ -0,0 +1,24 @@
#### Polygon stroke color function
<div class="divider"></div>
<br/>
*function (data, dsData): string*
A JavaScript function used to compute stroke color of the polygon.
**Parameters:**
<ul>
{% include widget/lib/map/map_fn_args %}
</ul>
**Returns:**
Should return string value presenting stroke color of the polygon.
In case no data is returned, color value from **Color** settings field will be used.
<div class="divider"></div>
{% include widget/lib/map/color_fn_examples %}

24
ui-ngx/src/assets/help/en_US/widget/lib/map/polygon_tooltip_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute text or HTML code to be displayed in the polygon tooltip. A JavaScript function used to compute text or HTML code to be displayed in the polygon tooltip.
@ -15,26 +15,8 @@ A JavaScript function used to compute text or HTML code to be displayed in the p
**Returns:** **Returns:**
Should return string value presenting text or HTML for the polygon tooltip. Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/tooltip_fn_examples %}
* Display details with corresponding telemetry data for `energy meter` or `thermostat` device types:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermostat") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

6
ui-ngx/src/assets/help/en_US/widget/lib/map/position_fn.md

@ -3,7 +3,7 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (origXPos, origYPos, data, dsData, dsIndex, aspect): {x: number, y: number}* *function (origXPos, origYPos, data, dsData, aspect): {x: number, y: number}*
A JavaScript function used to convert original relative x, y coordinates of the marker. A JavaScript function used to convert original relative x, y coordinates of the marker.
@ -22,8 +22,8 @@ Should return position data having the following structure:
```typescript ```typescript
{ {
x: number, x: number;
y: number y: number;
} }
``` ```

24
ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn.md

@ -3,9 +3,9 @@
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): string* *function (data, dsData): string*
A JavaScript function used to compute text or HTML code to be displayed in the marker, point or polygon tooltip. A JavaScript function used to compute text or HTML code to be displayed in the marker tooltip.
**Parameters:** **Parameters:**
@ -19,22 +19,4 @@ Should return string value presenting text or HTML for the tooltip.
<div class="divider"></div> <div class="divider"></div>
##### Examples {% include widget/lib/map/tooltip_fn_examples %}
* Display details with corresponding telemetry data for `thermostat` device type:
```javascript
var deviceType = data['Type'];
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermometer") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

19
ui-ngx/src/assets/help/en_US/widget/lib/map/tooltip_fn_examples.md

@ -0,0 +1,19 @@
##### Examples
* Display details with corresponding telemetry data for `energy meter` or `thermometer` device types:
```javascript
var deviceType = data.Type;
if (typeof deviceType !== undefined) {
if (deviceType == "energy meter") {
return '<b>${entityName}</b><br/><b>Energy:</b> ${energy:2} kWt<br/>';
} else if (deviceType == "thermometer") {
return '<b>${entityName}</b><br/><b>Temperature:</b> ${temperature:2} °C<br/>';
}
}
return data.entityName;
{:copy-code}
```
<br>
<br>

4
ui-ngx/src/assets/help/en_US/widget/lib/map/trip_point_as_anchor_fn.md

@ -1,9 +1,9 @@
#### Point as anchor function #### Location snap filter function
<div class="divider"></div> <div class="divider"></div>
<br/> <br/>
*function (data, dsData, dsIndex): boolean* *function (data, dsData): boolean*
A JavaScript function evaluating whether to use trip point as time anchor used in time selector. A JavaScript function evaluating whether to use trip point as time anchor used in time selector.

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

@ -15,8 +15,8 @@
/// ///
import { FormattedData } from '@shared/models/widget.models'; import { FormattedData } from '@shared/models/widget.models';
import L, { Control, ControlOptions } from 'leaflet'; import L from 'leaflet';
import { TbMapDatasource } from '@home/components/widget/lib/maps/models/map.models'; import { TbMapDatasource } from '@shared/models/widget/maps/map.models';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';
// redeclare module, maintains compatibility with @types/leaflet // redeclare module, maintains compatibility with @types/leaflet

Loading…
Cancel
Save