@vcmap/ui 5.1.4 → 5.1.6

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 (48) 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.8b769f.js → core.950fcb.js} +707 -678
  6. package/dist/assets/core.js +1 -1
  7. package/dist/assets/index-c4a24e02.js +1 -0
  8. package/dist/assets/ol.js +1 -1
  9. package/dist/assets/{ui.576b59.css → ui.a4ccf8.css} +2 -2
  10. package/dist/assets/{ui.576b59.js → ui.a4ccf8.js} +3783 -3647
  11. package/dist/assets/ui.js +1 -1
  12. package/dist/assets/vue.js +2 -2
  13. package/dist/assets/{vuetify.515b3c.js → vuetify.f23a17.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 +57 -2
  21. package/src/actions/listActions.js +111 -1
  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/viewpoint/VcsViewpointComponent.vue +27 -5
  30. package/src/components/viewpoint/VcsViewpointComponent.vue.d.ts +9 -0
  31. package/src/components/viewpoint/VcsViewpointEditor.vue +10 -1
  32. package/src/components/viewpoint/VcsViewpointEditor.vue.d.ts +11 -1
  33. package/src/contentTree/LayerTree.vue +22 -3
  34. package/src/i18n/de.d.ts +6 -1
  35. package/src/i18n/de.js +6 -1
  36. package/src/i18n/en.d.ts +6 -1
  37. package/src/i18n/en.js +6 -1
  38. package/src/siteConfig.d.ts +5 -0
  39. package/src/siteConfig.js +93 -0
  40. package/src/uiConfig.d.ts +16 -6
  41. package/src/uiConfig.js +5 -3
  42. package/src/vcsUiApp.d.ts +1 -0
  43. package/src/vcsUiApp.js +4 -0
  44. package/dist/assets/index-97b02a80.js +0 -1
  45. /package/dist/assets/{cesium.88a354.js → cesium.a8db01.js} +0 -0
  46. /package/dist/assets/{ol.98520e.js → ol.39cfab.js} +0 -0
  47. /package/dist/assets/{vue.e13c02.js → vue.4e258b.js} +0 -0
  48. /package/dist/assets/{vuetify.515b3c.css → vuetify.f23a17.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui.576b59.js";
1
+ export * from "./ui.a4ccf8.js";
@@ -1,5 +1,5 @@
1
- export * from "./vue.e13c02.js";
2
- import { default as f } from "./vue.e13c02.js";
1
+ export * from "./vue.4e258b.js";
2
+ import { default as f } from "./vue.4e258b.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.515b3c.css');import v from "./vue.e13c02.js";
16
+ } await loadCss('./assets/vuetify.f23a17.css');import v from "./vue.4e258b.js";
17
17
  const Ne = v.extend().extend({
18
18
  name: "themeable",
19
19
  provide() {
@@ -1,5 +1,5 @@
1
- export * from "./vuetify.515b3c.js";
2
- import { default as f } from "./vuetify.515b3c.js";
1
+ export * from "./vuetify.f23a17.js";
2
+ import { default as f } from "./vuetify.f23a17.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-97b02a80.js"></script>
98
+ <script type="module" crossorigin src="./assets/index-c4a24e02.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.4",
3
+ "version": "5.1.6",
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.3",
56
+ "@vcmap/core": "^5.1.5",
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
  };
@@ -62,3 +82,38 @@ export function createListEditAction<T extends Object>(selection: import("vue").
62
82
  action: import("./actionHelper.js").VcsAction;
63
83
  destroy: () => void;
64
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
@@ -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;
@@ -14,7 +14,13 @@
14
14
  </VcsLabel>
15
15
  </v-col>
16
16
  <v-col>
17
- <VcsTextField id="name" dense clearable v-model="name" />
17
+ <VcsTextField
18
+ id="name"
19
+ dense
20
+ clearable
21
+ v-model="name"
22
+ :rules="nameRules"
23
+ />
18
24
  </v-col>
19
25
  </v-row>
20
26
  <v-row no-gutters v-if="!hideTitle">
@@ -203,10 +209,16 @@
203
209
  * @param {import("vue").emit} emit
204
210
  * @param {() => import("@vcmap/core").ViewpointOptions} getModelValue
205
211
  * @param {import("vue").Ref<boolean>} isCesiumMap
206
- * @param {boolean} active - whether to set up post render handler on creation
212
+ * @param {boolean} startSync - whether to set up post render handler on creation
207
213
  * @returns {{action: import("../../actions/actionHelper.js").VcsAction, destroy: function():void}}
208
214
  */
209
- function createEditingAction(app, emit, getModelValue, isCesiumMap, active) {
215
+ function createEditingAction(
216
+ app,
217
+ emit,
218
+ getModelValue,
219
+ isCesiumMap,
220
+ startSync,
221
+ ) {
210
222
  let destroyPostRenderListener = () => {};
211
223
  let cachedViewpoint = new Viewpoint(getModelValue());
212
224
 
@@ -231,11 +243,14 @@
231
243
  }
232
244
  }
233
245
 
246
+ const isObliqueMap = app.maps.activeMap?.className === ObliqueMap.className;
247
+ const active = isObliqueMap ? false : startSync;
248
+
234
249
  const action = reactive({
235
250
  name: 'edit-viewpoint-action',
236
251
  icon: active ? 'mdi-sync' : 'mdi-sync-off',
237
252
  title: 'components.viewpoint.syncOff',
238
- disabled: app.maps.activeMap?.className === ObliqueMap.className,
253
+ disabled: isObliqueMap,
239
254
  active,
240
255
  callback() {
241
256
  this.active = !this.active;
@@ -322,6 +337,7 @@
322
337
  * @vue-prop {boolean} hideTitle - Hide title input.
323
338
  * @vue-prop {boolean} hideAnimate - Hide animate & duration input.
324
339
  * @vue-prop {boolean} hideGeneral - Hide all general settings (name, title, animate).
340
+ * @vue-prop {Array<(v:string)=>(boolean|string)>} nameRules - Optional rules for name input.
325
341
  */
326
342
  export default {
327
343
  name: 'VcsViewpointComponent',
@@ -366,10 +382,16 @@
366
382
  type: Boolean,
367
383
  default: false,
368
384
  },
385
+ nameRules: {
386
+ type: Array,
387
+ default: () => [],
388
+ },
369
389
  },
370
390
  setup(props, { emit }) {
371
391
  const app = inject('vcsApp');
372
- const isCesiumMap = ref(app.maps.activeMap?.className === 'CesiumMap');
392
+ const isCesiumMap = ref(
393
+ app.maps.activeMap?.className === CesiumMap.className,
394
+ );
373
395
 
374
396
  const name = usePrimitiveProperty(() => props.value, 'name', emit);
375
397
  const title = computed({