From f332096288de06b4ccfd463b0190ee8c3d0becf6 Mon Sep 17 00:00:00 2001 From: LeoMorgan113 Date: Tue, 14 Oct 2025 16:06:29 +0300 Subject: [PATCH] Added cut action for polyline --- .../maps/data-layer/polylines-data-layer.ts | 96 ++++++++++++++++++- .../lib/maps/data-layer/trips-data-layer.ts | 2 +- .../map/map-data-layer-dialog.component.html | 2 - .../map/map-data-layer-dialog.component.ts | 45 --------- .../shared/models/widget/maps/map.models.ts | 45 ++------- .../assets/locale/locale.constant-en_US.json | 4 +- 6 files changed, 107 insertions(+), 87 deletions(-) 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 e2b5f2b1c9..06cb32d71f 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 @@ -157,12 +157,29 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { + const map = this.dataLayer.getMap().getMap(); + if (!map.pm.globalCutModeEnabled()) { + this.disablePolylineRotateMode(); + this.disablePolylineEditMode(); + this.enablePolylineCutMode(button); + } else { + this.disablePolylineCutMode(button); + this.enablePolylineEditMode(); + } + } + }, { id: 'rotate', title: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polyline.rotate'), iconClass: 'tb-rotate', click: (e, button) => { if (!this.polyline.pm.rotateEnabled()) { + this.disablePolylineCutMode(); this.disablePolylineEditMode(); this.enablePolylineRotateMode(button); } else { @@ -184,7 +201,13 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { + if (e.layer instanceof L.Polyline) { + this.polylineContainer.removeLayer(this.polyline); + this.polyline = L.polyline(e.layer.getLatLngs() as L.LatLngExpression[] | L.LatLngExpression[][], { + ...this.polylineStyleInfo.style, + snapIgnore: !this.dataLayer.isSnappable(), + bubblingMouseEvents: !this.dataLayer.isEditMode() + }); + this.polyline.addTo(this.polylineContainer); + } + // @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.savePolylineCoordinates() + }); + const map = this.dataLayer.getMap().getMap(); + map.pm.setLang('en', { + tooltips: { + firstVertex: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polyline.polyline-place-first-point-cut-hint'), + finishLine: this.getDataLayer().getCtx().translate.instant('widgets.maps.data-layer.polyline.finish-polyline-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.disablePolylineCutMode(cutButton); + this.enablePolylineEditMode(); + } + }); + } + + private disablePolylineCutMode(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 enablePolylineRotateMode(rotateButton?: L.TB.ToolbarButton) { this.polylineContainer.closePopup(); this.editing = true; @@ -250,6 +336,13 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem boundsArray.find(boundPoint => boundPoint.equals(point as L.LatLng)) !== undefined)) { + coordinates = [bounds.getNorthWest(), bounds.getSouthEast()]; + } + } this.dataLayer.savePolylineCoordinates(this.data, coordinates).subscribe(); } @@ -279,7 +372,6 @@ class TbPolylineDataLayerItem extends TbLatestDataLayerItem { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts index ae2f62853e..bfb872c75a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/trips-data-layer.ts @@ -44,7 +44,7 @@ import { MarkerDataProcessor } from '@home/components/widget/lib/maps/data-layer type TripRouteData = {[time: number]: FormattedData}; -interface PointItem { +export interface PointItem { point: L.CircleMarker; tooltip?: L.Popup; } 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 df53c44be7..178c948f43 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 @@ -390,8 +390,6 @@ - -
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 71b6a2b31a..af653308da 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 @@ -306,24 +306,6 @@ export class MapDataLayerDialogComponent extends DialogComponent - this.updateValidators() - ); break; } this.dataLayerFormGroup.get('dsType').valueChanges.pipe( @@ -473,33 +455,6 @@ export class MapDataLayerDialogComponent extends DialogComponent mergeDeep( defaultMarkersDataSourceSettings(mapType, true, functionsOnly) as TripsDataLayerSettings, defaultBaseTripsDataLayerSettings(mapType) as TripsDataLayerSettings); @@ -673,7 +670,7 @@ export const defaultBaseCirclesDataLayerSettings = (mapType: MapType): Partial${entityName}

TimeStamp: ${ts:7}'} } as Partial) -export interface PolylinesDataLayerSettings extends ShapeDataLayerSettings, PathDataLayerSettings { +export interface PolylinesDataLayerSettings extends ShapeDataLayerSettings { polylineKey: DataKey; } @@ -699,31 +696,7 @@ export const defaultBasePolylinesDataLayerSettings = (mapType: MapType): Partial type: DataLayerColorType.constant, color: '#3388ff', }, - strokeWeight: 3, - // usePathDecorator: false, - // pathDecoratorSymbol: PathDecoratorSymbol.arrowHead, - // pathDecoratorSymbolSize: 10, - // pathDecoratorSymbolColor: '#307FE5', - // pathDecoratorOffset: 20, - // pathEndDecoratorOffset: 20, - // pathDecoratorRepeat: 20, - showPoints: false, - pointSize: 10, - pointColor: { - type: DataLayerColorType.constant, - color: '#307FE5', - }, - pointTooltip: { - show: false, - trigger: DataLayerTooltipTrigger.click, - autoclose: true, - type: DataLayerPatternType.pattern, - pattern: mapType === MapType.geoMap ? - '${entityName}

Latitude: ${latitude:7}
Longitude: ${longitude:7}
End Time: ${maxTime}
Start Time: ${minTime}' - : '${entityName}

X Pos: ${xPos:2}
Y Pos: ${yPos:2}
End Time: ${maxTime}
Start Time: ${minTime}', - offsetX: 0, - offsetY: -1 - }, + strokeWeight: 3 } as Partial, defaultBaseDataLayerSettings(mapType), { label: {show: false}, 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 4290f39c24..47fdda19a3 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -8643,7 +8643,9 @@ "draw-polyline": "Draw polyline", "polyline-place-first-point-hint-with-entity": "Polyline for '{{entityName}}': click to place first point", "polyline-place-first-point-hint": "Polyline: click to place first point", - "finish-polyline-hint": "Polyline for '{{entityName}}': click to finish drawing" + "finish-polyline-hint": "Polyline for '{{entityName}}': click to finish drawing", + "polyline-place-first-point-cut-hint": "Click to place first point", + "finish-polyline-cut-hint": "Click first marker to finish and save" }, "select-entity": "Select entity", "select-entity-hint": "Hint: after selection click at the map to set position"