funkwhale/front/src/components/library/import/BatchDetail.vue

238 lines
6.8 KiB
Vue

<template>
<div v-title="'Import Batch #' + id">
<div v-if="isLoading && !batch" class="ui vertical segment">
<div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
</div>
<div v-if="batch" class="ui vertical stripe segment">
<table class="ui very basic table">
<tbody>
<tr>
<td>
<strong>{{ $t('Import batch') }}</strong>
</td>
<td>
#{{ batch.id }}
</td>
</tr>
<tr>
<td>
<strong>{{ $t('Launch date') }}</strong>
</td>
<td>
<human-date :date="batch.creation_date"></human-date>
</td>
</tr>
<tr v-if="batch.user">
<td>
<strong>{{ $t('Submitted by') }}</strong>
</td>
<td>
<username :username="batch.user.username" />
</td>
</tr>
<tr v-if="stats">
<td><strong>{{ $t('Pending') }}</strong></td>
<td>{{ stats.pending }}</td>
</tr>
<tr v-if="stats">
<td><strong>{{ $t('Skipped') }}</strong></td>
<td>{{ stats.skipped }}</td>
</tr>
<tr v-if="stats">
<td><strong>{{ $t('Errored') }}</strong></td>
<td>{{ stats.errored }}</td>
</tr>
<tr v-if="stats">
<td><strong>{{ $t('Finished') }}</strong></td>
<td>{{ stats.finished }}/{{ stats.count}}</td>
</tr>
</tbody>
</table>
<div class="ui inline form">
<div class="fields">
<div class="ui field">
<label>{{ $t('Search') }}</label>
<input type="text" v-model="jobFilters.search" placeholder="Search by source..." />
</div>
<div class="ui field">
<label>{{ $t('Status') }}</label>
<select class="ui dropdown" v-model="jobFilters.status">
<option :value="null">{{ $t('Any') }}</option>
<option :value="'pending'">{{ $t('Pending') }}</option>
<option :value="'errored'">{{ $t('Errored') }}</option>
<option :value="'finished'">{{ $t('Success') }}</option>
<option :value="'skipped'">{{ $t('Skipped') }}</option>
</select>
</div>
</div>
</div>
<table v-if="jobResult" class="ui unstackable table">
<thead>
<tr>
<th>{{ $t('Job ID') }}</th>
<th>{{ $t('Recording MusicBrainz ID') }}</th>
<th>{{ $t('Source') }}</th>
<th>{{ $t('Status') }}</th>
<th>{{ $t('Track') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="job in jobResult.results">
<td>{{ job.id }}</th>
<td>
<a :href="'https://www.musicbrainz.org/recording/' + job.mbid" target="_blank">{{ job.mbid }}</a>
</td>
<td>
<a :href="job.source" target="_blank">{{ job.source }}</a>
</td>
<td>
<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>
</td>
</tr>
</tbody>
<tfoot class="full-width">
<tr>
<th>
<pagination
v-if="jobResult && jobResult.results.length > 0"
@page-changed="selectPage"
:compact="true"
:current="jobFilters.page"
:paginate-by="jobFilters.paginateBy"
:total="jobResult.count"
></pagination>
</th>
<th v-if="jobResult && jobResult.results.length > 0">
{{ $t('Showing results {%start%}-{%end%} on {%total%}', {start: ((jobFilters.page-1) * jobFilters.paginateBy) + 1 , end: ((jobFilters.page-1) * jobFilters.paginateBy) + jobResult.results.length, total: jobResult.count})}}
<th>
<th></th>
<th></th>
<th></th>
</tr>
</tfoot>
</table>
</div>
</div>
</template>
<script>
import _ from 'lodash'
import axios from 'axios'
import logger from '@/logging'
import Pagination from '@/components/Pagination'
export default {
props: ['id'],
components: {
Pagination
},
data () {
return {
isLoading: true,
batch: null,
stats: null,
jobResult: null,
timeout: null,
jobFilters: {
status: null,
source: null,
search: '',
paginateBy: 25,
page: 1
}
}
},
created () {
let self = this
this.fetchData().then(() => {
self.fetchJobs()
self.fetchStats()
})
},
destroyed () {
if (this.timeout) {
clearTimeout(this.timeout)
}
},
methods: {
fetchData () {
var self = this
this.isLoading = true
let url = 'import-batches/' + this.id + '/'
logger.default.debug('Fetching batch "' + this.id + '"')
return axios.get(url).then((response) => {
self.batch = response.data
self.isLoading = false
if (self.batch.status === 'pending') {
self.timeout = setTimeout(
self.fetchData,
5000
)
}
})
},
fetchStats () {
var self = this
let url = 'import-jobs/stats/'
axios.get(url, {params: {batch: self.id}}).then((response) => {
let old = self.stats
self.stats = response.data
self.isLoading = false
if (!_.isEqual(old, self.stats)) {
self.fetchJobs()
self.fetchData()
}
if (self.batch.status === 'pending') {
self.timeout = setTimeout(
self.fetchStats,
5000
)
}
})
},
fetchJobs () {
let params = {
batch: this.id,
page_size: this.jobFilters.paginateBy,
page: this.jobFilters.page,
q: this.jobFilters.search
}
if (this.jobFilters.status) {
params.status = this.jobFilters.status
}
if (this.jobFilters.source) {
params.source = this.jobFilters.source
}
let self = this
axios.get('import-jobs/', {params}).then((response) => {
self.jobResult = response.data
})
},
selectPage: function (page) {
this.jobFilters.page = page
}
},
watch: {
id () {
this.fetchData()
},
jobFilters: {
handler () {
this.fetchJobs()
},
deep: true
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>