@vcmap/ui 5.0.0-rc.15 → 5.0.0-rc.17

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/build/buildHelpers.js +7 -1
  2. package/config/base.config.json +7 -45
  3. package/config/dev.config.json +5 -1
  4. package/config/www.config.json +14 -13
  5. package/dist/assets/{cesium.2e288a.js → cesium.41de56.js} +0 -0
  6. package/dist/assets/cesium.js +1 -1
  7. package/dist/assets/{core.8014d3.js → core.af84e3.js} +6077 -4544
  8. package/dist/assets/core.js +1 -1
  9. package/dist/assets/{index.3f74fa92.js → index.5b773cad.js} +1 -1
  10. package/dist/assets/{ol.31c3a5.js → ol.5c7490.js} +0 -0
  11. package/dist/assets/ol.js +1 -1
  12. package/dist/assets/ui.dffe32.css +1 -0
  13. package/dist/assets/{ui.36f84f.js → ui.dffe32.js} +7243 -6234
  14. package/dist/assets/ui.js +1 -1
  15. package/dist/assets/{vue.a39c10.js → vue.25da17.js} +0 -0
  16. package/dist/assets/vue.js +2 -2
  17. package/dist/assets/{vuetify.378637.css → vuetify.e4ece7.css} +1 -1
  18. package/dist/assets/{vuetify.378637.js → vuetify.e4ece7.js} +5 -2
  19. package/dist/assets/vuetify.js +2 -2
  20. package/dist/index.html +1 -1
  21. package/index.html +77 -0
  22. package/index.js +18 -3
  23. package/package.json +4 -2
  24. package/plugins/@vcmap/create-link/fallbackCreateLink.vue +4 -1
  25. package/plugins/@vcmap/create-link/index.js +4 -1
  26. package/plugins/@vcmap/pluginExample/exampleActions.js +45 -0
  27. package/plugins/@vcmap/pluginExample/index.js +26 -2
  28. package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +77 -42
  29. package/plugins/@vcmap/search-nominatim/nominatim.js +1 -1
  30. package/plugins/@vcmap/theme-changer/ThemeChangerComponent.vue +4 -2
  31. package/plugins/categoryTest/Categories.vue +27 -13
  32. package/plugins/categoryTest/Category.vue +7 -1
  33. package/plugins/categoryTest/index.js +1 -1
  34. package/plugins/notifier/index.js +31 -0
  35. package/plugins/notifier/notifierTester.vue +88 -0
  36. package/plugins/package.json +1 -1
  37. package/plugins/test/allIconsComponent.vue +5 -5
  38. package/plugins/test/emptyComponent.vue +1 -1
  39. package/plugins/test/index.js +27 -3
  40. package/plugins/test/myCustomHeader.vue +9 -1
  41. package/plugins/test/testList.vue +290 -0
  42. package/plugins/test/vcsContent.vue +1 -1
  43. package/plugins/test/windowManagerExample.vue +12 -7
  44. package/plugins/wizardExample/index.js +41 -0
  45. package/plugins/wizardExample/wizardExample.vue +77 -0
  46. package/src/actions/actionHelper.js +10 -9
  47. package/src/application/VcsApp.vue +43 -34
  48. package/src/components/form-inputs-controls/VcsCheckbox.vue +1 -0
  49. package/src/components/form-inputs-controls/VcsFormSection.vue +23 -15
  50. package/src/components/form-inputs-controls/VcsSelect.vue +33 -1
  51. package/src/components/form-inputs-controls/VcsTextField.vue +11 -3
  52. package/src/components/form-inputs-controls/VcsWizard.vue +133 -0
  53. package/src/components/imageElementInjector.vue +22 -0
  54. package/src/components/lists/VcsList.vue +468 -0
  55. package/src/components/lists/VcsTreeview.vue +1 -2
  56. package/src/components/lists/VcsTreeviewLeaf.vue +18 -50
  57. package/src/components/lists/VcsTreeviewSearchbar.vue +1 -23
  58. package/src/components/tables/VcsTable.vue +13 -1
  59. package/src/contentTree/LayerTree.vue +1 -1
  60. package/src/contentTree/contentTreeCollection.js +9 -0
  61. package/src/contentTree/contentTreeItem.js +13 -13
  62. package/src/contentTree/layerContentTreeItem.js +1 -1
  63. package/src/contentTree/subContentTreeItem.js +1 -1
  64. package/src/contentTree/vcsObjectContentTreeItem.js +1 -1
  65. package/src/featureInfo/BalloonComponent.vue +13 -8
  66. package/src/featureInfo/balloonFeatureInfoView.js +16 -22
  67. package/src/featureInfo/balloonHelper.js +26 -5
  68. package/src/featureInfo/featureInfo.js +14 -2
  69. package/src/featureInfo/featureInfoInteraction.js +1 -1
  70. package/src/i18n/de.js +13 -1
  71. package/src/i18n/en.js +13 -1
  72. package/src/icons/+all.js +4 -0
  73. package/src/icons/WandIcon.vue +63 -0
  74. package/src/manager/categoryManager/CategoryComponent.vue +115 -0
  75. package/src/manager/categoryManager/CategoryComponentList.vue +57 -0
  76. package/src/manager/categoryManager/CategoryManager.vue +35 -0
  77. package/src/manager/categoryManager/categoryManager.js +251 -165
  78. package/src/manager/contextMenu/contextMenuManager.js +8 -2
  79. package/src/manager/window/WindowComponent.vue +51 -70
  80. package/src/manager/window/WindowComponentHeader.vue +81 -13
  81. package/src/manager/window/WindowManager.vue +54 -30
  82. package/src/manager/window/windowHelper.js +341 -0
  83. package/src/manager/window/windowManager.js +173 -151
  84. package/src/navigation/overviewMap.js +10 -9
  85. package/src/notifier/notifier.js +120 -0
  86. package/src/notifier/notifierComponent.vue +84 -0
  87. package/src/styles/variables.scss +19 -3
  88. package/src/vcsUiApp.js +26 -2
  89. package/src/vuePlugins/vuetify.js +2 -0
  90. package/dist/assets/ui.36f84f.css +0 -1
  91. package/src/manager/categoryManager/ComponentsManager.vue +0 -30
@@ -2,8 +2,10 @@
2
2
  <v-sheet
3
3
  :id="`window-component--${windowState.id}`"
4
4
  class="elevation-3 position-absolute d-flex flex-column"
5
- ref="windowComponentRef"
6
5
  @click="clicked"
6
+ @dragstart="dragStart"
7
+ @dragend="dragEnd"
8
+ :draggable="isDynamic"
7
9
  :class="{
8
10
  'rounded': !isDocked,
9
11
  'marginToTop': isDocked
@@ -11,15 +13,13 @@
11
13
  >
12
14
  <div
13
15
  v-if="!windowState.hideHeader"
14
- ref="draggableHeaderRef"
15
16
  class="pa-2"
16
17
  :class="{
17
18
  'cursor-grab': isDynamic,
18
19
  'grey--text': !isOnTop,
19
20
  }"
20
- :draggable="isDynamic"
21
21
  >
22
- <slot name="headerComponent" />
22
+ <slot name="headerComponent" :props="$attrs" />
23
23
  </div>
24
24
  <v-divider />
25
25
  <div
@@ -40,13 +40,21 @@
40
40
 
41
41
  <script>
42
42
  import {
43
- onMounted, onUnmounted, computed, ref, nextTick,
43
+ computed, inject, provide,
44
44
  } from 'vue';
45
- import { fromEvent } from 'rxjs';
46
- import { switchMap, take, map, tap } from 'rxjs/operators';
47
45
  import { VDivider, VSheet } from 'vuetify/lib';
48
46
  import { WindowSlot } from './windowManager.js';
49
47
 
48
+ /**
49
+ * WindowComponent defining the structure and style of VC Map windows
50
+ * @vue-prop {WindowState} windowState
51
+ * @vue-prop {boolean} isOnTop - Whether the component is focused
52
+ * @vue-prop {Object} slotWindow - slot ref of the window
53
+ * @vue-event {PointerEvent} clicked - raised when the component is clicked
54
+ * @vue-event {{dx: number, dy: number}} move - raised when the component is moved (dragged)
55
+ * @vue-data {slot} [#default] - slot with the window content
56
+ * @vue-data {slot} [#headerComponent] - slot to override the default header
57
+ */
50
58
  export default {
51
59
  name: 'WindowComponent',
52
60
  components: {
@@ -68,77 +76,50 @@
68
76
  required: true,
69
77
  },
70
78
  },
71
- setup({ windowState, slotWindow }, { emit }) {
72
- const draggableHeaderRef = ref(null);
73
- const windowComponentRef = ref(null);
74
- const isDynamic = computed(() => slotWindow.value !== WindowSlot.STATIC);
75
- const isDocked = computed(() => slotWindow.value !== WindowSlot.DETACHED);
79
+ setup(props, { emit }) {
80
+ const app = inject('vcsApp');
81
+ const { provides } = app.windowManager.get(props.windowState.id);
82
+ Object.entries(provides)
83
+ .forEach(([key, value]) => {
84
+ provide(key, value);
85
+ });
86
+
87
+ const isDynamic = computed(() => props.slotWindow !== WindowSlot.STATIC);
88
+ const isDocked = computed(() => props.slotWindow !== WindowSlot.DETACHED);
89
+ /**
90
+ * @param {PointerEvent} e
91
+ */
76
92
  const clicked = (e) => {
77
93
  emit('click', e);
78
94
  };
95
+ /**
96
+ * @type {DragEvent}
97
+ */
98
+ let startEvent;
99
+ /**
100
+ * @param {DragEvent} e
101
+ */
102
+ const dragStart = (e) => {
103
+ startEvent = e;
104
+ };
105
+ /**
106
+ * @param {DragEvent} endEvent
107
+ */
108
+ const dragEnd = (endEvent) => {
109
+ const movement = {
110
+ dx: endEvent.clientX - startEvent.clientX,
111
+ dy: endEvent.clientY - startEvent.clientY,
112
+ };
113
+ emit('moved', movement);
114
+ startEvent = null;
115
+ };
79
116
 
80
- let dragOverSub;
81
- let dropSub;
82
- onMounted(() => {
83
- if (!windowState.hideHeader && slotWindow.value !== WindowSlot.STATIC) {
84
- nextTick(() => {
85
- const dragStart = fromEvent(draggableHeaderRef.value, 'dragstart');
86
- const dragOver = fromEvent(document.body, 'dragover');
87
- const drop = fromEvent(document.body, 'drop');
88
- const dragThenDrop = dragStart.pipe(
89
- tap(() => {
90
- dragOverSub = dragOver.subscribe((e) => {
91
- // make it accepting drop events
92
- // TODO check if setting the position here works.
93
- e.preventDefault();
94
- });
95
- }),
96
- switchMap((startEvent) => {
97
- // To get to the Root Element of a Custom Component .$el is used here.
98
- const style = window.getComputedStyle(windowComponentRef.value.$el, null);
99
- const windowPosition = {
100
- top: parseInt(style.getPropertyValue('top'), 10),
101
- left: parseInt(style.getPropertyValue('left'), 10),
102
- width: parseInt(style.getPropertyValue('width'), 10),
103
- height: parseInt(style.getPropertyValue('height'), 10),
104
- };
105
- // set dataTransfer for Firefox
106
- startEvent.dataTransfer.setData('text/html', null);
107
-
108
- return drop.pipe(
109
- take(1),
110
- map((dropEvent) => {
111
- windowPosition.dx = startEvent.clientX - dropEvent.clientX;
112
- windowPosition.dy = startEvent.clientY - dropEvent.clientY;
113
- return windowPosition;
114
- }),
115
- tap(() => {
116
- dragOverSub.unsubscribe();
117
- }),
118
- );
119
- }),
120
- );
121
- dropSub = dragThenDrop.subscribe((pos) => {
122
- emit('dropped', pos);
123
- });
124
- });
125
- }
126
- });
127
-
128
- onUnmounted(() => {
129
- if (dragOverSub) {
130
- dragOverSub.unsubscribe();
131
- }
132
- if (dropSub) {
133
- dropSub.unsubscribe();
134
- }
135
- });
136
117
  return {
137
118
  isDynamic,
138
119
  isDocked,
139
- draggableHeaderRef,
140
- windowComponentRef,
141
120
  clicked,
121
+ dragStart,
122
+ dragEnd,
142
123
  };
143
124
  },
144
125
  };
@@ -3,54 +3,122 @@
3
3
  <span>
4
4
  <v-icon
5
5
  v-if="windowState.headerIcon"
6
- class="mr-2 primary--text"
6
+ class="mr-2"
7
+ :class="{ 'text--primary': isOnTop }"
7
8
  v-text="windowState.headerIcon"
8
9
  />
9
- <h3 class="font-size-14 d-inline-block user-select-none font-weight-bold">
10
+ <h3
11
+ class="font-size-14 d-inline-block user-select-none font-weight-bold"
12
+ :class="{ 'text--primary': isOnTop }"
13
+ >
10
14
  {{ $t(windowState.headerTitle) }}
11
15
  </h3>
12
16
  </span>
13
- <VcsButton
14
- @click.stop="close"
15
- small
16
- icon="mdi-close-thick"
17
- />
17
+ <div class="d-flex justify-space-between align-center">
18
+ <template v-if="windowState.headerActions?.length > 0">
19
+ <VcsActionButtonList
20
+ :actions="windowState.headerActions"
21
+ :overflow-count="windowState.headerActionsOverflowCount ?? 3"
22
+ small
23
+ />
24
+ <v-divider
25
+ vertical
26
+ inset
27
+ class="mx-1"
28
+ />
29
+ </template>
30
+ <VcsButton
31
+ v-if="windowState.infoUrl"
32
+ @click.stop="infoAction.callback()"
33
+ small
34
+ :icon="infoAction.icon"
35
+ :tooltip="infoAction.title"
36
+ class="px-1"
37
+ />
38
+ <VcsButton
39
+ v-if="isDockable"
40
+ @click.stop="pin"
41
+ small
42
+ icon="mdi-pin"
43
+ tooltip="components.pin"
44
+ class="px-1"
45
+ />
46
+ <VcsButton
47
+ @click.stop="close"
48
+ small
49
+ icon="mdi-close-thick"
50
+ tooltip="components.close"
51
+ />
52
+ </div>
18
53
  </span>
19
54
  </template>
20
55
 
21
- <style>
56
+ <style lang="scss" scoped>
22
57
  .window-component-header{
23
58
  max-height: 16px;
59
+
60
+ .v-divider--vertical.v-divider--inset {
61
+ margin-top: 2px;
62
+ }
24
63
  }
25
64
  </style>
26
65
 
27
66
  <script>
28
- import { VIcon } from 'vuetify/lib';
67
+ import { VIcon, VDivider } from 'vuetify/lib';
68
+ import { computed } from 'vue';
29
69
  import VcsButton from '../../components/buttons/VcsButton.vue';
70
+ import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
71
+ import { createLinkAction } from '../../actions/actionHelper.js';
30
72
 
73
+ /**
74
+ * Default window component header with drag functionality close action and further optional window actions.
75
+ * @vue-prop {WindowState} windowState - state of the window component.
76
+ * @vue-event {void} pin - raised when pin button is clicked
77
+ * @vue-event {void} close - raised when close button is clicked
78
+ */
31
79
  export default {
32
80
  name: 'WindowComponentHeader',
33
81
  components: {
82
+ VcsActionButtonList,
34
83
  VcsButton,
35
84
  VIcon,
85
+ VDivider,
36
86
  },
37
87
  props: {
38
88
  windowState: {
39
89
  type: Object,
40
90
  required: true,
41
91
  },
92
+ isOnTop: {
93
+ type: Boolean,
94
+ required: true,
95
+ default: false,
96
+ },
97
+ slotWindow: {
98
+ type: Object,
99
+ required: true,
100
+ },
42
101
  },
43
102
  setup(props, { emit }) {
103
+ const pin = () => {
104
+ emit('pin');
105
+ };
44
106
  const close = () => {
45
107
  emit('close');
46
108
  };
47
- const clicked = (e) => {
48
- emit('click', e);
49
- };
109
+ const isDockable = computed(() => !props.windowState.hidePin && props.windowState.dockable);
110
+
111
+ const infoAction = props.windowState.infoUrl ? createLinkAction({
112
+ name: 'info',
113
+ title: 'content.infoAction.title',
114
+ icon: '$vcsInfo',
115
+ }, props.windowState.infoUrl) : {};
50
116
 
51
117
  return {
118
+ pin,
52
119
  close,
53
- clicked,
120
+ isDockable,
121
+ infoAction,
54
122
  };
55
123
  },
56
124
  };
@@ -8,9 +8,9 @@
8
8
  :window-state="getState(id)"
9
9
  :slot-window="getSlot(id)"
10
10
  :z-index="zIndex"
11
- @dropped="dropped(id, $event)"
11
+ @moved="move(id, $event)"
12
12
  @click="clicked(id)"
13
- :style="getStyles(id, zIndex)"
13
+ :style="getStyles(id, zIndex).value"
14
14
  :class="getState(id).classes"
15
15
  :is-on-top="isOnTop(zIndex)"
16
16
  >
@@ -23,7 +23,11 @@
23
23
  <component
24
24
  :is="getHeaderComponent(id)"
25
25
  :window-state="getState(id)"
26
+ :is-on-top="isOnTop(zIndex)"
27
+ :slot-window="getSlot(id)"
28
+ v-bind="getProps(id)"
26
29
  @close="close(id)"
30
+ @pin="pin(id)"
27
31
  />
28
32
  </template>
29
33
  </WindowComponent>
@@ -47,11 +51,15 @@
47
51
  </style>
48
52
 
49
53
  <script>
50
- import { inject, ref } from 'vue';
54
+ import { computed, inject, onUnmounted, ref } from 'vue';
51
55
 
52
56
  import WindowComponent from './WindowComponent.vue';
53
57
  import WindowComponentHeader from './WindowComponentHeader.vue';
58
+ import { applyPositionOnTarget, getTargetSize, moveWindow } from './windowHelper.js';
54
59
 
60
+ /**
61
+ * WindowManager rendering all registered WindowComponents
62
+ */
55
63
  export default {
56
64
  name: 'VcsWindowManager',
57
65
  components: { WindowComponent },
@@ -59,55 +67,70 @@
59
67
  const app = inject('vcsApp');
60
68
  /** @type {WindowManager} */
61
69
  const { windowManager } = app;
62
-
63
70
  const { componentIds } = windowManager;
64
-
71
+ const targetSize = ref(null);
72
+ /**
73
+ * @param {string} id
74
+ * @returns {WindowState}
75
+ */
65
76
  const getState = (id) => {
66
77
  return windowManager.get(id)?.state;
67
78
  };
68
-
79
+ /**
80
+ * @param {string} id
81
+ * @returns {Object}
82
+ */
69
83
  const getProps = (id) => {
70
84
  return windowManager.get(id)?.props ?? {};
71
85
  };
72
-
86
+ /**
87
+ * @param {number} zIndex
88
+ * @returns {boolean}
89
+ */
73
90
  const isOnTop = (zIndex) => {
74
91
  return zIndex === componentIds.length - 1;
75
92
  };
76
-
77
- const getStyles = (id, zIndex) => {
93
+ /**
94
+ * @param {string} id
95
+ * @param {number} zIndex
96
+ * @returns {import("vue").ComputedRef<Object>}
97
+ */
98
+ const getStyles = (id, zIndex) => computed(() => {
78
99
  const windowComponent = windowManager.get(id);
79
100
  const state = windowComponent?.state;
80
- const position = windowComponent?.position;
101
+ const position = applyPositionOnTarget(windowComponent?.position, targetSize.value);
81
102
  return {
82
103
  zIndex,
83
- left: position.left,
84
- top: position.top,
85
- right: position.right,
86
- bottom: position.bottom,
87
- width: position.width,
88
- height: position.height,
104
+ ...position,
89
105
  ...(state.styles || {}),
90
106
  };
91
- };
92
-
107
+ });
108
+ /**
109
+ * @param {string} id
110
+ */
93
111
  const clicked = (id) => {
94
112
  if (windowManager.has(id)) {
95
113
  windowManager.bringWindowToTop(id);
96
114
  }
97
115
  };
116
+ /**
117
+ * @param {string} id
118
+ * @param {{dx: number, dy: number}} translation
119
+ */
120
+ const move = (id, translation) => {
121
+ moveWindow(id, translation, windowManager, targetSize.value);
122
+ };
98
123
 
99
- const dropped = (id, pos) => {
100
- const { innerWidth, innerHeight } = window;
101
- // clip position
102
- const top = Math.min(Math.max(0, pos.top - pos.dy), innerHeight - pos.height);
103
- const left = Math.min(Math.max(0, pos.left - pos.dx), innerWidth - pos.width);
104
- windowManager.setWindowPositionOptions(id, {
105
- top,
106
- left,
107
- width: pos.width,
108
- height: pos.height,
109
- });
124
+ const setTargetSize = () => {
125
+ targetSize.value = getTargetSize(app.maps.target);
110
126
  };
127
+ window.addEventListener('resize', setTargetSize);
128
+ const setTargetDestroy = app.maps.mapActivated.addEventListener(setTargetSize);
129
+
130
+ onUnmounted(() => {
131
+ window.removeEventListener('resize', setTargetSize);
132
+ setTargetDestroy();
133
+ });
111
134
 
112
135
  return {
113
136
  componentIds: ref(componentIds),
@@ -119,8 +142,9 @@
119
142
  isOnTop,
120
143
  getSlot: id => windowManager.get(id).slot,
121
144
  close: (id) => { windowManager.remove(id); },
122
- dropped,
145
+ pin: (id) => { windowManager.pinWindow(id); },
123
146
  clicked,
147
+ move,
124
148
  };
125
149
  },
126
150
  };