@finema/core 2.12.2 → 2.13.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/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/FlexDeck/Base.vue +1 -1
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/EmptyState.vue +35 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/EmptyState.vue.d.ts +12 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/FailedState.vue +54 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/FailedState.vue.d.ts +14 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/LoadingState.vue +54 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/LoadingState.vue.d.ts +8 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/PreviewModal.vue +35 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/PreviewModal.vue.d.ts +10 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/SuccessState.vue +88 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/SuccessState.vue.d.ts +17 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue +91 -76
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/index.vue.d.ts +10 -6
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/types.d.ts +7 -5
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/useUploadState.d.ts +25 -0
- package/dist/runtime/components/Form/InputUploadDropzoneAuto/useUploadState.js +187 -0
- package/dist/runtime/components/Image.vue +1 -1
- package/dist/runtime/components/Table/Base.vue +77 -77
- package/dist/runtime/components/Table/Base.vue.d.ts +5 -5
- package/dist/runtime/components/Table/Simple.vue +21 -21
- package/dist/runtime/components/Table/index.vue +4 -3
- package/dist/runtime/components/Table/index.vue.d.ts +1 -1
- package/dist/runtime/components/Table/types.d.ts +1 -2
- package/dist/runtime/composables/useUpload.js +2 -4
- package/dist/runtime/helpers/componentHelper.d.ts +3 -2
- package/dist/runtime/helpers/componentHelper.js +6 -2
- package/dist/runtime/theme/uploadFileDropzone.d.ts +32 -0
- package/dist/runtime/theme/uploadFileDropzone.js +41 -5
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="theme.placeholderWrapper()">
|
|
3
|
+
<Icon
|
|
4
|
+
:name="themeStatic.uploadIcon"
|
|
5
|
+
:class="theme.labelIcon()"
|
|
6
|
+
/>
|
|
7
|
+
<div :class="theme.labelWrapper()">
|
|
8
|
+
<p
|
|
9
|
+
class="text-primary cursor-pointer font-bold"
|
|
10
|
+
@click="$emit('openFile')"
|
|
11
|
+
>
|
|
12
|
+
{{ selectFileLabel }}
|
|
13
|
+
</p>
|
|
14
|
+
<p>{{ selectFileSubLabel }}</p>
|
|
15
|
+
</div>
|
|
16
|
+
<p
|
|
17
|
+
v-if="placeholder"
|
|
18
|
+
:class="theme.placeholder()"
|
|
19
|
+
>
|
|
20
|
+
{{ placeholder }}
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { useUiConfigStatic } from "#imports";
|
|
27
|
+
defineProps({
|
|
28
|
+
theme: { type: null, required: true },
|
|
29
|
+
selectFileLabel: { type: String, required: true },
|
|
30
|
+
selectFileSubLabel: { type: String, required: true },
|
|
31
|
+
placeholder: { type: String, required: false }
|
|
32
|
+
});
|
|
33
|
+
defineEmits(["openFile"]);
|
|
34
|
+
const themeStatic = useUiConfigStatic("uploadFileDropzone");
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
theme: any;
|
|
3
|
+
selectFileLabel: string;
|
|
4
|
+
selectFileSubLabel: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
+
openFile: () => any;
|
|
9
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
10
|
+
onOpenFile?: (() => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="theme.onFailedWrapper()">
|
|
3
|
+
<div :class="theme.onFailedFailedImgWrapper()">
|
|
4
|
+
<Icon
|
|
5
|
+
:name="getFileIcon(selectedFile)"
|
|
6
|
+
:class="theme.onFailedFailedIconClass()"
|
|
7
|
+
/>
|
|
8
|
+
</div>
|
|
9
|
+
<div :class="theme.onFailedTextWrapper()">
|
|
10
|
+
<div class="truncate">
|
|
11
|
+
<h1 class="truncate font-bold">
|
|
12
|
+
{{ selectedFile.name }}
|
|
13
|
+
</h1>
|
|
14
|
+
<p class="text-error truncate font-light">
|
|
15
|
+
{{ uploadFailedLabel }}
|
|
16
|
+
</p>
|
|
17
|
+
<Button
|
|
18
|
+
variant="link"
|
|
19
|
+
:icon="themeStatic.actionRetryIcon"
|
|
20
|
+
:class="theme.actionRetryBtnClass()"
|
|
21
|
+
color="primary"
|
|
22
|
+
@click="$emit('retry')"
|
|
23
|
+
>
|
|
24
|
+
{{ retryLabel }}
|
|
25
|
+
</Button>
|
|
26
|
+
</div>
|
|
27
|
+
<Icon
|
|
28
|
+
:name="themeStatic.actionDeleteIcon"
|
|
29
|
+
:class="theme.actionDeleteIconClass()"
|
|
30
|
+
title="ลบไฟล์"
|
|
31
|
+
@click="$emit('delete')"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup>
|
|
38
|
+
import { isImage } from "#core/helpers/componentHelper";
|
|
39
|
+
import { useUiConfigStatic } from "#imports";
|
|
40
|
+
const props = defineProps({
|
|
41
|
+
theme: { type: null, required: true },
|
|
42
|
+
selectedFile: { type: null, required: true },
|
|
43
|
+
uploadFailedLabel: { type: String, required: true },
|
|
44
|
+
retryLabel: { type: String, required: true }
|
|
45
|
+
});
|
|
46
|
+
defineEmits(["retry", "delete"]);
|
|
47
|
+
const themeStatic = useUiConfigStatic("uploadFileDropzone");
|
|
48
|
+
const getFileIcon = (file) => {
|
|
49
|
+
if (isImage(file)) {
|
|
50
|
+
return themeStatic.placeholderImgIcon;
|
|
51
|
+
}
|
|
52
|
+
return themeStatic.filePreviewIcon;
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
theme: any;
|
|
3
|
+
selectedFile: File;
|
|
4
|
+
uploadFailedLabel: string;
|
|
5
|
+
retryLabel: string;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
+
delete: () => any;
|
|
9
|
+
retry: () => any;
|
|
10
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
11
|
+
onDelete?: (() => any) | undefined;
|
|
12
|
+
onRetry?: (() => any) | undefined;
|
|
13
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="theme.onLoadingWrapper()">
|
|
3
|
+
<div :class="theme.onLoadingPlaceholderWrapper()">
|
|
4
|
+
<Icon
|
|
5
|
+
:name="getFileIcon(selectedFile)"
|
|
6
|
+
:class="theme.onLoadingPlaceholderIconClass()"
|
|
7
|
+
/>
|
|
8
|
+
</div>
|
|
9
|
+
<div :class="theme.onLoadingTextWrapper()">
|
|
10
|
+
<div class="truncate">
|
|
11
|
+
<h1 class="truncate font-bold">
|
|
12
|
+
{{ selectedFile.name }}
|
|
13
|
+
</h1>
|
|
14
|
+
<p class="truncate font-light text-gray-400">
|
|
15
|
+
{{ getFileSize(selectedFile) }} - {{ percent }}% {{ uploadingLabel }}
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
<div>
|
|
19
|
+
<Icon
|
|
20
|
+
:name="themeStatic.loadingIcon"
|
|
21
|
+
:class="theme.onLoadingLoadingIconClass()"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup>
|
|
29
|
+
import { isImage } from "#core/helpers/componentHelper";
|
|
30
|
+
import { useUiConfigStatic } from "#imports";
|
|
31
|
+
const props = defineProps({
|
|
32
|
+
theme: { type: null, required: true },
|
|
33
|
+
selectedFile: { type: null, required: true },
|
|
34
|
+
percent: { type: Number, required: true },
|
|
35
|
+
uploadingLabel: { type: String, required: true }
|
|
36
|
+
});
|
|
37
|
+
const themeStatic = useUiConfigStatic("uploadFileDropzone");
|
|
38
|
+
const getFileIcon = (file) => {
|
|
39
|
+
if (isImage(file)) {
|
|
40
|
+
return themeStatic.placeholderImgIcon;
|
|
41
|
+
}
|
|
42
|
+
return themeStatic.filePreviewIcon;
|
|
43
|
+
};
|
|
44
|
+
const getFileSize = (file) => {
|
|
45
|
+
const size = file.size;
|
|
46
|
+
const useMb = size > 1024 * 1024;
|
|
47
|
+
if (useMb) {
|
|
48
|
+
const sizeMb = (size / (1024 * 1024)).toFixed(2);
|
|
49
|
+
return `${sizeMb} MB`;
|
|
50
|
+
}
|
|
51
|
+
const sizeKb = (size / 1024).toFixed(2);
|
|
52
|
+
return `${sizeKb} KB`;
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
theme: any;
|
|
3
|
+
selectedFile: File;
|
|
4
|
+
percent: number;
|
|
5
|
+
uploadingLabel: string;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Modal
|
|
3
|
+
:close="{ onClick: () => emits('close', false) }"
|
|
4
|
+
:dismissible="false"
|
|
5
|
+
:title="value?.name"
|
|
6
|
+
:ui="{
|
|
7
|
+
content: 'max-w-3xl'
|
|
8
|
+
}"
|
|
9
|
+
>
|
|
10
|
+
<template #body>
|
|
11
|
+
<div class="flex justify-center">
|
|
12
|
+
<img
|
|
13
|
+
v-if="value && isImageFromPath(value.path)"
|
|
14
|
+
:src="value.url"
|
|
15
|
+
alt="img-preview"
|
|
16
|
+
class="max-h-96 max-w-full rounded-lg"
|
|
17
|
+
/>
|
|
18
|
+
<video
|
|
19
|
+
v-else-if="value && isVideoFromPath(value.path)"
|
|
20
|
+
:src="value.url"
|
|
21
|
+
controls
|
|
22
|
+
class="max-h-96 max-w-full"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
</Modal>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup>
|
|
30
|
+
import { isImageFromPath, isVideoFromPath } from "#core/helpers/componentHelper";
|
|
31
|
+
defineProps({
|
|
32
|
+
value: { type: Object, required: false }
|
|
33
|
+
});
|
|
34
|
+
const emits = defineEmits(["close"]);
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IFileValue } from '#core/components/Form/types';
|
|
2
|
+
interface Props {
|
|
3
|
+
value?: IFileValue;
|
|
4
|
+
}
|
|
5
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
+
close: (args_0: boolean) => any;
|
|
7
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
8
|
+
onClose?: ((args_0: boolean) => any) | undefined;
|
|
9
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
export default _default;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="theme.onPreviewWrapper()">
|
|
3
|
+
<div :class="theme.onPreviewPreviewImgWrapper()">
|
|
4
|
+
<div
|
|
5
|
+
v-if="isImageFromPath(value.path)"
|
|
6
|
+
class="size-full overflow-hidden"
|
|
7
|
+
>
|
|
8
|
+
<img
|
|
9
|
+
:src="value.url"
|
|
10
|
+
:class="theme.onPreviewPreviewImgClass()"
|
|
11
|
+
alt="img-preview"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
<div v-else>
|
|
15
|
+
<Icon
|
|
16
|
+
:name="themeStatic.filePreviewIcon"
|
|
17
|
+
:class="theme.onPreviewPreviewFileClass()"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div :class="theme.onPreviewTextWrapper()">
|
|
22
|
+
<div class="truncate">
|
|
23
|
+
<h1 class="truncate font-bold">
|
|
24
|
+
{{ value.name }}
|
|
25
|
+
</h1>
|
|
26
|
+
<p class="truncate text-sm font-light text-gray-400">
|
|
27
|
+
{{ getFileSizeFromValue(value) }}
|
|
28
|
+
</p>
|
|
29
|
+
</div>
|
|
30
|
+
<div :class="theme.actionWrapper()">
|
|
31
|
+
<a
|
|
32
|
+
v-if="isPDFFromPath(value.path)"
|
|
33
|
+
:href="value.url"
|
|
34
|
+
target="_blank"
|
|
35
|
+
class="flex"
|
|
36
|
+
>
|
|
37
|
+
<Icon
|
|
38
|
+
:name="themeStatic.actionPreviewIcon"
|
|
39
|
+
:class="theme.actionIconClass()"
|
|
40
|
+
title="ดูตัวอย่าง"
|
|
41
|
+
/>
|
|
42
|
+
</a>
|
|
43
|
+
<Icon
|
|
44
|
+
v-if="isImageFromPath(value.path) || isVideoFromPath(value.path)"
|
|
45
|
+
:name="themeStatic.actionPreviewIcon"
|
|
46
|
+
:class="theme.actionIconClass()"
|
|
47
|
+
title="ดูตัวอย่าง"
|
|
48
|
+
@click="$emit('preview')"
|
|
49
|
+
/>
|
|
50
|
+
<Icon
|
|
51
|
+
:name="themeStatic.actionDownloadIcon"
|
|
52
|
+
:class="theme.actionIconClass()"
|
|
53
|
+
title="ดาวน์โหลดไฟล์"
|
|
54
|
+
@click="$emit('download')"
|
|
55
|
+
/>
|
|
56
|
+
<Icon
|
|
57
|
+
v-if="!disabled && !readonly"
|
|
58
|
+
:name="themeStatic.actionDeleteIcon"
|
|
59
|
+
:class="theme.actionIconClass()"
|
|
60
|
+
title="ลบไฟล์"
|
|
61
|
+
@click="$emit('delete')"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<script setup>
|
|
69
|
+
import {
|
|
70
|
+
isImageFromPath,
|
|
71
|
+
isPDFFromPath,
|
|
72
|
+
isVideoFromPath,
|
|
73
|
+
useFileSize
|
|
74
|
+
} from "#core/helpers/componentHelper";
|
|
75
|
+
import { useUiConfigStatic } from "#imports";
|
|
76
|
+
defineProps({
|
|
77
|
+
theme: { type: null, required: true },
|
|
78
|
+
value: { type: Object, required: true },
|
|
79
|
+
disabled: { type: Boolean, required: false },
|
|
80
|
+
readonly: { type: Boolean, required: false }
|
|
81
|
+
});
|
|
82
|
+
defineEmits(["preview", "download", "delete"]);
|
|
83
|
+
const themeStatic = useUiConfigStatic("uploadFileDropzone");
|
|
84
|
+
const getFileSizeFromValue = (fileValue) => {
|
|
85
|
+
const allocate = useFileSize(fileValue.size || 0);
|
|
86
|
+
return allocate.isSelectedFileUseMb.value ? `${allocate.selectedFileSizeMb.value} MB` : `${allocate.selectedFileSizeKb.value} KB`;
|
|
87
|
+
};
|
|
88
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IFileValue } from '#core/components/Form/types';
|
|
2
|
+
interface Props {
|
|
3
|
+
theme: any;
|
|
4
|
+
value: IFileValue;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
readonly?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
delete: () => any;
|
|
10
|
+
preview: () => any;
|
|
11
|
+
download: () => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
13
|
+
onDelete?: (() => any) | undefined;
|
|
14
|
+
onPreview?: (() => any) | undefined;
|
|
15
|
+
onDownload?: (() => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
export default _default;
|
|
@@ -1,60 +1,83 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
-
<div
|
|
4
|
-
ref="
|
|
5
|
-
:class="theme.base()"
|
|
6
|
-
>
|
|
7
|
-
<div :class="theme.wrapper()">
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
2
|
+
<FieldWrapper v-bind="wrapperProps">
|
|
3
|
+
<div
|
|
4
|
+
ref="dropzoneRef"
|
|
5
|
+
:class="theme.base()"
|
|
6
|
+
>
|
|
7
|
+
<div :class="theme.wrapper()">
|
|
8
|
+
<!-- Empty State -->
|
|
9
|
+
<EmptyState
|
|
10
|
+
v-if="uploadState.isEmpty.value"
|
|
11
|
+
:theme="theme"
|
|
12
|
+
:select-file-label="selectFileLabel"
|
|
13
|
+
:select-file-sub-label="selectFileSubLabel"
|
|
14
|
+
:placeholder="placeholder"
|
|
15
|
+
@open-file="uploadState.handleOpenFile"
|
|
16
|
+
/>
|
|
17
|
+
|
|
18
|
+
<!-- Loading State -->
|
|
19
|
+
<LoadingState
|
|
20
|
+
v-if="uploadState.isUploading.value"
|
|
21
|
+
:theme="theme"
|
|
22
|
+
:selected-file="uploadState.selectedFile.value"
|
|
23
|
+
:percent="uploadState.percent.value"
|
|
24
|
+
:uploading-label="uploadingLabel"
|
|
25
|
+
/>
|
|
26
|
+
|
|
27
|
+
<!-- Success State -->
|
|
28
|
+
<SuccessState
|
|
29
|
+
v-if="uploadState.isSuccess.value"
|
|
30
|
+
:theme="theme"
|
|
31
|
+
:value="value"
|
|
32
|
+
:disabled="wrapperProps.disabled"
|
|
33
|
+
:readonly="wrapperProps.readonly"
|
|
34
|
+
@preview="uploadState.handlePreview"
|
|
35
|
+
@download="handleDownloadFile"
|
|
36
|
+
@delete="uploadState.handleDeleteFile"
|
|
37
|
+
/>
|
|
38
|
+
|
|
39
|
+
<!-- Failed State -->
|
|
40
|
+
<FailedState
|
|
41
|
+
v-if="uploadState.isError.value"
|
|
42
|
+
:theme="theme"
|
|
43
|
+
:selected-file="uploadState.selectedFile.value"
|
|
44
|
+
:upload-failed-label="uploadFailedLabel"
|
|
45
|
+
:retry-label="retryLabel"
|
|
46
|
+
@retry="uploadState.handleRetryUpload"
|
|
47
|
+
@delete="uploadState.handleDeleteFile"
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</FieldWrapper>
|
|
35
52
|
</template>
|
|
36
53
|
|
|
37
54
|
<script setup>
|
|
38
|
-
import
|
|
39
|
-
import
|
|
55
|
+
import EmptyState from "./EmptyState.vue";
|
|
56
|
+
import LoadingState from "./LoadingState.vue";
|
|
57
|
+
import SuccessState from "./SuccessState.vue";
|
|
58
|
+
import FailedState from "./FailedState.vue";
|
|
59
|
+
import { useUploadState } from "./useUploadState";
|
|
60
|
+
import { computed, useTemplateRef } from "#imports";
|
|
40
61
|
import FieldWrapper from "#core/components/Form/FieldWrapper.vue";
|
|
41
62
|
import { useFieldHOC } from "#core/composables/useForm";
|
|
42
63
|
import { uploadFileDropzoneTheme } from "#core/theme/uploadFileDropzone";
|
|
43
|
-
import { useUiConfig
|
|
44
|
-
import {
|
|
64
|
+
import { useUiConfig } from "#core/composables/useConfig";
|
|
65
|
+
import { downloadFileFromURL } from "#core/helpers/componentHelper";
|
|
45
66
|
const props = defineProps({
|
|
46
67
|
requestOptions: { type: Object, required: true },
|
|
47
68
|
uploadPathURL: { type: String, required: false },
|
|
48
|
-
selectFileLabel: { type: String, required: false, default: "\u0E04\u0E25\u0E34\u0E01\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E44\u0E1F\u0E25\u0E4C" },
|
|
49
|
-
selectFileSubLabel: { type: String, required: false, default: "\u0E2B\u0E23\u0E37\u0E2D \u0E25\u0E32\u0E01\u0E41\u0E25\u0E30\u0E27\u0E32\u0E07\u0E17\u0E35\u0E48\u0E19\u0E35\u0E48" },
|
|
50
|
-
uploadingLabel: { type: String, required: false, default: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14..." },
|
|
51
|
-
uploadFailedLabel: { type: String, required: false, default: "\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27, \u0E01\u0E23\u0E38\u0E13\u0E32\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07" },
|
|
52
|
-
retryLabel: { type: String, required: false },
|
|
53
|
-
accept: { type: [Array, String], required: false },
|
|
54
69
|
bodyKey: { type: String, required: false, default: "file" },
|
|
55
70
|
responseURL: { type: String, required: false, default: "url" },
|
|
56
71
|
responsePath: { type: String, required: false, default: "path" },
|
|
72
|
+
responseName: { type: String, required: false, default: "name" },
|
|
73
|
+
responseSize: { type: String, required: false, default: "size" },
|
|
74
|
+
accept: { type: [Array, String], required: false },
|
|
57
75
|
maxSize: { type: Number, required: false },
|
|
76
|
+
selectFileLabel: { type: String, required: false, default: "\u0E04\u0E25\u0E34\u0E01\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E44\u0E1F\u0E25\u0E4C" },
|
|
77
|
+
selectFileSubLabel: { type: String, required: false, default: "\u0E2B\u0E23\u0E37\u0E2D \u0E25\u0E32\u0E01\u0E41\u0E25\u0E30\u0E27\u0E32\u0E07\u0E17\u0E35\u0E48\u0E19\u0E35\u0E48" },
|
|
78
|
+
uploadingLabel: { type: String, required: false, default: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14..." },
|
|
79
|
+
uploadFailedLabel: { type: String, required: false, default: "\u0E2D\u0E31\u0E1E\u0E42\u0E2B\u0E25\u0E14\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27, \u0E01\u0E23\u0E38\u0E13\u0E32\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07" },
|
|
80
|
+
retryLabel: { type: String, required: false, default: "\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07" },
|
|
58
81
|
form: { type: Object, required: false },
|
|
59
82
|
name: { type: String, required: true },
|
|
60
83
|
errorMessage: { type: String, required: false },
|
|
@@ -77,38 +100,30 @@ const {
|
|
|
77
100
|
setErrors,
|
|
78
101
|
value
|
|
79
102
|
} = useFieldHOC(props);
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
const acceptedFileTypes = computed(
|
|
104
|
+
() => typeof props.accept === "string" ? props.accept : props.accept?.join(",")
|
|
105
|
+
);
|
|
106
|
+
const dropzoneRef = useTemplateRef("dropzoneRef");
|
|
107
|
+
const uploadState = useUploadState(
|
|
108
|
+
props,
|
|
109
|
+
emits,
|
|
110
|
+
onChange,
|
|
111
|
+
setErrors,
|
|
112
|
+
value,
|
|
113
|
+
acceptedFileTypes,
|
|
114
|
+
wrapperProps,
|
|
115
|
+
dropzoneRef
|
|
116
|
+
);
|
|
117
|
+
const theme = computed(
|
|
118
|
+
() => useUiConfig(uploadFileDropzoneTheme, "uploadFileDropzone")({
|
|
119
|
+
dragover: uploadState.dropzone.isOverDropZone.value && uploadState.isEmpty.value,
|
|
120
|
+
disabled: wrapperProps.value.disabled,
|
|
121
|
+
failed: uploadState.upload.status.value.isError
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
const handleDownloadFile = () => {
|
|
125
|
+
if (value.value?.url && value.value?.name) {
|
|
126
|
+
downloadFileFromURL(value.value.url, value.value.name);
|
|
127
|
+
}
|
|
104
128
|
};
|
|
105
|
-
const dropzone = useDropZone(dropZoneRef, {
|
|
106
|
-
onDrop,
|
|
107
|
-
// specify the types of data to be received.
|
|
108
|
-
dataTypes: typeof props.accept === "string" ? [props.accept] : props.accept,
|
|
109
|
-
// control multi-file drop
|
|
110
|
-
multiple: false,
|
|
111
|
-
// whether to prevent default behavior for unhandled events
|
|
112
|
-
preventDefaultForUnhandled: false
|
|
113
|
-
});
|
|
114
129
|
</script>
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import type { IUploadDropzoneAutoProps } from './types.js';
|
|
2
|
+
import type { IFileValue } from '#core/components/Form/types';
|
|
2
3
|
declare const _default: import("vue").DefineComponent<IUploadDropzoneAutoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
3
|
-
success: (
|
|
4
|
-
delete: (
|
|
5
|
-
change: (
|
|
4
|
+
success: (res: IFileValue) => any;
|
|
5
|
+
delete: () => any;
|
|
6
|
+
change: (value: File | undefined) => any;
|
|
6
7
|
}, string, import("vue").PublicProps, Readonly<IUploadDropzoneAutoProps> & Readonly<{
|
|
7
|
-
onSuccess?: ((
|
|
8
|
-
onDelete?: ((
|
|
9
|
-
onChange?: ((
|
|
8
|
+
onSuccess?: ((res: IFileValue) => any) | undefined;
|
|
9
|
+
onDelete?: (() => any) | undefined;
|
|
10
|
+
onChange?: ((value: File | undefined) => any) | undefined;
|
|
10
11
|
}>, {
|
|
11
12
|
selectFileLabel: string;
|
|
12
13
|
selectFileSubLabel: string;
|
|
13
14
|
uploadingLabel: string;
|
|
14
15
|
uploadFailedLabel: string;
|
|
16
|
+
retryLabel: string;
|
|
15
17
|
bodyKey: string;
|
|
16
18
|
responseURL: string;
|
|
17
19
|
responsePath: string;
|
|
20
|
+
responseName: string;
|
|
21
|
+
responseSize: string;
|
|
18
22
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
23
|
export default _default;
|
|
@@ -5,16 +5,18 @@ export interface IUploadDropzoneAutoProps extends IFieldProps {
|
|
|
5
5
|
baseURL: string;
|
|
6
6
|
};
|
|
7
7
|
uploadPathURL?: string;
|
|
8
|
+
bodyKey?: string;
|
|
9
|
+
responseURL?: string;
|
|
10
|
+
responsePath?: string;
|
|
11
|
+
responseName?: string;
|
|
12
|
+
responseSize?: string;
|
|
13
|
+
accept?: string[] | string;
|
|
14
|
+
maxSize?: number;
|
|
8
15
|
selectFileLabel?: string;
|
|
9
16
|
selectFileSubLabel?: string;
|
|
10
17
|
uploadingLabel?: string;
|
|
11
18
|
uploadFailedLabel?: string;
|
|
12
19
|
retryLabel?: string;
|
|
13
|
-
accept?: string[] | string;
|
|
14
|
-
bodyKey?: string;
|
|
15
|
-
responseURL?: string;
|
|
16
|
-
responsePath?: string;
|
|
17
|
-
maxSize?: number;
|
|
18
20
|
}
|
|
19
21
|
export type IUploadDropzoneAutoField = IFormFieldBase<INPUT_TYPES.UPLOAD_DROPZONE_AUTO, IUploadDropzoneAutoProps, {
|
|
20
22
|
change: (value: File | undefined) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TemplateRef } from 'vue';
|
|
2
|
+
import type { IUploadDropzoneAutoProps } from './types.js';
|
|
3
|
+
import type { IFileValue } from '#core/components/Form/types';
|
|
4
|
+
export declare enum UploadState {
|
|
5
|
+
EMPTY = "empty",
|
|
6
|
+
UPLOADING = "uploading",
|
|
7
|
+
SUCCESS = "success",
|
|
8
|
+
ERROR = "error"
|
|
9
|
+
}
|
|
10
|
+
export declare const useUploadState: (props: IUploadDropzoneAutoProps, emits: any, onChange: (value: IFileValue | undefined) => void, setErrors: (error: string) => void, value: any, acceptedFileTypes: any, wrapperProps: any, dropzoneRef: TemplateRef<HTMLDivElement | undefined>) => {
|
|
11
|
+
currentState: import("vue").ComputedRef<UploadState>;
|
|
12
|
+
isEmpty: import("vue").ComputedRef<boolean>;
|
|
13
|
+
isUploading: import("vue").ComputedRef<boolean>;
|
|
14
|
+
isSuccess: import("vue").ComputedRef<boolean>;
|
|
15
|
+
isError: import("vue").ComputedRef<boolean>;
|
|
16
|
+
selectedFile: import("vue").Ref<File | undefined, File | undefined>;
|
|
17
|
+
upload: import("../../../helpers/apiObjectHelper.js").IUseObjectLoader<any, any, Record<string, any>>;
|
|
18
|
+
dropzone: import("@vueuse/core").UseDropZoneReturn;
|
|
19
|
+
percent: import("vue").Ref<number, number>;
|
|
20
|
+
handleInputChange: (event: Event) => void;
|
|
21
|
+
handleOpenFile: () => void;
|
|
22
|
+
handleDeleteFile: () => void;
|
|
23
|
+
handleRetryUpload: () => void;
|
|
24
|
+
handlePreview: () => void;
|
|
25
|
+
};
|