@vcmap/ui 5.0.0-rc.16 → 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 (57) hide show
  1. package/build/buildHelpers.js +7 -1
  2. package/config/base.config.json +3 -45
  3. package/config/www.config.json +9 -10
  4. package/dist/assets/{cesium.430460.js → cesium.41de56.js} +0 -0
  5. package/dist/assets/cesium.js +1 -1
  6. package/dist/assets/{core.5089ba.js → core.af84e3.js} +1700 -1718
  7. package/dist/assets/core.js +1 -1
  8. package/dist/assets/{index.854f8e2b.js → index.5b773cad.js} +1 -1
  9. package/dist/assets/{ol.9be53a.js → ol.5c7490.js} +0 -0
  10. package/dist/assets/ol.js +1 -1
  11. package/dist/assets/{ui.49010a.css → ui.dffe32.css} +1 -1
  12. package/dist/assets/{ui.49010a.js → ui.dffe32.js} +6345 -6011
  13. package/dist/assets/ui.js +1 -1
  14. package/dist/assets/{vue.247c1c.js → vue.25da17.js} +0 -0
  15. package/dist/assets/vue.js +2 -2
  16. package/dist/assets/{vuetify.735e58.css → vuetify.e4ece7.css} +0 -0
  17. package/dist/assets/{vuetify.735e58.js → vuetify.e4ece7.js} +5 -2
  18. package/dist/assets/vuetify.js +2 -2
  19. package/dist/index.html +1 -1
  20. package/index.js +14 -3
  21. package/package.json +2 -2
  22. package/plugins/@vcmap/pluginExample/index.js +2 -1
  23. package/plugins/@vcmap/pluginExample/pluginExampleComponent.vue +7 -0
  24. package/plugins/categoryTest/Categories.vue +27 -13
  25. package/plugins/categoryTest/Category.vue +7 -1
  26. package/plugins/categoryTest/index.js +1 -1
  27. package/plugins/test/allIconsComponent.vue +3 -3
  28. package/plugins/test/index.js +6 -4
  29. package/plugins/test/testList.vue +4 -1
  30. package/plugins/test/vcsContent.vue +1 -1
  31. package/plugins/test/windowManagerExample.vue +9 -7
  32. package/src/actions/actionHelper.js +10 -9
  33. package/src/application/VcsApp.vue +25 -26
  34. package/src/components/form-inputs-controls/VcsCheckbox.vue +1 -0
  35. package/src/components/form-inputs-controls/VcsFormSection.vue +14 -6
  36. package/src/components/lists/VcsList.vue +4 -2
  37. package/src/contentTree/contentTreeCollection.js +9 -0
  38. package/src/contentTree/layerContentTreeItem.js +1 -1
  39. package/src/featureInfo/BalloonComponent.vue +3 -0
  40. package/src/featureInfo/balloonFeatureInfoView.js +2 -8
  41. package/src/featureInfo/balloonHelper.js +22 -5
  42. package/src/featureInfo/featureInfo.js +1 -2
  43. package/src/i18n/de.js +6 -1
  44. package/src/i18n/en.js +6 -1
  45. package/src/manager/categoryManager/CategoryComponent.vue +115 -0
  46. package/src/manager/categoryManager/CategoryComponentList.vue +57 -0
  47. package/src/manager/categoryManager/CategoryManager.vue +35 -0
  48. package/src/manager/categoryManager/categoryManager.js +251 -165
  49. package/src/manager/contextMenu/contextMenuManager.js +8 -2
  50. package/src/manager/window/WindowComponent.vue +49 -75
  51. package/src/manager/window/WindowComponentHeader.vue +49 -7
  52. package/src/manager/window/WindowManager.vue +53 -30
  53. package/src/manager/window/windowHelper.js +341 -0
  54. package/src/manager/window/windowManager.js +162 -150
  55. package/src/notifier/notifier.js +4 -5
  56. package/src/vcsUiApp.js +7 -1
  57. 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,13 +13,11 @@
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
22
  <slot name="headerComponent" :props="$attrs" />
23
23
  </div>
@@ -40,13 +40,21 @@
40
40
 
41
41
  <script>
42
42
  import {
43
- onMounted, onUnmounted, computed, ref, nextTick, inject, provide,
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,84 +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);
76
- const clicked = (e) => {
77
- emit('click', e);
78
- };
79
-
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
-
79
+ setup(props, { emit }) {
137
80
  const app = inject('vcsApp');
138
- const { provides } = app.windowManager.get(windowState.id);
81
+ const { provides } = app.windowManager.get(props.windowState.id);
139
82
  Object.entries(provides)
140
83
  .forEach(([key, value]) => {
141
84
  provide(key, value);
142
85
  });
86
+
87
+ const isDynamic = computed(() => props.slotWindow !== WindowSlot.STATIC);
88
+ const isDocked = computed(() => props.slotWindow !== WindowSlot.DETACHED);
89
+ /**
90
+ * @param {PointerEvent} e
91
+ */
92
+ const clicked = (e) => {
93
+ emit('click', e);
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
+ };
116
+
143
117
  return {
144
118
  isDynamic,
145
119
  isDocked,
146
- draggableHeaderRef,
147
- windowComponentRef,
148
120
  clicked,
121
+ dragStart,
122
+ dragEnd,
149
123
  };
150
124
  },
151
125
  };
@@ -3,10 +3,14 @@
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>
@@ -20,9 +24,25 @@
20
24
  <v-divider
21
25
  vertical
22
26
  inset
23
- class="mx-2"
27
+ class="mx-1"
24
28
  />
25
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
+ />
26
46
  <VcsButton
27
47
  @click.stop="close"
28
48
  small
@@ -45,12 +65,16 @@
45
65
 
46
66
  <script>
47
67
  import { VIcon, VDivider } from 'vuetify/lib';
68
+ import { computed } from 'vue';
48
69
  import VcsButton from '../../components/buttons/VcsButton.vue';
49
70
  import VcsActionButtonList from '../../components/buttons/VcsActionButtonList.vue';
71
+ import { createLinkAction } from '../../actions/actionHelper.js';
50
72
 
51
73
  /**
52
74
  * Default window component header with drag functionality close action and further optional window actions.
53
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
54
78
  */
55
79
  export default {
56
80
  name: 'WindowComponentHeader',
@@ -65,18 +89,36 @@
65
89
  type: Object,
66
90
  required: true,
67
91
  },
92
+ isOnTop: {
93
+ type: Boolean,
94
+ required: true,
95
+ default: false,
96
+ },
97
+ slotWindow: {
98
+ type: Object,
99
+ required: true,
100
+ },
68
101
  },
69
102
  setup(props, { emit }) {
103
+ const pin = () => {
104
+ emit('pin');
105
+ };
70
106
  const close = () => {
71
107
  emit('close');
72
108
  };
73
- const clicked = (e) => {
74
- emit('click', e);
75
- };
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) : {};
76
116
 
77
117
  return {
118
+ pin,
78
119
  close,
79
- clicked,
120
+ isDockable,
121
+ infoAction,
80
122
  };
81
123
  },
82
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,8 +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)"
26
28
  v-bind="getProps(id)"
27
29
  @close="close(id)"
30
+ @pin="pin(id)"
28
31
  />
29
32
  </template>
30
33
  </WindowComponent>
@@ -48,11 +51,15 @@
48
51
  </style>
49
52
 
50
53
  <script>
51
- import { inject, ref } from 'vue';
54
+ import { computed, inject, onUnmounted, ref } from 'vue';
52
55
 
53
56
  import WindowComponent from './WindowComponent.vue';
54
57
  import WindowComponentHeader from './WindowComponentHeader.vue';
58
+ import { applyPositionOnTarget, getTargetSize, moveWindow } from './windowHelper.js';
55
59
 
60
+ /**
61
+ * WindowManager rendering all registered WindowComponents
62
+ */
56
63
  export default {
57
64
  name: 'VcsWindowManager',
58
65
  components: { WindowComponent },
@@ -60,55 +67,70 @@
60
67
  const app = inject('vcsApp');
61
68
  /** @type {WindowManager} */
62
69
  const { windowManager } = app;
63
-
64
70
  const { componentIds } = windowManager;
65
-
71
+ const targetSize = ref(null);
72
+ /**
73
+ * @param {string} id
74
+ * @returns {WindowState}
75
+ */
66
76
  const getState = (id) => {
67
77
  return windowManager.get(id)?.state;
68
78
  };
69
-
79
+ /**
80
+ * @param {string} id
81
+ * @returns {Object}
82
+ */
70
83
  const getProps = (id) => {
71
84
  return windowManager.get(id)?.props ?? {};
72
85
  };
73
-
86
+ /**
87
+ * @param {number} zIndex
88
+ * @returns {boolean}
89
+ */
74
90
  const isOnTop = (zIndex) => {
75
91
  return zIndex === componentIds.length - 1;
76
92
  };
77
-
78
- 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(() => {
79
99
  const windowComponent = windowManager.get(id);
80
100
  const state = windowComponent?.state;
81
- const position = windowComponent?.position;
101
+ const position = applyPositionOnTarget(windowComponent?.position, targetSize.value);
82
102
  return {
83
103
  zIndex,
84
- left: position.left,
85
- top: position.top,
86
- right: position.right,
87
- bottom: position.bottom,
88
- width: position.width,
89
- height: position.height,
104
+ ...position,
90
105
  ...(state.styles || {}),
91
106
  };
92
- };
93
-
107
+ });
108
+ /**
109
+ * @param {string} id
110
+ */
94
111
  const clicked = (id) => {
95
112
  if (windowManager.has(id)) {
96
113
  windowManager.bringWindowToTop(id);
97
114
  }
98
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
+ };
99
123
 
100
- const dropped = (id, pos) => {
101
- const { innerWidth, innerHeight } = window;
102
- // clip position
103
- const top = Math.min(Math.max(0, pos.top - pos.dy), innerHeight - pos.height);
104
- const left = Math.min(Math.max(0, pos.left - pos.dx), innerWidth - pos.width);
105
- windowManager.setWindowPositionOptions(id, {
106
- top,
107
- left,
108
- width: pos.width,
109
- height: pos.height,
110
- });
124
+ const setTargetSize = () => {
125
+ targetSize.value = getTargetSize(app.maps.target);
111
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
+ });
112
134
 
113
135
  return {
114
136
  componentIds: ref(componentIds),
@@ -120,8 +142,9 @@
120
142
  isOnTop,
121
143
  getSlot: id => windowManager.get(id).slot,
122
144
  close: (id) => { windowManager.remove(id); },
123
- dropped,
145
+ pin: (id) => { windowManager.pinWindow(id); },
124
146
  clicked,
147
+ move,
125
148
  };
126
149
  },
127
150
  };