@vc-shell/framework 1.0.57 → 1.0.59

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 (139) hide show
  1. package/core/plugins/validation/rules.ts +67 -24
  2. package/core/types/index.ts +19 -2
  3. package/dist/framework.mjs +1859 -4863
  4. package/dist/index.css +1 -1
  5. package/dist/types/core/plugins/validation/rules.d.ts +8 -30
  6. package/dist/types/core/plugins/validation/rules.d.ts.map +1 -1
  7. package/dist/types/core/types/index.d.ts +17 -2
  8. package/dist/types/core/types/index.d.ts.map +1 -1
  9. package/dist/types/index.d.ts.map +1 -1
  10. package/dist/types/shared/components/app-switcher/components/index.d.ts.map +1 -0
  11. package/dist/types/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/index.d.ts +5 -5
  12. package/dist/types/shared/components/app-switcher/components/vc-app-switcher/index.d.ts.map +1 -0
  13. package/dist/types/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/vc-app-switcher.vue.d.ts +1 -1
  14. package/dist/types/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +1 -0
  15. package/dist/types/shared/components/app-switcher/composables/index.d.ts.map +1 -0
  16. package/dist/types/shared/{app-switcher → components/app-switcher}/composables/useAppSwitcher/index.d.ts +1 -1
  17. package/dist/types/shared/components/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -0
  18. package/dist/types/shared/components/app-switcher/index.d.ts.map +1 -0
  19. package/dist/types/shared/components/blade-navigation/components/index.d.ts.map +1 -0
  20. package/dist/types/shared/components/blade-navigation/components/vc-blade-navigation/index.d.ts.map +1 -0
  21. package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts +1 -1
  22. package/dist/types/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -0
  23. package/dist/types/shared/components/blade-navigation/composables/index.d.ts.map +1 -0
  24. package/dist/types/shared/{blade-navigation → components/blade-navigation}/composables/useBladeNavigation/index.d.ts +1 -1
  25. package/dist/types/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -0
  26. package/dist/types/shared/components/blade-navigation/index.d.ts.map +1 -0
  27. package/dist/types/shared/{blade-navigation → components/blade-navigation}/types/index.d.ts +1 -1
  28. package/dist/types/shared/components/blade-navigation/types/index.d.ts.map +1 -0
  29. package/dist/types/shared/index.d.ts +4 -3
  30. package/dist/types/shared/index.d.ts.map +1 -1
  31. package/dist/types/shared/{assets → modules/assets}/components/assets-details/assets-details.vue.d.ts +4 -13
  32. package/dist/types/shared/modules/assets/components/assets-details/assets-details.vue.d.ts.map +1 -0
  33. package/dist/types/shared/{assets → modules/assets}/components/assets-details/index.d.ts +6 -7
  34. package/dist/types/shared/modules/assets/components/assets-details/index.d.ts.map +1 -0
  35. package/dist/types/shared/modules/assets/components/index.d.ts.map +1 -0
  36. package/dist/types/shared/modules/assets/index.d.ts.map +1 -0
  37. package/dist/types/shared/modules/assets/locales/index.d.ts +3 -0
  38. package/dist/types/shared/modules/assets/locales/index.d.ts.map +1 -0
  39. package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts +58 -0
  40. package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -0
  41. package/dist/types/shared/modules/assets-manager/components/assets-manager/index.d.ts +59 -0
  42. package/dist/types/shared/modules/assets-manager/components/assets-manager/index.d.ts.map +1 -0
  43. package/dist/types/shared/modules/assets-manager/components/index.d.ts +2 -0
  44. package/dist/types/shared/modules/assets-manager/components/index.d.ts.map +1 -0
  45. package/dist/types/shared/modules/assets-manager/index.d.ts +12 -0
  46. package/dist/types/shared/modules/assets-manager/index.d.ts.map +1 -0
  47. package/dist/types/shared/modules/assets-manager/locales/index.d.ts.map +1 -0
  48. package/dist/types/shared/utilities/assets.d.ts +5 -0
  49. package/dist/types/shared/utilities/assets.d.ts.map +1 -0
  50. package/dist/types/ui/components/atoms/vc-checkbox/vc-checkbox.vue.d.ts.map +1 -1
  51. package/dist/types/ui/components/molecules/vc-file-upload/vc-file-upload.vue.d.ts.map +1 -1
  52. package/dist/types/ui/components/molecules/vc-input/index.d.ts +0 -4
  53. package/dist/types/ui/components/molecules/vc-input/index.d.ts.map +1 -1
  54. package/dist/types/ui/components/molecules/vc-input/vc-input.vue.d.ts +1 -1
  55. package/dist/types/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  56. package/dist/types/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
  57. package/dist/types/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts.map +1 -1
  58. package/dist/types/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts +2 -19
  59. package/dist/types/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
  60. package/dist/types/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts +2 -20
  61. package/dist/types/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts.map +1 -1
  62. package/dist/types/ui/components/organisms/vc-gallery/index.d.ts +30 -33
  63. package/dist/types/ui/components/organisms/vc-gallery/index.d.ts.map +1 -1
  64. package/dist/types/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts +2 -6
  65. package/dist/types/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts.map +1 -1
  66. package/dist/types/ui/components/organisms/vc-table/index.d.ts +49 -37
  67. package/dist/types/ui/components/organisms/vc-table/index.d.ts.map +1 -1
  68. package/dist/types/ui/components/organisms/vc-table/vc-table.stories.d.ts +49 -37
  69. package/dist/types/ui/components/organisms/vc-table/vc-table.stories.d.ts.map +1 -1
  70. package/dist/types/ui/components/organisms/vc-table/vc-table.vue.d.ts +12 -7
  71. package/dist/types/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
  72. package/package.json +5 -6
  73. package/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/vc-app-switcher.vue +1 -1
  74. package/shared/{app-switcher → components/app-switcher}/composables/useAppSwitcher/index.ts +2 -2
  75. package/shared/{app-switcher → components/app-switcher}/index.ts +1 -1
  76. package/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/vc-blade-navigation.vue +2 -2
  77. package/shared/{blade-navigation → components/blade-navigation}/composables/useBladeNavigation/index.ts +6 -5
  78. package/shared/{blade-navigation → components/blade-navigation}/index.ts +1 -1
  79. package/shared/{blade-navigation → components/blade-navigation}/types/index.ts +1 -1
  80. package/shared/index.ts +10 -7
  81. package/shared/modules/assets/components/assets-details/assets-details.vue +166 -0
  82. package/shared/{assets → modules/assets}/index.ts +1 -1
  83. package/shared/{assets → modules/assets}/locales/en.json +7 -5
  84. package/shared/modules/assets/locales/index.ts +2 -0
  85. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +372 -0
  86. package/shared/modules/assets-manager/components/assets-manager/index.ts +3 -0
  87. package/shared/modules/assets-manager/components/index.ts +1 -0
  88. package/shared/modules/assets-manager/index.ts +14 -0
  89. package/shared/modules/assets-manager/locales/en.json +28 -0
  90. package/shared/utilities/assets.ts +40 -0
  91. package/ui/components/atoms/vc-checkbox/vc-checkbox.vue +1 -11
  92. package/ui/components/molecules/vc-file-upload/vc-file-upload.vue +1 -0
  93. package/ui/components/molecules/vc-input/vc-input.vue +1 -1
  94. package/ui/components/molecules/vc-select/vc-select.vue +2 -2
  95. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +3 -2
  96. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +3 -6
  97. package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +2 -6
  98. package/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +6 -0
  99. package/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue +5 -11
  100. package/ui/components/organisms/vc-gallery/vc-gallery.vue +164 -49
  101. package/ui/components/organisms/vc-table/vc-table.vue +171 -100
  102. package/dist/types/shared/app-switcher/components/index.d.ts.map +0 -1
  103. package/dist/types/shared/app-switcher/components/vc-app-switcher/index.d.ts.map +0 -1
  104. package/dist/types/shared/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +0 -1
  105. package/dist/types/shared/app-switcher/composables/index.d.ts.map +0 -1
  106. package/dist/types/shared/app-switcher/composables/useAppSwitcher/index.d.ts.map +0 -1
  107. package/dist/types/shared/app-switcher/index.d.ts.map +0 -1
  108. package/dist/types/shared/assets/components/assets-details/assets-details.vue.d.ts.map +0 -1
  109. package/dist/types/shared/assets/components/assets-details/index.d.ts.map +0 -1
  110. package/dist/types/shared/assets/components/index.d.ts.map +0 -1
  111. package/dist/types/shared/assets/index.d.ts.map +0 -1
  112. package/dist/types/shared/assets/locales/index.d.ts.map +0 -1
  113. package/dist/types/shared/blade-navigation/components/index.d.ts.map +0 -1
  114. package/dist/types/shared/blade-navigation/components/vc-blade-navigation/index.d.ts.map +0 -1
  115. package/dist/types/shared/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +0 -1
  116. package/dist/types/shared/blade-navigation/composables/index.d.ts.map +0 -1
  117. package/dist/types/shared/blade-navigation/composables/useBladeNavigation/index.d.ts.map +0 -1
  118. package/dist/types/shared/blade-navigation/index.d.ts.map +0 -1
  119. package/dist/types/shared/blade-navigation/types/index.d.ts.map +0 -1
  120. package/shared/assets/components/assets-details/assets-details.vue +0 -116
  121. /package/dist/types/shared/{app-switcher → components/app-switcher}/components/index.d.ts +0 -0
  122. /package/dist/types/shared/{app-switcher → components/app-switcher}/composables/index.d.ts +0 -0
  123. /package/dist/types/shared/{app-switcher → components/app-switcher}/index.d.ts +0 -0
  124. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/index.d.ts +0 -0
  125. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/index.d.ts +0 -0
  126. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/composables/index.d.ts +0 -0
  127. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/index.d.ts +0 -0
  128. /package/dist/types/shared/{assets → modules/assets}/components/index.d.ts +0 -0
  129. /package/dist/types/shared/{assets → modules/assets}/index.d.ts +0 -0
  130. /package/dist/types/shared/{assets → modules/assets-manager}/locales/index.d.ts +0 -0
  131. /package/shared/{app-switcher → components/app-switcher}/components/index.ts +0 -0
  132. /package/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/index.ts +0 -0
  133. /package/shared/{app-switcher → components/app-switcher}/composables/index.ts +0 -0
  134. /package/shared/{blade-navigation → components/blade-navigation}/components/index.ts +0 -0
  135. /package/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/index.ts +0 -0
  136. /package/shared/{blade-navigation → components/blade-navigation}/composables/index.ts +0 -0
  137. /package/shared/{assets → modules/assets}/components/assets-details/index.ts +0 -0
  138. /package/shared/{assets → modules/assets}/components/index.ts +0 -0
  139. /package/shared/{assets → modules/assets-manager}/locales/index.ts +0 -0
@@ -1,4 +1,4 @@
1
- import { createModule } from "../../core/plugins/modularity";
1
+ import { createModule } from "../../../core/plugins/modularity";
2
2
  import * as components from "./components";
3
3
  import * as locales from "./locales";
4
4
 
@@ -2,15 +2,18 @@
2
2
  "ASSETS": {
3
3
  "PAGES": {
4
4
  "DETAILS": {
5
- "SUBTITLE": "Image edit",
5
+ "SUBTITLE": "Asset edit",
6
6
  "TOOLBAR": {
7
7
  "SAVE": "Save",
8
8
  "DELETE": "Delete"
9
9
  },
10
10
  "FIELDS": {
11
+ "SIZE": "Size",
12
+ "CREATED_DATE": "Created date",
13
+ "URL": "Url",
11
14
  "NAME": {
12
- "TITLE": "Image name",
13
- "PLACEHOLDER": "Enter image name"
15
+ "TITLE": "Asset name",
16
+ "PLACEHOLDER": "Enter asset name"
14
17
  },
15
18
  "ALT": {
16
19
  "TITLE": "Image alternative text",
@@ -21,8 +24,7 @@
21
24
  "TITLE": "Meta description",
22
25
  "PLACEHOLDER": "Enter meta description"
23
26
  }
24
- },
25
- "DELETE_CONFIRMATION": "Are you sure you want to delete this image?"
27
+ }
26
28
  }
27
29
  }
28
30
  }
@@ -0,0 +1,2 @@
1
+ import * as en from "./en.json";
2
+ export { en };
@@ -0,0 +1,372 @@
1
+ <template>
2
+ <VcBlade
3
+ :title="$t('ASSETS_MANAGER.TITLE')"
4
+ :expanded="expanded"
5
+ :closable="closable"
6
+ :toolbarItems="bladeToolbar"
7
+ @close="$emit('close:blade')"
8
+ width="50%"
9
+ >
10
+ <div
11
+ class="tw-relative tw-h-full"
12
+ @dragover.prevent.stop="dragOver"
13
+ @dragleave.prevent="dragLeave"
14
+ @drop.prevent.stop="onDrop"
15
+ >
16
+ <VcLoading :active="loading"></VcLoading>
17
+ <VcTable
18
+ :columns="columns"
19
+ :expanded="expanded"
20
+ stateKey="assets_manager"
21
+ :reorderableRows="true"
22
+ :items="defaultAssets"
23
+ :header="false"
24
+ :footer="false"
25
+ :itemActionBuilder="actionBuilder"
26
+ multiselect
27
+ class="tw-h-full tw-w-full"
28
+ @item-click="onItemClick"
29
+ @row:reorder="sortAssets"
30
+ @selectionChanged="onSelectionChanged"
31
+ >
32
+ <!-- Empty template -->
33
+ <template v-slot:empty>
34
+ <div class="tw-w-full tw-h-full tw-box-border tw-flex tw-flex-col tw-items-center tw-justify-center">
35
+ <VcIcon
36
+ icon="fas fa-cloud-upload-alt"
37
+ class="tw-text-[100px] tw-text-[#41afe6]"
38
+ ></VcIcon>
39
+ <div class="tw-m-4 tw-text-xl tw-font-medium">
40
+ {{ $t("ASSETS_MANAGER.EMPTY.NO_ASSETS") }}
41
+ </div>
42
+ <VcButton @click="toggleUploader">{{ $t("ASSETS_MANAGER.EMPTY.UPLOAD") }}</VcButton>
43
+ </div>
44
+ </template>
45
+
46
+ <!-- Override size column -->
47
+ <template v-slot:item_size="{ item }">
48
+ <div>
49
+ {{ readableSize(item.size) }}
50
+ </div>
51
+ </template>
52
+
53
+ <!-- Override url column -->
54
+ <template v-slot:item_url="{ item }">
55
+ <div class="tw-flex tw-items-center tw-justify-center">
56
+ <template v-if="isImage(item.name)">
57
+ <VcImage
58
+ :bordered="true"
59
+ size="s"
60
+ aspect="1x1"
61
+ :src="item.url"
62
+ background="contain"
63
+ ></VcImage>
64
+ </template>
65
+ <template v-else>
66
+ <VcIcon
67
+ :icon="getFileThumbnail(item.name)"
68
+ class="tw-text-[#a9bfd2] tw-text-[38px]"
69
+ ></VcIcon>
70
+ </template>
71
+ </div>
72
+ </template>
73
+
74
+ <!-- Overide order column -->
75
+ <template v-slot:item_sortOrder="{ item }">
76
+ <div>
77
+ {{ item.sortOrder }}
78
+ </div>
79
+ </template>
80
+
81
+ <!-- Mobile -->
82
+ <template v-slot:mobile-item="{ item }">
83
+ <div class="tw-border-b tw-border-solid tw-border-b-[#e3e7ec] tw-p-3 tw-flex tw-flex-nowrap">
84
+ <template v-if="isImage(item.name)">
85
+ <VcImage
86
+ :bordered="true"
87
+ size="s"
88
+ aspect="1x1"
89
+ :src="item.url"
90
+ background="contain"
91
+ ></VcImage>
92
+ </template>
93
+ <template v-else>
94
+ <div class="tw-w-12 tw-flex tw-items-center tw-justify-center">
95
+ <VcIcon
96
+ :icon="getFileThumbnail(item.name)"
97
+ class="tw-text-[#a9bfd2] tw-w-12 tw-text-[48px]"
98
+ ></VcIcon>
99
+ </div>
100
+ </template>
101
+ <div class="tw-grow tw-basis-0 tw-ml-3 tw-truncate">
102
+ <div class="tw-font-bold tw-text-lg tw-truncate">
103
+ {{ item.name }}
104
+ </div>
105
+ <div class="tw-mt-3 tw-w-full tw-flex tw-justify-between">
106
+ <div class="tw-truncate tw-grow tw-basis-0 tw-mr-2">
107
+ <VcHint>{{ $t("ASSETS_MANAGER.TABLE.SIZE") }}</VcHint>
108
+ <div class="tw-truncate tw-mt-1">
109
+ {{ readableSize(item.size) }}
110
+ </div>
111
+ </div>
112
+ <div class="tw-truncate tw-grow tw-basis-0 tw-mr-2">
113
+ <VcHint>{{ $t("ASSETS_MANAGER.TABLE.CREATED_DATE") }}</VcHint>
114
+ <div class="tw-truncate tw-mt-1">
115
+ {{ item.createdDate && moment(item.createdDate).fromNow() }}
116
+ </div>
117
+ </div>
118
+ <div class="tw-truncate tw-grow tw-basis-0 tw-mr-2">
119
+ <VcHint>{{ $t("ASSETS_MANAGER.TABLE.SORT_ORDER") }}</VcHint>
120
+ <div class="tw-truncate tw-mt-1">
121
+ {{ item.sortOrder }}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </template>
128
+ </VcTable>
129
+ </div>
130
+
131
+ <input
132
+ ref="uploader"
133
+ type="file"
134
+ hidden
135
+ @change="inputUpload"
136
+ multiple
137
+ name="assets_manager"
138
+ />
139
+ </VcBlade>
140
+ </template>
141
+
142
+ <script setup lang="ts">
143
+ import { Asset, IActionBuilderResult, IBladeToolbar, ITableColumns } from "../../../../../core/types";
144
+ import { ref, computed, onMounted, shallowRef, unref, watch } from "vue";
145
+ import { useI18n } from "vue-i18n";
146
+ import { IBladeEvent, IParentCallArgs } from "./../../../../../shared";
147
+ import moment from "moment";
148
+ import Assets from "./../../../assets/components/assets-details/assets-details.vue";
149
+ import { isImage, getFileThumbnail, readableSize } from "./../../../../utilities/assets";
150
+
151
+ export interface Props {
152
+ expanded?: boolean;
153
+ closable?: boolean;
154
+ options: {
155
+ assets: Asset[];
156
+ assetsEditHandler: (assets: Asset[]) => void;
157
+ assetsUploadHandler: (files: FileList) => void;
158
+ assetsRemoveHandler: (assets: Asset[]) => void;
159
+ disabled: boolean;
160
+ };
161
+ }
162
+
163
+ export interface Emits {
164
+ (event: "parent:call", args: IParentCallArgs): void;
165
+ (event: "close:blade"): void;
166
+ (event: "open:blade", blade: IBladeEvent): void;
167
+ }
168
+
169
+ const props = withDefaults(defineProps<Props>(), {
170
+ expanded: true,
171
+ closable: true,
172
+ param: undefined,
173
+ });
174
+
175
+ const emit = defineEmits<Emits>();
176
+
177
+ const { t } = useI18n();
178
+
179
+ const defaultAssets = ref<Asset[]>([]);
180
+
181
+ const isDragging = ref(false);
182
+ const uploader = ref();
183
+ const loading = ref(false);
184
+ const selectedItems = ref([]);
185
+
186
+ const bladeToolbar = ref<IBladeToolbar[]>([
187
+ {
188
+ id: "save",
189
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.SAVE")),
190
+ icon: "fas fa-save",
191
+ clickHandler() {
192
+ emit("close:blade");
193
+ },
194
+ },
195
+ {
196
+ id: "add",
197
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.ADD")),
198
+ icon: "fas fa-plus",
199
+ clickHandler() {
200
+ toggleUploader();
201
+ },
202
+ },
203
+ {
204
+ id: "delete",
205
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.DELETE")),
206
+ icon: "fas fa-trash",
207
+ clickHandler() {
208
+ if (props.options.assetsRemoveHandler && typeof props.options.assetsRemoveHandler === "function") {
209
+ props.options.assetsRemoveHandler(selectedItems.value);
210
+ defaultAssets.value = defaultAssets.value.filter((asset) => !selectedItems.value.includes(asset));
211
+ }
212
+ },
213
+ disabled: computed(() => !selectedItems.value.length),
214
+ },
215
+ ]);
216
+
217
+ const columns = ref<ITableColumns[]>([
218
+ {
219
+ id: "url",
220
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.IMAGE")),
221
+ width: "60px",
222
+ alwaysVisible: true,
223
+ },
224
+ {
225
+ id: "name",
226
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.NAME")),
227
+ width: "120px",
228
+ alwaysVisible: true,
229
+ },
230
+ {
231
+ id: "size",
232
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.SIZE")),
233
+ width: "100px",
234
+ alwaysVisible: true,
235
+ },
236
+ {
237
+ id: "sortOrder",
238
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.SORT_ORDER")),
239
+ width: "180px",
240
+ alwaysVisible: true,
241
+ },
242
+ {
243
+ id: "createdDate",
244
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.CREATED_DATE")),
245
+ width: "140px",
246
+ alwaysVisible: true,
247
+ type: "date-ago",
248
+ },
249
+ ]);
250
+
251
+ onMounted(() => {
252
+ defaultAssets.value = props.options?.assets;
253
+ });
254
+
255
+ function sortAssets(event: { dragIndex: number; dropIndex: number; value: Asset[] }) {
256
+ if (props.options.assetsEditHandler && typeof props.options.assetsEditHandler === "function") {
257
+ const sorted = event.value.map((item, index) => {
258
+ item.sortOrder = index;
259
+ return item;
260
+ });
261
+ defaultAssets.value = sorted;
262
+ props.options.assetsEditHandler(sorted);
263
+ }
264
+ }
265
+
266
+ function dragOver() {
267
+ if (!props.options.disabled) {
268
+ isDragging.value = true;
269
+ }
270
+ }
271
+
272
+ function dragLeave() {
273
+ if (!props.options.disabled) {
274
+ isDragging.value = false;
275
+ }
276
+ }
277
+
278
+ async function onDrop(event: DragEvent) {
279
+ if (!props.options.disabled) {
280
+ const fileList = event.dataTransfer?.files;
281
+
282
+ if (fileList && fileList.length) {
283
+ await upload(fileList);
284
+ }
285
+ isDragging.value = false;
286
+ }
287
+ }
288
+
289
+ function toggleUploader() {
290
+ uploader.value.value = "";
291
+ uploader.value.click();
292
+ }
293
+
294
+ async function upload(files: FileList) {
295
+ if (files && files.length) {
296
+ try {
297
+ loading.value = true;
298
+ await props.options.assetsUploadHandler(files);
299
+ } finally {
300
+ loading.value = false;
301
+ }
302
+ }
303
+ }
304
+
305
+ async function inputUpload(event: Event) {
306
+ const target = event.target as HTMLInputElement;
307
+ const fileList = target.files;
308
+
309
+ if (fileList && fileList.length) {
310
+ upload(fileList);
311
+ }
312
+ }
313
+
314
+ function onItemClick(item: Asset) {
315
+ emit("open:blade", {
316
+ component: shallowRef(Assets),
317
+ bladeOptions: {
318
+ asset: unref(item),
319
+ assetEditHandler: (asset: Asset) => {
320
+ const mutated = defaultAssets.value.map((x) => {
321
+ if (x.id === asset.id || x.url === asset.url) {
322
+ return asset;
323
+ }
324
+ return x;
325
+ });
326
+
327
+ if (props.options.assetsEditHandler && typeof props.options.assetsEditHandler === "function") {
328
+ defaultAssets.value = mutated;
329
+ props.options.assetsEditHandler(mutated);
330
+ }
331
+ },
332
+ assetRemoveHandler: (asset: Asset) => {
333
+ props.options.assetsRemoveHandler([asset]);
334
+ },
335
+ },
336
+ });
337
+ }
338
+
339
+ const onSelectionChanged = (items: Asset[]) => {
340
+ selectedItems.value = items;
341
+ };
342
+
343
+ const actionBuilder = (): IActionBuilderResult[] => {
344
+ let result = [];
345
+
346
+ result.push({
347
+ icon: "fas fa-edit",
348
+ title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.EDIT")),
349
+ clickHandler(item: Asset) {
350
+ onItemClick(item);
351
+ },
352
+ });
353
+
354
+ result.push({
355
+ icon: "fas fa-trash",
356
+ title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.DELETE")),
357
+ variant: "danger",
358
+ leftActions: true,
359
+ clickHandler(item: Asset) {
360
+ props.options.assetsRemoveHandler([item]);
361
+ defaultAssets.value = defaultAssets.value.filter((asset) => asset !== item);
362
+ selectedItems.value = [];
363
+ },
364
+ });
365
+
366
+ return result;
367
+ };
368
+
369
+ defineExpose({
370
+ title: t("ASSETS_MANAGER.TITLE"),
371
+ });
372
+ </script>
@@ -0,0 +1,3 @@
1
+ import _AssetsManager from "./assets-manager.vue";
2
+
3
+ export const AssetsManager = _AssetsManager as typeof _AssetsManager;
@@ -0,0 +1 @@
1
+ export { AssetsManager } from "./assets-manager";
@@ -0,0 +1,14 @@
1
+ import { createModule } from "../../../core/plugins/modularity";
2
+ import * as components from "./components";
3
+ import * as locales from "./locales";
4
+
5
+ // Declare globally
6
+ declare module "@vue/runtime-core" {
7
+ export interface GlobalComponents {
8
+ AssetsManager: (typeof components)["AssetsManager"];
9
+ }
10
+ }
11
+
12
+ export default createModule(components, locales);
13
+
14
+ export * from "./components";
@@ -0,0 +1,28 @@
1
+ {
2
+ "ASSETS_MANAGER": {
3
+ "TITLE": "Assets",
4
+ "TOOLBAR": {
5
+ "SAVE":"Save",
6
+ "REFRESH":"Resfresh",
7
+ "ADD": "Add",
8
+ "DELETE": "Delete selected"
9
+ },
10
+ "EMPTY": {
11
+ "NO_ASSETS":"Drag & drop assets here or click 'Upload' button",
12
+ "UPLOAD": "Upload"
13
+ },
14
+ "TABLE":{
15
+ "HEADER":{
16
+ "IMAGE": "Img",
17
+ "NAME":"Name",
18
+ "SIZE":"Size",
19
+ "SORT_ORDER":"Sort order",
20
+ "CREATED_DATE":"Created date"
21
+ },
22
+ "ACTIONS":{
23
+ "DELETE":"Delete",
24
+ "EDIT": "Edit"
25
+ }
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,40 @@
1
+ const fileThumbnails = [
2
+ { image: "fas fa-file-pdf", extensions: ["pdf"] },
3
+ { image: "fas fa-file-word", extensions: ["doc", "docx"] },
4
+ { image: "fas fa-file-excel", extensions: ["xls", "xlsx"] },
5
+ { image: "fas fa-file-powerpoint", extensions: ["ppt", "pptx"] },
6
+ { image: "fas fa-file-csv", extensions: ["csv"] },
7
+ { image: "fas fa-file-archive", extensions: ["zip"] },
8
+ { image: "fas fa-file-music", extensions: ["mp3", "aac"] },
9
+ { image: "fas fa-file-video", extensions: ["mp4", "avi"] },
10
+ ];
11
+
12
+ const imageExtensions = new Set(["png", "jpg", "jpeg", "svg", "gif"]);
13
+
14
+ function getExtension(fileName: string) {
15
+ return fileName.split(".").pop()?.toLowerCase();
16
+ }
17
+
18
+ function isImage(name: string) {
19
+ return imageExtensions.has(getExtension(name));
20
+ }
21
+
22
+ function getFileThumbnail(name: string) {
23
+ return (
24
+ fileThumbnails.find((thumb) => thumb.extensions.some((ext) => ext === getExtension(name)))?.image || "fas fa-file"
25
+ );
26
+ }
27
+
28
+ function readableSize(bytes: number, decimals = 2) {
29
+ if (!bytes) return "0 Bytes";
30
+
31
+ const k = 1024;
32
+ const dm = decimals < 0 ? 0 : decimals;
33
+ const sizes = ["Bytes", "KB", "MB", "GB"];
34
+
35
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
36
+
37
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
38
+ }
39
+
40
+ export { isImage, getFileThumbnail, readableSize };
@@ -37,8 +37,6 @@
37
37
  </template>
38
38
 
39
39
  <script lang="ts" setup>
40
- import { watch } from "vue";
41
-
42
40
  export interface Props {
43
41
  modelValue?: boolean;
44
42
  disabled?: boolean;
@@ -51,17 +49,9 @@ export interface Emits {
51
49
  (event: "update:modelValue", value: boolean): void;
52
50
  }
53
51
 
54
- const props = withDefaults(defineProps<Props>(), { name: "Field" });
52
+ withDefaults(defineProps<Props>(), { name: "Field" });
55
53
  const emit = defineEmits<Emits>();
56
54
 
57
- watch(
58
- () => props.modelValue,
59
- (value) => {
60
- emit("update:modelValue", value);
61
- }
62
- );
63
-
64
- // Handle input event to propertly validate value and emit changes
65
55
  function onChange(e: Event) {
66
56
  const newValue = (e.target as HTMLInputElement).checked;
67
57
  emit("update:modelValue", newValue);
@@ -109,6 +109,7 @@ function toggleUploader() {
109
109
  }
110
110
 
111
111
  function onDrop(event: DragEvent) {
112
+ dragLeave();
112
113
  const fileList = event.dataTransfer?.files;
113
114
 
114
115
  if (fileList && fileList.length) {
@@ -176,7 +176,7 @@ export interface Props {
176
176
  /**
177
177
  * Model of the component; Use with a listener for 'update:model-value' event OR use v-model directive
178
178
  */
179
- modelValue: string | number | Date | null | undefined;
179
+ modelValue?: string | number | Date | null | undefined;
180
180
  /**
181
181
  * Input label text
182
182
  */
@@ -60,7 +60,7 @@
60
60
  {{ prefix }}
61
61
  </div>
62
62
  <div
63
- class="tw-w-full tw-appearance-none tw-border-none tw-outline-none tw-min-h-[var(--select-height)] tw-flex tw-items-center tw-w-full tw-box-border tw-box-border tw-cursor-pointer invalid:tw-text-[color:var(--select-placeholder-color)] tw-truncate"
63
+ class="tw-appearance-none tw-border-none tw-outline-none tw-min-h-[var(--select-height)] tw-flex tw-items-center tw-w-full tw-box-border tw-cursor-pointer invalid:tw-text-[color:var(--select-placeholder-color)] tw-truncate"
64
64
  @click.stop="toggleDropdown"
65
65
  >
66
66
  <div
@@ -90,7 +90,7 @@
90
90
  <div
91
91
  class="tw-bg-[#fbfdfe] tw-border tw-border-solid tw-border-[color:#bdd1df] tw-rounded-[2px] tw-flex tw-items-center tw-h-[28px] tw-box-border tw-px-2"
92
92
  >
93
- <span>{{ getEmittingOptionValue(item.opt) }}</span>
93
+ <span>{{ getOptionLabel(item.opt) }}</span>
94
94
  <VcIcon
95
95
  v-if="!disabled"
96
96
  class="tw-text-[#a9bfd2] tw-ml-2 tw-cursor-pointer hover:tw-text-[color:var(--select-clear-color-hover)]"
@@ -26,13 +26,14 @@
26
26
  <!-- Show blades name when at least one blade is opened -->
27
27
  <div
28
28
  v-if="blades.length === 1"
29
- class="tw-overflow-ellipsis tw-overflow-hidden tw-whitespace-nowrap tw-text-2xl tw-leading-header"
29
+ class="tw-overflow-ellipsis tw-overflow-hidden tw-whitespace-nowrap tw-text-2xl tw-leading-header tw-ml-2"
30
30
  >
31
31
  {{ blades[0].title }}
32
32
  </div>
33
33
 
34
34
  <!-- Show back link when more than one blade is opened -->
35
35
  <VcLink
36
+ class="tw-ml-3"
36
37
  v-else-if="blades.length > 1"
37
38
  @click="$emit('backlink:click')"
38
39
  >
@@ -45,7 +46,7 @@
45
46
  </template>
46
47
 
47
48
  <!-- Additional spacer -->
48
- <div class="tw-grow tw-basis-0 tw-basis-0"></div>
49
+ <div class="tw-grow tw-basis-0"></div>
49
50
 
50
51
  <!-- Toolbar container -->
51
52
  <div class="tw-flex tw-h-full tw-box-border">
@@ -4,10 +4,10 @@
4
4
  <router-link
5
5
  :to="component.url"
6
6
  custom
7
- v-slot="{ isActive, navigate }"
7
+ v-slot="{ isExactActive, navigate }"
8
8
  >
9
9
  <vc-app-menu-link
10
- :isActive="isActive"
10
+ :isActive="isExactActive"
11
11
  :children="children"
12
12
  :sticky="sticky"
13
13
  :icon="icon as string"
@@ -23,7 +23,6 @@
23
23
  :icon="icon as string"
24
24
  :title="title"
25
25
  @onClick="onMenuItemClick"
26
- :isActive="isHomePage"
27
26
  />
28
27
 
29
28
  <!-- Nested menu items -->
@@ -61,7 +60,7 @@
61
60
  </template>
62
61
 
63
62
  <script lang="ts" setup>
64
- import { onMounted, ref, computed } from "vue";
63
+ import { onMounted, ref } from "vue";
65
64
  import { IBladeToolbar, IMenuItems } from "./../../../../../../../../core/types";
66
65
  import VcAppMenuLink from "./_internal/vc-app-menu-link.vue";
67
66
  import { NavigationFailure, useRoute } from "vue-router";
@@ -109,8 +108,6 @@ const emit = defineEmits<Emits>();
109
108
 
110
109
  const isOpened = ref(false);
111
110
 
112
- const isHomePage = computed(() => route.path === "/");
113
-
114
111
  onMounted(() => {
115
112
  if (props.children && props.children.length && props.children.find((x) => x.component?.url === route?.path)) {
116
113
  isOpened.value = true;
@@ -50,7 +50,7 @@
50
50
  </div>
51
51
  <div
52
52
  v-else
53
- class="vc-blade-header__button"
53
+ class="tw-text-[color:var(--blade-header-button-color)] tw-ml-4 tw-cursor-pointer hover:tw-text-[color:var(--blade-header-button-color-hover)]"
54
54
  @click="onExpand"
55
55
  >
56
56
  <VcIcon
@@ -81,11 +81,7 @@ export interface Props {
81
81
  subtitle?: string | undefined;
82
82
  icon?: string | undefined;
83
83
  }
84
- const props = withDefaults(defineProps<Props>(), {
85
- expandable: false,
86
- expanded: false,
87
- closable: false,
88
- });
84
+ const props = defineProps<Props>();
89
85
 
90
86
  const emit = defineEmits(["close", "expand", "collapse"]);
91
87
 
@@ -56,7 +56,11 @@
56
56
  :required="property.required || property.isRequired"
57
57
  placeholder="Add value"
58
58
  :disabled="disabled"
59
+ option-label="alias"
60
+ option-value="id"
59
61
  :multiple="true"
62
+ :emit-value="false"
63
+ :clearable="false"
60
64
  ></VcSelect>
61
65
  </Field>
62
66
 
@@ -91,6 +95,8 @@
91
95
  @search="onSearch"
92
96
  @close="onClose"
93
97
  :multiple="property.multivalue"
98
+ :emit-value="false"
99
+ :clearable="false"
94
100
  ></VcSelect>
95
101
  </Field>
96
102