fix(uploader): register FilePond component at module level and restore proper dropzone styling
deploy-chabokan / deploy (push) Canceled after 0s

This commit is contained in:
2026-08-19 05:14:03 +03:30
parent ba54647837
commit cf7e1ee45c
+52 -75
View File
@@ -5,7 +5,7 @@
name="filepond-image"
:max-files="maxFiles"
:allow-multiple="allowMultiple"
:accepted-file-types="acceptedFileTypes"
store-as-file="true"
:server="{
process: {
url: resolvedUploadUrl,
@@ -20,37 +20,38 @@
withCredentials: true,
headers: authHeaders,
onload: (response) => handleRevertResponse(response)
},
load: (source, load, error, progress, abort, headers) => {
fetch(source)
.then((res) => res.blob())
.then(load)
.catch((err) => {
console.warn('FilePond failed to load existing image:', source, err);
error(err.message);
});
}
}"
:files="initialFiles"
@removefile="handleRemoveFile"
label-idle="برای آپلود کلیک کنید یا فایل را بکشید و رها کنید"
:label-idle="'برای آپلود کلیک کنید یا فایل را بکشید و رها کنید <span class=\'filepond--label-action\'>انتخاب فایل</span>'"
label-tap-to-undo="برای حذف کلیک کنید"
label-file-processing="در حال آپلود"
label-file-processing="در حال آپلود..."
label-file-processing-complete="آپلود فایل تکمیل شد"
@removefile="handleRemoveFile"
/>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import Cookies from 'js-cookie';
<script>
import vueFilePond from 'vue-filepond';
import 'filepond/dist/filepond.min.css';
import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
// Define props
// Create FilePond component at module level
const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview);
export default {
components: {
FilePond
}
};
</script>
<script setup>
import { ref, computed } from 'vue';
import Cookies from 'js-cookie';
const props = defineProps({
bucketName: {
type: String,
@@ -95,16 +96,8 @@ const props = defineProps({
});
const emit = defineEmits(['update:modelValue', 'upload', 'uploaded', 'delete']);
// Define FilePond component
const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview);
const pond = ref(null);
const acceptedFileTypes = computed(() => {
if (!props.acceptedFiles) return undefined;
return props.acceptedFiles.split(',').map((s) => s.trim());
});
const API_URL = (import.meta.env.VITE_API_URL || '').replace(/\/$/, '');
const authHeaders = computed(() => {
@@ -136,33 +129,6 @@ const resolvedDeleteUrl = computed(() => {
return `${API_URL}${cleanEndpoint}`;
});
const initialFiles = ref([]);
let isInitialLoaded = false;
watch(
() => props.modelValue,
(val) => {
// Only populate initialFiles on first load with existing items (e.g. edit mode)
// to avoid resetting active FilePond state during live uploads
if (!isInitialLoaded && Array.isArray(val) && val.length > 0) {
isInitialLoaded = true;
initialFiles.value = val
.map((item) => {
const url = typeof item === 'string' ? item : item.url || item.source || '';
if (!url) return null;
return {
source: url,
options: {
type: 'local'
}
};
})
.filter(Boolean);
}
},
{ immediate: true }
);
// Handle server responses for file processing
function handleProcessResponse(response) {
let parsed;
@@ -249,39 +215,50 @@ function removeFromFileList(identifier) {
</script>
<style>
/* Apply dark mode styles to FilePond component */
/* FilePond Container & Theme Styling */
.image-uploader-wrapper {
width: 100%;
}
.filepond--root {
font-family: 'Estedad FD', sans-serif;
background-color: var(--surface-ground);
color: var(--text-color);
border-radius: 8px;
font-family: inherit;
margin-bottom: 0 !important;
}
.app-dark .filepond--root {
background-color: var(--code-background);
border-radius: 8px;
.filepond--panel-root {
border-radius: 0.75rem !important;
background-color: var(--surface-100, #f1f5f9) !important;
border: 2px dashed var(--surface-300, #cbd5e1) !important;
transition: all 0.2s ease;
}
.filepond--label {
color: var(--text-color-secondary);
.app-dark .filepond--panel-root,
.dark .filepond--panel-root {
background-color: var(--surface-800, #1e293b) !important;
border-color: var(--surface-700, #334155) !important;
}
.app-dark .filepond--label {
color: var(--code-color);
.filepond--drop-label {
min-height: 5.5rem !important;
color: var(--text-color-secondary, #64748b) !important;
cursor: pointer;
font-size: 0.875rem !important;
}
.app-dark .filepond--drop-label {
background-color: var(--code-background);
color: var(--code-color);
border: 1px solid var(--surface-border);
border-radius: 8px;
.app-dark .filepond--drop-label,
.dark .filepond--drop-label {
color: var(--text-color-secondary, #94a3b8) !important;
}
.filepond--label-action {
color: var(--primary-color, #10b981) !important;
font-weight: 600;
text-decoration: underline;
text-underline-offset: 3px;
}
.filepond--item-panel {
background-color: var(--surface-card);
}
.app-dark .filepond--item-panel {
background-color: var(--code-background);
background-color: var(--primary-color, #10b981) !important;
}
</style>