Skip to content
Snippets Groups Projects
Builder.vue 6.31 KiB
Newer Older
  • Learn to ignore specific revisions
  • <template>
    
    Bat's avatar
    Bat committed
      <div class="ui vertical stripe segment" v-title="'Radio Builder'">
    
        <div>
          <div>
    
    Bat's avatar
    Bat committed
            <h2 class="ui header"><i18next path="Builder"/></h2>
            <i18next tag="p" path="You can use this interface to build your own custom radio, which will play tracks according to your criteria"/>
              <div class="ui form">
    
              <div class="inline fields">
                <div class="field">
    
    Bat's avatar
    Bat committed
                  <i18next tag="label" for="name" path="Radio name"/>
    
                  <input id="name" type="text" v-model="radioName" placeholder="My awesome radio" />
                </div>
                <div class="field">
                  <input id="public" type="checkbox" v-model="isPublic" />
    
    Bat's avatar
    Bat committed
                  <i18next tag="label" for="public" path="Display publicly"/>
    
                </div>
    
    Bat's avatar
    Bat committed
                <button :disabled="!canSave" @click="save" class="ui green button"><i18ext path="Save"/></button>
    
                <radio-button v-if="id" type="custom" :custom-radio-id="id"></radio-button>
              </div>
            </div>
            <div class="ui form">
    
    Bat's avatar
    Bat committed
              <p><i18next path="Add filters to customize your radio"/></p>
    
              <div class="inline field">
                <select class="ui dropdown" v-model="currentFilterType">
    
    Bat's avatar
    Bat committed
                  <option value=""><i18next path="Select a filter"/></option>
    
                  <option v-for="f in availableFilters" :value="f.type">{{ f.label }}</option>
                </select>
    
    Bat's avatar
    Bat committed
                <button :disabled="!currentFilterType" @click="add" class="ui button"><i18next path="Add filter"/></button>
    
              </div>
              <p v-if="currentFilter">
                {{ currentFilter.help_text }}
              </p>
            </div>
            <table class="ui table">
              <thead>
                <tr>
    
    Bat's avatar
    Bat committed
                  <i18next tag="th" class="two wide" path="Filter name"/>
                  <i18next tag="th" class="one wide" path="Exclude"/>
                  <i18next tag="th" class="six wide" path="Config"/>
                  <i18next tag="th" class="five wide" path="Candidates"/>
                  <i18next tag="th" class="two wide" path="Actions"/>
    
                </tr>
              </thead>
              <tbody>
                <builder-filter
                  v-for="(f, index) in filters"
                  :key="(f, index, f.hash)"
                  :index="index"
                  @update-config="updateConfig"
                  @delete="deleteFilter"
                  :config="f.config"
                  :filter="f.filter">
                </builder-filter>
              </tbody>
            </table>
            <template v-if="checkResult">
    
    Bat's avatar
    Bat committed
              <i18next tag="h3" class="ui header" path="{%0%} tracks matching combined filters">
                {{ checkResult.candidates.count }}
              </i18next>
    
              <track-table v-if="checkResult.candidates.sample" :tracks="checkResult.candidates.sample"></track-table>
            </template>
          </div>
        </div>
      </div>
    </template>
    <script>
    
    import axios from 'axios'
    
    import $ from 'jquery'
    import _ from 'lodash'
    import BuilderFilter from './Filter'
    import TrackTable from '@/components/audio/track/Table'
    import RadioButton from '@/components/radios/Button'
    
    export default {
      props: {
        id: {required: false}
      },
      components: {
        BuilderFilter,
        TrackTable,
        RadioButton
      },
      data: function () {
        return {
          availableFilters: [],
          currentFilterType: null,
          filters: [],
          checkResult: null,
          radioName: '',
          isPublic: true
        }
      },
      created: function () {
        let self = this
        this.fetchFilters().then(() => {
          if (self.id) {
            self.fetch()
          }
        })
      },
      mounted () {
        $('.ui.dropdown').dropdown()
      },
      methods: {
        fetchFilters: function () {
          let self = this
    
          let url = 'radios/radios/filters/'
          return axios.get(url).then((response) => {
    
            self.availableFilters = response.data
          })
        },
        add () {
          this.filters.push({
            config: {},
            filter: this.currentFilter,
            hash: +new Date()
          })
          this.fetchCandidates()
        },
        updateConfig (index, field, value) {
          this.filters[index].config[field] = value
          this.fetchCandidates()
        },
        deleteFilter (index) {
          this.filters.splice(index, 1)
          this.fetchCandidates()
        },
        fetch: function () {
          let self = this
    
          let url = 'radios/radios/' + this.id + '/'
          axios.get(url).then((response) => {
    
            self.filters = response.data.config.map(f => {
              return {
                config: f,
                filter: this.availableFilters.filter(e => { return e.type === f.type })[0],
                hash: +new Date()
              }
            })
            self.radioName = response.data.name
            self.isPublic = response.data.is_public
          })
        },
        fetchCandidates: function () {
          let self = this
    
          let url = 'radios/radios/validate/'
    
          let final = this.filters.map(f => {
            let c = _.clone(f.config)
            c.type = f.filter.type
            return c
          })
          final = {
            'filters': [
              {'type': 'group', filters: final}
            ]
          }
    
          axios.post(url, final).then((response) => {
    
            self.checkResult = response.data.filters[0]
          })
        },
        save: function () {
          let self = this
          let final = this.filters.map(f => {
            let c = _.clone(f.config)
            c.type = f.filter.type
            return c
          })
          final = {
            'name': this.radioName,
            'is_public': this.isPublic,
            'config': final
          }
          if (this.id) {
    
            let url = 'radios/radios/' + this.id + '/'
            axios.put(url, final).then((response) => {
    
            })
          } else {
    
            let url = 'radios/radios/'
            axios.post(url, final).then((response) => {
    
              self.$router.push({
    
    Bat's avatar
    Bat committed
                name: 'library.radios.detail',
    
                params: {
                  id: response.data.id
                }
              })
            })
          }
        }
      },
      computed: {
        canSave: function () {
          return (
            this.radioName.length > 0 && this.checkErrors.length === 0
          )
        },
        checkErrors: function () {
          if (!this.checkResult) {
            return []
          }
          let errors = this.checkResult.errors
          return errors
        },
        currentFilter: function () {
          let self = this
          return this.availableFilters.filter(e => {
            return e.type === self.currentFilterType
          })[0]
        }
      },
      watch: {
        filters: {
          handler: function () {
            this.fetchCandidates()
          },
          deep: true
        }
      }
    }
    </script>