@vcmap/ui 5.0.0-rc.16 → 5.0.0-rc.18
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/build/buildHelpers.js +7 -1
- package/config/base.config.json +3 -45
- package/config/www.config.json +756 -132
- package/dist/assets/{cesium.430460.js → cesium.2f992f.js} +0 -0
- package/dist/assets/cesium.js +1 -1
- package/dist/assets/{core.5089ba.js → core.cb0408.js} +1700 -1718
- package/dist/assets/core.js +1 -1
- package/dist/assets/{index.854f8e2b.js → index.bccdf969.js} +1 -1
- package/dist/assets/{ol.9be53a.js → ol.5e3fd0.js} +0 -0
- package/dist/assets/ol.js +1 -1
- package/dist/assets/ui.08c48f.css +1 -0
- package/dist/assets/{ui.49010a.js → ui.08c48f.js} +6254 -5906
- package/dist/assets/ui.js +1 -1
- package/dist/assets/{vue.247c1c.js → vue.228ead.js} +0 -0
- package/dist/assets/vue.js +2 -2
- package/dist/assets/{vuetify.735e58.css → vuetify.0b5039.css} +0 -0
- package/dist/assets/{vuetify.735e58.js → vuetify.0b5039.js} +5 -2
- package/dist/assets/vuetify.js +2 -2
- package/dist/index.html +1 -1
- package/index.js +14 -3
- package/package.json +2 -2
- package/plugins/@vcmap/pluginExample/index.js +2 -1
- package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +7 -0
- package/plugins/buttonExamples/ButtonExamples.vue +18 -0
- package/plugins/categoryTest/Categories.vue +27 -13
- package/plugins/categoryTest/Category.vue +7 -1
- package/plugins/categoryTest/index.js +1 -1
- package/plugins/package.json +1 -1
- package/plugins/test/allIconsComponent.vue +3 -3
- package/plugins/test/index.js +9 -5
- package/plugins/test/testList.vue +4 -1
- package/plugins/test/toolbox-data.js +168 -111
- package/plugins/test/vcsContent.vue +1 -1
- package/plugins/test/windowManagerExample.vue +9 -7
- package/src/actions/actionHelper.js +13 -10
- package/src/application/VcsApp.vue +25 -26
- package/src/application/VcsNavbar.vue +1 -1
- package/src/components/buttons/VcsButton.vue +14 -3
- package/src/components/form-inputs-controls/VcsCheckbox.vue +1 -0
- package/src/components/form-inputs-controls/VcsFormSection.vue +14 -6
- package/src/components/lists/VcsActionList.vue +2 -0
- package/src/components/lists/VcsList.vue +4 -2
- package/src/contentTree/contentTreeCollection.js +9 -0
- package/src/contentTree/layerContentTreeItem.js +3 -3
- package/src/featureInfo/BalloonComponent.vue +5 -2
- package/src/featureInfo/balloonFeatureInfoView.js +2 -8
- package/src/featureInfo/balloonHelper.js +22 -5
- package/src/featureInfo/featureInfo.js +1 -2
- package/src/i18n/de.js +12 -3
- package/src/i18n/en.js +10 -1
- package/src/legend/legendHelper.js +6 -7
- package/src/legend/vcsLegend.vue +12 -3
- package/src/manager/categoryManager/CategoryComponent.vue +115 -0
- package/src/manager/categoryManager/CategoryComponentList.vue +57 -0
- package/src/manager/categoryManager/CategoryManager.vue +35 -0
- package/src/manager/categoryManager/categoryManager.js +251 -165
- package/src/manager/contextMenu/contextMenuManager.js +8 -2
- package/src/manager/toolbox/ToolboxManager.vue +1 -0
- package/src/manager/window/WindowComponent.vue +49 -75
- package/src/manager/window/WindowComponentHeader.vue +49 -7
- package/src/manager/window/WindowManager.vue +53 -30
- package/src/manager/window/windowHelper.js +341 -0
- package/src/manager/window/windowManager.js +162 -150
- package/src/notifier/notifier.js +4 -5
- package/src/vcsUiApp.js +7 -1
- package/dist/assets/ui.49010a.css +0 -1
- package/src/manager/categoryManager/ComponentsManager.vue +0 -30
@@ -388,15 +388,17 @@
|
|
388
388
|
.forEach(i => i.selectionChanged(false));
|
389
389
|
selected.value = [];
|
390
390
|
firstSelected = null;
|
391
|
+
emit('input', selected.value);
|
391
392
|
},
|
392
393
|
selectAll() {
|
393
394
|
const currentSelection = [...selected.value];
|
394
395
|
selected.value = this.renderingItems.slice(0);
|
395
396
|
selected.value.forEach((item) => {
|
396
|
-
if (item.selectionChanged && currentSelection.includes(item)) {
|
397
|
+
if (item.selectionChanged && !currentSelection.includes(item)) {
|
397
398
|
item.selectionChanged(true);
|
398
399
|
}
|
399
400
|
});
|
401
|
+
emit('input', selected.value);
|
400
402
|
},
|
401
403
|
};
|
402
404
|
},
|
@@ -409,7 +411,7 @@
|
|
409
411
|
.v-list-item {
|
410
412
|
padding: 4px 8px 4px 16px;
|
411
413
|
display: grid;
|
412
|
-
grid-template-columns: auto
|
414
|
+
grid-template-columns: auto auto;
|
413
415
|
&:after{
|
414
416
|
display: none;
|
415
417
|
}
|
@@ -198,6 +198,15 @@ class ContentTreeCollection extends IndexedCollection {
|
|
198
198
|
this._subTreeListeners = subTrees.map(subTree => this._createSubtreeActionButton(subTree));
|
199
199
|
}
|
200
200
|
|
201
|
+
/**
|
202
|
+
* Returns all managed subtrees. Entries are not persisted and will change, if the trees get recalculated.
|
203
|
+
* @type {import("vue").Ref<Map<string, TreeViewItem>>}
|
204
|
+
* @readonly
|
205
|
+
*/
|
206
|
+
get subTreeViewItems() {
|
207
|
+
return this._subTreeViewItems;
|
208
|
+
}
|
209
|
+
|
201
210
|
/**
|
202
211
|
* All ids of the currently managed subtrees. Ids are not persisted and will change if
|
203
212
|
* the trees get recalculated. The first ID is always the default tree. Other ids are subtree ids.
|
@@ -127,7 +127,7 @@ class LayerContentTreeItem extends VcsObjectContentTreeItem {
|
|
127
127
|
layerName: this._layerName,
|
128
128
|
}),
|
129
129
|
},
|
130
|
-
this._app
|
130
|
+
this._app,
|
131
131
|
vcsAppSymbol,
|
132
132
|
);
|
133
133
|
this.addAction(action, 4);
|
@@ -139,7 +139,7 @@ class LayerContentTreeItem extends VcsObjectContentTreeItem {
|
|
139
139
|
* @private
|
140
140
|
*/
|
141
141
|
_setLayerExtentAction() {
|
142
|
-
const name = '
|
142
|
+
const name = 'content.layerExtentAction.name';
|
143
143
|
this.removeAction(name);
|
144
144
|
if (this._layer) {
|
145
145
|
const { extent } = this._layer.toJSON();
|
@@ -147,7 +147,7 @@ class LayerContentTreeItem extends VcsObjectContentTreeItem {
|
|
147
147
|
const viewpoint = Viewpoint.createViewpointFromExtent(this._layer.extent);
|
148
148
|
const action = createGoToViewpointAction(
|
149
149
|
{
|
150
|
-
name
|
150
|
+
name,
|
151
151
|
title: 'content.layerExtentAction.title',
|
152
152
|
},
|
153
153
|
viewpoint,
|
@@ -40,9 +40,9 @@
|
|
40
40
|
<v-list-item class="px-2">
|
41
41
|
<v-list-item-content>
|
42
42
|
<v-list-item-title>
|
43
|
-
{{ name }}
|
43
|
+
{{ $t(name) }}
|
44
44
|
</v-list-item-title>
|
45
|
-
<v-list-item-subtitle>{{ value }}</v-list-item-subtitle>
|
45
|
+
<v-list-item-subtitle>{{ $t(value) }}</v-list-item-subtitle>
|
46
46
|
</v-list-item-content>
|
47
47
|
</v-list-item>
|
48
48
|
</v-list>
|
@@ -150,6 +150,9 @@
|
|
150
150
|
</script>
|
151
151
|
|
152
152
|
<style lang="scss">
|
153
|
+
.balloon {
|
154
|
+
z-index: 0 !important;
|
155
|
+
}
|
153
156
|
.balloon hr:first-child {
|
154
157
|
display: none;
|
155
158
|
}
|
@@ -4,9 +4,8 @@ import { Cartographic, Entity, Math as CesiumMath } from '@vcmap/cesium';
|
|
4
4
|
import { Projection } from '@vcmap/core';
|
5
5
|
import { check } from '@vcsuite/check';
|
6
6
|
import AbstractFeatureInfoView from './abstractFeatureInfoView.js';
|
7
|
-
import {
|
7
|
+
import { WindowSlot } from '../manager/window/windowManager.js';
|
8
8
|
import BalloonComponent from './BalloonComponent.vue';
|
9
|
-
import { balloonOffset } from './balloonHelper.js';
|
10
9
|
|
11
10
|
/**
|
12
11
|
* derive value from attributes
|
@@ -124,12 +123,7 @@ class BalloonFeatureInfoView extends AbstractFeatureInfoView {
|
|
124
123
|
options.state.hideHeader = true;
|
125
124
|
options.state.classes = ['balloon'];
|
126
125
|
options.slot = WindowSlot.DETACHED;
|
127
|
-
|
128
|
-
(featureInfo.windowPosition?.[0] ?? 0) - balloonOffset.x, // if we do not have a windowPosition, let the next render handle it
|
129
|
-
(featureInfo.windowPosition?.[1] ?? 0) - balloonOffset.y,
|
130
|
-
null,
|
131
|
-
WindowAlignment.BOTTOM_LEFT,
|
132
|
-
);
|
126
|
+
// windowPosition is handled by next render
|
133
127
|
return options;
|
134
128
|
}
|
135
129
|
|
@@ -4,7 +4,7 @@ import { unByKey } from 'ol/Observable.js';
|
|
4
4
|
import {
|
5
5
|
getWindowPositionOptionsFromMapEvent,
|
6
6
|
WindowAlignment,
|
7
|
-
} from '../manager/window/
|
7
|
+
} from '../manager/window/windowHelper.js';
|
8
8
|
|
9
9
|
/**
|
10
10
|
* balloon offset from location or click position in pixel
|
@@ -63,8 +63,9 @@ export async function getBalloonPosition(app, position) {
|
|
63
63
|
* @param {WindowManager} windowManager
|
64
64
|
* @param {string} id - windowId of balloon
|
65
65
|
* @param {import("@vcmap/cesium").Cartesian2|undefined} windowPosition
|
66
|
+
* @param {HTMLElement} target - the map's target { @link @import("@vcmap/core").MapCollection }
|
66
67
|
*/
|
67
|
-
export function setBalloonPosition(windowManager, id, windowPosition) {
|
68
|
+
export function setBalloonPosition(windowManager, id, windowPosition, target) {
|
68
69
|
if (!windowPosition) {
|
69
70
|
return;
|
70
71
|
}
|
@@ -72,6 +73,7 @@ export function setBalloonPosition(windowManager, id, windowPosition) {
|
|
72
73
|
id,
|
73
74
|
getWindowPositionOptionsFromMapEvent(
|
74
75
|
new Cartesian2(windowPosition.x - balloonOffset.x, windowPosition.y - balloonOffset.y),
|
76
|
+
target,
|
75
77
|
WindowAlignment.BOTTOM_LEFT,
|
76
78
|
),
|
77
79
|
);
|
@@ -106,10 +108,20 @@ export async function setupBalloonPositionListener(vcsApp, windowId, clickedPosi
|
|
106
108
|
const wgs84Position = Projection.mercatorToWgs84(position);
|
107
109
|
const cartesian = Cartographic.toCartesian(Cartographic.fromDegrees(...wgs84Position));
|
108
110
|
listeners.push(map.getScene().postRender.addEventListener((scene) => {
|
109
|
-
setBalloonPosition(
|
111
|
+
setBalloonPosition(
|
112
|
+
app.windowManager,
|
113
|
+
windowId,
|
114
|
+
getBalloonPositionCesium(scene, cartesian),
|
115
|
+
app.maps.target,
|
116
|
+
);
|
110
117
|
}));
|
111
118
|
} else if (map instanceof OpenlayersMap) {
|
112
|
-
const handler = () => setBalloonPosition(
|
119
|
+
const handler = () => setBalloonPosition(
|
120
|
+
app.windowManager,
|
121
|
+
windowId,
|
122
|
+
getBalloonPositionOL(map.olMap, position),
|
123
|
+
app.maps.target,
|
124
|
+
);
|
113
125
|
const key = map.olMap.on(
|
114
126
|
'postrender',
|
115
127
|
handler,
|
@@ -121,7 +133,12 @@ export async function setupBalloonPositionListener(vcsApp, windowId, clickedPosi
|
|
121
133
|
position,
|
122
134
|
);
|
123
135
|
listeners.push(map.imageChanged.addEventListener(setup.bind(null, app, windowId, position)));
|
124
|
-
const handler = () => setBalloonPosition(
|
136
|
+
const handler = () => setBalloonPosition(
|
137
|
+
app.windowManager,
|
138
|
+
windowId,
|
139
|
+
getBalloonPositionOL(map.olMap, coords),
|
140
|
+
app.maps.target,
|
141
|
+
);
|
125
142
|
const key = map.olMap.on(
|
126
143
|
'postrender',
|
127
144
|
handler,
|
@@ -25,7 +25,6 @@ import {
|
|
25
25
|
} from '@vcmap/cesium';
|
26
26
|
import { Feature } from 'ol';
|
27
27
|
import { check, checkMaybe } from '@vcsuite/check';
|
28
|
-
import { v4 as uuidv4 } from 'uuid';
|
29
28
|
|
30
29
|
import { vcsAppSymbol } from '../pluginHelper.js';
|
31
30
|
import FeatureInfoInteraction from './featureInfoInteraction.js';
|
@@ -402,7 +401,7 @@ class FeatureInfo {
|
|
402
401
|
});
|
403
402
|
this._clearHighlightingCb = () => layer.featureVisibility.unHighlight([featureId]);
|
404
403
|
}
|
405
|
-
this._windowId =
|
404
|
+
this._windowId = usedFeatureInfoView.className; // use className for a type based position caching
|
406
405
|
this._app.windowManager.add(
|
407
406
|
{
|
408
407
|
id: this._windowId,
|
package/src/i18n/de.js
CHANGED
@@ -8,6 +8,9 @@ const messages = {
|
|
8
8
|
menu: {
|
9
9
|
tooltip: 'Menü',
|
10
10
|
},
|
11
|
+
share: {
|
12
|
+
tooltip: 'Den aktuellen Kartenausschnitt teilen.',
|
13
|
+
},
|
11
14
|
},
|
12
15
|
content: {
|
13
16
|
title: 'Inhalte',
|
@@ -30,7 +33,8 @@ const messages = {
|
|
30
33
|
title: 'Öffne Stil Auswahl',
|
31
34
|
},
|
32
35
|
layerExtentAction: {
|
33
|
-
|
36
|
+
name: 'Ebenenausdehnung',
|
37
|
+
title: 'Auf Ebenenausdehnung zoomen',
|
34
38
|
},
|
35
39
|
},
|
36
40
|
navigation: {
|
@@ -38,12 +42,17 @@ const messages = {
|
|
38
42
|
obliqueRightTooltip: 'Schrägluftbild nach rechts drehen',
|
39
43
|
zoomInTooltip: 'Hineinzoomen',
|
40
44
|
zoomOutTooltip: 'Herauszoomen',
|
41
|
-
pitchTooltip: '
|
45
|
+
pitchTooltip: 'Kameraneigung: {0}°',
|
42
46
|
overviewMapTooltip: 'Übersichtskarte',
|
43
47
|
},
|
44
|
-
|
48
|
+
categoryManager: {
|
45
49
|
title: 'Komponenten',
|
46
50
|
tooltip: 'Komponenten',
|
51
|
+
more: 'Weitere anzeigen...',
|
52
|
+
empty: 'Es gibt noch keine Einträge.',
|
53
|
+
},
|
54
|
+
components: {
|
55
|
+
pin: 'Fenster andocken.',
|
47
56
|
close: 'Fenster schließen.',
|
48
57
|
vcsFormSection: {
|
49
58
|
help: 'Hilfe anzeigen.',
|
package/src/i18n/en.js
CHANGED
@@ -8,6 +8,9 @@ const messages = {
|
|
8
8
|
menu: {
|
9
9
|
tooltip: 'Menu',
|
10
10
|
},
|
11
|
+
share: {
|
12
|
+
tooltip: 'Share current view of the map.',
|
13
|
+
},
|
11
14
|
},
|
12
15
|
content: {
|
13
16
|
title: 'Content',
|
@@ -30,6 +33,7 @@ const messages = {
|
|
30
33
|
title: 'Open Style selector',
|
31
34
|
},
|
32
35
|
layerExtentAction: {
|
36
|
+
name: 'Layer extent',
|
33
37
|
title: 'Jump to layer extent',
|
34
38
|
},
|
35
39
|
},
|
@@ -41,9 +45,14 @@ const messages = {
|
|
41
45
|
pitchTooltip: 'Camera pitch: {0}°',
|
42
46
|
overviewMapTooltip: 'Overview Map',
|
43
47
|
},
|
44
|
-
|
48
|
+
categoryManager: {
|
45
49
|
title: 'Components',
|
46
50
|
tooltip: 'Components',
|
51
|
+
more: 'Show more...',
|
52
|
+
empty: 'There are no entries yet.',
|
53
|
+
},
|
54
|
+
components: {
|
55
|
+
pin: 'Pin window.',
|
47
56
|
close: 'Close window.',
|
48
57
|
vcsFormSection: {
|
49
58
|
help: 'Show help.',
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { getShapeFromOptions } from '@vcmap/core';
|
2
|
-
import {
|
2
|
+
import { shallowRef } from 'vue';
|
3
3
|
|
4
4
|
/**
|
5
5
|
* @enum {string}
|
@@ -142,7 +142,7 @@ export function getLegendEntries(app) {
|
|
142
142
|
/**
|
143
143
|
* @type {import("vue").Ref<Array<LegendEntry>>}>}
|
144
144
|
*/
|
145
|
-
const entries =
|
145
|
+
const entries = shallowRef([]);
|
146
146
|
/**
|
147
147
|
* @type {Object<string,function():void>}
|
148
148
|
*/
|
@@ -153,10 +153,8 @@ export function getLegendEntries(app) {
|
|
153
153
|
*/
|
154
154
|
function removeEntryForLayer(layer) {
|
155
155
|
const layerName = layer.name;
|
156
|
-
|
157
|
-
|
158
|
-
entries.value.splice(index, 1);
|
159
|
-
}
|
156
|
+
// reassign to trigger update
|
157
|
+
entries.value = entries.value.filter(({ key }) => key !== layerName);
|
160
158
|
if (styleChangedListener[layerName]) {
|
161
159
|
styleChangedListener[layerName]();
|
162
160
|
delete styleChangedListener[layerName];
|
@@ -176,7 +174,8 @@ export function getLegendEntries(app) {
|
|
176
174
|
const legend = layer.style?.properties?.legend ?? layer.properties?.legend;
|
177
175
|
if (legend) {
|
178
176
|
const legendEntry = createLayerLegendEntry(key, title, legend);
|
179
|
-
|
177
|
+
// use spread since push won't trigger updates
|
178
|
+
entries.value = [...entries.value, legendEntry];
|
180
179
|
}
|
181
180
|
if (layer.styleChanged) {
|
182
181
|
styleChangedListener[layer.name] = layer.styleChanged.addEventListener(() => syncLayerLegendEntries(layer));
|
package/src/legend/vcsLegend.vue
CHANGED
@@ -27,7 +27,13 @@
|
|
27
27
|
<v-list dense>
|
28
28
|
<div v-for="(item, idx) in entry.legend" :key="idx">
|
29
29
|
<div v-if="item.type === LegendType.Image" class="mx-2">
|
30
|
-
<
|
30
|
+
<img
|
31
|
+
:src="$t(item.src)"
|
32
|
+
max-width="287"
|
33
|
+
max-height="auto"
|
34
|
+
class="mx-2 legend-image"
|
35
|
+
:title="item.tooltip"
|
36
|
+
>
|
31
37
|
</div>
|
32
38
|
<div v-else-if="item.type === LegendType.Iframe" class="mx-2">
|
33
39
|
<iframe
|
@@ -58,7 +64,6 @@
|
|
58
64
|
VExpansionPanelContent,
|
59
65
|
VIcon,
|
60
66
|
VList,
|
61
|
-
VImg,
|
62
67
|
} from 'vuetify/lib';
|
63
68
|
import { LegendType } from './legendHelper.js';
|
64
69
|
import StyleLegendItem from './styleLegendItem.vue';
|
@@ -80,7 +85,6 @@
|
|
80
85
|
VExpansionPanelContent,
|
81
86
|
VIcon,
|
82
87
|
VList,
|
83
|
-
VImg,
|
84
88
|
},
|
85
89
|
props: {
|
86
90
|
entries: {
|
@@ -115,4 +119,9 @@
|
|
115
119
|
max-width: 189px;
|
116
120
|
}
|
117
121
|
}
|
122
|
+
.legend-image {
|
123
|
+
max-width: 287px;
|
124
|
+
height: auto;
|
125
|
+
width: auto;
|
126
|
+
}
|
118
127
|
</style>
|
@@ -0,0 +1,115 @@
|
|
1
|
+
<template>
|
2
|
+
<v-container>
|
3
|
+
<v-row @click="open = !open" class="px-2 py-1 cursor-pointer">
|
4
|
+
<span>
|
5
|
+
<v-icon v-if="open">mdi-chevron-up</v-icon>
|
6
|
+
<v-icon v-else>mdi-chevron-down</v-icon>
|
7
|
+
</span>
|
8
|
+
<span class="flex-grow-1 flex-shrink-1">{{ $t(category.title) }}</span>
|
9
|
+
<vcs-action-button-list
|
10
|
+
v-if="category.actions?.length > 0"
|
11
|
+
:actions="category.actions"
|
12
|
+
small
|
13
|
+
/>
|
14
|
+
</v-row>
|
15
|
+
<template v-if="open">
|
16
|
+
<v-row>
|
17
|
+
<v-col class="pa-0">
|
18
|
+
<vcs-list
|
19
|
+
:items="category.items.slice(0, 10)"
|
20
|
+
:selectable="category.selectable"
|
21
|
+
:single-select="category.singleSelect"
|
22
|
+
v-model="selection"
|
23
|
+
:show-title="false"
|
24
|
+
/>
|
25
|
+
</v-col>
|
26
|
+
</v-row>
|
27
|
+
<v-row v-if="category.items.length > 10">
|
28
|
+
<v-col class="pa-0">
|
29
|
+
<VcsButton @click="openCategoryItemWindow" class="pa-2" small>
|
30
|
+
{{ $t('categoryManager.more') }}
|
31
|
+
</VcsButton>
|
32
|
+
</v-col>
|
33
|
+
</v-row>
|
34
|
+
<v-row v-else-if="category.items.length === 0">
|
35
|
+
<v-col class="pa-2">
|
36
|
+
{{ $t('categoryManager.empty') }}
|
37
|
+
</v-col>
|
38
|
+
</v-row>
|
39
|
+
</template>
|
40
|
+
</v-container>
|
41
|
+
</template>
|
42
|
+
|
43
|
+
<script>
|
44
|
+
import { computed, inject, ref } from 'vue';
|
45
|
+
import { VIcon, VContainer, VRow, VCol } from 'vuetify/lib';
|
46
|
+
import VcsList from '../../components/lists/VcsList.vue';
|
47
|
+
import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
|
48
|
+
import VcsButton from '../../components/buttons/VcsButton.vue';
|
49
|
+
import { vcsAppSymbol } from '../../pluginHelper.js';
|
50
|
+
import CategoryComponentList from './CategoryComponentList.vue';
|
51
|
+
import { WindowSlot } from '../window/windowManager.js';
|
52
|
+
|
53
|
+
export default {
|
54
|
+
name: 'CategoryComponent',
|
55
|
+
components: {
|
56
|
+
VcsActionButtonList,
|
57
|
+
VcsList,
|
58
|
+
VContainer,
|
59
|
+
VRow,
|
60
|
+
VcsButton,
|
61
|
+
VCol,
|
62
|
+
VIcon,
|
63
|
+
},
|
64
|
+
props: {
|
65
|
+
/** @type {ManagedCategory} */
|
66
|
+
category: {
|
67
|
+
type: Object,
|
68
|
+
required: true,
|
69
|
+
},
|
70
|
+
},
|
71
|
+
setup({ category }) {
|
72
|
+
/** @type {VcsUiApp} */
|
73
|
+
const app = inject('vcsApp');
|
74
|
+
const windowId = `${category.id}-category-list`;
|
75
|
+
const open = ref(false);
|
76
|
+
|
77
|
+
const selection = computed({
|
78
|
+
get() { return category.selection; },
|
79
|
+
set(value) {
|
80
|
+
// eslint-disable-next-line vue/no-mutating-props
|
81
|
+
category.selection = value;
|
82
|
+
},
|
83
|
+
});
|
84
|
+
|
85
|
+
return {
|
86
|
+
selection,
|
87
|
+
open,
|
88
|
+
openCategoryItemWindow() {
|
89
|
+
if (app.windowManager.has(windowId)) {
|
90
|
+
setTimeout(() => {
|
91
|
+
app.windowManager.bringWindowToTop(windowId);
|
92
|
+
}, 0);
|
93
|
+
} else {
|
94
|
+
app.windowManager.add({
|
95
|
+
id: windowId,
|
96
|
+
component: CategoryComponentList,
|
97
|
+
props: {
|
98
|
+
category,
|
99
|
+
windowId,
|
100
|
+
},
|
101
|
+
provides: {
|
102
|
+
selection,
|
103
|
+
},
|
104
|
+
slot: WindowSlot.DYNAMIC_LEFT,
|
105
|
+
}, vcsAppSymbol);
|
106
|
+
}
|
107
|
+
},
|
108
|
+
};
|
109
|
+
},
|
110
|
+
};
|
111
|
+
</script>
|
112
|
+
|
113
|
+
<style scoped>
|
114
|
+
|
115
|
+
</style>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<template>
|
2
|
+
<vcs-list
|
3
|
+
:items="category.items"
|
4
|
+
:selectable="category.selectable"
|
5
|
+
:single-select="category.singleSelect"
|
6
|
+
v-model="selection"
|
7
|
+
:title="category.title"
|
8
|
+
/>
|
9
|
+
</template>
|
10
|
+
|
11
|
+
<script>
|
12
|
+
import { computed, inject, watch } from 'vue';
|
13
|
+
import VcsList from '../../components/lists/VcsList.vue';
|
14
|
+
|
15
|
+
export default {
|
16
|
+
name: 'CategoryComponenList',
|
17
|
+
components: {
|
18
|
+
VcsList,
|
19
|
+
},
|
20
|
+
props: {
|
21
|
+
category: {
|
22
|
+
type: Object,
|
23
|
+
required: true,
|
24
|
+
},
|
25
|
+
windowId: {
|
26
|
+
type: String,
|
27
|
+
required: true,
|
28
|
+
},
|
29
|
+
},
|
30
|
+
setup({ category, windowId }) {
|
31
|
+
/** @type {VcsUiApp} */
|
32
|
+
const app = inject('vcsApp');
|
33
|
+
|
34
|
+
const selection = computed({
|
35
|
+
get() { return category.selection; },
|
36
|
+
set(value) {
|
37
|
+
// eslint-disable-next-line vue/no-mutating-props
|
38
|
+
category.selection = value;
|
39
|
+
},
|
40
|
+
});
|
41
|
+
|
42
|
+
watch(app.categoryManager.componentIds, () => {
|
43
|
+
if (!app.categoryManager.get(category.id)) {
|
44
|
+
app.windowManager.remove(windowId);
|
45
|
+
}
|
46
|
+
});
|
47
|
+
|
48
|
+
return {
|
49
|
+
selection,
|
50
|
+
};
|
51
|
+
},
|
52
|
+
};
|
53
|
+
</script>
|
54
|
+
|
55
|
+
<style scoped>
|
56
|
+
|
57
|
+
</style>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<template>
|
2
|
+
<div
|
3
|
+
v-if="categories.length > 0"
|
4
|
+
>
|
5
|
+
<category-component
|
6
|
+
v-for="category in categories"
|
7
|
+
:category="category"
|
8
|
+
:key="category.categoryName"
|
9
|
+
/>
|
10
|
+
</div>
|
11
|
+
</template>
|
12
|
+
|
13
|
+
<script>
|
14
|
+
import { inject, ref, computed } from 'vue';
|
15
|
+
import CategoryComponent from './CategoryComponent.vue';
|
16
|
+
|
17
|
+
/**
|
18
|
+
* @description
|
19
|
+
* uses a VcsList and renders 'a components Window' based on the "categoryManager"
|
20
|
+
* Uses the provided 'vcsApp'
|
21
|
+
*/
|
22
|
+
export default {
|
23
|
+
name: 'CategoryManager',
|
24
|
+
components: { CategoryComponent },
|
25
|
+
setup() {
|
26
|
+
const app = inject('vcsApp');
|
27
|
+
const categoryIds = ref(app.categoryManager.componentIds);
|
28
|
+
const categories = computed(() => categoryIds.value.map(id => app.categoryManager.get(id)));
|
29
|
+
|
30
|
+
return {
|
31
|
+
categories,
|
32
|
+
};
|
33
|
+
},
|
34
|
+
};
|
35
|
+
</script>
|