@vcmap/ui 5.0.0-rc.10 → 5.0.0-rc.13

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 (165) hide show
  1. package/README.md +12 -5
  2. package/build/build.js +6 -3
  3. package/build/buildHelpers.js +12 -4
  4. package/build/buildPreview.js +7 -0
  5. package/build/getPluginProxies.js +4 -0
  6. package/config/aerowest.config.json +13 -3
  7. package/config/base.config.json +398 -219
  8. package/config/codes.config.json +397 -0
  9. package/config/dev.config.json +375 -1
  10. package/config/graphFeatureInfo.config.json +100 -0
  11. package/config/www.config.json +1232 -0
  12. package/dist/assets/{cesium.eb5667.js → cesium.21663e.js} +0 -0
  13. package/dist/assets/cesium.js +1 -1
  14. package/dist/assets/core.63242d.js +4 -0
  15. package/dist/assets/core.js +1 -1
  16. package/dist/assets/font/OFL.txt +93 -0
  17. package/dist/assets/font/TitilliumWeb-Regular.woff2 +0 -0
  18. package/dist/assets/{index.4ccd4433.js → index.44b91cfe.js} +1 -1
  19. package/dist/assets/{ol.ef03b1.js → ol.88ba9d.js} +0 -0
  20. package/dist/assets/ol.js +1 -1
  21. package/dist/assets/ui.3c2933.css +1 -0
  22. package/dist/assets/ui.3c2933.js +71 -0
  23. package/dist/assets/ui.js +1 -1
  24. package/dist/assets/vue.c897fc.js +9 -0
  25. package/dist/assets/vue.js +2 -1
  26. package/dist/assets/{vuetify.401a29.css → vuetify.147c3a.css} +1 -1
  27. package/dist/assets/{vuetify.401a29.js → vuetify.147c3a.js} +72 -72
  28. package/dist/assets/vuetify.js +2 -2
  29. package/dist/index.html +1 -5
  30. package/index.js +39 -5
  31. package/lib/vue.js +1 -0
  32. package/map.config.json +15 -6
  33. package/package.json +17 -8
  34. package/plugins/@vcmap/create-link/fallbackCreateLink.vue +71 -0
  35. package/plugins/@vcmap/create-link/index.js +83 -0
  36. package/plugins/@vcmap/create-link/package.json +6 -0
  37. package/plugins/@vcmap/pluginExample/index.js +2 -2
  38. package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +20 -3
  39. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +1 -1
  40. package/plugins/@vcmap/project-selector/index.js +1 -1
  41. package/plugins/@vcmap/project-selector/package.json +1 -2
  42. package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +1 -1
  43. package/plugins/@vcmap/theme-changer/index.js +1 -1
  44. package/plugins/@vcmap/theme-changer/package.json +1 -2
  45. package/plugins/categoryTest/Categories.vue +89 -1
  46. package/plugins/categoryTest/Category.vue +1 -1
  47. package/plugins/example/index.js +10 -23
  48. package/plugins/simple-graph/README.md +51 -0
  49. package/plugins/simple-graph/SimpleGraphComponent.vue +70 -0
  50. package/plugins/simple-graph/index.js +17 -0
  51. package/plugins/simple-graph/package.json +11 -0
  52. package/plugins/simple-graph/simpleGraphView.js +76 -0
  53. package/plugins/test/editor.vue +1 -1
  54. package/plugins/test/index.js +76 -9
  55. package/plugins/test/toolbox-data.js +82 -57
  56. package/plugins/test/windowManagerExample.vue +1 -1
  57. package/src/actions/stateRefAction.js +2 -2
  58. package/src/actions/styleSelector.vue +1 -1
  59. package/src/application/Navbar.vue +13 -2
  60. package/src/application/VcsApp.vue +301 -116
  61. package/src/application/VcsMap.vue +1 -1
  62. package/src/application/VcsSettings.vue +1 -1
  63. package/src/application/vcsAppWrapper.vue +1 -0
  64. package/src/assets/font/OFL.txt +93 -0
  65. package/src/assets/font/TitilliumWeb-Regular.woff2 +0 -0
  66. package/src/components/form-inputs-controls/VcsCheckbox.vue +13 -0
  67. package/src/components/form-inputs-controls/VcsColorPicker.vue +1 -1
  68. package/src/components/form-inputs-controls/VcsRadio.vue +123 -0
  69. package/src/components/form-output/VcsFormattedNumber.vue +1 -1
  70. package/src/components/lists/VcsActionList.vue +22 -7
  71. package/src/components/lists/VcsTreeview.vue +4 -4
  72. package/src/components/lists/VcsTreeviewLeaf.vue +10 -3
  73. package/src/components/lists/VcsTreeviewSearchbar.vue +1 -2
  74. package/src/components/tables/VcsTable.vue +245 -0
  75. package/src/contentTree/LayerTree.vue +1 -1
  76. package/src/contentTree/contentTreeCollection.js +4 -4
  77. package/src/contentTree/contentTreeItem.js +9 -9
  78. package/src/contentTree/groupContentTreeItem.js +1 -1
  79. package/src/contentTree/layerContentTreeItem.js +15 -1
  80. package/src/contentTree/layerGroupContentTreeItem.js +21 -1
  81. package/src/contentTree/nodeContentTreeItem.js +1 -1
  82. package/src/featureInfo/AddressBalloonComponent.vue +47 -0
  83. package/src/featureInfo/BalloonComponent.vue +140 -0
  84. package/src/featureInfo/abstractFeatureInfoView.js +313 -0
  85. package/src/featureInfo/addressBalloonFeatureInfoView.js +118 -0
  86. package/src/featureInfo/balloonFeatureInfoView.js +151 -0
  87. package/src/featureInfo/balloonHelper.js +132 -0
  88. package/src/featureInfo/featureInfo.js +457 -0
  89. package/src/featureInfo/featureInfoInteraction.js +42 -0
  90. package/src/featureInfo/iframeFeatureInfoView.js +95 -0
  91. package/src/featureInfo/tableFeatureInfoView.js +106 -0
  92. package/src/i18n/de.js +26 -0
  93. package/src/i18n/en.js +26 -0
  94. package/src/i18n/i18nCollection.js +17 -0
  95. package/src/icons/+all.js +80 -0
  96. package/src/icons/ClippingHorizontalIcon.vue +7 -0
  97. package/src/icons/ClippingIcon.vue +7 -0
  98. package/src/icons/ClippingVerticalIcon.vue +7 -0
  99. package/src/icons/ColorPickerIcon.vue +7 -0
  100. package/src/icons/ComponentsIcon.vue +2 -2
  101. package/src/icons/DimensionsHouseIcon.vue +11 -9
  102. package/src/icons/EditIcon.vue +7 -0
  103. package/src/icons/GlobalTerrainIcon.vue +9 -0
  104. package/src/icons/GroundIcon.vue +18 -0
  105. package/src/icons/HideIcon.vue +12 -0
  106. package/src/icons/LogoutIcon.vue +7 -0
  107. package/src/icons/ObjectAttributeIcon.vue +2 -13
  108. package/src/icons/PedestrianIcon.vue +2 -3
  109. package/src/icons/PenIcon.vue +2 -9
  110. package/src/icons/PoiIcon.vue +5 -2
  111. package/src/icons/PointSelectIcon.vue +4 -2
  112. package/src/icons/QueryIcon.vue +6 -7
  113. package/src/icons/ScreenshotIcon.vue +16 -0
  114. package/src/icons/ShareIcon.vue +4 -16
  115. package/src/icons/SkipNextIcon.vue +3 -1
  116. package/src/icons/TerrainBoxIcon.vue +9 -0
  117. package/src/icons/ToolsIcon.vue +4 -30
  118. package/src/icons/UploadIcon.vue +2 -9
  119. package/src/icons/UserProfileIcon.vue +7 -0
  120. package/src/icons/UserShareIcon.vue +7 -0
  121. package/src/icons/VideoRecorderIcon.vue +5 -9
  122. package/src/icons/ViewpointFlightIcon.vue +11 -0
  123. package/src/icons/ViewpointIcon.vue +11 -0
  124. package/src/icons/Viewshed360Icon.vue +7 -0
  125. package/src/icons/ViewshedConeIcon.vue +7 -0
  126. package/src/icons/ViewshedIcon.vue +7 -0
  127. package/src/icons/WallIcon.vue +4 -9
  128. package/src/legend/legendHelper.js +193 -0
  129. package/src/legend/styleLegendItem.vue +129 -0
  130. package/src/legend/vcsLegend.vue +92 -0
  131. package/src/manager/buttonManager.js +7 -12
  132. package/src/manager/categoryManager/ComponentsManager.vue +30 -0
  133. package/src/manager/categoryManager/categoryManager.js +500 -0
  134. package/src/manager/contextMenu/contextMenuComponent.vue +43 -0
  135. package/src/manager/contextMenu/contextMenuInteraction.js +42 -0
  136. package/src/manager/contextMenu/contextMenuManager.js +197 -0
  137. package/src/manager/navbarManager.js +9 -9
  138. package/src/manager/toolbox/GroupToolboxComponent.vue +118 -0
  139. package/src/manager/toolbox/SelectToolboxComponent.vue +128 -0
  140. package/src/manager/toolbox/ToolboxManager.vue +116 -98
  141. package/src/manager/toolbox/toolboxManager.js +235 -86
  142. package/src/manager/window/WindowComponent.vue +1 -1
  143. package/src/manager/window/WindowManager.vue +5 -3
  144. package/src/manager/window/windowManager.js +118 -14
  145. package/src/navigation/mapNavigation.vue +3 -5
  146. package/src/navigation/overviewMap.js +28 -5
  147. package/src/navigation/vcsCompass.vue +1 -1
  148. package/src/pluginHelper.js +42 -10
  149. package/src/setup.js +0 -2
  150. package/src/state.js +256 -0
  151. package/src/styles/_theming.scss +0 -5
  152. package/src/styles/variables.scss +7 -0
  153. package/src/styles/vcsFont.scss +17 -0
  154. package/src/uiConfig.js +79 -0
  155. package/src/vcsUiApp.js +213 -22
  156. package/src/vuePlugins/vuetify.js +14 -4
  157. package/config/berlin.config.json +0 -510
  158. package/dist/assets/core.216494.js +0 -4
  159. package/dist/assets/ui.99a1a7.css +0 -1
  160. package/dist/assets/ui.99a1a7.js +0 -70
  161. package/dist/assets/vue-composition-api.c5aca1.js +0 -14
  162. package/dist/assets/vue-composition-api.js +0 -2
  163. package/dist/assets/vue.762edd.js +0 -9
  164. package/lib/vue-composition-api.js +0 -2
  165. package/src/manager/toolbox/ToolboxGroupComponent.vue +0 -128
@@ -1,23 +1,36 @@
1
- <script src="../../vcsUiApp.js"></script>
2
1
  <template>
3
2
  <v-toolbar
4
- v-if="toolboxOpen && actionGroups.length > 0 && $vuetify.breakpoint.mdAndUp"
3
+ v-if="toolboxOpen && orderedGroups.length > 0 && $vuetify.breakpoint.mdAndUp"
4
+ class="vcs-toolbox toolbar__secondary mx-auto v-sheet marginToTop"
5
+ :class="{ 'rounded-b': !open }"
6
+ :height="40"
7
+ width="fit-content"
5
8
  dense
6
- class="vcs-toolbox toolbar__secondary rounded-b mx-auto v-sheet marginToTop"
7
- :width="width"
8
9
  >
9
10
  <v-toolbar-items class="w-full">
10
- <div class="d-flex align-center justify-space-between w-full">
11
- <ToolboxGroupComponent
12
- v-for="(group, idx) in actionGroups"
13
- :key="group.id"
14
- :group-icon="group.icon"
15
- :group-title="group.title"
16
- :actions="group.actions"
17
- class="px-2"
18
- :active="groupId === group.id"
19
- :position="getPosition(idx)"
20
- @click="toggleGroup(group.id)"
11
+ <div
12
+ class="d-flex align-center justify-space-between w-full mx-1"
13
+ v-for="group in orderedGroups"
14
+ :key="group.id"
15
+ >
16
+ <ToolboxActionGroup
17
+ v-if="group.type === ToolboxType.GROUP"
18
+ :group="group"
19
+ @toggle="(groupOpen) => open = groupOpen"
20
+ />
21
+ <ToolboxActionSelect
22
+ v-else-if="group.type === ToolboxType.SELECT"
23
+ :group="group"
24
+ @toggle="(selectOpen) => open = selectOpen"
25
+ />
26
+ <VcsButton
27
+ v-else
28
+ :tooltip="group.action.title"
29
+ :icon="group.action.icon"
30
+ :active="group.action.active"
31
+ @click.stop="group.action.callback($event)"
32
+ v-bind="{...$attrs}"
33
+ large
21
34
  />
22
35
  </div>
23
36
  </v-toolbar-items>
@@ -40,71 +53,95 @@
40
53
  &.theme--light.v-toolbar.v-sheet {
41
54
  background-color: #ffffffda;
42
55
  }
56
+ &.theme--dark.v-toolbar.v-sheet {
57
+ background-color: #000000da;
58
+ }
43
59
  }
44
60
 
45
61
  .marginToTop {
46
62
  margin-top: 2px;
47
63
  }
64
+
65
+ .v-toolbar__items > div{
66
+ gap: 8px;
67
+ width: fit-content;
68
+ display: inline-block;
69
+ }
48
70
  </style>
49
71
 
50
72
  <script>
73
+ import { inject, ref, computed, watch, onUnmounted } from 'vue';
74
+ import { ButtonLocation, vcsAppSymbol } from '@vcmap/ui';
75
+ import { getComponentsByOrder, ToolboxType } from './toolboxManager.js';
76
+ import ToolboxActionSelect from './SelectToolboxComponent.vue';
77
+ import ToolboxActionGroup from './GroupToolboxComponent.vue';
78
+ import VcsButton from '../../components/buttons/VcsButton.vue';
51
79
 
52
- import { inject, ref, computed, watch, onUnmounted } from '@vue/composition-api';
53
- import ToolboxGroupComponent from './ToolboxGroupComponent.vue';
54
- import {ButtonLocation, vcsAppSymbol} from '@vcmap/ui';
80
+ /**
81
+ * @typedef {Object} ToolboxButtonGroup
82
+ * @property {string} id
83
+ * @property {string} type
84
+ * @property {string} icon
85
+ * @property {string} title
86
+ * @property {Array<ButtonComponent>} buttons
87
+ * @property {string} [selected]
88
+ * @property {function(index:number):void} [selectCb]
89
+ */
55
90
 
56
- /**
57
- * @typedef {Object} ActionGroup
58
- * @property {string} id
59
- * @property {string} icon
60
- * @property {string} title
61
- * @property {Array<VcsAction>} actions
62
- */
91
+ /**
92
+ * @description ToolboxManager component rendering toolbox different kind of Toolbox buttons:
93
+ * - Single toggle button
94
+ * - Select drop down button to select an item, selected button is rendered besides
95
+ * - Group drop down button showing a group of toggle buttons
96
+ * Watches for changes in toolbox components.
97
+ * Adds Toolbox button in Navbar, if components are available or removes it otherwise.
98
+ * @vue-computed {Array<ToolboxButtonGroup>} groups - Array of group components
99
+ * @vue-computed {Array<ToolboxButtonGroup>} orderedGroups - Array of group components sorted by owner
100
+ */
101
+ export default {
102
+ name: 'VcsToolboxManager',
103
+ components: {
104
+ ToolboxActionSelect,
105
+ ToolboxActionGroup,
106
+ VcsButton,
107
+ },
108
+ setup() {
109
+ const app = inject('vcsApp');
63
110
 
64
- /**
65
- * @description ToolboxManager component rendering toolbox using {@link ToolboxGroupComponent}.
66
- * @vue-computed {Array<ActionGroup>} actionGroups - Array of group components
67
- * @vue-computed {number} width - width of toolbox depending on number of groups
68
- */
69
- export default {
70
- name: 'VcsToolboxManager',
71
- components: {
72
- ToolboxGroupComponent,
73
- },
74
- setup() {
75
- const app = inject('vcsApp');
111
+ const toolboxComponentIds = ref(app.toolboxManager.componentIds);
112
+ const groups = computed(() => {
113
+ return toolboxComponentIds.value.map(id => app.toolboxManager.get(id));
114
+ });
76
115
 
77
- const toolboxComponentIds = ref(app.toolboxManager.componentIds);
78
- const actionGroups = computed(() => {
79
- const groups = toolboxComponentIds.value.map(id => app.toolboxManager.get(id));
80
- return groups
81
- .map((g) => {
82
- const buttonIds = ref(g.buttonManager.componentIds);
83
- return {
84
- id: g.id,
85
- icon: g.icon,
86
- title: g.title,
87
- actions: buttonIds.value.map(id => g.buttonManager.get(id).action),
88
- };
89
- })
90
- .filter(g => g.actions.length > 0);
91
- });
116
+ /**
117
+ * To be rendered in Toolbox components must meet certain conditions:
118
+ * - SingleToolboxComponent: no further conditions
119
+ * - SelectToolboxComponent: must have at least two tools
120
+ * - GroupToolboxComponent: must have at least one member (button)
121
+ * @param {SingleToolboxComponent|SelectToolboxComponent|GroupToolboxComponent} c
122
+ * @returns {boolean}
123
+ */
124
+ function filterFunc(c) {
125
+ return c.type === ToolboxType.SINGLE ||
126
+ c?.action?.tools?.length > 1 ||
127
+ c.buttonManager?.componentIds?.length > 0;
128
+ }
129
+ const orderedGroups = computed(() => getComponentsByOrder(groups.value).filter(filterFunc));
92
130
 
93
- const toolboxOpen = ref(true);
94
- const toolboxToggleAction = {
95
- name: 'toolboxToggleAction',
96
- icon: '$vcsTools',
97
- title: 'Toolbox',
98
- active: true,
99
- callback() {
100
- this.active = !this.active;
101
- toolboxOpen.value = this.active;
102
- },
103
- };
131
+ const toolboxOpen = ref(true);
132
+ const toolboxToggleAction = {
133
+ name: 'toolboxToggleAction',
134
+ icon: '$vcsTools',
135
+ title: 'Toolbox',
136
+ active: true,
137
+ callback() {
138
+ this.active = !this.active;
139
+ toolboxOpen.value = this.active;
140
+ },
141
+ };
104
142
 
105
- const stopWatching = watch([actionGroups],
106
- ([actionGroups]) => {
107
- if (actionGroups.length > 0) {
143
+ function handleToolboxButton() {
144
+ if (groups.value.length > 0) {
108
145
  if (!app.navbarManager.has('toolbox')) {
109
146
  app.navbarManager.add(
110
147
  {
@@ -119,39 +156,20 @@ export default {
119
156
  app.navbarManager.remove('toolbox');
120
157
  }
121
158
  }
122
- );
123
-
124
- onUnmounted(() => {
125
- stopWatching();
126
- });
159
+ handleToolboxButton();
127
160
 
128
- // XXX can this solved by CSS to get rid of the hardcoded size and padding?
129
- const buttonSize = 54;
130
- const buttonPadding = 8;
131
- const size = buttonSize + (2 * buttonPadding);
132
- const width = computed(() => actionGroups.value.length * size);
161
+ const stopWatching = watch(groups, () => handleToolboxButton());
133
162
 
134
- /**
135
- * calculates relative x-position of a button from the left edge of toolbar
136
- * @param {number} idx
137
- * @returns {number}
138
- */
139
- const getPosition = (idx) => (size * (idx + 1)) - (size / 2);
163
+ onUnmounted(() => {
164
+ stopWatching();
165
+ });
140
166
 
141
- return {
142
- toolboxOpen,
143
- actionGroups,
144
- width,
145
- getPosition,
146
- groupId: null,
147
- toggleGroup(groupId) {
148
- if (this.groupId === groupId) {
149
- this.groupId = null;
150
- } else {
151
- this.groupId = groupId;
152
- }
153
- },
154
- };
155
- },
156
- };
167
+ return {
168
+ toolboxOpen,
169
+ orderedGroups,
170
+ ToolboxType,
171
+ open: ref(false),
172
+ };
173
+ },
174
+ };
157
175
  </script>
@@ -1,79 +1,186 @@
1
- /* eslint-disable import/prefer-default-export */
2
1
  import { VcsEvent } from '@vcmap/core';
3
- import { reactive } from '@vue/composition-api';
4
2
  import { check, checkMaybe } from '@vcsuite/check';
5
3
  import { v4 as uuidv4 } from 'uuid';
6
- import { ButtonManager } from '../buttonManager.js';
4
+ import { reactive } from 'vue';
5
+ import { vcsAppSymbol } from '../../pluginHelper.js';
6
+ import ButtonManager from '../buttonManager.js';
7
+ import { ActionPattern } from '../../components/lists/VcsActionList.vue';
7
8
 
8
9
  /**
9
- * @typedef ToolboxGroupComponentOptions
10
- * @property {string} [id] Optional ID, If not provided an uuid will be generated.
11
- * @property {string} [icon] Optional group icon, for dropdowns
12
- * @property {string} [title] Optional group title, for dropdowns
10
+ * Possible group types. Define behaviour of group:
11
+ * @property {number} SINGLE - SingleToolboxComponent with single toggle action rendered as VcsButton
12
+ * @property {number} SELECT - SelectToolboxComponent with one selected item of a list of items
13
+ * @property {number} GROUP - GroupToolboxComponent with multiple non-exclusive items rendered as VcsButton
14
+ * @enum {number}
13
15
  */
16
+ export const ToolboxType = {
17
+ SINGLE: 0,
18
+ SELECT: 1,
19
+ GROUP: 2,
20
+ };
14
21
 
15
22
  /**
16
- * @typedef ToolboxGroupComponent
23
+ * @typedef {Object} ToolboxComponentOptions
24
+ * @property {string} [id] - Optional ID, If not provided an uuid will be generated.
25
+ * @property {ToolboxType} type - Group type, defining the behaviour of the group
26
+ */
27
+
28
+ /**
29
+ * @typedef {ToolboxComponentOptions} SingleToolboxComponentOptions
30
+ * @property {VcsAction} action - An action of a single tool
31
+ */
32
+
33
+ /**
34
+ * @typedef {ToolboxComponentOptions} SelectToolboxComponentOptions
35
+ * @property {ToolboxSelectAction} action - An action determining the behaviour of the select group
36
+ */
37
+
38
+ /**
39
+ * @typedef {ToolboxComponentOptions} GroupToolboxComponentOptions
40
+ * @property {string} icon - Group icon
41
+ * @property {string} [title] - Optional group title, for dropdown
42
+ */
43
+
44
+ /**
45
+ * @typedef {Object} ToolboxComponent
17
46
  * @property {string} id
18
- * @property {string} title
47
+ * @property {ToolboxType} type - Group type, defining the behaviour of the group
48
+ * @property {string|vcsAppSymbol} owner
49
+ */
50
+
51
+ /**
52
+ * @typedef {ToolboxComponent} SingleToolboxComponent
53
+ * @property {VcsAction} action
54
+ */
55
+
56
+ /**
57
+ * @typedef {ToolboxComponent} GroupToolboxComponent
58
+ * @property {string|undefined} icon
59
+ * @property {string|undefined} title
19
60
  * @property {ButtonManager} buttonManager
20
61
  */
21
62
 
63
+ /**
64
+ * @typedef {ToolboxComponent} SelectToolboxComponent
65
+ * @property {ToolboxSelectAction} action
66
+ */
67
+
68
+ /**
69
+ * @typedef {VcsAction} ToolboxSelectAction
70
+ * @property {function(index:number):void} selected - A callback determining the select behavior of the group. Should set the currentIndex.
71
+ * @property {Array<ToolboxSelectItem>} tools - A list of exclusive tools belonging to the group
72
+ * @property {number} currentIndex - Index of the current item
73
+ */
74
+
75
+ /**
76
+ * @typedef {Object} ToolboxSelectItem
77
+ * @property {string} name
78
+ * @property {string} [title]
79
+ * @property {string} icon
80
+ */
81
+
22
82
  /**
23
83
  * Default groups predefining icon and title of the group
24
- * @type {Array<ToolboxGroupComponentOptions>}
84
+ * @type {Array<ToolboxComponentOptions>}
25
85
  */
26
86
  const defaultGroups = [
27
- {
28
- id: 'select',
29
- icon: '$vcsPen',
30
- title: 'select',
31
- },
32
- {
33
- id: 'measurement',
34
- icon: '$vcsDimensionsHouse',
35
- title: 'measurement',
36
- },
37
87
  {
38
88
  id: 'flight',
89
+ type: ToolboxType.GROUP,
39
90
  icon: '$vcsVideoRecorder',
40
- title: 'flight',
91
+ title: 'toolbox.flight',
92
+ },
93
+ {
94
+ id: 'miscellaneous',
95
+ type: ToolboxType.GROUP,
96
+ icon: 'mdi-dots-grid',
97
+ title: 'toolbox.miscellaneous',
41
98
  },
42
99
  ];
43
100
 
44
101
  /**
45
- * Requests default groups for a toolboxManager.
102
+ * Default order of toolboxComponents shown in the toolbox
103
+ * @type {string[]}
104
+ */
105
+ const defaultOrder = ['featureInfo', 'flight'];
106
+
107
+ /**
108
+ * sorts by owner and optionally plugin order
109
+ * If both components are owned by vcsApp, defaultOrder is used to compare
110
+ * @param {ToolboxComponent|ButtonComponent} compA
111
+ * @param {ToolboxComponent|ButtonComponent} compB
112
+ * @param {string[]} [order] order of owners to sort by
113
+ * @returns {number}
114
+ */
115
+ export function sortByOwner(compA, compB, order = []) {
116
+ const sorted = [vcsAppSymbol, ...order];
117
+ let indexA = sorted.indexOf(compA.owner);
118
+ let indexB = sorted.indexOf(compB.owner);
119
+
120
+ if (compA.owner === vcsAppSymbol && compB.owner === vcsAppSymbol) {
121
+ indexA = defaultOrder.indexOf(compA.id);
122
+ indexB = defaultOrder.indexOf(compB.id);
123
+ }
124
+
125
+ if (indexA === indexB) {
126
+ return 0;
127
+ }
128
+
129
+ if (indexA === -1) {
130
+ return 1;
131
+ }
132
+
133
+ if (indexB === -1) {
134
+ return -1;
135
+ }
136
+ return indexA - indexB;
137
+ }
138
+
139
+ /**
140
+ * returns ToolboxComponents sorted by owner (or other sort function)
141
+ * @param {Array<ToolboxComponent|ButtonComponent>} components
142
+ * @param {string[]} [order] optional order to sort by (plugin names)
143
+ * @param {function(ownerA:string, ownerB:string, order: string[]):number} [compareFn=sortByOwner] Per default components are sorted by owner: app first, then plugins
144
+ * @returns {Array<ToolboxComponent|ButtonComponent>}
145
+ */
146
+ export function getComponentsByOrder(components, order = [], compareFn = sortByOwner) {
147
+ return [...components]
148
+ .sort((a, b) => compareFn(a, b, order));
149
+ }
150
+
151
+ /**
152
+ * Adds default groups for a toolboxManager.
46
153
  * Once requested, group id, icon and title are defined and cannot be changed or overwritten.
47
154
  * @param {ToolboxManager} toolboxManager
48
- * @param {Array<ToolboxGroupComponentOptions>} groups
155
+ * @param {Array<ToolboxComponentOptions>} groups
49
156
  */
50
157
  export function setupDefaultGroups(toolboxManager, groups = defaultGroups) {
51
- groups.forEach(({ id, icon, title }) => toolboxManager.requestGroup(id, icon, title));
158
+ groups.forEach(toolboxComponentOptions => toolboxManager.add(toolboxComponentOptions, vcsAppSymbol));
52
159
  }
53
160
 
54
161
  /**
55
162
  * @class ToolboxManager
56
- * @description Manages a set of Toolbox Groups
57
- * @implements VcsComponentManager<ToolboxGroupComponent,ToolboxGroupComponentOptions>
163
+ * @description Manages a set of Toolbox Components
164
+ * @implements VcsComponentManager<ToolboxComponent,ToolboxComponentOptions>
58
165
  */
59
- export class ToolboxManager {
166
+ class ToolboxManager {
60
167
  constructor() {
61
168
  /**
62
- * @type {import("@vcmap/core").VcsEvent<ToolboxGroupComponent>}
169
+ * @type {import("@vcmap/core").VcsEvent<ToolboxComponent>}
63
170
  */
64
171
  this.added = new VcsEvent();
65
172
  /**
66
- * @type {import("@vcmap/core").VcsEvent<ToolboxGroupComponent>}
173
+ * @type {import("@vcmap/core").VcsEvent<ToolboxComponent>}
67
174
  */
68
175
  this.removed = new VcsEvent();
69
176
  /**
70
177
  * reactive ordered array of ids,
71
178
  * @type {Array<string>}
72
179
  */
73
- this.componentIds = reactive([]);
180
+ this.componentIds = [];
74
181
 
75
182
  /**
76
- * @type {Map<string, ToolboxGroupComponent>}
183
+ * @type {Map<string, ToolboxComponent>}
77
184
  * @private
78
185
  */
79
186
  this._toolboxGroups = new Map();
@@ -81,7 +188,7 @@ export class ToolboxManager {
81
188
 
82
189
  /**
83
190
  * @param {string} id
84
- * @returns {ToolboxGroupComponent}
191
+ * @returns {ToolboxComponent}
85
192
  */
86
193
  get(id) {
87
194
  return this._toolboxGroups.get(id);
@@ -96,95 +203,135 @@ export class ToolboxManager {
96
203
  }
97
204
 
98
205
  /**
99
- * Toolbox groups should be static. Removing them can lead to undefined behavior.
206
+ * removes a ToolboxComponent, Component will not be rendered anymore and will be destroyed.
207
+ * Add ToolboxComponent again to show the component again
100
208
  * @param {string} id
101
209
  */
102
210
  remove(id) {
103
211
  check(id, String);
104
- const toolboxGroupComponent = this._toolboxGroups.get(id);
105
- if (toolboxGroupComponent) {
212
+ const toolboxComponent = this._toolboxGroups.get(id);
213
+ if (toolboxComponent) {
106
214
  const index = this.componentIds.indexOf(id);
107
215
  this.componentIds.splice(index, 1);
108
216
  this._toolboxGroups.delete(id);
109
- this.removed.raiseEvent(toolboxGroupComponent);
110
- toolboxGroupComponent.buttonManager.destroy();
217
+ this.removed.raiseEvent(toolboxComponent);
218
+ if (toolboxComponent.buttonManager) {
219
+ toolboxComponent.buttonManager.destroy();
220
+ }
111
221
  }
112
222
  }
113
223
 
114
224
  /**
115
- * Do not call add directly. Use requestGroup for adding toolbox groups.
116
- * @param {ToolboxGroupComponentOptions} toolboxGroupComponentOptions
117
- * @throws {Error} if a buttonComponent with the same ID has already been added
118
- * @returns {ToolboxGroupComponent}
225
+ * adds a ToolboxComponent
226
+ * @param {SingleToolboxComponentOptions|SelectToolboxComponentOptions|GroupToolboxComponentOptions} toolboxComponentOptions
227
+ * @param {string|symbol} owner pluginName or vcsAppSymbol
228
+ * @throws {Error} if a toolboxComponent with the same ID has already been added
229
+ * @returns {SingleToolboxComponent|SelectToolboxComponent|GroupToolboxComponent}
119
230
  */
120
- add(toolboxGroupComponentOptions) {
121
- checkMaybe(toolboxGroupComponentOptions.id, String);
122
- checkMaybe(toolboxGroupComponentOptions.icon, String);
123
- checkMaybe(toolboxGroupComponentOptions.title, String);
231
+ add(toolboxComponentOptions, owner) {
232
+ checkMaybe(toolboxComponentOptions.id, String);
233
+ check(toolboxComponentOptions.type, Object.values(ToolboxType));
234
+ check(owner, [String, vcsAppSymbol]);
124
235
 
125
- if (toolboxGroupComponentOptions.id && this.has(toolboxGroupComponentOptions.id)) {
126
- throw new Error(`A toolGroup with id ${toolboxGroupComponentOptions.id} has already been registered.`);
236
+ if (toolboxComponentOptions.id && this.has(toolboxComponentOptions.id)) {
237
+ throw new Error(`A toolGroup with id ${toolboxComponentOptions.id} has already been registered.`);
127
238
  }
128
- const id = toolboxGroupComponentOptions.id || uuidv4();
129
- const icon = toolboxGroupComponentOptions.icon || undefined;
130
- const title = toolboxGroupComponentOptions.title || undefined;
131
- const buttonManager = new ButtonManager();
239
+ const id = toolboxComponentOptions.id || uuidv4();
240
+ const { type } = toolboxComponentOptions;
132
241
 
133
242
  /**
134
- * @type {ToolboxGroupComponent}
243
+ * @type {ToolboxComponent}
135
244
  */
136
- const toolboxGroupComponent = {
245
+ let toolboxComponent = {
137
246
  get id() {
138
247
  return id;
139
248
  },
140
- get icon() {
141
- return icon;
249
+ get type() {
250
+ return type;
142
251
  },
143
- get title() {
144
- return title;
145
- },
146
- get buttonManager() {
147
- return buttonManager;
252
+ get owner() {
253
+ return owner;
148
254
  },
149
255
  };
150
256
 
151
- this._toolboxGroups.set(id, toolboxGroupComponent);
152
- this.componentIds.push(id);
153
- this.added.raiseEvent(toolboxGroupComponent);
154
- return toolboxGroupComponent;
155
- }
156
-
157
- /**
158
- * Returns an existing group or creates a new group. Add toolbox groups with this API.
159
- * @param {string} id
160
- * @param {string} [icon='mdi-select-group']
161
- * @param {string} [title='defaultGroup']
162
- * @returns {ToolboxGroupComponent}
163
- */
164
- requestGroup(id, icon = 'mdi-select-group', title = 'defaultGroup') {
165
- check(id, String);
166
- checkMaybe(icon, String);
167
- checkMaybe(title, String);
168
-
169
- if (this.has(id)) {
170
- return this.get(id);
257
+ if (type === ToolboxType.SINGLE) {
258
+ check(toolboxComponentOptions.action, ActionPattern);
259
+ /**
260
+ * @type {SingleToolboxComponent}
261
+ */
262
+ toolboxComponent = {
263
+ ...toolboxComponent,
264
+ get action() {
265
+ return reactive(toolboxComponentOptions.action);
266
+ },
267
+ };
268
+ } else if (type === ToolboxType.SELECT) {
269
+ check(toolboxComponentOptions.action, {
270
+ ...ActionPattern,
271
+ selected: Function,
272
+ currentIndex: Number,
273
+ tools: [{
274
+ name: String,
275
+ title: [undefined, String],
276
+ icon: String,
277
+ }],
278
+ });
279
+ /**
280
+ * @type {SelectToolboxComponent}
281
+ */
282
+ toolboxComponent = {
283
+ ...toolboxComponent,
284
+ get action() {
285
+ return reactive(toolboxComponentOptions.action);
286
+ },
287
+ };
171
288
  } else {
172
- return this.add({ id, icon, title });
289
+ check(toolboxComponentOptions.icon, String);
290
+ checkMaybe(toolboxComponentOptions.title, String);
291
+ const { icon, title = undefined } = toolboxComponentOptions;
292
+ const buttonManager = new ButtonManager();
293
+ /**
294
+ * @type {GroupToolboxComponent}
295
+ */
296
+ toolboxComponent = {
297
+ ...toolboxComponent,
298
+ get icon() {
299
+ return icon;
300
+ },
301
+ get title() {
302
+ return title;
303
+ },
304
+ get buttonManager() {
305
+ return buttonManager;
306
+ },
307
+ };
173
308
  }
309
+
310
+ this._toolboxGroups.set(toolboxComponent.id, toolboxComponent);
311
+ this.componentIds.push(toolboxComponent.id);
312
+ this.added.raiseEvent(toolboxComponent);
313
+ return toolboxComponent;
174
314
  }
175
315
 
176
316
  /**
177
- * removes all {@link ButtonComponent}s of a specific owner and fires removed Events
317
+ * removes all {@link ToolboxComponent}s of a specific owner and fires removed Events
178
318
  * @param {string|vcsAppSymbol} owner
179
319
  */
180
320
  removeOwner(owner) {
181
- this.componentIds.forEach((id) => {
182
- this.get(id).buttonManager.removeOwner(owner);
321
+ const componentIds = [...this.componentIds];
322
+ componentIds.forEach((id) => {
323
+ const toolboxComponent = this.get(id);
324
+ if (toolboxComponent.buttonManager) {
325
+ toolboxComponent.buttonManager.removeOwner(owner);
326
+ }
327
+ if (owner === toolboxComponent.owner) {
328
+ this.remove(id);
329
+ }
183
330
  });
184
331
  }
185
332
 
186
333
  /**
187
- * removes all buttonComponents and fires removed Events
334
+ * removes all toolboxComponents and fires removed Events
188
335
  */
189
336
  clear() {
190
337
  const componentIds = [...this.componentIds];
@@ -192,7 +339,7 @@ export class ToolboxManager {
192
339
  }
193
340
 
194
341
  /**
195
- * destroys the ButtonManager;
342
+ * destroys the ToolboxManager;
196
343
  */
197
344
  destroy() {
198
345
  this.added.destroy();
@@ -202,3 +349,5 @@ export class ToolboxManager {
202
349
  this._toolboxGroups.clear();
203
350
  }
204
351
  }
352
+
353
+ export default ToolboxManager;