Browse Source

Merge branch 'map/3.0' of https://github.com/ArtemHalushko/thingsboard into ArtemHalushko-map/3.0

pull/2729/head
Igor Kulikov 6 years ago
parent
commit
6440f9acfe
  1. 7
      ui-ngx/src/app/core/utils.ts
  2. 11
      ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
  3. 9
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-models.ts
  4. 17
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts
  5. 11
      ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
  6. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/markers.ts
  7. 16
      ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts
  8. 5
      ui-ngx/src/app/modules/home/components/widget/lib/maps/providers/image-map.ts

7
ui-ngx/src/app/core/utils.ts

@ -19,6 +19,7 @@ import { Observable, Observer, of, Subject } from 'rxjs';
import { finalize, map, share } from 'rxjs/operators'; import { finalize, map, share } from 'rxjs/operators';
import base64js from 'base64-js'; import base64js from 'base64-js';
import { Datasource } from '@app/shared/models/widget.models'; import { Datasource } from '@app/shared/models/widget.models';
import { FormattedData } from '@app/modules/home/components/widget/lib/maps/map-models';
export function onParentScrollOrWindowResize(el: Node): Observable<Event> { export function onParentScrollOrWindowResize(el: Node): Observable<Event> {
const scrollSubject = new Subject<Event>(); const scrollSubject = new Subject<Event>();
@ -521,12 +522,12 @@ export function parseArray(input: any[]): any[] {
); );
} }
export function parseData(input: any[]): any[] { export function parseData(input: any[]): FormattedData[] {
return _(input).groupBy(el => el?.datasource?.entityName) return _(input).groupBy(el => el?.datasource?.entityName)
.values().value().map((entityArray, i) => { .values().value().map((entityArray, i) => {
const obj = { const obj = {
entityName: entityArray[0]?.datasource?.entityName, entityName: entityArray[0]?.datasource?.entityName,
$datasource: entityArray[0]?.datasource, $datasource: entityArray[0]?.datasource as Datasource,
dsIndex: i, dsIndex: i,
deviceType: null deviceType: null
}; };
@ -585,7 +586,7 @@ export function parseTemplate(template: string, data: { $datasource?: Datasource
formatted.forEach(value => { formatted.forEach(value => {
const [variable, digits] = value.replace('${', '').replace('}', '').split(':'); const [variable, digits] = value.replace('${', '').replace('}', '').split(':');
data[variable] = padValue(data[variable], +digits); data[variable] = padValue(data[variable], +digits);
if (isNaN(data[variable])) data[value] = ''; if (data[variable] === 'NaN') data[variable] = '';
template = template.replace(value, '${' + variable + '}'); template = template.replace(value, '${' + variable + '}');
}); });
const variables = template.match(/\$\{.*?\}/g); const variables = template.match(/\$\{.*?\}/g);

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

@ -198,9 +198,15 @@ export default abstract class LeafletMap {
fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) { fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) {
if (bounds.isValid()) { if (bounds.isValid()) {
if ((!this.options.fitMapBounds || this.options.useDefaultCenterPosition) && this.options.defaultZoomLevel) { this.bounds = this.bounds.extend(bounds);
if (!this.options.fitMapBounds && this.options.defaultZoomLevel) {
this.map.setZoom(this.options.defaultZoomLevel, { animate: false }); this.map.setZoom(this.options.defaultZoomLevel, { animate: false });
this.map.panTo(this.options.defaultCenterPosition, { animate: false }); if (this.options.useDefaultCenterPosition) {
this.map.panTo(this.options.defaultCenterPosition, { animate: false });
}
else {
this.map.panTo(this.bounds.getCenter());
}
} else { } else {
this.map.once('zoomend', () => { this.map.once('zoomend', () => {
if (!this.options.defaultZoomLevel && this.map.getZoom() > this.options.minZoomLevel) { if (!this.options.defaultZoomLevel && this.map.getZoom() > this.options.minZoomLevel) {
@ -212,7 +218,6 @@ 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 = bounds;
} }
} }

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

@ -15,6 +15,7 @@
/// ///
import { LatLngTuple, LeafletMouseEvent } from 'leaflet'; import { LatLngTuple, LeafletMouseEvent } from 'leaflet';
import { Datasource } from '@app/shared/models/widget.models';
export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type GenericFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string; export type MarkerImageFunction = (data: FormattedData, dsData: FormattedData[], dsIndex: number) => string;
@ -96,11 +97,11 @@ export type MarkerSettings = {
} }
export interface FormattedData { export interface FormattedData {
aliasName: string; $datasource: Datasource;
entityName: string; entityName: string;
$datasource: string;
dsIndex: number; dsIndex: number;
deviceType: string deviceType: string;
[key: string]: any
} }
export type PolygonSettings = { export type PolygonSettings = {
@ -151,6 +152,6 @@ export interface HistorySelectSettings {
buttonColor: string; buttonColor: string;
} }
export type actionsHandler = ($event: Event | LeafletMouseEvent) => void; export type actionsHandler = ($event: Event | LeafletMouseEvent, datasource: Datasource) => void;
export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings; export type UnitedMapSettings = MapSettings & PolygonSettings & MarkerSettings & PolylineSettings;

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

@ -36,7 +36,7 @@ import { initSchema, addToSchema, mergeSchemes, addCondition, addGroupInfo } fro
import { of, Subject } 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, DatasourceType, widgetType } from '@shared/models/widget.models'; import { JsonSettingsSchema, WidgetActionDescriptor, DatasourceType, widgetType, Datasource } from '@shared/models/widget.models';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { AttributeScope, DataKeyType, LatestTelemetry } 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';
@ -142,7 +142,7 @@ export class MapWidgetController implements MapWidgetInterface {
const descriptors = this.ctx.actionsApi.getActionDescriptors(name); const descriptors = this.ctx.actionsApi.getActionDescriptors(name);
const actions = {}; const actions = {};
descriptors.forEach(descriptor => { descriptors.forEach(descriptor => {
actions[descriptor.name] = ($event: Event) => this.onCustomAction(descriptor, $event); actions[descriptor.name] = ($event: Event, datasource: Datasource) => this.onCustomAction(descriptor, $event, datasource);
}, actions); }, actions);
return actions; return actions;
} }
@ -150,16 +150,15 @@ export class MapWidgetController implements MapWidgetInterface {
onInit() { onInit() {
} }
private onCustomAction(descriptor: WidgetActionDescriptor, $event: any) { private onCustomAction(descriptor: WidgetActionDescriptor, $event: any, entityInfo: Datasource) {
if ($event && $event.stopPropagation) { if ($event && $event.stopPropagation) {
$event?.stopPropagation(); $event?.stopPropagation();
} }
// safeExecute(parseFunction(descriptor.customFunction, ['$event', 'widgetContext']), [$event, this.ctx]) const { entityId, entityName, entityLabel, entityType } = entityInfo;
const entityInfo = this.ctx.actionsApi.getActiveEntityInfo(); this.ctx.actionsApi.handleWidgetAction($event, descriptor, {
const entityId = entityInfo ? entityInfo.entityId : null; entityType,
const entityName = entityInfo ? entityInfo.entityName : null; id: entityId
const entityLabel = entityInfo ? entityInfo.entityLabel : null; }, entityName, null, entityLabel);
this.ctx.actionsApi.handleWidgetAction($event, descriptor, entityId, entityName, null, entityLabel);
} }
setMarkerLocation = (e) => { setMarkerLocation = (e) => {

11
ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts

@ -16,19 +16,22 @@
import L from 'leaflet'; import L from 'leaflet';
import { MarkerSettings, PolygonSettings, PolylineSettings } from './map-models'; import { MarkerSettings, PolygonSettings, PolylineSettings } from './map-models';
import { Datasource } from '@app/shared/models/widget.models';
export function createTooltip(target: L.Layer, export function createTooltip(target: L.Layer,
settings: MarkerSettings | PolylineSettings | PolygonSettings, settings: MarkerSettings | PolylineSettings | PolygonSettings,
content?: string | HTMLElement): L.Popup { datasource: Datasource,
content?: string | HTMLElement
): L.Popup {
const popup = L.popup(); const popup = L.popup();
popup.setContent(content); popup.setContent(content);
target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false });
if (settings.showTooltipAction === 'hover') { if (settings.showTooltipAction === 'hover') {
target.off('click'); target.off('click');
target.on('mouseover', function () { target.on('mouseover', () => {
target.openPopup(); target.openPopup();
}); });
target.on('mouseout', function () { target.on('mouseout', () => {
target.closePopup(); target.closePopup();
}); });
} }
@ -37,7 +40,7 @@ export function createTooltip(target: L.Layer,
Array.from(actions).forEach( Array.from(actions).forEach(
(element: HTMLElement) => { (element: HTMLElement) => {
if (element && settings.tooltipAction[element.id]) { if (element && settings.tooltipAction[element.id]) {
element.addEventListener('click', settings.tooltipAction[element.id]) element.addEventListener('click', ($event) => settings.tooltipAction[element.id]($event, datasource));
} }
}); });
}); });

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

@ -42,7 +42,7 @@ export class Marker {
}); });
if (settings.showTooltip) { if (settings.showTooltip) {
this.tooltip = createTooltip(this.leafletMarker, settings); this.tooltip = createTooltip(this.leafletMarker, settings, data.$datasource);
this.updateMarkerTooltip(data); this.updateMarkerTooltip(data);
} }
@ -50,7 +50,7 @@ export class Marker {
this.leafletMarker.on('click', (event: LeafletMouseEvent) => { this.leafletMarker.on('click', (event: LeafletMouseEvent) => {
for (const action in this.settings.markerClick) { for (const action in this.settings.markerClick) {
if (typeof (this.settings.markerClick[action]) === 'function') { if (typeof (this.settings.markerClick[action]) === 'function') {
this.settings.markerClick[action](event); this.settings.markerClick[action](event, this.data.$datasource);
} }
} }
}); });

16
ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { LatLngExpression, LatLngTuple } from 'leaflet'; import L, { LatLngExpression, LatLngTuple, LeafletMouseEvent } from 'leaflet';
import { createTooltip } from './maps-utils'; import { createTooltip } from './maps-utils';
import { PolygonSettings, FormattedData } from './map-models'; import { PolygonSettings, FormattedData } from './map-models';
import { DatasourceData } from '@app/shared/models/widget.models'; import { DatasourceData } from '@app/shared/models/widget.models';
@ -27,7 +27,7 @@ export class Polygon {
data; data;
dataSources; dataSources;
constructor(public map, polyData: DatasourceData, dataSources, private settings: PolygonSettings, onClickListener?) { constructor(public map, polyData: DatasourceData, dataSources, private settings: PolygonSettings) {
this.leafletPoly = L.polygon(polyData.data, { this.leafletPoly = L.polygon(polyData.data, {
fill: true, fill: true,
fillColor: settings.polygonColor, fillColor: settings.polygonColor,
@ -39,11 +39,17 @@ export class Polygon {
this.dataSources = dataSources; this.dataSources = dataSources;
this.data = polyData; this.data = polyData;
if (settings.showPolygonTooltip) { if (settings.showPolygonTooltip) {
this.tooltip = createTooltip(this.leafletPoly, settings); this.tooltip = createTooltip(this.leafletPoly, settings, polyData.datasource);
this.updateTooltip(polyData); this.updateTooltip(polyData);
} }
if (onClickListener) { if (settings.polygonClick) {
this.leafletPoly.on('click', onClickListener); 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, polyData.datasource);
}
}
});
} }
} }

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

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import L, { LatLngLiteral } from 'leaflet'; import L, { LatLngLiteral, LatLngBounds, LatLngTuple } from 'leaflet';
import LeafletMap from '../leaflet-map'; import LeafletMap from '../leaflet-map';
import { UnitedMapSettings } from '../map-models'; import { UnitedMapSettings } from '../map-models';
import { aspectCache, parseFunction } from '@app/core/utils'; import { aspectCache, parseFunction } from '@app/core/utils';
@ -108,11 +108,12 @@ export class ImageMap extends LeafletMap {
this.updateBounds(updateImage, lastCenterPos); this.updateBounds(updateImage, lastCenterPos);
this.map.invalidateSize(true); this.map.invalidateSize(true);
} }
} }
} }
} }
fitBounds(bounds: LatLngBounds, useDefaultZoom = false, padding?: LatLngTuple) { }
initMap(updateImage?) { initMap(updateImage?) {
if (!this.map && this.aspect > 0) { if (!this.map && this.aspect > 0) {
const center = this.pointToLatLng(this.width / 2, this.height / 2); const center = this.pointToLatLng(this.width / 2, this.height / 2);

Loading…
Cancel
Save