Frontend for custom radios
This commit is contained in:
parent
e7f0c1b88b
commit
07bff17e51
|
@ -3,6 +3,7 @@
|
||||||
<div class="ui secondary pointing menu">
|
<div class="ui secondary pointing menu">
|
||||||
<router-link class="ui item" to="/library" exact>Browse</router-link>
|
<router-link class="ui item" to="/library" exact>Browse</router-link>
|
||||||
<router-link class="ui item" to="/library/artists" exact>Artists</router-link>
|
<router-link class="ui item" to="/library/artists" exact>Artists</router-link>
|
||||||
|
<router-link class="ui item" to="/library/radios" exact>Radios</router-link>
|
||||||
<div class="ui secondary right menu">
|
<div class="ui secondary right menu">
|
||||||
<router-link v-if="$store.state.auth.availablePermissions['import.launch']" class="ui item" to="/library/import/launch" exact>Import</router-link>
|
<router-link v-if="$store.state.auth.availablePermissions['import.launch']" class="ui item" to="/library/import/launch" exact>Import</router-link>
|
||||||
<router-link v-if="$store.state.auth.availablePermissions['import.launch']" class="ui item" to="/library/import/batches">Import batches</router-link>
|
<router-link v-if="$store.state.auth.availablePermissions['import.launch']" class="ui item" to="/library/import/batches">Import batches</router-link>
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="ui vertical stripe segment">
|
||||||
|
<h2 class="ui header">Browsing radios</h2>
|
||||||
|
<router-link class="ui green basic button" to="/library/radios/build" exact>Create your own radio</router-link>
|
||||||
|
<div class="ui hidden divider"></div>
|
||||||
|
<div :class="['ui', {'loading': isLoading}, 'form']">
|
||||||
|
<div class="fields">
|
||||||
|
<div class="field">
|
||||||
|
<label>Search</label>
|
||||||
|
<input type="text" v-model="query" placeholder="Enter a radio name..."/>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Ordering</label>
|
||||||
|
<select class="ui dropdown" v-model="ordering">
|
||||||
|
<option v-for="option in orderingOptions" :value="option[0]">
|
||||||
|
{{ option[1] }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Ordering direction</label>
|
||||||
|
<select class="ui dropdown" v-model="orderingDirection">
|
||||||
|
<option value="">Ascending</option>
|
||||||
|
<option value="-">Descending</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label>Results per page</label>
|
||||||
|
<select class="ui dropdown" v-model="paginateBy">
|
||||||
|
<option :value="parseInt(12)">12</option>
|
||||||
|
<option :value="parseInt(25)">25</option>
|
||||||
|
<option :value="parseInt(50)">50</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui hidden divider"></div>
|
||||||
|
<div v-if="result" class="ui stackable three column grid">
|
||||||
|
<div
|
||||||
|
v-if="result.results.length > 0"
|
||||||
|
v-for="radio in result.results"
|
||||||
|
:key="radio.id"
|
||||||
|
class="column">
|
||||||
|
<radio-card class="fluid" type="custom" :custom-radio="radio"></radio-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui center aligned basic segment">
|
||||||
|
<pagination
|
||||||
|
v-if="result && result.results.length > 0"
|
||||||
|
@page-changed="selectPage"
|
||||||
|
:current="page"
|
||||||
|
:paginate-by="paginateBy"
|
||||||
|
:total="result.count"
|
||||||
|
></pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
|
import $ from 'jquery'
|
||||||
|
|
||||||
|
import config from '@/config'
|
||||||
|
import logger from '@/logging'
|
||||||
|
|
||||||
|
import OrderingMixin from '@/components/mixins/Ordering'
|
||||||
|
import PaginationMixin from '@/components/mixins/Pagination'
|
||||||
|
import RadioCard from '@/components/radios/Card'
|
||||||
|
import Pagination from '@/components/Pagination'
|
||||||
|
|
||||||
|
const FETCH_URL = config.API_URL + 'radios/radios/'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [OrderingMixin, PaginationMixin],
|
||||||
|
props: {
|
||||||
|
defaultQuery: {type: String, required: false, default: ''}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
RadioCard,
|
||||||
|
Pagination
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || '-creation_date')
|
||||||
|
return {
|
||||||
|
isLoading: true,
|
||||||
|
result: null,
|
||||||
|
page: parseInt(this.defaultPage),
|
||||||
|
query: this.defaultQuery,
|
||||||
|
paginateBy: parseInt(this.defaultPaginateBy || 12),
|
||||||
|
orderingDirection: defaultOrdering.direction,
|
||||||
|
ordering: defaultOrdering.field,
|
||||||
|
orderingOptions: [
|
||||||
|
['creation_date', 'Creation date'],
|
||||||
|
['name', 'Name']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
$('.ui.dropdown').dropdown()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateQueryString: _.debounce(function () {
|
||||||
|
this.$router.replace({
|
||||||
|
query: {
|
||||||
|
query: this.query,
|
||||||
|
page: this.page,
|
||||||
|
paginateBy: this.paginateBy,
|
||||||
|
ordering: this.getOrderingAsString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 500),
|
||||||
|
fetchData: _.debounce(function () {
|
||||||
|
var self = this
|
||||||
|
this.isLoading = true
|
||||||
|
let url = FETCH_URL
|
||||||
|
let params = {
|
||||||
|
page: this.page,
|
||||||
|
page_size: this.paginateBy,
|
||||||
|
name__icontains: this.query,
|
||||||
|
ordering: this.getOrderingAsString()
|
||||||
|
}
|
||||||
|
logger.default.debug('Fetching radios')
|
||||||
|
this.$http.get(url, {params: params}).then((response) => {
|
||||||
|
self.result = response.data
|
||||||
|
self.isLoading = false
|
||||||
|
})
|
||||||
|
}, 500),
|
||||||
|
selectPage: function (page) {
|
||||||
|
this.page = page
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
page () {
|
||||||
|
this.updateQueryString()
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
paginateBy () {
|
||||||
|
this.updateQueryString()
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
ordering () {
|
||||||
|
this.updateQueryString()
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
orderingDirection () {
|
||||||
|
this.updateQueryString()
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
query () {
|
||||||
|
this.updateQueryString()
|
||||||
|
this.fetchData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
|
@ -93,18 +93,15 @@ export default {
|
||||||
inputFile (newFile, oldFile) {
|
inputFile (newFile, oldFile) {
|
||||||
if (newFile && !oldFile) {
|
if (newFile && !oldFile) {
|
||||||
// add
|
// add
|
||||||
console.log('add', newFile)
|
|
||||||
if (!this.batch) {
|
if (!this.batch) {
|
||||||
this.createBatch()
|
this.createBatch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newFile && oldFile) {
|
if (newFile && oldFile) {
|
||||||
// update
|
// update
|
||||||
console.log('update', newFile)
|
|
||||||
}
|
}
|
||||||
if (!newFile && oldFile) {
|
if (!newFile && oldFile) {
|
||||||
// remove
|
// remove
|
||||||
console.log('remove', oldFile)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createBatch () {
|
createBatch () {
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
<template>
|
||||||
|
<div class="ui vertical stripe segment">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h2 class="ui header">Builder</h2>
|
||||||
|
<p>
|
||||||
|
You can use this interface to build your own custom radio, which
|
||||||
|
will play tracks according to your criteria
|
||||||
|
</p>
|
||||||
|
<div class="ui form">
|
||||||
|
<div class="inline fields">
|
||||||
|
<div class="field">
|
||||||
|
<label for="name">Radio name</label>
|
||||||
|
<input id="name" type="text" v-model="radioName" placeholder="My awesome radio" />
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<input id="public" type="checkbox" v-model="isPublic" />
|
||||||
|
<label for="public">Display publicly</label>
|
||||||
|
</div>
|
||||||
|
<button :disabled="!canSave" @click="save" class="ui green button">Save</button>
|
||||||
|
<radio-button v-if="id" type="custom" :custom-radio-id="id"></radio-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui form">
|
||||||
|
<p>Add filters to customize your radio</p>
|
||||||
|
<div class="inline field">
|
||||||
|
<select class="ui dropdown" v-model="currentFilterType">
|
||||||
|
<option value="">Select a filter</option>
|
||||||
|
<option v-for="f in availableFilters" :value="f.type">{{ f.label }}</option>
|
||||||
|
</select>
|
||||||
|
<button :disabled="!currentFilterType" @click="add" class="ui button">Add filter</button>
|
||||||
|
</div>
|
||||||
|
<p v-if="currentFilter">
|
||||||
|
{{ currentFilter.help_text }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<table class="ui table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="two wide">Filter name</th>
|
||||||
|
<th class="one wide">Exclude</th>
|
||||||
|
<th class="six wide">Config</th>
|
||||||
|
<th class="five wide">Candidates</th>
|
||||||
|
<th class="two wide">Actions</th>
|
||||||
|
</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">
|
||||||
|
<h3 class="ui header">
|
||||||
|
{{ checkResult.candidates.count }} tracks matching combined filters
|
||||||
|
</h3>
|
||||||
|
<track-table v-if="checkResult.candidates.sample" :tracks="checkResult.candidates.sample"></track-table>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import config from '@/config'
|
||||||
|
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 = config.API_URL + 'radios/radios/filters/'
|
||||||
|
return this.$http.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 = config.API_URL + 'radios/radios/' + this.id + '/'
|
||||||
|
this.$http.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 = config.API_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}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
this.$http.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 = config.API_URL + 'radios/radios/' + this.id + '/'
|
||||||
|
this.$http.put(url, final).then((response) => {
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let url = config.API_URL + 'radios/radios/'
|
||||||
|
this.$http.post(url, final).then((response) => {
|
||||||
|
self.$router.push({
|
||||||
|
name: 'library.radios.edit',
|
||||||
|
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>
|
|
@ -0,0 +1,150 @@
|
||||||
|
<template>
|
||||||
|
<tr>
|
||||||
|
<td>{{ filter.label }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui toggle checkbox">
|
||||||
|
<input name="public" type="checkbox" v-model="exclude" @change="$emit('update-config', index, 'not', exclude)">
|
||||||
|
<label></label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
v-for="(f, index) in filter.fields"
|
||||||
|
class="ui field"
|
||||||
|
:key="(f.name, index)"
|
||||||
|
:ref="f.name">
|
||||||
|
<div :class="['ui', 'search', 'selection', 'dropdown', {'autocomplete': f.autocomplete}, {'multiple': f.type === 'list'}]">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<div class="default text">{{ f.placeholder }}</div>
|
||||||
|
<input v-if="f.type === 'list' && config[f.name]" :value="config[f.name].join(',')" type="hidden">
|
||||||
|
<div v-if="config[f.name]" class="ui menu">
|
||||||
|
<div
|
||||||
|
v-if="f.type === 'list'"
|
||||||
|
v-for="(v, index) in config[f.name]"
|
||||||
|
class="ui item"
|
||||||
|
:data-value="v">
|
||||||
|
<template v-if="config.names">
|
||||||
|
{{ config.names[index] }}
|
||||||
|
</template>
|
||||||
|
<template v-else>{{ v }}</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
@click="showCandidadesModal = !showCandidadesModal"
|
||||||
|
v-if="checkResult"
|
||||||
|
:class="['ui', {'green': checkResult.candidates.count > 10}, 'label']">
|
||||||
|
{{ checkResult.candidates.count }} tracks matching filter
|
||||||
|
</span>
|
||||||
|
<modal v-if="checkResult" :show.sync="showCandidadesModal">
|
||||||
|
<div class="header">
|
||||||
|
Track matching filter
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="description">
|
||||||
|
<track-table v-if="checkResult.candidates.count > 0" :tracks="checkResult.candidates.sample"></track-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="actions">
|
||||||
|
<div class="ui black deny button">
|
||||||
|
Cancel
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</modal>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button @click="$emit('delete', index)" class="ui basic red button">Remove</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import config from '@/config'
|
||||||
|
import $ from 'jquery'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
import Modal from '@/components/semantic/Modal'
|
||||||
|
import TrackTable from '@/components/audio/track/Table'
|
||||||
|
import BuilderFilter from './Filter'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
BuilderFilter,
|
||||||
|
TrackTable,
|
||||||
|
Modal
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
filter: {type: Object},
|
||||||
|
config: {type: Object},
|
||||||
|
index: {type: Number}
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
checkResult: null,
|
||||||
|
showCandidadesModal: false,
|
||||||
|
exclude: config.not
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
let self = this
|
||||||
|
this.filter.fields.forEach(f => {
|
||||||
|
let selector = ['.dropdown']
|
||||||
|
let settings = {
|
||||||
|
onChange: function (value, text, $choice) {
|
||||||
|
value = $(this).dropdown('get value').split(',')
|
||||||
|
if (f.type === 'list' && f.subtype === 'number') {
|
||||||
|
value = value.map(e => {
|
||||||
|
return parseInt(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
self.value = value
|
||||||
|
self.$emit('update-config', self.index, f.name, value)
|
||||||
|
self.fetchCandidates()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f.type === 'list') {
|
||||||
|
selector.push('.multiple')
|
||||||
|
}
|
||||||
|
if (f.autocomplete) {
|
||||||
|
selector.push('.autocomplete')
|
||||||
|
settings.fields = f.autocomplete_fields
|
||||||
|
settings.minCharacters = 1
|
||||||
|
settings.apiSettings = {
|
||||||
|
url: config.BACKEND_URL + f.autocomplete + '?' + f.autocomplete_qs,
|
||||||
|
beforeXHR: function (xhrObject) {
|
||||||
|
xhrObject.setRequestHeader('Authorization', self.$store.getters['auth/header'])
|
||||||
|
return xhrObject
|
||||||
|
},
|
||||||
|
onResponse: function (initialResponse) {
|
||||||
|
if (settings.fields.remoteValues) {
|
||||||
|
return initialResponse
|
||||||
|
}
|
||||||
|
return {results: initialResponse}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$(self.$el).find(selector.join('')).dropdown(settings)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchCandidates: function () {
|
||||||
|
let self = this
|
||||||
|
let url = config.API_URL + 'radios/radios/validate/'
|
||||||
|
let final = _.clone(this.config)
|
||||||
|
final.type = this.filter.type
|
||||||
|
final = {'filters': [final]}
|
||||||
|
this.$http.post(url, final).then((response) => {
|
||||||
|
self.checkResult = response.data.filters[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
exclude: function () {
|
||||||
|
this.fetchCandidates()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
type: {type: String, required: true},
|
customRadioId: {required: false},
|
||||||
|
type: {type: String, required: false},
|
||||||
objectId: {type: Number, default: null}
|
objectId: {type: Number, default: null}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -19,7 +20,7 @@ export default {
|
||||||
if (this.running) {
|
if (this.running) {
|
||||||
this.$store.dispatch('radios/stop')
|
this.$store.dispatch('radios/stop')
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('radios/start', {type: this.type, objectId: this.objectId})
|
this.$store.dispatch('radios/start', {type: this.type, objectId: this.objectId, customRadioId: this.customRadioId})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ui card">
|
<div class="ui card">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="header">Radio : {{ radio.name }}</div>
|
<div class="header">{{ radio.name }}</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
{{ radio.description }}
|
{{ radio.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="extra content">
|
<div class="extra content">
|
||||||
<radio-button class="right floated button" :type="type"></radio-button>
|
<router-link
|
||||||
|
class="ui basic yellow button"
|
||||||
|
v-if="$store.state.auth.authenticated && type === 'custom' && customRadio.user === $store.state.auth.profile.id"
|
||||||
|
:to="{name: 'library.radios.edit', params: {id: customRadioId }}">
|
||||||
|
Edit...
|
||||||
|
</router-link>
|
||||||
|
<radio-button class="right floated button" :type="type" :custom-radio-id="customRadioId"></radio-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -17,14 +23,24 @@ import RadioButton from './Button'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
type: {type: String, required: true}
|
type: {type: String, required: true},
|
||||||
|
customRadio: {required: false}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
RadioButton
|
RadioButton
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
radio () {
|
radio () {
|
||||||
|
if (this.customRadio) {
|
||||||
|
return this.customRadio
|
||||||
|
}
|
||||||
return this.$store.getters['radios/types'][this.type]
|
return this.$store.getters['radios/types'][this.type]
|
||||||
|
},
|
||||||
|
customRadioId: function () {
|
||||||
|
if (this.customRadio) {
|
||||||
|
return this.customRadio.id
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import LibraryArtists from '@/components/library/Artists'
|
||||||
import LibraryAlbum from '@/components/library/Album'
|
import LibraryAlbum from '@/components/library/Album'
|
||||||
import LibraryTrack from '@/components/library/Track'
|
import LibraryTrack from '@/components/library/Track'
|
||||||
import LibraryImport from '@/components/library/import/Main'
|
import LibraryImport from '@/components/library/import/Main'
|
||||||
|
import LibraryRadios from '@/components/library/Radios'
|
||||||
|
import RadioBuilder from '@/components/library/radios/Builder'
|
||||||
import BatchList from '@/components/library/import/BatchList'
|
import BatchList from '@/components/library/import/BatchList'
|
||||||
import BatchDetail from '@/components/library/import/BatchDetail'
|
import BatchDetail from '@/components/library/import/BatchDetail'
|
||||||
|
|
||||||
|
@ -76,6 +78,19 @@ export default new Router({
|
||||||
defaultPage: route.query.page
|
defaultPage: route.query.page
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'radios/',
|
||||||
|
name: 'library.radios.browse',
|
||||||
|
component: LibraryRadios,
|
||||||
|
props: (route) => ({
|
||||||
|
defaultOrdering: route.query.ordering,
|
||||||
|
defaultQuery: route.query.query,
|
||||||
|
defaultPaginateBy: route.query.paginateBy,
|
||||||
|
defaultPage: route.query.page
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ path: 'radios/build', name: 'library.radios.build', component: RadioBuilder, props: true },
|
||||||
|
{ path: 'radios/build/:id', name: 'library.radios.edit', component: RadioBuilder, props: true },
|
||||||
{ path: 'artists/:id', name: 'library.artists.detail', component: LibraryArtist, props: true },
|
{ path: 'artists/:id', name: 'library.artists.detail', component: LibraryArtist, props: true },
|
||||||
{ path: 'albums/:id', name: 'library.albums.detail', component: LibraryAlbum, props: true },
|
{ path: 'albums/:id', name: 'library.albums.detail', component: LibraryAlbum, props: true },
|
||||||
{ path: 'tracks/:id', name: 'library.tracks.detail', component: LibraryTrack, props: true },
|
{ path: 'tracks/:id', name: 'library.tracks.detail', component: LibraryTrack, props: true },
|
||||||
|
|
|
@ -38,15 +38,16 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
start ({commit, dispatch}, {type, objectId}) {
|
start ({commit, dispatch}, {type, objectId, customRadioId}) {
|
||||||
let resource = Vue.resource(CREATE_RADIO_URL)
|
let resource = Vue.resource(CREATE_RADIO_URL)
|
||||||
var params = {
|
var params = {
|
||||||
radio_type: type,
|
radio_type: type,
|
||||||
related_object_id: objectId
|
related_object_id: objectId,
|
||||||
|
custom_radio: customRadioId
|
||||||
}
|
}
|
||||||
resource.save({}, params).then((response) => {
|
resource.save({}, params).then((response) => {
|
||||||
logger.default.info('Successfully started radio ', type)
|
logger.default.info('Successfully started radio ', type)
|
||||||
commit('current', {type, objectId, session: response.data.id})
|
commit('current', {type, objectId, session: response.data.id, customRadioId})
|
||||||
commit('running', true)
|
commit('running', true)
|
||||||
dispatch('populateQueue')
|
dispatch('populateQueue')
|
||||||
}, (response) => {
|
}, (response) => {
|
||||||
|
|
Loading…
Reference in New Issue