@vcmap/ui 5.0.0-rc.26 → 5.0.0-rc.28

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.
Files changed (107) hide show
  1. package/build/buildCesium.js +7 -0
  2. package/build/bundle.js +2 -1
  3. package/config/dev.config.json +4 -0
  4. package/config/www.config.json +1 -1
  5. package/dist/assets/cesium/ThirdParty/Workers/basis_transcoder.js +21 -0
  6. package/dist/assets/cesium/ThirdParty/Workers/draco_decoder_nodejs.js +117 -0
  7. package/dist/assets/cesium/ThirdParty/Workers/package.json +1 -0
  8. package/dist/assets/cesium/ThirdParty/Workers/pako_deflate.min.js +2 -0
  9. package/dist/assets/cesium/ThirdParty/Workers/pako_inflate.min.js +2 -0
  10. package/dist/assets/cesium/ThirdParty/Workers/z-worker-pako.js +1 -0
  11. package/dist/assets/cesium/ThirdParty/basis_transcoder.wasm +0 -0
  12. package/dist/assets/cesium/ThirdParty/draco_decoder.wasm +0 -0
  13. package/dist/assets/cesium/ThirdParty/google-earth-dbroot-parser.js +8337 -0
  14. package/dist/assets/cesium/Workers/cesiumWorkerBootstrapper.js +1 -1
  15. package/dist/assets/cesium/Workers/package.js +1 -1
  16. package/dist/assets/cesium/Workers/transferTypedArrayTest.js +1 -1
  17. package/dist/assets/{cesium.305b7c.js → cesium.973919.js} +66787 -66580
  18. package/dist/assets/cesium.js +1 -1
  19. package/dist/assets/{core.f3d6d4.js → core.7a2173.js} +2769 -2782
  20. package/dist/assets/core.js +1 -1
  21. package/dist/assets/index-1b09f88d.js +1 -0
  22. package/dist/assets/ol.js +1 -1
  23. package/dist/assets/style/icon-marker-blue.534e37.png +0 -0
  24. package/dist/assets/style/icon-marker-green.0b6a92.png +0 -0
  25. package/dist/assets/style/icon-marker-o-blue.7b6d62.png +0 -0
  26. package/dist/assets/style/icon-marker-o-green.c863c0.png +0 -0
  27. package/dist/assets/style/icon-marker-o-red.93ff58.png +0 -0
  28. package/dist/assets/style/icon-marker-o.036477.png +0 -0
  29. package/dist/assets/style/icon-marker-red.313d03.png +0 -0
  30. package/dist/assets/style/icon-marker.70960f.png +0 -0
  31. package/dist/assets/style/icon-pin-blue.7be369.png +0 -0
  32. package/dist/assets/style/icon-pin-green.cbb935.png +0 -0
  33. package/dist/assets/style/icon-pin-red.3f25b2.png +0 -0
  34. package/dist/assets/style/icon-pin.b7ce77.png +0 -0
  35. package/dist/assets/{ui.74022f.css → ui.bd7a9a.css} +2 -2
  36. package/dist/assets/ui.bd7a9a.js +14764 -0
  37. package/dist/assets/ui.js +1 -1
  38. package/dist/assets/vue.js +2 -2
  39. package/dist/assets/{vuetify.30486f.js → vuetify.95f6c3.js} +1 -1
  40. package/dist/assets/vuetify.js +2 -2
  41. package/dist/index.html +1 -1
  42. package/index.js +17 -1
  43. package/package.json +3 -3
  44. package/plugins/@vcmap/create-link/index.js +8 -8
  45. package/plugins/@vcmap-show-case/collection-manager-example/index.js +6 -1
  46. package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +36 -8
  47. package/plugins/@vcmap-show-case/form-inputs-example/exampleActions.js +0 -19
  48. package/plugins/@vcmap-show-case/form-inputs-example/index.js +1 -2
  49. package/plugins/@vcmap-show-case/style-input-example/README.md +4 -0
  50. package/plugins/@vcmap-show-case/style-input-example/index.js +42 -0
  51. package/plugins/@vcmap-show-case/style-input-example/package.json +5 -0
  52. package/plugins/@vcmap-show-case/style-input-example/styleExample.vue +191 -0
  53. package/plugins/@vcmap-show-case/window-tester/WindowExample.vue +12 -13
  54. package/plugins/@vcmap-show-case/window-tester/windowExampleToggleChild.vue +44 -0
  55. package/public/assets/style/icon-marker-blue.png +0 -0
  56. package/public/assets/style/icon-marker-green.png +0 -0
  57. package/public/assets/style/icon-marker-o-blue.png +0 -0
  58. package/public/assets/style/icon-marker-o-green.png +0 -0
  59. package/public/assets/style/icon-marker-o-red.png +0 -0
  60. package/public/assets/style/icon-marker-o.png +0 -0
  61. package/public/assets/style/icon-marker-red.png +0 -0
  62. package/public/assets/style/icon-marker.png +0 -0
  63. package/public/assets/style/icon-pin-blue.png +0 -0
  64. package/public/assets/style/icon-pin-green.png +0 -0
  65. package/public/assets/style/icon-pin-red.png +0 -0
  66. package/public/assets/style/icon-pin.png +0 -0
  67. package/src/actions/actionHelper.js +1 -0
  68. package/src/application/VcsApp.vue +7 -1
  69. package/src/components/buttons/VcsActionButtonList.vue +1 -0
  70. package/src/components/form-inputs-controls/VcsCheckbox.vue +3 -2
  71. package/src/components/form-inputs-controls/VcsFormSection.vue +59 -9
  72. package/src/components/form-inputs-controls/VcsLabel.vue +10 -0
  73. package/src/components/form-inputs-controls/VcsRadioGrid.vue +175 -0
  74. package/src/components/form-inputs-controls/VcsSelect.vue +3 -0
  75. package/src/components/form-inputs-controls/VcsTextField.vue +12 -0
  76. package/src/components/icons/+all.js +4 -0
  77. package/src/components/icons/EditVerticesIcon.vue +39 -0
  78. package/src/components/lists/VcsActionList.vue +2 -0
  79. package/src/components/style/MenuWrapper.vue +138 -0
  80. package/src/components/style/VcsFillMenu.vue +61 -0
  81. package/src/components/style/VcsFillSelector.vue +45 -0
  82. package/src/components/style/VcsImageMenu.vue +84 -0
  83. package/src/components/style/VcsImageSelector.vue +609 -0
  84. package/src/components/style/VcsStrokeMenu.vue +73 -0
  85. package/src/components/style/VcsStrokeSelector.vue +87 -0
  86. package/src/components/style/VcsTextMenu.vue +81 -0
  87. package/src/components/style/VcsTextSelector.vue +271 -0
  88. package/src/components/style/VcsVectorStyleComponent.vue +119 -0
  89. package/src/components/style/composables.js +84 -0
  90. package/src/contentTree/contentTreeCollection.js +20 -11
  91. package/src/i18n/de.js +51 -17
  92. package/src/i18n/en.js +56 -22
  93. package/src/legend/vcsLegend.vue +7 -5
  94. package/src/manager/collectionManager/CollectionComponent.vue +15 -18
  95. package/src/manager/collectionManager/CollectionComponentList.vue +22 -9
  96. package/src/manager/collectionManager/CollectionManager.vue +20 -1
  97. package/src/manager/collectionManager/collectionComponent.js +17 -0
  98. package/src/manager/window/WindowComponent.vue +2 -1
  99. package/src/manager/window/WindowManager.vue +23 -9
  100. package/src/manager/window/windowHelper.js +76 -4
  101. package/src/manager/window/windowManager.js +38 -6
  102. package/src/vcsUiApp.js +1 -0
  103. package/dist/assets/index-f94d5be3.js +0 -1
  104. package/dist/assets/ui.74022f.js +0 -13466
  105. /package/dist/assets/{ol.39cc05.js → ol.f6e2e4.js} +0 -0
  106. /package/dist/assets/{vue.9b8c6e.js → vue.d4be99.js} +0 -0
  107. /package/dist/assets/{vuetify.30486f.css → vuetify.95f6c3.css} +0 -0
@@ -4,7 +4,6 @@ import {
4
4
  makeOverrideCollection,
5
5
  getObjectFromClassRegistry,
6
6
  } from '@vcmap/core';
7
- import { v4 as uuid } from 'uuid';
8
7
  import { computed, ref } from 'vue';
9
8
  import ContentTreeItem from './contentTreeItem.js';
10
9
  import { vcsAppSymbol } from '../pluginHelper.js';
@@ -71,7 +70,13 @@ class ContentTreeCollection extends IndexedCollection {
71
70
  this._weightListeners.get(child.name)();
72
71
  this._weightListeners.delete(child.name);
73
72
  }
73
+ if (this._subTreeListeners.has(child.name)) {
74
+ this._subTreeListeners.get(child.name)();
75
+ this._subTreeListeners.delete(child.name);
76
+ this._subTreeViewItems.value.delete(child.name);
77
+ }
74
78
  }),
79
+ this.moved.addEventListener(recreateTree),
75
80
  ];
76
81
  /**
77
82
  * This is the default content tree.
@@ -89,10 +94,10 @@ class ContentTreeCollection extends IndexedCollection {
89
94
  this._subTreeViewItems = ref(new Map());
90
95
  /**
91
96
  * The subtree content action button destroy handlers
92
- * @type {Array<function():void>}
97
+ * @type {Map<string, function():void>}
93
98
  * @private
94
99
  */
95
- this._subTreeListeners = [];
100
+ this._subTreeListeners = new Map();
96
101
  /**
97
102
  * @type {boolean}
98
103
  * @private
@@ -105,7 +110,7 @@ class ContentTreeCollection extends IndexedCollection {
105
110
  */
106
111
  _clearSubTrees() {
107
112
  this._subTreeViewItems.value.clear();
108
- this._subTreeListeners.forEach((cb) => {
113
+ [...this._subTreeListeners.values()].forEach((cb) => {
109
114
  cb();
110
115
  });
111
116
  }
@@ -118,7 +123,7 @@ class ContentTreeCollection extends IndexedCollection {
118
123
  */
119
124
  _createSubtreeActionButton(subTreeViewItem, slot = WindowSlot.STATIC) {
120
125
  // TODO make configurable?
121
- const id = uuid();
126
+ const id = subTreeViewItem.name;
122
127
  const app = this._app;
123
128
  const { action, destroy } = createToggleAction(
124
129
  // TODO icon & title are not reactive
@@ -157,7 +162,6 @@ class ContentTreeCollection extends IndexedCollection {
157
162
  * @private
158
163
  */
159
164
  _setTreeView() {
160
- this._clearSubTrees();
161
165
  /** @type {Map<string, ParentTreeViewItem>} */
162
166
  const baseTreeMap = new Map();
163
167
  [...this._array]
@@ -209,9 +213,14 @@ class ContentTreeCollection extends IndexedCollection {
209
213
  ...topLevelItems.filter((i) => i[subTreeSymbol]),
210
214
  ];
211
215
 
212
- this._subTreeListeners = subTrees.map((subTree) =>
213
- this._createSubtreeActionButton(subTree),
214
- );
216
+ subTrees.forEach((subTree) => {
217
+ if (!this._app.navbarManager.has(subTree.name)) {
218
+ this._subTreeListeners.set(
219
+ subTree.name,
220
+ this._createSubtreeActionButton(subTree),
221
+ );
222
+ }
223
+ });
215
224
  }
216
225
 
217
226
  /**
@@ -224,8 +233,8 @@ class ContentTreeCollection extends IndexedCollection {
224
233
  }
225
234
 
226
235
  /**
227
- * All ids of the currently managed subtrees. Ids are not persisted and will change if
228
- * the trees get recalculated. The first ID is always the default tree. Other ids are subtree ids.
236
+ * All ids of the currently managed subtrees.
237
+ * The first ID is always the default tree. Other ids are subtree ids.
229
238
  * Order of ids is dependent on their position in the collection and weight.
230
239
  * @type {Array<string>}
231
240
  * @readonly
package/src/i18n/de.js CHANGED
@@ -9,7 +9,7 @@ const messages = {
9
9
  tooltip: 'Menü',
10
10
  },
11
11
  share: {
12
- tooltip: 'Den aktuellen Kartenausschnitt teilen.',
12
+ tooltip: 'Aktuellen Kartenausschnitt teilen',
13
13
  },
14
14
  },
15
15
  content: {
@@ -22,24 +22,24 @@ const messages = {
22
22
  title: 'Weitere Informationen',
23
23
  },
24
24
  viewpointAction: {
25
- title: 'Springe zur Ansicht',
25
+ title: 'Zur Ansicht springen',
26
26
  },
27
27
  styleAction: {
28
- title: 'Öffne Stil Auswahl',
28
+ title: 'Stilauswahl öffnen',
29
29
  },
30
30
  layerExtentAction: {
31
- name: 'Ebenenausdehnung',
31
+ name: 'Auf Ebene zoomen',
32
32
  title: 'Auf Ebenenausdehnung zoomen',
33
33
  },
34
34
  },
35
35
  navigation: {
36
- obliqueLeftTooltip: 'Schrägluftbild nach links drehen',
37
- obliqueRightTooltip: 'Schrägluftbild nach rechts drehen',
36
+ obliqueLeftTooltip: 'Ansicht nach links drehen',
37
+ obliqueRightTooltip: 'Ansicht nach rechts drehen',
38
38
  zoomInTooltip: 'Hineinzoomen',
39
39
  zoomOutTooltip: 'Herauszoomen',
40
40
  pitchTooltip: 'Kameraneigung: {0}°',
41
41
  overviewMapTooltip: 'Übersichtskarte',
42
- homeButton: 'Springe zur Startansicht',
42
+ homeButton: 'Zur Startansicht springen',
43
43
  },
44
44
  categoryManager: {
45
45
  title: 'Mein Arbeitsbereich',
@@ -50,10 +50,10 @@ const messages = {
50
50
  empty: 'Es gibt noch keine Einträge.',
51
51
  },
52
52
  components: {
53
- pin: 'Fenster andocken.',
54
- close: 'Fenster schließen.',
53
+ pin: 'Fenster andocken',
54
+ close: 'Fenster schließen',
55
55
  vcsFormSection: {
56
- help: 'Hilfe anzeigen.',
56
+ help: 'Hilfe anzeigen',
57
57
  },
58
58
  vcsTable: {
59
59
  key: 'Name',
@@ -68,6 +68,40 @@ const messages = {
68
68
  noDataPlaceholder: 'Keine Daten verfügbar',
69
69
  noResultsPlaceholder: 'Keine übereinstimmenden Einträge gefunden',
70
70
  },
71
+ style: {
72
+ fill: 'Füll Stil',
73
+ stroke: 'Linien Stil',
74
+ reset: 'Zurücksetzen',
75
+ lineWidth: 'Linienbreite',
76
+ type: 'Typ',
77
+ points: 'Points',
78
+ radius: 'Radius',
79
+ radius2: 'Radius2',
80
+ angle: 'Winkel',
81
+ rotation: 'Rotation',
82
+ scale: 'Skalierung',
83
+ opacity: 'Deckkraft',
84
+ image: 'Punkt Stil',
85
+ icon: 'Icon',
86
+ presets: 'Vorlagen',
87
+ shape: 'Form',
88
+ circle: 'Kreis',
89
+ square: 'Quadrat',
90
+ rectangle: 'Rechteck',
91
+ triangle: 'Dreieck',
92
+ star: 'Stern',
93
+ cross: 'Kreuz',
94
+ x: 'X',
95
+ custom: 'Benutzerdefiniert',
96
+ bold: 'Fett',
97
+ italic: 'Kursiv',
98
+ text: 'Text',
99
+ enterText: 'Text hier eingeben',
100
+ allowedRange: 'Erlaubter Wertebereich',
101
+ notValid: 'Eingabe nicht gültig',
102
+ required: 'Eingabe ist erforderlich',
103
+ offset: 'Versatz',
104
+ },
71
105
  },
72
106
  settings: {
73
107
  title: 'Einstellungen',
@@ -80,8 +114,8 @@ const messages = {
80
114
  },
81
115
  },
82
116
  featureInfo: {
83
- activateToolTitle: 'Informationstool aktivieren',
84
- deactivateToolTitle: 'Informationstool deaktivieren',
117
+ activateToolTitle: 'Informationswerkzeug aktivieren',
118
+ deactivateToolTitle: 'Informationswerkzeug deaktivieren',
85
119
  },
86
120
  legend: {
87
121
  title: 'Legende',
@@ -93,10 +127,10 @@ const messages = {
93
127
  search: {
94
128
  title: 'Suche',
95
129
  tooltip: 'Suche',
96
- select: 'Suchergebnis selektieren',
97
- placeholder: 'Suche nach Straße, Adresse, Ort, POI',
130
+ select: 'Suchergebnis auswählen',
131
+ placeholder: 'Suche nach Adresse oder Ort/Sehenswürdigkeit',
98
132
  zoomToFeatureAction: 'Auf Ergebnis zoomen',
99
- zoomToAll: 'Zu allen Ergebnissen zoomen',
133
+ zoomToAll: 'Auf alle Ergebnisse zoomen',
100
134
  },
101
135
  toolbox: {
102
136
  flight: 'Flug',
@@ -105,8 +139,8 @@ const messages = {
105
139
  footer: {
106
140
  title: 'Fußzeile',
107
141
  attributions: {
108
- title: 'Attribution',
109
- tooltip: 'Öffne Attribution Fenster',
142
+ title: 'Attributionen',
143
+ tooltip: 'Öffne Attributionsfenster',
110
144
  },
111
145
  },
112
146
  notification: {
package/src/i18n/en.js CHANGED
@@ -1,15 +1,15 @@
1
1
  const messages = {
2
2
  navbar: {
3
3
  maps: {
4
- CesiumMap: 'Activate 3D map',
5
- OpenlayersMap: 'Activate 2D map',
6
- ObliqueMap: 'Activate Oblique map',
4
+ CesiumMap: 'Enable 3D view',
5
+ OpenlayersMap: 'Enable 2D view',
6
+ ObliqueMap: 'Enable oblique view',
7
7
  },
8
8
  menu: {
9
9
  tooltip: 'Menu',
10
10
  },
11
11
  share: {
12
- tooltip: 'Share current view of the map.',
12
+ tooltip: 'Share current view of the map',
13
13
  },
14
14
  },
15
15
  content: {
@@ -19,27 +19,27 @@ const messages = {
19
19
  placeholder: 'Search elements',
20
20
  },
21
21
  infoAction: {
22
- title: 'Info',
22
+ title: 'Further informationen',
23
23
  },
24
24
  viewpointAction: {
25
25
  title: 'Go to viewpoint',
26
26
  },
27
27
  styleAction: {
28
- title: 'Open Style selector',
28
+ title: 'Open style selector',
29
29
  },
30
30
  layerExtentAction: {
31
- name: 'Layer extent',
32
- title: 'Jump to layer extent',
31
+ name: 'Zoom to extent',
32
+ title: 'Zoom to layer extent',
33
33
  },
34
34
  },
35
35
  navigation: {
36
- obliqueLeftTooltip: 'Rotate view left',
37
- obliqueRightTooltip: 'Rotate view right',
36
+ obliqueLeftTooltip: 'Rotate view to left',
37
+ obliqueRightTooltip: 'Rotate view to right',
38
38
  zoomInTooltip: 'Zoom in',
39
39
  zoomOutTooltip: 'Zoom out',
40
40
  pitchTooltip: 'Camera pitch: {0}°',
41
- overviewMapTooltip: 'Overview Map',
42
- homeButton: 'Go to starting view',
41
+ overviewMapTooltip: 'Show overview map',
42
+ homeButton: 'Go to home view',
43
43
  },
44
44
  categoryManager: {
45
45
  title: 'My Workspace',
@@ -50,28 +50,62 @@ const messages = {
50
50
  empty: 'There are no entries yet.',
51
51
  },
52
52
  components: {
53
- pin: 'Pin window.',
54
- close: 'Close window.',
53
+ pin: 'Dock window',
54
+ close: 'Close window',
55
55
  vcsFormSection: {
56
- help: 'Show help.',
56
+ help: 'Show help',
57
57
  },
58
58
  vcsTable: {
59
59
  key: 'Name',
60
60
  value: 'Value',
61
61
  },
62
62
  vcsDataTable: {
63
- searchbarPlaceholder: 'Name, Value, ...',
63
+ searchbarPlaceholder: 'Name, value, ...',
64
64
  itemsPerPage: 'per page',
65
65
  ofItems: 'of',
66
66
  nextPage: 'Next page',
67
- formerPage: 'Former page',
67
+ formerPage: 'Previous page',
68
68
  noDataPlaceholder: 'No data available',
69
69
  noResultsPlaceholder: 'No matching records found',
70
70
  },
71
+ style: {
72
+ fill: 'Fill',
73
+ stroke: 'Stroke',
74
+ reset: 'Reset',
75
+ lineWidth: 'Line width',
76
+ type: 'Type',
77
+ points: 'Points',
78
+ radius: 'Radius',
79
+ radius2: 'Radius2',
80
+ angle: 'Angle',
81
+ rotation: 'Rotation',
82
+ scale: 'Scale',
83
+ opacity: 'Opacity',
84
+ image: 'Point style',
85
+ icon: 'Icon',
86
+ shape: 'Shape',
87
+ presets: 'Presets',
88
+ circle: 'Circle',
89
+ square: 'Square',
90
+ rectangle: 'Rectangle',
91
+ triangle: 'Triangle',
92
+ star: 'Star',
93
+ cross: 'Cross',
94
+ x: 'X',
95
+ custom: 'Custom',
96
+ bold: 'Bold',
97
+ italic: 'Italic',
98
+ text: 'Text',
99
+ enterText: 'Enter text here',
100
+ allowedRange: 'Allowed value range',
101
+ notValid: 'Input not valid',
102
+ required: 'Input is required',
103
+ offset: 'Offset',
104
+ },
71
105
  },
72
106
  settings: {
73
107
  title: 'Settings',
74
- tooltip: 'Settings',
108
+ tooltip: 'Configure settings',
75
109
  languageSelector: 'Language',
76
110
  theme: {
77
111
  title: 'Color theme',
@@ -80,8 +114,8 @@ const messages = {
80
114
  },
81
115
  },
82
116
  featureInfo: {
83
- activateToolTitle: 'Activate Infotool',
84
- deactivateToolTitle: 'Deactivate Infotool',
117
+ activateToolTitle: 'Enable Info Tool',
118
+ deactivateToolTitle: 'Disable Info Tool',
85
119
  },
86
120
  legend: {
87
121
  title: 'Legend',
@@ -94,7 +128,7 @@ const messages = {
94
128
  title: 'Search',
95
129
  tooltip: 'Search',
96
130
  select: 'Select result item',
97
- placeholder: 'Search for Street, Address, Landmark, POI',
131
+ placeholder: 'Search for address or landmark/point of interest',
98
132
  zoomToFeatureAction: 'Zoom to result',
99
133
  zoomToAll: 'Zoom to all',
100
134
  },
@@ -106,7 +140,7 @@ const messages = {
106
140
  title: 'Footer',
107
141
  attributions: {
108
142
  title: 'Attributions',
109
- tooltip: 'Open Attributions Window',
143
+ tooltip: 'Open attributions window',
110
144
  },
111
145
  },
112
146
  notification: {
@@ -108,13 +108,15 @@
108
108
  };
109
109
 
110
110
  /**
111
- * Sets all entry panels open
112
111
  * @type {import("vue").ComputedRef<number[]>}
113
112
  */
114
- const panels = computed(() => {
115
- return [...Array(props.entries.length).keys()].filter(
116
- (p, idx) => !!props.entries[idx].open,
117
- );
113
+ const panels = computed({
114
+ get() {
115
+ return [...Array(props.entries.length).keys()].filter(
116
+ (p, idx) => !!props.entries[idx].open,
117
+ );
118
+ },
119
+ set() {},
118
120
  });
119
121
 
120
122
  return {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <v-expansion-panel @change="active = !active">
2
+ <v-expansion-panel>
3
3
  <v-expansion-panel-header hide-actions class="px-2">
4
4
  <template #default="{ open }">
5
5
  <div class="d-flex justify-space-between">
@@ -9,13 +9,17 @@
9
9
  </v-icon>
10
10
  {{ $t(title) }}
11
11
  </div>
12
- <VcsActionButtonList v-if="actions?.length > 0" :actions="actions" />
12
+ <VcsActionButtonList
13
+ v-if="actions?.length > 0"
14
+ :actions="actions"
15
+ :overflow-count="overflowCount"
16
+ />
13
17
  </div>
14
18
  </template>
15
19
  </v-expansion-panel-header>
16
20
  <v-expansion-panel-content class="pb-1">
17
21
  <vcs-list
18
- :items="items.slice(0, 10)"
22
+ :items="items.slice(0, limit)"
19
23
  :draggable="draggable"
20
24
  :selectable="selectable"
21
25
  :single-select="singleSelect"
@@ -23,7 +27,7 @@
23
27
  :show-title="false"
24
28
  @item-moved="move"
25
29
  />
26
- <v-sheet v-if="items.length > 10" class="ma-2 pl-2">
30
+ <v-sheet v-if="items.length > limit" class="ma-2 pl-2">
27
31
  <VcsButton @click="openCollectionComponentList">
28
32
  {{ $t('collectionManager.more') }}
29
33
  </VcsButton>
@@ -36,7 +40,7 @@
36
40
  </template>
37
41
 
38
42
  <script>
39
- import { inject, ref } from 'vue';
43
+ import { inject } from 'vue';
40
44
  import {
41
45
  VIcon,
42
46
  VExpansionPanel,
@@ -44,13 +48,14 @@
44
48
  VExpansionPanelContent,
45
49
  VSheet,
46
50
  } from 'vuetify/lib';
47
- import { IndexedCollection } from '@vcmap/core';
48
51
  import VcsList from '../../components/lists/VcsList.vue';
49
52
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
50
53
  import VcsButton from '../../components/buttons/VcsButton.vue';
51
54
  import { vcsAppSymbol } from '../../pluginHelper.js';
52
55
  import { WindowSlot } from '../window/windowManager.js';
53
- import CollectionComponentList from './CollectionComponentList.vue';
56
+ import CollectionComponentList, {
57
+ moveItem,
58
+ } from './CollectionComponentList.vue';
54
59
 
55
60
  /**
56
61
  * Renders the first ten items of a collectionComponent in a List. Uses CollectionComponentList to render more items.
@@ -76,7 +81,6 @@
76
81
  */
77
82
  const collectionComponent = inject('collectionComponent');
78
83
  const windowId = `${collectionComponent.id}-list`;
79
- const active = ref(false);
80
84
 
81
85
  return {
82
86
  title: collectionComponent.title,
@@ -85,19 +89,12 @@
85
89
  draggable: collectionComponent.draggable,
86
90
  selectable: collectionComponent.selectable,
87
91
  singleSelect: collectionComponent.singleSelect,
92
+ overflowCount: collectionComponent.overflowCount,
93
+ limit: collectionComponent.limit,
88
94
  actions: collectionComponent.getActions(),
89
95
  move({ item, targetIndex }) {
90
- if (collectionComponent.collection instanceof IndexedCollection) {
91
- const collectionItem = collectionComponent.collection.getByKey(
92
- item.name,
93
- );
94
- collectionComponent.collection.moveTo(
95
- collectionItem,
96
- targetIndex, // collectionItemOffset.value for paginated lists?
97
- );
98
- }
96
+ moveItem(collectionComponent, item, targetIndex);
99
97
  },
100
- active,
101
98
  openCollectionComponentList() {
102
99
  if (app.windowManager.has(windowId)) {
103
100
  setTimeout(() => {
@@ -15,6 +15,27 @@
15
15
  import { IndexedCollection } from '@vcmap/core';
16
16
  import VcsList from '../../components/lists/VcsList.vue';
17
17
 
18
+ /**
19
+ * Moves an item to a new position.
20
+ * New position is derived from a target item in the collection.
21
+ * This ensures correct movement, if rendered list is only a subset of the collection.
22
+ * @param {CollectionComponent} collectionComponent
23
+ * @param {VcsListItem} item
24
+ * @param {number} targetIndex
25
+ */
26
+ export function moveItem(collectionComponent, item, targetIndex) {
27
+ const { collection } = collectionComponent;
28
+ if (collection instanceof IndexedCollection) {
29
+ const collectionItem = collection.getByKey(item.name);
30
+ const keyProperty = collection.uniqueKey;
31
+ const targetItem = collectionComponent.items.value[targetIndex];
32
+ const targetIndexCol = [...collection].findIndex(
33
+ (i) => i[keyProperty] === targetItem[keyProperty],
34
+ );
35
+ collection.moveTo(collectionItem, targetIndexCol);
36
+ }
37
+ }
38
+
18
39
  /**
19
40
  * Renders the items of a CollectionComponent in a List.
20
41
  * The collectionComponent must be passed via {@link https://vuejs.org/api/composition-api-dependency-injection.html |provide }.
@@ -44,15 +65,7 @@
44
65
  selectable: collectionComponent.selectable,
45
66
  singleSelect: collectionComponent.singleSelect,
46
67
  move({ item, targetIndex }) {
47
- if (collectionComponent.collection instanceof IndexedCollection) {
48
- const collectionItem = collectionComponent.collection.getByKey(
49
- item.id,
50
- );
51
- collectionComponent.collection.moveTo(
52
- collectionItem,
53
- targetIndex, // collectionItemOffset.value for paginated lists?
54
- );
55
- }
68
+ moveItem(collectionComponent, item, targetIndex);
56
69
  },
57
70
  };
58
71
  },
@@ -4,6 +4,7 @@
4
4
  accordion
5
5
  multiple
6
6
  v-if="componentIds.length > 0"
7
+ v-model="panels"
7
8
  class="rounded-0"
8
9
  >
9
10
  <collection-component-provider
@@ -16,7 +17,7 @@
16
17
  </template>
17
18
 
18
19
  <script>
19
- import { inject, ref } from 'vue';
20
+ import { computed, inject, ref } from 'vue';
20
21
  import { VExpansionPanels, VContainer } from 'vuetify/lib';
21
22
  import CollectionComponentProvider from './CollectionComponentProvider.vue';
22
23
 
@@ -35,8 +36,26 @@
35
36
  const collectionManager = inject('collectionManager');
36
37
  const componentIds = ref(collectionManager.componentIds);
37
38
 
39
+ /**
40
+ * @type {WritableComputedRef<number[]>}
41
+ */
42
+ const panels = computed({
43
+ get() {
44
+ return [...Array(componentIds.value.length).keys()].filter(
45
+ (p, idx) =>
46
+ !!collectionManager.get(componentIds.value[idx]).open.value,
47
+ );
48
+ },
49
+ set(value) {
50
+ componentIds.value.forEach((id, idx) => {
51
+ collectionManager.get(id).open.value = value.includes(idx);
52
+ });
53
+ },
54
+ });
55
+
38
56
  return {
39
57
  componentIds,
58
+ panels,
40
59
  };
41
60
  },
42
61
  };
@@ -2,6 +2,7 @@ import { IndexedCollection, isOverrideCollection } from '@vcmap/core';
2
2
  import { getLogger } from '@vcsuite/logger';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { computed, ref } from 'vue';
5
+ import { parseNumber } from '@vcsuite/parsers';
5
6
  import { validateAction } from '../../components/lists/VcsActionList.vue';
6
7
  import { sortByWeight } from '../buttonManager.js';
7
8
 
@@ -12,6 +13,8 @@ import { sortByWeight } from '../buttonManager.js';
12
13
  * @property {boolean} [draggable] - only supported for IndexedCollections
13
14
  * @property {boolean} [selectable]
14
15
  * @property {boolean} [singleSelect]
16
+ * @property {number} [overflowCount=2] - number of header action buttons rendered until overflow
17
+ * @property {number} [limit=10] - limit number of items in rendered list (more items are rendered in extra window)
15
18
  */
16
19
 
17
20
  /**
@@ -53,6 +56,20 @@ class CollectionComponent {
53
56
  * @type {import("vue").Ref<string>}
54
57
  */
55
58
  this.title = ref(options.title);
59
+ /**
60
+ * @type {import("vue").Ref<boolean>}
61
+ */
62
+ this.open = ref(false);
63
+ /**
64
+ *
65
+ * @type {import("vue").Ref<number>}
66
+ */
67
+ this.overflowCount = ref(parseNumber(options.overflowCount, 2));
68
+ /**
69
+ *
70
+ * @type {import("vue").Ref<number>}
71
+ */
72
+ this.limit = ref(parseNumber(options.limit, 10));
56
73
  /**
57
74
  * @type {import("vue").Ref<boolean>}
58
75
  * @private
@@ -91,7 +91,8 @@
91
91
  const isDockedLeft = computed(() => {
92
92
  return (
93
93
  props.slotWindow === WindowSlot.STATIC ||
94
- props.slotWindow === WindowSlot.DYNAMIC_LEFT
94
+ props.slotWindow === WindowSlot.DYNAMIC_LEFT ||
95
+ props.slotWindow === WindowSlot.DYNAMIC_CHILD
95
96
  );
96
97
  });
97
98
  const isDockedRight = computed(
@@ -60,7 +60,7 @@
60
60
  import WindowComponent from './WindowComponent.vue';
61
61
  import WindowComponentHeader from './WindowComponentHeader.vue';
62
62
  import {
63
- applyPositionOnTarget,
63
+ getPositionAppliedOnTarget,
64
64
  getTargetSize,
65
65
  moveWindow,
66
66
  } from './windowHelper.js';
@@ -98,6 +98,23 @@
98
98
  const isOnTop = (id) => {
99
99
  return windowManager.get(id)?.zIndex.value === componentIds.length - 1;
100
100
  };
101
+ /**
102
+ * @param {WindowComponent} windowComponent
103
+ * @returns {WindowPosition|null}
104
+ */
105
+ const getPosition = (windowComponent) => {
106
+ if (!windowComponent) {
107
+ return null;
108
+ }
109
+ const parentComponent =
110
+ !windowComponent?.state?.dockable &&
111
+ windowManager.get(windowComponent.parentId);
112
+ return getPositionAppliedOnTarget(
113
+ windowComponent?.position,
114
+ targetSize.value,
115
+ getPosition(parentComponent),
116
+ );
117
+ };
101
118
  /**
102
119
  * @param {string} id
103
120
  * @returns {import("vue").ComputedRef<Object>}
@@ -105,15 +122,10 @@
105
122
  const getStyles = (id) =>
106
123
  computed(() => {
107
124
  const windowComponent = windowManager.get(id);
108
- const state = windowComponent?.state;
109
- const position = applyPositionOnTarget(
110
- windowComponent?.position,
111
- targetSize.value,
112
- );
113
125
  return {
114
126
  zIndex: windowComponent.zIndex.value,
115
- ...position,
116
- ...(state.styles || {}),
127
+ ...getPosition(windowComponent),
128
+ ...(windowComponent?.state?.styles || {}),
117
129
  };
118
130
  });
119
131
  /**
@@ -129,7 +141,9 @@
129
141
  * @param {{dx: number, dy: number}} translation
130
142
  */
131
143
  const move = (id, translation) => {
132
- moveWindow(id, translation, windowManager, targetSize.value);
144
+ const windowComponent = windowManager.get(id);
145
+ const position = getPosition(windowComponent);
146
+ moveWindow(id, translation, windowManager, targetSize.value, position);
133
147
  };
134
148
 
135
149
  const componentIdRef = ref(componentIds);