Brand new file importer

This commit is contained in:
Eliot Berriot 2017-12-27 23:32:02 +01:00
commit 1c8f055490
No known key found for this signature in database
GPG key ID: DD6965E2476E5C27
16 changed files with 302 additions and 15 deletions

View file

@ -23,6 +23,7 @@
"vue-lazyload": "^1.1.4",
"vue-resource": "^1.3.4",
"vue-router": "^2.3.1",
"vue-upload-component": "^2.7.4",
"vuedraggable": "^2.14.1",
"vuex": "^3.0.1",
"vuex-persistedstate": "^2.4.2"

View file

@ -8,6 +8,7 @@
['ui',
{'active': batch.status === 'pending'},
{'warning': batch.status === 'pending'},
{'error': batch.status === 'errored'},
{'success': batch.status === 'finished'},
'progress']">
<div class="bar" :style="progressBarStyle">
@ -37,7 +38,7 @@
</td>
<td>
<span
:class="['ui', {'yellow': job.status === 'pending'}, {'green': job.status === 'finished'}, 'label']">{{ job.status }}</span>
:class="['ui', {'yellow': job.status === 'pending'}, {'red': job.status === 'errored'}, {'green': job.status === 'finished'}, 'label']">{{ job.status }}</span>
</td>
<td>
<router-link v-if="job.track_file" :to="{name: 'library.tracks.detail', params: {id: job.track_file.track }}">{{ job.track_file.track }}</router-link>
@ -89,7 +90,7 @@ export default {
computed: {
progress () {
return this.batch.jobs.filter(j => {
return j.status === 'finished'
return j.status !== 'pending'
}).length * 100 / this.batch.jobs.length
},
progressBarStyle () {

View file

@ -32,7 +32,7 @@
<td>{{ result.jobs.length }}</td>
<td>
<span
:class="['ui', {'yellow': result.status === 'pending'}, {'green': result.status === 'finished'}, 'label']">{{ result.status }}</span>
:class="['ui', {'yellow': result.status === 'pending'}, {'red': result.status === 'errored'}, {'green': result.status === 'finished'}, 'label']">{{ result.status }}</span>
</td>
</tr>
</tbody>

View file

@ -0,0 +1,140 @@
<template>
<div>
<div v-if="batch" class="ui two buttons">
<file-upload-widget
class="ui icon button"
:post-action="uploadUrl"
:multiple="true"
:size="1024 * 1024 * 30"
:data="uploadData"
:drop="true"
extensions="ogg,mp3"
accept="audio/*"
v-model="files"
name="audio_file"
:thread="3"
@input-filter="inputFilter"
@input-file="inputFile"
ref="upload">
<i class="upload icon"></i>
Select files to upload...
</file-upload-widget>
<button class="ui icon teal button" v-if="!$refs.upload || !$refs.upload.active" @click.prevent="$refs.upload.active = true">
<i class="play icon" aria-hidden="true"></i>
Start Upload
</button>
<button type="button" class="ui icon yellow button" v-else @click.prevent="$refs.upload.active = false">
<i class="pause icon" aria-hidden="true"></i>
Stop Upload
</button>
</div>
<div class="ui hidden divider"></div>
<p>
Once all your files are uploaded, simply head over <router-link :to="{name: 'library.import.batches.detail', params: {id: batch.id }}">import detail page</router-link> to check the import status.
</p>
<table class="ui single line table">
<thead>
<tr>
<th>File name</th>
<th>Size</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr v-for="(file, index) in files" :key="file.id">
<td>{{ file.name }}</td>
<td>{{ file.size }}</td>
<td>
<span v-if="file.error" class="ui red label">
{{ file.error }}
</span>
<span v-else-if="file.success" class="ui green label">Success</span>
<span v-else-if="file.active" class="ui yellow label">Uploading...</span>
<template v-else>
<span class="ui label">Pending</span>
<button class="ui tiny basic red icon button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button>
</template>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import Vue from 'vue'
import logger from '@/logging'
import FileUploadWidget from './FileUploadWidget'
import config from '@/config'
export default {
components: {
FileUploadWidget
},
data () {
return {
files: [],
uploadUrl: config.API_URL + 'import-jobs/',
batch: null
}
},
mounted: function () {
this.createBatch()
},
methods: {
inputFilter (newFile, oldFile, prevent) {
if (newFile && !oldFile) {
let extension = newFile.name.split('.').pop()
if (['ogg', 'mp3'].indexOf(extension) < 0) {
prevent()
}
}
},
inputFile (newFile, oldFile) {
if (newFile && !oldFile) {
// add
console.log('add', newFile)
if (!this.batch) {
this.createBatch()
}
}
if (newFile && oldFile) {
// update
console.log('update', newFile)
}
if (!newFile && oldFile) {
// remove
console.log('remove', oldFile)
}
},
createBatch () {
let self = this
let url = config.API_URL + 'import-batches/'
let resource = Vue.resource(url)
resource.save({}, {}).then((response) => {
self.batch = response.data
}, (response) => {
logger.default.error('error while launching creating batch')
})
}
},
computed: {
batchId: function () {
if (this.batch) {
return this.batch.id
}
return null
},
uploadData: function () {
return {
'batch': this.batchId,
'source': 'file://'
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View file

@ -0,0 +1,34 @@
<script>
import FileUpload from 'vue-upload-component'
export default {
extends: FileUpload,
methods: {
uploadHtml5 (file) {
let form = new window.FormData()
let value
for (let key in file.data) {
value = file.data[key]
if (value && typeof value === 'object' && typeof value.toString !== 'function') {
if (value instanceof File) {
form.append(key, value, value.name)
} else {
form.append(key, JSON.stringify(value))
}
} else if (value !== null && value !== undefined) {
form.append(key, value)
}
}
form.append(this.name, file.file, file.file.filename || file.name)
let xhr = new XMLHttpRequest()
xhr.open('POST', file.postAction)
xhr.setRequestHeader('Authorization', this.$store.getters['auth/header'])
return this.uploadXhr(xhr, file, form)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

View file

@ -39,8 +39,8 @@
</div>
</div>
<div class="field">
<div class="ui disabled radio checkbox">
<input type="radio" id="upload" value="upload" v-model="currentSource" disabled>
<div class="ui radio checkbox">
<input type="radio" id="upload" value="upload" v-model="currentSource">
<label for="upload">File upload</label>
</div>
</div>
@ -84,8 +84,14 @@
</div>
</div>
<div v-if="currentStep === 2">
<file-upload
ref="import"
v-if="currentSource == 'upload'"
></file-upload>
<component
ref="import"
v-if="currentSource == 'external'"
:metadata="metadata"
:is="importComponent"
:backends="backends"
@ -119,6 +125,7 @@ import MetadataSearch from '@/components/metadata/Search'
import ReleaseCard from '@/components/metadata/ReleaseCard'
import ArtistCard from '@/components/metadata/ArtistCard'
import ReleaseImport from './ReleaseImport'
import FileUpload from './FileUpload'
import ArtistImport from './ArtistImport'
import router from '@/router'
@ -130,7 +137,8 @@ export default {
ArtistCard,
ReleaseCard,
ArtistImport,
ReleaseImport
ReleaseImport,
FileUpload
},
props: {
mbType: {type: String, required: false},
@ -142,7 +150,7 @@ export default {
currentType: this.mbType || 'artist',
currentId: this.mbId,
currentStep: 0,
currentSource: this.source || 'external',
currentSource: '',
metadata: {},
isImporting: false,
importData: {