@vc-shell/framework 1.0.57 → 1.0.60

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 (173) hide show
  1. package/core/composables/index.ts +0 -1
  2. package/core/composables/useNotifications/index.ts +2 -2
  3. package/core/composables/usePermissions/index.ts +1 -1
  4. package/core/composables/useSettings/index.ts +2 -2
  5. package/core/composables/useUser/index.ts +2 -2
  6. package/core/plugins/validation/rules.ts +67 -24
  7. package/core/types/index.ts +19 -2
  8. package/dist/framework.mjs +2816 -5023
  9. package/dist/index.css +1 -1
  10. package/dist/types/core/composables/index.d.ts +0 -1
  11. package/dist/types/core/composables/index.d.ts.map +1 -1
  12. package/dist/types/core/composables/useNotifications/index.d.ts +1 -1
  13. package/dist/types/core/composables/useNotifications/index.d.ts.map +1 -1
  14. package/dist/types/core/composables/useUser/index.d.ts +2 -2
  15. package/dist/types/core/composables/useUser/index.d.ts.map +1 -1
  16. package/dist/types/core/plugins/validation/rules.d.ts +8 -30
  17. package/dist/types/core/plugins/validation/rules.d.ts.map +1 -1
  18. package/dist/types/core/types/index.d.ts +17 -2
  19. package/dist/types/core/types/index.d.ts.map +1 -1
  20. package/dist/types/index.d.ts.map +1 -1
  21. package/dist/types/shared/components/app-switcher/components/index.d.ts.map +1 -0
  22. package/dist/types/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/index.d.ts +5 -5
  23. package/dist/types/shared/components/app-switcher/components/vc-app-switcher/index.d.ts.map +1 -0
  24. package/dist/types/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/vc-app-switcher.vue.d.ts +1 -1
  25. package/dist/types/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +1 -0
  26. package/dist/types/shared/components/app-switcher/composables/index.d.ts.map +1 -0
  27. package/dist/types/shared/{app-switcher → components/app-switcher}/composables/useAppSwitcher/index.d.ts +1 -1
  28. package/dist/types/shared/components/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -0
  29. package/dist/types/shared/components/app-switcher/index.d.ts.map +1 -0
  30. package/dist/types/shared/components/blade-navigation/components/index.d.ts.map +1 -0
  31. package/dist/types/shared/components/blade-navigation/components/vc-blade-navigation/index.d.ts.map +1 -0
  32. package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts +1 -1
  33. package/dist/types/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -0
  34. package/dist/types/shared/components/blade-navigation/composables/index.d.ts.map +1 -0
  35. package/dist/types/shared/{blade-navigation → components/blade-navigation}/composables/useBladeNavigation/index.d.ts +1 -1
  36. package/dist/types/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -0
  37. package/dist/types/shared/components/blade-navigation/index.d.ts.map +1 -0
  38. package/dist/types/shared/{blade-navigation → components/blade-navigation}/types/index.d.ts +1 -1
  39. package/dist/types/shared/components/blade-navigation/types/index.d.ts.map +1 -0
  40. package/dist/types/shared/index.d.ts +4 -3
  41. package/dist/types/shared/index.d.ts.map +1 -1
  42. package/dist/types/shared/{assets → modules/assets}/components/assets-details/assets-details.vue.d.ts +5 -13
  43. package/dist/types/shared/modules/assets/components/assets-details/assets-details.vue.d.ts.map +1 -0
  44. package/dist/types/shared/{assets → modules/assets}/components/assets-details/index.d.ts +8 -7
  45. package/dist/types/shared/modules/assets/components/assets-details/index.d.ts.map +1 -0
  46. package/dist/types/shared/modules/assets/components/index.d.ts.map +1 -0
  47. package/dist/types/shared/modules/assets/index.d.ts.map +1 -0
  48. package/dist/types/shared/modules/assets/locales/index.d.ts +3 -0
  49. package/dist/types/shared/modules/assets/locales/index.d.ts.map +1 -0
  50. package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts +58 -0
  51. package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -0
  52. package/dist/types/shared/modules/assets-manager/components/assets-manager/index.d.ts +59 -0
  53. package/dist/types/shared/modules/assets-manager/components/assets-manager/index.d.ts.map +1 -0
  54. package/dist/types/shared/modules/assets-manager/components/index.d.ts +2 -0
  55. package/dist/types/shared/modules/assets-manager/components/index.d.ts.map +1 -0
  56. package/dist/types/shared/modules/assets-manager/index.d.ts +12 -0
  57. package/dist/types/shared/modules/assets-manager/index.d.ts.map +1 -0
  58. package/dist/types/shared/modules/assets-manager/locales/index.d.ts.map +1 -0
  59. package/dist/types/shared/utilities/assets.d.ts +5 -0
  60. package/dist/types/shared/utilities/assets.d.ts.map +1 -0
  61. package/dist/types/ui/components/atoms/vc-checkbox/vc-checkbox.vue.d.ts.map +1 -1
  62. package/dist/types/ui/components/molecules/vc-editor/vc-editor.vue.d.ts.map +1 -1
  63. package/dist/types/ui/components/molecules/vc-file-upload/index.d.ts +12 -12
  64. package/dist/types/ui/components/molecules/vc-file-upload/vc-file-upload.vue.d.ts.map +1 -1
  65. package/dist/types/ui/components/molecules/vc-input/index.d.ts +0 -4
  66. package/dist/types/ui/components/molecules/vc-input/index.d.ts.map +1 -1
  67. package/dist/types/ui/components/molecules/vc-input/vc-input.vue.d.ts +1 -1
  68. package/dist/types/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  69. package/dist/types/ui/components/molecules/vc-select/index.d.ts +24 -0
  70. package/dist/types/ui/components/molecules/vc-select/index.d.ts.map +1 -1
  71. package/dist/types/ui/components/molecules/vc-select/vc-select.vue.d.ts +20 -0
  72. package/dist/types/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
  73. package/dist/types/ui/components/molecules/vc-textarea/index.d.ts +0 -4
  74. package/dist/types/ui/components/molecules/vc-textarea/index.d.ts.map +1 -1
  75. package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.stories.d.ts +0 -4
  76. package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.stories.d.ts.map +1 -1
  77. package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts +1 -1
  78. package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts.map +1 -1
  79. 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
  80. package/dist/types/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts +2 -19
  81. package/dist/types/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
  82. package/dist/types/ui/components/organisms/vc-dynamic-property/index.d.ts +12 -0
  83. package/dist/types/ui/components/organisms/vc-dynamic-property/index.d.ts.map +1 -1
  84. package/dist/types/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts +7 -0
  85. package/dist/types/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts.map +1 -1
  86. package/dist/types/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts +2 -20
  87. package/dist/types/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts.map +1 -1
  88. package/dist/types/ui/components/organisms/vc-gallery/index.d.ts +28 -31
  89. package/dist/types/ui/components/organisms/vc-gallery/index.d.ts.map +1 -1
  90. package/dist/types/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts +2 -6
  91. package/dist/types/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts.map +1 -1
  92. package/dist/types/ui/components/organisms/vc-table/index.d.ts +49 -37
  93. package/dist/types/ui/components/organisms/vc-table/index.d.ts.map +1 -1
  94. package/dist/types/ui/components/organisms/vc-table/vc-table.stories.d.ts +49 -37
  95. package/dist/types/ui/components/organisms/vc-table/vc-table.stories.d.ts.map +1 -1
  96. package/dist/types/ui/components/organisms/vc-table/vc-table.vue.d.ts +12 -7
  97. package/dist/types/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
  98. package/package.json +5 -6
  99. package/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/vc-app-switcher.vue +1 -1
  100. package/shared/{app-switcher → components/app-switcher}/composables/useAppSwitcher/index.ts +2 -2
  101. package/shared/{app-switcher → components/app-switcher}/index.ts +1 -1
  102. package/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/vc-blade-navigation.vue +2 -2
  103. package/shared/{blade-navigation → components/blade-navigation}/composables/useBladeNavigation/index.ts +6 -5
  104. package/shared/{blade-navigation → components/blade-navigation}/index.ts +1 -1
  105. package/shared/{blade-navigation → components/blade-navigation}/types/index.ts +1 -1
  106. package/shared/index.ts +10 -7
  107. package/shared/modules/assets/components/assets-details/assets-details.vue +204 -0
  108. package/shared/{assets → modules/assets}/index.ts +1 -1
  109. package/shared/{assets → modules/assets}/locales/en.json +7 -5
  110. package/shared/modules/assets/locales/index.ts +2 -0
  111. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +389 -0
  112. package/shared/modules/assets-manager/components/assets-manager/index.ts +3 -0
  113. package/shared/modules/assets-manager/components/index.ts +1 -0
  114. package/shared/modules/assets-manager/index.ts +14 -0
  115. package/shared/modules/assets-manager/locales/en.json +28 -0
  116. package/shared/utilities/assets.ts +40 -0
  117. package/tailwind.config.js +0 -2
  118. package/ui/components/atoms/vc-button/vc-button.vue +0 -1
  119. package/ui/components/atoms/vc-checkbox/vc-checkbox.vue +1 -11
  120. package/ui/components/molecules/vc-editor/vc-editor.vue +21 -0
  121. package/ui/components/molecules/vc-file-upload/vc-file-upload.vue +1 -0
  122. package/ui/components/molecules/vc-input/vc-input.vue +1 -1
  123. package/ui/components/molecules/vc-select/vc-select.vue +40 -9
  124. package/ui/components/molecules/vc-textarea/vc-textarea.vue +1 -1
  125. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +3 -2
  126. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +3 -6
  127. package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +2 -6
  128. package/ui/components/organisms/vc-dynamic-property/index.ts +0 -1
  129. package/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +18 -1
  130. package/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue +5 -11
  131. package/ui/components/organisms/vc-gallery/vc-gallery.vue +164 -49
  132. package/ui/components/organisms/vc-table/vc-table.vue +189 -144
  133. package/core/composables/useAutosave/index.ts +0 -55
  134. package/dist/types/core/composables/useAutosave/index.d.ts +0 -9
  135. package/dist/types/core/composables/useAutosave/index.d.ts.map +0 -1
  136. package/dist/types/shared/app-switcher/components/index.d.ts.map +0 -1
  137. package/dist/types/shared/app-switcher/components/vc-app-switcher/index.d.ts.map +0 -1
  138. package/dist/types/shared/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +0 -1
  139. package/dist/types/shared/app-switcher/composables/index.d.ts.map +0 -1
  140. package/dist/types/shared/app-switcher/composables/useAppSwitcher/index.d.ts.map +0 -1
  141. package/dist/types/shared/app-switcher/index.d.ts.map +0 -1
  142. package/dist/types/shared/assets/components/assets-details/assets-details.vue.d.ts.map +0 -1
  143. package/dist/types/shared/assets/components/assets-details/index.d.ts.map +0 -1
  144. package/dist/types/shared/assets/components/index.d.ts.map +0 -1
  145. package/dist/types/shared/assets/index.d.ts.map +0 -1
  146. package/dist/types/shared/assets/locales/index.d.ts.map +0 -1
  147. package/dist/types/shared/blade-navigation/components/index.d.ts.map +0 -1
  148. package/dist/types/shared/blade-navigation/components/vc-blade-navigation/index.d.ts.map +0 -1
  149. package/dist/types/shared/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +0 -1
  150. package/dist/types/shared/blade-navigation/composables/index.d.ts.map +0 -1
  151. package/dist/types/shared/blade-navigation/composables/useBladeNavigation/index.d.ts.map +0 -1
  152. package/dist/types/shared/blade-navigation/index.d.ts.map +0 -1
  153. package/dist/types/shared/blade-navigation/types/index.d.ts.map +0 -1
  154. package/shared/assets/components/assets-details/assets-details.vue +0 -116
  155. /package/dist/types/shared/{app-switcher → components/app-switcher}/components/index.d.ts +0 -0
  156. /package/dist/types/shared/{app-switcher → components/app-switcher}/composables/index.d.ts +0 -0
  157. /package/dist/types/shared/{app-switcher → components/app-switcher}/index.d.ts +0 -0
  158. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/index.d.ts +0 -0
  159. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/index.d.ts +0 -0
  160. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/composables/index.d.ts +0 -0
  161. /package/dist/types/shared/{blade-navigation → components/blade-navigation}/index.d.ts +0 -0
  162. /package/dist/types/shared/{assets → modules/assets}/components/index.d.ts +0 -0
  163. /package/dist/types/shared/{assets → modules/assets}/index.d.ts +0 -0
  164. /package/dist/types/shared/{assets → modules/assets-manager}/locales/index.d.ts +0 -0
  165. /package/shared/{app-switcher → components/app-switcher}/components/index.ts +0 -0
  166. /package/shared/{app-switcher → components/app-switcher}/components/vc-app-switcher/index.ts +0 -0
  167. /package/shared/{app-switcher → components/app-switcher}/composables/index.ts +0 -0
  168. /package/shared/{blade-navigation → components/blade-navigation}/components/index.ts +0 -0
  169. /package/shared/{blade-navigation → components/blade-navigation}/components/vc-blade-navigation/index.ts +0 -0
  170. /package/shared/{blade-navigation → components/blade-navigation}/composables/index.ts +0 -0
  171. /package/shared/{assets → modules/assets}/components/assets-details/index.ts +0 -0
  172. /package/shared/{assets → modules/assets}/components/index.ts +0 -0
  173. /package/shared/{assets → modules/assets-manager}/locales/index.ts +0 -0
@@ -0,0 +1,389 @@
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="!readonly"
22
+ :items="defaultAssets"
23
+ :header="false"
24
+ :footer="false"
25
+ :itemActionBuilder="!readonly && actionBuilder"
26
+ :multiselect="!readonly"
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
+ import { cloneDeep, isEqual } from "lodash-es";
151
+
152
+ export interface Props {
153
+ expanded?: boolean;
154
+ closable?: boolean;
155
+ options: {
156
+ assets: Asset[];
157
+ assetsEditHandler: (assets: Asset[]) => Asset[];
158
+ assetsUploadHandler: (files: FileList) => Promise<Asset[]>;
159
+ assetsRemoveHandler: (assets: Asset[]) => Asset[];
160
+ disabled: boolean;
161
+ };
162
+ }
163
+
164
+ export interface Emits {
165
+ (event: "parent:call", args: IParentCallArgs): void;
166
+ (event: "close:blade"): void;
167
+ (event: "open:blade", blade: IBladeEvent): void;
168
+ }
169
+
170
+ const props = withDefaults(defineProps<Props>(), {
171
+ expanded: true,
172
+ closable: true,
173
+ param: undefined,
174
+ });
175
+
176
+ const emit = defineEmits<Emits>();
177
+
178
+ const { t } = useI18n();
179
+
180
+ const defaultAssets = ref<Asset[]>([]);
181
+
182
+ const isDragging = ref(false);
183
+ const uploader = ref();
184
+ const loading = ref(false);
185
+ const selectedItems = ref([]);
186
+ const readonly = computed(() => props.options.disabled);
187
+ let assetsCopy;
188
+ const modified = ref(false);
189
+
190
+ const bladeToolbar = ref<IBladeToolbar[]>([
191
+ {
192
+ id: "save",
193
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.SAVE")),
194
+ icon: "fas fa-save",
195
+ clickHandler() {
196
+ emit("close:blade");
197
+ },
198
+ disabled: computed(() => !modified.value || readonly.value),
199
+ },
200
+ {
201
+ id: "add",
202
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.ADD")),
203
+ icon: "fas fa-plus",
204
+ clickHandler() {
205
+ toggleUploader();
206
+ },
207
+ disabled: computed(() => readonly.value),
208
+ },
209
+ {
210
+ id: "delete",
211
+ title: computed(() => t("ASSETS_MANAGER.TOOLBAR.DELETE")),
212
+ icon: "fas fa-trash",
213
+ clickHandler() {
214
+ if (props.options.assetsRemoveHandler && typeof props.options.assetsRemoveHandler === "function") {
215
+ defaultAssets.value = props.options.assetsRemoveHandler(selectedItems.value);
216
+ }
217
+ },
218
+ disabled: computed(() => !selectedItems.value.length || readonly.value),
219
+ },
220
+ ]);
221
+
222
+ const columns = ref<ITableColumns[]>([
223
+ {
224
+ id: "url",
225
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.IMAGE")),
226
+ width: "60px",
227
+ alwaysVisible: true,
228
+ },
229
+ {
230
+ id: "name",
231
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.NAME")),
232
+ width: "120px",
233
+ alwaysVisible: true,
234
+ },
235
+ {
236
+ id: "size",
237
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.SIZE")),
238
+ width: "100px",
239
+ alwaysVisible: true,
240
+ },
241
+ {
242
+ id: "sortOrder",
243
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.SORT_ORDER")),
244
+ width: "180px",
245
+ alwaysVisible: true,
246
+ },
247
+ {
248
+ id: "createdDate",
249
+ title: computed(() => t("ASSETS_MANAGER.TABLE.HEADER.CREATED_DATE")),
250
+ width: "140px",
251
+ alwaysVisible: true,
252
+ type: "date-ago",
253
+ },
254
+ ]);
255
+
256
+ watch(
257
+ () => defaultAssets.value,
258
+ (newVal) => {
259
+ modified.value = !isEqual(newVal, assetsCopy);
260
+ },
261
+ { deep: true }
262
+ );
263
+
264
+ onMounted(() => {
265
+ defaultAssets.value = props.options?.assets;
266
+ assetsCopy = cloneDeep(props.options?.assets);
267
+ });
268
+
269
+ function sortAssets(event: { dragIndex: number; dropIndex: number; value: Asset[] }) {
270
+ if (
271
+ props.options.assetsEditHandler &&
272
+ typeof props.options.assetsEditHandler === "function" &&
273
+ event.dragIndex !== event.dropIndex
274
+ ) {
275
+ const sorted = event.value.map((item, index) => {
276
+ item.sortOrder = index;
277
+ return item;
278
+ });
279
+
280
+ defaultAssets.value = props.options.assetsEditHandler(sorted);
281
+ }
282
+ }
283
+
284
+ function dragOver() {
285
+ if (!readonly.value) {
286
+ isDragging.value = true;
287
+ }
288
+ }
289
+
290
+ function dragLeave() {
291
+ if (!readonly.value) {
292
+ isDragging.value = false;
293
+ }
294
+ }
295
+
296
+ async function onDrop(event: DragEvent) {
297
+ if (!readonly.value) {
298
+ const fileList = event.dataTransfer?.files;
299
+
300
+ if (fileList && fileList.length) {
301
+ await upload(fileList);
302
+ }
303
+ isDragging.value = false;
304
+ }
305
+ }
306
+
307
+ function toggleUploader() {
308
+ uploader.value.value = "";
309
+ uploader.value.click();
310
+ }
311
+
312
+ async function upload(files: FileList) {
313
+ if (files && files.length) {
314
+ try {
315
+ loading.value = true;
316
+ defaultAssets.value = await props.options.assetsUploadHandler(files);
317
+ } finally {
318
+ loading.value = false;
319
+ }
320
+ }
321
+ }
322
+
323
+ async function inputUpload(event: Event) {
324
+ const target = event.target as HTMLInputElement;
325
+ const fileList = target.files;
326
+
327
+ if (fileList && fileList.length) {
328
+ upload(fileList);
329
+ }
330
+ }
331
+
332
+ function onItemClick(item: Asset) {
333
+ emit("open:blade", {
334
+ component: shallowRef(Assets),
335
+ bladeOptions: {
336
+ asset: unref(item),
337
+ disabled: readonly.value,
338
+ assetEditHandler: (asset: Asset) => {
339
+ const mutated = defaultAssets.value.map((x) => {
340
+ if (x.id === asset.id || x.url === asset.url) {
341
+ return asset;
342
+ }
343
+ return x;
344
+ });
345
+
346
+ if (props.options.assetsEditHandler && typeof props.options.assetsEditHandler === "function") {
347
+ defaultAssets.value = props.options.assetsEditHandler(mutated);
348
+ }
349
+ },
350
+ assetRemoveHandler: (asset: Asset) => {
351
+ defaultAssets.value = props.options.assetsRemoveHandler([asset]);
352
+ },
353
+ },
354
+ });
355
+ }
356
+
357
+ const onSelectionChanged = (items: Asset[]) => {
358
+ selectedItems.value = items;
359
+ };
360
+
361
+ const actionBuilder = (): IActionBuilderResult[] => {
362
+ let result = [];
363
+
364
+ result.push({
365
+ icon: "fas fa-edit",
366
+ title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.EDIT")),
367
+ clickHandler(item: Asset) {
368
+ onItemClick(item);
369
+ },
370
+ });
371
+
372
+ result.push({
373
+ icon: "fas fa-trash",
374
+ title: computed(() => t("ASSETS_MANAGER.TABLE.ACTIONS.DELETE")),
375
+ variant: "danger",
376
+ leftActions: true,
377
+ clickHandler(item: Asset) {
378
+ defaultAssets.value = props.options.assetsRemoveHandler([item]);
379
+ selectedItems.value = [];
380
+ },
381
+ });
382
+
383
+ return result;
384
+ };
385
+
386
+ defineExpose({
387
+ title: t("ASSETS_MANAGER.TITLE"),
388
+ });
389
+ </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 };
@@ -47,6 +47,4 @@ module.exports = {
47
47
  }
48
48
  },
49
49
  },
50
-
51
- plugins: [require("@tailwindcss/line-clamp")],
52
50
  }
@@ -150,7 +150,6 @@ $variants: primary, secondary, special, danger, widget;
150
150
  tw-shadow-[1px_4px_10px_rgba(197,206,214,0.24)]
151
151
  tw-rounded-[4px]
152
152
  tw-p-[15px]
153
- tw-border-[color:var(--button-widget-background-color)]
154
153
  hover:tw-bg-[color:var(--button-widget-background-color-hover)]
155
154
  focus:tw-bg-[color:var(--button-widget-background-color-active)]
156
155
  focus:tw-border-[color:var(--button-widget-border-color-active)]
@@ -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);
@@ -25,6 +25,7 @@
25
25
  <!-- Editor field -->
26
26
  <QuillEditor
27
27
  class="quill-editor tw-border tw-border-solid tw-border-[color:var(--editor-border-color)] tw-rounded-b-[var(--editor-border-radius)] tw-h-[200px]"
28
+ :class="{ 'tw-bg-[#fafafa] tw-text-[#424242] tw-cursor-default': disabled }"
28
29
  v-model:content="content"
29
30
  theme="snow"
30
31
  :toolbar="toolbar"
@@ -147,11 +148,31 @@ function isQuillEmpty(value: string) {
147
148
  --editor-border-color: #d3dbe9;
148
149
  --editor-border-color-error: #f14e4e;
149
150
  --editor-placeholder-color: #a5a5a5;
151
+
152
+ --editor-scroll-width: 8px;
153
+ --editor-scroll-color-hover: #cce4f5;
150
154
  }
151
155
 
152
156
  .vc-editor {
153
157
  &_error .quill-editor {
154
158
  @apply tw-border tw-border-solid tw-border-[color:var(--editor-border-color-error)] #{!important};
155
159
  }
160
+
161
+ .quill-editor .ql-editor {
162
+ &::-webkit-scrollbar {
163
+ @apply tw-w-[var(--editor-scroll-width)] tw-bg-transparent;
164
+ }
165
+
166
+ &::-webkit-scrollbar-track {
167
+ @apply tw-bg-transparent;
168
+ }
169
+
170
+ &::-webkit-scrollbar-thumb {
171
+ @apply tw-bg-[color:var(--editor-scroll-color)]
172
+ tw-rounded-[calc(var(--editor-scroll-width)/2)]
173
+ tw-overflow-x-hidden
174
+ hover:tw-bg-[color:var(--editor-scroll-color-hover)];
175
+ }
176
+ }
156
177
  }
157
178
  </style>
@@ -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
  */