Skip to content

Commit

Permalink
Merge pull request #3033 from bahadirsofuoglu/fileupload-uploadmethod…
Browse files Browse the repository at this point in the history
…-changes

FileUpload templating changes
  • Loading branch information
bahadirsofuoglu authored Oct 13, 2022
2 parents 7f88d4a + 8ca2496 commit 3fee126
Show file tree
Hide file tree
Showing 4 changed files with 647 additions and 55 deletions.
57 changes: 57 additions & 0 deletions src/components/fileupload/FileContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="card flex justify-content-between border-1 surface-border">
<div class="align-self-center">
<img role="presentation" :alt="file.name" :src="file.objectURL" height="50" width="50" />
</div>
<div class="p-fileupload-content-body flex flex-column justify-content-between">
<div>{{ file.name }}</div>
<div class="flex">
<div>{{ formatSize(file.size) }}</div>
<Badge :value="badgeValue" class="ml-2" :severity="badgeSeverity" />
</div>
</div>
<div class="align-self-center">
<Button icon="pi pi-times" @click="$emit('remove', index)" class="p-button-text p-button-secondary" />
</div>
</div>
</template>

<script>
export default {
emits: ['remove'],
props: {
files: {
type: Array,
default: () => []
},
badgeSeverity: {
type: String,
default: 'warning'
},
badgeValue: {
type: String,
default: 'Pending'
}
},
methods: {
formatSize(bytes) {
if (bytes === 0) {
return '0 B';
}
let k = 1000,
dm = 3,
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
}
};
</script>

<style scoped>
.p-fileupload-content-body {
flex: 0.96;
}
</style>
74 changes: 45 additions & 29 deletions src/components/fileupload/FileUpload.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
<template>
<div v-if="isAdvanced" class="p-fileupload p-fileupload-advanced p-component">
<div class="p-fileupload-buttonbar">
<span v-ripple :class="advancedChooseButtonClass" :style="style" @click="choose" @keydown.enter="choose" @focus="onFocus" @blur="onBlur" tabindex="0">
<input ref="fileInput" type="file" @change="onFileSelect" :multiple="multiple" :accept="accept" :disabled="chooseDisabled" />
<span :class="advancedChooseIconClass"></span>
<span class="p-button-label">{{ chooseButtonLabel }}</span>
</span>
<FileUploadButton v-if="showUploadButton" :label="uploadButtonLabel" :icon="uploadIcon" @click="upload" :disabled="uploadDisabled" />
<FileUploadButton v-if="showCancelButton" :label="cancelButtonLabel" :icon="cancelIcon" @click="clear" :disabled="cancelDisabled" />
<input ref="fileInput" type="file" @change="onFileSelect" :multiple="multiple" :accept="accept" :disabled="chooseDisabled" />
<slot name="header" :uploadDisabled="uploadDisabled" :cancelDisabled="cancelDisabled" :choose="headerSlotCallbacks.choose" :upload="headerSlotCallbacks.upload" :clear="headerSlotCallbacks.clear">
<span v-ripple :class="advancedChooseButtonClass" :style="style" @click="choose" @keydown.enter="choose" @focus="onFocus" @blur="onBlur" tabindex="0">
<span :class="advancedChooseIconClass"></span>
<span class="p-button-label">{{ chooseButtonLabel }}</span>
</span>
<FileUploadButton v-if="showUploadButton" :label="uploadButtonLabel" :icon="uploadIcon" @click="upload" :disabled="uploadDisabled" />
<FileUploadButton v-if="showCancelButton" :label="cancelButtonLabel" :icon="cancelIcon" @click="clear" :disabled="cancelDisabled" />
</slot>
</div>
<div ref="content" class="p-fileupload-content" @dragenter="onDragEnter" @dragover="onDragOver" @dragleave="onDragLeave" @drop="onDrop">
<FileUploadProgressBar v-if="hasFiles" :value="progress" />
<FileUploadProgressBar v-if="hasFiles" :value="progress" style="height: 14px" />

<FileUploadMessage v-for="msg of messages" :key="msg" severity="error" @close="onMessageClose">{{ msg }}</FileUploadMessage>
<div v-if="hasFiles" class="p-fileupload-files">
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="p-fileupload-row">
<div>
<img v-if="isImage(file)" role="presentation" :alt="file.name" :src="file.objectURL" :width="previewWidth" />
</div>
<div class="p-fileupload-filename">{{ file.name }}</div>
<div>{{ formatSize(file.size) }}</div>
<div>
<FileUploadButton type="button" icon="pi pi-times" @click="remove(index)" />
</div>
</div>
</div>
<slot name="fileContent" :files="files" :uploadedFiles="uploadedFiles" :onUploadedFileRemove="removeUploadedFile" :onFileRemove="remove">
<FileContent v-if="hasFiles" :files="files" @remove="remove" />
<FileContent :files="uploadedFiles" badge-value="Completed" badge-severity="success" @remove="removeUploadedFile" />
</slot>
<div v-if="$slots.content && !hasFiles">
<slot name="content"></slot>
</div>
Expand All @@ -48,10 +43,11 @@ import Message from 'primevue/message';
import ProgressBar from 'primevue/progressbar';
import Ripple from 'primevue/ripple';
import { DomHandler } from 'primevue/utils';
import FileContent from './FileContent.vue';
export default {
name: 'FileUpload',
emits: ['select', 'uploader', 'before-upload', 'progress', 'upload', 'error', 'before-send', 'clear', 'remove'],
emits: ['select', 'uploader', 'before-upload', 'progress', 'upload', 'error', 'before-send', 'clear', 'remove', 'removeUploadedFile'],
props: {
name: {
type: String,
Expand Down Expand Up @@ -155,9 +151,22 @@ export default {
files: [],
messages: [],
focused: false,
progress: null
progress: null,
uploadedFiles: [],
headerSlotCallbacks: {
choose: () => {
this.choose();
},
upload: () => {
this.upload();
},
clear: () => {
this.clear();
}
}
};
},
methods: {
onFileSelect(event) {
if (event.type !== 'drop' && this.isIE11() && this.duplicateIEEvent) {
Expand Down Expand Up @@ -253,6 +262,7 @@ export default {
});
}
this.uploadedFiles.push(...this.files);
this.clear();
}
};
Expand Down Expand Up @@ -382,6 +392,15 @@ export default {
files: this.files
});
},
removeUploadedFile(index) {
let removedFile = this.uploadedFiles.splice(index, 1)[0];
this.uploadedFiles = [...this.uploadedFiles];
this.$emit('removeUploadedFile', {
file: removedFile,
files: this.uploadedFiles
});
},
clearInputElement() {
this.$refs.fileInput.value = '';
},
Expand Down Expand Up @@ -481,15 +500,16 @@ export default {
components: {
FileUploadButton: Button,
FileUploadProgressBar: ProgressBar,
FileUploadMessage: Message
FileUploadMessage: Message,
FileContent
},
directives: {
ripple: Ripple
}
};
</script>

<style>
<style scoped>
.p-fileupload-content {
position: relative;
}
Expand Down Expand Up @@ -520,11 +540,7 @@ export default {
overflow: hidden;
}
.p-button.p-fileupload-choose input[type='file'] {
display: none;
}
.p-fileupload-choose.p-fileupload-choose-selected input[type='file'] {
input[type='file'] {
display: none;
}
Expand Down
124 changes: 120 additions & 4 deletions src/views/fileupload/FileUploadDemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,74 @@
</template>
</FileUpload>

<h5>Templating</h5>
<FileUpload name="demo[]" url="./upload.php" @upload="onAdvancedUpload($event)" :multiple="true" accept="image/*" :maxFileSize="1000000" @select="onSelectedFiles">
<template #header="{ uploadDisabled, cancelDisabled, choose, upload, clear }">
<div class="flex justify-content-between align-items-center">
<div>
<button @click="choose()" class="p-button p-fileupload-choose p-component p-button-icon-only custom-choose-btn p-button-rounded p-button-outlined">
<span class="p-button-icon p-button-icon-left p-clickable pi pi-fw pi-images"></span>
</button>
<button @click="upload()" type="button" class="p-button p-component custom-upload-btn p-button-success p-button-rounded p-button-outlined p-button-icon-only" :disabled="uploadDisabled">
<span class="p-button-icon p-c pi pi-fw pi-cloud-upload"></span>
</button>
<button @click="onClearTemplatingUpload(clear)" type="button" class="p-button p-component custom-cancel-btn p-button-danger p-button-rounded p-button-outlined p-button-icon-only" :disabled="cancelDisabled">
<span class="p-button-icon p-c pi pi-fw pi-times"></span>
</button>
</div>
<ProgressBar v-if="totalSizePercent > 100" :value="100" class="custom-progress-bar" style="width: 300px; height: 20px; margin-left: auto">{{ totalSize }}B / 1Mb</ProgressBar>
<ProgressBar v-else-if="totalSizePercent <= 100 && totalSizePercent !== 0" :value="totalSizePercent" style="width: 300px; height: 20px; margin-left: auto">{{ totalSize }}B / 1Mb</ProgressBar>
</div>
</template>
<template #fileContent="{ files, uploadedFiles, onUploadedFileRemove, onFileRemove }">
<div v-if="files.length > 0">
<h5>Pending</h5>
<div class="grid p-5">
<div v-for="(file, index) of files" :key="file.name + file.type + file.size" class="col-3 mx-3 card flex flex-column border-1 surface-border align-items-center">
<div>
<img role="presentation" :alt="file.name" :src="file.objectURL" height="50" width="50" />
</div>

<div class="mt-2 flex align-content-center">
<span v-tooltip="file.name" class="fileinput-file-name">{{ file.name }}</span>
</div>
<div class="mt-3">{{ formatSize(file.size) }}</div>
<Badge value="Pending" class="mt-3" severity="warning" />
<div class="mt-3">
<Button icon="pi pi-times" @click="onRemoveTemplatingFile(file, onFileRemove, index)" class="p-button-text p-button-secondary" />
</div>
</div>
</div>
</div>

<div v-if="uploadedFiles.length > 0">
<h5>Completed</h5>
<div class="grid p-5">
<div v-for="(file, index) of uploadedFiles" :key="file.name + file.type + file.size" class="col-3 mx-3 card flex flex-column border-1 surface-border align-items-center">
<div>
<img role="presentation" :alt="file.name" :src="file.objectURL" height="50" width="50" />
</div>
<div class="mt-2 flex align-content-center">
<span v-tooltip="file.name" class="fileinput-file-name">{{ file.name }}</span>
</div>
<div class="mt-3">{{ formatSize(file.size) }}</div>
<Badge value="Completed" class="mt-3" severity="success" />

<div class="mt-3">
<Button icon="pi pi-times" @click="onUploadedFileRemove(index)" class="p-button-text p-button-secondary" />
</div>
</div>
</div>
</div>
</template>
<template #empty>
<div class="flex align-items-center justify-content-center flex-column">
<i class="pi pi-cloud-upload border-1 border-circle border-solid surface-border p-5 text-8xl text-500" />
<p class="mt-4">Drag and drop files to here to upload.</p>
</div>
</template>
</FileUpload>

<h5>Basic</h5>
<FileUpload mode="basic" name="demo[]" url="./upload.php" accept="image/*" :maxFileSize="1000000" @upload="onUpload" />

Expand All @@ -36,20 +104,53 @@

<script>
import FileUploadDoc from './FileUploadDoc';
export default {
data() {
return {
uploadedFiles: []
uploadedFiles: [],
files: [],
totalSize: 0,
totalSizePercent: 0
};
},
methods: {
onAdvancedUpload(event) {
this.uploadedFiles.push(event.files);
onRemoveTemplatingFile(file, onFileRemove, index) {
onFileRemove(index);
this.totalSize -= parseInt(this.formatSize(file.size));
this.totalSizePercent = this.totalSize / 10;
},
onClearTemplatingUpload(clear) {
clear();
this.totalSize = 0;
this.totalSizePercent = 0;
},
onSelectedFiles(event) {
this.files = event.files;
this.files.forEach((file) => {
this.totalSize += parseInt(this.formatSize(file.size));
});
this.totalSizePercent = this.totalSize / 10;
},
onAdvancedUpload() {
this.totalSize = 0;
this.totalSizePercent = 0;
this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 });
},
onUpload() {
this.$toast.add({ severity: 'info', summary: 'Success', detail: 'File Uploaded', life: 3000 });
},
formatSize(bytes) {
if (bytes === 0) {
return '0 B';
}
let k = 1000,
dm = 3,
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
},
components: {
Expand All @@ -62,4 +163,19 @@ export default {
p {
margin: 0;
}
.fileinput-file-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 1500px) {
.fileinput-file-name {
width: 100px;
}
}
::v-deep(.custom-progress-bar) {
.p-progressbar-value {
background-color: #f44336;
}
}
</style>
Loading

0 comments on commit 3fee126

Please sign in to comment.