Skip to content

Instantly share code, notes, and snippets.

@bayareawebpro
Created October 20, 2019 05:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bayareawebpro/73f8614e8f70196264ec7f142ae8ff85 to your computer and use it in GitHub Desktop.
Save bayareawebpro/73f8614e8f70196264ec7f142ae8ff85 to your computer and use it in GitHub Desktop.
<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