adminforth 2.4.0-next.300 → 2.4.0-next.302
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.
|
@@ -222,6 +222,11 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
222
222
|
data: { provider },
|
|
223
223
|
condition: Boolean(prismaDbUrl), // only create if prismaDbUrl is truthy
|
|
224
224
|
},
|
|
225
|
+
{
|
|
226
|
+
src: 'prisma.config.ts.hbs',
|
|
227
|
+
dest: 'prisma.config.ts',
|
|
228
|
+
data: {},
|
|
229
|
+
},
|
|
225
230
|
{
|
|
226
231
|
src: 'package.json.hbs',
|
|
227
232
|
dest: 'package.json',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<!-- tag form used to reset the input (method .reset() in
|
|
2
|
+
<!-- tag form used to reset the input (method .reset() in clear() function) -->
|
|
3
3
|
<form class="flex items-center justify-center w-full"
|
|
4
4
|
@dragover.prevent="dragging = true"
|
|
5
5
|
@dragleave.prevent="dragging = false"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
:id="id"
|
|
21
21
|
type="file"
|
|
22
22
|
class="hidden"
|
|
23
|
-
:accept="
|
|
23
|
+
:accept="normalizedExtensions.join(',')"
|
|
24
24
|
@change="$event.target && doEmit(($event.target as HTMLInputElement).files!)"
|
|
25
25
|
:multiple="props.multiple || false"
|
|
26
26
|
/>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
</p>
|
|
81
81
|
|
|
82
82
|
<p class="text-xs text-lightDropzoneText dark:text-darkDropzoneText">
|
|
83
|
-
{{
|
|
83
|
+
{{ normalizedExtensions.join(', ').toUpperCase().replace(/\./g, '') }}
|
|
84
84
|
<template v-if="props.maxSizeBytes">
|
|
85
85
|
(Max size: {{ humanifySize(props.maxSizeBytes) }})
|
|
86
86
|
</template>
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
|
|
93
93
|
<script setup lang="ts">
|
|
94
94
|
import { humanifySize } from '@/utils';
|
|
95
|
-
import { ref, type Ref } from 'vue';
|
|
95
|
+
import { ref, type Ref, computed } from 'vue';
|
|
96
96
|
import { IconFileSolid } from '@iconify-prerendered/vue-flowbite';
|
|
97
97
|
import { watch } from 'vue';
|
|
98
98
|
import adminforth from '@/adminforth';
|
|
@@ -108,6 +108,13 @@ const emit = defineEmits(['update:modelValue']);
|
|
|
108
108
|
|
|
109
109
|
const id = `afcl-dropzone-${Math.random().toString(36).substring(7)}`;
|
|
110
110
|
|
|
111
|
+
const normalizedExtensions = computed(() => {
|
|
112
|
+
return props.extensions.map(ext => {
|
|
113
|
+
const trimmed = ext.trim().toLowerCase();
|
|
114
|
+
return trimmed.startsWith('.') ? trimmed : `.${trimmed}`;
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
111
118
|
const selectedFiles: Ref<{
|
|
112
119
|
name: string,
|
|
113
120
|
size: number,
|
|
@@ -131,7 +138,7 @@ function doEmit(filesIn: FileList) {
|
|
|
131
138
|
|
|
132
139
|
const multiple = props.multiple || false;
|
|
133
140
|
const files = Array.from(filesIn);
|
|
134
|
-
const allowedExtensions =
|
|
141
|
+
const allowedExtensions = normalizedExtensions.value;
|
|
135
142
|
const maxSizeBytes = props.maxSizeBytes;
|
|
136
143
|
|
|
137
144
|
if (!files.length) return;
|
|
@@ -142,6 +149,18 @@ function doEmit(filesIn: FileList) {
|
|
|
142
149
|
const extension = file.name.split('.').pop()?.toLowerCase() || '';
|
|
143
150
|
const size = file.size;
|
|
144
151
|
|
|
152
|
+
const isDuplicate = storedFiles.value.some(
|
|
153
|
+
existingFile => existingFile.name === file.name && existingFile.size === file.size
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (isDuplicate) {
|
|
157
|
+
adminforth.alert({
|
|
158
|
+
message: `The file "${file.name}" is already selected.`,
|
|
159
|
+
variant: 'warning',
|
|
160
|
+
});
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
145
164
|
if (!allowedExtensions.includes(`.${extension}`)) {
|
|
146
165
|
adminforth.alert({
|
|
147
166
|
message: `Sorry, the file type .${extension} is not allowed. Please upload a file with one of the following extensions: ${allowedExtensions.join(', ')}`,
|