Merge pull request #1021 from ramiresviana/upload-queue
This commit is contained in:
		
						commit
						a47b69bcec
					
				| 
						 | 
					@ -89,25 +89,17 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { mapState, mapMutations } from 'vuex'
 | 
					import { mapState, mapMutations } from 'vuex'
 | 
				
			||||||
import throttle from 'lodash.throttle'
 | 
					 | 
				
			||||||
import Item from './ListingItem'
 | 
					import Item from './ListingItem'
 | 
				
			||||||
import css from '@/utils/css'
 | 
					import css from '@/utils/css'
 | 
				
			||||||
import { users, files as api } from '@/api'
 | 
					import { users, files as api } from '@/api'
 | 
				
			||||||
import buttons from '@/utils/buttons'
 | 
					import * as upload  from '@/utils/upload'
 | 
				
			||||||
import url from '@/utils/url'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: 'listing',
 | 
					  name: 'listing',
 | 
				
			||||||
  components: { Item },
 | 
					  components: { Item },
 | 
				
			||||||
  data: function () {
 | 
					  data: function () {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      showLimit: 50,
 | 
					      showLimit: 50
 | 
				
			||||||
      uploading: {
 | 
					 | 
				
			||||||
        id: 0,
 | 
					 | 
				
			||||||
        count: 0,
 | 
					 | 
				
			||||||
        size: 0,
 | 
					 | 
				
			||||||
        progress: []
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
| 
						 | 
					@ -194,7 +186,7 @@ export default {
 | 
				
			||||||
    base64: function (name) {
 | 
					    base64: function (name) {
 | 
				
			||||||
      return window.btoa(unescape(encodeURIComponent(name)))
 | 
					      return window.btoa(unescape(encodeURIComponent(name)))
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    keyEvent (event) {      
 | 
					    keyEvent (event) {
 | 
				
			||||||
      if (this.show !== null) {
 | 
					      if (this.show !== null) {
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -311,7 +303,7 @@ export default {
 | 
				
			||||||
    dragEnd () {
 | 
					    dragEnd () {
 | 
				
			||||||
      this.resetOpacity()
 | 
					      this.resetOpacity()
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    drop: function (event) {
 | 
					    drop: async function (event) {
 | 
				
			||||||
      event.preventDefault()
 | 
					      event.preventDefault()
 | 
				
			||||||
      this.resetOpacity()
 | 
					      this.resetOpacity()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -331,65 +323,34 @@ export default {
 | 
				
			||||||
        base = el.querySelector('.name').innerHTML + '/'
 | 
					        base = el.querySelector('.name').innerHTML + '/'
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (base === '') {
 | 
					      let files = await upload.scanFiles(dt)
 | 
				
			||||||
        this.scanFiles(dt).then((result) => {
 | 
					      let path = this.$route.path + base
 | 
				
			||||||
          this.checkConflict(result, this.req.items, base)
 | 
					      let items = this.req.items
 | 
				
			||||||
        })
 | 
					
 | 
				
			||||||
      } else {
 | 
					      if (base !== '') {
 | 
				
			||||||
        this.scanFiles(dt).then((result) => {
 | 
					        try {
 | 
				
			||||||
          api.fetch(this.$route.path + base)
 | 
					          items = (await api.fetch(path)).items
 | 
				
			||||||
            .then(req => {
 | 
					        } catch (error) {
 | 
				
			||||||
                this.checkConflict(result, req.items, base)
 | 
					          this.$showError(error)
 | 
				
			||||||
            })
 | 
					        }
 | 
				
			||||||
            .catch(this.$showError)
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    checkConflict (files, items, base) {
 | 
					 | 
				
			||||||
      if (typeof items === 'undefined' || items === null) {
 | 
					 | 
				
			||||||
        items = []
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      let folder_upload = false
 | 
					      let conflict = upload.checkConflict(files, items)
 | 
				
			||||||
      if (files[0].fullPath !== undefined) {
 | 
					 | 
				
			||||||
        folder_upload = true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      let conflict = false
 | 
					      if (conflict) {
 | 
				
			||||||
      for (let i = 0; i < files.length; i++) {
 | 
					        this.$store.commit('showHover', {
 | 
				
			||||||
        let file = files[i]
 | 
					          prompt: 'replace',
 | 
				
			||||||
        let name = file.name
 | 
					          confirm: (event) => {
 | 
				
			||||||
 | 
					            event.preventDefault()
 | 
				
			||||||
        if (folder_upload) {
 | 
					            this.$store.commit('closeHovers')
 | 
				
			||||||
          let dirs = file.fullPath.split("/")
 | 
					            upload.handleFiles(files, path, true)
 | 
				
			||||||
          if (dirs.length > 1) {
 | 
					 | 
				
			||||||
            name = dirs[0]
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let res = items.findIndex(function hasConflict (element) {
 | 
					 | 
				
			||||||
          return (element.name === this)
 | 
					 | 
				
			||||||
        }, name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (res >= 0) {
 | 
					 | 
				
			||||||
          conflict = true
 | 
					 | 
				
			||||||
          break
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!conflict) {
 | 
					 | 
				
			||||||
        this.handleFiles(files, base)
 | 
					 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.$store.commit('showHover', {
 | 
					      upload.handleFiles(files, path)
 | 
				
			||||||
        prompt: 'replace',
 | 
					 | 
				
			||||||
        confirm: (event) => {
 | 
					 | 
				
			||||||
          event.preventDefault()
 | 
					 | 
				
			||||||
          this.$store.commit('closeHovers')
 | 
					 | 
				
			||||||
          this.handleFiles(files, base, true)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    uploadInput (event) {
 | 
					    uploadInput (event) {
 | 
				
			||||||
      this.$store.commit('closeHovers')
 | 
					      this.$store.commit('closeHovers')
 | 
				
			||||||
| 
						 | 
					@ -404,7 +365,22 @@ export default {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.checkConflict(files, this.req.items, '')
 | 
					      let path = this.$route.path
 | 
				
			||||||
 | 
					      let conflict = upload.checkConflict(files, this.req.items)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (conflict) {
 | 
				
			||||||
 | 
					        this.$store.commit('showHover', {
 | 
				
			||||||
 | 
					          prompt: 'replace',
 | 
				
			||||||
 | 
					          confirm: (event) => {
 | 
				
			||||||
 | 
					            event.preventDefault()
 | 
				
			||||||
 | 
					            this.$store.commit('closeHovers')
 | 
				
			||||||
 | 
					            this.handleFiles(files, path, true)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      upload.handleFiles(files, path)
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    resetOpacity () {
 | 
					    resetOpacity () {
 | 
				
			||||||
      let items = document.getElementsByClassName('item')
 | 
					      let items = document.getElementsByClassName('item')
 | 
				
			||||||
| 
						 | 
					@ -413,145 +389,6 @@ export default {
 | 
				
			||||||
        file.style.opacity = 1
 | 
					        file.style.opacity = 1
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    scanFiles(dt) {
 | 
					 | 
				
			||||||
        return new Promise((resolve) => {
 | 
					 | 
				
			||||||
            let reading = 0
 | 
					 | 
				
			||||||
            const contents = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (dt.items !== undefined) {
 | 
					 | 
				
			||||||
              for (let item of dt.items) {
 | 
					 | 
				
			||||||
                if (item.kind === "file" && typeof item.webkitGetAsEntry === "function") {
 | 
					 | 
				
			||||||
                  const entry = item.webkitGetAsEntry()
 | 
					 | 
				
			||||||
                  readEntry(entry)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
              resolve(dt.files)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            function readEntry(entry, directory = "") {
 | 
					 | 
				
			||||||
                if (entry.isFile) {
 | 
					 | 
				
			||||||
                    reading++
 | 
					 | 
				
			||||||
                    entry.file(file => {
 | 
					 | 
				
			||||||
                        reading--
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        file.fullPath = `${directory}${file.name}`
 | 
					 | 
				
			||||||
                        contents.push(file)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if (reading === 0) {
 | 
					 | 
				
			||||||
                            resolve(contents)
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                } else if (entry.isDirectory) {
 | 
					 | 
				
			||||||
                    const dir = {
 | 
					 | 
				
			||||||
                      isDir: true,
 | 
					 | 
				
			||||||
                      path: `${directory}${entry.name}`
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    contents.push(dir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    readReaderContent(entry.createReader(), `${directory}${entry.name}`)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            function readReaderContent(reader, directory) {
 | 
					 | 
				
			||||||
                reading++
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                reader.readEntries(function (entries) {
 | 
					 | 
				
			||||||
                    reading--
 | 
					 | 
				
			||||||
                    if (entries.length > 0) {
 | 
					 | 
				
			||||||
                        for (const entry of entries) {
 | 
					 | 
				
			||||||
                            readEntry(entry, `${directory}/`)
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        readReaderContent(reader, `${directory}/`)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (reading === 0) {
 | 
					 | 
				
			||||||
                        resolve(contents)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    setProgress: throttle(function() {
 | 
					 | 
				
			||||||
      if (this.uploading.count == 0) {
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      let sum = this.uploading.progress.reduce((acc, val) => acc + val)
 | 
					 | 
				
			||||||
      this.$store.commit('setProgress', Math.ceil(sum / this.uploading.size * 100))
 | 
					 | 
				
			||||||
    }, 100, {leading: false, trailing: true}),
 | 
					 | 
				
			||||||
    handleFiles (files, base, overwrite = false) {
 | 
					 | 
				
			||||||
      if (this.uploading.count == 0) {
 | 
					 | 
				
			||||||
        buttons.loading('upload')
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      let promises = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      let onupload = (id) => (event) => {
 | 
					 | 
				
			||||||
        this.uploading.progress[id] = event.loaded
 | 
					 | 
				
			||||||
        this.setProgress()
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for (let i = 0; i < files.length; i++) {
 | 
					 | 
				
			||||||
        let file = files[i]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!file.isDir) {
 | 
					 | 
				
			||||||
          let filename = (file.fullPath !== undefined) ? file.fullPath : file.name
 | 
					 | 
				
			||||||
          let filenameEncoded = url.encodeRFC5987ValueChars(filename)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          let id = this.uploading.id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          this.uploading.size += file.size
 | 
					 | 
				
			||||||
          this.uploading.id++
 | 
					 | 
				
			||||||
          this.uploading.count++
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          let promise = api.post(this.$route.path + base + filenameEncoded, file, overwrite, throttle(onupload(id), 100)).finally(() => {            
 | 
					 | 
				
			||||||
            this.uploading.count--
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          promises.push(promise)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          let uri = this.$route.path + base
 | 
					 | 
				
			||||||
          let folders = file.path.split("/")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          for (let i = 0; i < folders.length; i++) {
 | 
					 | 
				
			||||||
            let folder = folders[i]
 | 
					 | 
				
			||||||
            let folderEncoded = encodeURIComponent(folder)
 | 
					 | 
				
			||||||
            uri += folderEncoded + "/"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          api.post(uri)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      let finish = () => {
 | 
					 | 
				
			||||||
        if (this.uploading.count > 0) {
 | 
					 | 
				
			||||||
          return
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        buttons.success('upload')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.$store.commit('setProgress', 0)
 | 
					 | 
				
			||||||
        this.$store.commit('setReload', true)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.uploading.id = 0
 | 
					 | 
				
			||||||
        this.uploading.sizes = []
 | 
					 | 
				
			||||||
        this.uploading.progress = []        
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Promise.all(promises)
 | 
					 | 
				
			||||||
        .then(() => {
 | 
					 | 
				
			||||||
          finish()
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .catch(error => {
 | 
					 | 
				
			||||||
          finish()
 | 
					 | 
				
			||||||
          this.$showError(error)
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return false
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    async sort (by) {
 | 
					    async sort (by) {
 | 
				
			||||||
      let asc = false
 | 
					      let asc = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,15 @@ const getters = {
 | 
				
			||||||
  isFiles: state => !state.loading && state.route.name === 'Files',
 | 
					  isFiles: state => !state.loading && state.route.name === 'Files',
 | 
				
			||||||
  isListing: (state, getters) => getters.isFiles && state.req.isDir,
 | 
					  isListing: (state, getters) => getters.isFiles && state.req.isDir,
 | 
				
			||||||
  isEditor: (state, getters) => getters.isFiles && (state.req.type === 'text' || state.req.type === 'textImmutable'),
 | 
					  isEditor: (state, getters) => getters.isFiles && (state.req.type === 'text' || state.req.type === 'textImmutable'),
 | 
				
			||||||
  selectedCount: state => state.selected.length
 | 
					  selectedCount: state => state.selected.length,
 | 
				
			||||||
 | 
					  progress : state => {
 | 
				
			||||||
 | 
					    if (state.upload.progress.length == 0) {
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let sum = state.upload.progress.reduce((acc, val) => acc + val)
 | 
				
			||||||
 | 
					    return Math.ceil(sum / state.upload.size * 100);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default getters
 | 
					export default getters
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import Vue from 'vue'
 | 
				
			||||||
import Vuex from 'vuex'
 | 
					import Vuex from 'vuex'
 | 
				
			||||||
import mutations from './mutations'
 | 
					import mutations from './mutations'
 | 
				
			||||||
import getters from './getters'
 | 
					import getters from './getters'
 | 
				
			||||||
 | 
					import upload from './modules/upload'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.use(Vuex)
 | 
					Vue.use(Vuex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,5 +30,6 @@ export default new Vuex.Store({
 | 
				
			||||||
  strict: true,
 | 
					  strict: true,
 | 
				
			||||||
  state,
 | 
					  state,
 | 
				
			||||||
  getters,
 | 
					  getters,
 | 
				
			||||||
  mutations
 | 
					  mutations,
 | 
				
			||||||
 | 
					  modules: { upload }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,95 @@
 | 
				
			||||||
 | 
					import Vue from 'vue'
 | 
				
			||||||
 | 
					import { files as api } from '@/api'
 | 
				
			||||||
 | 
					import throttle from 'lodash.throttle'
 | 
				
			||||||
 | 
					import buttons from '@/utils/buttons'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const UPLOADS_LIMIT = 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const state = {
 | 
				
			||||||
 | 
					  id: 0,
 | 
				
			||||||
 | 
					  size: 0,
 | 
				
			||||||
 | 
					  progress: [],
 | 
				
			||||||
 | 
					  queue: [],
 | 
				
			||||||
 | 
					  uploads: {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const mutations = {
 | 
				
			||||||
 | 
					  setProgress(state, { id, loaded }) {
 | 
				
			||||||
 | 
					    Vue.set(state.progress, id, loaded)
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  reset: (state) => {
 | 
				
			||||||
 | 
					    state.id = 0
 | 
				
			||||||
 | 
					    state.size = 0
 | 
				
			||||||
 | 
					    state.progress = []
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  addJob: (state, item) => {
 | 
				
			||||||
 | 
					    state.queue.push(item)
 | 
				
			||||||
 | 
					    state.size += item.file.size
 | 
				
			||||||
 | 
					    state.id++
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  moveJob(state) {
 | 
				
			||||||
 | 
					    const item = state.queue[0]
 | 
				
			||||||
 | 
					    state.queue.shift()
 | 
				
			||||||
 | 
					    Vue.set(state.uploads, item.id, item)
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  removeJob(state, id) {
 | 
				
			||||||
 | 
					    delete state.uploads[id]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const actions = {
 | 
				
			||||||
 | 
					  upload: (context, item) => {
 | 
				
			||||||
 | 
					    let uploadsCount = Object.keys(context.state.uploads).length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let isQueueEmpty = context.state.queue.length == 0
 | 
				
			||||||
 | 
					    let isUploadsEmpty = uploadsCount == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isQueueEmpty && isUploadsEmpty) {
 | 
				
			||||||
 | 
					      buttons.loading('upload')
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context.commit('addJob', item)
 | 
				
			||||||
 | 
					    context.dispatch('processUploads')
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  finishUpload: (context, item) => {
 | 
				
			||||||
 | 
					    context.commit('setProgress', { id: item.id, loaded: item.file.size })
 | 
				
			||||||
 | 
					    context.commit('removeJob', item.id)
 | 
				
			||||||
 | 
					    context.dispatch('processUploads')
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  processUploads: async (context) => {
 | 
				
			||||||
 | 
					    let uploadsCount = Object.keys(context.state.uploads).length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let isBellowLimit = uploadsCount < UPLOADS_LIMIT
 | 
				
			||||||
 | 
					    let isQueueEmpty = context.state.queue.length == 0
 | 
				
			||||||
 | 
					    let isUploadsEmpty = uploadsCount == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let isFinished = isQueueEmpty && isUploadsEmpty
 | 
				
			||||||
 | 
					    let canProcess = isBellowLimit && !isQueueEmpty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isFinished) {
 | 
				
			||||||
 | 
					      buttons.success('upload')
 | 
				
			||||||
 | 
					      context.commit('reset')
 | 
				
			||||||
 | 
					      context.commit('setReload', true, { root: true })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (canProcess) {
 | 
				
			||||||
 | 
					      const item = context.state.queue[0];
 | 
				
			||||||
 | 
					      context.commit('moveJob')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (item.file.isDir) {
 | 
				
			||||||
 | 
					        await api.post(item.path).catch(Vue.prototype.$showError)
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        let onUpload = throttle(
 | 
				
			||||||
 | 
					          (event) => context.commit('setProgress', { id: item.id, loaded: event.loaded }),
 | 
				
			||||||
 | 
					          100, { leading: true, trailing: false }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await api.post(item.path, item.file, item.overwrite, onUpload).catch(Vue.prototype.$showError)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      context.dispatch('finishUpload', item)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default { state, mutations, actions, namespaced: true }
 | 
				
			||||||
| 
						 | 
					@ -82,9 +82,6 @@ const mutations = {
 | 
				
			||||||
  resetClipboard: (state) => {
 | 
					  resetClipboard: (state) => {
 | 
				
			||||||
    state.clipboard.key = ''
 | 
					    state.clipboard.key = ''
 | 
				
			||||||
    state.clipboard.items = []
 | 
					    state.clipboard.items = []
 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  setProgress: (state, value) => {
 | 
					 | 
				
			||||||
    state.progress = value
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,133 @@
 | 
				
			||||||
 | 
					import store from '@/store'
 | 
				
			||||||
 | 
					import url from '@/utils/url'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function checkConflict(files, items) {
 | 
				
			||||||
 | 
					  if (typeof items === 'undefined' || items === null) {
 | 
				
			||||||
 | 
					    items = []
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let folder_upload = false
 | 
				
			||||||
 | 
					  if (files[0].fullPath !== undefined) {
 | 
				
			||||||
 | 
					    folder_upload = true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let conflict = false
 | 
				
			||||||
 | 
					  for (let i = 0; i < files.length; i++) {
 | 
				
			||||||
 | 
					    let file = files[i]
 | 
				
			||||||
 | 
					    let name = file.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (folder_upload) {
 | 
				
			||||||
 | 
					      let dirs = file.fullPath.split("/")
 | 
				
			||||||
 | 
					      if (dirs.length > 1) {
 | 
				
			||||||
 | 
					        name = dirs[0]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let res = items.findIndex(function hasConflict(element) {
 | 
				
			||||||
 | 
					      return (element.name === this)
 | 
				
			||||||
 | 
					    }, name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (res >= 0) {
 | 
				
			||||||
 | 
					      conflict = true
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return conflict
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function scanFiles(dt) {
 | 
				
			||||||
 | 
					  return new Promise((resolve) => {
 | 
				
			||||||
 | 
					    let reading = 0
 | 
				
			||||||
 | 
					    const contents = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dt.items !== undefined) {
 | 
				
			||||||
 | 
					      for (let item of dt.items) {
 | 
				
			||||||
 | 
					        if (item.kind === "file" && typeof item.webkitGetAsEntry === "function") {
 | 
				
			||||||
 | 
					          const entry = item.webkitGetAsEntry()
 | 
				
			||||||
 | 
					          readEntry(entry)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      resolve(dt.files)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function readEntry(entry, directory = "") {
 | 
				
			||||||
 | 
					      if (entry.isFile) {
 | 
				
			||||||
 | 
					        reading++
 | 
				
			||||||
 | 
					        entry.file(file => {
 | 
				
			||||||
 | 
					          reading--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          file.fullPath = `${directory}${file.name}`
 | 
				
			||||||
 | 
					          contents.push(file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (reading === 0) {
 | 
				
			||||||
 | 
					            resolve(contents)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      } else if (entry.isDirectory) {
 | 
				
			||||||
 | 
					        const dir = {
 | 
				
			||||||
 | 
					          isDir: true,
 | 
				
			||||||
 | 
					          size: 0,
 | 
				
			||||||
 | 
					          path: `${directory}${entry.name}`
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        contents.push(dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        readReaderContent(entry.createReader(), `${directory}${entry.name}`)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function readReaderContent(reader, directory) {
 | 
				
			||||||
 | 
					      reading++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      reader.readEntries(function (entries) {
 | 
				
			||||||
 | 
					        reading--
 | 
				
			||||||
 | 
					        if (entries.length > 0) {
 | 
				
			||||||
 | 
					          for (const entry of entries) {
 | 
				
			||||||
 | 
					            readEntry(entry, `${directory}/`)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          readReaderContent(reader, `${directory}/`)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (reading === 0) {
 | 
				
			||||||
 | 
					          resolve(contents)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function handleFiles(files, path, overwrite = false) {
 | 
				
			||||||
 | 
					  for (let i = 0; i < files.length; i++) {
 | 
				
			||||||
 | 
					    let file = files[i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let filename = (file.fullPath !== undefined) ? file.fullPath : file.name
 | 
				
			||||||
 | 
					    let filenameEncoded = url.encodeRFC5987ValueChars(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let id = store.state.upload.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let itemPath = path + filenameEncoded
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (file.isDir) {
 | 
				
			||||||
 | 
					      itemPath = path
 | 
				
			||||||
 | 
					      let folders = file.path.split("/")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (let i = 0; i < folders.length; i++) {
 | 
				
			||||||
 | 
					        let folder = folders[i]
 | 
				
			||||||
 | 
					        let folderEncoded = encodeURIComponent(folder)
 | 
				
			||||||
 | 
					        itemPath += folderEncoded + "/"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const item = {
 | 
				
			||||||
 | 
					      id,
 | 
				
			||||||
 | 
					      path: itemPath,
 | 
				
			||||||
 | 
					      file,
 | 
				
			||||||
 | 
					      overwrite
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    store.dispatch('upload/upload', item);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div>
 | 
					  <div>
 | 
				
			||||||
    <div id="progress">
 | 
					    <div id="progress">
 | 
				
			||||||
      <div v-bind:style="{ width: $store.state.progress + '%' }"></div>
 | 
					      <div v-bind:style="{ width: this.progress + '%' }"></div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <site-header></site-header>
 | 
					    <site-header></site-header>
 | 
				
			||||||
    <sidebar></sidebar>
 | 
					    <sidebar></sidebar>
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ export default {
 | 
				
			||||||
    Shell
 | 
					    Shell
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    ...mapGetters([ 'isLogged' ]),
 | 
					    ...mapGetters([ 'isLogged', 'progress' ]),
 | 
				
			||||||
    ...mapState([ 'user' ])
 | 
					    ...mapState([ 'user' ])
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  watch: {
 | 
					  watch: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue