@finema/core 3.22.0 → 3.24.0
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/README.md +22 -2
- package/dist/module.d.mts +2 -0
- package/dist/module.json +2 -2
- package/dist/module.mjs +18 -15
- package/dist/runtime/components/App.vue +1 -1
- package/dist/runtime/components/DevToolsWindow/index.vue +24 -26
- package/dist/runtime/components/Dialog/index.d.vue.ts +1 -4
- package/dist/runtime/components/Dialog/index.vue +17 -17
- package/dist/runtime/components/Dialog/index.vue.d.ts +1 -4
- package/dist/runtime/components/Empty.d.vue.ts +1 -2
- package/dist/runtime/components/Empty.vue +19 -11
- package/dist/runtime/components/Empty.vue.d.ts +1 -2
- package/dist/runtime/components/FlexDeck/index.vue +21 -23
- package/dist/runtime/components/Form/FieldWrapper.vue +1 -1
- package/dist/runtime/components/Form/Fields.d.vue.ts +1 -1
- package/dist/runtime/components/Form/Fields.vue +26 -20
- package/dist/runtime/components/Form/Fields.vue.d.ts +1 -1
- package/dist/runtime/components/Form/InputCheckbox/index.vue +3 -6
- package/dist/runtime/components/Form/InputCheckboxGroup/index.vue +3 -6
- package/dist/runtime/components/Form/InputComponent/index.vue +2 -1
- package/dist/runtime/components/Form/InputCurrency/index.vue +11 -11
- package/dist/runtime/components/Form/InputDateTime/date_time_field.types.d.ts +3 -1
- package/dist/runtime/components/Form/InputDateTime/index.vue +12 -17
- package/dist/runtime/components/Form/InputDateTimeRange/date_range_time_field.types.d.ts +1 -1
- package/dist/runtime/components/Form/InputDateTimeRange/index.vue +28 -20
- package/dist/runtime/components/Form/InputMonth/index.vue +14 -12
- package/dist/runtime/components/Form/InputMonth/types.d.ts +1 -1
- package/dist/runtime/components/Form/InputNumber/index.vue +3 -6
- package/dist/runtime/components/Form/InputRadio/index.vue +3 -6
- package/dist/runtime/components/Form/InputRating/index.vue +3 -6
- package/dist/runtime/components/Form/InputSearch/index.vue +6 -7
- package/dist/runtime/components/Form/InputSelect/index.vue +6 -15
- package/dist/runtime/components/Form/InputSelectMultiple/index.vue +7 -18
- package/dist/runtime/components/Form/InputTags/index.vue +3 -6
- package/dist/runtime/components/Form/InputText/index.vue +41 -51
- package/dist/runtime/components/Form/InputTextarea/index.vue +3 -6
- package/dist/runtime/components/Form/InputTime/index.vue +32 -27
- package/dist/runtime/components/Form/InputTime/types.d.ts +1 -1
- package/dist/runtime/components/Form/InputToggle/index.vue +3 -5
- package/dist/runtime/components/Form/InputUploadDropzone/index.d.vue.ts +1 -4
- package/dist/runtime/components/Form/InputUploadDropzone/index.vue +25 -23
- package/dist/runtime/components/Form/InputUploadDropzone/index.vue.d.ts +1 -4
- package/dist/runtime/components/Form/InputUploadDropzone/types.d.ts +2 -2
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.d.vue.ts +0 -5
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +22 -23
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue.d.ts +0 -5
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/types.d.ts +3 -3
- package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.d.vue.ts +0 -5
- package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue +26 -24
- package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/index.vue.d.ts +0 -5
- package/dist/runtime/components/Form/InputUploadDropzoneAutoMultiple/types.d.ts +3 -3
- package/dist/runtime/components/Form/InputUploadImageAuto/index.d.vue.ts +1 -6
- package/dist/runtime/components/Form/InputUploadImageAuto/index.vue +22 -23
- package/dist/runtime/components/Form/InputUploadImageAuto/index.vue.d.ts +1 -6
- package/dist/runtime/components/Form/InputUploadImageAuto/types.d.ts +3 -3
- package/dist/runtime/components/Form/InputWYSIWYG/EditorImagePasteExtension.js +7 -6
- package/dist/runtime/components/Form/InputWYSIWYG/EditorImageUploadExtension.js +13 -12
- package/dist/runtime/components/Form/InputWYSIWYG/EditorImageUploadNode.vue +3 -1
- package/dist/runtime/components/Form/InputWYSIWYG/EditorLinkPopover.vue +20 -22
- package/dist/runtime/components/Form/InputWYSIWYG/index.vue +140 -118
- package/dist/runtime/components/Form/fileState/EmptyState.vue +1 -1
- package/dist/runtime/components/Form/fileState/FailedState.vue +4 -2
- package/dist/runtime/components/Form/fileState/MultipleFilesState.d.vue.ts +4 -4
- package/dist/runtime/components/Form/fileState/MultipleFilesState.vue +5 -5
- package/dist/runtime/components/Form/fileState/MultipleFilesState.vue.d.ts +4 -4
- package/dist/runtime/components/Form/fileState/SuccessState.d.vue.ts +2 -2
- package/dist/runtime/components/Form/fileState/SuccessState.vue +8 -13
- package/dist/runtime/components/Form/fileState/SuccessState.vue.d.ts +2 -2
- package/dist/runtime/components/Form/fileState/useFilePicker.d.ts +34 -0
- package/dist/runtime/components/Form/fileState/useFilePicker.js +48 -0
- package/dist/runtime/components/Form/fileState/useFileState.d.ts +7 -9
- package/dist/runtime/components/Form/fileState/useFileState.js +32 -120
- package/dist/runtime/components/Form/fileState/useUploadImageState.d.ts +7 -8
- package/dist/runtime/components/Form/fileState/useUploadImageState.js +27 -301
- package/dist/runtime/components/Form/fileState/useUploadState.d.ts +11 -7
- package/dist/runtime/components/Form/fileState/useUploadState.js +52 -136
- package/dist/runtime/components/Form/fileState/useUploadStateMultiple.d.ts +12 -18
- package/dist/runtime/components/Form/fileState/useUploadStateMultiple.js +88 -226
- package/dist/runtime/components/Form/types.d.ts +2 -0
- package/dist/runtime/components/Image.vue +4 -10
- package/dist/runtime/components/Loader.d.vue.ts +2 -1
- package/dist/runtime/components/Loader.vue +10 -7
- package/dist/runtime/components/Loader.vue.d.ts +2 -1
- package/dist/runtime/components/Log/LogItem.vue +1 -3
- package/dist/runtime/components/Log/index.vue +1 -3
- package/dist/runtime/components/Table/Base.d.vue.ts +15 -1
- package/dist/runtime/components/Table/Base.vue +9 -29
- package/dist/runtime/components/Table/Base.vue.d.ts +15 -1
- package/dist/runtime/components/Table/ColumnText.d.vue.ts +2 -3
- package/dist/runtime/components/Table/ColumnText.vue +1 -1
- package/dist/runtime/components/Table/ColumnText.vue.d.ts +2 -3
- package/dist/runtime/components/Table/Pagination.vue +19 -22
- package/dist/runtime/components/Table/index.d.vue.ts +1 -1
- package/dist/runtime/components/Table/index.vue +5 -7
- package/dist/runtime/components/Table/index.vue.d.ts +1 -1
- package/dist/runtime/composables/loaderList.d.ts +2 -1
- package/dist/runtime/composables/loaderList.js +3 -4
- package/dist/runtime/composables/loaderObject.d.ts +2 -1
- package/dist/runtime/composables/loaderObject.js +2 -1
- package/dist/runtime/composables/loaderPage.js +223 -350
- package/dist/runtime/composables/useConfig.js +4 -3
- package/dist/runtime/composables/useDialog.js +3 -1
- package/dist/runtime/composables/useForm.d.ts +2 -2
- package/dist/runtime/composables/useForm.js +2 -4
- package/dist/runtime/composables/useMessages.d.ts +10 -0
- package/dist/runtime/composables/useMessages.js +10 -0
- package/dist/runtime/composables/useTable.js +2 -14
- package/dist/runtime/helpers/apiBaseHelper.js +6 -24
- package/dist/runtime/helpers/apiListHelper.js +2 -5
- package/dist/runtime/helpers/apiObjectHelper.js +2 -5
- package/dist/runtime/helpers/apiPageHelper.d.ts +0 -1
- package/dist/runtime/helpers/apiPageHelper.js +19 -38
- package/dist/runtime/helpers/componentHelper.js +2 -6
- package/dist/runtime/helpers/uploadCore.d.ts +54 -0
- package/dist/runtime/helpers/uploadCore.js +81 -0
- package/dist/runtime/i18n/valibot.d.ts +5 -68
- package/dist/runtime/i18n/valibot.js +33 -29
- package/dist/runtime/locale/en.d.ts +2 -0
- package/dist/runtime/locale/en.js +42 -0
- package/dist/runtime/locale/index.d.ts +7 -0
- package/dist/runtime/locale/index.js +5 -0
- package/dist/runtime/locale/th.d.ts +43 -0
- package/dist/runtime/locale/th.js +42 -0
- package/dist/runtime/server/tsconfig.json +1 -1
- package/dist/runtime/styles/main.css +1 -1
- package/dist/runtime/utils/ParamHelper.js +1 -1
- package/dist/runtime/utils/StringHelper.js +1 -4
- package/dist/runtime/utils/TimeHelper.js +2 -2
- package/dist/runtime/utils/lodash.js +2 -2
- package/package.json +57 -36
|
@@ -1,211 +1,121 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import { useFilePicker } from "./useFilePicker.js";
|
|
2
|
+
import { toFileValue, toUploadFormData, UploadState, validateFile } from "#core/helpers/uploadCore";
|
|
3
|
+
import { useCoreMessages } from "#core/composables/useMessages";
|
|
4
4
|
import { useUploadLoader } from "#core/composables/useUpload";
|
|
5
|
-
import {
|
|
5
|
+
import { useFileProgress } from "#core/helpers/componentHelper";
|
|
6
6
|
import { StringHelper } from "#core/utils/StringHelper";
|
|
7
|
-
import {
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
UploadState2["ERROR"] = "error";
|
|
13
|
-
return UploadState2;
|
|
14
|
-
})(UploadState || {});
|
|
15
|
-
export const useUploadStateMultiple = (props, emits, onChange, setErrors, value, acceptedFileTypes, wrapperProps, dropzoneRef) => {
|
|
16
|
-
const overlay = useOverlay();
|
|
17
|
-
const previewModal = overlay.create(PreviewModal);
|
|
7
|
+
import { ArrayHelper, computed, ref, watch } from "#imports";
|
|
8
|
+
export { UploadState };
|
|
9
|
+
export const useUploadStateMultiple = (context) => {
|
|
10
|
+
const { props, emits, onChange, setErrors, value } = context;
|
|
11
|
+
const { messages, format } = useCoreMessages();
|
|
18
12
|
const fileItems = ref([]);
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
if (props.accept && fileAllocate.acceptFile.value) {
|
|
22
|
-
const acceptedTypes = fileAllocate.acceptFile.value;
|
|
23
|
-
const acceptedTypesList = acceptedTypes.split(",").map((type) => type.trim());
|
|
24
|
-
const fileExtension = file.name.toLowerCase().split(".").pop();
|
|
25
|
-
const isValidFileType = acceptedTypesList.some((acceptedType) => {
|
|
26
|
-
if (acceptedType.startsWith(".")) {
|
|
27
|
-
return fileExtension === acceptedType.slice(1).toLowerCase();
|
|
28
|
-
}
|
|
29
|
-
if (!acceptedType.includes("/") && !acceptedType.includes("*")) {
|
|
30
|
-
return fileExtension === acceptedType.toLowerCase();
|
|
31
|
-
}
|
|
32
|
-
if (acceptedType.endsWith("/*")) {
|
|
33
|
-
return file.type.startsWith(acceptedType.slice(0, -2) + "/");
|
|
34
|
-
}
|
|
35
|
-
return file.type === acceptedType;
|
|
36
|
-
});
|
|
37
|
-
if (!isValidFileType) {
|
|
38
|
-
return {
|
|
39
|
-
valid: false,
|
|
40
|
-
error: `\u0E1B\u0E23\u0E30\u0E40\u0E20\u0E17\u0E44\u0E1F\u0E25\u0E4C\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07 (\u0E23\u0E2D\u0E07\u0E23\u0E31\u0E1A\u0E40\u0E09\u0E1E\u0E32\u0E30 ${acceptedTypesList.join(", ")})`
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (props.maxSize) {
|
|
45
|
-
const maxSizeBytes = (fileAllocate.acceptFileSizeKb.value || 0) * 1024;
|
|
46
|
-
if (file.size > maxSizeBytes) {
|
|
47
|
-
const sizeLabel = fileAllocate.isAcceptFileUseMb.value ? `${fileAllocate.acceptFileSizeMb.value} MB` : `${fileAllocate.acceptFileSizeKb.value} KB`;
|
|
48
|
-
return {
|
|
49
|
-
valid: false,
|
|
50
|
-
error: `\u0E02\u0E19\u0E32\u0E14\u0E44\u0E1F\u0E25\u0E4C\u0E15\u0E49\u0E2D\u0E07\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 ${sizeLabel}`
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
valid: true
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
const updateFileItem = (index, updates) => {
|
|
13
|
+
let nextId = 0;
|
|
14
|
+
const updateFileItem = (id, updates) => {
|
|
59
15
|
fileItems.value = fileItems.value.map(
|
|
60
|
-
(item
|
|
16
|
+
(item) => item.id === id ? {
|
|
61
17
|
...item,
|
|
62
18
|
...updates
|
|
63
19
|
} : item
|
|
64
20
|
);
|
|
65
21
|
};
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
22
|
+
const removeFileItem = (id) => {
|
|
23
|
+
fileItems.value = fileItems.value.filter((item) => item.id !== id);
|
|
24
|
+
};
|
|
25
|
+
const isFull = () => !!props.maxFiles && fileItems.value.length >= props.maxFiles;
|
|
26
|
+
const setMaxFilesError = () => {
|
|
27
|
+
setErrors(
|
|
28
|
+
format(messages.value.upload.maxFiles, {
|
|
29
|
+
max: props.maxFiles
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
const uploadFile = async (id, file) => {
|
|
34
|
+
const { percent, onDownloadProgress, onUploadProgress } = useFileProgress();
|
|
35
|
+
const uploadLoader = useUploadLoader({
|
|
73
36
|
requestOptions: {
|
|
74
37
|
...props.requestOptions,
|
|
75
38
|
onDownloadProgress,
|
|
76
39
|
onUploadProgress
|
|
77
40
|
},
|
|
78
41
|
pathURL: props.uploadPathURL
|
|
79
|
-
};
|
|
80
|
-
const uploadLoader = useUploadLoader(request);
|
|
81
|
-
updateFileItem(index, {
|
|
82
|
-
uploadLoader,
|
|
83
|
-
percentRef: percent
|
|
84
42
|
});
|
|
85
|
-
const stopProgressWatch = watch(
|
|
86
|
-
|
|
87
|
-
|
|
43
|
+
const stopProgressWatch = watch(
|
|
44
|
+
percent,
|
|
45
|
+
(progress) => updateFileItem(id, {
|
|
46
|
+
progress
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
try {
|
|
50
|
+
await uploadLoader.run({
|
|
51
|
+
data: toUploadFormData(props.bodyKey, file)
|
|
88
52
|
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
53
|
+
} finally {
|
|
54
|
+
stopProgressWatch();
|
|
55
|
+
}
|
|
56
|
+
if (uploadLoader.status.value.isSuccess && uploadLoader.data.value) {
|
|
57
|
+
const fileValue = toFileValue(uploadLoader.data.value, props, file);
|
|
58
|
+
removeFileItem(id);
|
|
59
|
+
onChange([fileValue, ...ArrayHelper.toArray(value.value)]);
|
|
60
|
+
emits("success", fileValue);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
updateFileItem(id, {
|
|
64
|
+
state: UploadState.ERROR,
|
|
65
|
+
error: format(messages.value.upload.error, {
|
|
66
|
+
message: StringHelper.getError(uploadLoader.status.value.errorData, messages.value.common.somethingWentWrong)
|
|
67
|
+
})
|
|
98
68
|
});
|
|
99
69
|
};
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
if (
|
|
103
|
-
setErrors(
|
|
70
|
+
const processFile = async (file) => {
|
|
71
|
+
const error = validateFile(file, props, messages.value.upload);
|
|
72
|
+
if (error) {
|
|
73
|
+
setErrors(error);
|
|
104
74
|
return;
|
|
105
75
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
76
|
+
if (isFull()) {
|
|
77
|
+
setMaxFilesError();
|
|
108
78
|
return;
|
|
109
79
|
}
|
|
110
80
|
setErrors("");
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
await
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const fileValue = {
|
|
127
|
-
url: _get(uploadLoader.data.value, props.responseURL),
|
|
128
|
-
path: _get(uploadLoader.data.value, props.responsePath),
|
|
129
|
-
name: _get(uploadLoader.data.value, props.responseName) || fileItem.file.name,
|
|
130
|
-
size: Number(_get(uploadLoader.data.value, props.responseSize) || fileItem.file.size),
|
|
131
|
-
id: _get(uploadLoader.data.value, props.responseID)
|
|
132
|
-
};
|
|
133
|
-
fileItems.value = fileItems.value.filter((_, i) => i !== newIndex);
|
|
134
|
-
onChange([fileValue, ...ArrayHelper.toArray(value.value)]);
|
|
135
|
-
emits("success", fileValue);
|
|
136
|
-
stopSuccessWatch();
|
|
137
|
-
stopErrorWatch();
|
|
138
|
-
resolve();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
);
|
|
142
|
-
const stopErrorWatch = watch(
|
|
143
|
-
() => uploadLoader.status.value.isError,
|
|
144
|
-
(isError) => {
|
|
145
|
-
if (isError) {
|
|
146
|
-
updateFileItem(newIndex, {
|
|
147
|
-
state: "error" /* ERROR */,
|
|
148
|
-
error: "\u0E1E\u0E1A\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14: " + StringHelper.getError(
|
|
149
|
-
uploadLoader.status.value.errorData
|
|
150
|
-
)
|
|
151
|
-
});
|
|
152
|
-
stopSuccessWatch();
|
|
153
|
-
stopErrorWatch();
|
|
154
|
-
reject(new Error("Upload failed"));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
uploadLoader.run({
|
|
159
|
-
data: formData
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
emits("change", fileItems.value.map((item) => item.file));
|
|
163
|
-
};
|
|
164
|
-
const handleFileDrop = async (files) => {
|
|
165
|
-
if (wrapperProps.value.disabled || wrapperProps.value.readonly || !files?.length) return;
|
|
166
|
-
for (const file of files) {
|
|
167
|
-
await processFileAsync(file);
|
|
168
|
-
}
|
|
81
|
+
const id = nextId++;
|
|
82
|
+
fileItems.value = [
|
|
83
|
+
...fileItems.value,
|
|
84
|
+
{
|
|
85
|
+
id,
|
|
86
|
+
file,
|
|
87
|
+
state: UploadState.UPLOADING,
|
|
88
|
+
progress: 0
|
|
89
|
+
}
|
|
90
|
+
];
|
|
91
|
+
await uploadFile(id, file);
|
|
92
|
+
emits(
|
|
93
|
+
"change",
|
|
94
|
+
fileItems.value.map((item) => item.file)
|
|
95
|
+
);
|
|
169
96
|
};
|
|
170
|
-
const
|
|
171
|
-
accept: acceptedFileTypes.value || "",
|
|
172
|
-
directory: false,
|
|
173
|
-
multiple: true
|
|
174
|
-
});
|
|
175
|
-
const dropzone = useDropZone(dropzoneRef, {
|
|
176
|
-
onDrop: handleFileDrop,
|
|
97
|
+
const picker = useFilePicker(context, {
|
|
177
98
|
multiple: true,
|
|
178
|
-
|
|
99
|
+
onFiles: async (files) => {
|
|
100
|
+
for (const file of files) {
|
|
101
|
+
await processFile(file);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
179
104
|
});
|
|
180
105
|
const isEmpty = computed(() => fileItems.value.length === 0);
|
|
181
|
-
const hasUploading = computed(
|
|
182
|
-
() => fileItems.value.some((item) => item.state === "uploading" /* UPLOADING */)
|
|
183
|
-
);
|
|
106
|
+
const hasUploading = computed(() => fileItems.value.some((item) => item.state === UploadState.UPLOADING));
|
|
184
107
|
const allSuccess = computed(
|
|
185
|
-
() => fileItems.value.length > 0 && fileItems.value.every((item) => item.state ===
|
|
108
|
+
() => fileItems.value.length > 0 && fileItems.value.every((item) => item.state === UploadState.SUCCESS)
|
|
186
109
|
);
|
|
187
|
-
fileDialog.onChange(async (files) => {
|
|
188
|
-
if (files?.length) {
|
|
189
|
-
for (const file of Array.from(files)) {
|
|
190
|
-
await processFileAsync(file);
|
|
191
|
-
}
|
|
192
|
-
fileDialog.reset();
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
110
|
const handleOpenFile = () => {
|
|
196
|
-
if (
|
|
197
|
-
|
|
111
|
+
if (isFull()) {
|
|
112
|
+
setMaxFilesError();
|
|
198
113
|
return;
|
|
199
114
|
}
|
|
200
|
-
|
|
201
|
-
fileDialog.open();
|
|
115
|
+
picker.handleOpenFile();
|
|
202
116
|
};
|
|
203
117
|
const handleDeleteFile = (index) => {
|
|
204
|
-
|
|
205
|
-
if (fileItem?.cleanupWatchers) {
|
|
206
|
-
fileItem.cleanupWatchers.forEach((cleanup) => cleanup());
|
|
207
|
-
}
|
|
208
|
-
fileItems.value.splice(index, 1);
|
|
118
|
+
fileItems.value = fileItems.value.filter((_, itemIndex) => itemIndex !== index);
|
|
209
119
|
if (fileItems.value.length === 0) {
|
|
210
120
|
setErrors("");
|
|
211
121
|
}
|
|
@@ -214,60 +124,12 @@ export const useUploadStateMultiple = (props, emits, onChange, setErrors, value,
|
|
|
214
124
|
const handleRetryUpload = async (index) => {
|
|
215
125
|
const fileItem = fileItems.value[index];
|
|
216
126
|
if (!fileItem) return;
|
|
217
|
-
updateFileItem(
|
|
218
|
-
state:
|
|
127
|
+
updateFileItem(fileItem.id, {
|
|
128
|
+
state: UploadState.UPLOADING,
|
|
219
129
|
error: void 0,
|
|
220
130
|
progress: 0
|
|
221
131
|
});
|
|
222
|
-
|
|
223
|
-
const formData = new FormData();
|
|
224
|
-
formData.append(props.bodyKey, fileItem.file);
|
|
225
|
-
await new Promise((resolve, reject) => {
|
|
226
|
-
const stopSuccessWatch = watch(
|
|
227
|
-
() => uploadLoader.status.value.isSuccess,
|
|
228
|
-
(isSuccess) => {
|
|
229
|
-
if (isSuccess && uploadLoader.data.value) {
|
|
230
|
-
const fileValue = {
|
|
231
|
-
url: _get(uploadLoader.data.value, props.responseURL),
|
|
232
|
-
path: _get(uploadLoader.data.value, props.responsePath),
|
|
233
|
-
name: _get(uploadLoader.data.value, props.responseName) || fileItem.file.name,
|
|
234
|
-
size: Number(_get(uploadLoader.data.value, props.responseSize) || fileItem.file.size),
|
|
235
|
-
id: _get(uploadLoader.data.value, props.responseID)
|
|
236
|
-
};
|
|
237
|
-
fileItems.value = fileItems.value.filter((_, i) => i !== index);
|
|
238
|
-
onChange([fileValue, ...ArrayHelper.toArray(value.value)]);
|
|
239
|
-
emits("success", fileValue);
|
|
240
|
-
stopSuccessWatch();
|
|
241
|
-
stopErrorWatch();
|
|
242
|
-
resolve();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
);
|
|
246
|
-
const stopErrorWatch = watch(
|
|
247
|
-
() => uploadLoader.status.value.isError,
|
|
248
|
-
(isError) => {
|
|
249
|
-
if (isError) {
|
|
250
|
-
updateFileItem(index, {
|
|
251
|
-
state: "error" /* ERROR */,
|
|
252
|
-
error: "\u0E1E\u0E1A\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14: " + StringHelper.getError(
|
|
253
|
-
uploadLoader.status.value.errorData
|
|
254
|
-
)
|
|
255
|
-
});
|
|
256
|
-
stopSuccessWatch();
|
|
257
|
-
stopErrorWatch();
|
|
258
|
-
reject(new Error("Upload failed"));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
);
|
|
262
|
-
uploadLoader.run({
|
|
263
|
-
data: formData
|
|
264
|
-
});
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
const handlePreview = (fileValue) => {
|
|
268
|
-
previewModal.open({
|
|
269
|
-
value: fileValue
|
|
270
|
-
});
|
|
132
|
+
await uploadFile(fileItem.id, fileItem.file);
|
|
271
133
|
};
|
|
272
134
|
return {
|
|
273
135
|
// State
|
|
@@ -276,11 +138,11 @@ export const useUploadStateMultiple = (props, emits, onChange, setErrors, value,
|
|
|
276
138
|
hasUploading,
|
|
277
139
|
allSuccess,
|
|
278
140
|
// Upload utilities
|
|
279
|
-
dropzone,
|
|
141
|
+
dropzone: picker.dropzone,
|
|
280
142
|
// Handlers
|
|
281
143
|
handleOpenFile,
|
|
282
144
|
handleDeleteFile,
|
|
283
145
|
handleRetryUpload,
|
|
284
|
-
handlePreview
|
|
146
|
+
handlePreview: picker.openPreview
|
|
285
147
|
};
|
|
286
148
|
};
|
|
@@ -71,6 +71,8 @@ export interface IFieldProps {
|
|
|
71
71
|
required?: boolean;
|
|
72
72
|
help?: string;
|
|
73
73
|
ui?: object | any;
|
|
74
|
+
/** Classes for the FormField wrapper (label, hint, error); set by FormFields from the field's `ui` */
|
|
75
|
+
containerUi?: object | any;
|
|
74
76
|
}
|
|
75
77
|
export interface IFormFieldBase<I extends INPUT_TYPES, P extends IFieldProps, O> {
|
|
76
78
|
type: I;
|
|
@@ -2,25 +2,19 @@
|
|
|
2
2
|
<UseImage v-bind="$props">
|
|
3
3
|
<template #loading>
|
|
4
4
|
<slot name="loading">
|
|
5
|
-
<div
|
|
6
|
-
|
|
7
|
-
>
|
|
8
|
-
<Loader
|
|
9
|
-
:loading="true"
|
|
10
|
-
/>
|
|
5
|
+
<div class="flex h-full w-full items-center justify-center">
|
|
6
|
+
<Loader :loading="true" />
|
|
11
7
|
</div>
|
|
12
8
|
</slot>
|
|
13
9
|
</template>
|
|
14
10
|
|
|
15
11
|
<template #error>
|
|
16
12
|
<slot name="error">
|
|
17
|
-
<div
|
|
18
|
-
class="flex h-full w-full items-center justify-center"
|
|
19
|
-
>
|
|
13
|
+
<div class="flex h-full w-full items-center justify-center">
|
|
20
14
|
<p class="text-error-400">
|
|
21
15
|
<Icon
|
|
22
16
|
name="i-heroicons:exclamation-circle-solid"
|
|
23
|
-
class="text-error-400
|
|
17
|
+
class="size-8 text-error-400"
|
|
24
18
|
/>
|
|
25
19
|
</p>
|
|
26
20
|
</div>
|
|
@@ -2,11 +2,12 @@ import { loaderTheme } from '#core/theme/loader';
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
loading?: boolean;
|
|
4
4
|
icon?: string;
|
|
5
|
-
ui?: typeof loaderTheme['slots'];
|
|
5
|
+
ui?: (typeof loaderTheme)['slots'];
|
|
6
6
|
class?: any;
|
|
7
7
|
};
|
|
8
8
|
type __VLS_Slots = {
|
|
9
9
|
loading: () => any;
|
|
10
|
+
default: () => any;
|
|
10
11
|
};
|
|
11
12
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
12
13
|
loading: boolean;
|
|
@@ -4,16 +4,19 @@
|
|
|
4
4
|
name="loading"
|
|
5
5
|
>
|
|
6
6
|
<div
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
})
|
|
7
|
+
:class="
|
|
8
|
+
theme.base({
|
|
9
|
+
class: [ui?.base, props.class]
|
|
10
|
+
})
|
|
11
|
+
"
|
|
11
12
|
>
|
|
12
13
|
<Icon
|
|
13
14
|
:name="icon"
|
|
14
|
-
:class="[
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
:class="[
|
|
16
|
+
theme.icon({
|
|
17
|
+
class: [ui?.icon]
|
|
18
|
+
})
|
|
19
|
+
]"
|
|
17
20
|
/>
|
|
18
21
|
</div>
|
|
19
22
|
</slot>
|
|
@@ -2,11 +2,12 @@ import { loaderTheme } from '#core/theme/loader';
|
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
loading?: boolean;
|
|
4
4
|
icon?: string;
|
|
5
|
-
ui?: typeof loaderTheme['slots'];
|
|
5
|
+
ui?: (typeof loaderTheme)['slots'];
|
|
6
6
|
class?: any;
|
|
7
7
|
};
|
|
8
8
|
type __VLS_Slots = {
|
|
9
9
|
loading: () => any;
|
|
10
|
+
default: () => any;
|
|
10
11
|
};
|
|
11
12
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
12
13
|
loading: boolean;
|
|
@@ -7,7 +7,21 @@ type __VLS_Props = {
|
|
|
7
7
|
target?: string | ((row: any) => string | undefined);
|
|
8
8
|
preserveQuery?: boolean;
|
|
9
9
|
};
|
|
10
|
-
declare var __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_44: `${string}-cell`, __VLS_45:
|
|
10
|
+
declare var __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_44: `${string}-cell`, __VLS_45: {
|
|
11
|
+
cell: import("@tanstack/table-core").Cell<any, unknown>;
|
|
12
|
+
column: import("@tanstack/table-core").Column<any, unknown>;
|
|
13
|
+
getValue: import("@tanstack/table-core").Getter<unknown>;
|
|
14
|
+
renderValue: import("@tanstack/table-core").Getter<unknown>;
|
|
15
|
+
row: import("@tanstack/table-core").Row<any>;
|
|
16
|
+
table: import("@tanstack/table-core").Table<any>;
|
|
17
|
+
}, __VLS_64: string, __VLS_65: {
|
|
18
|
+
cell: import("@tanstack/table-core").Cell<any, unknown>;
|
|
19
|
+
column: import("@tanstack/table-core").Column<any, unknown>;
|
|
20
|
+
getValue: import("@tanstack/table-core").Getter<unknown>;
|
|
21
|
+
renderValue: import("@tanstack/table-core").Getter<unknown>;
|
|
22
|
+
row: import("@tanstack/table-core").Row<any>;
|
|
23
|
+
table: import("@tanstack/table-core").Table<any>;
|
|
24
|
+
};
|
|
11
25
|
type __VLS_Slots = {} & {
|
|
12
26
|
[K in NonNullable<typeof __VLS_44>]?: (props: typeof __VLS_45) => any;
|
|
13
27
|
} & {
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
v-else-if="options.status.isError"
|
|
39
39
|
name="error"
|
|
40
40
|
>
|
|
41
|
-
<div
|
|
42
|
-
class="text-error-400 flex h-[200px] items-center justify-center text-2xl"
|
|
43
|
-
>
|
|
41
|
+
<div class="flex h-[200px] items-center justify-center text-2xl text-error-400">
|
|
44
42
|
{{ StringHelper.getError(options.status.errorData) }}
|
|
45
43
|
</div>
|
|
46
44
|
</slot>
|
|
@@ -61,18 +59,12 @@
|
|
|
61
59
|
v-if="to && column.accessorKey !== 'actions'"
|
|
62
60
|
:to="resolveTo(slotProps.row.original)"
|
|
63
61
|
:target="resolveTarget(slotProps.row.original)"
|
|
64
|
-
:rel="
|
|
65
|
-
resolveTarget(slotProps.row.original) === '_blank' ? 'noopener noreferrer' : void 0
|
|
66
|
-
"
|
|
62
|
+
:rel="resolveTarget(slotProps.row.original) === '_blank' ? 'noopener noreferrer' : void 0"
|
|
67
63
|
class="absolute inset-0"
|
|
68
64
|
tabindex="-1"
|
|
69
65
|
aria-hidden="true"
|
|
70
66
|
/>
|
|
71
|
-
<div
|
|
72
|
-
:class="
|
|
73
|
-
to && column.accessorKey !== 'actions' ? 'pointer-events-none relative z-10' : 'relative z-10'
|
|
74
|
-
"
|
|
75
|
-
>
|
|
67
|
+
<div :class="to && column.accessorKey !== 'actions' ? 'pointer-events-none relative z-10' : 'relative z-10'">
|
|
76
68
|
<slot
|
|
77
69
|
:name="`${column.accessorKey}-cell`"
|
|
78
70
|
v-bind="slotProps"
|
|
@@ -86,9 +78,7 @@
|
|
|
86
78
|
/>
|
|
87
79
|
<component
|
|
88
80
|
:is="columnTypeComponents[column.type]"
|
|
89
|
-
v-else-if="
|
|
90
|
-
column.type !== COLUMN_TYPES.COMPONENT && columnTypeComponents[column.type]
|
|
91
|
-
"
|
|
81
|
+
v-else-if="column.type !== COLUMN_TYPES.COMPONENT && columnTypeComponents[column.type]"
|
|
92
82
|
:value="transformValue(column, slotProps.row)"
|
|
93
83
|
:column="column"
|
|
94
84
|
:row="slotProps.row"
|
|
@@ -135,18 +125,12 @@ import {
|
|
|
135
125
|
} from "#core/components/Table/types";
|
|
136
126
|
import ColumnNumber from "#core/components/Table/ColumnNumber.vue";
|
|
137
127
|
import ColumnImage from "#core/components/Table/ColumnImage.vue";
|
|
138
|
-
import {
|
|
139
|
-
useAppConfig,
|
|
140
|
-
useRoute,
|
|
141
|
-
useUiConfig,
|
|
142
|
-
useWatchChange,
|
|
143
|
-
StringHelper
|
|
144
|
-
} from "#imports";
|
|
128
|
+
import { useAppConfig, useRoute, useUiConfig, useWatchChange, StringHelper } from "#imports";
|
|
145
129
|
import ColumnDateTime from "#core/components/Table/ColumnDateTime.vue";
|
|
146
130
|
import Empty from "#core/components/Empty.vue";
|
|
147
131
|
import ColumnDate from "#core/components/Table/ColumnDate.vue";
|
|
148
132
|
import ColumnText from "#core/components/Table/ColumnText.vue";
|
|
149
|
-
import UTable from "#ui/components/Table";
|
|
133
|
+
import UTable from "#ui/components/Table.vue";
|
|
150
134
|
import Pagination from "./Pagination.vue";
|
|
151
135
|
import { tableTheme } from "#core/theme/table";
|
|
152
136
|
const emits = defineEmits(["pageChange", "search"]);
|
|
@@ -170,9 +154,7 @@ const VNodeRenderer = defineComponent({
|
|
|
170
154
|
});
|
|
171
155
|
const route = useRoute();
|
|
172
156
|
const slots = useSlots();
|
|
173
|
-
const forwardedSlotNames = computed(
|
|
174
|
-
() => Object.keys(slots).filter((name) => !name.endsWith("-cell"))
|
|
175
|
-
);
|
|
157
|
+
const forwardedSlotNames = computed(() => Object.keys(slots).filter((name) => !name.endsWith("-cell")));
|
|
176
158
|
const columnTypeComponents = {
|
|
177
159
|
[COLUMN_TYPES.NUMBER]: ColumnNumber,
|
|
178
160
|
[COLUMN_TYPES.IMAGE]: ColumnImage,
|
|
@@ -183,9 +165,7 @@ const columnTypeComponents = {
|
|
|
183
165
|
const theme = computed(() => useUiConfig(tableTheme, "table")());
|
|
184
166
|
const config = useAppConfig();
|
|
185
167
|
const page = ref(props.options.pageOptions?.currentPage || 1);
|
|
186
|
-
const pageLimit = ref(
|
|
187
|
-
props.options.pageOptions?.limit || config.core.limit_per_page
|
|
188
|
-
);
|
|
168
|
+
const pageLimit = ref(props.options.pageOptions?.limit || config.core.limit_per_page);
|
|
189
169
|
const uTableCompatibleColumns = computed(
|
|
190
170
|
() => props.options.columns.map((col) => ({
|
|
191
171
|
...col,
|
|
@@ -216,7 +196,7 @@ const resolveTo = (rowOriginal) => {
|
|
|
216
196
|
...resolved,
|
|
217
197
|
query: {
|
|
218
198
|
...route.query,
|
|
219
|
-
...resolved.query
|
|
199
|
+
...resolved.query
|
|
220
200
|
}
|
|
221
201
|
};
|
|
222
202
|
};
|
|
@@ -7,7 +7,21 @@ type __VLS_Props = {
|
|
|
7
7
|
target?: string | ((row: any) => string | undefined);
|
|
8
8
|
preserveQuery?: boolean;
|
|
9
9
|
};
|
|
10
|
-
declare var __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_44: `${string}-cell`, __VLS_45:
|
|
10
|
+
declare var __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_44: `${string}-cell`, __VLS_45: {
|
|
11
|
+
cell: import("@tanstack/table-core").Cell<any, unknown>;
|
|
12
|
+
column: import("@tanstack/table-core").Column<any, unknown>;
|
|
13
|
+
getValue: import("@tanstack/table-core").Getter<unknown>;
|
|
14
|
+
renderValue: import("@tanstack/table-core").Getter<unknown>;
|
|
15
|
+
row: import("@tanstack/table-core").Row<any>;
|
|
16
|
+
table: import("@tanstack/table-core").Table<any>;
|
|
17
|
+
}, __VLS_64: string, __VLS_65: {
|
|
18
|
+
cell: import("@tanstack/table-core").Cell<any, unknown>;
|
|
19
|
+
column: import("@tanstack/table-core").Column<any, unknown>;
|
|
20
|
+
getValue: import("@tanstack/table-core").Getter<unknown>;
|
|
21
|
+
renderValue: import("@tanstack/table-core").Getter<unknown>;
|
|
22
|
+
row: import("@tanstack/table-core").Row<any>;
|
|
23
|
+
table: import("@tanstack/table-core").Table<any>;
|
|
24
|
+
};
|
|
11
25
|
type __VLS_Slots = {} & {
|
|
12
26
|
[K in NonNullable<typeof __VLS_44>]?: (props: typeof __VLS_45) => any;
|
|
13
27
|
} & {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { type ComponentProps } from 'vue';
|
|
2
1
|
import type { TableColumn } from '@nuxt/ui';
|
|
3
|
-
import
|
|
2
|
+
import type { NuxtLinkProps } from '#app';
|
|
4
3
|
type __VLS_Props = {
|
|
5
4
|
value: any;
|
|
6
5
|
row: any;
|
|
7
6
|
column: TableColumn<any> & {
|
|
8
7
|
meta: {
|
|
9
8
|
max: number;
|
|
10
|
-
link?:
|
|
9
|
+
link?: NuxtLinkProps;
|
|
11
10
|
};
|
|
12
11
|
};
|
|
13
12
|
};
|
|
@@ -24,7 +24,7 @@ const getValue = computed(() => {
|
|
|
24
24
|
const value = props.value;
|
|
25
25
|
const max = props.column?.meta?.max;
|
|
26
26
|
if (max) {
|
|
27
|
-
return StringHelper.truncate(value, max);
|
|
27
|
+
return StringHelper.truncate(value, max) || "-";
|
|
28
28
|
}
|
|
29
29
|
if (typeof value === "string") {
|
|
30
30
|
return value || "-";
|