Brand new file importer
This commit is contained in:
parent
2e616282fd
commit
1c8f055490
16 changed files with 302 additions and 15 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 () {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
140
front/src/components/library/import/FileUpload.vue
Normal file
140
front/src/components/library/import/FileUpload.vue
Normal 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>
|
||||
34
front/src/components/library/import/FileUploadWidget.vue
Normal file
34
front/src/components/library/import/FileUploadWidget.vue
Normal 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>
|
||||
|
|
@ -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: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue