@vc-shell/framework 1.0.59 → 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.
- package/core/composables/index.ts +0 -1
- package/core/composables/useNotifications/index.ts +2 -2
- package/core/composables/usePermissions/index.ts +1 -1
- package/core/composables/useSettings/index.ts +2 -2
- package/core/composables/useUser/index.ts +2 -2
- package/dist/framework.mjs +1124 -327
- package/dist/index.css +1 -1
- package/dist/types/core/composables/index.d.ts +0 -1
- package/dist/types/core/composables/index.d.ts.map +1 -1
- package/dist/types/core/composables/useNotifications/index.d.ts +1 -1
- package/dist/types/core/composables/useNotifications/index.d.ts.map +1 -1
- package/dist/types/core/composables/useUser/index.d.ts +2 -2
- package/dist/types/core/composables/useUser/index.d.ts.map +1 -1
- package/dist/types/shared/modules/assets/components/assets-details/assets-details.vue.d.ts +1 -0
- package/dist/types/shared/modules/assets/components/assets-details/assets-details.vue.d.ts.map +1 -1
- package/dist/types/shared/modules/assets/components/assets-details/index.d.ts +2 -0
- package/dist/types/shared/modules/assets/components/assets-details/index.d.ts.map +1 -1
- package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts +3 -3
- package/dist/types/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
- package/dist/types/shared/modules/assets-manager/components/assets-manager/index.d.ts +6 -6
- package/dist/types/ui/components/molecules/vc-editor/vc-editor.vue.d.ts.map +1 -1
- package/dist/types/ui/components/molecules/vc-file-upload/index.d.ts +12 -12
- package/dist/types/ui/components/molecules/vc-select/index.d.ts +24 -0
- package/dist/types/ui/components/molecules/vc-select/index.d.ts.map +1 -1
- package/dist/types/ui/components/molecules/vc-select/vc-select.vue.d.ts +20 -0
- package/dist/types/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
- package/dist/types/ui/components/molecules/vc-textarea/index.d.ts +0 -4
- package/dist/types/ui/components/molecules/vc-textarea/index.d.ts.map +1 -1
- package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.stories.d.ts +0 -4
- package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.stories.d.ts.map +1 -1
- package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts +1 -1
- package/dist/types/ui/components/molecules/vc-textarea/vc-textarea.vue.d.ts.map +1 -1
- package/dist/types/ui/components/organisms/vc-dynamic-property/index.d.ts +12 -0
- package/dist/types/ui/components/organisms/vc-dynamic-property/index.d.ts.map +1 -1
- package/dist/types/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts +7 -0
- package/dist/types/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue.d.ts.map +1 -1
- package/dist/types/ui/components/organisms/vc-gallery/index.d.ts +6 -6
- package/dist/types/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/modules/assets/components/assets-details/assets-details.vue +60 -22
- package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +38 -21
- package/tailwind.config.js +0 -2
- package/ui/components/atoms/vc-button/vc-button.vue +0 -1
- package/ui/components/molecules/vc-editor/vc-editor.vue +21 -0
- package/ui/components/molecules/vc-select/vc-select.vue +39 -8
- package/ui/components/molecules/vc-textarea/vc-textarea.vue +1 -1
- package/ui/components/organisms/vc-dynamic-property/index.ts +0 -1
- package/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.vue +14 -3
- package/ui/components/organisms/vc-table/vc-table.vue +26 -52
- package/core/composables/useAutosave/index.ts +0 -55
- package/dist/types/core/composables/useAutosave/index.d.ts +0 -9
- package/dist/types/core/composables/useAutosave/index.d.ts.map +0 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
>
|
|
10
10
|
<!-- Blade contents -->
|
|
11
11
|
<div class="tw-flex tw-grow-1 tw-border-t tw-border-solid tw-border-t-[#eaedf3]">
|
|
12
|
-
<div class="assets-details__content tw-grow tw-basis-0">
|
|
12
|
+
<div class="assets-details__content tw-grow tw-basis-0 tw-w-full">
|
|
13
13
|
<VcContainer :no-padding="true">
|
|
14
14
|
<div class="tw-p-4">
|
|
15
15
|
<VcForm>
|
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
:src="defaultAsset.url"
|
|
20
20
|
size="xl"
|
|
21
21
|
:bordered="true"
|
|
22
|
+
class="tw-shrink-0"
|
|
22
23
|
></VcImage>
|
|
23
24
|
</template>
|
|
24
25
|
<template v-else>
|
|
25
26
|
<VcIcon
|
|
26
27
|
:icon="getFileThumbnail(defaultAsset.name)"
|
|
27
|
-
class="tw-text-[#a9bfd2] tw-text-[128px]"
|
|
28
|
+
class="tw-text-[#a9bfd2] tw-text-[128px] tw-shrink-0"
|
|
28
29
|
></VcIcon>
|
|
29
30
|
</template>
|
|
30
31
|
<VcCol class="tw-ml-6">
|
|
@@ -39,14 +40,16 @@
|
|
|
39
40
|
(defaultAsset.createdDate && moment(defaultAsset.createdDate).fromNow()) || "N/A"
|
|
40
41
|
}}</VcHint>
|
|
41
42
|
</VcCol>
|
|
42
|
-
<VcCol>
|
|
43
|
+
<VcCol class="tw-w-full">
|
|
43
44
|
<VcLabel>{{ $t("ASSETS.PAGES.DETAILS.FIELDS.URL") }}</VcLabel>
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
<div class="tw-flex tw-flex-row tw-justify-stretch tw-truncate">
|
|
46
|
+
<div class="tw-truncate">
|
|
47
|
+
<VcLink
|
|
48
|
+
class="vc-link tw-text-s tw-truncate tw-w-full"
|
|
49
|
+
@click="openLink(defaultAsset.url)"
|
|
50
|
+
>{{ props.options?.asset.name }}</VcLink
|
|
51
|
+
>
|
|
52
|
+
</div>
|
|
50
53
|
<VcButton
|
|
51
54
|
icon="far fa-copy"
|
|
52
55
|
size="m"
|
|
@@ -55,20 +58,32 @@
|
|
|
55
58
|
@click="copyLink(defaultAsset.url)"
|
|
56
59
|
title="Copy link"
|
|
57
60
|
></VcButton>
|
|
58
|
-
</
|
|
61
|
+
</div>
|
|
59
62
|
</VcCol>
|
|
60
63
|
</VcCol>
|
|
61
64
|
</VcCol>
|
|
62
65
|
</VcRow>
|
|
63
66
|
|
|
64
|
-
<
|
|
65
|
-
class="tw-mb-4"
|
|
67
|
+
<Field
|
|
66
68
|
:label="$t('ASSETS.PAGES.DETAILS.FIELDS.NAME.TITLE')"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
name="asset_name"
|
|
70
|
+
rules="required"
|
|
71
|
+
:modelValue="defaultAsset.name"
|
|
72
|
+
v-slot="{ errorMessage, handleChange, errors }"
|
|
73
|
+
>
|
|
74
|
+
<VcInput
|
|
75
|
+
class="tw-mb-4"
|
|
76
|
+
:label="$t('ASSETS.PAGES.DETAILS.FIELDS.NAME.TITLE')"
|
|
77
|
+
v-model="assetNameClean"
|
|
78
|
+
@update:modelValue="handleChange"
|
|
79
|
+
clearable
|
|
80
|
+
required
|
|
81
|
+
:error="!!errors.length"
|
|
82
|
+
:error-message="errorMessage"
|
|
83
|
+
:placeholder="$t('ASSETS.PAGES.DETAILS.FIELDS.NAME.PLACEHOLDER')"
|
|
84
|
+
:disabled="readonly"
|
|
85
|
+
></VcInput>
|
|
86
|
+
</Field>
|
|
72
87
|
<VcInput
|
|
73
88
|
class="tw-mb-4"
|
|
74
89
|
:label="$t('ASSETS.PAGES.DETAILS.FIELDS.ALT.TITLE')"
|
|
@@ -76,15 +91,15 @@
|
|
|
76
91
|
clearable
|
|
77
92
|
:placeholder="$t('ASSETS.PAGES.DETAILS.FIELDS.ALT.PLACEHOLDER')"
|
|
78
93
|
:tooltip="$t('ASSETS.PAGES.DETAILS.FIELDS.ALT.TOOLTIP')"
|
|
79
|
-
required
|
|
80
94
|
v-if="assetType === 'Image'"
|
|
95
|
+
:disabled="readonly"
|
|
81
96
|
></VcInput>
|
|
82
97
|
<VcTextarea
|
|
83
98
|
class="tw-mb-4"
|
|
84
99
|
:label="$t('ASSETS.PAGES.DETAILS.FIELDS.DESCRIPTION.TITLE')"
|
|
85
100
|
v-model="defaultAsset.description"
|
|
86
101
|
:placeholder="$t('ASSETS.PAGES.DETAILS.FIELDS.DESCRIPTION.PLACEHOLDER')"
|
|
87
|
-
|
|
102
|
+
:disabled="readonly"
|
|
88
103
|
></VcTextarea>
|
|
89
104
|
</VcForm>
|
|
90
105
|
</div>
|
|
@@ -95,18 +110,20 @@
|
|
|
95
110
|
</template>
|
|
96
111
|
|
|
97
112
|
<script lang="ts" setup>
|
|
98
|
-
import { Asset } from "./../../../../../core/types";
|
|
113
|
+
import { Asset, IBladeToolbar } from "./../../../../../core/types";
|
|
99
114
|
import { computed, ref } from "vue";
|
|
100
115
|
import { useI18n } from "vue-i18n";
|
|
101
116
|
import { VcBlade, VcContainer, VcForm, VcImage, VcInput, VcTextarea } from "./../../../../../ui/components";
|
|
102
117
|
import { isImage, getFileThumbnail, readableSize } from "./../../../../utilities/assets";
|
|
103
118
|
import moment from "moment";
|
|
119
|
+
import { useIsFormValid, Field, useForm, useIsFormDirty } from "vee-validate";
|
|
104
120
|
|
|
105
121
|
export interface Props {
|
|
106
122
|
expanded?: boolean;
|
|
107
123
|
closable?: boolean;
|
|
108
124
|
options?: {
|
|
109
125
|
asset: Asset;
|
|
126
|
+
disabled?: boolean;
|
|
110
127
|
assetEditHandler?: (defaultAsset: Asset) => void;
|
|
111
128
|
assetRemoveHandler?: (defaultAsset: Asset) => void;
|
|
112
129
|
};
|
|
@@ -122,10 +139,29 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
122
139
|
});
|
|
123
140
|
|
|
124
141
|
const emit = defineEmits<Emits>();
|
|
142
|
+
useForm({ validateOnMount: false });
|
|
143
|
+
const isValid = useIsFormValid();
|
|
144
|
+
const isDirty = useIsFormDirty();
|
|
125
145
|
const { t } = useI18n();
|
|
126
146
|
const defaultAsset = ref<Asset>({ ...props.options?.asset });
|
|
127
147
|
|
|
128
|
-
const
|
|
148
|
+
const readonly = computed(() => props.options.disabled);
|
|
149
|
+
|
|
150
|
+
const assetNameClean = computed({
|
|
151
|
+
get() {
|
|
152
|
+
return defaultAsset.value.name.split(".").shift();
|
|
153
|
+
},
|
|
154
|
+
set(value: string) {
|
|
155
|
+
const fileExtension = defaultAsset.value.name.split(".").pop();
|
|
156
|
+
defaultAsset.value.name = value + "." + fileExtension;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const isDisabled = computed(() => {
|
|
161
|
+
return !isDirty.value || !isValid.value;
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
129
165
|
{
|
|
130
166
|
id: "save",
|
|
131
167
|
title: t("ASSETS.PAGES.DETAILS.TOOLBAR.SAVE"),
|
|
@@ -136,6 +172,7 @@ const bladeToolbar = [
|
|
|
136
172
|
emit("close:blade");
|
|
137
173
|
}
|
|
138
174
|
},
|
|
175
|
+
disabled: computed(() => isDisabled.value || readonly.value),
|
|
139
176
|
},
|
|
140
177
|
{
|
|
141
178
|
id: "delete",
|
|
@@ -147,8 +184,9 @@ const bladeToolbar = [
|
|
|
147
184
|
emit("close:blade");
|
|
148
185
|
}
|
|
149
186
|
},
|
|
187
|
+
disabled: computed(() => readonly.value),
|
|
150
188
|
},
|
|
151
|
-
];
|
|
189
|
+
]);
|
|
152
190
|
|
|
153
191
|
const assetType = computed(() => defaultAsset.value?.typeId);
|
|
154
192
|
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
:columns="columns"
|
|
19
19
|
:expanded="expanded"
|
|
20
20
|
stateKey="assets_manager"
|
|
21
|
-
:reorderableRows="
|
|
21
|
+
:reorderableRows="!readonly"
|
|
22
22
|
:items="defaultAssets"
|
|
23
23
|
:header="false"
|
|
24
24
|
:footer="false"
|
|
25
|
-
:itemActionBuilder="actionBuilder"
|
|
26
|
-
multiselect
|
|
25
|
+
:itemActionBuilder="!readonly && actionBuilder"
|
|
26
|
+
:multiselect="!readonly"
|
|
27
27
|
class="tw-h-full tw-w-full"
|
|
28
28
|
@item-click="onItemClick"
|
|
29
29
|
@row:reorder="sortAssets"
|
|
@@ -147,15 +147,16 @@ import { IBladeEvent, IParentCallArgs } from "./../../../../../shared";
|
|
|
147
147
|
import moment from "moment";
|
|
148
148
|
import Assets from "./../../../assets/components/assets-details/assets-details.vue";
|
|
149
149
|
import { isImage, getFileThumbnail, readableSize } from "./../../../../utilities/assets";
|
|
150
|
+
import { cloneDeep, isEqual } from "lodash-es";
|
|
150
151
|
|
|
151
152
|
export interface Props {
|
|
152
153
|
expanded?: boolean;
|
|
153
154
|
closable?: boolean;
|
|
154
155
|
options: {
|
|
155
156
|
assets: Asset[];
|
|
156
|
-
assetsEditHandler: (assets: Asset[]) =>
|
|
157
|
-
assetsUploadHandler: (files: FileList) =>
|
|
158
|
-
assetsRemoveHandler: (assets: Asset[]) =>
|
|
157
|
+
assetsEditHandler: (assets: Asset[]) => Asset[];
|
|
158
|
+
assetsUploadHandler: (files: FileList) => Promise<Asset[]>;
|
|
159
|
+
assetsRemoveHandler: (assets: Asset[]) => Asset[];
|
|
159
160
|
disabled: boolean;
|
|
160
161
|
};
|
|
161
162
|
}
|
|
@@ -182,6 +183,9 @@ const isDragging = ref(false);
|
|
|
182
183
|
const uploader = ref();
|
|
183
184
|
const loading = ref(false);
|
|
184
185
|
const selectedItems = ref([]);
|
|
186
|
+
const readonly = computed(() => props.options.disabled);
|
|
187
|
+
let assetsCopy;
|
|
188
|
+
const modified = ref(false);
|
|
185
189
|
|
|
186
190
|
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
187
191
|
{
|
|
@@ -191,6 +195,7 @@ const bladeToolbar = ref<IBladeToolbar[]>([
|
|
|
191
195
|
clickHandler() {
|
|
192
196
|
emit("close:blade");
|
|
193
197
|
},
|
|
198
|
+
disabled: computed(() => !modified.value || readonly.value),
|
|
194
199
|
},
|
|
195
200
|
{
|
|
196
201
|
id: "add",
|
|
@@ -199,6 +204,7 @@ const bladeToolbar = ref<IBladeToolbar[]>([
|
|
|
199
204
|
clickHandler() {
|
|
200
205
|
toggleUploader();
|
|
201
206
|
},
|
|
207
|
+
disabled: computed(() => readonly.value),
|
|
202
208
|
},
|
|
203
209
|
{
|
|
204
210
|
id: "delete",
|
|
@@ -206,11 +212,10 @@ const bladeToolbar = ref<IBladeToolbar[]>([
|
|
|
206
212
|
icon: "fas fa-trash",
|
|
207
213
|
clickHandler() {
|
|
208
214
|
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));
|
|
215
|
+
defaultAssets.value = props.options.assetsRemoveHandler(selectedItems.value);
|
|
211
216
|
}
|
|
212
217
|
},
|
|
213
|
-
disabled: computed(() => !selectedItems.value.length),
|
|
218
|
+
disabled: computed(() => !selectedItems.value.length || readonly.value),
|
|
214
219
|
},
|
|
215
220
|
]);
|
|
216
221
|
|
|
@@ -248,35 +253,48 @@ const columns = ref<ITableColumns[]>([
|
|
|
248
253
|
},
|
|
249
254
|
]);
|
|
250
255
|
|
|
256
|
+
watch(
|
|
257
|
+
() => defaultAssets.value,
|
|
258
|
+
(newVal) => {
|
|
259
|
+
modified.value = !isEqual(newVal, assetsCopy);
|
|
260
|
+
},
|
|
261
|
+
{ deep: true }
|
|
262
|
+
);
|
|
263
|
+
|
|
251
264
|
onMounted(() => {
|
|
252
265
|
defaultAssets.value = props.options?.assets;
|
|
266
|
+
assetsCopy = cloneDeep(props.options?.assets);
|
|
253
267
|
});
|
|
254
268
|
|
|
255
269
|
function sortAssets(event: { dragIndex: number; dropIndex: number; value: Asset[] }) {
|
|
256
|
-
if (
|
|
270
|
+
if (
|
|
271
|
+
props.options.assetsEditHandler &&
|
|
272
|
+
typeof props.options.assetsEditHandler === "function" &&
|
|
273
|
+
event.dragIndex !== event.dropIndex
|
|
274
|
+
) {
|
|
257
275
|
const sorted = event.value.map((item, index) => {
|
|
258
276
|
item.sortOrder = index;
|
|
259
277
|
return item;
|
|
260
278
|
});
|
|
261
|
-
|
|
262
|
-
props.options.assetsEditHandler(sorted);
|
|
279
|
+
|
|
280
|
+
defaultAssets.value = props.options.assetsEditHandler(sorted);
|
|
263
281
|
}
|
|
264
282
|
}
|
|
265
283
|
|
|
266
284
|
function dragOver() {
|
|
267
|
-
if (!
|
|
285
|
+
if (!readonly.value) {
|
|
268
286
|
isDragging.value = true;
|
|
269
287
|
}
|
|
270
288
|
}
|
|
271
289
|
|
|
272
290
|
function dragLeave() {
|
|
273
|
-
if (!
|
|
291
|
+
if (!readonly.value) {
|
|
274
292
|
isDragging.value = false;
|
|
275
293
|
}
|
|
276
294
|
}
|
|
277
295
|
|
|
278
296
|
async function onDrop(event: DragEvent) {
|
|
279
|
-
if (!
|
|
297
|
+
if (!readonly.value) {
|
|
280
298
|
const fileList = event.dataTransfer?.files;
|
|
281
299
|
|
|
282
300
|
if (fileList && fileList.length) {
|
|
@@ -295,7 +313,7 @@ async function upload(files: FileList) {
|
|
|
295
313
|
if (files && files.length) {
|
|
296
314
|
try {
|
|
297
315
|
loading.value = true;
|
|
298
|
-
await props.options.assetsUploadHandler(files);
|
|
316
|
+
defaultAssets.value = await props.options.assetsUploadHandler(files);
|
|
299
317
|
} finally {
|
|
300
318
|
loading.value = false;
|
|
301
319
|
}
|
|
@@ -316,6 +334,7 @@ function onItemClick(item: Asset) {
|
|
|
316
334
|
component: shallowRef(Assets),
|
|
317
335
|
bladeOptions: {
|
|
318
336
|
asset: unref(item),
|
|
337
|
+
disabled: readonly.value,
|
|
319
338
|
assetEditHandler: (asset: Asset) => {
|
|
320
339
|
const mutated = defaultAssets.value.map((x) => {
|
|
321
340
|
if (x.id === asset.id || x.url === asset.url) {
|
|
@@ -325,12 +344,11 @@ function onItemClick(item: Asset) {
|
|
|
325
344
|
});
|
|
326
345
|
|
|
327
346
|
if (props.options.assetsEditHandler && typeof props.options.assetsEditHandler === "function") {
|
|
328
|
-
defaultAssets.value = mutated;
|
|
329
|
-
props.options.assetsEditHandler(mutated);
|
|
347
|
+
defaultAssets.value = props.options.assetsEditHandler(mutated);
|
|
330
348
|
}
|
|
331
349
|
},
|
|
332
350
|
assetRemoveHandler: (asset: Asset) => {
|
|
333
|
-
props.options.assetsRemoveHandler([asset]);
|
|
351
|
+
defaultAssets.value = props.options.assetsRemoveHandler([asset]);
|
|
334
352
|
},
|
|
335
353
|
},
|
|
336
354
|
});
|
|
@@ -357,8 +375,7 @@ const actionBuilder = (): IActionBuilderResult[] => {
|
|
|
357
375
|
variant: "danger",
|
|
358
376
|
leftActions: true,
|
|
359
377
|
clickHandler(item: Asset) {
|
|
360
|
-
props.options.assetsRemoveHandler([item]);
|
|
361
|
-
defaultAssets.value = defaultAssets.value.filter((asset) => asset !== item);
|
|
378
|
+
defaultAssets.value = props.options.assetsRemoveHandler([item]);
|
|
362
379
|
selectedItems.value = [];
|
|
363
380
|
},
|
|
364
381
|
});
|
package/tailwind.config.js
CHANGED
|
@@ -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)]
|
|
@@ -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>
|
|
@@ -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>{{
|
|
93
|
+
<span>{{ getDisplayLabel(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)]"
|
|
@@ -344,6 +344,26 @@ export interface Props {
|
|
|
344
344
|
* @returns Label of the current option
|
|
345
345
|
*/
|
|
346
346
|
optionLabel?: OptionProp;
|
|
347
|
+
/**
|
|
348
|
+
* @requires optionValue
|
|
349
|
+
* @description Similar to optionValue, but used only for displaying selection result in rare cases. **Can't be used without optionValue**
|
|
350
|
+
*
|
|
351
|
+
* Property of option which holds the 'value'
|
|
352
|
+
* Default value: id
|
|
353
|
+
* @param option The current option being processed
|
|
354
|
+
* @returns Value of the current option
|
|
355
|
+
*/
|
|
356
|
+
displayValue?: OptionProp;
|
|
357
|
+
/**
|
|
358
|
+
* @requires optionLabel
|
|
359
|
+
* @description Similar to optionValue, but used only for displaying selection result in rare cases. **Can't be used without optionLabel**
|
|
360
|
+
*
|
|
361
|
+
* Property of option which holds the 'label'
|
|
362
|
+
* Default value: title
|
|
363
|
+
* @param option The current option being processed
|
|
364
|
+
* @returns Label of the current option
|
|
365
|
+
*/
|
|
366
|
+
displayLabel?: OptionProp;
|
|
347
367
|
/**
|
|
348
368
|
* Update model with the value of the selected option instead of the whole option
|
|
349
369
|
*/
|
|
@@ -548,9 +568,13 @@ const hasNextPage = computed(() => {
|
|
|
548
568
|
return optionsList.value.length < totalItems.value;
|
|
549
569
|
});
|
|
550
570
|
|
|
551
|
-
const getOptionValue = computed(() => getPropValueFn(props.optionValue, "
|
|
571
|
+
const getOptionValue = computed(() => getPropValueFn(props.optionValue, "id"));
|
|
572
|
+
|
|
573
|
+
const getOptionLabel = computed(() => getPropValueFn(props.optionLabel, "title"));
|
|
574
|
+
|
|
575
|
+
const getDisplayValue = computed(() => getPropValueFn(props.displayValue, "id"));
|
|
552
576
|
|
|
553
|
-
const
|
|
577
|
+
const getDisplayLabel = computed(() => getPropValueFn(props.displayLabel, "title"));
|
|
554
578
|
|
|
555
579
|
const innerValue = computed((): Record<string, unknown>[] | string[] => {
|
|
556
580
|
const mapNull = props.mapOptions === true && props.multiple !== true;
|
|
@@ -593,7 +617,9 @@ const selectedScope = computed(() => {
|
|
|
593
617
|
|
|
594
618
|
const hasValue = computed(() => fieldValueIsFilled(innerValue.value));
|
|
595
619
|
|
|
596
|
-
const innerOptionsValue = computed(() =>
|
|
620
|
+
const innerOptionsValue = computed(() =>
|
|
621
|
+
innerValue.value.map((opt) => getOptionValue.value(opt) || getDisplayValue.value(opt))
|
|
622
|
+
);
|
|
597
623
|
|
|
598
624
|
const optionScope = computed(() => {
|
|
599
625
|
return optionsTemp.value.map((opt, i) => {
|
|
@@ -601,7 +627,7 @@ const optionScope = computed(() => {
|
|
|
601
627
|
index: i,
|
|
602
628
|
opt,
|
|
603
629
|
selected: isOptionSelected(opt) === true,
|
|
604
|
-
label: getOptionLabel.value(opt),
|
|
630
|
+
label: getOptionLabel.value(opt) || getDisplayLabel.value(opt),
|
|
605
631
|
toggleOption,
|
|
606
632
|
};
|
|
607
633
|
});
|
|
@@ -624,7 +650,7 @@ function getPropValueFn(propValue: OptionProp, defaultVal: OptionProp) {
|
|
|
624
650
|
}
|
|
625
651
|
|
|
626
652
|
function getOption(value: Record<string, unknown> | string, valueCache: Array<Record<string, unknown> | string>) {
|
|
627
|
-
const fn = (opt) => isEqual(getOptionValue.value(opt), value);
|
|
653
|
+
const fn = (opt) => isEqual(getOptionValue.value(opt), value) || isEqual(getDisplayValue.value(opt), value);
|
|
628
654
|
return defaultValue.value.find(fn) || optionsList.value.find(fn) || valueCache.find(fn) || value;
|
|
629
655
|
}
|
|
630
656
|
|
|
@@ -649,7 +675,8 @@ function removeAtIndex(index: number) {
|
|
|
649
675
|
}
|
|
650
676
|
|
|
651
677
|
function isOptionSelected(opt: Record<string, unknown>) {
|
|
652
|
-
const val = getOptionValue.value(opt);
|
|
678
|
+
const val = getOptionValue.value(opt) || getDisplayValue.value(opt);
|
|
679
|
+
|
|
653
680
|
return innerOptionsValue.value.find((v) => isEqual(v, val)) !== void 0;
|
|
654
681
|
}
|
|
655
682
|
|
|
@@ -722,7 +749,7 @@ function toggleOption(opt: { [x: string]: string }) {
|
|
|
722
749
|
return;
|
|
723
750
|
}
|
|
724
751
|
|
|
725
|
-
const optValue = getOptionValue.value(opt);
|
|
752
|
+
const optValue = getOptionValue.value(opt) || getDisplayValue.value(opt);
|
|
726
753
|
|
|
727
754
|
if (props.multiple !== true) {
|
|
728
755
|
if (innerValue.value.length === 0 || isEqual(getOptionValue.value(innerValue.value[0]), optValue) !== true) {
|
|
@@ -796,6 +823,10 @@ function emitValue(val: string) {
|
|
|
796
823
|
}
|
|
797
824
|
|
|
798
825
|
function onReset() {
|
|
826
|
+
if (props.multiple) {
|
|
827
|
+
emit("update:modelValue", []);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
799
830
|
emit("update:modelValue", null);
|
|
800
831
|
}
|
|
801
832
|
</script>
|
|
@@ -58,9 +58,10 @@
|
|
|
58
58
|
:disabled="disabled"
|
|
59
59
|
option-label="alias"
|
|
60
60
|
option-value="id"
|
|
61
|
+
:display-label="displayedValueLabel.label"
|
|
62
|
+
:display-value="displayedValueLabel.value"
|
|
61
63
|
:multiple="true"
|
|
62
64
|
:emit-value="false"
|
|
63
|
-
:clearable="false"
|
|
64
65
|
></VcSelect>
|
|
65
66
|
</Field>
|
|
66
67
|
|
|
@@ -92,11 +93,12 @@
|
|
|
92
93
|
:options="items"
|
|
93
94
|
option-label="alias"
|
|
94
95
|
option-value="id"
|
|
96
|
+
:display-label="displayedValueLabel.label"
|
|
97
|
+
:display-value="displayedValueLabel.value"
|
|
95
98
|
@search="onSearch"
|
|
96
99
|
@close="onClose"
|
|
97
100
|
:multiple="property.multivalue"
|
|
98
101
|
:emit-value="false"
|
|
99
|
-
:clearable="false"
|
|
100
102
|
></VcSelect>
|
|
101
103
|
</Field>
|
|
102
104
|
|
|
@@ -154,6 +156,8 @@
|
|
|
154
156
|
:options="items"
|
|
155
157
|
option-value="id"
|
|
156
158
|
:option-label="handleDisplayProperty"
|
|
159
|
+
:display-label="displayedValueLabel.label"
|
|
160
|
+
:display-value="displayedValueLabel.value"
|
|
157
161
|
multiple
|
|
158
162
|
></VcSelect>
|
|
159
163
|
</Field>
|
|
@@ -323,8 +327,8 @@
|
|
|
323
327
|
|
|
324
328
|
<script lang="ts" setup>
|
|
325
329
|
import { ref, onMounted, computed } from "vue";
|
|
326
|
-
import { useI18n } from "./../../../../core/composables";
|
|
327
330
|
import { Field } from "vee-validate";
|
|
331
|
+
import { useI18n } from "vue-i18n";
|
|
328
332
|
|
|
329
333
|
export interface Props {
|
|
330
334
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -348,6 +352,13 @@ export interface Props {
|
|
|
348
352
|
) => void | undefined;
|
|
349
353
|
culture?: string;
|
|
350
354
|
disabled?: boolean;
|
|
355
|
+
/**
|
|
356
|
+
* @description Used only with multiple selection **only** in rare cases, where we need to display selection with other value-label pair
|
|
357
|
+
*/
|
|
358
|
+
displayedValueLabel?: {
|
|
359
|
+
value: string;
|
|
360
|
+
label: string;
|
|
361
|
+
};
|
|
351
362
|
}
|
|
352
363
|
|
|
353
364
|
export interface PropertyItem {
|