@vcmap/module-selector 2.0.3 → 2.0.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.
@@ -4,7 +4,7 @@
4
4
  v-if="localConfig"
5
5
  v-bind="{ ...$attrs, ...$props }"
6
6
  >
7
- <v-container v-if="currentGroup === undefined" class="py-0 px-0">
7
+ <v-container class="py-0 px-0">
8
8
  <VcsFormSection heading="moduleSelector.configEditor.general">
9
9
  <v-container class="py-0 px-1">
10
10
  <v-row no-gutters>
@@ -91,73 +91,117 @@
91
91
  />
92
92
  </v-col>
93
93
  </v-row>
94
+ <v-row v-if="basisModuleExists" no-gutters>
95
+ <v-col cols="6">
96
+ <VcsLabel html-for="basisModuleDescription">
97
+ {{ $st('moduleSelector.configEditor.moduleDescription') }}
98
+ </VcsLabel>
99
+ </v-col>
100
+ <v-col>
101
+ <VcsTextArea
102
+ id="basisModuleDescription"
103
+ v-model="basisModule.description"
104
+ />
105
+ </v-col>
106
+ </v-row>
94
107
  </v-container>
95
108
  </VcsFormSection>
96
109
  </v-container>
97
- <v-container v-else class="py-0 px-1">
98
- <v-breadcrumbs :items="breadcrumbItems" divider="/">
99
- <template #item="{ item }">
100
- <v-breadcrumbs-item
101
- :key="item.title"
102
- :disabled="item.disabled"
103
- :href="item.href"
104
- @click="item.disabled ? null : returnLevel()"
105
- >
106
- {{ item.title }}
107
- </v-breadcrumbs-item>
108
- </template>
109
- </v-breadcrumbs>
110
-
111
- <v-row no-gutters>
112
- <v-col cols="6">
113
- <VcsLabel required html-for="groupModuleName">
114
- {{ $st('moduleSelector.configEditor.groupName') }}
115
- </VcsLabel>
116
- </v-col>
117
- <v-col>
118
- <VcsTextField
119
- id="groupModuleName"
120
- placeholder="Module Name"
121
- v-model="currentGroup!.title"
122
- :rules="[(v: string) => !!v || 'moduleSelector.configEditor.error']"
110
+ <v-dialog v-model="groupItemDialogVisible" width="800" :persistent="true">
111
+ <v-sheet v-if="currentGroup">
112
+ <VcsFormSection
113
+ heading="moduleSelector.configEditor.groupHeading"
114
+ :start-open="true"
115
+ >
116
+ <v-form v-model="isFormValid">
117
+ <v-container class="py-0 px-1">
118
+ <v-row no-gutters>
119
+ <v-col cols="6">
120
+ <VcsLabel required html-for="groupModuleName">
121
+ {{ $st('moduleSelector.configEditor.groupName') }}
122
+ </VcsLabel>
123
+ </v-col>
124
+ <v-col>
125
+ <VcsTextField
126
+ id="groupModuleName"
127
+ placeholder="Module Name"
128
+ v-model="currentGroup.title"
129
+ :rules="[isRequired]"
130
+ />
131
+ </v-col>
132
+ </v-row>
133
+ <v-row no-gutters>
134
+ <v-col cols="6">
135
+ <VcsLabel required html-for="groupModuleIcon">
136
+ {{ $st('moduleSelector.configEditor.moduleIcon') }}
137
+ </VcsLabel>
138
+ </v-col>
139
+ <v-col>
140
+ <VcsTextField
141
+ id="groupModuleIcon"
142
+ placeholder="Module Icon"
143
+ v-model="currentGroup.icon"
144
+ :rules="[isRequired]"
145
+ />
146
+ </v-col>
147
+ </v-row>
148
+ <v-row no-gutters>
149
+ <v-col cols="6">
150
+ <VcsLabel html-for="groupModuleDescription">
151
+ {{ $st('moduleSelector.configEditor.groupDescription') }}
152
+ </VcsLabel>
153
+ </v-col>
154
+ <v-col>
155
+ <VcsTextArea
156
+ id="groupModuleDescription"
157
+ placeholder=""
158
+ v-model="currentGroup.description"
159
+ />
160
+ </v-col>
161
+ </v-row>
162
+ </v-container>
163
+ </v-form>
164
+ </VcsFormSection>
165
+ <VcsFormSection
166
+ heading="moduleSelector.configEditor.heading2"
167
+ :start-open="true"
168
+ :header-actions="headerActions"
169
+ >
170
+ <VcsList
171
+ class="draggable-list"
172
+ :items="currentGroup.cards"
173
+ :draggable="true"
174
+ @item-moved="moveCard"
123
175
  />
124
- </v-col>
125
- </v-row>
126
- <v-row no-gutters>
127
- <v-col cols="6">
128
- <VcsLabel required html-for="groupModuleIcon">
129
- {{ $st('moduleSelector.configEditor.moduleIcon') }}
130
- </VcsLabel>
131
- </v-col>
132
- <v-col>
133
- <VcsTextField
134
- id="groupModuleIcon"
135
- placeholder="Module Icon"
136
- v-model="currentGroup!.icon"
137
- :rules="[
138
- (v: string) => !!v || 'moduleSelector.configEditor.editorError',
139
- ]"
140
- />
141
- </v-col>
142
- </v-row>
143
- </v-container>
176
+ </VcsFormSection>
177
+ <div class="d-flex gc-2 px-2 pt-2 pb-2">
178
+ <div class="d-flex gc-2 justify-end w-100">
179
+ <VcsFormButton
180
+ variant="filled"
181
+ :disabled="!isFormValid"
182
+ @click="returnLevel()"
183
+ >
184
+ {{ $t('components.apply') }}
185
+ </VcsFormButton>
186
+ <VcsFormButton @click="cancelCurrentGroup()">
187
+ {{ $t('components.cancel') }}
188
+ </VcsFormButton>
189
+ </div>
190
+ </div>
191
+ </v-sheet>
192
+ </v-dialog>
193
+
144
194
  <VcsFormSection
145
195
  heading="moduleSelector.configEditor.heading"
146
196
  :start-open="true"
147
197
  :header-actions="headerActions"
148
198
  >
149
199
  <VcsList
150
- v-if="currentGroup === undefined"
151
200
  :items="listItemArray"
152
201
  :draggable="true"
153
- @item-moved="move"
154
- />
155
- <VcsList
156
- v-else
157
- :items="currentGroup.cards"
158
- :draggable="true"
159
- @item-moved="move"
202
+ @item-moved="moveItem"
160
203
  />
204
+
161
205
  <v-dialog
162
206
  v-model="editingItemDialogVisible"
163
207
  width="400"
@@ -212,12 +256,12 @@
212
256
  VcsList,
213
257
  VcsListItem,
214
258
  VcsTextField,
215
- VcsUiApp,
259
+ VcsTextArea,
260
+ VcsFormButton,
216
261
  } from '@vcmap/ui';
217
262
  import {
218
263
  computed,
219
264
  defineComponent,
220
- inject,
221
265
  PropType,
222
266
  reactive,
223
267
  Ref,
@@ -226,12 +270,12 @@
226
270
  watch,
227
271
  } from 'vue';
228
272
  import {
229
- VBreadcrumbs,
230
- VBreadcrumbsItem,
231
273
  VCol,
232
274
  VContainer,
233
275
  VDialog,
234
276
  VRow,
277
+ VSheet,
278
+ VForm,
235
279
  } from 'vuetify/components';
236
280
  import ModuleEditor from './ModuleEditor.vue';
237
281
  import { Module, ModuleSelectorConfig, ModuleType } from '../index';
@@ -245,28 +289,38 @@
245
289
  icon: string;
246
290
  type: string;
247
291
  moduleUrl?: string;
292
+ description?: string;
248
293
  cards?: VcsListItemWithLabel[];
249
294
  }
295
+ interface ModuleItem {
296
+ id: string;
297
+ title: string;
298
+ icon: string;
299
+ moduleUrl: string;
300
+ description?: string;
301
+ }
250
302
 
251
303
  export const windowIdConfigEditor = 'configEditor_window_id';
252
304
  export default defineComponent({
253
305
  name: 'ModuleSelectorConfigEditor',
254
306
  components: {
307
+ VForm,
308
+ VcsFormButton,
255
309
  VcsCheckbox,
256
310
  VDialog,
257
311
  VcsList,
258
312
  VcsFormSection,
259
313
  VRow,
314
+ VSheet,
260
315
  VcsLabel,
261
316
  AbstractConfigEditor,
262
317
  VcsTextField,
263
318
  VCol,
264
319
  VContainer,
265
320
  ModuleEditor,
266
- VBreadcrumbs,
267
- VBreadcrumbsItem,
268
321
  WindowPositionSettings,
269
322
  VcsModuleTable: CloudModuleSelector,
323
+ VcsTextArea,
270
324
  },
271
325
  props: {
272
326
  getConfig: {
@@ -279,24 +333,34 @@
279
333
  },
280
334
  },
281
335
  setup(props) {
282
- const app = inject('vcsApp') as VcsUiApp;
283
336
  const level = ref<number>(0);
284
337
  const localConfig = ref<ModuleSelectorConfig | undefined>(undefined);
285
338
  const listItemArray: Ref<VcsListItemWithLabel[]> = ref([]);
286
339
  const currentGroup: Ref<VcsListItemWithLabel | undefined> =
287
340
  ref(undefined);
288
- const editingItem: Ref<{
289
- id: string;
290
- title: string;
291
- icon: string;
292
- moduleUrl: string;
293
- }> = ref({ id: '', title: '', icon: '', moduleUrl: '' });
294
- const selectCloudItem: Ref<{
295
- id: string;
296
- title: string;
297
- icon: string;
298
- moduleUrl: string;
299
- }> = ref({ id: '', title: '', icon: '', moduleUrl: '' });
341
+ const editingItem: Ref<ModuleItem> = ref({
342
+ id: '',
343
+ title: '',
344
+ icon: '',
345
+ moduleUrl: '',
346
+ description: '',
347
+ });
348
+ const selectCloudItem: Ref<ModuleItem> = ref({
349
+ id: '',
350
+ title: '',
351
+ icon: '',
352
+ moduleUrl: '',
353
+ description: '',
354
+ });
355
+
356
+ let selectedGroupItem: Module<ModuleType> = {
357
+ title: '',
358
+ icon: '',
359
+ type: 'group',
360
+ description: '',
361
+ cards: [],
362
+ };
363
+
300
364
  const selectCloudItemDialogVisible: Ref<boolean> = ref(false);
301
365
  const editingItemDialogVisible: Ref<boolean> = ref(false);
302
366
  const groupItemDialogVisible: Ref<boolean> = ref(false);
@@ -327,6 +391,36 @@
327
391
  });
328
392
  const headerActions = reactive<VcsAction[]>([]);
329
393
 
394
+ function removeIdAndActions(
395
+ item: VcsListItemWithLabel,
396
+ ): Module<ModuleType> {
397
+ if (item.type === 'url') {
398
+ const { actions, id, name, ...configItem } = item;
399
+ return {
400
+ ...configItem,
401
+ moduleUrl: item.moduleUrl || '',
402
+ } as Module<'url'>;
403
+ } else {
404
+ const updatedCards =
405
+ item.cards?.map((card) => {
406
+ const { actions, id, name, ...configItem } = card;
407
+ return {
408
+ ...configItem,
409
+ } as Module<'url'>;
410
+ }) || [];
411
+ const { actions, id, name, ...configItem } = item;
412
+ return {
413
+ ...configItem,
414
+ ...(updatedCards.length ? { cards: updatedCards } : {}),
415
+ } as Module<'group'>;
416
+ }
417
+ }
418
+
419
+ function removeIdAndActionsFromArray(
420
+ items: VcsListItemWithLabel[],
421
+ ): Module<ModuleType>[] {
422
+ return items.map(removeIdAndActions);
423
+ }
330
424
  function createListItem(
331
425
  moduleInfo: Module<ModuleType>,
332
426
  index: number,
@@ -337,6 +431,7 @@
337
431
  title: moduleInfo.title,
338
432
  icon: moduleInfo.icon,
339
433
  type: moduleInfo.type,
434
+ description: moduleInfo.description,
340
435
  actions: [],
341
436
  };
342
437
  if (moduleInfo.type === 'url') {
@@ -360,6 +455,7 @@
360
455
  title: item.title,
361
456
  icon: item.icon,
362
457
  moduleUrl: item.moduleUrl!,
458
+ description: item.description,
363
459
  };
364
460
  }
365
461
  } else {
@@ -373,6 +469,7 @@
373
469
  title: item.title,
374
470
  icon: item.icon,
375
471
  moduleUrl: item.moduleUrl!,
472
+ description: item.description,
376
473
  };
377
474
  }
378
475
  }
@@ -392,6 +489,15 @@
392
489
  );
393
490
  if (item) {
394
491
  currentGroup.value = item;
492
+ groupItemDialogVisible.value = true;
493
+ const [firstItem] = removeIdAndActionsFromArray([
494
+ currentGroup.value,
495
+ ]) as Module<'group'>[];
496
+ if (firstItem.cards.length === 0) {
497
+ firstItem.cards = [];
498
+ }
499
+ selectedGroupItem = structuredClone(firstItem);
500
+
395
501
  headerActions.splice(2, 1);
396
502
  if (headerActions.length > 1) {
397
503
  headerActions[1].icon = '$vcsPlus';
@@ -427,6 +533,7 @@
427
533
 
428
534
  headerActions.push({
429
535
  name: 'moduleSelector.configEditor.addFromCloud',
536
+ title: 'moduleSelector.configEditor.TooltipAddCloudModule',
430
537
  icon: '$vcsImport',
431
538
  callback(): void {
432
539
  selectCloudItem.value = {
@@ -434,36 +541,12 @@
434
541
  title: '',
435
542
  icon: '',
436
543
  moduleUrl: '',
544
+ description: '',
437
545
  };
438
546
  selectCloudItemDialogVisible.value = true;
439
547
  },
440
548
  });
441
549
 
442
- function removeIdAndActions(
443
- item: VcsListItemWithLabel,
444
- ): Module<ModuleType> {
445
- if (item.type === 'url') {
446
- const { actions, id, name, ...configItem } = item;
447
- return {
448
- ...configItem,
449
- moduleUrl: item.moduleUrl || '',
450
- } as Module<'url'>;
451
- } else {
452
- const updatedCards =
453
- item.cards?.map((card) => {
454
- const { actions, id, name, ...configItem } = card;
455
- return {
456
- ...configItem,
457
- } as Module<'url'>;
458
- }) || [];
459
- const { actions, id, name, ...configItem } = item;
460
- return {
461
- ...configItem,
462
- ...(updatedCards.length ? { cards: updatedCards } : {}),
463
- } as Module<'group'>;
464
- }
465
- }
466
-
467
550
  const headerGroupAction = {
468
551
  name: 'moduleSelector.configEditor.addGroup',
469
552
  callback(): void {
@@ -471,6 +554,7 @@
471
554
  type: 'group',
472
555
  title: '',
473
556
  icon: '',
557
+ description: '',
474
558
  cards: [],
475
559
  };
476
560
 
@@ -483,6 +567,7 @@
483
567
  );
484
568
 
485
569
  currentGroup.value = listItemArray.value[indexItem - 1];
570
+ groupItemDialogVisible.value = true;
486
571
 
487
572
  headerActions.splice(2, 1);
488
573
  if (headerActions.length > 1) {
@@ -492,13 +577,6 @@
492
577
  }
493
578
  },
494
579
  };
495
-
496
- function removeIdAndActionsFromArray(
497
- items: VcsListItemWithLabel[],
498
- ): Module<ModuleType>[] {
499
- return items.map(removeIdAndActions);
500
- }
501
-
502
580
  if (localConfig.value?.modules) {
503
581
  listItemArray.value = localConfig.value.modules.map(createListItem);
504
582
  }
@@ -512,6 +590,7 @@
512
590
  title: '',
513
591
  icon: '',
514
592
  moduleUrl: '',
593
+ description: '',
515
594
  };
516
595
  editingItemDialogVisible.value = true;
517
596
  },
@@ -622,6 +701,7 @@
622
701
  title: '',
623
702
  icon: '',
624
703
  moduleUrl: '',
704
+ description: '',
625
705
  };
626
706
  editingItemDialogVisible.value = false;
627
707
  };
@@ -636,6 +716,7 @@
636
716
  icon: selectCloudItem.value.icon,
637
717
  moduleUrl: selectCloudItem.value.moduleUrl,
638
718
  type: 'url',
719
+ description: selectCloudItem.value.description,
639
720
  },
640
721
  listItemArray.value.length,
641
722
  ),
@@ -668,11 +749,14 @@
668
749
  title: '',
669
750
  icon: '',
670
751
  moduleUrl: '',
752
+ description: '',
671
753
  };
672
754
  selectCloudItemDialogVisible.value = false;
673
755
  };
674
756
 
675
757
  const returnLevel = (): void => {
758
+ groupItemDialogVisible.value = false;
759
+
676
760
  currentGroup.value = undefined;
677
761
  if (headerActions.length > 1) {
678
762
  delete headerActions[1].icon;
@@ -681,34 +765,45 @@
681
765
  headerActions.push(headerGroupAction);
682
766
  };
683
767
 
684
- const breadcrumbItems = ref([
685
- {
686
- title: app.vueI18n.t(
687
- 'moduleSelector.configEditor.breadcrumbs.overview',
688
- ),
689
- disabled: false,
690
- href: '#',
691
- },
692
- {
693
- title: app.vueI18n.t('moduleSelector.configEditor.breadcrumbs.group'),
694
- disabled: true,
695
- href: '#',
696
- },
697
- ]);
698
- watch(currentGroup, (currentG) => {
699
- if (currentG && currentG.title) {
700
- breadcrumbItems.value[1].title = `${app.vueI18n.t('moduleSelector.configEditor.breadcrumbs.group')}: ${currentG.title}`;
701
- currentG.name = currentG.title;
768
+ const isRequired = (v: string): boolean | string => {
769
+ return v && v.trim() !== ''
770
+ ? true
771
+ : 'moduleSelector.configEditor.error';
772
+ };
773
+
774
+ const isFormValid = ref();
775
+
776
+ const cancelCurrentGroup = (): void => {
777
+ const groupIndex = listItemArray.value.findIndex(
778
+ (item) => item.id === currentGroup.value!.id,
779
+ );
780
+ if (selectedGroupItem.title !== '') {
781
+ const newGroupItem = createListItem(selectedGroupItem, groupIndex);
782
+ listItemArray.value.splice(groupIndex, 1, newGroupItem);
783
+ } else {
784
+ listItemArray.value.splice(groupIndex, 1);
702
785
  }
703
- });
786
+
787
+ groupItemDialogVisible.value = false;
788
+ currentGroup.value = undefined;
789
+ if (headerActions.length > 1) {
790
+ delete headerActions[1].icon;
791
+ delete headerActions[1].title;
792
+ }
793
+ headerActions.push(headerGroupAction);
794
+ };
795
+
704
796
  return {
797
+ isFormValid,
705
798
  editingItem,
799
+ selectedGroupItem,
800
+ groupItemDialogVisible,
801
+ cancelCurrentGroup,
706
802
  selectCloudItem,
707
803
  editingItemDialogVisible,
708
804
  selectCloudItemDialogVisible,
709
805
  localConfig,
710
806
  listItemArray,
711
- breadcrumbItems,
712
807
  currentGroup,
713
808
  apply,
714
809
  returnLevel,
@@ -719,37 +814,31 @@
719
814
  basisModule,
720
815
  basisModuleExists,
721
816
  headerActions,
722
- move({
817
+ isRequired,
818
+ moveItem({
723
819
  item,
724
820
  targetIndex,
725
821
  }: {
726
822
  item: VcsListItemWithLabel;
727
823
  targetIndex: number;
728
824
  }): void {
729
- if (listItemArray.value && currentGroup.value === undefined) {
730
- let target = targetIndex;
731
- target = target >= 0 ? target : 0;
732
- target =
733
- target < listItemArray.value?.length
734
- ? target
735
- : listItemArray.value.length - 1;
736
- const from = listItemArray.value?.indexOf(item);
737
- if (from !== target) {
738
- listItemArray.value?.splice(from, 1);
739
- listItemArray.value?.splice(target, 0, item);
740
- }
741
- } else if ((currentGroup.value?.cards?.length ?? 0) > 1) {
742
- let target = targetIndex;
743
- target = target >= 0 ? target : 0;
744
- target =
745
- target < currentGroup.value!.cards!.length
746
- ? target
747
- : currentGroup.value!.cards!.length - 1;
748
- const from = currentGroup.value!.cards!.indexOf(item);
749
- if (from && from !== target) {
750
- currentGroup.value!.cards!.splice(from, 1);
751
- currentGroup.value!.cards!.splice(target, 0, item);
752
- }
825
+ const from = listItemArray.value?.indexOf(item);
826
+ if (from !== targetIndex) {
827
+ listItemArray.value?.splice(from, 1);
828
+ listItemArray.value?.splice(targetIndex, 0, item);
829
+ }
830
+ },
831
+ moveCard({
832
+ item,
833
+ targetIndex,
834
+ }: {
835
+ item: VcsListItemWithLabel;
836
+ targetIndex: number;
837
+ }): void {
838
+ const from = currentGroup.value!.cards!.indexOf(item);
839
+ if (from !== targetIndex) {
840
+ currentGroup.value?.cards?.splice(from, 1);
841
+ currentGroup.value?.cards?.splice(targetIndex, 0, item);
753
842
  }
754
843
  },
755
844
  };
@@ -757,8 +846,4 @@
757
846
  });
758
847
  </script>
759
848
 
760
- <style scoped>
761
- .v-breadcrumbs {
762
- padding: 16px 0 4px 0;
763
- }
764
- </style>
849
+ <style scoped></style>
@@ -8,6 +8,7 @@ export default (): ModuleSelectorConfig => ({
8
8
  left: '33%',
9
9
  right: '33%',
10
10
  top: '10%',
11
+ maxHeight: '80%',
11
12
  },
12
13
  basisModule: undefined,
13
14
  modules: [],