inertia-bootstrap-forms 1.0.80 → 1.0.82
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/package.json
CHANGED
package/src/UppyInput.vue
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script setup>
|
|
14
|
-
import {computed, inject, onBeforeUnmount, onMounted, shallowRef, ref} from 'vue'
|
|
14
|
+
import {computed, inject, onBeforeUnmount, onMounted, shallowRef, ref, watch} from 'vue'
|
|
15
15
|
import {
|
|
16
16
|
Dropzone,
|
|
17
17
|
FilesList,
|
|
@@ -43,6 +43,9 @@ const emits = defineEmits([
|
|
|
43
43
|
const restrictionCaption = ref(null);
|
|
44
44
|
const inputEl = ref(null);
|
|
45
45
|
const uppy = shallowRef(null);
|
|
46
|
+
const isResetting = ref(false);
|
|
47
|
+
const isUnmounting = ref(false);
|
|
48
|
+
const uploadingFiles = ref(0);
|
|
46
49
|
|
|
47
50
|
// Inject form and group contexts
|
|
48
51
|
const form = inject("form", {value: {}, errors: {}, getID: n => n});
|
|
@@ -64,9 +67,8 @@ const modelValue = computed({
|
|
|
64
67
|
}
|
|
65
68
|
});
|
|
66
69
|
|
|
67
|
-
// ایجاد اینستنس اختصاصی برای هر کامپوننت
|
|
68
70
|
uppy.value = new Uppy({
|
|
69
|
-
id: props.name,
|
|
71
|
+
id: props.name,
|
|
70
72
|
autoProceed: true,
|
|
71
73
|
...props.config,
|
|
72
74
|
restrictions: {
|
|
@@ -75,11 +77,18 @@ uppy.value = new Uppy({
|
|
|
75
77
|
},
|
|
76
78
|
});
|
|
77
79
|
|
|
80
|
+
uppy.value.on('upload', () => {
|
|
81
|
+
uploadingFiles.value = uppy.value.getFiles().filter(f => !f.progress.uploadComplete).length;
|
|
82
|
+
emits('upload');
|
|
83
|
+
});
|
|
84
|
+
|
|
78
85
|
uppy.value.on('before-upload', (files) => {
|
|
79
86
|
emits('beforeUpload', files);
|
|
80
87
|
});
|
|
81
88
|
|
|
82
89
|
uppy.value.on('upload-success', (file, response) => {
|
|
90
|
+
uploadingFiles.value = Math.max(0, uploadingFiles.value - 1);
|
|
91
|
+
|
|
83
92
|
const result = response.body ?? response;
|
|
84
93
|
if (props.multiple) {
|
|
85
94
|
const currentValues = Array.isArray(modelValue.value) ? modelValue.value : [];
|
|
@@ -91,21 +100,19 @@ uppy.value.on('upload-success', (file, response) => {
|
|
|
91
100
|
});
|
|
92
101
|
|
|
93
102
|
uppy.value.on('file-added', (file) => emits('file-added', file));
|
|
103
|
+
|
|
94
104
|
uppy.value.on('file-removed', (file) => {
|
|
95
105
|
const serverResponse = file.response?.body ?? file.response;
|
|
96
106
|
|
|
97
107
|
if (props.multiple && Array.isArray(modelValue.value)) {
|
|
98
108
|
modelValue.value = modelValue.value.filter(item => {
|
|
99
|
-
// مقایسه بر اساس شناسه یا کل آبجکت (بسته به ساختار ارسالی سرور شما)
|
|
100
|
-
// اگر سرور ID برمیگرداند: return item.id !== serverResponse.id;
|
|
101
|
-
// اگر مستقیماً خود آبجکت است:
|
|
102
109
|
return JSON.stringify(item) !== JSON.stringify(serverResponse);
|
|
103
110
|
});
|
|
104
111
|
} else {
|
|
105
112
|
modelValue.value = null;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
|
-
if (serverResponse) {
|
|
115
|
+
if (serverResponse && !isResetting.value && !isUnmounting.value) {
|
|
109
116
|
fetch(props.url, {
|
|
110
117
|
method: 'DELETE',
|
|
111
118
|
headers: {
|
|
@@ -120,23 +127,37 @@ uppy.value.on('file-removed', (file) => {
|
|
|
120
127
|
});
|
|
121
128
|
|
|
122
129
|
uppy.value.on('progress', (progress) => {
|
|
123
|
-
|
|
130
|
+
if (progress <= 0) {
|
|
131
|
+
form.value['uploading'] = null;
|
|
132
|
+
} else if (progress >= 100) {
|
|
133
|
+
// هنوز منتظر جواب سرور - uploading رو null نکن
|
|
134
|
+
form.value['uploading'] = uploadingFiles.value > 0 ? 99 : null;
|
|
135
|
+
} else {
|
|
136
|
+
form.value['uploading'] = progress;
|
|
137
|
+
}
|
|
138
|
+
|
|
124
139
|
emits('progress', progress)
|
|
125
140
|
});
|
|
126
141
|
uppy.value.on('upload-progress', (file, progress) => emits('upload-progress', file, progress));
|
|
127
142
|
uppy.value.on('upload-pause', (file, progress) => emits('upload-pause', file, progress));
|
|
128
143
|
uppy.value.on('cancel-all', () => emits('cancel-all'));
|
|
129
|
-
uppy.value.on('retry-all', () => emits('retry-all'
|
|
144
|
+
uppy.value.on('retry-all', () => emits('retry-all'));
|
|
130
145
|
uppy.value.on('upload-stalled', (error, files) => emits('upload-stalled', error, files));
|
|
131
146
|
uppy.value.on('upload-retry', (file) => emits('upload-retry', file));
|
|
132
147
|
|
|
133
|
-
uppy.value.on('complete', (result) =>
|
|
148
|
+
uppy.value.on('complete', (result) => {
|
|
149
|
+
uploadingFiles.value = 0;
|
|
150
|
+
form.value['uploading'] = null;
|
|
151
|
+
emits('complete', result);
|
|
152
|
+
});
|
|
134
153
|
|
|
135
154
|
uppy.value.on('error', (error) => {
|
|
136
155
|
emits('error', error)
|
|
137
156
|
});
|
|
138
157
|
|
|
139
158
|
uppy.value.on('upload-error', (file, error, response) => {
|
|
159
|
+
uploadingFiles.value = Math.max(0, uploadingFiles.value - 1);
|
|
160
|
+
|
|
140
161
|
const errorMessage = JSON.parse(response.response)?.message ?? error;
|
|
141
162
|
handleError(errorMessage);
|
|
142
163
|
emits('upload-error', file, error, response, errorMessage)
|
|
@@ -147,11 +168,16 @@ uppy.value.on('restriction-failed', (file, error) => {
|
|
|
147
168
|
emits('restriction-failed', file, error);
|
|
148
169
|
});
|
|
149
170
|
|
|
171
|
+
watch(() => form.value?.wasSuccessful, (newVal, oldVal) => {
|
|
172
|
+
if (newVal === true && oldVal === false) {
|
|
173
|
+
resetUppy();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
150
177
|
onMounted(() => {
|
|
151
|
-
let XHR;
|
|
152
178
|
if (props.useXHR) {
|
|
153
179
|
import('@uppy/xhr-upload').then(module => {
|
|
154
|
-
XHR = module.default;
|
|
180
|
+
const XHR = module.default;
|
|
155
181
|
uppy.value.use(XHR, {
|
|
156
182
|
method: 'POST',
|
|
157
183
|
endpoint: props.url,
|
|
@@ -163,17 +189,27 @@ onMounted(() => {
|
|
|
163
189
|
});
|
|
164
190
|
}
|
|
165
191
|
|
|
166
|
-
if(uppy.value?.opts?.restrictions){
|
|
192
|
+
if (uppy.value?.opts?.restrictions) {
|
|
167
193
|
restrictionCaption.value = buildRestrictionsCaption(uppy.value.opts.restrictions)
|
|
168
194
|
}
|
|
169
195
|
});
|
|
170
196
|
|
|
171
197
|
onBeforeUnmount(() => {
|
|
198
|
+
isUnmounting.value = true;
|
|
172
199
|
if (uppy.value) {
|
|
173
200
|
uppy.value.destroy();
|
|
174
201
|
}
|
|
175
202
|
});
|
|
176
203
|
|
|
204
|
+
function resetUppy() {
|
|
205
|
+
if (uppy.value) {
|
|
206
|
+
isResetting.value = true;
|
|
207
|
+
uppy.value.cancelAll();
|
|
208
|
+
isResetting.value = false;
|
|
209
|
+
modelValue.value = props.multiple ? [] : null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
177
213
|
function handleError(error) {
|
|
178
214
|
if (props.errorHandler) {
|
|
179
215
|
props.errorHandler(error);
|
|
@@ -193,20 +229,13 @@ function showError(message) {
|
|
|
193
229
|
}
|
|
194
230
|
}
|
|
195
231
|
|
|
196
|
-
function formatBytesToKB(size) {
|
|
197
|
-
if (!size) return null;
|
|
198
|
-
return Math.round(size / 1024);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
232
|
const niceBytesUnits = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
202
|
-
function niceBytes(x){
|
|
233
|
+
function niceBytes(x) {
|
|
203
234
|
let l = 0, n = parseInt(x, 10) || 0;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
n = n/1024;
|
|
235
|
+
while (n >= 1024 && ++l) {
|
|
236
|
+
n = n / 1024;
|
|
207
237
|
}
|
|
208
|
-
|
|
209
|
-
return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + niceBytesUnits[l]);
|
|
238
|
+
return (n.toFixed(n < 10 && l > 0 ? 1 : 0) + niceBytesUnits[l]);
|
|
210
239
|
}
|
|
211
240
|
|
|
212
241
|
function buildRestrictionsCaption(restrictions) {
|
|
@@ -223,7 +252,6 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
223
252
|
|
|
224
253
|
const parts = [];
|
|
225
254
|
|
|
226
|
-
// پسوندها
|
|
227
255
|
if (allowedFileTypes && allowedFileTypes.length) {
|
|
228
256
|
const types = allowedFileTypes
|
|
229
257
|
.map(type => type.replace('.', ''))
|
|
@@ -231,8 +259,7 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
231
259
|
parts.push(`فقط فایلهای ${types}`);
|
|
232
260
|
}
|
|
233
261
|
|
|
234
|
-
|
|
235
|
-
if (maxNumberOfFiles) {
|
|
262
|
+
if (maxNumberOfFiles && maxNumberOfFiles > 1) {
|
|
236
263
|
parts.push(`امکان انتخاب حداکثر ${maxNumberOfFiles} فایل`);
|
|
237
264
|
}
|
|
238
265
|
|
|
@@ -240,7 +267,6 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
240
267
|
parts.push(`حداقل ${minNumberOfFiles} فایل نیاز است`);
|
|
241
268
|
}
|
|
242
269
|
|
|
243
|
-
// حجم هر فایل
|
|
244
270
|
if (maxFileSize) {
|
|
245
271
|
parts.push(`با حداکثر حجم ${niceBytes(maxFileSize)} برای هر فایل`);
|
|
246
272
|
}
|
|
@@ -249,7 +275,6 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
249
275
|
parts.push(`با حداقل حجم ${niceBytes(minFileSize)} برای هر فایل`);
|
|
250
276
|
}
|
|
251
277
|
|
|
252
|
-
// مجموع حجم
|
|
253
278
|
if (maxTotalFileSize) {
|
|
254
279
|
parts.push(`و مجموع حجم کل حداکثر ${niceBytes(maxTotalFileSize)}`);
|
|
255
280
|
}
|
|
@@ -258,7 +283,6 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
258
283
|
|
|
259
284
|
return parts.join('، ') + ' مجاز است.';
|
|
260
285
|
}
|
|
261
|
-
|
|
262
286
|
</script>
|
|
263
287
|
|
|
264
288
|
<style>
|
|
@@ -283,9 +307,8 @@ function buildRestrictionsCaption(restrictions) {
|
|
|
283
307
|
margin-bottom: 5px;
|
|
284
308
|
}
|
|
285
309
|
|
|
286
|
-
.uppy-input-area .uppy-input-area--caption{
|
|
310
|
+
.uppy-input-area .uppy-input-area--caption {
|
|
287
311
|
text-align: center;
|
|
288
312
|
margin: 5px 0;
|
|
289
313
|
}
|
|
290
|
-
|
|
291
314
|
</style>
|