@vcmap/ui 5.0.0-rc.22 → 5.0.0-rc.23

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 (91) hide show
  1. package/README.md +2 -2
  2. package/app.config.json +5 -0
  3. package/build/buildPreview.js +2 -2
  4. package/config/aerowest.config.json +2 -0
  5. package/config/base.config.json +1 -0
  6. package/config/codes.config.json +2 -0
  7. package/config/dev.config.json +6 -0
  8. package/config/graphFeatureInfo.config.json +3 -1
  9. package/config/projects.config.json +27 -0
  10. package/config/www.config.json +2 -0
  11. package/dist/assets/cesium.js +1 -1
  12. package/dist/assets/{core.a66593.js → core.9342a1.js} +7804 -5352
  13. package/dist/assets/core.js +1 -1
  14. package/dist/assets/index.fd041928.js +1 -0
  15. package/dist/assets/ol.js +1 -1
  16. package/dist/assets/ui.c27597.css +5 -0
  17. package/dist/assets/{ui.d760e4.js → ui.c27597.js} +5055 -4694
  18. package/dist/assets/ui.js +1 -1
  19. package/dist/assets/vue.js +2 -2
  20. package/dist/assets/{vuetify.427322.js → vuetify.2f1432.js} +1 -1
  21. package/dist/assets/vuetify.js +2 -2
  22. package/dist/index.html +1 -1
  23. package/index.js +5 -2
  24. package/package.json +3 -3
  25. package/plugins/@vcmap/project-selector/{ContextsListComponent.vue → ModulesListComponent.vue} +10 -10
  26. package/plugins/@vcmap/project-selector/ProjectSelectorComponent.vue +15 -15
  27. package/plugins/@vcmap/project-selector/README.md +15 -21
  28. package/plugins/@vcmap/project-selector/config.json +3 -3
  29. package/plugins/@vcmap/project-selector/de.json +3 -0
  30. package/plugins/@vcmap/project-selector/en.json +3 -0
  31. package/plugins/@vcmap/project-selector/index.js +76 -101
  32. package/plugins/@vcmap/simple-graph/index.js +1 -1
  33. package/plugins/@vcmap-show-case/category-tester/Categories.vue +2 -2
  34. package/plugins/@vcmap-show-case/category-tester/Category.vue +1 -4
  35. package/plugins/@vcmap-show-case/config-editor/editor.vue +14 -14
  36. package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +18 -1
  37. package/plugins/@vcmap-show-case/form-inputs-example/index.js +1 -0
  38. package/plugins/@vcmap-show-case/table-example/DataTableExample.vue +202 -0
  39. package/plugins/@vcmap-show-case/table-example/README.md +3 -0
  40. package/plugins/@vcmap-show-case/table-example/index.js +47 -0
  41. package/plugins/@vcmap-show-case/table-example/package.json +5 -0
  42. package/src/actions/actionHelper.js +16 -27
  43. package/src/actions/styleSelector.vue +26 -19
  44. package/src/components/form-inputs-controls/VcsDatePicker.vue +111 -0
  45. package/src/components/form-inputs-controls/VcsTextField.vue +18 -7
  46. package/src/components/form-inputs-controls/VcsWizard.vue +3 -1
  47. package/src/components/icons/CheckboxCheckedIcon.vue +1 -1
  48. package/src/components/icons/LegendIcon.vue +10 -60
  49. package/src/components/lists/VcsList.vue +25 -6
  50. package/src/components/tables/VcsDataTable.vue +386 -0
  51. package/src/components/tables/VcsTable.vue +33 -278
  52. package/src/contentTree/contentTreeCollection.js +1 -1
  53. package/src/contentTree/layerContentTreeItem.js +3 -0
  54. package/src/downloadHelper.js +49 -0
  55. package/src/featureInfo/BalloonComponent.vue +9 -8
  56. package/src/featureInfo/abstractFeatureInfoView.js +1 -1
  57. package/src/featureInfo/featureInfo.js +3 -3
  58. package/src/i18n/de.js +8 -0
  59. package/src/i18n/en.js +8 -0
  60. package/src/i18n/i18nCollection.js +22 -22
  61. package/src/init.js +90 -7
  62. package/src/manager/categoryManager/CategoryComponent.vue +56 -47
  63. package/src/manager/categoryManager/CategoryManager.vue +23 -10
  64. package/src/manager/categoryManager/categoryManager.js +11 -11
  65. package/src/manager/navbarManager.js +18 -0
  66. package/src/manager/window/WindowComponent.vue +10 -15
  67. package/src/manager/window/WindowComponentHeader.vue +4 -2
  68. package/src/manager/window/WindowManager.vue +14 -15
  69. package/src/manager/window/windowHelper.js +1 -1
  70. package/src/manager/window/windowManager.js +18 -7
  71. package/src/navigation/mapNavCompass.vue +1 -1
  72. package/src/navigation/mapNavigation.vue +6 -6
  73. package/src/navigation/obliqueRotation.vue +36 -13
  74. package/src/navigation/orientationToolsButton.vue +0 -1
  75. package/src/navigation/overviewMap.js +5 -5
  76. package/src/navigation/vcsZoomButton.vue +37 -11
  77. package/src/pluginHelper.js +20 -0
  78. package/src/search/search.js +12 -3
  79. package/src/search/searchComponent.vue +15 -0
  80. package/src/state.js +6 -6
  81. package/src/uiConfig.js +3 -3
  82. package/src/vcsUiApp.js +44 -40
  83. package/src/vuePlugins/i18n.js +1 -0
  84. package/start.js +8 -2
  85. package/dist/assets/index.8b833ead.js +0 -1
  86. package/dist/assets/ui.d760e4.css +0 -5
  87. package/map.config.json +0 -44
  88. /package/dist/assets/{cesium.88cffd.js → cesium.166f91.js} +0 -0
  89. /package/dist/assets/{ol.d4539f.js → ol.d2cba3.js} +0 -0
  90. /package/dist/assets/{vue.db5102.js → vue.5d00e9.js} +0 -0
  91. /package/dist/assets/{vuetify.427322.css → vuetify.2f1432.css} +0 -0
@@ -1,5 +1,5 @@
1
1
  // eslint-disable-next-line max-classes-per-file
2
- import { contextIdSymbol, IndexedCollection } from '@vcmap/core';
2
+ import { moduleIdSymbol, IndexedCollection } from '@vcmap/core';
3
3
  import { getLogger } from '@vcsuite/logger';
4
4
 
5
5
  /**
@@ -51,59 +51,59 @@ export function mergeDeep(...sources) {
51
51
  */
52
52
  class I18nCollection extends IndexedCollection {
53
53
  /**
54
- * @param {function():string} getDynamicContextId - function to get the current dynamic context id
54
+ * @param {function():string} getDynamicModuleId - function to get the current dynamic module id
55
55
  */
56
- constructor(getDynamicContextId) {
56
+ constructor(getDynamicModuleId) {
57
57
  super(false);
58
58
  /**
59
59
  * @type {function(): string}
60
60
  * @private
61
61
  */
62
- this._getDynamicContextId = getDynamicContextId;
62
+ this._getDynamicModuleId = getDynamicModuleId;
63
63
  }
64
64
 
65
65
  /**
66
66
  * @inheritDoc
67
67
  */
68
68
  add(item) {
69
- if (!item[contextIdSymbol]) {
70
- item[contextIdSymbol] = this._getDynamicContextId();
69
+ if (!item[moduleIdSymbol]) {
70
+ item[moduleIdSymbol] = this._getDynamicModuleId();
71
71
  }
72
72
  super.add(item);
73
73
  }
74
74
 
75
75
  /**
76
76
  * @param {Array<Object>} configArray
77
- * @param {string} contextId
77
+ * @param {string} moduleId
78
78
  * @returns {Promise<void>}
79
79
  */
80
- async parseItems(configArray, contextId) {
80
+ async parseItems(configArray, moduleId) {
81
81
  if (Array.isArray(configArray)) {
82
82
  configArray.forEach((item) => {
83
- item[contextIdSymbol] = contextId;
83
+ item[moduleIdSymbol] = moduleId;
84
84
  this.add(item);
85
85
  });
86
86
  }
87
87
  }
88
88
 
89
89
  /**
90
- * @param {string} contextId
90
+ * @param {string} moduleId
91
91
  */
92
- async removeContext(contextId) {
92
+ async removeModule(moduleId) {
93
93
  [...this]
94
- .filter(item => item[contextIdSymbol] === contextId)
94
+ .filter(item => item[moduleIdSymbol] === moduleId)
95
95
  .forEach((item) => {
96
96
  this.remove(item);
97
97
  });
98
98
  }
99
99
 
100
100
  /**
101
- * @param {string} contextId
101
+ * @param {string} moduleId
102
102
  * @returns {Array<Object>}
103
103
  */
104
- serializeContext(contextId) {
104
+ serializeModule(moduleId) {
105
105
  return [...this]
106
- .filter(item => item[contextIdSymbol] === contextId)
106
+ .filter(item => item[moduleIdSymbol] === moduleId)
107
107
  .filter(item => !item[i18nPluginSymbol])
108
108
  .map(item => JSON.parse(JSON.stringify(item)));
109
109
  }
@@ -112,12 +112,12 @@ class I18nCollection extends IndexedCollection {
112
112
  * This method adds plugin messages to the collection. It is no necessary to call this function
113
113
  * from within a plugin. Use the i18n property on your plugin.
114
114
  * @param {string} plugin Name of the plugin
115
- * @param {string} contextId
115
+ * @param {string} moduleId
116
116
  * @param {Object} messages
117
117
  */
118
- addPluginMessages(plugin, contextId, messages) {
118
+ addPluginMessages(plugin, moduleId, messages) {
119
119
  messages[i18nPluginSymbol] = plugin;
120
- messages[contextIdSymbol] = contextId;
120
+ messages[moduleIdSymbol] = moduleId;
121
121
  this.add(messages);
122
122
  }
123
123
 
@@ -125,11 +125,11 @@ class I18nCollection extends IndexedCollection {
125
125
  * This method removes plugin messages from the collection. It is no necessary to call this function
126
126
  * from within a plugin. Once your plugin is removed, the VcsUiApp will call this for you.
127
127
  * @param {string} pluginName
128
- * @param {string} contextId
128
+ * @param {string} moduleId
129
129
  */
130
- removePluginMessages(pluginName, contextId) {
130
+ removePluginMessages(pluginName, moduleId) {
131
131
  [...this]
132
- .filter(item => item[i18nPluginSymbol] === pluginName && item[contextIdSymbol] === contextId)
132
+ .filter(item => item[i18nPluginSymbol] === pluginName && item[moduleIdSymbol] === moduleId)
133
133
  .forEach((item) => {
134
134
  this.remove(item);
135
135
  });
@@ -147,7 +147,7 @@ class I18nCollection extends IndexedCollection {
147
147
  * @inheritDoc
148
148
  */
149
149
  destroy() {
150
- this._getDynamicContextId = null;
150
+ this._getDynamicModuleId = null;
151
151
  super.destroy();
152
152
  }
153
153
  }
package/src/init.js CHANGED
@@ -1,20 +1,49 @@
1
1
  import Vue from 'vue';
2
- import { check, checkMaybe } from '@vcsuite/check';
3
- import { Context } from '@vcmap/core';
2
+ import { check, checkMaybe, is } from '@vcsuite/check';
3
+ import { VcsModule } from '@vcmap/core';
4
4
  import VcsAppComponentWrapper from './application/vcsAppWrapper.vue';
5
5
  import { vuetify } from './vuePlugins/vuetify.js';
6
6
  import { createVueI18n, setupI18n } from './vuePlugins/i18n.js';
7
7
  import VcsUiApp from './vcsUiApp.js';
8
8
 
9
+ /**
10
+ * Base pattern to check VcsObjects
11
+ * @type {import("vcsuite/check").PatternFor<import("@vcmap/core").VcsObject>}
12
+ */
13
+ const VcsObjectPattern = {
14
+ type: String,
15
+ name: String,
16
+ };
17
+
18
+ /**
19
+ * Base pattern to check VcsUiAppConfig
20
+ * @type {import("vcsuite/check").PatternFor<VcsUiAppConfig>}
21
+ */
22
+ export const VcsUiAppConfigPattern = {
23
+ id: [undefined, String],
24
+ layers: [undefined, [VcsObjectPattern]],
25
+ maps: [undefined, [VcsObjectPattern]],
26
+ styles: [undefined, [VcsObjectPattern]],
27
+ viewpoints: [undefined, [VcsObjectPattern]],
28
+ startingViewpointName: [undefined, String],
29
+ startingMapName: [undefined, String],
30
+ projection: [undefined, Object],
31
+ categories: [undefined, [{ name: String, items: [Object] }]],
32
+ obliqueCollections: [undefined, [VcsObjectPattern]],
33
+ plugins: [undefined, [Object]],
34
+ contentTree: [undefined, [Object]],
35
+ uiConfig: [undefined, [Object]],
36
+ featureInfo: [undefined, [VcsObjectPattern]],
37
+ i18n: [undefined, [Object]],
38
+ };
39
+
9
40
  /**
10
41
  * creates and mounts a vcsApp
11
42
  * @param {string} mountTarget
12
- * @param {string=} configUrl optional config
13
43
  * @returns {Promise<VcsUiApp>}
14
44
  */
15
- export default async function initApp(mountTarget, configUrl) {
45
+ export default async function initApp(mountTarget) {
16
46
  check(mountTarget, String);
17
- checkMaybe(configUrl, String);
18
47
  const app = new VcsUiApp();
19
48
  const i18n = createVueI18n();
20
49
  new Vue({
@@ -28,11 +57,65 @@ export default async function initApp(mountTarget, configUrl) {
28
57
  }).$mount(mountTarget);
29
58
 
30
59
  setupI18n(app, i18n);
60
+ return app;
61
+ }
62
+
63
+ /**
64
+ * Initializes app with an optional single config
65
+ * @param {string} mountTarget
66
+ * @param {string=} configUrl optional config
67
+ * @returns {Promise<VcsUiApp>}
68
+ */
69
+ export async function initAppFromModule(mountTarget, configUrl) {
70
+ check(mountTarget, String);
71
+ checkMaybe(configUrl, String);
72
+
73
+ const app = await initApp(mountTarget);
31
74
  if (configUrl) {
32
75
  const config = await fetch(configUrl)
33
76
  .then(response => response.json());
34
- const context = new Context(config);
35
- await app.addContext(context);
77
+ const module = new VcsModule(config);
78
+ await app.addModule(module);
36
79
  }
80
+
37
81
  return app;
38
82
  }
83
+
84
+ /**
85
+ * Initializes app with a map config containing a set of config urls
86
+ * @param {string} mountTarget
87
+ * @param {string} appUrl app config containing further modules to be loaded
88
+ * @returns {Promise<VcsUiApp>}
89
+ */
90
+ export async function initAppFromAppConfig(mountTarget, appUrl) {
91
+ check(mountTarget, String);
92
+ check(appUrl, String);
93
+
94
+ const app = await initApp(mountTarget);
95
+ /**
96
+ * @type {{modules: Array<string|VcsUiAppConfig>}}
97
+ */
98
+ const appConfig = await fetch(appUrl)
99
+ .then(response => response.json());
100
+
101
+ check(appConfig.modules, [String, Object]);
102
+
103
+ const modules = await Promise.all(appConfig.modules.map(async (c) => {
104
+ if (is(c, VcsUiAppConfigPattern)) {
105
+ return new VcsModule(/** @type{import("@vcmap/core").VcsAppConfig} */ c);
106
+ } else if (is(c, String)) {
107
+ const response = await fetch(c);
108
+ if (response.ok) {
109
+ const config = await response.json();
110
+ return new VcsModule(config);
111
+ }
112
+ }
113
+ return null;
114
+ }));
115
+ // eslint-disable-next-line no-restricted-syntax
116
+ for await (const module of modules) {
117
+ if (module) {
118
+ await app.addModule(module);
119
+ }
120
+ }
121
+ }
@@ -1,48 +1,54 @@
1
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"
2
+ <v-expansion-panel
3
+ class="px-2"
4
+ @change="active = !active"
5
+ >
6
+ <v-expansion-panel-header hide-actions>
7
+ <template #default="{ open }">
8
+ <div class="d-flex justify-space-between">
9
+ <div class="d-flex align-center">
10
+ <v-icon class="mr-1" :class="{ 'rotate': !open }">
11
+ mdi-chevron-down
12
+ </v-icon>
13
+ {{ $t(category.title) }}
14
+ </div>
15
+ <VcsActionButtonList
16
+ v-if="category.actions?.length > 0"
17
+ :actions="category.actions"
18
+ small
19
+ class="float-end"
24
20
  />
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>
21
+ </div>
22
+ </template>
23
+ </v-expansion-panel-header>
24
+ <v-expansion-panel-content class="pb-1">
25
+ <vcs-list
26
+ :items="category.items.slice(0, 10)"
27
+ :selectable="category.selectable"
28
+ :single-select="category.singleSelect"
29
+ v-model="selection"
30
+ :show-title="false"
31
+ />
32
+ <v-sheet v-if="category.items.length > 10" class="ma-2 pl-2">
33
+ <VcsButton @click="openCategoryItemWindow" small>
34
+ {{ $t('categoryManager.more') }}
35
+ </VcsButton>
36
+ </v-sheet>
37
+ <v-sheet v-else-if="category.items.length === 0" class="ma-2 pl-2">
38
+ {{ $t('categoryManager.empty') }}
39
+ </v-sheet>
40
+ </v-expansion-panel-content>
41
+ </v-expansion-panel>
41
42
  </template>
42
43
 
43
44
  <script>
44
45
  import { computed, inject, ref } from 'vue';
45
- import { VIcon, VContainer, VRow, VCol } from 'vuetify/lib';
46
+ import {
47
+ VIcon, VExpansionPanel,
48
+ VExpansionPanelHeader,
49
+ VExpansionPanelContent,
50
+ VSheet,
51
+ } from 'vuetify/lib';
46
52
  import VcsList from '../../components/lists/VcsList.vue';
47
53
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
48
54
  import VcsButton from '../../components/buttons/VcsButton.vue';
@@ -54,11 +60,12 @@
54
60
  name: 'CategoryComponent',
55
61
  components: {
56
62
  VcsActionButtonList,
57
- VcsList,
58
- VContainer,
59
- VRow,
60
63
  VcsButton,
61
- VCol,
64
+ VcsList,
65
+ VExpansionPanel,
66
+ VExpansionPanelHeader,
67
+ VExpansionPanelContent,
68
+ VSheet,
62
69
  VIcon,
63
70
  },
64
71
  props: {
@@ -72,7 +79,7 @@
72
79
  /** @type {VcsUiApp} */
73
80
  const app = inject('vcsApp');
74
81
  const windowId = `${category.id}-category-list`;
75
- const open = ref(false);
82
+ const active = ref(false);
76
83
 
77
84
  const selection = computed({
78
85
  get() { return category.selection; },
@@ -84,7 +91,7 @@
84
91
 
85
92
  return {
86
93
  selection,
87
- open,
94
+ active,
88
95
  openCategoryItemWindow() {
89
96
  if (app.windowManager.has(windowId)) {
90
97
  setTimeout(() => {
@@ -110,6 +117,8 @@
110
117
  };
111
118
  </script>
112
119
 
113
- <style scoped>
114
-
120
+ <style lang="scss" scoped>
121
+ .rotate {
122
+ transform: rotate(-90deg);
123
+ }
115
124
  </style>
@@ -1,17 +1,26 @@
1
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>
2
+ <v-sheet>
3
+ <v-expansion-panels
4
+ accordion
5
+ multiple
6
+ v-if="categories.length > 0"
7
+ class="rounded-0"
8
+ >
9
+ <category-component
10
+ v-for="category in categories"
11
+ :category="category"
12
+ :key="category.categoryName"
13
+ />
14
+ </v-expansion-panels>
15
+ </v-sheet>
11
16
  </template>
12
17
 
13
18
  <script>
14
19
  import { inject, ref, computed } from 'vue';
20
+ import {
21
+ VExpansionPanels,
22
+ VSheet,
23
+ } from 'vuetify/lib';
15
24
  import CategoryComponent from './CategoryComponent.vue';
16
25
 
17
26
  /**
@@ -21,7 +30,11 @@
21
30
  */
22
31
  export default {
23
32
  name: 'CategoryManager',
24
- components: { CategoryComponent },
33
+ components: {
34
+ VExpansionPanels,
35
+ VSheet,
36
+ CategoryComponent,
37
+ },
25
38
  setup() {
26
39
  const app = inject('vcsApp');
27
40
  const categoryIds = ref(app.categoryManager.componentIds);
@@ -1,5 +1,5 @@
1
1
  import { reactive } from 'vue';
2
- import { contextIdSymbol, IndexedCollection, VcsEvent } from '@vcmap/core';
2
+ import { moduleIdSymbol, IndexedCollection, VcsEvent } from '@vcmap/core';
3
3
  import { check } from '@vcsuite/check';
4
4
  import { sortByOwner } from '../navbarManager.js';
5
5
  import { validateAction, validateActions } from '../../components/lists/VcsActionList.vue';
@@ -145,8 +145,8 @@ class CategoryManager {
145
145
  * @type {function():void}
146
146
  * @private
147
147
  */
148
- this._dynamicContextIdListener = this._app.dynamicContextIdChanged.addEventListener((id) => {
149
- this._dynamicContextId = id;
148
+ this._dynamicModuleIdListener = this._app.dynamicModuleIdChanged.addEventListener((id) => {
149
+ this._dynamicModuleId = id;
150
150
  this._resetManagedCategories();
151
151
  });
152
152
 
@@ -162,7 +162,7 @@ class CategoryManager {
162
162
  * @type {string}
163
163
  * @private
164
164
  */
165
- this._dynamicContextId = this._app.dynamicContextId;
165
+ this._dynamicModuleId = this._app.dynamicModuleId;
166
166
 
167
167
  /**
168
168
  * @type {Array<ItemMapping<*>>}
@@ -250,7 +250,7 @@ class CategoryManager {
250
250
  }
251
251
 
252
252
  /**
253
- * removes all items from all categories and rebuilds the item tree depending on the ContextId
253
+ * removes all items from all categories and rebuilds the item tree depending on the ModuleId
254
254
  * @private
255
255
  */
256
256
  _resetManagedCategories() {
@@ -281,7 +281,7 @@ class CategoryManager {
281
281
  });
282
282
  managedCategory.items = [...category.collection]
283
283
  .filter((item) => {
284
- return item[contextIdSymbol] === this._dynamicContextId;
284
+ return item[moduleIdSymbol] === this._dynamicModuleId;
285
285
  })
286
286
  .map((item) => {
287
287
  return transformItem(item, category, itemMappings);
@@ -306,17 +306,17 @@ class CategoryManager {
306
306
 
307
307
  const listeners = [
308
308
  category.collection.added.addEventListener((item) => {
309
- if (item[contextIdSymbol] === this._dynamicContextId) {
309
+ if (item[moduleIdSymbol] === this._dynamicModuleId) {
310
310
  this._handleItemAdded(item, category);
311
311
  }
312
312
  }),
313
313
  category.collection.removed.addEventListener((item) => {
314
- if (item[contextIdSymbol] === this._dynamicContextId) {
314
+ if (item[moduleIdSymbol] === this._dynamicModuleId) {
315
315
  this._handleItemRemoved(item, category);
316
316
  }
317
317
  }),
318
318
  category.collection.replaced.addEventListener((replacedEvent) => {
319
- if (replacedEvent.old[contextIdSymbol] === this._dynamicContextId) {
319
+ if (replacedEvent.old[moduleIdSymbol] === this._dynamicModuleId) {
320
320
  this._handleItemRemoved(replacedEvent.old, category);
321
321
  }
322
322
  }),
@@ -324,7 +324,7 @@ class CategoryManager {
324
324
 
325
325
  if (category.collection instanceof IndexedCollection) {
326
326
  listeners.push(category.collection.moved.addEventListener((item) => {
327
- if (item[contextIdSymbol] === this._dynamicContextId) {
327
+ if (item[moduleIdSymbol] === this._dynamicModuleId) {
328
328
  this._handleItemMoved(item, category);
329
329
  }
330
330
  }));
@@ -572,7 +572,7 @@ class CategoryManager {
572
572
  * destroys the categoryManager, removes all Listeners and clears all Managed Categories
573
573
  */
574
574
  destroy() {
575
- this._dynamicContextIdListener();
575
+ this._dynamicModuleIdListener();
576
576
  this._appCategoriesRemovedListener();
577
577
  this.componentIds = [];
578
578
  this._managedCategories.forEach((item) => {
@@ -84,6 +84,24 @@ class NavbarManager extends ButtonManager {
84
84
  buttonComponent[locationSymbol] = location;
85
85
  return buttonComponent;
86
86
  }
87
+
88
+ /**
89
+ * Toggles a button of provided id by executing its callback.
90
+ * Use active flag to force a state to be applied.
91
+ * @param {string} id
92
+ * @param {boolean} [active]
93
+ */
94
+ toggle(id, active = undefined) {
95
+ check(id, String);
96
+ const { action } = this.get(id);
97
+ if (active !== undefined) {
98
+ if (action?.active !== active) {
99
+ action.callback();
100
+ }
101
+ } else if (action) {
102
+ action.callback();
103
+ }
104
+ }
87
105
  }
88
106
 
89
107
  export default NavbarManager;
@@ -2,7 +2,7 @@
2
2
  <v-sheet
3
3
  :id="`window-component--${windowState.id}`"
4
4
  class="elevation-3 position-absolute d-flex flex-column"
5
- @click="clicked"
5
+ v-on="{ ...$listeners }"
6
6
  @dragstart="dragStart"
7
7
  @dragend="dragEnd"
8
8
  :draggable="isDraggable"
@@ -24,9 +24,14 @@
24
24
  >
25
25
  <slot name="headerComponent" :props="$attrs" />
26
26
  </div>
27
- <v-divider />
27
+ <v-divider
28
+ v-if="!windowState.hideHeader"
29
+ />
28
30
  <div
29
31
  class="overflow-x-hidden mb-1"
32
+ :class="{
33
+ 'rounded': !isDocked,
34
+ }"
30
35
  >
31
36
  <slot />
32
37
  </div>
@@ -53,7 +58,8 @@
53
58
  * @vue-prop {WindowState} windowState
54
59
  * @vue-prop {boolean} isOnTop - Whether the component is focused
55
60
  * @vue-prop {Object} slotWindow - slot ref of the window
56
- * @vue-event {PointerEvent} clicked - raised when the component is clicked
61
+ * @vue-event {PointerEvent} click - raised when the component is clicked
62
+ * @vue-event {MouseEvent} mousedown - raised when the component is mousedown
57
63
  * @vue-event {{dx: number, dy: number}} move - raised when the component is moved (dragged)
58
64
  * @vue-data {slot} [#default] - slot with the window content
59
65
  * @vue-data {slot} [#headerComponent] - slot to override the default header
@@ -94,21 +100,14 @@
94
100
  });
95
101
  const isDockedRight = computed(() => props.slotWindow === WindowSlot.DYNAMIC_RIGHT);
96
102
  const isDraggable = ref(false);
97
- /**
98
- * @param {PointerEvent} e
99
- */
100
- const clicked = (e) => {
101
- emit('click', e);
102
- };
103
103
  /**
104
104
  * Sets window as draggable on mousedown on header.
105
105
  * Stops bubbling of header action buttons.
106
106
  * @param {MouseEvent} e
107
107
  */
108
108
  const mousedown = (e) => {
109
+ emit('mousedown', e);
109
110
  if (e.target.closest('button')) {
110
- e.preventDefault();
111
- e.stopPropagation();
112
111
  return;
113
112
  }
114
113
  isDraggable.value = isDynamic.value;
@@ -128,9 +127,6 @@
128
127
  startEvent = e;
129
128
  // set mouse cursor to move
130
129
  e.dataTransfer.effectAllowed = 'move';
131
- const preventDefaultDragover = dragOverEvent => dragOverEvent.preventDefault();
132
- e.target.parentElement.ondragover = preventDefaultDragover;
133
- app.maps.target.ondragover = preventDefaultDragover;
134
130
  };
135
131
  /**
136
132
  * @param {DragEvent} endEvent
@@ -153,7 +149,6 @@
153
149
  isDynamicLeft: isDockedLeft,
154
150
  isDynamicRight: isDockedRight,
155
151
  isDraggable,
156
- clicked,
157
152
  dragStart,
158
153
  dragEnd,
159
154
  mousedown,
@@ -6,6 +6,7 @@
6
6
  class="mr-2"
7
7
  :class="{ 'primary--text': isOnTop }"
8
8
  v-text="windowState.headerIcon"
9
+ size="16"
9
10
  />
10
11
  <h3
11
12
  class="d-inline-block user-select-none font-weight-bold"
@@ -33,7 +34,7 @@
33
34
  small
34
35
  :icon="infoAction.icon"
35
36
  :tooltip="infoAction.title"
36
- class="px-1"
37
+ class="px-1 d-flex"
37
38
  />
38
39
  <VcsButton
39
40
  v-if="isDockable"
@@ -41,13 +42,14 @@
41
42
  small
42
43
  icon="mdi-pin"
43
44
  tooltip="components.pin"
44
- class="px-1"
45
+ class="px-1 d-flex"
45
46
  />
46
47
  <VcsButton
47
48
  @click.stop="close"
48
49
  small
49
50
  icon="mdi-close-thick"
50
51
  tooltip="components.close"
52
+ class="d-flex"
51
53
  />
52
54
  </div>
53
55
  </span>