Skip to content
Snippets Groups Projects
BatchDetail.vue 8.19 KiB
Newer Older
  • Learn to ignore specific revisions
  • Eliot Berriot's avatar
    Eliot Berriot committed
      <div v-title="labels.title">
    
        <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><translate>Import batch</translate></strong>
    
                  <strong><translate>Launch date</translate></strong>
    
                </td>
                <td>
                  <human-date :date="batch.creation_date"></human-date>
                </td>
              </tr>
              <tr v-if="batch.user">
                <td>
    
                  <strong><translate>Submitted by</translate></strong>
    
                </td>
                <td>
                  <username :username="batch.user.username" />
                </td>
              </tr>
              <tr v-if="stats">
    
                <td><strong><translate>Pending</translate></strong></td>
    
                <td>{{ stats.pending }}</td>
              </tr>
              <tr v-if="stats">
    
                <td><strong><translate>Skipped</translate></strong></td>
    
                <td>{{ stats.skipped }}</td>
              </tr>
              <tr v-if="stats">
    
                <td><strong><translate>Errored</translate></strong></td>
    
                <td>
                  {{ stats.errored }}
                  <button
                    @click="rerun({batches: [batch.id], jobs: []})"
                    v-if="stats.errored > 0"
                    class="ui tiny basic icon button">
                    <i class="redo icon" />
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    <translate>Rerun errored jobs</translate>
    
                <td><strong><translate>Finished</translate></strong></td>
    
                <td>{{ stats.finished }}/{{ stats.count}}</td>
              </tr>
            </tbody>
          </table>
          <div class="ui inline form">
            <div class="fields">
              <div class="ui field">
    
                <label><translate>Search</translate></label>
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                <input type="text" v-model="jobFilters.search" :placeholder="labels.searchPlaceholder" />
    
                <label><translate>Status</translate></label>
    
                <select class="ui dropdown" v-model="jobFilters.status">
    
                  <option :value="null"><translate>Any</translate></option>
                  <option :value="'pending'"><translate>Pending</translate></option>
                  <option :value="'errored'"><translate>Errored</translate></option>
                  <option :value="'finished'"><translate>Success</translate></option>
                  <option :value="'skipped'"><translate>Skipped</translate></option>
    
          <table v-if="jobResult" class="ui unstackable table">
    
                <th><translate>Job ID</translate></th>
                <th><translate>Recording MusicBrainz ID</translate></th>
                <th><translate>Source</translate></th>
                <th><translate>Status</translate></th>
                <th><translate>Track</translate></th>
    
              <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 :title="job.source" :href="job.source" target="_blank">
                    {{ job.source|truncate(50) }}
                  </a>
    
                    :class="['ui', {'yellow': job.status === 'pending'}, {'red': job.status === 'errored'}, {'green': job.status === 'finished'}, 'label']">
                    {{ job.status }}</span>
                    <button
                      @click="rerun({batches: [], jobs: [job.id]})"
                      v-if="job.status === 'errored'"
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                      :title="labels.rerun"
    
                      class="ui tiny basic icon button">
                      <i class="redo icon" />
                    </button>
    
                <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>
    
            <tfoot class="full-width">
              <tr>
                <th>
                  <pagination
    
                  v-if="jobResult && jobResult.count > jobFilters.paginateBy"
    
                  @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">
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                  <translate
                    :translate-params="{start: ((jobFilters.page-1) * jobFilters.paginateBy) + 1, end: ((jobFilters.page-1) * jobFilters.paginateBy) + jobResult.results.length, total: jobResult.count}">
                    Showing results %{ start }-%{ end } on %{ total }
                  </translate>
    
    import axios from 'axios'
    
    import Pagination from '@/components/Pagination'
    
          stats: null,
          jobResult: null,
          timeout: null,
          jobFilters: {
            status: null,
            source: null,
            search: '',
            paginateBy: 25,
            page: 1
          }
    
        let self = this
        this.fetchData().then(() => {
          self.fetchJobs()
          self.fetchStats()
        })
    
      destroyed () {
        if (this.timeout) {
          clearTimeout(this.timeout)
        }
      },
    
    Eliot Berriot's avatar
    Eliot Berriot committed
      computed: {
        labels () {
          let msg = this.$gettext('Import Batch #%{ id }')
          let title = this.$gettextInterpolate(msg, {id: this.id})
          let rerun = this.$gettext('Rerun job')
          let searchPlaceholder = this.$gettext('Search by source...')
          return {
            title,
            searchPlaceholder,
            rerun
          }
        }
      },
    
      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
          })
        },
    
        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.stats.pending > 0) {
    
              self.timeout = setTimeout(
                self.fetchStats,
                5000
              )
            }
          })
        },
    
        rerun ({jobs, batches}) {
          let payload = {
            jobs, batches
          }
          let self = this
          axios.post('import-jobs/run/', payload).then((response) => {
            self.fetchStats()
          })
        },
    
        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
    
        },
        jobFilters: {
          handler () {
            this.fetchJobs()
          },
          deep: true
    
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped lang="scss">
    
    </style>