Visual improvements to fileupload templating

pull/5806/head
Cagatay Civici 2024-05-30 10:31:02 +03:00
parent cc7ae3b82a
commit db722d8ba2
1 changed files with 114 additions and 106 deletions

View File

@ -5,51 +5,53 @@
<div class="card"> <div class="card">
<FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
<template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }">
<div class="flex flex-wrap justify-between items-center flex-1 gap-2"> <div class="flex flex-wrap justify-between items-center flex-1 gap-4">
<div class="flex gap-2"> <div class="flex gap-2">
<Button @click="chooseCallback()" icon="pi pi-images" rounded outlined></Button> <Button @click="chooseCallback()" icon="pi pi-images" rounded outlined severity="secondary"></Button>
<Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button>
<Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button>
</div> </div>
<ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-4 w-full md:ml-auto', { 'exceeded-progress-bar': totalSizePercent > 100 }]"> <ProgressBar :value="totalSizePercent" :showValue="false" class="md:w-20rem h-1 w-full md:ml-auto">
<span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span> <span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span>
</ProgressBar> </ProgressBar>
</div> </div>
</template> </template>
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }"> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
<div v-if="files.length > 0"> <div class="flex flex-col gap-8 pt-4">
<h5>Pending</h5> <div v-if="files.length > 0">
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <h5>Pending</h5>
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div class="flex flex-wrap gap-4">
<div> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div>
<div v-if="uploadedFiles.length > 0"> <div v-if="uploadedFiles.length > 0">
<h5>Completed</h5> <h5>Completed</h5>
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <div class="flex flex-wrap gap-4">
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<div> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<template #empty> <template #empty>
<div class="flex items-center justify-center flex-col"> <div class="flex items-center justify-center flex-col">
<i class="pi pi-cloud-upload border-2 rounded-full p-8 text-8xl text-surface-400 border-surface-400" /> <i class="pi pi-cloud-upload border-2 rounded-full p-8 text-4xl text-muted-color" />
<p class="mt-6 mb-0">Drag and drop files to here to upload.</p> <p class="mt-6 mb-0">Drag and drop files to here to upload.</p>
</div> </div>
</template> </template>
@ -69,51 +71,53 @@ export default {
basic: ` basic: `
<FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
<template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }">
<div class="flex flex-wrap justify-between items-center flex-1 gap-2"> <div class="flex flex-wrap justify-between items-center flex-1 gap-4">
<div class="flex gap-2"> <div class="flex gap-2">
<Button @click="chooseCallback()" icon="pi pi-images" rounded outlined></Button> <Button @click="chooseCallback()" icon="pi pi-images" rounded outlined severity="secondary"></Button>
<Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button>
<Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button>
</div> </div>
<ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-4 w-full md:ml-auto', { 'exceeded-progress-bar': totalSizePercent > 100 }]" <ProgressBar :value="totalSizePercent" :showValue="false" class="md:w-20rem h-1 w-full md:ml-auto">
><span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar <span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span>
> </ProgressBar>
</div> </div>
</template> </template>
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }"> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
<div v-if="files.length > 0"> <div class="flex flex-col gap-8 pt-4">
<h5>Pending</h5> <div v-if="files.length > 0">
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <h5>Pending</h5>
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div class="flex flex-wrap gap-4">
<div> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div>
<div v-if="uploadedFiles.length > 0"> <div v-if="uploadedFiles.length > 0">
<h5>Completed</h5> <h5>Completed</h5>
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <div class="flex flex-wrap gap-4">
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<div> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<template #empty> <template #empty>
<div class="flex items-center justify-center flex-col"> <div class="flex items-center justify-center flex-col">
<i class="pi pi-cloud-upload border-2 rounded-full p-8 text-8xl text-surface-400 border-surface-400" /> <i class="pi pi-cloud-upload border-2 rounded-full p-8 text-4xl text-muted-color" />
<p class="mt-6 mb-0">Drag and drop files to here to upload.</p> <p class="mt-6 mb-0">Drag and drop files to here to upload.</p>
</div> </div>
</template> </template>
@ -125,51 +129,53 @@ export default {
<Toast /> <Toast />
<FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
<template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }">
<div class="flex flex-wrap justify-between items-center flex-1 gap-2"> <div class="flex flex-wrap justify-between items-center flex-1 gap-4">
<div class="flex gap-2"> <div class="flex gap-2">
<Button @click="chooseCallback()" icon="pi pi-images" rounded outlined></Button> <Button @click="chooseCallback()" icon="pi pi-images" rounded outlined severity="secondary"></Button>
<Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button>
<Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button>
</div> </div>
<ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-4 w-full md:ml-auto', { 'exceeded-progress-bar': totalSizePercent > 100 }]" <ProgressBar :value="totalSizePercent" :showValue="false" class="md:w-20rem h-1 w-full md:ml-auto">
><span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar <span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span>
> </ProgressBar>
</div> </div>
</template> </template>
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }"> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
<div v-if="files.length > 0"> <div class="flex flex-col gap-8 pt-4">
<h5>Pending</h5> <div v-if="files.length > 0">
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <h5>Pending</h5>
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div class="flex flex-wrap gap-4">
<div> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div>
<div v-if="uploadedFiles.length > 0"> <div v-if="uploadedFiles.length > 0">
<h5>Completed</h5> <h5>Completed</h5>
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <div class="flex flex-wrap gap-4">
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<div> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<template #empty> <template #empty>
<div class="flex items-center justify-center flex-col"> <div class="flex items-center justify-center flex-col">
<i class="pi pi-cloud-upload border-2 rounded-full p-8 text-8xl text-surface-400 border-surface-400" /> <i class="pi pi-cloud-upload border-2 rounded-full p-8 text-4xl text-muted-color" />
<p class="mt-6 mb-0">Drag and drop files to here to upload.</p> <p class="mt-6 mb-0">Drag and drop files to here to upload.</p>
</div> </div>
</template> </template>
@ -234,51 +240,53 @@ export default {
<Toast /> <Toast />
<FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles"> <FileUpload name="demo[]" url="/api/upload" @upload="onTemplatedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
<template #header="{ chooseCallback, uploadCallback, clearCallback, files }"> <template #header="{ chooseCallback, uploadCallback, clearCallback, files }">
<div class="flex flex-wrap justify-between items-center flex-1 gap-2"> <div class="flex flex-wrap justify-between items-center flex-1 gap-4">
<div class="flex gap-2"> <div class="flex gap-2">
<Button @click="chooseCallback()" icon="pi pi-images" rounded outlined></Button> <Button @click="chooseCallback()" icon="pi pi-images" rounded outlined severity="secondary"></Button>
<Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button> <Button @click="uploadEvent(uploadCallback)" icon="pi pi-cloud-upload" rounded outlined severity="success" :disabled="!files || files.length === 0"></Button>
<Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button> <Button @click="clearCallback()" icon="pi pi-times" rounded outlined severity="danger" :disabled="!files || files.length === 0"></Button>
</div> </div>
<ProgressBar :value="totalSizePercent" :showValue="false" :class="['md:w-20rem h-4 w-full md:ml-auto', { 'exceeded-progress-bar': totalSizePercent > 100 }]" <ProgressBar :value="totalSizePercent" :showValue="false" class="md:w-20rem h-1 w-full md:ml-auto">
><span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span></ProgressBar <span class="whitespace-nowrap">{{ totalSize }}B / 1Mb</span>
> </ProgressBar>
</div> </div>
</template> </template>
<template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }"> <template #content="{ files, uploadedFiles, removeUploadedFileCallback, removeFileCallback }">
<div v-if="files.length > 0"> <div class="flex flex-col gap-8 pt-4">
<h5>Pending</h5> <div v-if="files.length > 0">
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <h5>Pending</h5>
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div class="flex flex-wrap gap-4">
<div> <div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Pending" severity="warn" />
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, removeFileCallback, index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div>
<div v-if="uploadedFiles.length > 0"> <div v-if="uploadedFiles.length > 0">
<h5>Completed</h5> <h5>Completed</h5>
<div class="flex flex-wrap p-0 sm:p-8 gap-8"> <div class="flex flex-wrap gap-4">
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="card m-0 px-12 flex flex-col border border-surface-200 dark:border-surface-700 items-center gap-4"> <div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
<div> <div>
<img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" /> <img role="presentation" :alt="file.name" :src="file.objectURL" width="100" height="50" />
</div>
<span class="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
<span class="font-semibold">{{ file.name }}</span>
<div>{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-4" severity="success" />
<Button icon="pi pi-times" @click="removeUploadedFileCallback(index)" outlined rounded severity="danger" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<template #empty> <template #empty>
<div class="flex items-center justify-center flex-col"> <div class="flex items-center justify-center flex-col">
<i class="pi pi-cloud-upload border-2 rounded-full p-8 text-8xl text-surface-400 border-surface-400" /> <i class="pi pi-cloud-upload border-2 rounded-full p-8 text-4xl text-muted-color" />
<p class="mt-6 mb-0">Drag and drop files to here to upload.</p> <p class="mt-6 mb-0">Drag and drop files to here to upload.</p>
</div> </div>
</template> </template>