Browse Source

UI: Map data layer click action

pull/12723/head
Igor Kulikov 2 years ago
parent
commit
3c94c86098
  1. 4
      application/src/main/data/json/system/widget_types/image_map.json
  2. 4
      application/src/main/data/json/system/widget_types/map.json
  3. 2
      ui-ngx/src/app/core/api/widget-api.models.ts
  4. 8
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/circles-data-layer.ts
  5. 11
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/map-data-layer.ts
  6. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/markers-data-layer.ts
  7. 4
      ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polygons-data-layer.ts
  8. 65
      ui-ngx/src/app/modules/home/components/widget/lib/maps/map.ts
  9. 15
      ui-ngx/src/app/modules/home/components/widget/lib/maps/models/map.models.ts
  10. 1
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/action-settings-button.component.html
  11. 12
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html
  12. 1
      ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts
  13. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

4
application/src/main/data/json/system/widget_types/image_map.json

File diff suppressed because one or more lines are too long

4
application/src/main/data/json/system/widget_types/map.json

File diff suppressed because one or more lines are too long

2
ui-ngx/src/app/core/api/widget-api.models.ts

@ -93,7 +93,7 @@ export interface IWidgetUtils {
export interface WidgetActionsApi {
actionDescriptorsBySourceId: {[sourceId: string]: Array<WidgetActionDescriptor>};
getActionDescriptors: (actionSourceId: string) => Array<WidgetActionDescriptor>;
handleWidgetAction: ($event: Event, descriptor: WidgetActionDescriptor,
handleWidgetAction: ($event: Event, descriptor: WidgetAction,
entityId?: EntityId, entityName?: string, additionalParams?: any, entityLabel?: string) => void;
onWidgetAction: ($event: Event, action: WidgetAction) => void;
elementClick: ($event: Event) => void;

8
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/circles-data-layer.ts

@ -16,7 +16,9 @@
import {
CirclesDataLayerSettings,
defaultBaseCirclesDataLayerSettings, isJSON, TbCircleData,
defaultBaseCirclesDataLayerSettings,
isJSON,
TbCircleData,
TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models';
import L from 'leaflet';
@ -59,10 +61,6 @@ class TbCircleDataLayerItem extends TbDataLayerItem<CirclesDataLayerSettings, Tb
return this.circle;
}
protected createEventListeners(data: FormattedData<TbMapDatasource>, _dsData: FormattedData<TbMapDatasource>[]): void {
this.dataLayer.getMap().circleClick(this, data.$datasource);
}
protected unbindLabel() {
this.circle.unbindTooltip();
}

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

@ -29,7 +29,7 @@ import {
TbMapDatasource
} from '@home/components/widget/lib/maps/models/map.models';
import { TbMap } from '@home/components/widget/lib/maps/map';
import { FormattedData } from '@shared/models/widget.models';
import { FormattedData, WidgetActionType } from '@shared/models/widget.models';
import { forkJoin, Observable, of } from 'rxjs';
import {
createLabelFromPattern,
@ -64,7 +64,6 @@ export abstract class TbDataLayerItem<S extends MapDataLayerSettings = MapDataLa
this.updateTooltip(data, dsData);
}
this.bindEvents();
this.createEventListeners(data, dsData);
try {
this.dataLayer.getDataLayerContainer().addLayer(this.layer);
this.editModeUpdated();
@ -83,8 +82,6 @@ export abstract class TbDataLayerItem<S extends MapDataLayerSettings = MapDataLa
protected abstract bindLabel(content: L.Content): void;
protected abstract createEventListeners(data: FormattedData<TbMapDatasource>, dsData: FormattedData<TbMapDatasource>[]): void;
protected abstract addItemClass(clazz: string): void;
protected abstract removeItemClass(clazz: string): void;
@ -103,6 +100,12 @@ export abstract class TbDataLayerItem<S extends MapDataLayerSettings = MapDataLa
}
});
}
const clickAction = this.settings.click;
if (clickAction && clickAction.type !== WidgetActionType.doNothing) {
this.layer.on('click', (event) => {
this.dataLayer.getMap().dataItemClick(event.originalEvent, clickAction, this.data.$datasource);
});
}
}
protected enableEdit(): void {

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

@ -91,10 +91,6 @@ class TbMarkerDataLayerItem extends TbDataLayerItem<MarkersDataLayerSettings, Tb
return this.marker;
}
protected createEventListeners(data: FormattedData<TbMapDatasource>, _dsData: FormattedData<TbMapDatasource>[]): void {
this.dataLayer.getMap().markerClick(this, data.$datasource);
}
protected unbindLabel() {
this.marker.unbindTooltip();
}

4
ui-ngx/src/app/modules/home/components/widget/lib/maps/data-layer/polygons-data-layer.ts

@ -64,10 +64,6 @@ class TbPolygonDataLayerItem extends TbDataLayerItem<PolygonsDataLayerSettings,
return this.polygonContainer;
}
protected createEventListeners(data: FormattedData<TbMapDatasource>, _dsData: FormattedData<TbMapDatasource>[]): void {
this.dataLayer.getMap().polygonClick(this, data.$datasource);
}
protected unbindLabel() {
this.polygonContainer.unbindTooltip();
}

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

@ -20,8 +20,8 @@ import {
DataKeyValuePair,
MapActionHandler,
MapType,
mergeUnplacedDataItemsArrays,
mergeMapDatasources,
mergeUnplacedDataItemsArrays,
parseCenterPosition,
TbCircleData,
TbMapDatasource,
@ -38,10 +38,11 @@ import '@home/components/widget/lib/maps/leaflet/leaflet-tb';
import {
MapDataLayerType,
TbDataLayerItem,
TbMapDataLayer, UnplacedMapDataItem,
TbMapDataLayer,
UnplacedMapDataItem,
} from '@home/components/widget/lib/maps/data-layer/map-data-layer';
import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
import { FormattedData, WidgetActionDescriptor, widgetType } from '@shared/models/widget.models';
import { FormattedData, WidgetAction, WidgetActionDescriptor, widgetType } from '@shared/models/widget.models';
import { EntityDataPageLink } from '@shared/models/query/query.models';
import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
import { TbMarkersDataLayer } from '@home/components/widget/lib/maps/data-layer/markers-data-layer';
@ -50,8 +51,6 @@ import { TbCirclesDataLayer } from '@home/components/widget/lib/maps/data-layer/
import { AttributeService } from '@core/http/attribute.service';
import { AttributeData, AttributeScope, DataKeyType, LatestTelemetry } from '@shared/models/telemetry/telemetry.models';
import { EntityId } from '@shared/models/id/entity-id';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide;
import { TbPopoverService } from '@shared/components/popover.service';
import {
SelectMapEntityPanelComponent
@ -61,6 +60,8 @@ import { createColorMarkerShapeURI, MarkerShape } from '@home/components/widget/
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import tinycolor from 'tinycolor2';
import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance;
import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide;
type TooltipInstancesData = {root: HTMLElement, instances: ITooltipsterInstance[]};
@ -99,9 +100,6 @@ export abstract class TbMap<S extends BaseMapSettings> {
private readonly mapResize$: ResizeObserver;
private readonly tooltipActions: { [name: string]: MapActionHandler };
private readonly markerClickActions: { [name: string]: MapActionHandler };
private readonly polygonClickActions: { [name: string]: MapActionHandler };
private readonly circleClickActions: { [name: string]: MapActionHandler };
private tooltipInstances: TooltipInstancesData[] = [];
@ -118,9 +116,6 @@ export abstract class TbMap<S extends BaseMapSettings> {
this.settings = mergeDeepIgnoreArray({} as S, this.defaultSettings(), this.inputSettings as S);
this.tooltipActions = this.loadActions('tooltipAction');
this.markerClickActions = this.loadActions('markerClick');
this.polygonClickActions = this.loadActions('polygonClick');
this.circleClickActions = this.loadActions('circleClick');
$(containerElement).empty();
$(containerElement).addClass('tb-map-layout');
@ -698,6 +693,18 @@ export abstract class TbMap<S extends BaseMapSettings> {
this.updateAddButtonsStates();
}
public dataItemClick($event: Event, action: WidgetAction, entityInfo: TbMapDatasource) {
if ($event) {
$event.preventDefault();
$event.stopPropagation();
}
const { entityId, entityName, entityLabel, entityType } = entityInfo;
this.ctx.actionsApi.handleWidgetAction($event, action, {
entityType,
id: entityId
}, entityName, null, entityLabel);
}
public tooltipElementClick(element: HTMLElement, action: string, datasource: TbMapDatasource): void {
if (element && this.tooltipActions[action]) {
element.onclick = ($event) =>
@ -708,42 +715,6 @@ export abstract class TbMap<S extends BaseMapSettings> {
}
}
public markerClick(marker: TbDataLayerItem, datasource: TbMapDatasource): void {
if (Object.keys(this.markerClickActions).length) {
marker.getLayer().on('click', (event: L.LeafletMouseEvent) => {
if (!marker.isEditing()) {
for (const action in this.markerClickActions) {
this.markerClickActions[action](event.originalEvent, datasource);
}
}
});
}
}
public polygonClick(polygon: TbDataLayerItem, datasource: TbMapDatasource): void {
if (Object.keys(this.polygonClickActions).length) {
polygon.getLayer().on('click', (event: L.LeafletMouseEvent) => {
if (!polygon.isEditing()) {
for (const action in this.polygonClickActions) {
this.polygonClickActions[action](event.originalEvent, datasource);
}
}
});
}
}
public circleClick(circle: TbDataLayerItem, datasource: TbMapDatasource): void {
if (Object.keys(this.circleClickActions).length) {
circle.getLayer().on('click', (event: L.LeafletMouseEvent) => {
if (!circle.isEditing()) {
for (const action in this.circleClickActions) {
this.circleClickActions[action](event.originalEvent, datasource);
}
}
});
}
}
public selectItem(item: TbDataLayerItem, cancel = false, force = false): boolean {
if (this.isPlacingItem) {
return false;

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

@ -14,12 +14,19 @@
/// limitations under the License.
///
import { DataKey, Datasource, DatasourceType, FormattedData } from '@shared/models/widget.models';
import {
DataKey,
Datasource,
DatasourceType,
FormattedData,
WidgetAction,
WidgetActionType
} from '@shared/models/widget.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { guid, hashCode, isDefinedAndNotNull, isNotEmptyStr, isString, mergeDeep } from '@core/utils';
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
import { materialColors } from '@shared/models/material.models';
import L, { LatLngExpression } from 'leaflet';
import L from 'leaflet';
import { TbFunction } from '@shared/models/js-function.models';
import { Observable, Observer, of, switchMap } from 'rxjs';
import { map } from 'rxjs/operators';
@ -117,6 +124,7 @@ export interface MapDataLayerSettings extends MapDataSourceSettings {
additionalDataKeys?: DataKey[];
label: DataLayerPatternSettings;
tooltip: DataLayerTooltipSettings;
click: WidgetAction;
groups?: string[];
edit: DataLayerEditSettings;
}
@ -138,6 +146,9 @@ export const defaultBaseDataLayerSettings = (mapType: MapType): Partial<MapDataL
offsetX: 0,
offsetY: -1
},
click: {
type: WidgetActionType.doNothing
},
edit: {
enabledActions: [],
snappable: false

1
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/action-settings-button.component.html

@ -16,6 +16,7 @@
-->
<button #matButton [disabled]="disabled"
type="button"
class="tb-action-settings-button"
mat-stroked-button color="primary"
(click)="openActionSettingsPopup($event, matButton)">

12
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.html

@ -252,6 +252,18 @@
formControlName="tooltip">
</tb-data-layer-pattern-settings>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title" translate>widgets.maps.data-layer.behavior</div>
<div class="tb-form-row">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{'widgets.maps.data-layer.on-click-hint' | translate}}" translate>widgets.maps.data-layer.on-click</div>
<tb-widget-action-settings class="flex-1"
panelTitle="{{ 'widgets.maps.data-layer.on-click' | translate }}"
[callbacks]="context.callbacks"
[widgetType]="widgetType"
formControlName="click">
</tb-widget-action-settings>
</div>
</div>
<div class="tb-form-panel">
<div class="tb-form-panel-title">{{ 'widgets.maps.data-layer.groups' | translate }}</div>
<tb-string-items-list class="tb-inline-chips"

1
ui-ngx/src/app/modules/home/components/widget/lib/settings/common/map/map-data-layer-dialog.component.ts

@ -117,6 +117,7 @@ export class MapDataLayerDialogComponent extends DialogComponent<MapDataLayerDia
additionalDataKeys: [this.settings.additionalDataKeys, []],
label: [this.settings.label, []],
tooltip: [this.settings.tooltip, []],
click: [this.settings.click, []],
groups: [this.settings.groups, []],
edit: this.fb.group({
enabledActions: [this.settings.edit?.enabledActions, []],

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -7641,6 +7641,9 @@
"add-datasource": "Add datasource",
"no-datasources": "No datasources configured",
"remove-datasource": "Remove datasource",
"behavior": "Behavior",
"on-click": "On click",
"on-click-hint": "Action invoked when user clicks on the map item.",
"groups": "Groups",
"color": "Color",
"fill-color": "Fill color",

Loading…
Cancel
Save