@vcmap/module-selector 2.0.0 → 2.0.1
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.
- package/CHANGELOG.md +5 -1
- package/dist/index.js +1291 -151
- package/package.json +11 -6
- package/src/ModuleSelector.vue +12 -27
- package/src/config/ModuleEditor.vue +136 -0
- package/src/config/ModuleSelectorConfigEditor.vue +660 -0
- package/src/config/WindowPositionSettings.vue +105 -0
- package/src/defaultOptions.ts +3 -0
- package/src/index.ts +163 -22
- package/src/moduleHelper.ts +31 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container class="py-0 px-1">
|
|
3
|
+
<v-row
|
|
4
|
+
no-gutters
|
|
5
|
+
v-for="{ key, checkbox, input, placeholder } in inputs"
|
|
6
|
+
:key="key"
|
|
7
|
+
>
|
|
8
|
+
<v-col>
|
|
9
|
+
<VcsCheckbox
|
|
10
|
+
:label="`appConfigurator.editors.featureInfo.window.position.${key}`"
|
|
11
|
+
v-model="checkbox.value"
|
|
12
|
+
/>
|
|
13
|
+
</v-col>
|
|
14
|
+
<v-col>
|
|
15
|
+
<VcsTextField
|
|
16
|
+
clearable
|
|
17
|
+
:disabled="!checkbox.value"
|
|
18
|
+
:placeholder="placeholder"
|
|
19
|
+
v-model.trim="input.value"
|
|
20
|
+
/>
|
|
21
|
+
</v-col>
|
|
22
|
+
</v-row>
|
|
23
|
+
</v-container>
|
|
24
|
+
</template>
|
|
25
|
+
<script lang="ts">
|
|
26
|
+
import {
|
|
27
|
+
computed,
|
|
28
|
+
defineComponent,
|
|
29
|
+
PropType,
|
|
30
|
+
Ref,
|
|
31
|
+
WritableComputedRef,
|
|
32
|
+
} from 'vue';
|
|
33
|
+
import { VContainer, VRow, VCol } from 'vuetify/components';
|
|
34
|
+
import {
|
|
35
|
+
useModelHasProperty,
|
|
36
|
+
useProxiedComplexModel,
|
|
37
|
+
VcsCheckbox,
|
|
38
|
+
VcsTextField,
|
|
39
|
+
WindowPositionOptions,
|
|
40
|
+
} from '@vcmap/ui';
|
|
41
|
+
|
|
42
|
+
export default defineComponent({
|
|
43
|
+
name: 'WindowPositionSettings',
|
|
44
|
+
components: {
|
|
45
|
+
VContainer,
|
|
46
|
+
VRow,
|
|
47
|
+
VCol,
|
|
48
|
+
VcsCheckbox,
|
|
49
|
+
VcsTextField,
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
modelValue: {
|
|
53
|
+
type: Object as PropType<WindowPositionOptions>,
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
positionKeys: {
|
|
57
|
+
type: Array as PropType<(keyof WindowPositionOptions)[]>,
|
|
58
|
+
default: () => ['height', 'maxHeight', 'width', 'maxWidth'],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
setup(props, { emit }) {
|
|
62
|
+
const localValue: Ref<WindowPositionOptions> = useProxiedComplexModel(
|
|
63
|
+
props,
|
|
64
|
+
'modelValue',
|
|
65
|
+
emit,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const inputs = computed(() => {
|
|
69
|
+
return props.positionKeys.reduce(
|
|
70
|
+
(acc, key) => {
|
|
71
|
+
acc[key] = {
|
|
72
|
+
key,
|
|
73
|
+
checkbox: useModelHasProperty(localValue, key, null),
|
|
74
|
+
input: computed({
|
|
75
|
+
get() {
|
|
76
|
+
return localValue.value[key];
|
|
77
|
+
},
|
|
78
|
+
set(value) {
|
|
79
|
+
localValue.value[key] = value;
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
placeholder: 'auto',
|
|
83
|
+
};
|
|
84
|
+
return acc;
|
|
85
|
+
},
|
|
86
|
+
{} as Record<
|
|
87
|
+
keyof WindowPositionOptions,
|
|
88
|
+
{
|
|
89
|
+
key: keyof WindowPositionOptions;
|
|
90
|
+
checkbox: WritableComputedRef<boolean>;
|
|
91
|
+
input: WritableComputedRef<string | number | undefined>;
|
|
92
|
+
placeholder: string | null | undefined;
|
|
93
|
+
}
|
|
94
|
+
>,
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
inputs,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<style scoped></style>
|
package/src/defaultOptions.ts
CHANGED
|
@@ -2,10 +2,13 @@ import { ModuleSelectorConfig } from './index.js';
|
|
|
2
2
|
|
|
3
3
|
export default (): ModuleSelectorConfig => ({
|
|
4
4
|
windowTitle: 'moduleSelector.title',
|
|
5
|
+
isActiveOnStart: true,
|
|
6
|
+
requireModuleSelection: false,
|
|
5
7
|
position: {
|
|
6
8
|
left: '33%',
|
|
7
9
|
right: '33%',
|
|
8
10
|
top: '10%',
|
|
9
11
|
},
|
|
12
|
+
basisModule: undefined,
|
|
10
13
|
modules: [],
|
|
11
14
|
});
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ButtonLocation,
|
|
3
|
+
createToggleAction,
|
|
4
|
+
PluginConfigEditor,
|
|
2
5
|
VcsPlugin,
|
|
3
6
|
VcsUiApp,
|
|
4
|
-
WindowSlot,
|
|
5
|
-
ButtonLocation,
|
|
6
7
|
WindowPositionOptions,
|
|
7
|
-
|
|
8
|
+
WindowSlot,
|
|
8
9
|
} from '@vcmap/ui';
|
|
9
10
|
import { Ref, ref } from 'vue';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
11
|
+
import { parseBoolean, parseInteger } from '@vcsuite/parsers';
|
|
12
|
+
import equal from 'fast-deep-equal';
|
|
13
|
+
import { mapVersion, name, version } from '../package.json';
|
|
14
|
+
import moduleSelector from './ModuleSelector.vue';
|
|
12
15
|
import getDefaultOptions from './defaultOptions.js';
|
|
16
|
+
import ModuleSelectorConfigEditor from './config/ModuleSelectorConfigEditor.vue';
|
|
17
|
+
import { startApplication, windowIdModuleSelector } from './moduleHelper';
|
|
13
18
|
|
|
14
19
|
export type BasisModule = {
|
|
15
20
|
title: string;
|
|
@@ -24,19 +29,29 @@ export type Module<T extends ModuleType> = T extends 'group'
|
|
|
24
29
|
? BasisModule & { moduleUrl: string; type: T }
|
|
25
30
|
: never;
|
|
26
31
|
|
|
27
|
-
type
|
|
28
|
-
type PluginState = Record<never, never>;
|
|
29
|
-
|
|
30
|
-
export type ModuleSelectorConfig = PluginConfig & {
|
|
32
|
+
export type ModuleSelectorConfig = {
|
|
31
33
|
windowTitle?: string;
|
|
32
34
|
isActiveOnStart?: boolean;
|
|
33
35
|
requireModuleSelection?: boolean;
|
|
34
36
|
position?: WindowPositionOptions;
|
|
35
37
|
basisModule?: BasisModule;
|
|
36
|
-
modules
|
|
38
|
+
modules?: Array<Module<ModuleType>>;
|
|
37
39
|
};
|
|
38
40
|
|
|
39
|
-
export type
|
|
41
|
+
export type PluginState = {
|
|
42
|
+
// selectedMainModuleIndex
|
|
43
|
+
smi?: number | undefined | null;
|
|
44
|
+
// selectedNestedModuleIndex
|
|
45
|
+
snmi?: number | undefined | null;
|
|
46
|
+
// module elector window open
|
|
47
|
+
w?: boolean;
|
|
48
|
+
modules?: Array<Module<ModuleType>>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type ModuleSelectorPlugin = VcsPlugin<
|
|
52
|
+
Partial<ModuleSelectorConfig>,
|
|
53
|
+
PluginState
|
|
54
|
+
> & {
|
|
40
55
|
readonly config: ModuleSelectorConfig;
|
|
41
56
|
selectedMainModuleIndex: Ref<number | undefined | null>;
|
|
42
57
|
selectedNestedModuleIndex: Ref<number | undefined | null>;
|
|
@@ -45,6 +60,7 @@ export type ModuleSelectorPlugin = VcsPlugin<PluginConfig, PluginState> & {
|
|
|
45
60
|
export default function plugin(
|
|
46
61
|
configInput: ModuleSelectorConfig,
|
|
47
62
|
): ModuleSelectorPlugin {
|
|
63
|
+
let app: VcsUiApp;
|
|
48
64
|
return {
|
|
49
65
|
get name(): string {
|
|
50
66
|
return name;
|
|
@@ -60,7 +76,11 @@ export default function plugin(
|
|
|
60
76
|
},
|
|
61
77
|
selectedMainModuleIndex: ref(undefined),
|
|
62
78
|
selectedNestedModuleIndex: ref(undefined),
|
|
63
|
-
initialize(
|
|
79
|
+
async initialize(
|
|
80
|
+
vcsUiApp: VcsUiApp,
|
|
81
|
+
state: PluginState | undefined,
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
app = vcsUiApp;
|
|
64
84
|
const moduleSelectorComponent = {
|
|
65
85
|
id: windowIdModuleSelector,
|
|
66
86
|
component: moduleSelector,
|
|
@@ -68,6 +88,7 @@ export default function plugin(
|
|
|
68
88
|
position: this.config.position,
|
|
69
89
|
state: {
|
|
70
90
|
headerTitle: this.config.windowTitle,
|
|
91
|
+
infoUrlCallback: app.getHelpUrlCallback('/tools/moduleSelector.html'),
|
|
71
92
|
},
|
|
72
93
|
props: {
|
|
73
94
|
modules: this.config.modules,
|
|
@@ -75,6 +96,35 @@ export default function plugin(
|
|
|
75
96
|
requireModuleSelection: this.config.requireModuleSelection,
|
|
76
97
|
},
|
|
77
98
|
};
|
|
99
|
+
if (state) {
|
|
100
|
+
const smi = parseInteger(state.smi);
|
|
101
|
+
const snmi = parseInteger(state.snmi);
|
|
102
|
+
const w = parseBoolean(state.w);
|
|
103
|
+
const { modules } = this.config;
|
|
104
|
+
|
|
105
|
+
if (smi !== undefined && smi < modules?.length) {
|
|
106
|
+
this.selectedMainModuleIndex.value = smi;
|
|
107
|
+
const selectedModule = modules[smi];
|
|
108
|
+
|
|
109
|
+
if (
|
|
110
|
+
snmi !== undefined &&
|
|
111
|
+
selectedModule?.type === 'group' &&
|
|
112
|
+
snmi < selectedModule?.cards?.length
|
|
113
|
+
) {
|
|
114
|
+
this.selectedNestedModuleIndex.value = snmi;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!w) {
|
|
119
|
+
await startApplication(
|
|
120
|
+
this.selectedMainModuleIndex.value,
|
|
121
|
+
this.selectedNestedModuleIndex.value,
|
|
122
|
+
app,
|
|
123
|
+
configInput.modules!,
|
|
124
|
+
configInput.basisModule,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
78
128
|
|
|
79
129
|
const { action } = createToggleAction(
|
|
80
130
|
{
|
|
@@ -83,11 +133,11 @@ export default function plugin(
|
|
|
83
133
|
icon: 'mdi-view-grid',
|
|
84
134
|
},
|
|
85
135
|
moduleSelectorComponent,
|
|
86
|
-
|
|
136
|
+
app.windowManager,
|
|
87
137
|
name,
|
|
88
138
|
);
|
|
89
139
|
|
|
90
|
-
|
|
140
|
+
app.navbarManager.add(
|
|
91
141
|
{
|
|
92
142
|
id: action.name,
|
|
93
143
|
action,
|
|
@@ -96,41 +146,132 @@ export default function plugin(
|
|
|
96
146
|
ButtonLocation.PROJECT,
|
|
97
147
|
);
|
|
98
148
|
|
|
99
|
-
if (configInput.isActiveOnStart) {
|
|
100
|
-
|
|
149
|
+
if ((state && state.w) || (!state && configInput.isActiveOnStart)) {
|
|
150
|
+
app.windowManager.add(moduleSelectorComponent, name);
|
|
101
151
|
}
|
|
102
152
|
|
|
103
153
|
return Promise.resolve();
|
|
104
154
|
},
|
|
105
155
|
getDefaultOptions,
|
|
156
|
+
getState(): PluginState {
|
|
157
|
+
const smi = this.selectedMainModuleIndex?.value;
|
|
158
|
+
const snmi = this.selectedNestedModuleIndex?.value;
|
|
159
|
+
const windowState = app.windowManager.has(windowIdModuleSelector);
|
|
160
|
+
const isActive = this.config.isActiveOnStart;
|
|
161
|
+
|
|
162
|
+
return smi !== undefined || snmi !== undefined || windowState !== isActive
|
|
163
|
+
? { smi, snmi, w: windowState }
|
|
164
|
+
: {};
|
|
165
|
+
},
|
|
166
|
+
getConfigEditors(): PluginConfigEditor<object>[] {
|
|
167
|
+
return [
|
|
168
|
+
{
|
|
169
|
+
component: ModuleSelectorConfigEditor,
|
|
170
|
+
title: 'moduleSelector.name',
|
|
171
|
+
infoUrlCallback: app.getHelpUrlCallback(
|
|
172
|
+
'/components/plugins/moduleSelectorConfig.html',
|
|
173
|
+
'app-configurator',
|
|
174
|
+
),
|
|
175
|
+
},
|
|
176
|
+
];
|
|
177
|
+
},
|
|
106
178
|
toJSON(): Partial<ModuleSelectorConfig> {
|
|
107
179
|
const serial: Partial<ModuleSelectorConfig> = {};
|
|
108
|
-
|
|
109
|
-
|
|
180
|
+
const defaultOptions = getDefaultOptions();
|
|
181
|
+
if (this.config.windowTitle !== defaultOptions.windowTitle) {
|
|
182
|
+
serial.windowTitle = this.config.windowTitle;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (this.config.isActiveOnStart !== defaultOptions.isActiveOnStart) {
|
|
186
|
+
serial.isActiveOnStart = this.config.isActiveOnStart;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (
|
|
190
|
+
this.config.requireModuleSelection !==
|
|
191
|
+
defaultOptions.requireModuleSelection
|
|
192
|
+
) {
|
|
193
|
+
serial.requireModuleSelection = this.config.requireModuleSelection;
|
|
110
194
|
}
|
|
111
195
|
|
|
112
|
-
if (
|
|
113
|
-
serial.position =
|
|
196
|
+
if (!equal(this.config.position, defaultOptions.position)) {
|
|
197
|
+
serial.position = this.config.position;
|
|
114
198
|
}
|
|
115
199
|
|
|
116
|
-
if (
|
|
117
|
-
serial.modules =
|
|
200
|
+
if (!equal(this.config.modules, defaultOptions.modules)) {
|
|
201
|
+
serial.modules = this.config.modules;
|
|
118
202
|
}
|
|
203
|
+
|
|
204
|
+
if (!equal(this.config.basisModule, defaultOptions.basisModule)) {
|
|
205
|
+
serial.basisModule = this.config.basisModule;
|
|
206
|
+
}
|
|
207
|
+
|
|
119
208
|
return serial;
|
|
120
209
|
},
|
|
121
210
|
i18n: {
|
|
122
211
|
de: {
|
|
123
212
|
moduleSelector: {
|
|
213
|
+
name: 'Modul Auswahl Editor',
|
|
124
214
|
title: 'Themenkartenauswahl',
|
|
125
215
|
startButton: 'Anwendung starten',
|
|
126
216
|
cardBack: 'Zurück',
|
|
217
|
+
configEditor: {
|
|
218
|
+
TooltipAddModule: 'Modul hinzufügen',
|
|
219
|
+
TooltipEditModule: 'Modul bearbeiten',
|
|
220
|
+
TooltipEditGroup: 'Modul-Gruppe bearbeiten',
|
|
221
|
+
TooltipDeleteMG: 'Modul/Gruppe löschen',
|
|
222
|
+
error: 'Bitte tragen Sie einen Namen ein',
|
|
223
|
+
editorError: 'Bitte füllen Sie das Feld aus',
|
|
224
|
+
breadcrumbs: { overview: 'Übersicht', group: 'Gruppe' },
|
|
225
|
+
heading: 'Themen- & Modulzuordnung',
|
|
226
|
+
baseModule: 'Basismodul',
|
|
227
|
+
baseModuleCheckbox: 'Basismodul anzeigen',
|
|
228
|
+
title: 'Titel',
|
|
229
|
+
add: 'Module hinzufügen',
|
|
230
|
+
addGroup: 'Module Gruppe hinzufügen',
|
|
231
|
+
moduleName: 'Module Name',
|
|
232
|
+
moduleIcon: 'Icon Name',
|
|
233
|
+
moduleUrl: 'Module URL',
|
|
234
|
+
groupName: 'Gruppen Name',
|
|
235
|
+
back: 'Zurück',
|
|
236
|
+
general: 'Allgemeine Einstellungen',
|
|
237
|
+
isActiveOnStart: 'Themenkartenauswahl beim Start der Karte zeigen',
|
|
238
|
+
requireModuleSelection: 'Modulauswahl erforderlich machen',
|
|
239
|
+
windowTitle: 'Fenster Titel',
|
|
240
|
+
windowPosition: 'Fenster Position',
|
|
241
|
+
},
|
|
127
242
|
},
|
|
128
243
|
},
|
|
129
244
|
en: {
|
|
130
245
|
moduleSelector: {
|
|
246
|
+
name: 'Module Selector Editor',
|
|
131
247
|
title: 'Theme map selection',
|
|
132
248
|
startButton: 'Start application',
|
|
133
249
|
cardBack: 'Back',
|
|
250
|
+
configEditor: {
|
|
251
|
+
TooltipAddModule: 'Add module',
|
|
252
|
+
TooltipEditModule: 'Edit module',
|
|
253
|
+
TooltipEditGroup: 'Edit module group',
|
|
254
|
+
TooltipDeleteMG: 'Delete module/group',
|
|
255
|
+
error: 'Please add a name',
|
|
256
|
+
editorError: 'Please fill in the field',
|
|
257
|
+
breadcrumbs: { overview: 'Overview', group: 'Group' },
|
|
258
|
+
heading: 'Topic & module assignment',
|
|
259
|
+
baseModule: 'Base module',
|
|
260
|
+
baseModuleCheckbox: 'Show base module',
|
|
261
|
+
title: 'Title',
|
|
262
|
+
add: 'Add module',
|
|
263
|
+
addGroup: 'Add module Group',
|
|
264
|
+
moduleName: 'Module name',
|
|
265
|
+
moduleIcon: 'Icon name',
|
|
266
|
+
moduleUrl: 'Module URL',
|
|
267
|
+
groupName: 'Group name',
|
|
268
|
+
back: 'Back',
|
|
269
|
+
general: 'General settings',
|
|
270
|
+
isActiveOnStart: 'Show theme map selection on map start',
|
|
271
|
+
requireModuleSelection: 'Require module selection',
|
|
272
|
+
windowTitle: 'Window title',
|
|
273
|
+
windowPosition: 'Window position',
|
|
274
|
+
},
|
|
134
275
|
},
|
|
135
276
|
},
|
|
136
277
|
},
|
package/src/moduleHelper.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// eslint-disable-next-line import/prefer-default-export
|
|
2
2
|
import { VcsModule } from '@vcmap/core';
|
|
3
3
|
import { VcsUiApp } from '@vcmap/ui';
|
|
4
|
+
import type { BasisModule, Module, ModuleType } from './index';
|
|
4
5
|
|
|
5
6
|
export async function loadModule(
|
|
6
7
|
moduleUrl: string,
|
|
@@ -33,3 +34,33 @@ export async function unloadModule(app: VcsUiApp): Promise<void> {
|
|
|
33
34
|
await app.maps.setActiveMap(activeMapName || [...app.maps][0]?.name);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
export const windowIdModuleSelector = 'moduleSelector_window_id';
|
|
39
|
+
|
|
40
|
+
export async function startApplication(
|
|
41
|
+
mainModuleIndex: number | undefined | null,
|
|
42
|
+
nestedModuleIndex: number | undefined | null,
|
|
43
|
+
app: VcsUiApp,
|
|
44
|
+
modules: Module<ModuleType>[],
|
|
45
|
+
basisModule?: BasisModule,
|
|
46
|
+
): Promise<void> {
|
|
47
|
+
await unloadModule(app);
|
|
48
|
+
|
|
49
|
+
if (mainModuleIndex === null && !basisModule) {
|
|
50
|
+
app.windowManager.remove(windowIdModuleSelector);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const mainModule = modules[mainModuleIndex!];
|
|
55
|
+
const nestedModule =
|
|
56
|
+
mainModule?.type === 'group'
|
|
57
|
+
? mainModule.cards?.[nestedModuleIndex!]
|
|
58
|
+
: null;
|
|
59
|
+
|
|
60
|
+
if (nestedModule?.moduleUrl) {
|
|
61
|
+
await loadModule(nestedModule.moduleUrl, app);
|
|
62
|
+
} else if (mainModule?.type === 'url') {
|
|
63
|
+
await loadModule(mainModule.moduleUrl, app);
|
|
64
|
+
}
|
|
65
|
+
app.windowManager.remove(windowIdModuleSelector);
|
|
66
|
+
}
|