@vcmap/ui 5.1.3 → 5.1.5

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 (65) hide show
  1. package/config/base.config.json +0 -2
  2. package/config/dev.config.json +4 -0
  3. package/config/www.config.json +0 -2
  4. package/dist/assets/cesium.js +1 -1
  5. package/dist/assets/{core.c815b8.js → core.a3bdf3.js} +2491 -2446
  6. package/dist/assets/core.js +1 -1
  7. package/dist/assets/index-dccddacb.js +1 -0
  8. package/dist/assets/ol.js +1 -1
  9. package/dist/assets/{ui.f85ce1.css → ui.f5e8c3.css} +2 -2
  10. package/dist/assets/{ui.f85ce1.js → ui.f5e8c3.js} +4461 -4276
  11. package/dist/assets/ui.js +1 -1
  12. package/dist/assets/vue.js +2 -2
  13. package/dist/assets/{vuetify.bf2ba1.js → vuetify.4aa1eb.js} +1 -1
  14. package/dist/assets/vuetify.js +2 -2
  15. package/dist/index.html +6 -2
  16. package/index.d.ts +1 -1
  17. package/index.html +5 -1
  18. package/index.js +1 -0
  19. package/package.json +2 -2
  20. package/src/actions/listActions.d.ts +59 -3
  21. package/src/actions/listActions.js +114 -2
  22. package/src/application/VcsApp.vue +20 -4
  23. package/src/application/VcsApp.vue.d.ts +8 -2
  24. package/src/application/VcsNavbar.vue +1 -1
  25. package/src/application/VcsTextPageFooter.vue +47 -30
  26. package/src/application/VcsTextPageFooter.vue.d.ts +5 -3
  27. package/src/components/form-inputs-controls/VcsTextArea.vue +11 -3
  28. package/src/components/form-inputs-controls/VcsTextArea.vue.d.ts +2 -0
  29. package/src/components/icons/+all.js +8 -0
  30. package/src/components/icons/2DPointIcon.vue +22 -0
  31. package/src/components/icons/2DPointIcon.vue.d.ts +2 -0
  32. package/src/components/icons/3DPointIcon.vue +22 -0
  33. package/src/components/icons/3DPointIcon.vue.d.ts +2 -0
  34. package/src/components/icons/AxisIcon.vue +10 -15
  35. package/src/components/icons/PointMeasurementIcon.vue +7 -17
  36. package/src/components/viewpoint/VcsViewpointComponent.vue +27 -5
  37. package/src/components/viewpoint/VcsViewpointComponent.vue.d.ts +9 -0
  38. package/src/components/viewpoint/VcsViewpointEditor.vue +10 -1
  39. package/src/components/viewpoint/VcsViewpointEditor.vue.d.ts +11 -1
  40. package/src/contentTree/LayerTree.vue +22 -3
  41. package/src/featureInfo/abstractFeatureInfoView.d.ts +8 -0
  42. package/src/featureInfo/abstractFeatureInfoView.js +20 -1
  43. package/src/i18n/de.d.ts +6 -1
  44. package/src/i18n/de.js +6 -1
  45. package/src/i18n/en.d.ts +6 -1
  46. package/src/i18n/en.js +6 -1
  47. package/src/manager/collectionManager/collectionComponentClass.d.ts +14 -4
  48. package/src/manager/collectionManager/collectionComponentClass.js +40 -22
  49. package/src/manager/collectionManager/editorCollectionComponentClass.d.ts +7 -1
  50. package/src/manager/collectionManager/editorCollectionComponentClass.js +7 -2
  51. package/src/manager/contextMenu/contextMenuManager.d.ts +11 -0
  52. package/src/manager/contextMenu/contextMenuManager.js +22 -1
  53. package/src/navigation/MapNavigation.vue +7 -4
  54. package/src/navigation/overviewMap.js +24 -19
  55. package/src/siteConfig.d.ts +5 -0
  56. package/src/siteConfig.js +93 -0
  57. package/src/uiConfig.d.ts +16 -6
  58. package/src/uiConfig.js +5 -3
  59. package/src/vcsUiApp.d.ts +1 -0
  60. package/src/vcsUiApp.js +4 -0
  61. package/dist/assets/index-0abd9815.js +0 -1
  62. /package/dist/assets/{cesium.012009.js → cesium.a6cb0f.js} +0 -0
  63. /package/dist/assets/{ol.fbe9a4.js → ol.6a61cd.js} +0 -0
  64. /package/dist/assets/{vue.65726b.js → vue.7cc217.js} +0 -0
  65. /package/dist/assets/{vuetify.bf2ba1.css → vuetify.4aa1eb.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui.f85ce1.js";
1
+ export * from "./ui.f5e8c3.js";
@@ -1,5 +1,5 @@
1
- export * from "./vue.65726b.js";
2
- import { default as f } from "./vue.65726b.js";
1
+ export * from "./vue.7cc217.js";
2
+ import { default as f } from "./vue.7cc217.js";
3
3
  export {
4
4
  f as default
5
5
  };
@@ -13,7 +13,7 @@ function loadCss(href) {
13
13
  elem.onerror = reject;
14
14
  document.head.appendChild(elem);
15
15
  });
16
- } await loadCss('./assets/vuetify.bf2ba1.css');import v from "./vue.65726b.js";
16
+ } await loadCss('./assets/vuetify.4aa1eb.css');import v from "./vue.7cc217.js";
17
17
  const Ne = v.extend().extend({
18
18
  name: "themeable",
19
19
  provide() {
@@ -1,5 +1,5 @@
1
- export * from "./vuetify.bf2ba1.js";
2
- import { default as f } from "./vuetify.bf2ba1.js";
1
+ export * from "./vuetify.4aa1eb.js";
2
+ import { default as f } from "./vuetify.4aa1eb.js";
3
3
  export {
4
4
  f as default
5
5
  };
package/dist/index.html CHANGED
@@ -5,30 +5,34 @@
5
5
  <meta charset="utf-8">
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
7
  <link
8
+ class="vcs-favicon"
8
9
  rel="icon"
9
10
  type="image/png"
10
11
  href="./assets/favicon-32.6b9add.png"
11
12
  sizes="32x32"
12
13
  >
13
14
  <link
15
+ class="vcs-favicon"
14
16
  rel="icon"
15
17
  type="image/png"
16
18
  href="./assets/favicon-128.4c4ce5.png"
17
19
  sizes="128x128"
18
20
  >
19
21
  <link
22
+ class="vcs-favicon"
20
23
  rel="icon"
21
24
  type="image/png"
22
25
  href="./assets/favicon-180.5b99c0.png"
23
26
  sizes="180x180"
24
27
  >
25
28
  <link
29
+ class="vcs-favicon"
26
30
  rel="icon"
27
31
  type="image/png"
28
32
  href="./assets/favicon-192.0e205e.png"
29
33
  sizes="192x192"
30
34
  >
31
- <link rel="icon" type="image/svg+xml" href="./assets/favicon.d5ec97.svg">
35
+ <link class="vcs-favicon" rel="icon" type="image/svg+xml" href="./assets/favicon.d5ec97.svg">
32
36
  <link
33
37
  rel="stylesheet"
34
38
  href="./assets/@mdi/font/css/materialdesignicons.min.e3f476.css"
@@ -91,7 +95,7 @@
91
95
  }
92
96
  }
93
97
  </style>
94
- <script type="module" crossorigin src="./assets/index-0abd9815.js"></script>
98
+ <script type="module" crossorigin src="./assets/index-dccddacb.js"></script>
95
99
  </head>
96
100
  <body style="height: 100vh; margin: 0;">
97
101
  <noscript>
package/index.d.ts CHANGED
@@ -198,7 +198,7 @@ export { createStateRefAction, StateActionState } from "./src/actions/stateRefAc
198
198
  export type * from "./src/actions/stateRefAction.d.ts";
199
199
  export { createLayerToggleAction, createZoomToExtentAction, createExtentFeatureAction, setupExtentComponentActions } from "./src/actions/extentActions.js";
200
200
  export type * from "./src/actions/extentActions.d.ts";
201
- export { createListItemRenameAction, createListItemDeleteAction, createListItemBulkAction, createListExportAction, createListImportAction } from "./src/actions/listActions.js";
201
+ export { createListItemRenameAction, createListItemDeleteAction, createListItemBulkAction, createListExportAction, createListImportAction, importIntoLayer } from "./src/actions/listActions.js";
202
202
  export type * from "./src/actions/listActions.d.ts";
203
203
  export { default as VcsCallback, executeCallbacks } from "./src/callback/vcsCallback.js";
204
204
  export type * from "./src/callback/vcsCallback.d.ts";
package/index.html CHANGED
@@ -5,30 +5,34 @@
5
5
  <meta charset="utf-8">
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
7
  <link
8
+ class="vcs-favicon"
8
9
  rel="icon"
9
10
  type="image/png"
10
11
  href="./assets/favicon-32.png"
11
12
  sizes="32x32"
12
13
  >
13
14
  <link
15
+ class="vcs-favicon"
14
16
  rel="icon"
15
17
  type="image/png"
16
18
  href="./assets/favicon-128.png"
17
19
  sizes="128x128"
18
20
  >
19
21
  <link
22
+ class="vcs-favicon"
20
23
  rel="icon"
21
24
  type="image/png"
22
25
  href="./assets/favicon-180.png"
23
26
  sizes="180x180"
24
27
  >
25
28
  <link
29
+ class="vcs-favicon"
26
30
  rel="icon"
27
31
  type="image/png"
28
32
  href="./assets/favicon-192.png"
29
33
  sizes="192x192"
30
34
  >
31
- <link rel="icon" type="image/svg+xml" href="./assets/favicon.svg">
35
+ <link class="vcs-favicon" rel="icon" type="image/svg+xml" href="./assets/favicon.svg">
32
36
  <link
33
37
  rel="stylesheet"
34
38
  href="./assets/@mdi/font/css/materialdesignicons.min.css"
package/index.js CHANGED
@@ -28,6 +28,7 @@ export {
28
28
  createListItemBulkAction,
29
29
  createListExportAction,
30
30
  createListImportAction,
31
+ importIntoLayer,
31
32
  } from './src/actions/listActions.js';
32
33
 
33
34
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "5.1.3",
3
+ "version": "5.1.5",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@vcmap-cesium/engine": "^4.0.3",
56
- "@vcmap/core": "^5.1.2",
56
+ "@vcmap/core": "^5.1.4",
57
57
  "ol": "^7.5.2",
58
58
  "vue": "~2.7.3",
59
59
  "vuetify": "~2.6.7"
@@ -36,15 +36,35 @@ export function createListExportAction(selection: import("vue").Ref<Array<import
36
36
  action: import("../manager/collectionManager/collectionManager.js").OwnedAction;
37
37
  destroy: (() => void);
38
38
  };
39
+ /**
40
+ * @typedef {Object} ImportIntoLayerOptions
41
+ * @property {import("@vcmap/core").GeoJSONreadOptions} [readOptions]
42
+ * @property {function(import("ol").Feature):boolean} [predicate] - predicate to filter features by
43
+ * @property {string} [predicateFailureMessage='components.import.predicateFailure'] - message to be displayed on predicate failures
44
+ * @property {string} [addFailureMessage='components.import.addFailure'] - message to be displayed if feature could not be added to layer (same id)
45
+ * @property {string} [featuresAddedMessage='components.import.featuresAdded'] - message to be displayed if features where imported
46
+ * @property {string} [nothingAddedMessage='components.import.nothingAdded'] - message to be displayed if no features where imported
47
+ * @property {boolean} [setStyle] - set the style from the last imported file on the provided layer
48
+ * @property {boolean} [setVcsMeta] - set vcs meta from the last imported file on the provided layer
49
+ * @property {boolean} [returnValue] - by default true is returned to close the window, this can be overriden.
50
+ */
51
+ /**
52
+ * @param {File[]} files
53
+ * @param {import("../vcsUiApp.js").default} app
54
+ * @param {import("@vcmap/core").VectorLayer} layer
55
+ * @param {ImportIntoLayerOptions} [options={}]
56
+ * @returns {Promise<boolean>}
57
+ */
58
+ export function importIntoLayer(files: File[], app: import("../vcsUiApp.js").default, layer: import("@vcmap/core").VectorLayer, options?: ImportIntoLayerOptions | undefined): Promise<boolean>;
39
59
  /**
40
60
  *
41
- * @param {function(File[]):void|Promise<void>} importCallback
61
+ * @param {function(File[]):boolean|Promise<boolean>} importCallback
42
62
  * @param {import("../manager/window/windowManager.js").default} windowManager
43
63
  * @param {string|symbol} owner
44
64
  * @param {string} parentId
45
65
  * @returns {{action: import("../manager/collectionManager/collectionManager.js").OwnedAction, destroy: (function(): void)}}
46
66
  */
47
- export function createListImportAction(importCallback: (arg0: File[]) => void | Promise<void>, windowManager: import("../manager/window/windowManager.js").default, owner: string | symbol, parentId: string): {
67
+ export function createListImportAction(importCallback: (arg0: File[]) => boolean | Promise<boolean>, windowManager: import("../manager/window/windowManager.js").default, owner: string | symbol, parentId: string): {
48
68
  action: import("../manager/collectionManager/collectionManager.js").OwnedAction;
49
69
  destroy: (() => void);
50
70
  };
@@ -54,10 +74,46 @@ export function createListImportAction(importCallback: (arg0: File[]) => void |
54
74
  * @param {import("../manager/window/windowManager.js").default} windowManager
55
75
  * @param {string|symbol} owner
56
76
  * @param {string} multiEditorId
77
+ * @param {string} [name="list.edit"]
57
78
  * @template {Object} T
58
79
  * @returns {{action: import("./actionHelper.js").VcsAction, destroy: function(): void}}
59
80
  */
60
- export function createListEditAction<T extends Object>(selection: import("vue").Ref<Array<import("../manager/collectionManager/collectionComponentClass.js").CollectionComponentListItem>>, editCallback: (arg0: T) => void, windowManager: import("../manager/window/windowManager.js").default, owner: string | symbol, multiEditorId: string): {
81
+ export function createListEditAction<T extends Object>(selection: import("vue").Ref<Array<import("../manager/collectionManager/collectionComponentClass.js").CollectionComponentListItem>>, editCallback: (arg0: T) => void, windowManager: import("../manager/window/windowManager.js").default, owner: string | symbol, multiEditorId: string, name?: string | undefined): {
61
82
  action: import("./actionHelper.js").VcsAction;
62
83
  destroy: () => void;
63
84
  };
85
+ export type ImportIntoLayerOptions = {
86
+ readOptions?: import("@vcmap/core").GeoJSONreadOptions | undefined;
87
+ /**
88
+ * - predicate to filter features by
89
+ */
90
+ predicate?: ((arg0: import("ol").Feature) => boolean) | undefined;
91
+ /**
92
+ * - message to be displayed on predicate failures
93
+ */
94
+ predicateFailureMessage?: string | undefined;
95
+ /**
96
+ * - message to be displayed if feature could not be added to layer (same id)
97
+ */
98
+ addFailureMessage?: string | undefined;
99
+ /**
100
+ * - message to be displayed if features where imported
101
+ */
102
+ featuresAddedMessage?: string | undefined;
103
+ /**
104
+ * - message to be displayed if no features where imported
105
+ */
106
+ nothingAddedMessage?: string | undefined;
107
+ /**
108
+ * - set the style from the last imported file on the provided layer
109
+ */
110
+ setStyle?: boolean | undefined;
111
+ /**
112
+ * - set vcs meta from the last imported file on the provided layer
113
+ */
114
+ setVcsMeta?: boolean | undefined;
115
+ /**
116
+ * - by default true is returned to close the window, this can be overriden.
117
+ */
118
+ returnValue?: boolean | undefined;
119
+ };
@@ -1,9 +1,12 @@
1
1
  import { reactive, watch } from 'vue';
2
2
  import { check } from '@vcsuite/check';
3
+ import { getLogger } from '@vcsuite/logger';
4
+ import { parseGeoJSON } from '@vcmap/core';
3
5
  import { createToggleAction } from './actionHelper.js';
4
6
  import ImportComponent from '../components/import/ImportComponent.vue';
5
7
  import { WindowSlot } from '../manager/window/windowManager.js';
6
8
  import { vcsAppSymbol } from '../pluginHelper.js';
9
+ import { NotificationType } from '../notifier/notifier.js';
7
10
 
8
11
  /**
9
12
  * Creates an action for renaming an item in a VcsList. Sho VcsTextfield in VcsList.
@@ -93,9 +96,116 @@ export function createListExportAction(selection, exportCallback, owner) {
93
96
  };
94
97
  }
95
98
 
99
+ /**
100
+ * @typedef {Object} ImportIntoLayerOptions
101
+ * @property {import("@vcmap/core").GeoJSONreadOptions} [readOptions]
102
+ * @property {function(import("ol").Feature):boolean} [predicate] - predicate to filter features by
103
+ * @property {string} [predicateFailureMessage='components.import.predicateFailure'] - message to be displayed on predicate failures
104
+ * @property {string} [addFailureMessage='components.import.addFailure'] - message to be displayed if feature could not be added to layer (same id)
105
+ * @property {string} [featuresAddedMessage='components.import.featuresAdded'] - message to be displayed if features where imported
106
+ * @property {string} [nothingAddedMessage='components.import.nothingAdded'] - message to be displayed if no features where imported
107
+ * @property {boolean} [setStyle] - set the style from the last imported file on the provided layer
108
+ * @property {boolean} [setVcsMeta] - set vcs meta from the last imported file on the provided layer
109
+ * @property {boolean} [returnValue] - by default true is returned to close the window, this can be overriden.
110
+ */
111
+
112
+ /**
113
+ * @param {File[]} files
114
+ * @param {import("../vcsUiApp.js").default} app
115
+ * @param {import("@vcmap/core").VectorLayer} layer
116
+ * @param {ImportIntoLayerOptions} [options={}]
117
+ * @returns {Promise<boolean>}
118
+ */
119
+ export async function importIntoLayer(files, app, layer, options = {}) {
120
+ const { vueI18n } = app;
121
+ const results = await Promise.all(
122
+ files.map(async (file) => {
123
+ const text = await file.text();
124
+ try {
125
+ return parseGeoJSON(text, options.readOptions);
126
+ } catch (e) {
127
+ app.notifier.add({
128
+ type: NotificationType.ERROR,
129
+ message: vueI18n.t('components.import.failure', {
130
+ fileName: file.name,
131
+ }),
132
+ });
133
+ getLogger('import').error(e);
134
+ }
135
+ return {
136
+ features: [],
137
+ };
138
+ }),
139
+ );
140
+
141
+ const features = results.flatMap((r) => r.features);
142
+ const featureToImport = options.predicate
143
+ ? features.filter((f) => options.predicate(f))
144
+ : features;
145
+
146
+ const predicateDelta = features.length - featureToImport.length;
147
+ if (predicateDelta > 0) {
148
+ app.notifier.add({
149
+ type: NotificationType.WARNING,
150
+ message: vueI18n.t(
151
+ options.predicateFailureMessage ?? 'components.import.predicateFailure',
152
+ [predicateDelta],
153
+ ),
154
+ });
155
+ }
156
+
157
+ const imported = layer
158
+ .addFeatures(featureToImport)
159
+ .filter((id) => id != null);
160
+
161
+ const importedDelta = featureToImport.length - imported.length;
162
+ if (importedDelta > 0) {
163
+ app.notifier.add({
164
+ type: NotificationType.WARNING,
165
+ message: vueI18n.t(
166
+ options.addFailureMessage ?? 'components.import.addFailure',
167
+ [importedDelta],
168
+ ),
169
+ });
170
+ }
171
+
172
+ if (imported.length > 0) {
173
+ app.notifier.add({
174
+ type: NotificationType.SUCCESS,
175
+ message: vueI18n.t(
176
+ options.featuresAddedMessage ?? 'components.import.featuresAdded',
177
+ [imported.length],
178
+ ),
179
+ });
180
+ } else {
181
+ app.notifier.add({
182
+ type: NotificationType.ERROR,
183
+ message: vueI18n.t(
184
+ options.nothingAddedMessage ?? 'components.import.nothingAdded',
185
+ ),
186
+ });
187
+ }
188
+
189
+ if (options.setStyle) {
190
+ const lastStyle = results.findLast((r) => !!r.style)?.style;
191
+ if (lastStyle) {
192
+ layer.setStyle(lastStyle);
193
+ }
194
+ }
195
+
196
+ if (options.setVcsMeta) {
197
+ const lastVcsMeta = results.findLast((r) => !!r.vcsMeta)?.vcsMeta;
198
+ if (lastVcsMeta) {
199
+ layer.setVcsMeta(lastVcsMeta);
200
+ }
201
+ }
202
+
203
+ return options.returnValue ?? true;
204
+ }
205
+
96
206
  /**
97
207
  *
98
- * @param {function(File[]):void|Promise<void>} importCallback
208
+ * @param {function(File[]):boolean|Promise<boolean>} importCallback
99
209
  * @param {import("../manager/window/windowManager.js").default} windowManager
100
210
  * @param {string|symbol} owner
101
211
  * @param {string} parentId
@@ -148,6 +258,7 @@ export function createListImportAction(
148
258
  * @param {import("../manager/window/windowManager.js").default} windowManager
149
259
  * @param {string|symbol} owner
150
260
  * @param {string} multiEditorId
261
+ * @param {string} [name="list.edit"]
151
262
  * @template {Object} T
152
263
  * @returns {{action: import("./actionHelper.js").VcsAction, destroy: function(): void}}
153
264
  */
@@ -157,11 +268,12 @@ export function createListEditAction(
157
268
  windowManager,
158
269
  owner,
159
270
  multiEditorId,
271
+ name = 'list.edit',
160
272
  ) {
161
273
  const { action, destroy: destroyEditSelected } = createListItemBulkAction(
162
274
  selection,
163
275
  {
164
- name: 'list.edit',
276
+ name,
165
277
  callback: editCallback,
166
278
  },
167
279
  );
@@ -657,10 +657,26 @@
657
657
  app.uiConfig.config.value.logo ??
658
658
  VcsDefaultLogoMobile,
659
659
  ),
660
- imprint: computed(() => app.uiConfig.config.value.imprint),
661
- dataProtection: computed(
662
- () => app.uiConfig.config.value.dataProtection,
663
- ),
660
+ imprint: computed(() => {
661
+ if (app.uiConfig.config.value.imprint) {
662
+ return {
663
+ title: 'footer.imprint.title',
664
+ tooltip: 'footer.imprint.tooltip',
665
+ ...app.uiConfig.config.value.imprint,
666
+ };
667
+ }
668
+ return undefined;
669
+ }),
670
+ dataProtection: computed(() => {
671
+ if (app.uiConfig.config.value.dataProtection) {
672
+ return {
673
+ title: 'footer.dataProtection.title',
674
+ tooltip: 'footer.dataProtection.tooltip',
675
+ ...app.uiConfig.config.value.dataProtection,
676
+ };
677
+ }
678
+ return undefined;
679
+ }),
664
680
  attributionEntries,
665
681
  attributionAction,
666
682
  showMapNavigation,
@@ -72,8 +72,14 @@ declare const _default: import("vue").DefineComponent<{
72
72
  }, {
73
73
  mapId: string;
74
74
  mobileLogo: import("vue").ComputedRef<any>;
75
- imprint: import("vue").ComputedRef<unknown>;
76
- dataProtection: import("vue").ComputedRef<unknown>;
75
+ imprint: import("vue").ComputedRef<{
76
+ title: string;
77
+ tooltip: string;
78
+ } | undefined>;
79
+ dataProtection: import("vue").ComputedRef<{
80
+ title: string;
81
+ tooltip: string;
82
+ } | undefined>;
77
83
  attributionEntries: import("vue").Ref<import("./attributionsHelper.js").AttributionEntry[]>;
78
84
  attributionAction: import("../actions/actionHelper.js").VcsAction;
79
85
  showMapNavigation: import("vue").Ref<boolean>;
@@ -52,7 +52,7 @@
52
52
  </template>
53
53
  <div
54
54
  v-if="$vuetify.breakpoint.mdAndUp && config.appTitle"
55
- class="ml-4"
55
+ class="ml-4 text-h6 font-weight-bold"
56
56
  >
57
57
  {{ $t(config.appTitle) }}
58
58
  </div>
@@ -1,18 +1,25 @@
1
- <template>
2
- <span class="d-inline-block text-truncate mr-10 setmargin">
3
- <span v-if="textPage.url" class="imprint-span imprint button">
4
- <a :href="textPage.url" class="link" target="_blank"
5
- >{{ $t(textPage.title) }} <span></span>
6
- </a>
7
- </span>
1
+ <template v-if="textPage.title">
2
+ <VcsTooltip :tooltip="textPage.tooltip">
3
+ <template #activator="{ on }">
4
+ <span
5
+ class="d-inline-block text-truncate mr-10 setmargin"
6
+ v-on="{ ...$listeners, ...on }"
7
+ >
8
+ <span v-if="textPage.url" class="imprint-span imprint button">
9
+ <a :href="textPage.url" class="link" target="_blank"
10
+ >{{ $t(textPage.title) }} <span></span>
11
+ </a>
12
+ </span>
8
13
 
9
- <span
10
- v-else
11
- class="imprint-span imprint button link"
12
- @click="addTextPage()"
13
- >{{ $t(textPage.title) }}</span
14
- >
15
- </span>
14
+ <span
15
+ v-else
16
+ class="imprint-span imprint button link"
17
+ @click="addTextPage()"
18
+ >{{ $t(textPage.title) }}</span
19
+ >
20
+ </span>
21
+ </template>
22
+ </VcsTooltip>
16
23
  </template>
17
24
 
18
25
  <style lang="scss" scoped>
@@ -42,17 +49,23 @@
42
49
 
43
50
  <script>
44
51
  import { inject } from 'vue';
52
+ import VcsTooltip from '../components/notification/VcsTooltip.vue';
45
53
  import VcsTextPage from './VcsTextPage.vue';
46
54
  import { vcsAppSymbol } from '../pluginHelper.js';
47
55
  import { WindowSlot } from '../manager/window/windowManager.js';
48
56
 
57
+ /**
58
+ * A Footer element opening either an URL in a new tab or a WindowComponent with provided content
59
+ * @vue-prop {import("../uiConfig.js").TextPageType} [textPage]
60
+ * @vue-prop {string} windowId
61
+ */
49
62
  export default {
50
63
  name: 'VcsTextPageFooter',
51
- components: {},
64
+ components: { VcsTooltip },
52
65
  props: {
53
66
  textPage: {
54
67
  type: Object,
55
- required: true,
68
+ default: () => {},
56
69
  },
57
70
  windowId: {
58
71
  type: String,
@@ -64,21 +77,25 @@
64
77
  const { content } = props.textPage;
65
78
 
66
79
  function addTextPage() {
67
- app.windowManager.add(
68
- {
69
- id: props.windowId,
70
- component: VcsTextPage,
71
- state: {
72
- headerTitle: props.textPage.title,
73
- },
74
- slot: WindowSlot.DYNAMIC_RIGHT,
75
- position: {
76
- width: 600,
80
+ if (!app.windowManager.has(props.windowId)) {
81
+ app.windowManager.add(
82
+ {
83
+ id: props.windowId,
84
+ component: VcsTextPage,
85
+ state: {
86
+ headerTitle: props.textPage.title,
87
+ },
88
+ slot: WindowSlot.DYNAMIC_RIGHT,
89
+ position: {
90
+ width: 600,
91
+ },
92
+ props: { content },
77
93
  },
78
- props: { content },
79
- },
80
- vcsAppSymbol,
81
- );
94
+ vcsAppSymbol,
95
+ );
96
+ } else {
97
+ app.windowManager.remove(props.windowId);
98
+ }
82
99
  }
83
100
 
84
101
  return {
@@ -1,7 +1,7 @@
1
1
  declare const _default: import("vue").DefineComponent<{
2
2
  textPage: {
3
3
  type: ObjectConstructor;
4
- required: true;
4
+ default: () => void;
5
5
  };
6
6
  windowId: {
7
7
  type: StringConstructor;
@@ -12,11 +12,13 @@ declare const _default: import("vue").DefineComponent<{
12
12
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
13
13
  textPage: {
14
14
  type: ObjectConstructor;
15
- required: true;
15
+ default: () => void;
16
16
  };
17
17
  windowId: {
18
18
  type: StringConstructor;
19
19
  required: true;
20
20
  };
21
- }>>, {}>;
21
+ }>>, {
22
+ textPage: Record<string, any>;
23
+ }>;
22
24
  export default _default;
@@ -12,8 +12,8 @@
12
12
  hide-details
13
13
  :dense="isDense"
14
14
  :clearable="isClearable"
15
- @focus="focus = true"
16
- @blur="focus = false"
15
+ @focus="onFocus"
16
+ @blur="onBlur"
17
17
  @mouseover="hover = true"
18
18
  @mouseleave="hover = false"
19
19
  outlined
@@ -145,7 +145,7 @@
145
145
  default: 'right',
146
146
  },
147
147
  },
148
- setup(props, { attrs }) {
148
+ setup(props, { attrs, emit }) {
149
149
  const hover = ref(false);
150
150
  const focus = ref(false);
151
151
  const textAreaRef = ref();
@@ -174,6 +174,14 @@
174
174
  isClearable,
175
175
  isDense,
176
176
  isOutlined,
177
+ onFocus(e) {
178
+ focus.value = true;
179
+ emit('focus', e);
180
+ },
181
+ onBlur(e) {
182
+ focus.value = false;
183
+ emit('blur', e);
184
+ },
177
185
  };
178
186
  },
179
187
  };
@@ -11,6 +11,8 @@ declare const _default: import("vue").DefineComponent<{
11
11
  isClearable: import("vue").ComputedRef<string | boolean>;
12
12
  isDense: import("vue").ComputedRef<boolean>;
13
13
  isOutlined: import("vue").ComputedRef<boolean | "">;
14
+ onFocus(e: any): void;
15
+ onBlur(e: any): void;
14
16
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
15
17
  tooltipPosition: {
16
18
  type: StringConstructor;
@@ -1,9 +1,11 @@
1
1
  import TwoDAreaIcon from './2DAreaIcon.vue';
2
2
  import TwoDDistanceIcon from './2DDistanceIcon.vue';
3
3
  import TwoDHeightObliqueIcon from './2DHeightObliqueIcon.vue';
4
+ import TwoDPointIcon from './2DPointIcon.vue';
4
5
  import ThreeDAreaIcon from './3DAreaIcon.vue';
5
6
  import ThreeDDistanceIcon from './3DDistanceIcon.vue';
6
7
  import ThreeDHeightIcon from './3DHeightIcon.vue';
8
+ import ThreeDPointIcon from './3DPointIcon.vue';
7
9
  import AngleIcon from './AngleIcon.vue';
8
10
  import AssociationsIcon from './AssociationsIcon.vue';
9
11
  import AxisIcon from './AxisIcon.vue';
@@ -144,6 +146,9 @@ const IconMap = {
144
146
  '2dHeightOblique': {
145
147
  component: TwoDHeightObliqueIcon,
146
148
  },
149
+ '2dPoint': {
150
+ component: TwoDPointIcon,
151
+ },
147
152
  '3d': {
148
153
  component: ThreeDimensionsIcon,
149
154
  },
@@ -156,6 +161,9 @@ const IconMap = {
156
161
  '3dHeight': {
157
162
  component: ThreeDHeightIcon,
158
163
  },
164
+ '3dPoint': {
165
+ component: ThreeDPointIcon,
166
+ },
159
167
  angle: {
160
168
  component: AngleIcon,
161
169
  },