Created
October 20, 2019 05:22
-
-
Save bayareawebpro/73f8614e8f70196264ec7f142ae8ff85 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
import dragDrop from 'drag-drop' | |
import {HasLoadingState, HasErrors} from '../mixins' | |
export default { | |
mixins: [ | |
HasLoadingState, | |
HasErrors, | |
], | |
data() { | |
return { | |
isDragging: false, | |
queue: [] | |
} | |
}, | |
computed: { | |
firstInQueue() { | |
return this.queue.find(entry => { | |
return !entry.completed | |
}) | |
}, | |
percent(){ | |
const total = this.queue.reduce((accumulator, entry) => { | |
return accumulator + entry.total | |
}, 0) | |
const loaded = this.queue.reduce((accumulator, entry) => { | |
return accumulator + entry.loaded | |
}, 0) | |
return Math.round((loaded / total) * 100) | |
} | |
}, | |
methods: { | |
uploadRequest(entry) { | |
//Build Form Data | |
let formData = new FormData | |
formData.append('file', entry.file) | |
const route = Nova.config.media_upload_route | |
return Nova.request().post(`${route}`,formData, { | |
onUploadProgress: (progress) => { | |
entry.status = 'Uploading...' | |
entry.loaded = progress.loaded | |
entry.total = progress.total | |
if (entry.loaded === entry.total) { | |
entry.status = 'Processing...' | |
} | |
} | |
}) | |
}, | |
processQueue() { | |
let entry = this.firstInQueue | |
if (entry) { | |
this.uploadRequest(entry) | |
.then((response) => { | |
this.$emit('upload', response) | |
entry.status = 'Completed!' | |
}) | |
.catch(({response}) => { | |
entry.status = 'Failed!' | |
this.$toasted.show( | |
this.__(':name failed!', { | |
name: entry.name, | |
}), | |
{ type: 'error' } | |
) | |
}) | |
.finally(() => { | |
entry.completed = true | |
this.processQueue() | |
}) | |
} else { | |
this.loading(false) | |
if(this.queue.length > 0){ | |
const message = this.__(':total :label completed!', { | |
total: this.queue.length, | |
label: this.queue.length > 1 ? 'uploads' : 'upload', | |
}) | |
this.$toasted.show(message, { type: 'success' }) | |
} | |
this.queue = [] | |
this.$emit('complete') | |
} | |
}, | |
/** | |
* Handle the HTTP File Upload Asynchronously. | |
* @return Void | |
*/ | |
handleUploads(files) { | |
this.clearErrors() | |
files.forEach((file, index) => { | |
if ([ | |
"image/jpeg", | |
"image/bmp", | |
"image/png", | |
"image/jpg", | |
"image/gif" | |
].includes(file.type)) { | |
this.queue.push({ | |
status: 'Queued...', | |
completed: false, | |
loaded: 0, | |
total: file.size, | |
name: _(file.name).truncate(20), | |
file: file | |
}) | |
}else{ | |
this.$toasted.show( | |
this.__(':name not allowed!', { | |
name: _(file.name).truncate(20), | |
}), | |
{ type: 'error' } | |
) | |
} | |
}) | |
if (!this.isLoading()){ | |
this.loading() | |
this.processQueue() | |
} | |
}, | |
fromFileInput() { | |
this.handleUploads(Array.prototype.slice.call(this.$refs.files.files)) | |
}, | |
cancel(){ | |
this.$emit('complete') | |
}, | |
addFiles(){ | |
if(this.$refs.files){ | |
this.$refs.files.click() | |
} | |
}, | |
}, | |
mounted() { | |
this.$nextTick(() => { | |
this.destroyDragDrop = dragDrop(this.$refs.dropzone, { | |
onDrop: this.handleUploads, | |
onDragEnter: (event) => { | |
this.dropTarget = event.target | |
this.isDragging = true | |
event.stopPropagation() | |
event.preventDefault() | |
return false; | |
}, | |
onDragLeave: (event) => { | |
if (this.dropTarget === event.target) { | |
this.isDragging = false | |
event.stopPropagation() | |
event.preventDefault() | |
} | |
return false; | |
} | |
}) | |
}) | |
}, | |
beforeDestroy() { | |
if (this.destroyDragDrop) { | |
this.destroyDragDrop() | |
this.destroyDragDrop = null | |
} | |
} | |
} | |
</script> | |
<template> | |
<div ref="dropzone" | |
class="drop-zone h-full flex flex-col items-center justify-center" | |
:class="{isDragging: isDragging}"> | |
<div class="w-full"> | |
<template v-if="firstInQueue"> | |
<i class="fa fa-circle-o-notch fa-spin fa-2x"></i> | |
<p class="mb-0">{{ firstInQueue.status }} <small>{{ firstInQueue.name }}</small></p> | |
<div class="progress-bar-animated bg-primary-dark h-2 w-100" | |
role="progressbar" | |
:style="'width:' + percent + '%'" | |
:aria-valuenow="percent" | |
aria-valuemin="0" | |
aria-valuemax="100"> | |
</div> | |
</template> | |
<div v-else class="text-80 text-center mb-0"> | |
<h3><i class="fa fa-upload fa-2x"></i><br/> Drop to Upload!</h3> | |
<button class="btn btn-primary p-2 rounded" @click.prevent="cancel">Cancel</button> | |
</div> | |
</div> | |
</div> | |
</template> | |
<style lang="sass" scoped> | |
.progress-bar-animated | |
transition: width 300ms ease-in-out | |
.drop-zone | |
cursor: pointer | |
text-align: center | |
background-color: white | |
border: 2px dashed gray | |
color: gray | |
&.isDragging | |
border: 2px dashed blue | |
color: blue | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment