Initiated Advanced FileUploader
parent
3292c502b8
commit
3b2c4dee49
|
@ -0,0 +1 @@
|
|||
<?php echo '<p>Fake Upload Process</p>'; ?>
|
|
@ -89,7 +89,7 @@
|
|||
</a>
|
||||
<div :class="{'submenuhide': activeMenuIndex !== 5, 'submenushow': activeMenuIndex === 5}">
|
||||
<div>
|
||||
<router-link to="/">● Link</router-link>
|
||||
<router-link to="/fileupload">● Upload</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1077,4 +1077,9 @@ pre[class*="language-"] {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.p-toast.p-toast-topright,
|
||||
.p-toast.p-toast-topleft {
|
||||
top: 100px;
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
@import '../../components/dialog/Dialog.css';
|
||||
@import '../../components/dropdown/Dropdown.css';
|
||||
@import '../../components/fieldset/Fieldset.css';
|
||||
@import '../../components/fileupload/FileUpload.css';
|
||||
@import '../../components/inputtext/InputText.css';
|
||||
@import '../../components/inputswitch/InputSwitch.css';
|
||||
@import '../../components/listbox/Listbox.css';
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* FileUpload
|
||||
*/
|
||||
.p-fileupload-buttonbar .p-fileupload-choose.p-disabled input {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.p-fileupload-buttonbar {
|
||||
padding: .5em;
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
|
||||
.p-fileupload-buttonbar .p-button {
|
||||
vertical-align: middle;
|
||||
margin-right: .25em;
|
||||
}
|
||||
|
||||
.p-fileupload-content {
|
||||
padding: 1em;
|
||||
position: relative;
|
||||
transition: border-color .3s;
|
||||
}
|
||||
|
||||
.p-fileupload-content.p-fileupload-highlight {
|
||||
border-color: #156090;
|
||||
}
|
||||
|
||||
.p-fileupload-files img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.p-fileupload-files {
|
||||
display: table;
|
||||
}
|
||||
|
||||
.p-fileupload-row {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.p-fileupload-row > div {
|
||||
display: table-cell;
|
||||
padding: .5em 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.p-fileupload-content .p-progressbar {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
height: .25em;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
.p-fileupload-content .p-progressbar-value {
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
/* Simple */
|
||||
.p-fileupload-choose {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-fileupload-choose input[type=file] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
min-height: 100%;
|
||||
font-size: 100px;
|
||||
text-align: right;
|
||||
filter: alpha(opacity=0);
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.p-fileupload-choose.p-fileupload-choose-selected input[type=file] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* p-fluid */
|
||||
.p-fluid .p-fileupload .p-button {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.p-fluid .p-fileupload-content .p-button-icon-only {
|
||||
width: 2em;
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
<template>
|
||||
<div class="p-fileupload p-component" v-if="isAdvanced">
|
||||
<div class="p-fileupload-buttonbar">
|
||||
<span icon="pi pi-plus" :class="advancedChooseButtonClass">
|
||||
<input ref="fileInput" type="file" @change="onFileSelect" @focus="onFocus" @blur="onBlur"
|
||||
:multiple="multiple" :accept="accept" :disabled="disabled" />
|
||||
<span class="p-button-icon p-button-icon-left p-clickable pi pi-fw pi-plus"></span>
|
||||
<span class="p-button-text p-clickable">{{chooseLabel}}</span>
|
||||
</span>
|
||||
<FileUploadButton :label="uploadLabel" icon="pi pi-upload" @click="upload" :disabled="disabled || !hasFiles" />
|
||||
<FileUploadButton :label="cancelLabel" icon="pi pi-times" @click="clear" :disabled="disabled || !hasFiles" />
|
||||
</div>
|
||||
<div ref="content" class="p-fileupload-content" @dragenter="onDragEnter" @dragover="onDragOver" @dragleave="onDragLeave" @drop="onDrop">
|
||||
<FileUploadProgressBar :value="progress" v-if="hasFiles" />
|
||||
<FileUploadMessage v-for="msg of messages" :severity="error" :key="msg">{{msg}}</FileUploadMessage>
|
||||
<div class="p-fileupload-files" v-if="hasFiles">
|
||||
<div class="p-fileupload-row" v-for="(file, index) of files" :key="file.name + file.type + file.size">
|
||||
<div v-if="isImage(file)">
|
||||
<img role="presentation" :alt="file.name" :src="file.objectURL" :width="previewWidth" />
|
||||
</div>
|
||||
<div>{{file.name}}</div>
|
||||
<div>{{formatSize(file.size)}}</div>
|
||||
<div>
|
||||
<Button type="button" icon="pi pi-times" @click="remove(index)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Button from '../button/Button';
|
||||
import ProgressBar from '../progressbar/ProgressBar';
|
||||
import Message from '../message/Message';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'advanced'
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
auto: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxFileSize: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
invalidFileSizeMessage: {
|
||||
type: String,
|
||||
default: '{0}: Invalid file size, maximum upload size is {1}.'
|
||||
},
|
||||
withCredentials: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
previewWidth: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
chooseLabel: {
|
||||
type: String,
|
||||
default: 'Choose'
|
||||
},
|
||||
uploadLabel: {
|
||||
type: String,
|
||||
default: 'Upload'
|
||||
},
|
||||
cancelLabel: {
|
||||
type: String,
|
||||
default: 'Cancel'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
files: null,
|
||||
messages: null,
|
||||
focused: false,
|
||||
progress: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onFileSelect(event) {
|
||||
this.messages = [];
|
||||
this.files = this.files || [];
|
||||
let files = event.dataTransfer ? event.dataTransfer.files : event.target.files;
|
||||
for (let file of files) {
|
||||
if (!this.isFileSelected(file)) {
|
||||
if (this.validate(file)) {
|
||||
if (this.isImage(file)) {
|
||||
file.objectURL = window.URL.createObjectURL(file);
|
||||
}
|
||||
this.files.push(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.auto) {
|
||||
this.upload();
|
||||
}
|
||||
|
||||
this.$emit('select', {originalEvent: event, files: files});
|
||||
this.clearInputElement();
|
||||
|
||||
if (this.mode === 'basic') {
|
||||
this.$refs.fileInput.style.display = 'none';
|
||||
}
|
||||
},
|
||||
upload() {
|
||||
this.messages = [];
|
||||
let xhr = new XMLHttpRequest();
|
||||
let formData = new FormData();
|
||||
|
||||
this.$emit('before-upload', {
|
||||
'xhr': xhr,
|
||||
'formData': formData
|
||||
});
|
||||
|
||||
for (let file of this.files) {
|
||||
formData.append(this.name, file, file.name);
|
||||
}
|
||||
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
this.progress = Math.round((event.loaded * 100) / event.total);
|
||||
}
|
||||
|
||||
this.$emit('progress', {
|
||||
originalEvent: event,
|
||||
progress: this.progress
|
||||
});
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
this.progress = 0;
|
||||
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
this.$emit('upload', {
|
||||
xhr: xhr,
|
||||
files: this.files
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.$emit('error', {
|
||||
xhr: xhr,
|
||||
files: this.files
|
||||
});
|
||||
}
|
||||
|
||||
this.clear();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.open('POST', this.url, true);
|
||||
|
||||
this.$emit('before-send', {
|
||||
'xhr': xhr,
|
||||
'formData': formData
|
||||
});
|
||||
|
||||
xhr.withCredentials = this.withCredentials;
|
||||
|
||||
xhr.send(formData);
|
||||
},
|
||||
clear() {
|
||||
this.files = null;
|
||||
this.$emit('clear');
|
||||
this.clearInputElement();
|
||||
},
|
||||
onFocus() {
|
||||
this.focused = true;
|
||||
},
|
||||
onBlur() {
|
||||
this.focused = false;
|
||||
},
|
||||
isFileSelected(file) {
|
||||
if (this.files && this.files.length) {
|
||||
for (let sFile of this.files) {
|
||||
if ((sFile.name + sFile.type + sFile.size) === (file.name + file.type + file.size))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
validate(file) {
|
||||
if (this.maxFileSize && file.size > this.maxFileSize) {
|
||||
this.messages.push[this.invalidFileSizeMessage.replace('{0}', file.name).replace('{0}', this.formatSize(this.maxFileSize))];
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
onDragEnter() {
|
||||
|
||||
},
|
||||
onDragLeave() {
|
||||
|
||||
},
|
||||
onDragOver() {
|
||||
|
||||
},
|
||||
onDrop() {
|
||||
|
||||
},
|
||||
remove(index) {
|
||||
this.clearInputElement();
|
||||
this.state.files.slice(index, 1);
|
||||
},
|
||||
isImage(file) {
|
||||
return /^image\//.test(file.type);
|
||||
},
|
||||
clearInputElement() {
|
||||
this.$refs.fileInput.value = '';
|
||||
if (this.mode === 'basic') {
|
||||
this.$refs.fileInput.style.display = 'inline';
|
||||
}
|
||||
},
|
||||
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];
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAdvanced() {
|
||||
return this.mode === 'advanced';
|
||||
},
|
||||
isBasic() {
|
||||
return this.mode === 'basic';
|
||||
},
|
||||
advancedChooseButtonClass() {
|
||||
return ['p-button p-fileupload-choose p-component p-button-text-icon-left', {
|
||||
'p-disabled': this.disabled,
|
||||
'p-focus': this.focused
|
||||
}
|
||||
];
|
||||
},
|
||||
hasFiles() {
|
||||
return this.files && this.files.length > 0;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'FileUploadButton': Button,
|
||||
'FileUploadProgressBar': ProgressBar,
|
||||
'FileUploadMessage': Message
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -12,10 +12,11 @@ import Chips from './components/chips/Chips';
|
|||
import Dialog from './components/dialog/Dialog';
|
||||
import Dropdown from './components/dropdown/Dropdown';
|
||||
import Editor from './components/editor/Editor';
|
||||
import Fieldset from './components/fieldset/Fieldset';
|
||||
import FileUpload from './components/fileupload/FileUpload';
|
||||
import FullCalendar from './components/fullcalendar/FullCalendar';
|
||||
import InputSwitch from './components/inputswitch/InputSwitch';
|
||||
import InputText from './components/inputtext/InputText';
|
||||
import Fieldset from './components/fieldset/Fieldset';
|
||||
import Listbox from './components/listbox/Listbox';
|
||||
import Message from './components/message/Message';
|
||||
import MultiSelect from './components/multiselect/MultiSelect';
|
||||
|
@ -58,11 +59,12 @@ Vue.component('Chips', Chips);
|
|||
Vue.component('Dialog', Dialog);
|
||||
Vue.component('Dropdown', Dropdown);
|
||||
Vue.component('Editor', Editor);
|
||||
Vue.component('Fieldset', Fieldset);
|
||||
Vue.component('FileUpload', FileUpload);
|
||||
Vue.component('FullCalendar', FullCalendar);
|
||||
Vue.component('InputSwitch', InputSwitch);
|
||||
Vue.component('InputText', InputText);
|
||||
Vue.component('Listbox', Listbox);
|
||||
Vue.component('Fieldset', Fieldset);
|
||||
Vue.component('Message', Message);
|
||||
Vue.component('MultiSelect', MultiSelect);
|
||||
Vue.component('OverlayPanel', OverlayPanel);
|
||||
|
|
|
@ -101,6 +101,11 @@ export default new Router({
|
|||
name: 'fieldset',
|
||||
component: () => import('./views/fieldset/FieldsetDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/fileupload',
|
||||
name: 'fileupload',
|
||||
component: () => import('./views/fileupload/FileUploadDemo.vue')
|
||||
},
|
||||
{
|
||||
path: '/flexgrid',
|
||||
name: 'flexgrid',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="content-section introduction">
|
||||
<div class="feature-intro">
|
||||
<h1>FileUpload</h1>
|
||||
<p>FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and validations.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-section implementation">
|
||||
<h3>Advanced</h3>
|
||||
<FileUpload name="demo[]" url="http://192.168.1.110:4000/upload" @upload="onUpload" :multiple="true" accept="image/*" :maxFileSize="1000000" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
onUpload() {
|
||||
this.$toast.add({severity: 'info', summary: 'Success', detail: 'File Uploaded'});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -101,9 +101,4 @@ export default {
|
|||
button.p-button {
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
.p-toast.p-toast-topright,
|
||||
.p-toast.p-toast-topleft {
|
||||
top: 100px;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue