diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polylines-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polylines-data-layer.ts index a6823b40d0..2e1b22f157 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polylines-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polylines-data-layer.ts @@ -73,14 +73,13 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { + this.dataLayer.getStrokeStyle(data, dsData, this.polylineStyleInfo?.patternId).subscribe((styleInfo) => { this.polylineStyleInfo = styleInfo; - if (this.polyline) { this.polyline.setStyle(this.polylineStyleInfo.style); } @@ -103,7 +102,7 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem, dsData: FormattedData[]): void { - this.dataLayer.getShapeStyle(data, dsData, this.polylineStyleInfo?.patternId).subscribe((styleInfo) => { + this.dataLayer.getStrokeStyle(data, dsData, this.polylineStyleInfo?.patternId).subscribe((styleInfo) => { this.polylineStyleInfo = styleInfo; this.updatePolylineShape(data); this.updateTooltip(data, dsData); @@ -159,36 +158,33 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { - const map = this.dataLayer.getMap().getMap(); - // if (!map.pm.globalCutModeEnabled()) { - // this.disablePolygonRotateMode(); - // this.disablePolygonEditMode(); - // this.enablePolygonCutMode(button); - // } else { - // this.disablePolygonCutMode(button); - // this.enablePolygonEditMode(); - // } - } - }, + // { + // id: 'cut', + // title: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polygon.cut'), + // iconClass: 'tb-cut', + // click: (e, button) => { + // const map = this.dataLayer.getMap().getMap(); + // if (!map.pm.globalCutModeEnabled()) { + // this.disablePolylineRotateMode(); + // this.disablePolylineEditMode(); + // } else { + // this.enablePolylineEditMode(); + // } + // } + // }, { id: 'rotate', title: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polygon.rotate'), iconClass: 'tb-rotate', click: (e, button) => { if (!this.polyline.pm.rotateEnabled()) { - // this.disablePolygonCutMode(); - // this.disablePolygonEditMode(); - // this.enablePolygonRotateMode(button); + this.disablePolylineEditMode(); + this.enablePolylineRotateMode(button); } else { - // this.disablePolygonRotateMode(button); - // this.enablePolygonEditMode(); + this.disablePolylineRotateMode(button); + this.enablePolylineEditMode(); } } } @@ -199,22 +195,15 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { - // if (e.layer instanceof L.Polygon) { - // if (this.polyline instanceof L.Rectangle) { - // this.polylineContainer.removeLayer(this.polyline); - // this.polyline = L.polyline(e.layer.getLatLngs(), { - // ...this.polylineStyleInfo.style, - // snapIgnore: !this.dataLayer.isSnappable(), - // bubblingMouseEvents: !this.dataLayer.isEditMode() - // }); - // this.polyline.addTo(this.polylineContainer); - // } else { - // this.polyline.setLatLngs(e.layer.getLatLngs()); - // } - // } - // // @ts-ignore - // e.layer._pmTempLayer = true; - // e.layer.remove(); - // this.polylineContainer.removeLayer(this.polyline); - // // @ts-ignore - // this.polyline._pmTempLayer = false; - // this.polyline.addTo(this.polylineContainer); - // this.updateSelectedState(); - // cutButton?.setActive(false); - // this.savePolygonCoordinates() - // }); - // const map = this.dataLayer.getMap().getMap(); - // map.pm.setLang('en', { - // tooltips: { - // firstVertex: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polygon.polygon-place-first-point-cut-hint'), - // continueLine: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polygon.continue-polygon-cut-hint'), - // finishPoly: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polygon.finish-polygon-cut-hint') - // } - // }, 'en'); - // map.pm.enableGlobalCutMode({ - // // @ts-ignore - // layersToCut: [this.polyline] - // }); - // // @ts-ignore - // L.DomUtil.addClass(map.pm.Draw.Cut._hintMarker.getTooltip()._container, 'tb-place-item-label'); - // cutButton?.setActive(true); - // map.once('pm:globalcutmodetoggled', (e) => { - // // if (!e.enabled) { - // // this.disablePolygonCutMode(cutButton); - // // this.enablePolygonEditMode(); - // // } - // }); - // } - - // private disablePolygonCutMode(cutButton?: L.TB.ToolbarButton) { - // this.editing = false; - // this.polyline.options.bubblingMouseEvents = !this.dataLayer.isEditMode(); - // this.polyline.setStyle({...this.polylineStyleInfo.style, dashArray: null}); - // this.removeItemClass('tb-cut-mode'); - // this.polyline.off('pm:cut'); - // const map = this.dataLayer.getMap().getMap(); - // map.pm.disableGlobalCutMode(); - // cutButton?.setActive(false); - // } - - // private enablePolygonRotateMode(rotateButton?: L.TB.ToolbarButton) { - // this.polylineContainer.closePopup(); - // this.editing = true; - // this.polyline.on('pm:rotateend', () => { - // this.savePolygonCoordinates(); - // }); - // this.polyline.pm.enableRotate(); - // rotateButton?.setActive(true); - // this.polyline.on('pm:rotatedisable', () => { - // this.disablePolygonRotateMode(rotateButton); - // this.enablePolygonEditMode(); - // }); - // } - // - // private disablePolygonRotateMode(rotateButton?: L.TB.ToolbarButton) { - // this.editing = false; - // this.polyline.pm.disableRotate(); - // this.polyline.off('pm:rotateend'); - // this.polyline.off('pm:rotatedisable'); - // rotateButton?.setActive(false); - // } + private disablePolylineEditMode() { + this.polyline.pm.disable(); + this.polyline.off('pm:markerdragstart'); + this.polyline.off('pm:markerdragend'); + this.polyline.off('pm:edit'); + const map = this.dataLayer.getMap(); + map.getEditToolbar().getButton('remove')?.setDisabled(true); + } + + private enablePolylineRotateMode(rotateButton?: L.TB.ToolbarButton) { + this.polylineContainer.closePopup(); + this.editing = true; + this.polyline.on('pm:rotateend', () => { + this.savePolylineCoordinates(); + }); + this.polyline.pm.enableRotate(); + rotateButton?.setActive(true); + this.polyline.on('pm:rotatedisable', () => { + this.disablePolylineRotateMode(rotateButton); + this.enablePolylineEditMode(); + }); + } + + private disablePolylineRotateMode(rotateButton?: L.TB.ToolbarButton) { + this.editing = false; + this.polyline.pm.disableRotate(); + this.polyline.off('pm:rotateend'); + this.polyline.off('pm:rotatedisable'); + rotateButton?.setActive(false); + } private savePolylineCoordinates() { let coordinates: TbPolylineCoordinates = this.polyline.getLatLngs(); @@ -361,20 +284,20 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem, dsData: FormattedData[]): TbPolylineDataLayerItem { return new TbPolylineDataLayerItem(data, dsData, this.settings, this); } - } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts index 93502588b1..c24d40c5bf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/shapes-data-layer.ts @@ -311,6 +311,23 @@ export abstract class TbShapesDataLayer, dsData: FormattedData[], fillPatternId: string): Observable { + return this.shapePatternProcessor.processPattern(data, dsData, fillPatternId).pipe( + map((patternWithId) => { + const stroke = this.strokeColorProcessor.processColor(data, dsData); + const style: L.PathOptions = { + color: stroke, + weight: this.settings.strokeWeight, + opacity: 1 + }; + return { + patternId: patternWithId.patternId, + style + } + }) + ); + } + public getShapeStyle(data: FormattedData, dsData: FormattedData[], fillPatternId: string): Observable { return this.shapePatternProcessor.processPattern(data, dsData, fillPatternId).pipe( map((patternWithId) => { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss index 985bdc17f5..5d00f9add6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.scss @@ -169,6 +169,9 @@ div.tb-widget .tb-widget-content.tb-no-interaction { &.tb-draw-circle { mask-image: url('data:image/svg+xml,'); } + &.tb-draw-polyline { + mask-image: url('data:image/svg+xml,'); + } &.tb-close { background: #D12730; mask-image: url('data:image/svg+xml,'); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts index faf328d203..24f88308ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts @@ -125,6 +125,7 @@ export abstract class TbMap { protected addRectangleButton: L.TB.ToolbarButton; protected addPolygonButton: L.TB.ToolbarButton; protected addCircleButton: L.TB.ToolbarButton; + protected addPolylineButton: L.TB.ToolbarButton; protected timeLineComponentRef: ComponentRef; protected timeLineComponent: MapTimelinePanelComponent; @@ -133,6 +134,7 @@ export abstract class TbMap { protected addMarkerDataLayers: TbLatestMapDataLayer[]; protected addPolygonDataLayers: TbLatestMapDataLayer[]; protected addCircleDataLayers: TbLatestMapDataLayer[]; + protected addPolylineDataLayers: TbLatestMapDataLayer[]; protected shapePatternStorage: ShapePatternStorage = {}; @@ -506,6 +508,18 @@ export abstract class TbMap { }); this.addCircleButton.setDisabled(true); } + this.addPolylineDataLayers = addSupportedDataLayers.filter(dl => dl.dataLayerType() === 'polylines'); + if (this.addPolylineDataLayers.length) { + this.addPolylineButton = drawToolbar.toolbarButton({ + id: 'addPolyline', + title: this.ctx.translate.instant('widgets.maps.data-layer.polyline.draw-polyline'), + iconClass: 'tb-draw-polyline', + click: (e, button) => { + this.drawPolyline(e, button); + } + }); + this.addPolylineButton.setDisabled(true); + } } } @@ -563,6 +577,13 @@ export abstract class TbMap { })); } + private drawPolyline(e: MouseEvent, button: L.TB.ToolbarButton): void { + this.placeItem(e, button, this.addCircleDataLayers, (entity) => this.prepareDrawMode('Polyline', { + firstVertex: this.ctx.translate.instant('widgets.maps.data-layer.polyline.polyline-place-first-point-hint-with-entity', {entityName: entity.entity.entityDisplayName}), + continueLine: this.ctx.translate.instant('widgets.maps.data-layer.polyline.continue-polyline-hint-with-entity', {entityName: entity.entity.entityDisplayName}), + })); + } + private placeItem(e: MouseEvent, button: L.TB.ToolbarButton, dataLayers: TbLatestMapDataLayer[], prepareDrawMode: (entity: UnplacedMapDataItem) => void): void { if (this.isPlacingItem) { @@ -684,6 +705,9 @@ export abstract class TbMap { case MapItemType.circle: this.createCircle(actionData); break; + case MapItemType.polyline: + // this.createPolyline(actionData); // TODO + break; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html index 1369deefcb..df53c44be7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html @@ -465,6 +465,8 @@ + +
widgets.maps.data-layer.shape.stroke
@@ -477,7 +479,9 @@ [dsType]="dataLayerFormGroup.get('dsType').value" [dsEntityAliasId]="dataLayerFormGroup.get('dsEntityAliasId').value" [dsDeviceId]="dataLayerFormGroup.get('dsDeviceId').value" - helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_stroke_color_fn' : 'widget/lib/map/circle_stroke_color_fn' }}" formControlName="strokeColor"> + helpId="{{ dataLayerType === 'polygons' ? 'widget/lib/map/polygon_stroke_color_fn' : + (dataLayerType === 'circles' ? 'widget/lib/map/polygon_stroke_color_fn' : 'widget/lib/map/polyline_stroke_color_fn') }}" + formControlName="strokeColor">
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts index 27a06f9a32..71b6a2b31a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts @@ -474,23 +474,23 @@ export class MapDataLayerDialogComponent extends DialogComponent
widgets.maps.data-layer.polygon.polygon-key
widgets.maps.data-layer.circle.circle-key
+
widgets.maps.data-layer.polyline.polyline-key
diff --git a/ui-ngx/src/app/shared/models/widget/maps/map.models.ts b/ui-ngx/src/app/shared/models/widget/maps/map.models.ts index e3e9de6839..99a3bc499b 100644 --- a/ui-ngx/src/app/shared/models/widget/maps/map.models.ts +++ b/ui-ngx/src/app/shared/models/widget/maps/map.models.ts @@ -687,6 +687,7 @@ export const defaultBasePolylinesDataLayerSettings = (mapType: MapType): Partial type: DataLayerColorType.constant, color: '#3388ff', }, + strokeWeight: 3, // usePathDecorator: false, // pathDecoratorSymbol: PathDecoratorSymbol.arrowHead, // pathDecoratorSymbolSize: 10, @@ -701,7 +702,7 @@ export const defaultBasePolylinesDataLayerSettings = (mapType: MapType): Partial color: '#307FE5', }, pointTooltip: { - show: true, + show: false, trigger: DataLayerTooltipTrigger.click, autoclose: true, type: DataLayerPatternType.pattern, diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md index be95f136ad..9af015d033 100644 --- a/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md +++ b/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_color_fn.md @@ -5,7 +5,7 @@ *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 path point. **Parameters:** @@ -15,7 +15,7 @@ A JavaScript function used to compute color of the trip path point. **Returns:** -Should return string value presenting color of the trip path point. +Should return string value presenting color of the path point. In case no data is returned, color value from **Color** settings field will be used. diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md index 4ce996626a..e9e202ef85 100644 --- a/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md +++ b/ui-ngx/src/assets/help/en_US/widget/lib/map/path_point_tooltip_fn.md @@ -5,7 +5,7 @@ *function (data, dsData): string* -A JavaScript function used to compute text or HTML code to be displayed in the trip path point tooltip. +A JavaScript function used to compute text or HTML code to be displayed in the path point tooltip. **Parameters:** diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/map/polyline_stroke_color_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/map/polyline_stroke_color_fn.md new file mode 100644 index 0000000000..6b49763393 --- /dev/null +++ b/ui-ngx/src/assets/help/en_US/widget/lib/map/polyline_stroke_color_fn.md @@ -0,0 +1,24 @@ +#### Polyline stroke color function + +
+
+ +*function (data, dsData): string* + +A JavaScript function used to compute stroke color of the polyline. + +**Parameters:** + +
    + {% include widget/lib/map/map_fn_args %} +
+ +**Returns:** + +Should return string value presenting stroke color of the polyline. + +In case no data is returned, color value from **Color** settings field will be used. + +
+ +{% include widget/lib/map/color_fn_examples %} diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 40302a0eae..0e13fda6be 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -8640,6 +8640,8 @@ "edit": "Edit polyline", "remove-polyline-for": "Remove polyline for '{{entityName}}'", "draw-polyline": "Draw polyline", + "polyline-place-first-point-hint": "Polyline: click to place first point", + "continue-polyline-hint-with-entity": "Polyline for '{{entityName}}': click to continue drawing", "finish-polyline-hint": "Polyline: click to finish drawing" }, "select-entity": "Select entity",