diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts index 27d6fb5edc..f4247d152e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts @@ -69,6 +69,8 @@ export default abstract class LeafletMap { loading = false; replaceInfoLabelMarker: Array = []; markerLabelText: string; + polygonLabelText: string; + replaceInfoLabelPolygon: Array = []; replaceInfoTooltipMarker: Array = []; markerTooltipText: string; drawRoutes: boolean; @@ -248,8 +250,16 @@ export default abstract class LeafletMap { this.saveLocation(this.selectedEntity, this.convertToCustomFormat(e.layer.getLatLng())).subscribe(() => { }); } else if (e.shape === 'tbRectangle' || e.shape === 'tbPolygon') { - // @ts-ignore - this.saveLocation(this.selectedEntity, this.convertPolygonToCustomFormat(e.layer.getLatLngs()[0])).subscribe(() => { + let coordinates; + if (e.shape === 'tbRectangle') { + // @ts-ignore + const bounds: L.LatLngBounds = e.layer.getBounds(); + coordinates = [bounds.getNorthWest(), bounds.getSouthEast()]; + } else { + // @ts-ignore + coordinates = e.layer.getLatLngs()[0]; + } + this.saveLocation(this.selectedEntity, this.convertPolygonToCustomFormat(coordinates)).subscribe(() => { }); } // @ts-ignore @@ -281,7 +291,7 @@ export default abstract class LeafletMap { result = iterator.next(); } this.saveLocation(result.value.data, this.convertToCustomFormat(null)).subscribe(() => {}); - } else if (e.shape === 'Polygon') { + } else if (e.shape === 'Polygon' || e.shape === 'Rectangle') { const iterator = this.polygons.values(); let result = iterator.next(); while (!result.done && e.layer !== result.value.leafletPoly) { @@ -333,6 +343,7 @@ export default abstract class LeafletMap { this.map.scrollWheelZoom.disable(); } if (this.options.draggableMarker || this.editPolygons) { + map.pm.setGlobalOptions({ snappable: false } as L.PM.GlobalOptions); this.addEditControl(); } else { this.map.pm.disableDraw(); @@ -764,6 +775,14 @@ export default abstract class LeafletMap { if (coordinates.length === 1) { coordinates = coordinates[0]; } + if (e.shape === 'Rectangle') { + // @ts-ignore + const bounds: L.LatLngBounds = e.layer.getBounds(); + const boundsArray = [bounds.getNorthWest(), bounds.getNorthEast(), bounds.getSouthWest(), bounds.getSouthEast()]; + if (coordinates.every(point => boundsArray.find(boundPoint => boundPoint.equals(point)) !== undefined)) { + coordinates = [bounds.getNorthWest(), bounds.getSouthEast()]; + } + } this.saveLocation(data, this.convertPolygonToCustomFormat(coordinates)).subscribe(() => {}); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts index 5b99b792e9..a472a99915 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts @@ -131,6 +131,11 @@ export type PolygonSettings = { polygonStrokeWeight: number; polygonStrokeColor: string; polygonColor: string; + showPolygonLabel?: boolean; + polygonLabel: string; + polygonLabelColor: string; + polygonLabelText: string; + usePolygonLabelFunction: boolean; showPolygonTooltip: boolean; autocloseTooltip: boolean; showTooltipAction: string; @@ -139,8 +144,11 @@ export type PolygonSettings = { usePolygonTooltipFunction: boolean; polygonClick: { [name: string]: actionsHandler }; usePolygonColorFunction: boolean; + usePolygonStrokeColorFunction: boolean; polygonTooltipFunction: GenericFunction; polygonColorFunction?: GenericFunction; + polygonStrokeColorFunction?: GenericFunction; + polygonLabelFunction?: GenericFunction; editablePolygon: boolean; }; @@ -227,8 +235,10 @@ export const defaultSettings: any = { showPolygon: false, labelColor: '#000000', color: '#FE7569', + showPolygonLabel: false, polygonColor: '#0000ff', polygonStrokeColor: '#fe0001', + polygonLabelColor: '#000000', polygonOpacity: 0.5, polygonStrokeOpacity: 1, polygonStrokeWeight: 1, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts index a2385b2877..f755754eca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts @@ -265,10 +265,13 @@ export class MapWidgetController implements MapWidgetInterface { tooltipFunction: parseFunction(settings.tooltipFunction, functionParams), colorFunction: parseFunction(settings.colorFunction, functionParams), colorPointFunction: parseFunction(settings.colorPointFunction, functionParams), + polygonLabelFunction: parseFunction(settings.polygonLabelFunction, functionParams), polygonColorFunction: parseFunction(settings.polygonColorFunction, functionParams), + polygonStrokeColorFunction: parseFunction(settings.polygonStrokeColorFunction, functionParams), polygonTooltipFunction: parseFunction(settings.polygonTooltipFunction, functionParams), markerImageFunction: parseFunction(settings.markerImageFunction, ['data', 'images', 'dsData', 'dsIndex']), labelColor: this.ctx.widgetConfig.color, + polygonLabelColor: this.ctx.widgetConfig.color, polygonKeyName: settings.polKeyName ? settings.polKeyName : settings.polygonKeyName, tooltipPattern: settings.tooltipPattern || '${entityName}

Latitude: ${' + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss index 147386685c..f45d08f9e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.scss @@ -29,6 +29,15 @@ box-shadow: none; } +.tb-polygon-label { + border: none; + background: none; + box-shadow: none; + &:before { + content: none; + } +} + .leaflet-container { background-color: white; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts index d87d764d0a..ab3abc7f7f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts @@ -16,8 +16,14 @@ import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet'; import { createTooltip } from './maps-utils'; -import { functionValueCalculator, parseWithTranslation, safeExecute } from './common-maps-utils'; -import { FormattedData, PolygonSettings } from './map-models'; +import { + fillPattern, + functionValueCalculator, + parseWithTranslation, + processPattern, + safeExecute +} from './common-maps-utils'; +import { FormattedData, MarkerSettings, PolygonSettings } from './map-models'; export class Polygon { @@ -26,38 +32,47 @@ export class Polygon { data: FormattedData; dataSources: FormattedData[]; - constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings, onDragendListener?) { + constructor(public map, data: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings, + private onDragendListener?) { this.dataSources = dataSources; - this.data = polyData; + this.data = data; const polygonColor = this.getPolygonColor(settings); - this.leafletPoly = L.polygon(polyData[this.settings.polygonKeyName], { + const polygonStrokeColor = this.getPolygonStrokeColor(settings); + const polyData = data[this.settings.polygonKeyName]; + const polyConstructor = polyData.length > 2 ? L.polygon : L.rectangle; + this.leafletPoly = polyConstructor(polyData, { fill: true, fillColor: polygonColor, - color: settings.polygonStrokeColor, + color: polygonStrokeColor, weight: settings.polygonStrokeWeight, fillOpacity: settings.polygonOpacity, opacity: settings.polygonStrokeOpacity, pmIgnore: !settings.editablePolygon }).addTo(this.map); - if (settings.editablePolygon && onDragendListener) { - this.leafletPoly.on('pm:edit', (e) => onDragendListener(e, this.data)); - } - + this.updateLabel(settings); if (settings.showPolygonTooltip) { - this.tooltip = createTooltip(this.leafletPoly, settings, polyData.$datasource); - this.updateTooltip(polyData); - } - if (settings.polygonClick) { - this.leafletPoly.on('click', (event: LeafletMouseEvent) => { - for (const action in this.settings.polygonClick) { - if (typeof (this.settings.polygonClick[action]) === 'function') { - this.settings.polygonClick[action](event.originalEvent, polyData.$datasource); - } - } - }); + this.tooltip = createTooltip(this.leafletPoly, settings, data.$datasource); + this.updateTooltip(data); } + this.createEventListeners(); + } + + private createEventListeners() { + if (this.settings.editablePolygon && this.onDragendListener) { + this.leafletPoly.on('pm:edit', (e) => this.onDragendListener(e, this.data)); + } + + if (this.settings.polygonClick) { + this.leafletPoly.on('click', (event: LeafletMouseEvent) => { + for (const action in this.settings.polygonClick) { + if (typeof (this.settings.polygonClick[action]) === 'function') { + this.settings.polygonClick[action](event.originalEvent, this.data.$datasource); + } + } + }); + } } updateTooltip(data: FormattedData) { @@ -67,13 +82,54 @@ export class Polygon { this.tooltip.setContent(parseWithTranslation.parseTemplate(pattern, data, true)); } + updateLabel(settings: PolygonSettings) { + this.leafletPoly.unbindTooltip(); + if (settings.showPolygonLabel) { + if (!this.map.polygonLabelText || settings.usePolygonLabelFunction) { + const pattern = settings.usePolygonLabelFunction ? + safeExecute(settings.polygonLabelFunction, [this.data, this.dataSources, this.data.dsIndex]) : settings.polygonLabel; + this.map.polygonLabelText = parseWithTranslation.prepareProcessPattern(pattern, true); + this.map.replaceInfoLabelPolygon = processPattern(this.map.polygonLabelText, this.data); + } + settings.polygonLabelText = fillPattern(this.map.polygonLabelText, this.map.replaceInfoLabelPolygon, this.data); + this.leafletPoly.bindTooltip(`
${settings.polygonLabelText}
`, + { className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center' }) + .openTooltip(this.leafletPoly.getBounds().getCenter()); + } + } + updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { this.data = data; this.dataSources = dataSources; - this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]); + const polyData = data[this.settings.polygonKeyName]; + if (polyData.length > 2) { + if (this.leafletPoly instanceof L.Rectangle) { + this.map.removeLayer(this.leafletPoly); + const polygonColor = this.getPolygonColor(settings); + const polygonStrokeColor = this.getPolygonStrokeColor(settings); + this.leafletPoly = L.polygon(polyData, { + fill: true, + fillColor: polygonColor, + color: polygonStrokeColor, + weight: settings.polygonStrokeWeight, + fillOpacity: settings.polygonOpacity, + opacity: settings.polygonStrokeOpacity, + pmIgnore: !settings.editablePolygon + }).addTo(this.map); + } else { + this.leafletPoly.setLatLngs(polyData); + } + } else if (polyData.length === 2) { + const bounds = new L.LatLngBounds(polyData); + // @ts-ignore + this.leafletPoly.setBounds(bounds); + } if (settings.showPolygonTooltip) { this.updateTooltip(this.data); } + if (settings.showPolygonLabel) { + this.updateLabel(settings); + } this.updatePolygonColor(settings); } @@ -83,10 +139,11 @@ export class Polygon { updatePolygonColor(settings: PolygonSettings) { const polygonColor = this.getPolygonColor(settings); + const polygonStrokeColor = this.getPolygonStrokeColor(settings); const style: L.PathOptions = { fill: true, fillColor: polygonColor, - color: settings.polygonStrokeColor, + color: polygonStrokeColor, weight: settings.polygonStrokeWeight, fillOpacity: settings.polygonOpacity, opacity: settings.polygonStrokeOpacity @@ -107,4 +164,9 @@ export class Polygon { return functionValueCalculator(settings.usePolygonColorFunction, settings.polygonColorFunction, [this.data, this.dataSources, this.data.dsIndex], settings.polygonColor); } + + private getPolygonStrokeColor(settings: PolygonSettings): string | null { + return functionValueCalculator(settings.usePolygonStrokeColorFunction, settings.polygonStrokeColorFunction, + [this.data, this.dataSources, this.data.dsIndex], settings.polygonStrokeColor); + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts index ff52ece929..b42da7d8b0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/schemes.ts @@ -556,6 +556,25 @@ export const mapPolygonSchema = type: 'boolean', default: false }, + showPolygonLabel: { + title: 'Show polygon label', + type: 'boolean', + default: false + }, + polygonLabel: { + title: 'Polygon label (pattern examples: \'${entityName}\', \'${entityName}: (Text ${keyName} units.)\' )', + type: 'string', + default: '${entityName}' + }, + usePolygonLabelFunction: { + title: 'Use polygon label function', + type: 'boolean', + default: false + }, + polygonLabelFunction: { + title: 'Polygon label function: f(data, dsData, dsIndex)', + type: 'string' + }, polygonColor: { title: 'Polygon color', type: 'string' @@ -607,6 +626,15 @@ export const mapPolygonSchema = title: 'Polygon Color function: f(data, dsData, dsIndex)', type: 'string' }, + usePolygonStrokeColorFunction: { + title: 'Use polygon stroke color function', + type: 'boolean', + default: false + }, + polygonStrokeColorFunction: { + title: 'Polygon Stroke Color function: f(data, dsData, dsIndex)', + type: 'string' + } }, required: [] }, @@ -614,6 +642,21 @@ export const mapPolygonSchema = 'showPolygon', 'polygonKeyName', 'editablePolygon', + 'showPolygonLabel', + { + key: 'usePolygonLabelFunction', + condition: 'model.showPolygonLabel === true' + }, + { + key: 'polygonLabel', + condition: 'model.showPolygonLabel === true && model.usePolygonLabelFunction !== true' + }, + { + key: 'polygonLabelFunction', + type: 'javascript', + helpId: 'widget/lib/map/label_fn', + condition: 'model.showPolygonLabel === true && model.usePolygonLabelFunction === true' + }, { key: 'polygonColor', type: 'color' @@ -630,6 +673,13 @@ export const mapPolygonSchema = key: 'polygonStrokeColor', type: 'color' }, + 'usePolygonStrokeColorFunction', + { + key: 'polygonStrokeColorFunction', + helpId: 'widget/lib/map/polygon_color_fn', + type: 'javascript', + condition: 'model.usePolygonStrokeColorFunction === true' + }, 'polygonStrokeOpacity', 'polygonStrokeWeight', 'showPolygonTooltip',