@vc-shell/framework 1.0.212 → 1.0.214

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 (67) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/framework.js +1559 -1548
  3. package/dist/index.css +1 -1
  4. package/dist/locales/en.json +1 -0
  5. package/dist/shared/modules/dynamic/components/SchemaRender.d.ts +3 -3
  6. package/dist/shared/modules/dynamic/components/fields/Button.d.ts +1 -1
  7. package/dist/shared/modules/dynamic/components/fields/Card.d.ts +1 -1
  8. package/dist/shared/modules/dynamic/components/fields/Checkbox.d.ts +1 -1
  9. package/dist/shared/modules/dynamic/components/fields/ContentField.d.ts +1 -1
  10. package/dist/shared/modules/dynamic/components/fields/CustomComponent.d.ts +1 -1
  11. package/dist/shared/modules/dynamic/components/fields/DynamicProperty.d.ts +1 -1
  12. package/dist/shared/modules/dynamic/components/fields/EditorField.d.ts +1 -1
  13. package/dist/shared/modules/dynamic/components/fields/Fieldset.d.ts +1 -1
  14. package/dist/shared/modules/dynamic/components/fields/GalleryField.d.ts +1 -1
  15. package/dist/shared/modules/dynamic/components/fields/ImageField.d.ts +1 -1
  16. package/dist/shared/modules/dynamic/components/fields/InputCurrency.d.ts +1 -1
  17. package/dist/shared/modules/dynamic/components/fields/InputField.d.ts +1 -1
  18. package/dist/shared/modules/dynamic/components/fields/MultivalueField.d.ts +1 -1
  19. package/dist/shared/modules/dynamic/components/fields/RatingField.d.ts +1 -1
  20. package/dist/shared/modules/dynamic/components/fields/SelectField.d.ts +1 -1
  21. package/dist/shared/modules/dynamic/components/fields/StatusField.d.ts +1 -1
  22. package/dist/shared/modules/dynamic/components/fields/SwitchField.d.ts +1 -1
  23. package/dist/shared/modules/dynamic/components/fields/Table.d.ts +1 -1
  24. package/dist/shared/modules/dynamic/components/fields/TextareaField.d.ts +1 -1
  25. package/dist/shared/modules/dynamic/components/fields/VideoField.d.ts +1 -1
  26. package/dist/shared/modules/dynamic/components/fields/props.d.ts +1 -1
  27. package/dist/shared/modules/dynamic/components/fields/storybook/Button.stories.d.ts +3 -3
  28. package/dist/shared/modules/dynamic/components/fields/storybook/Card.stories.d.ts +3 -3
  29. package/dist/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.d.ts +3 -3
  30. package/dist/shared/modules/dynamic/components/fields/storybook/ContentField.stories.d.ts +3 -3
  31. package/dist/shared/modules/dynamic/components/fields/storybook/EditorField.stories.d.ts +3 -3
  32. package/dist/shared/modules/dynamic/components/fields/storybook/Fieldset.stories.d.ts +3 -3
  33. package/dist/shared/modules/dynamic/components/fields/storybook/GalleryField.stories.d.ts +3 -3
  34. package/dist/shared/modules/dynamic/components/fields/storybook/ImageField.stories.d.ts +3 -3
  35. package/dist/shared/modules/dynamic/components/fields/storybook/InputCurrency.stories.d.ts +3 -3
  36. package/dist/shared/modules/dynamic/components/fields/storybook/InputField.stories.d.ts +3 -3
  37. package/dist/shared/modules/dynamic/components/fields/storybook/MultivalueField.stories.d.ts +3 -3
  38. package/dist/shared/modules/dynamic/components/fields/storybook/RatingField.stories.d.ts +3 -3
  39. package/dist/shared/modules/dynamic/components/fields/storybook/SelectField.stories.d.ts +3 -3
  40. package/dist/shared/modules/dynamic/components/fields/storybook/StatusField.stories.d.ts +3 -3
  41. package/dist/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.d.ts +3 -3
  42. package/dist/shared/modules/dynamic/components/fields/storybook/VideoField.stories.d.ts +3 -3
  43. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts +3 -3
  44. package/dist/shared/modules/dynamic/factories/base/useDetailsFactory.d.ts +3 -3
  45. package/dist/shared/modules/dynamic/factories/base/useDetailsFactory.d.ts.map +1 -1
  46. package/dist/shared/modules/dynamic/factories/base/useListFactory.d.ts +2 -2
  47. package/dist/shared/modules/dynamic/factories/base/useListFactory.d.ts.map +1 -1
  48. package/dist/shared/modules/dynamic/factories/types/index.d.ts +6 -2
  49. package/dist/shared/modules/dynamic/factories/types/index.d.ts.map +1 -1
  50. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +1 -1
  51. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
  52. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +4 -3
  53. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  54. package/dist/ui/components/organisms/vc-blade/vc-blade.stories.d.ts +12 -0
  55. package/dist/ui/components/organisms/vc-blade/vc-blade.stories.d.ts.map +1 -1
  56. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts +1 -0
  57. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  58. package/package.json +4 -4
  59. package/shared/modules/dynamic/factories/base/useDetailsFactory.ts +4 -4
  60. package/shared/modules/dynamic/factories/base/useListFactory.ts +2 -2
  61. package/shared/modules/dynamic/factories/types/index.ts +12 -2
  62. package/shared/modules/dynamic/pages/dynamic-blade-form.vue +13 -9
  63. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +31 -31
  64. package/ui/components/atoms/vc-switch/vc-switch.vue +6 -12
  65. package/ui/components/atoms/vc-widget/vc-widget.vue +1 -1
  66. package/ui/components/organisms/vc-blade/vc-blade.vue +16 -0
  67. package/ui/components/organisms/vc-table/vc-table.vue +1 -1
@@ -10,6 +10,7 @@
10
10
  :class="{
11
11
  'tw-flex tw-flex-auto': isWidgetView,
12
12
  }"
13
+ :has-unsaved-changes="unref(scope)?.modified"
13
14
  @close="$emit('close:blade')"
14
15
  @expand="$emit('expand:blade')"
15
16
  @collapse="$emit('collapse:blade')"
@@ -39,20 +40,20 @@
39
40
  class="tw-grow tw-basis-0"
40
41
  :loading="loading"
41
42
  :expanded="expanded"
42
- :columns="(tableColsWithLocales as ITableColumns[]) ?? []"
43
+ :columns="tableColsWithLocales ?? []"
43
44
  :state-key="stateKey ?? ''"
44
- :items="itemsProxy as Record<string, any>[]"
45
+ :items="itemsProxy ?? []"
45
46
  :multiselect="isWidgetView ? false : tableData?.multiselect"
46
47
  :header="isWidgetView ? false : tableData?.header"
47
48
  :item-action-builder="actionBuilder"
48
49
  :enable-item-actions="!!tableData?.actions && !isWidgetView"
49
- :footer="!isWidgetView"
50
+ :footer="isWidgetView ? false : tableData?.footer"
50
51
  :sort="sort"
51
52
  :pages="pagination?.pages"
52
53
  :current-page="pagination?.currentPage"
53
54
  :search-value="searchValue"
54
55
  :selected-item-id="selectedItemId"
55
- :total-label="$t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.TABLE.TOTALS`)"
56
+ :total-label="$t(`${localizationPrefix}.PAGES.LIST.TABLE.TOTALS`)"
56
57
  :total-count="pagination?.totalCount"
57
58
  :active-filter-count="activeFilterCount"
58
59
  :reorderable-rows="isWidgetView ? false : tableData?.reorderableRows"
@@ -87,12 +88,12 @@
87
88
  <template v-else>
88
89
  <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
89
90
  <div class="tw-m-4 tw-text-xl tw-font-medium">
90
- {{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.NOT_FOUND.EMPTY`) }}
91
+ {{ $t(`${localizationPrefix}.PAGES.LIST.NOT_FOUND.EMPTY`) }}
91
92
  </div>
92
93
  <VcButton
93
94
  v-if="isFilterVisible"
94
95
  @click="resetSearch"
95
- >{{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.NOT_FOUND.RESET`) }}</VcButton
96
+ >{{ $t(`${localizationPrefix}.PAGES.LIST.NOT_FOUND.RESET`) }}</VcButton
96
97
  >
97
98
  </div>
98
99
  </template>
@@ -113,7 +114,7 @@
113
114
  <template v-else>
114
115
  <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
115
116
  <div class="tw-m-4 tw-text-xl tw-font-medium">
116
- {{ $t(`${settings?.localizationPrefix.trim().toUpperCase()}.PAGES.LIST.EMPTY.NO_ITEMS`) }}
117
+ {{ $t(`${localizationPrefix}.PAGES.LIST.EMPTY.NO_ITEMS`) }}
117
118
  </div>
118
119
  </div>
119
120
  </template>
@@ -162,6 +163,7 @@ import {
162
163
  toRefs,
163
164
  provide,
164
165
  isRef,
166
+ onMounted,
165
167
  } from "vue";
166
168
  import { useI18n } from "vue-i18n";
167
169
  import { DynamicGridSchema, ListContentSchema, SettingsSchema } from "../types";
@@ -179,7 +181,7 @@ import { safeIn } from "../helpers/safeIn";
179
181
  export interface Props {
180
182
  expanded?: boolean;
181
183
  closable?: boolean;
182
- param?: string;
184
+ param?: string | any;
183
185
  options?: unknown;
184
186
  model?: DynamicGridSchema;
185
187
  composables?: Record<string, (...args: any[]) => Record<string, any>>;
@@ -209,6 +211,7 @@ const { debounce } = useFunctions();
209
211
  const emit = defineEmits<Emits>();
210
212
 
211
213
  const settings = computed(() => props.model?.settings);
214
+ const localizationPrefix = computed(() => settings.value?.localizationPrefix.trim().toUpperCase());
212
215
  const title = computed(() => t(settings.value?.titleTemplate as string));
213
216
  const allSelected = ref(false);
214
217
  const searchValue = ref();
@@ -216,7 +219,6 @@ const selectedItemId = shallowRef();
216
219
  const sort = shallowRef("createdDate:DESC");
217
220
  const selectedIds = shallowRef<string[]>([]);
218
221
  const itemsProxy = ref<Record<string, any>[]>();
219
- const modified = shallowRef(false);
220
222
 
221
223
  const { moduleNotifications, markAsRead } = useNotifications(settings.value?.pushNotificationType);
222
224
  const { setNavigationQuery, getNavigationQuery } = useBladeNavigation();
@@ -241,7 +243,10 @@ const tableData =
241
243
  props.composables &&
242
244
  computed(() => props.model?.content.find((type: ListContentSchema) => type.component === "vc-table"));
243
245
 
244
- const tableColsWithLocales = tableData?.value?.columns?.map((col) => ({ ...col, title: computed(() => t(col.title)) }));
246
+ const tableColsWithLocales = tableData?.value?.columns?.map((col) => ({
247
+ ...col,
248
+ title: computed(() => t(col.title)),
249
+ })) as ITableColumns[];
245
250
 
246
251
  const stateKey =
247
252
  props.composables &&
@@ -347,12 +352,6 @@ const toolbarComputed =
347
352
  useToolbarReducer({
348
353
  defaultToolbarSchema: settings.value?.toolbar ?? [],
349
354
  defaultToolbarBindings: {
350
- save: {
351
- clickHandler() {
352
- emit("close:blade");
353
- },
354
- disabled: computed(() => !modified.value),
355
- },
356
355
  openAddBlade: {
357
356
  async clickHandler() {
358
357
  if (
@@ -397,14 +396,6 @@ watch(
397
396
  { immediate: true },
398
397
  );
399
398
 
400
- watch(
401
- () => itemsProxy.value,
402
- (newVal) => {
403
- modified.value = !_.isEqual(newVal, items.value);
404
- },
405
- { deep: true },
406
- );
407
-
408
399
  watch(sort, async (value) => {
409
400
  await load({ ...query.value, sort: value });
410
401
  });
@@ -430,7 +421,22 @@ const openDetailsBlade = async () => {
430
421
 
431
422
  const onItemClick = (item: { [x: string]: any; id?: string }) => {
432
423
  if (!props.isWidgetView) {
433
- if (scope && safeIn("openDetailsBlade", toValue(scope)) && typeof toValue(scope).openDetailsBlade === "function") {
424
+ // TODO Add to docs
425
+ if (scope && safeIn("onListItemClick", toValue(scope)) && typeof toValue(scope).onListItemClick === "function") {
426
+ toValue(scope).onListItemClick?.({
427
+ item,
428
+ onOpen() {
429
+ selectedItemId.value = item.id;
430
+ },
431
+ onClose() {
432
+ selectedItemId.value = undefined;
433
+ },
434
+ });
435
+ } else if (
436
+ scope &&
437
+ safeIn("openDetailsBlade", toValue(scope)) &&
438
+ typeof toValue(scope).openDetailsBlade === "function"
439
+ ) {
434
440
  toValue(scope).openDetailsBlade?.({
435
441
  param: item.id,
436
442
  onOpen() {
@@ -441,12 +447,6 @@ const onItemClick = (item: { [x: string]: any; id?: string }) => {
441
447
  },
442
448
  });
443
449
  }
444
-
445
- if (scope && safeIn("onListItemClick", toValue(scope)) && typeof toValue(scope).onListItemClick === "function") {
446
- toValue(scope).onListItemClick?.({
447
- item,
448
- });
449
- }
450
450
  } else {
451
451
  emit("item-click", { param: item.id });
452
452
  }
@@ -8,7 +8,7 @@
8
8
  >
9
9
  <span>{{ label }}</span>
10
10
  </VcLabel>
11
- <div class="tw-relative tw-inline-block tw-w-[54px] tw-h-[18px]">
11
+ <div class="tw-relative tw-inline-block tw-w-[32px] tw-h-[18px]">
12
12
  <label>
13
13
  <input
14
14
  type="checkbox"
@@ -63,11 +63,9 @@ function onInput(e: Event) {
63
63
  <style lang="scss">
64
64
  :root {
65
65
  --switch-main-color: #43b0e6;
66
- --switch-secondary-color: #565656;
66
+ --switch-secondary-color: #d2d4d7;
67
67
  --switch-transition: all 0.2s ease-in-out;
68
68
  --switch-icon-transition: opacity 0.3s ease-in-out;
69
- --switch-active-icon: url("data:image/svg+xml;utf8,<svg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M3.73609 7.34288L0.161085 3.85628C-0.0536949 3.64681 -0.0536949 3.30718 0.161085 3.09769L0.938884 2.3391C1.15366 2.12961 1.50193 2.12961 1.71671 2.3391L4.125 4.68782L8.28329 0.657101C8.49807 0.447633 8.84634 0.447633 9.06112 0.657101L9.83892 1.41569C10.0537 1.62516 10.0537 1.96479 9.83892 2.17428L4.51391 7.3429C4.29911 7.55237 3.95087 7.55237 3.73609 7.34288Z' fill='white'/></svg>");
70
- --switch-disabled-icon: url("data:image/svg+xml;utf8,<svg width='8' height='8' viewBox='0 0 8 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M5.51636 4L7.79068 1.72568C8.06977 1.44659 8.06977 0.994091 7.79068 0.714773L7.28523 0.209318C7.00614 -0.0697727 6.55364 -0.0697727 6.27432 0.209318L4 2.48364L1.72568 0.209318C1.44659 -0.0697727 0.994091 -0.0697727 0.714773 0.209318L0.209318 0.714773C-0.0697727 0.993864 -0.0697727 1.44636 0.209318 1.72568L2.48364 4L0.209318 6.27432C-0.0697727 6.55341 -0.0697727 7.00591 0.209318 7.28523L0.714773 7.79068C0.993864 8.06977 1.44659 8.06977 1.72568 7.79068L4 5.51636L6.27432 7.79068C6.55341 8.06977 7.00614 8.06977 7.28523 7.79068L7.79068 7.28523C8.06977 7.00614 8.06977 6.55364 7.79068 6.27432L5.51636 4Z' fill='white'/></svg>");
71
69
  }
72
70
 
73
71
  .vc-switch {
@@ -75,11 +73,11 @@ function onInput(e: Event) {
75
73
  @apply tw-w-0 tw-h-0 tw-opacity-0;
76
74
 
77
75
  &:checked + .vc-switch__slider:before {
78
- @apply tw-translate-x-[29px];
76
+ @apply tw-translate-x-[14px];
79
77
  }
80
78
 
81
79
  &:checked + .vc-switch__slider {
82
- @apply tw-bg-[color:var(--switch-main-color)] after:tw-bg-[image:var(--switch-active-icon)] after:tw-bg-[position:10px] after:tw-bg-[length:10px_7px];
80
+ @apply tw-bg-[color:var(--switch-main-color)] after:tw-bg-[position:10px] after:tw-bg-[length:10px_7px];
83
81
  }
84
82
 
85
83
  &:disabled + .vc-switch__slider {
@@ -88,14 +86,10 @@ function onInput(e: Event) {
88
86
  }
89
87
 
90
88
  &__slider {
91
- @apply tw-absolute tw-top-0 tw-right-0 tw-bottom-0 tw-left-0 tw-bg-[color:var(--switch-secondary-color)] tw-rounded-[3px] tw-cursor-pointer tw-transition tw-duration-200;
92
-
93
- &:after {
94
- @apply tw-inline-block tw-w-full tw-h-full tw-bg-[image:var(--switch-disabled-icon)] tw-bg-[position:calc(100%-11px)] tw-bg-no-repeat tw-bg-[length:8px_8px] tw-content-[""];
95
- }
89
+ @apply tw-absolute tw-top-0 tw-right-0 tw-bottom-0 tw-left-0 tw-bg-[color:var(--switch-secondary-color)] tw-rounded-[9999px] tw-cursor-pointer tw-transition tw-duration-200 tw-shadow-[inset_0px_2px_4px_rgba(0,0,0,0.1)];
96
90
 
97
91
  &:before {
98
- @apply tw-absolute tw-bottom-px tw-left-px tw-flex tw-justify-center tw-items-center tw-w-[23px] tw-h-[16px] tw-bg-white tw-rounded-sm tw-text-[color:#d2d2d2] tw-text-[10px] tw-transition tw-duration-200 tw-content-["|||"];
92
+ @apply tw-absolute tw-bottom-px tw-left-px tw-flex tw-justify-center tw-items-center tw-w-[16px] tw-h-[16px] tw-bg-white tw-rounded-[9999px] tw-text-[color:#d2d2d2] tw-text-[10px] tw-transition tw-shadow-[0_2px_4px_rgba(0,0,0,0.1)] tw-duration-200 tw-content-[""];
99
93
  }
100
94
  }
101
95
  }
@@ -70,7 +70,7 @@ function onClick() {
70
70
  }
71
71
 
72
72
  &__title {
73
- @apply tw-font-medium tw-text-sm tw-text-[#333333] tw-mt-3 tw-mb-1 tw-mx-0;
73
+ @apply tw-font-medium tw-text-sm tw-text-[#333333] tw-mt-3 tw-mb-1 tw-mx-0 tw-text-center;
74
74
  }
75
75
 
76
76
  &_disabled &__title {
@@ -34,6 +34,7 @@
34
34
  </template>
35
35
  </VcBladeHeader>
36
36
 
37
+ <!-- Show error message -->
37
38
  <template v-if="error">
38
39
  <div class="tw-text-white tw-p-2 tw-flex tw-flex-row tw-items-center tw-bg-[color:var(--blade-color-error)]">
39
40
  <VcIcon
@@ -50,6 +51,19 @@
50
51
  </div>
51
52
  </template>
52
53
 
54
+ <!-- Unsaved changes -->
55
+ <template v-if="hasUnsavedChanges">
56
+ <div
57
+ class="tw-text-white tw-px-2 tw-py-1 tw-flex tw-flex-row tw-items-center tw-bg-[color:var(--blade-color-unsaved-changes)]"
58
+ >
59
+ <VcIcon
60
+ size="s"
61
+ icon="fas fa-info-circle"
62
+ />
63
+ <div class="tw-line-clamp-1 tw-w-full tw-ml-2">{{ t("COMPONENTS.ORGANISMS.VC_BLADE.UNSAVED_CHANGES") }}</div>
64
+ </div>
65
+ </template>
66
+
53
67
  <!-- Set up blade toolbar -->
54
68
  <VcBladeToolbar
55
69
  class="tw-shrink-0"
@@ -78,6 +92,7 @@ export interface Props {
78
92
  expandable?: boolean;
79
93
  closable?: boolean;
80
94
  toolbarItems?: IBladeToolbar[];
95
+ hasUnsavedChanges?: boolean;
81
96
  }
82
97
 
83
98
  export interface Emits {
@@ -123,6 +138,7 @@ const { open } = usePopup({
123
138
  --blade-background-color: #ffffff;
124
139
  --blade-border-radius: 6px;
125
140
  --blade-color-error: #f14e4e;
141
+ --blade-color-unsaved-changes: #82a6bd;
126
142
  }
127
143
 
128
144
  .vc-app_mobile .vc-blade {
@@ -629,7 +629,7 @@ const mobileTemplateRenderer = ({ item }: { item: TableItem }) => {
629
629
  { class: "tw-border-b tw-border-solid tw-border-b-[#e3e7ec] tw-p-3 tw-gap-2 tw-flex tw-flex-wrap" },
630
630
  props.columns.map((x) => {
631
631
  return h("div", { class: "tw-grow tw-w-[33%] tw-ml-3 tw-truncate" }, [
632
- h(VcHint, { class: "tw-mb-1 tw-truncate" }, toValue(x.title)),
632
+ h(VcHint, { class: "tw-mb-1 tw-truncate" }, () => toValue(x.title)),
633
633
  h(VcTableCell, { cell: { ...x, class: "!tw-justify-start" }, item, class: "" }),
634
634
  ]);
635
635
  }),