127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="dropzone mb-3 dz-clickable"
 | |
|        :class="[multiple ? 'dropzone-multiple': 'dropzone-single']">
 | |
|     <div class="fallback">
 | |
|       <div class="custom-file">
 | |
|         <input type="file"
 | |
|                class="custom-file-input"
 | |
|                id="projectCoverUploads"
 | |
|                :multiple="multiple">
 | |
|         <label class="custom-file-label" for="projectCoverUploads">Choose file</label>
 | |
|       </div>
 | |
|     </div>
 | |
|     <div class="dz-preview dz-preview-single"
 | |
|          v-if="!multiple"
 | |
|          :class="previewClasses"
 | |
|          ref="previewSingle">
 | |
|       <div class="dz-preview-cover">
 | |
|         <img class="dz-preview-img" data-dz-thumbnail>
 | |
|       </div>
 | |
|     </div>
 | |
|     <ul v-else
 | |
|         class="dz-preview dz-preview-multiple list-group list-group-lg list-group-flush"
 | |
|         :class="previewClasses"
 | |
|         ref="previewMultiple">
 | |
|       <li class="list-group-item px-0">
 | |
|         <div class="row align-items-center">
 | |
|           <div class="col-auto">
 | |
|             <div class="avatar">
 | |
|               <img class="avatar-img rounded" data-dz-thumbnail>
 | |
|             </div>
 | |
|           </div>
 | |
|           <div class="col ml--3">
 | |
|             <h4 class="mb-1" data-dz-name>...</h4>
 | |
|             <p class="small text-muted mb-0" data-dz-size>...</p>
 | |
|           </div>
 | |
|           <div class="col-auto">
 | |
|             <button data-dz-remove="true" class="btn btn-danger btn-sm">
 | |
|               <i class="fas fa-trash"></i>
 | |
|             </button>
 | |
|           </div>
 | |
|         </div>
 | |
|       </li>
 | |
|     </ul>
 | |
|   </div>
 | |
| </template>
 | |
| <script>
 | |
|   import Dropzone from 'dropzone';
 | |
| 
 | |
|   Dropzone.autoDiscover = false;
 | |
| 
 | |
|   export default {
 | |
|     name: 'dropzone-file-upload',
 | |
|     props: {
 | |
|       options: {
 | |
|         type: Object,
 | |
|         default: () => ({})
 | |
|       },
 | |
|       value: [String, Object, Array],
 | |
|       url: {
 | |
|         type: String,
 | |
|         default: 'http://'
 | |
|       },
 | |
|       multiple: Boolean,
 | |
|       previewClasses: [String, Object, Array]
 | |
|     },
 | |
|     model: {
 | |
|       prop: 'value',
 | |
|       event: 'change'
 | |
|     },
 | |
|     data() {
 | |
|       return {
 | |
|         currentFile: null,
 | |
|         files: [],
 | |
|         showList: false,
 | |
|       }
 | |
|     },
 | |
|     methods: {
 | |
|       async initDropzone() {
 | |
|         let preview = this.multiple ? this.$refs.previewMultiple : this.$refs.previewSingle;
 | |
|         let self = this
 | |
|         let finalOptions = {
 | |
|           ...this.options,
 | |
|           url: this.url,
 | |
|           thumbnailWidth: null,
 | |
|           thumbnailHeight: null,
 | |
|           previewsContainer: preview,
 | |
|           previewTemplate: preview.innerHTML,
 | |
|           maxFiles: (!this.multiple) ? 1 : null,
 | |
|           acceptedFiles: (!this.multiple) ? 'image/*' : null,
 | |
|           init: function () {
 | |
|             this.on("addedfile", function (file) {
 | |
|               if (!self.multiple && self.currentFile) {
 | |
|                 // this.removeFile(this.currentFile);
 | |
|               }
 | |
|               self.currentFile = file;
 | |
|             })
 | |
|           }
 | |
|         }
 | |
|         this.dropzone = new Dropzone(this.$el, finalOptions)
 | |
|         preview.innerHTML = ''
 | |
|         let evtList = ['drop', 'dragstart', 'dragend', 'dragenter', 'dragover', 'addedfile', 'removedfile', 'thumbnail', 'error', 'processing', 'uploadprogress', 'sending', 'success', 'complete', 'canceled', 'maxfilesreached', 'maxfilesexceeded', 'processingmultiple', 'sendingmultiple', 'successmultiple', 'completemultiple', 'canceledmultiple', 'totaluploadprogress', 'reset', 'queuecomplete']
 | |
|         evtList.forEach(evt => {
 | |
|           this.dropzone.on(evt, (data) => {
 | |
|             this.$emit(evt, data);
 | |
| 
 | |
|             if (evt === 'addedfile') {
 | |
|               this.files.push(data)
 | |
|               this.$emit('change', this.files);
 | |
|             } else if (evt === 'removedfile') {
 | |
|               let index = this.files.findIndex(f => f.upload.uuid === data.upload.uuid)
 | |
|               if (index !== -1) {
 | |
|                 this.files.splice(index, 1);
 | |
|               }
 | |
|               this.$emit('change', this.files);
 | |
|             }
 | |
|           })
 | |
|         })
 | |
|       }
 | |
|     },
 | |
|     async mounted() {
 | |
|       this.initDropzone()
 | |
|     }
 | |
|   }
 | |
| </script>
 | |
| <style>
 | |
| </style>
 |