Fix conflicts

This commit is contained in:
Igor Kulikov 2020-04-28 20:02:33 +03:00
commit 413ad261e2
22 changed files with 302 additions and 198 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1886,19 +1886,19 @@
"@types/geojson": "*" "@types/geojson": "*"
} }
}, },
"@types/leaflet-polylinedecorator": { "@types/leaflet-markercluster": {
"version": "1.6.0", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz", "resolved": "https://registry.npmjs.org/@types/leaflet-markercluster/-/leaflet-markercluster-1.0.3.tgz",
"integrity": "sha512-Z2BXZDjKEqHclwrAmhYdF1RwyFfa/NFxsoF79sitzaj5D/4YWHp/zDRcUZar5cQFKRgK66AYEIF7nKVuMzUGdw==", "integrity": "sha1-ZBUb5FP2SQ6HUVAEgt65YQZOeCw=",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/leaflet": "*" "@types/leaflet": "*"
} }
}, },
"@types/leaflet.markercluster": { "@types/leaflet-polylinedecorator": {
"version": "1.4.2", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.4.2.tgz", "resolved": "https://registry.npmjs.org/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz",
"integrity": "sha512-QQ//hevAxMH2dlRQdRre7V/1G+TbtuDtZnZF/75TNwVIgklrsQVCIcS/cvLsl7UUryfPJ6xmoYHfFzK5iGVgpg==", "integrity": "sha512-Z2BXZDjKEqHclwrAmhYdF1RwyFfa/NFxsoF79sitzaj5D/4YWHp/zDRcUZar5cQFKRgK66AYEIF7nKVuMzUGdw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/leaflet": "*" "@types/leaflet": "*"
@ -4873,9 +4873,9 @@
"dev": true "dev": true
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.3.420", "version": "1.3.421",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.420.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.421.tgz",
"integrity": "sha512-iVmQhf25F+5bdAyDrfOmCMjyLlIwsr9UT/LyYPQ3J1Vrypr9IgHf2PxqlsnzicnRAYDev6S9cl1tYlDHZUHY/g==", "integrity": "sha512-ogxgmvHGfDuLA+GtgfK0jkFWlBb4MCZK2U1MM+l98sf4U3Ixtrfw1iC9w4mQqNvo+lHgM4pR62TqoT4QrvKJCw==",
"dev": true "dev": true
}, },
"elliptic": { "elliptic": {
@ -5946,9 +5946,9 @@
} }
}, },
"graceful-fs": { "graceful-fs": {
"version": "4.2.3", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true "dev": true
}, },
"hammerjs": { "hammerjs": {
@ -8881,9 +8881,9 @@
} }
}, },
"npm-registry-fetch": { "npm-registry-fetch": {
"version": "4.0.3", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.4.tgz",
"integrity": "sha512-WGvUx0lkKFhu9MbiGFuT9nG2NpfQ+4dCJwRwwtK2HK5izJEvwDxMeUyqbuMS7N/OkpVCqDorV6rO5E4V9F8lJw==", "integrity": "sha512-6jb34hX/iYNQebqWUHtU8YF6Cjb1H6ouTFPClYsyiW6lpFkljTpdeftm53rRojtja1rKAvKNIIiTS5Sjpw4wsA==",
"dev": true, "dev": true,
"requires": { "requires": {
"JSONStream": "^1.3.4", "JSONStream": "^1.3.4",
@ -10441,9 +10441,9 @@
} }
}, },
"postcss-value-parser": { "postcss-value-parser": {
"version": "4.0.3", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true "dev": true
}, },
"prepend-http": { "prepend-http": {

View File

@ -61,7 +61,7 @@
"leaflet-geometryutil": "^0.9.3", "leaflet-geometryutil": "^0.9.3",
"leaflet-polylinedecorator": "^1.6.0", "leaflet-polylinedecorator": "^1.6.0",
"leaflet-providers": "^1.9.1", "leaflet-providers": "^1.9.1",
"leaflet.gridlayer.googlemutant": "^0.8.0", "leaflet.gridlayer.googlemutant": "0.8.0",
"leaflet.markercluster": "^1.4.1", "leaflet.markercluster": "^1.4.1",
"material-design-icons": "^3.0.1", "material-design-icons": "^3.0.1",
"messageformat": "^2.3.0", "messageformat": "^2.3.0",
@ -108,8 +108,8 @@
"@types/jstree": "^3.3.39", "@types/jstree": "^3.3.39",
"@types/jszip": "^3.1.7", "@types/jszip": "^3.1.7",
"@types/leaflet": "^1.5.12", "@types/leaflet": "^1.5.12",
"@types/leaflet.markercluster": "^1.4.2",
"@types/leaflet-polylinedecorator": "^1.6.0", "@types/leaflet-polylinedecorator": "^1.6.0",
"@types/leaflet-markercluster": "^1.0.3",
"@types/lodash": "^4.14.150", "@types/lodash": "^4.14.150",
"@types/raphael": "^2.3.0", "@types/raphael": "^2.3.0",
"@types/react": "^16.9.34", "@types/react": "^16.9.34",

View File

@ -62,19 +62,21 @@ export function mergeSchemes(schemes: JsonSettingsSchema[]): JsonSettingsSchema
}, initSchema()); }, initSchema());
} }
export function addCondition(schema: JsonSettingsSchema, condition: string): JsonSettingsSchema { export function addCondition(schema: JsonSettingsSchema, condition: string, exclude: string[] = []): JsonSettingsSchema {
schema.form = schema.form.map(element => { schema.form = schema.form.map(element => {
if (typeof element === 'string') { if (!exclude.includes(element) && !exclude.includes(element.key)) {
return { if (typeof element === 'string') {
key: element, return {
condition key: element,
condition
}
} }
} if (typeof element === 'object') {
if (typeof element === 'object') { if (element.condition) {
if (element.condition) { element.condition += ' && ' + condition
element.condition += ' && ' + condition }
else element.condition = condition;
} }
else element.condition = condition;
} }
return element; return element;
}); });

View File

@ -15,8 +15,8 @@
/// ///
import _ from 'lodash'; import _ from 'lodash';
import { fromEvent, Observable, of, Subject } from 'rxjs'; import { Observable, Subject, fromEvent, of } from 'rxjs';
import { finalize, map, share } from 'rxjs/operators'; import { finalize, share, map } from 'rxjs/operators';
import base64js from 'base64-js'; import base64js from 'base64-js';
export function onParentScrollOrWindowResize(el: Node): Observable<Event> { export function onParentScrollOrWindowResize(el: Node): Observable<Event> {
@ -224,7 +224,7 @@ function scrollParents(node: Node): Node[] {
function hashCode(str) { function hashCode(str) {
let hash = 0; let hash = 0;
let i, char; let i, char;
if (str.length == 0) return hash; if (str.length === 0) return hash;
for (i = 0; i < str.length; i++) { for (i = 0; i < str.length; i++) {
char = str.charCodeAt(i); char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char; hash = ((hash << 5) - hash) + char;
@ -464,7 +464,7 @@ export function parseArray(input: any[]): any[] {
time: el[0], time: el[0],
deviceType: null deviceType: null
}; };
entityArray.forEach(entity => { entityArray.filter(el => el.data.length).forEach(entity => {
obj[entity?.dataKey?.label] = entity?.data[i][1]; obj[entity?.dataKey?.label] = entity?.data[i][1];
obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0]; obj[entity?.dataKey?.label + '|ts'] = entity?.data[0][0];
if (entity?.dataKey?.label === 'type') { if (entity?.dataKey?.label === 'type') {
@ -485,7 +485,7 @@ export function parseData(input: any[]): any[] {
dsIndex: i, dsIndex: i,
deviceType: null deviceType: null
}; };
entityArray.forEach(el => { entityArray.filter(el => el.data.length).forEach(el => {
obj[el?.dataKey?.label] = el?.data[0][1]; obj[el?.dataKey?.label] = el?.data[0][1];
obj[el?.dataKey?.label + '|ts'] = el?.data[0][0]; obj[el?.dataKey?.label + '|ts'] = el?.data[0][0];
if (el?.dataKey?.label === 'type') { if (el?.dataKey?.label === 'type') {
@ -510,14 +510,13 @@ export function safeExecute(func: Function, params = []) {
return res; return res;
} }
export function parseFunction(source: any, params: string[] = []): Function { export function parseFunction(source: any, params: string[] = ['def']): Function {
let res = null; let res = null;
if (source?.length) { if (source?.length) {
try { try {
res = new Function(...params, source); res = new Function(...params, source);
} }
catch (err) { catch (err) {
console.error(err);
res = null; res = null;
} }
} }
@ -526,33 +525,34 @@ export function parseFunction(source: any, params: string[] = []): Function {
export function parseTemplate(template: string, data: object, translateFn?: (key: string) => string) { export function parseTemplate(template: string, data: object, translateFn?: (key: string) => string) {
let res = ''; let res = '';
let variables = '';
try { try {
if (template.match(/<link-act/g)) { if (template.match(/<link-act/g)) {
template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>').replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`); template = template.replace(/<link-act/g, '<a').replace(/link-act>/g, 'a>').replace(/name=(\'|")(.*?)(\'|")/g, `class='tb-custom-action' id='$2'`);
} }
if (template.includes('i18n')) { if (translateFn) {
const translateRegexp = /\{i18n:(.*?)\}/; template = translateFn(template);
template.match(new RegExp(translateRegexp.source, translateRegexp.flags + 'g')).forEach(match => { }
template = template.replace(match, translateFn(match.match(translateRegexp)[1])); const formatted = template.match(/\$\{([^}]*)\:\d*\}/g);
if (formatted)
formatted.forEach(value => {
const [variable, digits] = value.replace('${', '').replace('}', '').split(':');
data[variable] = padValue(data[variable], +digits);
if (isNaN(data[variable])) data[value] = '';
template = template.replace(value, '${' + variable + '}');
}); });
const variables = template.match(/\$\{.*?\}/g);
if (variables) {
variables.forEach(variable => {
variable = variable.replace('${', '').replace('}', '');
if (!data[variable])
data[variable] = '';
})
} }
const expressions = template.match(/\{(.*?)\}/g); const compiled = _.template(template);
if (expressions) { res = compiled(data);
// TODO: not supported in IE
// const clearMatches = template.match(/(?<=\{)(.+?)(?=(\}|\:))/g);
const clearMatches = template.match(/\{(.+?)(\}|\:)/g);
for (const key in data) {
if (!key.includes('|'))
variables += `let ${key} = '${clearMatches[key] ? padValue(data[key], +clearMatches[key]) : data[key]}';`;
}
template = template.replace(/\:\d+\}/g, '}');
res = safeExecute(parseFunction(variables + ' return' + '`' + template + '`'));
}
else res = template;
} }
catch (ex) { catch (ex) {
console.log(ex, variables, template) console.log(ex, template)
} }
return res; return res;
} }

View File

@ -14,19 +14,12 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { LatLngBounds, LatLngTuple } from 'leaflet'; import L, { LatLngTuple, LatLngBounds, Point, MarkerClusterGroupOptions, markerClusterGroup } from 'leaflet';
import 'leaflet-providers'; import 'leaflet-providers';
import LM from 'leaflet.markercluster/dist/leaflet.markercluster'; import 'leaflet.markercluster/dist/leaflet.markercluster';
import { import { MapSettings, MarkerSettings, FormattedData, UnitedMapSettings, PolygonSettings, PolylineSettings } from './map-models';
FormattedData,
MapSettings,
MarkerSettings,
PolygonSettings,
PolylineSettings,
UnitedMapSettings
} from './map-models';
import { Marker } from './markers'; import { Marker } from './markers';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { filter } from 'rxjs/operators'; import { filter } from 'rxjs/operators';
@ -48,7 +41,7 @@ export default abstract class LeafletMap {
bounds: L.LatLngBounds; bounds: L.LatLngBounds;
newMarker: L.Marker; newMarker: L.Marker;
datasources: FormattedData[]; datasources: FormattedData[];
markersCluster: LM.markerClusterGroup; markersCluster;
constructor(public $container: HTMLElement, options: UnitedMapSettings) { constructor(public $container: HTMLElement, options: UnitedMapSettings) {
this.options = options; this.options = options;
@ -72,7 +65,7 @@ export default abstract class LeafletMap {
setTimeout(options.initCallback, 0); setTimeout(options.initCallback, 0);
} }
if (useClusterMarkers) { if (useClusterMarkers) {
const clusteringSettings: LM.MarkerClusterGroupOptions = { const clusteringSettings: MarkerClusterGroupOptions = {
zoomToBoundsOnClick: zoomOnClick, zoomToBoundsOnClick: zoomOnClick,
showCoverageOnHover, showCoverageOnHover,
removeOutsideVisibleBounds, removeOutsideVisibleBounds,
@ -85,7 +78,7 @@ export default abstract class LeafletMap {
if (maxZoom && maxZoom >= 0 && maxZoom < 19) { if (maxZoom && maxZoom >= 0 && maxZoom < 19) {
clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom); clusteringSettings.disableClusteringAtZoom = Math.floor(maxZoom);
} }
this.markersCluster = LM.markerClusterGroup(clusteringSettings); this.markersCluster = markerClusterGroup(clusteringSettings);
this.ready$.subscribe(map => map.addLayer(this.markersCluster)); this.ready$.subscribe(map => map.addLayer(this.markersCluster));
} }
} }
@ -213,7 +206,7 @@ export default abstract class LeafletMap {
}); });
this.map.fitBounds(bounds, { padding: padding || [50, 50], animate: false }); this.map.fitBounds(bounds, { padding: padding || [50, 50], animate: false });
} }
this.bounds = this.bounds.extend(bounds); this.bounds = bounds;
} }
} }
@ -236,22 +229,20 @@ export default abstract class LeafletMap {
// Markers // Markers
updateMarkers(markersData) { updateMarkers(markersData) {
markersData.forEach(data => { markersData.filter(mdata => !!this.convertPosition(mdata)).forEach(data => {
if (this.convertPosition(data)) { if (data.rotationAngle || data.rotationAngle === 0) {
if (data.rotationAngle || data.rotationAngle === 0) { this.options.icon = L.divIcon({
this.options.icon = L.divIcon({ html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>`
html: `<div class="arrow" style="transform: translate(-10px, -10px) rotate(${data.rotationAngle}deg);"><div>` })
}) }
} else {
else { this.options.icon = null;
this.options.icon = null; }
} if (this.markers.get(data.entityName)) {
if (this.markers.get(data.entityName)) { this.updateMarker(data.entityName, data, markersData, this.options)
this.updateMarker(data.entityName, data, markersData, this.options) }
} else {
else { this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings);
this.createMarker(data.entityName, data, markersData, this.options as MarkerSettings);
}
} }
}); });
} }
@ -264,7 +255,7 @@ export default abstract class LeafletMap {
private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) { private createMarker(key: string, data: FormattedData, dataSources: FormattedData[], settings: MarkerSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker); const newMarker = new Marker(this.convertPosition(data), settings, data, dataSources, this.dragMarker);
this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()), settings.draggableMarker && this.markers.size > 2); this.fitBounds(this.bounds.extend(newMarker.leafletMarker.getLatLng()), settings.draggableMarker && this.markers.size < 2);
this.markers.set(key, newMarker); this.markers.set(key, newMarker);
if (this.options.useClusterMarkers) { if (this.options.useClusterMarkers) {
this.markersCluster.addLayer(newMarker.leafletMarker); this.markersCluster.addLayer(newMarker.leafletMarker);
@ -299,6 +290,9 @@ export default abstract class LeafletMap {
} }
} }
setImageAlias(alias: Observable<any>) {
}
// Polyline // Polyline
updatePolylines(polyData: FormattedData[][]) { updatePolylines(polyData: FormattedData[][]) {
@ -328,7 +322,7 @@ export default abstract class LeafletMap {
updatePolyline(key: string, data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) { updatePolyline(key: string, data: FormattedData[], dataSources: FormattedData[], settings: PolylineSettings) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
this.polylines.get(key).updatePolyline(settings, data, dataSources); this.polylines.get(key).updatePolyline(settings, data.map(el => this.convertPosition(el)), dataSources);
}); });
} }

View File

@ -23,6 +23,7 @@ export type MapSettings = {
polygonKeyName: any; polygonKeyName: any;
draggableMarker: boolean; draggableMarker: boolean;
initCallback?: () => any; initCallback?: () => any;
posFunction: (origXPos, origYPos) => { x, y };
defaultZoomLevel?: number; defaultZoomLevel?: number;
disableScrollZooming?: boolean; disableScrollZooming?: boolean;
minZoomLevel?: number; minZoomLevel?: number;
@ -31,6 +32,8 @@ export type MapSettings = {
lngKeyName?: string; lngKeyName?: string;
xPosKeyName?: string; xPosKeyName?: string;
yPosKeyName?: string; yPosKeyName?: string;
imageEntityAlias: string;
imageUrlAttribute: string;
mapProvider: MapProviders; mapProvider: MapProviders;
mapProviderHere: string; mapProviderHere: string;
mapUrl?: string; mapUrl?: string;
@ -49,7 +52,9 @@ export type MapSettings = {
animate: boolean, animate: boolean,
maxClusterRadius: number, maxClusterRadius: number,
chunkedLoading: boolean, chunkedLoading: boolean,
removeOutsideVisibleBounds: boolean removeOutsideVisibleBounds: boolean,
useCustomProvider: boolean,
customProviderTileUrl: string;
} }
export enum MapProviders { export enum MapProviders {

View File

@ -17,28 +17,28 @@
import { MapProviders, UnitedMapSettings } from './map-models'; import { MapProviders, UnitedMapSettings } from './map-models';
import LeafletMap from './leaflet-map'; import LeafletMap from './leaflet-map';
import { import {
commonMapSettingsSchema, openstreetMapSettingsSchema,
googleMapSettingsSchema, googleMapSettingsSchema,
hereMapSettingsSchema, imageMapSettingsSchema,
imageMapSettingsSchema, tencentMapSettingsSchema,
mapPolygonSchema, commonMapSettingsSchema,
mapProviderSchema, routeMapSettingsSchema,
markerClusteringSettingsSchema, markerClusteringSettingsSchema,
markerClusteringSettingsSchemaLeaflet, markerClusteringSettingsSchemaLeaflet,
openstreetMapSettingsSchema, hereMapSettingsSchema,
routeMapSettingsSchema, mapProviderSchema,
tencentMapSettingsSchema mapPolygonSchema
} from './schemes'; } from './schemes';
import { MapWidgetInterface, MapWidgetStaticInterface } from './map-widget.interface'; import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface';
import { GoogleMap, HEREMap, ImageMap, OpenStreetMap, TencentMap } from './providers'; import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers';
import { parseArray, parseData, parseFunction, parseWithTranslation } from '@core/utils'; import { parseFunction, parseArray, parseData, parseWithTranslation } from '@core/utils';
import { addCondition, addGroupInfo, addToSchema, initSchema, mergeSchemes } from '@core/schema-utils'; import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } from '@core/schema-utils';
import { forkJoin } from 'rxjs'; import { of, Subject } from 'rxjs';
import { WidgetContext } from '@app/modules/home/models/widget-component.models'; import { WidgetContext } from '@app/modules/home/models/widget-component.models';
import { getDefCenterPosition } from './maps-utils'; import { getDefCenterPosition } from './maps-utils';
import { JsonSettingsSchema, WidgetActionDescriptor } from '@shared/models/widget.models'; import { JsonSettingsSchema, WidgetActionDescriptor, DatasourceType, widgetType } from '@shared/models/widget.models';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; import { AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
import { AttributeService } from '@core/http/attribute.service'; import { AttributeService } from '@core/http/attribute.service';
import { Type } from '@angular/core'; import { Type } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@ -47,7 +47,7 @@ import { UtilsService } from '@core/services/utils.service';
// @dynamic // @dynamic
export class MapWidgetController implements MapWidgetInterface { export class MapWidgetController implements MapWidgetInterface {
constructor(public mapProvider: MapProviders, private drawRoutes: boolean, public ctx: WidgetContext, $element: HTMLElement) { constructor(public mapProvider: MapProviders, private drawRoutes: boolean, public ctx: WidgetContext, $element: HTMLElement, isEdit?) {
if (this.map) { if (this.map) {
this.map.map.remove(); this.map.map.remove();
delete this.map; delete this.map;
@ -58,6 +58,9 @@ export class MapWidgetController implements MapWidgetInterface {
$element = ctx.$container[0]; $element = ctx.$container[0];
} }
this.settings = this.initSettings(ctx.settings); this.settings = this.initSettings(ctx.settings);
if (isEdit) {
this.settings.draggableMarker = true;
}
this.settings.tooltipAction = this.getDescriptors('tooltipAction'); this.settings.tooltipAction = this.getDescriptors('tooltipAction');
this.settings.markerClick = this.getDescriptors('markerClick'); this.settings.markerClick = this.getDescriptors('markerClick');
this.settings.polygonClick = this.getDescriptors('polygonClick'); this.settings.polygonClick = this.getDescriptors('polygonClick');
@ -69,6 +72,7 @@ export class MapWidgetController implements MapWidgetInterface {
} }
parseWithTranslation.setTranslate(this.translate); parseWithTranslation.setTranslate(this.translate);
this.map = new MapClass($element, this.settings); this.map = new MapClass($element, this.settings);
this.map.setImageAlias(this.subscribeForImageAttribute());
this.map.saveMarkerLocation = this.setMarkerLocation; this.map.saveMarkerLocation = this.setMarkerLocation;
} }
@ -85,26 +89,28 @@ export class MapWidgetController implements MapWidgetInterface {
public static getProvidersSchema(mapProvider: MapProviders) { public static getProvidersSchema(mapProvider: MapProviders) {
mapProviderSchema.schema.properties.provider.default = mapProvider; mapProviderSchema.schema.properties.provider.default = mapProvider;
return mergeSchemes([mapProviderSchema, return mergeSchemes([mapProviderSchema,
...Object.values(providerSets)?.map( ...Object.keys(providerSets)?.map(
(setting: IProvider) => addCondition(setting?.schema, `model.provider === '${setting.name}'`))]); (key: string) => { const setting = providerSets[key]; return addCondition(setting?.schema, `model.provider === '${setting.name}'`) })]);
} }
public static settingsSchema(mapProvider: MapProviders, drawRoutes: boolean): JsonSettingsSchema { public static settingsSchema(mapProvider: MapProviders, drawRoutes: boolean): JsonSettingsSchema {
const schema = initSchema(); const schema = initSchema();
addToSchema(schema, this.getProvidersSchema(mapProvider)); addToSchema(schema, this.getProvidersSchema(mapProvider));
if(mapProvider!=='image-map'){ addGroupInfo(schema, 'Map Provider Settings');
addGroupInfo(schema, 'Map Provider Settings'); addToSchema(schema, addCondition(commonMapSettingsSchema, 'model.provider !== "image-map"'));
addToSchema(schema, mergeSchemes([commonMapSettingsSchema, addCondition(mapPolygonSchema, 'model.showPolygon === true')]));
addGroupInfo(schema, 'Common Map Settings'); addGroupInfo(schema, 'Common Map Settings');
addToSchema(schema, addCondition(mapPolygonSchema, 'model.showPolygon === true', ['showPolygon']));
addGroupInfo(schema, 'Polygon Settings');
if (drawRoutes) { if (drawRoutes) {
addToSchema(schema, routeMapSettingsSchema); addToSchema(schema, routeMapSettingsSchema);
addGroupInfo(schema, 'Route Map Settings'); addGroupInfo(schema, 'Route Map Settings');
} else if (mapProvider !== 'image-map') { } else {
const clusteringSchema = mergeSchemes([markerClusteringSettingsSchema, const clusteringSchema = mergeSchemes([markerClusteringSettingsSchema,
addCondition(markerClusteringSettingsSchemaLeaflet, `model.useClusterMarkers === true`)]) addCondition(markerClusteringSettingsSchemaLeaflet,
`model.useClusterMarkers === true && model.provider !== "image-map"`)])
addToSchema(schema, clusteringSchema); addToSchema(schema, clusteringSchema);
addGroupInfo(schema, 'Markers Clustering Settings'); addGroupInfo(schema, 'Markers Clustering Settings');
}} }
return schema; return schema;
} }
@ -125,9 +131,11 @@ export class MapWidgetController implements MapWidgetInterface {
}; };
} }
translate = (key: string, defaultTranslation?: string):string => { translate = (key: string, defaultTranslation?: string): string => {
return (this.ctx.$injector.get(UtilsService).customTranslation(key, defaultTranslation || key) if (key)
|| this.ctx.$injector.get(TranslateService).instant(key)); return (this.ctx.$injector.get(UtilsService).customTranslation(key, defaultTranslation || key)
|| this.ctx.$injector.get(TranslateService).instant(key));
else return '';
} }
getDescriptors(name: string): { [name: string]: ($event: Event) => void } { getDescriptors(name: string): { [name: string]: ($event: Event) => void } {
@ -143,7 +151,7 @@ export class MapWidgetController implements MapWidgetInterface {
} }
private onCustomAction(descriptor: WidgetActionDescriptor, $event: any) { private onCustomAction(descriptor: WidgetActionDescriptor, $event: any) {
if ($event & $event.stopPropagation) { if ($event && $event.stopPropagation) {
$event?.stopPropagation(); $event?.stopPropagation();
} }
// safeExecute(parseFunction(descriptor.customFunction, ['$event', 'widgetContext']), [$event, this.ctx]) // safeExecute(parseFunction(descriptor.customFunction, ['$event', 'widgetContext']), [$event, this.ctx])
@ -156,29 +164,48 @@ export class MapWidgetController implements MapWidgetInterface {
setMarkerLocation = (e) => { setMarkerLocation = (e) => {
const attributeService = this.ctx.$injector.get(AttributeService); const attributeService = this.ctx.$injector.get(AttributeService);
forkJoin(
this.data.filter(data => !!e[data.dataKey.name]) const entityId: EntityId = {
.map(data => { entityType: e.$datasource.entityType,
const entityId: EntityId = { id: e.$datasource.entityId
entityType: data.datasource.entityType, };
id: data.datasource.entityId const attributes = [];
}; const timeseries = [];
return attributeService.saveEntityAttributes( const latLngProperties = [this.settings.latKeyName, this.settings.lngKeyName, this.settings.xPosKeyName, this.settings.yPosKeyName];
entityId, e.$datasource.dataKeys.forEach(key => {
AttributeScope.SHARED_SCOPE, if (latLngProperties.includes(key.name)) {
[{ const value = {
key: data.dataKey.name, key: key.name,
value: e[data.dataKey.name] value: e[key.name]
}] };
); if (key.type === DataKeyType.attribute) {
})).subscribe(res => { attributes.push(value)
}); }
if (key.type === DataKeyType.timeseries) {
timeseries.push(value)
}
}
});
if (timeseries.length) {
attributeService.saveEntityTimeseries(
entityId,
LatestTelemetry.LATEST_TELEMETRY,
timeseries
).subscribe(() => { });
}
if (attributes.length) {
attributeService.saveEntityAttributes(
entityId,
AttributeScope.SERVER_SCOPE,
attributes
).subscribe(() => { });
}
} }
initSettings(settings: UnitedMapSettings): UnitedMapSettings { initSettings(settings: UnitedMapSettings): UnitedMapSettings {
const functionParams = ['data', 'dsData', 'dsIndex']; const functionParams = ['data', 'dsData', 'dsIndex'];
this.provider = settings.provider || this.mapProvider; this.provider = settings.provider || this.mapProvider;
if (!settings.mapProviderHere) { if (this.provider === MapProviders.here && !settings.mapProviderHere) {
if (settings.mapProvider && hereProviders.includes(settings.mapProvider)) if (settings.mapProvider && hereProviders.includes(settings.mapProvider))
settings.mapProviderHere = settings.mapProvider settings.mapProviderHere = settings.mapProvider
else settings.mapProviderHere = hereProviders[0]; else settings.mapProviderHere = hereProviders[0];
@ -213,8 +240,7 @@ export class MapWidgetController implements MapWidgetInterface {
if (this.settings.draggableMarker) { if (this.settings.draggableMarker) {
this.map.setDataSources(parseData(this.data)); this.map.setDataSources(parseData(this.data));
} }
else this.map.updateMarkers(parseData(this.data));
this.map.updateMarkers(parseData(this.data));
} }
resize() { resize() {
@ -222,6 +248,48 @@ export class MapWidgetController implements MapWidgetInterface {
this.map.onResize(); this.map.onResize();
} }
subscribeForImageAttribute() {
const imageEntityAlias = this.settings.imageEntityAlias;
const imageUrlAttribute = this.settings.imageUrlAttribute;
if (!imageEntityAlias || !imageUrlAttribute) {
return of(false);
}
const entityAliasId = this.ctx.aliasController.getEntityAliasId(imageEntityAlias);
if (!entityAliasId) {
return of(false);
}
const datasources = [
{
type: DatasourceType.entity,
name: imageEntityAlias,
aliasName: imageEntityAlias,
entityAliasId,
dataKeys: [
{
type: DataKeyType.attribute,
name: imageUrlAttribute,
label: imageUrlAttribute,
settings: {},
_hash: Math.random()
}
]
}
];
const result = new Subject();
const imageUrlSubscriptionOptions = {
datasources,
useDashboardTimewindow: false,
type: widgetType.latest,
callbacks: {
onDataUpdated: (subscription) => {
result.next(subscription?.data[0]?.data[0]);
}
}
};
this.ctx.subscriptionApi.createSubscription(imageUrlSubscriptionOptions, true).subscribe(() => { });
return result;
}
onDestroy() { onDestroy() {
} }
} }

View File

@ -16,8 +16,10 @@
.arrow { .arrow {
height: 30px; height: 30px;
width: 30px; width: 30px;
background-size: cover; background-size: contain;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAMAAAANxBKoAAACAVBMVEUAAAAAqv9AgP8ggP8udP8qgP8ndv8kbf8kgP8eeP8rcf8mc/8jdP8hev8me/8kdv8jcv8pcP8ic/8neP8leP8ofP8mef8pev8nef8oe/8nef8pef8qfv8qgf8qe/8mev8off8oev8oef8oe/8pev8qe/8oe/8off8pfP8oev8pev8qe/8qfP8pev8pe/8qfP8pe/8oev8pe/8qe/8qfP8qfP8qff8qff8qfP8qff8pe/8qff8qfP8qfP8pev8pev8JYf8KYP8UY/8UZf8WY/8WZv8YZP8bZP8fZv8fZ/8gZv8gZ/8hZP8iZ/8jaf8jav8kaP8kav8ka/8kbP8kbf8kb/8lbP8lbf8lbv8lb/8lcP8mb/8mcP8mcf8ncf8ncv8nc/8ndP8ndf8ocv4odP8odf8odv8od/8oeP8peP8pef8pev8qev8qe/8qfP8rbP8rfP8rff8tc/4vcP4xbv4zcf42dP49df4+gP4/fv5Rif5biP1ul/14mvx4nvyMrfuMrvuWsfuctvuguPuww/vD0fnH1vrI1frK2PrL2fnV3vnb4vnc5fnd5fnd5vne5fnj6vnl6/jm7Pno7fXo7fbo7ffo7fjp7fnp7vjq7vjs8fnt8Pjt8fjw8fXw8fbw8fjy8/jz9fn5+fj7+/f++/j/+/X/+/b/+/f/+/j//Pj//vhoUaHMAAAAQHRSTlMAAwQICwwNDg4REhQWFxscHTI1QkRGSktOU1RdYWFscXJzhYWKqre6wMHDw8PHx8rN09TW1uLi7e/x8vLz9fj5hfwW0QAAAnVJREFUSMeV1fdb00AYB/BzoQjurSjuvQcuFLcgWqTVtLVpL0GS2GuDuLeouPeAiLOuwOFf6WU0ucvq4/d52v6Qz/M+18u97wHgyfh5m5vUYlHt2rV8BojOqGUqonNhVgTegfxZE2JXoMAUFgXYsSoKy3YfnoIiUqxm8UwUnSoaT0WVUuPi6lCUz+ft/+pqNYwqsiwrlm8s45XBVpE7BQgFyeZLbB1ihVwmefjpDSjbi7HwziArCdlU/MArjDHfaestBh4dZs9/JBb/4kVbo5FEr/JaWRL4VPvZ39jMVV4q63qiCx7bIfDJtst/LYt/JnLldaNuACbS9JwiQj4Zu/3HlDr5nEyJivMcgPn0Nogwfaq1Z9igQ7pO9AuqNEJzQINTV5ZghjvywLFG6dYMVRptAF3uPvBc8xPsWH0Q44ccpEqjvaBoa0lI7/ts2kHdCsbDJ5jSSC2/SEU8856x+hDGd+JZujQquvp6ieT7Nyel0o/jCSgzTefq0y81I30f7PRr2i1fbWrd+98yXtMGfOt29wTyiebHpu83dZ+m3U969qSBeje5DHeod8Dx5PeYZ7/rPO8y0XLvk+1J8UcJyLzLScw5kTsgz8Xu2vXJV0uaOSfsGcznZZGcwdi1L5qV13HmDILV3tY1z3fbxa8Wv+Se74VEj/H3jmz0TvuVN4Z+x/ZORF8efU64s/CtUT0vCbk0d/DZTSgxPQ/WhswTSYTZrDNPllaaVQo1q/Y4k63mv+YgmFZxxk6gR/LsCngcO+6nR9lCrfcqqQ2/dxqD7rT1IXhxyB24O8BuCr9eq9axU7F7wYjoy3ty3TZVLaCC2rRxru/hPwVgtEdFK5vOAAAAAElFTkSuQmCC") no-repeat center center; background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAtCAMAAAANxBKoAAACAVBMVEUAAAAAqv9AgP8ggP8udP8qgP8ndv8kbf8kgP8eeP8rcf8mc/8jdP8hev8me/8kdv8jcv8pcP8ic/8neP8leP8ofP8mef8pev8nef8oe/8nef8pef8qfv8qgf8qe/8mev8off8oev8oef8oe/8pev8qe/8oe/8off8pfP8oev8pev8qe/8qfP8pev8pe/8qfP8pe/8oev8pe/8qe/8qfP8qfP8qff8qff8qfP8qff8pe/8qff8qfP8qfP8pev8pev8JYf8KYP8UY/8UZf8WY/8WZv8YZP8bZP8fZv8fZ/8gZv8gZ/8hZP8iZ/8jaf8jav8kaP8kav8ka/8kbP8kbf8kb/8lbP8lbf8lbv8lb/8lcP8mb/8mcP8mcf8ncf8ncv8nc/8ndP8ndf8ocv4odP8odf8odv8od/8oeP8peP8pef8pev8qev8qe/8qfP8rbP8rfP8rff8tc/4vcP4xbv4zcf42dP49df4+gP4/fv5Rif5biP1ul/14mvx4nvyMrfuMrvuWsfuctvuguPuww/vD0fnH1vrI1frK2PrL2fnV3vnb4vnc5fnd5fnd5vne5fnj6vnl6/jm7Pno7fXo7fbo7ffo7fjp7fnp7vjq7vjs8fnt8Pjt8fjw8fXw8fbw8fjy8/jz9fn5+fj7+/f++/j/+/X/+/b/+/f/+/j//Pj//vhoUaHMAAAAQHRSTlMAAwQICwwNDg4REhQWFxscHTI1QkRGSktOU1RdYWFscXJzhYWKqre6wMHDw8PHx8rN09TW1uLi7e/x8vLz9fj5hfwW0QAAAnVJREFUSMeV1fdb00AYB/BzoQjurSjuvQcuFLcgWqTVtLVpL0GS2GuDuLeouPeAiLOuwOFf6WU0ucvq4/d52v6Qz/M+18u97wHgyfh5m5vUYlHt2rV8BojOqGUqonNhVgTegfxZE2JXoMAUFgXYsSoKy3YfnoIiUqxm8UwUnSoaT0WVUuPi6lCUz+ft/+pqNYwqsiwrlm8s45XBVpE7BQgFyeZLbB1ihVwmefjpDSjbi7HwziArCdlU/MArjDHfaestBh4dZs9/JBb/4kVbo5FEr/JaWRL4VPvZ39jMVV4q63qiCx7bIfDJtst/LYt/JnLldaNuACbS9JwiQj4Zu/3HlDr5nEyJivMcgPn0Nogwfaq1Z9igQ7pO9AuqNEJzQINTV5ZghjvywLFG6dYMVRptAF3uPvBc8xPsWH0Q44ccpEqjvaBoa0lI7/ts2kHdCsbDJ5jSSC2/SEU8856x+hDGd+JZujQquvp6ieT7Nyel0o/jCSgzTefq0y81I30f7PRr2i1fbWrd+98yXtMGfOt29wTyiebHpu83dZ+m3U969qSBeje5DHeod8Dx5PeYZ7/rPO8y0XLvk+1J8UcJyLzLScw5kTsgz8Xu2vXJV0uaOSfsGcznZZGcwdi1L5qV13HmDILV3tY1z3fbxa8Wv+Se74VEj/H3jmz0TvuVN4Z+x/ZORF8efU64s/CtUT0vCbk0d/DZTSgxPQ/WhswTSYTZrDNPllaaVQo1q/Y4k63mv+YgmFZxxk6gR/LsCngcO+6nR9lCrfcqqQ2/dxqD7rT1IXhxyB24O8BuCr9eq9axU7F7wYjoy3ty3TZVLaCC2rRxru/hPwVgtEdFK5vOAAAAAElFTkSuQmCC");
background-position: center;
background-repeat: no-repeat;
} }
.leaflet-div-icon, .leaflet-div-icon,

View File

@ -150,7 +150,6 @@ export class Marker {
} }
createDefaultMarkerIcon(color, onMarkerIconReady) { createDefaultMarkerIcon(color, onMarkerIconReady) {
const pinColor = color.substr(1);
const icon = L.icon({ const icon = L.icon({
iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color, iconUrl: 'https://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|' + color,
iconSize: [21, 34], iconSize: [21, 34],

View File

@ -73,11 +73,14 @@ export class Polyline {
getPolyStyle(settings: PolylineSettings): L.PolylineOptions { getPolyStyle(settings: PolylineSettings): L.PolylineOptions {
return { return {
color: settings.useColorFunction ? color: settings.useColorFunction ?
safeExecute(settings.colorFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.color, safeExecute(settings.colorFunction,
[this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.color,
opacity: settings.useStrokeOpacityFunction ? opacity: settings.useStrokeOpacityFunction ?
safeExecute(settings.strokeOpacityFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeOpacity, safeExecute(settings.strokeOpacityFunction,
[this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.strokeOpacity,
weight: settings.useStrokeWeightFunction ? weight: settings.useStrokeWeightFunction ?
safeExecute(settings.strokeWeightFunction, [this.data, this.dataSources, this.data[0]?.dsIndex]) : settings.strokeWeight, safeExecute(settings.strokeWeightFunction,
[this.data, this.dataSources, this.dataSources[0]?.dsIndex]) : settings.strokeWeight,
} }
} }

View File

@ -17,7 +17,9 @@
import L, { LatLngLiteral } from 'leaflet'; import L, { LatLngLiteral } from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { UnitedMapSettings } from '../map-models'; import { UnitedMapSettings } from '../map-models';
import { aspectCache } from '@app/core/utils'; import { aspectCache, parseFunction } from '@app/core/utils';
import { Observable } from 'rxjs';
import { map, filter, switchMap } from 'rxjs/operators';
const maxZoom = 4;// ? const maxZoom = 4;// ?
@ -27,10 +29,13 @@ export class ImageMap extends LeafletMap {
aspect = 0; aspect = 0;
width = 0; width = 0;
height = 0; height = 0;
imageUrl;
constructor($container: HTMLElement, options: UnitedMapSettings) { constructor($container: HTMLElement, options: UnitedMapSettings) {
super($container, options); super($container, options);
aspectCache(options.mapUrl).subscribe(aspect => { options.posFunction = parseFunction(options.posFunction, ['origXPos', 'origYPos']) as ((origXPos, origYPos) => { x, y });
this.imageUrl = options.mapUrl;
aspectCache(this.imageUrl).subscribe(aspect => {
this.aspect = aspect; this.aspect = aspect;
this.onResize(); this.onResize();
super.setMap(this.map); super.setMap(this.map);
@ -38,6 +43,16 @@ export class ImageMap extends LeafletMap {
}); });
} }
setImageAlias(alias: Observable<any>) {
alias.pipe(filter(result => result), map(el => el[1]), switchMap(res => {
this.imageUrl = res;
return aspectCache(res);
})).subscribe(aspect => {
this.aspect = aspect;
this.onResize(true);
});
}
updateBounds(updateImage?, lastCenterPos?) { updateBounds(updateImage?, lastCenterPos?) {
const w = this.width; const w = this.width;
const h = this.height; const h = this.height;
@ -53,8 +68,7 @@ export class ImageMap extends LeafletMap {
if (this.imageOverlay) { if (this.imageOverlay) {
this.imageOverlay.setBounds(bounds); this.imageOverlay.setBounds(bounds);
} else { } else {
this.imageOverlay = L.imageOverlay(this.options.mapUrl, bounds).addTo(this.map); this.imageOverlay = L.imageOverlay(this.imageUrl, bounds).addTo(this.map);
} }
const padding = 200 * maxZoom; const padding = 200 * maxZoom;
southWest = this.pointToLatLng(-padding, h + padding); southWest = this.pointToLatLng(-padding, h + padding);
@ -116,6 +130,7 @@ export class ImageMap extends LeafletMap {
} }
convertPosition(expression): L.LatLng { convertPosition(expression): L.LatLng {
if (isNaN(expression[this.options.xPosKeyName]) || isNaN(expression[this.options.yPosKeyName])) return null;
return this.pointToLatLng( return this.pointToLatLng(
expression[this.options.xPosKeyName] * this.width, expression[this.options.xPosKeyName] * this.width,
expression[this.options.yPosKeyName] * this.height); expression[this.options.yPosKeyName] * this.height);
@ -129,10 +144,10 @@ export class ImageMap extends LeafletMap {
return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1); return L.CRS.Simple.latLngToPoint(latLng, maxZoom - 1);
} }
/* convertToCustomFormat(position: L.LatLng): object { convertToCustomFormat(position: L.LatLng): object {
return { return {
[this.options.xPosKeyName]: (position.lng + 180) / 360, [this.options.xPosKeyName]: (position.lng + 180) / 360,
[this.options.yPosKeyName]: (position.lat + 180) / 360 [this.options.yPosKeyName]: (position.lat + 180) / 360
} }
}*/ }
} }

View File

@ -22,7 +22,11 @@ export class OpenStreetMap extends LeafletMap {
constructor($container, options: UnitedMapSettings) { constructor($container, options: UnitedMapSettings) {
super($container, options); super($container, options);
const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel); const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
const tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik'); let tileLayer;
if (options.useCustomProvider)
tileLayer = L.tileLayer(options.customProviderTileUrl);
else
tileLayer = (L.tileLayer as any).provider(options.mapProvider || 'OpenStreetMap.Mapnik');
tileLayer.addTo(map); tileLayer.addTo(map);
super.setMap(map); super.setMap(map);
super.initSettings(options); super.initSettings(options);

View File

@ -336,11 +336,6 @@ export const commonMapSettingsSchema =
title: 'Color function: f(data, dsData, dsIndex)', title: 'Color function: f(data, dsData, dsIndex)',
type: 'string' type: 'string'
}, },
showPolygon: {
title: 'Show polygon',
type: 'boolean',
default: false
},
markerImage: { markerImage: {
title: 'Custom marker image', title: 'Custom marker image',
type: 'string' type: 'string'
@ -439,8 +434,7 @@ export const commonMapSettingsSchema =
type: 'image' type: 'image'
} }
] ]
}, }
'showPolygon',
] ]
}; };
@ -450,6 +444,11 @@ export const mapPolygonSchema =
title: 'Map Polygon Configuration', title: 'Map Polygon Configuration',
type: 'object', type: 'object',
properties: { properties: {
showPolygon: {
title: 'Show polygon',
type: 'boolean',
default: false
},
polygonKeyName: { polygonKeyName: {
title: 'Polygon key name', title: 'Polygon key name',
type: 'string', type: 'string',
@ -491,6 +490,7 @@ export const mapPolygonSchema =
required: [] required: []
}, },
form: [ form: [
'showPolygon',
'polygonKeyName', 'polygonKeyName',
{ {
key: 'polygonColor', key: 'polygonColor',

View File

@ -17,7 +17,7 @@
--> -->
<div class="trip-animation-widget"> <div class="trip-animation-widget">
<div class="trip-animation-label-container" *ngIf="settings.showLabel"> <div class="trip-animation-label-container" *ngIf="settings.showLabel">
{{label }} {{label}}
</div> </div>
<div class="trip-animation-container" fxLayout="column"> <div class="trip-animation-container" fxLayout="column">
<div class="map" #map></div> <div class="map" #map></div>

View File

@ -22,8 +22,8 @@ import { interpolateOnPointSegment } from 'leaflet-geometryutil';
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, Input, OnInit, SecurityContext, ViewChild } from '@angular/core';
import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2'; import { MapWidgetController, TbMapWidgetV2 } from '../lib/maps/map-widget2';
import { MapProviders } from '../lib/maps/map-models'; import { MapProviders } from '../lib/maps/map-models';
import { parseArray, parseWithTranslation, safeExecute } from '@app/core/utils'; import { parseArray, parseWithTranslation, safeExecute, parseTemplate } from '@app/core/utils';
import { addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils'; import { initSchema, addToSchema, addGroupInfo } from '@app/core/schema-utils';
import { tripAnimationSchema } from '../lib/maps/schemes'; import { tripAnimationSchema } from '../lib/maps/schemes';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { WidgetContext } from '@app/modules/home/models/widget-component.models'; import { WidgetContext } from '@app/modules/home/models/widget-component.models';
@ -100,8 +100,8 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
timeUpdated(time: number) { timeUpdated(time: number) {
const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]); const currentPosition = this.interpolatedData.map(dataSource => dataSource[time]);
this.activeTrip = currentPosition[0]; this.activeTrip = currentPosition[0];
this.minTime = moment(this.historicalData[0][this.historicalData.length - 1]?.time).format('YYYY-MM-DD HH:mm:ss') this.minTime = moment(this.intervals[this.intervals.length - 1]).format('YYYY-MM-DD HH:mm:ss')
this.maxTime = moment(this.historicalData[0][0]?.time).format('YYYY-MM-DD HH:mm:ss') this.maxTime = moment(this.intervals[0]).format('YYYY-MM-DD HH:mm:ss')
this.calcLabel(); this.calcLabel();
this.calcTooltip(); this.calcTooltip();
if (this.mapWidget) { if (this.mapWidget) {

View File

@ -51,6 +51,16 @@
padding: 0 0 2px; padding: 0 0 2px;
margin: 2px; margin: 2px;
line-height: 24px; line-height: 24px;
mat-icon {
width: 24px;
height: 24px;
svg {
width: inherit;
height: inherit;
}
}
} }
} }
@ -80,24 +90,24 @@
mat-slider { mat-slider {
min-width: 80px; min-width: 80px;
} }
}
button.mat-button.mat-icon-button { .mat-icon-button {
width: 44px; width: 44px;
min-width: 44px; min-width: 44px;
height: 44px; height: 48px;
min-height: 44px; min-height: 48px;
margin: 0; margin: 0;
line-height: 28px; line-height: 28px;
mat-icon { mat-icon {
width: 28px; width: 24px;
height: 28px; height: 24px;
font-size: 28px; font-size: 24px;
svg { svg {
width: inherit; width: inherit;
height: inherit; height: inherit;
}
} }
} }

View File

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { interval } from 'rxjs'; import { interval } from 'rxjs';
import { filter } from 'rxjs/operators'; import { filter } from 'rxjs/operators';
import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models'; import { HistorySelectSettings } from '@app/modules/home/components/widget/lib/maps/map-models';

View File

@ -15,7 +15,7 @@
/// ///
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { parseWithTranslation } from '@app/core/utils'; import { parseTemplate, parseWithTranslation } from '@app/core/utils';
@Pipe({ name: 'tbParseTemplate' }) @Pipe({ name: 'tbParseTemplate' })
export class TbTemplatePipe implements PipeTransform { export class TbTemplatePipe implements PipeTransform {

View File

@ -2,7 +2,8 @@
"extends": "../tsconfig.json", "extends": "../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/app", "outDir": "../out-tsc/app",
"types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify", "react", "react-dom", "jstree", "raphael", "canvas-gauges"] "types": ["node", "jquery", "flot", "tooltipster", "tinycolor2", "js-beautify",
"react", "react-dom", "jstree", "raphael", "canvas-gauges", "leaflet", "leaflet-markercluster"]
}, },
"angularCompilerOptions": { "angularCompilerOptions": {
"fullTemplateTypeCheck": true "fullTemplateTypeCheck": true

View File

@ -11,7 +11,8 @@
}, },
"import-blacklist": [ "import-blacklist": [
true, true,
"rxjs/Rx" "rxjs/Rx",
"^.*/public-api$"
], ],
"interface-name": false, "interface-name": false,
"max-classes-per-file": false, "max-classes-per-file": false,