@vcmap/ui 6.1.0-rc.2 → 6.1.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/base.config.json +6 -0
- package/config/clipping.config.json +384 -0
- package/config/cluster.config.json +106 -0
- package/config/concepts-show-case.config.json +4 -0
- package/config/projects.config.json +5 -2
- package/dist/assets/{cesium-57fbd309.js → cesium-bfb31a03.js} +438 -432
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core-fd079400.js → core-28960288.js} +4913 -4516
- package/dist/assets/core.js +1 -1
- package/dist/assets/{ol-50dfef96.js → ol-338a87a3.js} +23518 -22404
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui-4ae4c67a.css +1 -0
- package/dist/assets/{ui-5135917c.js → ui-4ae4c67a.js} +13456 -12758
- package/dist/assets/ui.js +1 -1
- package/dist/assets/vue.js +1 -1
- package/dist/assets/{vuetify-f02b7bb9.css → vuetify-1f5b5c90.css} +2 -2
- package/dist/assets/{vuetify-f02b7bb9.js → vuetify-1f5b5c90.js} +8024 -7634
- package/dist/assets/vuetify.js +1 -1
- package/index.d.ts +38 -19
- package/index.js +35 -6
- package/lib/olLib.js +25 -3
- package/package.json +6 -6
- package/plugins/@vcmap-show-case/callback-tester/README.md +3 -0
- package/plugins/@vcmap-show-case/callback-tester/package.json +5 -0
- package/plugins/@vcmap-show-case/callback-tester/src/CallbackTester.vue +62 -0
- package/plugins/@vcmap-show-case/callback-tester/src/index.js +48 -0
- package/plugins/@vcmap-show-case/form-inputs-example/src/FormInputsExample.vue +1 -0
- package/src/actions/actionHelper.d.ts +1 -0
- package/src/actions/actionHelper.js +70 -19
- package/src/application/VcsApp.vue +83 -50
- package/src/application/VcsApp.vue.d.ts +24 -2
- package/src/application/VcsContainer.vue.d.ts +8 -0
- package/src/application/VcsObliqueFooter.vue +9 -3
- package/src/application/VcsSplashScreen.vue +37 -0
- package/src/application/VcsSplashScreen.vue.d.ts +6 -0
- package/src/application/positionDisplayInteraction.js +1 -1
- package/src/callback/activateClippingPolygonCallback.d.ts +29 -0
- package/src/callback/activateClippingPolygonCallback.js +54 -0
- package/src/callback/closeSplashScreenCallback.d.ts +8 -0
- package/src/callback/closeSplashScreenCallback.js +33 -0
- package/src/callback/deactivateClippingPolygonCallback.d.ts +29 -0
- package/src/callback/deactivateClippingPolygonCallback.js +54 -0
- package/src/callback/openSplashScreenCallback.d.ts +8 -0
- package/src/callback/openSplashScreenCallback.js +35 -0
- package/src/callback/toggleNavbarButtonCallback.d.ts +36 -0
- package/src/callback/toggleNavbarButtonCallback.js +62 -0
- package/src/components/form-inputs-controls/VcsSelect.vue +1 -1
- package/src/components/form-inputs-controls/VcsTextArea.vue +12 -7
- package/src/components/form-output/markdownHelper.d.ts +0 -25
- package/src/components/form-output/markdownHelper.js +1 -386
- package/src/components/lists/VcsGroupedList.vue +178 -0
- package/src/components/lists/VcsGroupedList.vue.d.ts +17 -0
- package/src/components/lists/VcsList.vue +142 -396
- package/src/components/lists/VcsList.vue.d.ts +38 -168
- package/src/components/lists/VcsTreeview.vue +11 -12
- package/src/components/lists/listHelper.d.ts +87 -0
- package/src/components/lists/listHelper.js +348 -0
- package/src/components/section/VcsFormSection.vue +7 -2
- package/src/components/section/VcsFormSection.vue.d.ts +9 -0
- package/src/components/vector-properties/VcsVectorPropertiesComponent.vue.d.ts +1 -1
- package/src/contentTree/LayerTree.vue +2 -1
- package/src/contentTree/LayerTree.vue.d.ts +2 -0
- package/src/contentTree/contentTreeCollection.d.ts +1 -0
- package/src/contentTree/contentTreeCollection.js +7 -3
- package/src/contentTree/contentTreeItem.js +4 -2
- package/src/contentTree/groupContentTreeItem.js +5 -3
- package/src/featureInfo/ClusterFeatureComponent.vue +58 -0
- package/src/featureInfo/ClusterFeatureComponent.vue.d.ts +6 -0
- package/src/featureInfo/abstractFeatureInfoView.js +1 -2
- package/src/featureInfo/featureInfo.d.ts +87 -1
- package/src/featureInfo/featureInfo.js +350 -34
- package/src/featureInfo/featureInfoInteraction.js +18 -3
- package/src/featureInfo/iframeFeatureInfoView.js +1 -1
- package/src/featureInfo/markdownBalloonFeatureInfoView.js +2 -4
- package/src/featureInfo/markdownFeatureInfoView.js +1 -1
- package/src/i18n/de.d.ts +17 -4
- package/src/i18n/de.js +7 -0
- package/src/i18n/en.d.ts +17 -4
- package/src/i18n/en.js +7 -0
- package/src/legend/legendHelper.d.ts +1 -1
- package/src/legend/legendHelper.js +52 -9
- package/src/localStorage.d.ts +21 -0
- package/src/localStorage.js +51 -0
- package/src/manager/collectionManager/CollectionComponent.vue +1 -1
- package/src/manager/collectionManager/CollectionComponentContent.vue +2 -3
- package/src/manager/collectionManager/CollectionComponentList.vue +2 -3
- package/src/manager/collectionManager/CollectionComponentStandalone.vue +1 -1
- package/src/manager/navbarManager.js +9 -4
- package/src/manager/toolbox/ToolboxManagerComponent.vue +10 -8
- package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +11 -0
- package/src/manager/window/windowHelper.d.ts +7 -3
- package/src/manager/window/windowHelper.js +30 -10
- package/src/navigation/overviewMap.d.ts +1 -0
- package/src/navigation/overviewMap.js +4 -3
- package/src/pluginHelper.d.ts +7 -0
- package/src/pluginHelper.js +18 -4
- package/src/search/ResultItem.vue.d.ts +1 -1
- package/src/search/search.js +1 -1
- package/src/state.d.ts +4 -2
- package/src/state.js +54 -31
- package/src/uiConfig.d.ts +27 -0
- package/src/uiConfig.js +16 -1
- package/src/vcsUiApp.js +7 -11
- package/dist/assets/ui-5135917c.css +0 -1
- /package/dist/assets/{vue-c3c55d88.js → vue-b5c1e81a.js} +0 -0
@@ -12,6 +12,12 @@ import {
|
|
12
12
|
VectorStyleItem,
|
13
13
|
markVolatile,
|
14
14
|
maxZIndex,
|
15
|
+
vectorClusterGroupName,
|
16
|
+
hidden,
|
17
|
+
isProvidedClusterFeature,
|
18
|
+
alreadyTransformedToImage,
|
19
|
+
ObliqueMap,
|
20
|
+
originalFeatureSymbol,
|
15
21
|
} from '@vcmap/core';
|
16
22
|
import { getLogger as getLoggerByName } from '@vcsuite/logger';
|
17
23
|
import {
|
@@ -24,6 +30,7 @@ import { Feature } from 'ol';
|
|
24
30
|
import { check, maybe, oneOf } from '@vcsuite/check';
|
25
31
|
|
26
32
|
import { reactive } from 'vue';
|
33
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
27
34
|
import { vcsAppSymbol } from '../pluginHelper.js';
|
28
35
|
import FeatureInfoInteraction from './featureInfoInteraction.js';
|
29
36
|
import AbstractFeatureInfoView from './abstractFeatureInfoView.js';
|
@@ -36,6 +43,7 @@ import { getDefaultPrimaryColor } from '../vuePlugins/vuetify.js';
|
|
36
43
|
import { ToolboxType } from '../manager/toolbox/toolboxManager.js';
|
37
44
|
import MarkdownBalloonFeatureInfoView from './markdownBalloonFeatureInfoView.js';
|
38
45
|
import IframeWmsFeatureInfoView from './iframeWmsFeatureInfoView.js';
|
46
|
+
import ClusterFeatureComponent from './ClusterFeatureComponent.vue';
|
39
47
|
|
40
48
|
/** @typedef {import("ol").Feature|import("@vcmap-cesium/engine").Cesium3DTileFeature|import("@vcmap-cesium/engine").Cesium3DTilePointFeature|import("@vcmap-cesium/engine").Entity} FeatureType */
|
41
49
|
|
@@ -64,6 +72,43 @@ export const featureInfoClassRegistry = new ClassRegistry();
|
|
64
72
|
*/
|
65
73
|
export const featureInfoViewSymbol = Symbol('featureInfoView');
|
66
74
|
|
75
|
+
/**
|
76
|
+
*
|
77
|
+
* @param {import("ol/style/Style.js").default?} style
|
78
|
+
* @param {import("@vcmap-cesium/engine").Color} fillColor
|
79
|
+
* @returns {import("ol/style/Style.js").default}
|
80
|
+
*/
|
81
|
+
export function getHighlightStyleFromStyle(style, fillColor) {
|
82
|
+
const highlightStyle =
|
83
|
+
style?.clone?.() ??
|
84
|
+
new VectorStyleItem(getDefaultVectorStyleItemOptions()).style;
|
85
|
+
if (highlightStyle.getText()) {
|
86
|
+
if (highlightStyle.getText().getFill()) {
|
87
|
+
highlightStyle.getText().getFill().setColor(fillColor.toCssColorString());
|
88
|
+
}
|
89
|
+
highlightStyle
|
90
|
+
.getText()
|
91
|
+
.setScale((highlightStyle.getText().getScale() ?? 1) * 2);
|
92
|
+
}
|
93
|
+
if (highlightStyle.getImage()) {
|
94
|
+
highlightStyle
|
95
|
+
.getImage()
|
96
|
+
.setScale(highlightStyle.getImage().getScale() * 2);
|
97
|
+
}
|
98
|
+
if (highlightStyle.getStroke()) {
|
99
|
+
highlightStyle.getStroke().setColor(fillColor.toCssColorString());
|
100
|
+
highlightStyle
|
101
|
+
.getStroke()
|
102
|
+
.setWidth(highlightStyle.getStroke().getWidth() * 2);
|
103
|
+
}
|
104
|
+
if (highlightStyle.getFill()) {
|
105
|
+
const color = fillColor.toBytes();
|
106
|
+
color[3] /= 255;
|
107
|
+
highlightStyle.getFill().setColor(color);
|
108
|
+
}
|
109
|
+
return highlightStyle;
|
110
|
+
}
|
111
|
+
|
67
112
|
/**
|
68
113
|
* @param {FeatureType} feature
|
69
114
|
* @param {import("@vcmap/core").Layer} layer
|
@@ -71,7 +116,7 @@ export const featureInfoViewSymbol = Symbol('featureInfoView');
|
|
71
116
|
* @returns {import("ol/style/Style.js").default|import("@vcmap/core").VectorStyleItem}
|
72
117
|
*/
|
73
118
|
export function getHighlightStyle(feature, layer, defaultFillColor) {
|
74
|
-
if (layer
|
119
|
+
if (layer?.highlightStyle) {
|
75
120
|
return layer.highlightStyle;
|
76
121
|
}
|
77
122
|
|
@@ -81,32 +126,32 @@ export function getHighlightStyle(feature, layer, defaultFillColor) {
|
|
81
126
|
if (typeof style === 'function') {
|
82
127
|
style = style(feature, 1);
|
83
128
|
}
|
84
|
-
style
|
85
|
-
style?.clone?.() ??
|
86
|
-
new VectorStyleItem(getDefaultVectorStyleItemOptions()).style;
|
87
|
-
if (style.getText()) {
|
88
|
-
if (style.getText().getFill()) {
|
89
|
-
style.getText().getFill().setColor(fillColor.toCssColorString());
|
90
|
-
}
|
91
|
-
style.getText().setScale((style.getText().getScale() ?? 1) * 2);
|
92
|
-
}
|
93
|
-
if (style.getImage()) {
|
94
|
-
style.getImage().setScale(style.getImage().getScale() * 2);
|
95
|
-
}
|
96
|
-
if (style.getStroke()) {
|
97
|
-
style.getStroke().setColor(fillColor.toCssColorString());
|
98
|
-
style.getStroke().setWidth(style.getStroke().getWidth() * 2);
|
99
|
-
}
|
100
|
-
if (style.getFill()) {
|
101
|
-
const color = fillColor.toBytes();
|
102
|
-
color[3] /= 255;
|
103
|
-
style.getFill().setColor(color);
|
104
|
-
}
|
105
|
-
return style;
|
129
|
+
return getHighlightStyleFromStyle(style, fillColor);
|
106
130
|
}
|
107
131
|
return fromCesiumColor(fillColor);
|
108
132
|
}
|
109
133
|
|
134
|
+
/**
|
135
|
+
* @param {import("ol").Feature} clusterFeature
|
136
|
+
* @param {import("@vcmap/core").VectorClusterGroup} clusterGroup
|
137
|
+
* @param {import("ol/style/Style.js").default} clusterStyle
|
138
|
+
* @param {string} defaultFillColor
|
139
|
+
* @returns {import("ol/style/Style.js").default}
|
140
|
+
*/
|
141
|
+
export function getClusterHighlightStyle(
|
142
|
+
clusterFeature,
|
143
|
+
clusterGroup,
|
144
|
+
clusterStyle,
|
145
|
+
defaultFillColor,
|
146
|
+
) {
|
147
|
+
if (clusterGroup?.highlightStyle) {
|
148
|
+
return clusterGroup.getHighlightStyleForFeature(clusterFeature);
|
149
|
+
}
|
150
|
+
|
151
|
+
const fillColor = Color.fromCssColorString(defaultFillColor).withAlpha(0.8);
|
152
|
+
return getHighlightStyleFromStyle(clusterStyle, fillColor);
|
153
|
+
}
|
154
|
+
|
110
155
|
/**
|
111
156
|
* @param {import("../vcsUiApp.js").default} app
|
112
157
|
* @returns {FeatureInfoSession}
|
@@ -158,7 +203,7 @@ function setupFeatureInfoTool(app) {
|
|
158
203
|
session.stopped.addEventListener(() => {
|
159
204
|
action.active = false;
|
160
205
|
session = null;
|
161
|
-
app.featureInfo.
|
206
|
+
app.featureInfo.clearSelection();
|
162
207
|
action.title = 'featureInfo.activateToolTitle';
|
163
208
|
});
|
164
209
|
this.active = true;
|
@@ -266,7 +311,12 @@ class FeatureInfo extends Collection {
|
|
266
311
|
*/
|
267
312
|
this._windowId = null;
|
268
313
|
/**
|
269
|
-
* @type {
|
314
|
+
* @type {string|null}
|
315
|
+
* @private
|
316
|
+
*/
|
317
|
+
this._clusterWindowId = null;
|
318
|
+
/**
|
319
|
+
* @type {VcsEvent<FeatureType|null>}
|
270
320
|
* @private
|
271
321
|
*/
|
272
322
|
this._featureChanged = new VcsEvent();
|
@@ -280,6 +330,21 @@ class FeatureInfo extends Collection {
|
|
280
330
|
* @private
|
281
331
|
*/
|
282
332
|
this._selectedFeatureId = null;
|
333
|
+
/**
|
334
|
+
* @type {VcsEvent<import("ol").Feature|null>}
|
335
|
+
* @private
|
336
|
+
*/
|
337
|
+
this._clusterFeatureChanged = new VcsEvent();
|
338
|
+
/**
|
339
|
+
* @type {import("ol").Feature|null}
|
340
|
+
* @private
|
341
|
+
*/
|
342
|
+
this._selectedClusterFeature = null;
|
343
|
+
/**
|
344
|
+
* @type {string|null}
|
345
|
+
* @private
|
346
|
+
*/
|
347
|
+
this._selectedClusterFeatureId = null;
|
283
348
|
/**
|
284
349
|
* @type {Array<function():void>}
|
285
350
|
* @private
|
@@ -305,18 +370,39 @@ class FeatureInfo extends Collection {
|
|
305
370
|
) {
|
306
371
|
this._app.windowManager.remove(this._windowId);
|
307
372
|
}
|
373
|
+
|
374
|
+
if (
|
375
|
+
this._clusterWindowId &&
|
376
|
+
this._app.windowManager.has(this._clusterWindowId)
|
377
|
+
) {
|
378
|
+
const { props } = this._app.windowManager.get(this._clusterWindowId);
|
379
|
+
if (props.items.some((item) => item.group === layer.name)) {
|
380
|
+
props.items = props.items.filter(
|
381
|
+
(item) => item.group !== layer.name,
|
382
|
+
);
|
383
|
+
props.groups = props.groups.filter(
|
384
|
+
(group) => group.name !== layer.name,
|
385
|
+
);
|
386
|
+
if (props.items.length === 0) {
|
387
|
+
this._app.windowManager.remove(this._clusterWindowId);
|
388
|
+
}
|
389
|
+
}
|
390
|
+
}
|
308
391
|
}),
|
309
392
|
this._app.windowManager.removed.addEventListener(({ id }) => {
|
310
393
|
if (id === this._windowId) {
|
311
|
-
this.
|
394
|
+
this.clearFeature();
|
395
|
+
}
|
396
|
+
if (id === this._clusterWindowId) {
|
397
|
+
this.clearCluster();
|
312
398
|
}
|
313
399
|
}),
|
314
400
|
this._app.moduleAdded.addEventListener(() => {
|
315
|
-
this.
|
401
|
+
this.clearSelection();
|
316
402
|
this._destroyFeatureInfoTool();
|
317
403
|
this._destroyFeatureInfoTool = setupFeatureInfoTool(this._app);
|
318
404
|
}),
|
319
|
-
this._app.moduleRemoved.addEventListener(() => this.
|
405
|
+
this._app.moduleRemoved.addEventListener(() => this.clearSelection()),
|
320
406
|
];
|
321
407
|
/**
|
322
408
|
* A vector layer to render provided features on
|
@@ -332,6 +418,8 @@ class FeatureInfo extends Collection {
|
|
332
418
|
}
|
333
419
|
|
334
420
|
/**
|
421
|
+
* Emitted whenever a feature is selected or cleared.
|
422
|
+
* Does not reflect cluster feature changes!
|
335
423
|
* @type {VcsEvent<null|FeatureType>}
|
336
424
|
*/
|
337
425
|
get featureChanged() {
|
@@ -352,6 +440,28 @@ class FeatureInfo extends Collection {
|
|
352
440
|
return this._selectedFeatureId;
|
353
441
|
}
|
354
442
|
|
443
|
+
/**
|
444
|
+
* Emitted whenever a cluster feature is selected or cleared.
|
445
|
+
* @type {VcsEvent<null|import("ol").Feature>}
|
446
|
+
*/
|
447
|
+
get clusterFeatureChanged() {
|
448
|
+
return this._clusterFeatureChanged;
|
449
|
+
}
|
450
|
+
|
451
|
+
/**
|
452
|
+
* @type {null|import("ol").Feature}
|
453
|
+
*/
|
454
|
+
get selectedClusterFeature() {
|
455
|
+
return this._selectedClusterFeature;
|
456
|
+
}
|
457
|
+
|
458
|
+
/**
|
459
|
+
* @type {null|string}
|
460
|
+
*/
|
461
|
+
get selectedClusterFeatureId() {
|
462
|
+
return this._selectedClusterFeatureId;
|
463
|
+
}
|
464
|
+
|
355
465
|
/**
|
356
466
|
* The window id of the current features FeatureInfoView window
|
357
467
|
* @type {string|null}
|
@@ -360,6 +470,14 @@ class FeatureInfo extends Collection {
|
|
360
470
|
return this._windowId;
|
361
471
|
}
|
362
472
|
|
473
|
+
/**
|
474
|
+
* The window id of the current cluster feature window
|
475
|
+
* @type {string|null}
|
476
|
+
*/
|
477
|
+
get clusterWindowId() {
|
478
|
+
return this._clusterWindowId;
|
479
|
+
}
|
480
|
+
|
363
481
|
/**
|
364
482
|
* @private
|
365
483
|
*/
|
@@ -426,10 +544,22 @@ class FeatureInfo extends Collection {
|
|
426
544
|
|
427
545
|
if (usedFeatureInfoView && layer) {
|
428
546
|
this._clearInternal();
|
547
|
+
if (
|
548
|
+
this._selectedClusterFeature &&
|
549
|
+
!this._selectedClusterFeature
|
550
|
+
.get('features')
|
551
|
+
.map((f) => f[originalFeatureSymbol] ?? f)
|
552
|
+
.includes(feature)
|
553
|
+
) {
|
554
|
+
this.clearCluster();
|
555
|
+
}
|
429
556
|
if (feature[isProvidedFeature]) {
|
430
557
|
this._ensureScratchLayer();
|
431
|
-
|
432
|
-
const
|
558
|
+
// we need to clone the feature to avoid changing vcsLayerNameSymbol on the original feature
|
559
|
+
const clonedFeature = feature.clone();
|
560
|
+
clonedFeature.setId(feature.getId());
|
561
|
+
this._scratchLayer.addFeatures([clonedFeature]);
|
562
|
+
const featureId = clonedFeature.getId(); // make sure to grab ID after adding it to the layer
|
433
563
|
this._scratchLayer.featureVisibility.highlight({
|
434
564
|
[featureId]: getHighlightStyle(
|
435
565
|
feature,
|
@@ -440,6 +570,29 @@ class FeatureInfo extends Collection {
|
|
440
570
|
});
|
441
571
|
this._clearHighlightingCb = () =>
|
442
572
|
this._scratchLayer.featureVisibility.unHighlight([featureId]);
|
573
|
+
} else if (layer.vectorClusterGroup) {
|
574
|
+
this._ensureScratchLayer();
|
575
|
+
const clone = feature.clone();
|
576
|
+
const featureId = feature.getId();
|
577
|
+
this._scratchLayer.vectorProperties.setValuesForFeatures(
|
578
|
+
layer.vectorProperties.getValuesForFeatures([clone]),
|
579
|
+
[clone],
|
580
|
+
);
|
581
|
+
const eyeOffset = clone.get('olcs_eyeOffset') ?? [0, 0, 0];
|
582
|
+
eyeOffset[2] -= 10;
|
583
|
+
clone.set('olcs_eyeOffset', eyeOffset);
|
584
|
+
clone.setId(featureId);
|
585
|
+
this._scratchLayer.addFeatures([clone]);
|
586
|
+
this._scratchLayer.featureVisibility.highlight({
|
587
|
+
[featureId]: getHighlightStyle(
|
588
|
+
feature,
|
589
|
+
layer,
|
590
|
+
this._app.uiConfig.config.primaryColor ??
|
591
|
+
getDefaultPrimaryColor(this._app),
|
592
|
+
),
|
593
|
+
});
|
594
|
+
this._clearHighlightingCb = () =>
|
595
|
+
this._scratchLayer.featureVisibility.unHighlight([clone]);
|
443
596
|
} else if (layer.featureVisibility) {
|
444
597
|
const featureId = feature.getId();
|
445
598
|
layer.featureVisibility.highlight({
|
@@ -470,10 +623,121 @@ class FeatureInfo extends Collection {
|
|
470
623
|
this._selectedFeatureId = feature.getId();
|
471
624
|
this._featureChanged.raiseEvent(this._selectedFeature);
|
472
625
|
} else {
|
473
|
-
this.
|
626
|
+
this.clearSelection();
|
474
627
|
}
|
475
628
|
}
|
476
629
|
|
630
|
+
/**
|
631
|
+
* Selecting a cluster feature opens a window listing the features belonging to the cluster feature.
|
632
|
+
* To be listed the feature must meet the following criteria: a) the feature must be part of a layer, b) said layer must be managed in
|
633
|
+
* the same VcsApp as provided to the FeatureInfo on construction. if not providing a feature info view, then c) said layer must have a featureInfo property set on
|
634
|
+
* its properties bag and d) said featureInfo property must provide the name of a FeatureInfoView present on this FeatureInfos
|
635
|
+
* collection.
|
636
|
+
* The cluster feature will be cloned, highlighted and added on an internal scratch layer to ensure availability until deselection.
|
637
|
+
* The original cluster feature will be hidden until deselection.
|
638
|
+
* @param {import("ol").Feature} clusterFeature
|
639
|
+
* @returns {Promise<void>}
|
640
|
+
*/
|
641
|
+
async selectClusterFeature(clusterFeature) {
|
642
|
+
this.clearFeature();
|
643
|
+
this._clearClusterInternal();
|
644
|
+
const id = `cluster-at-${clusterFeature.getGeometry().getCoordinates().join('-')}`;
|
645
|
+
|
646
|
+
this._ensureScratchLayer();
|
647
|
+
const feature = clusterFeature.clone();
|
648
|
+
feature.setId(id);
|
649
|
+
|
650
|
+
clusterFeature[hidden] = true;
|
651
|
+
clusterFeature.changed();
|
652
|
+
|
653
|
+
const fillColor =
|
654
|
+
this._app.uiConfig.config.primaryColor ??
|
655
|
+
getDefaultPrimaryColor(this._app);
|
656
|
+
|
657
|
+
if (clusterFeature[vectorClusterGroupName]) {
|
658
|
+
const clusterGroup = this._app.vectorClusterGroups.getByKey(
|
659
|
+
clusterFeature[vectorClusterGroupName],
|
660
|
+
);
|
661
|
+
this._scratchLayer.vectorProperties.setValuesForFeatures(
|
662
|
+
clusterGroup.vectorProperties.getValuesForFeatures([feature]),
|
663
|
+
[feature],
|
664
|
+
);
|
665
|
+
const clusterStyle = clusterGroup.style.createStyleFunction((layerName) =>
|
666
|
+
this._app.layers.getByKey(layerName),
|
667
|
+
)(clusterFeature, 1);
|
668
|
+
const highlightStyle = getClusterHighlightStyle(
|
669
|
+
clusterFeature,
|
670
|
+
clusterGroup,
|
671
|
+
clusterStyle,
|
672
|
+
fillColor,
|
673
|
+
);
|
674
|
+
feature.setStyle(highlightStyle);
|
675
|
+
} else if (clusterFeature[isProvidedClusterFeature]) {
|
676
|
+
feature.setStyle(
|
677
|
+
fromCesiumColor(Color.fromCssColorString(fillColor)).style,
|
678
|
+
);
|
679
|
+
}
|
680
|
+
|
681
|
+
if (this._app.maps.activeMap instanceof ObliqueMap) {
|
682
|
+
feature.getGeometry()[alreadyTransformedToImage] = true;
|
683
|
+
}
|
684
|
+
this._scratchLayer.addFeatures([feature]);
|
685
|
+
|
686
|
+
const features = clusterFeature.get('features');
|
687
|
+
const groups = {};
|
688
|
+
const items = features.map((f) => {
|
689
|
+
const oFeature = f[originalFeatureSymbol] ?? f;
|
690
|
+
const listItem = reactive({
|
691
|
+
name: oFeature.getId(),
|
692
|
+
title:
|
693
|
+
oFeature.getAttributes()?.title ||
|
694
|
+
oFeature.getAttributes()?.name ||
|
695
|
+
oFeature.getId(),
|
696
|
+
disabled: !this._getFeatureInfoViewForFeature(oFeature),
|
697
|
+
selectionChanged: (value) => {
|
698
|
+
if (value) {
|
699
|
+
this.selectFeature(oFeature);
|
700
|
+
} else {
|
701
|
+
this.clearFeature();
|
702
|
+
}
|
703
|
+
},
|
704
|
+
});
|
705
|
+
const layerName = oFeature[vcsLayerName];
|
706
|
+
if (layerName) {
|
707
|
+
if (!groups[layerName]) {
|
708
|
+
const title = this._app.layers.getByKey(layerName)?.properties?.title;
|
709
|
+
groups[layerName] = {
|
710
|
+
name: layerName,
|
711
|
+
title: title || layerName,
|
712
|
+
};
|
713
|
+
}
|
714
|
+
listItem.group = layerName;
|
715
|
+
}
|
716
|
+
return listItem;
|
717
|
+
});
|
718
|
+
|
719
|
+
this._clusterWindowId = id;
|
720
|
+
this._app.windowManager.add(
|
721
|
+
{
|
722
|
+
id,
|
723
|
+
component: ClusterFeatureComponent,
|
724
|
+
props: reactive({
|
725
|
+
items,
|
726
|
+
groups: Object.values(groups),
|
727
|
+
}),
|
728
|
+
state: {
|
729
|
+
headerTitle: 'featureInfo.cluster.headerTitle',
|
730
|
+
},
|
731
|
+
slot: WindowSlot.DYNAMIC_LEFT,
|
732
|
+
},
|
733
|
+
vcsAppSymbol,
|
734
|
+
);
|
735
|
+
|
736
|
+
this._selectedClusterFeature = clusterFeature;
|
737
|
+
this._selectedClusterFeatureId = id;
|
738
|
+
this._clusterFeatureChanged.raiseEvent(this._selectedClusterFeature);
|
739
|
+
}
|
740
|
+
|
477
741
|
/**
|
478
742
|
* Clears the current feature. remove window, highlighting and provided feature.
|
479
743
|
* @private
|
@@ -487,16 +751,35 @@ class FeatureInfo extends Collection {
|
|
487
751
|
this._app.windowManager.remove(this._windowId);
|
488
752
|
this._windowId = null;
|
489
753
|
}
|
754
|
+
if (this._scratchLayer && this._selectedFeatureId) {
|
755
|
+
this._scratchLayer.removeFeaturesById([this._selectedFeatureId]);
|
756
|
+
}
|
757
|
+
}
|
490
758
|
|
491
|
-
|
492
|
-
|
759
|
+
/**
|
760
|
+
* Clears the current cluster feature. remove window, highlighting and provided cluster feature.
|
761
|
+
* @private
|
762
|
+
*/
|
763
|
+
_clearClusterInternal() {
|
764
|
+
if (this._clusterWindowId) {
|
765
|
+
this._app.windowManager.remove(this._clusterWindowId);
|
766
|
+
this._clusterWindowId = null;
|
767
|
+
}
|
768
|
+
|
769
|
+
if (this._selectedClusterFeature) {
|
770
|
+
this._selectedClusterFeature[hidden] = false;
|
771
|
+
this._selectedClusterFeature.changed();
|
772
|
+
|
773
|
+
if (this._scratchLayer) {
|
774
|
+
this._scratchLayer.removeFeaturesById([this._selectedClusterFeatureId]);
|
775
|
+
}
|
493
776
|
}
|
494
777
|
}
|
495
778
|
|
496
779
|
/**
|
497
780
|
* Deselecting feature clears highlighting and closes FeatureInfoView. fires feature changed with null
|
498
781
|
*/
|
499
|
-
|
782
|
+
clearFeature() {
|
500
783
|
this._clearInternal();
|
501
784
|
if (this._selectedFeature) {
|
502
785
|
this._selectedFeature = null;
|
@@ -505,12 +788,45 @@ class FeatureInfo extends Collection {
|
|
505
788
|
}
|
506
789
|
}
|
507
790
|
|
791
|
+
/**
|
792
|
+
* Deselecting and removing cluster feature. Closing cluster window and fires cluster feature changed with null
|
793
|
+
*/
|
794
|
+
clearCluster() {
|
795
|
+
this._clearClusterInternal();
|
796
|
+
if (this._selectedClusterFeature) {
|
797
|
+
this._selectedClusterFeature[hidden] = false;
|
798
|
+
this._selectedClusterFeature = null;
|
799
|
+
this._clusterFeatureChanged.raiseEvent(this._selectedClusterFeature);
|
800
|
+
}
|
801
|
+
}
|
802
|
+
|
803
|
+
/**
|
804
|
+
* @deprecated
|
805
|
+
*/
|
806
|
+
clear() {
|
807
|
+
getLogger().deprecate(
|
808
|
+
'clear',
|
809
|
+
'Use clearSelection instead. Clear will clear the FeatureInfo collection removing all registered FeatureInfoViews in feature.',
|
810
|
+
);
|
811
|
+
this.clearSelection();
|
812
|
+
}
|
813
|
+
|
814
|
+
/**
|
815
|
+
* Clears selection by deselecting current feature and cluster and closing all related windows.
|
816
|
+
* Fires feature changed and cluster feature changed events with null.
|
817
|
+
*/
|
818
|
+
clearSelection() {
|
819
|
+
this.clearFeature();
|
820
|
+
this.clearCluster();
|
821
|
+
}
|
822
|
+
|
508
823
|
/**
|
509
824
|
* Destroys the feature info and all its events & listeners
|
510
825
|
*/
|
511
826
|
destroy() {
|
512
827
|
super.destroy();
|
513
828
|
this._clearInternal();
|
829
|
+
this._clearClusterInternal();
|
514
830
|
this._featureChanged.destroy();
|
515
831
|
this._destroyFeatureInfoTool();
|
516
832
|
if (this._scratchLayer) {
|
@@ -2,6 +2,8 @@ import {
|
|
2
2
|
AbstractInteraction,
|
3
3
|
EventType,
|
4
4
|
ModificationKeyType,
|
5
|
+
vectorClusterGroupName,
|
6
|
+
isProvidedClusterFeature,
|
5
7
|
} from '@vcmap/core';
|
6
8
|
|
7
9
|
/**
|
@@ -28,9 +30,22 @@ class FeatureInfoInteraction extends AbstractInteraction {
|
|
28
30
|
*/
|
29
31
|
async pipe(event) {
|
30
32
|
if (event.feature) {
|
31
|
-
|
33
|
+
const featureId = event.feature.getId();
|
34
|
+
const isClusterFeature = !!(
|
35
|
+
event.feature[vectorClusterGroupName] ||
|
36
|
+
event.feature[isProvidedClusterFeature]
|
37
|
+
);
|
38
|
+
if (isClusterFeature) {
|
39
|
+
if (
|
40
|
+
!this._featureInfo.selectedClusterFeature ||
|
41
|
+
featureId !== this._featureInfo.selectedClusterFeatureId
|
42
|
+
) {
|
43
|
+
event.stopPropagation = true;
|
44
|
+
await this._featureInfo.selectClusterFeature(event.feature);
|
45
|
+
}
|
46
|
+
} else if (
|
32
47
|
!this._featureInfo.selectedFeature ||
|
33
|
-
|
48
|
+
featureId !== this._featureInfo.selectedFeatureId
|
34
49
|
) {
|
35
50
|
event.stopPropagation = true;
|
36
51
|
await this._featureInfo.selectFeature(event.feature, event.position, [
|
@@ -39,7 +54,7 @@ class FeatureInfoInteraction extends AbstractInteraction {
|
|
39
54
|
]);
|
40
55
|
}
|
41
56
|
} else {
|
42
|
-
await this._featureInfo.
|
57
|
+
await this._featureInfo.clearSelection();
|
43
58
|
}
|
44
59
|
return event;
|
45
60
|
}
|
@@ -1,7 +1,5 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
renderTemplate,
|
4
|
-
} from '../components/form-output/markdownHelper.js';
|
1
|
+
import { renderTemplate } from '@vcmap/core';
|
2
|
+
import { parseAndSanitizeMarkdown } from '../components/form-output/markdownHelper.js';
|
5
3
|
import BalloonFeatureInfoView from './balloonFeatureInfoView.js';
|
6
4
|
import MarkdownBalloonComponent from './MarkdownBalloonComponent.vue';
|
7
5
|
|
package/src/i18n/de.d.ts
CHANGED
@@ -73,6 +73,11 @@ declare namespace messages {
|
|
73
73
|
counter: string;
|
74
74
|
counterSize: string;
|
75
75
|
};
|
76
|
+
fileUpload: {
|
77
|
+
title: string;
|
78
|
+
divider: string;
|
79
|
+
browse: string;
|
80
|
+
};
|
76
81
|
timePicker: {
|
77
82
|
am: string;
|
78
83
|
pm: string;
|
@@ -278,6 +283,7 @@ declare namespace messages {
|
|
278
283
|
export { name_2 as name };
|
279
284
|
export let checkBoxText: string;
|
280
285
|
export let buttonTitle: string;
|
286
|
+
export let dontShowAgain: string;
|
281
287
|
}
|
282
288
|
export namespace customScreen {
|
283
289
|
let name_3: string;
|
@@ -457,14 +463,21 @@ declare namespace messages {
|
|
457
463
|
export namespace featureInfo {
|
458
464
|
let activateToolTitle: string;
|
459
465
|
let deactivateToolTitle: string;
|
466
|
+
namespace cluster {
|
467
|
+
export let headerTitle: string;
|
468
|
+
export let expand: string;
|
469
|
+
export let collapse: string;
|
470
|
+
let empty_2: string;
|
471
|
+
export { empty_2 as empty };
|
472
|
+
}
|
460
473
|
}
|
461
474
|
export namespace legend {
|
462
475
|
let title_17: string;
|
463
476
|
export { title_17 as title };
|
464
477
|
let tooltip_5: string;
|
465
478
|
export { tooltip_5 as tooltip };
|
466
|
-
let
|
467
|
-
export {
|
479
|
+
let empty_3: string;
|
480
|
+
export { empty_3 as empty };
|
468
481
|
export let openInNew: string;
|
469
482
|
export let defaultLabelText: string;
|
470
483
|
}
|
@@ -495,8 +508,8 @@ declare namespace messages {
|
|
495
508
|
export { title_21 as title };
|
496
509
|
let tooltip_7: string;
|
497
510
|
export { tooltip_7 as tooltip };
|
498
|
-
let
|
499
|
-
export {
|
511
|
+
let empty_4: string;
|
512
|
+
export { empty_4 as empty };
|
500
513
|
}
|
501
514
|
export namespace imprint {
|
502
515
|
let title_22: string;
|
package/src/i18n/de.js
CHANGED
@@ -172,6 +172,7 @@ const messages = {
|
|
172
172
|
checkBoxText:
|
173
173
|
'Bitte akzeptieren sie die [Bedingungen](https://vc.systems/) um Fortzufahren',
|
174
174
|
buttonTitle: 'Weiter',
|
175
|
+
dontShowAgain: 'Diese Nachricht nicht erneut anzeigen',
|
175
176
|
},
|
176
177
|
customScreen: {
|
177
178
|
name: 'Benutzerdefinierter Screen',
|
@@ -325,6 +326,12 @@ const messages = {
|
|
325
326
|
featureInfo: {
|
326
327
|
activateToolTitle: 'Informationen abfragen',
|
327
328
|
deactivateToolTitle: 'Informationen abfragen',
|
329
|
+
cluster: {
|
330
|
+
headerTitle: 'Gruppeninformationen',
|
331
|
+
expand: 'Informationsliste anzeigen',
|
332
|
+
collapse: 'Informationsliste minimieren',
|
333
|
+
empty: 'Keine Informationen verfügbar',
|
334
|
+
},
|
328
335
|
},
|
329
336
|
legend: {
|
330
337
|
title: 'Legende',
|