Merge pull request #1165 from chme/web_next

Update web interface v0.8.4
This commit is contained in:
Christian Meffert 2021-01-11 20:12:11 +01:00 committed by GitHub
commit 74c87f3080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1478 additions and 1277 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,6 +37,7 @@ static struct settings_option webinterface_options[] =
{ "show_menu_item_radio", SETTINGS_TYPE_BOOL, { false } }, { "show_menu_item_radio", SETTINGS_TYPE_BOOL, { false } },
{ "show_menu_item_files", SETTINGS_TYPE_BOOL, { true } }, { "show_menu_item_files", SETTINGS_TYPE_BOOL, { true } },
{ "show_menu_item_search", SETTINGS_TYPE_BOOL, { true } }, { "show_menu_item_search", SETTINGS_TYPE_BOOL, { true } },
{ "recently_added_limit", SETTINGS_TYPE_INT, { 100 } },
}; };
static struct settings_option artwork_options[] = static struct settings_option artwork_options[] =

2304
web-src/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "forked-daapd-web", "name": "forked-daapd-web",
"version": "0.8.3", "version": "0.8.4",
"private": true, "private": true,
"description": "forked-daapd web interface", "description": "forked-daapd web interface",
"author": "chme <christian.meffert@googlemail.com>", "author": "chme <christian.meffert@googlemail.com>",
@ -14,39 +14,39 @@
"axios": "^0.21.1", "axios": "^0.21.1",
"bulma": "^0.9.1", "bulma": "^0.9.1",
"bulma-switch": "^2.0.0", "bulma-switch": "^2.0.0",
"core-js": "^3.7.0", "core-js": "^3.8.2",
"mdi": "^2.2.43", "mdi": "^2.2.43",
"moment": "^2.29.1", "moment": "^2.29.1",
"moment-duration-format": "^2.3.2", "moment-duration-format": "^2.3.2",
"npm": "^6.14.9", "npm": "^6.14.11",
"reconnectingwebsocket": "^1.0.0", "reconnectingwebsocket": "^1.0.0",
"spotify-web-api-js": "^1.5.1", "spotify-web-api-js": "^1.5.1",
"string-to-color": "^2.2.2", "string-to-color": "^2.2.2",
"v-click-outside": "^3.1.2", "v-click-outside": "^3.1.2",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-infinite-loading": "^2.4.5", "vue-infinite-loading": "^2.4.5",
"vue-observe-visibility": "^0.4.6", "vue-observe-visibility": "^1.0.0",
"vue-progressbar": "^0.7.5", "vue-progressbar": "^0.7.5",
"vue-range-slider": "^0.6.0", "vue-range-slider": "^0.6.0",
"vue-router": "^3.4.9", "vue-router": "^3.4.9",
"vue-scrollto": "^2.20.0", "vue-scrollto": "^2.20.0",
"vue-tiny-lazyload-img": "^0.1.0", "vue-tiny-lazyload-img": "^0.1.0",
"vuedraggable": "^2.24.3", "vuedraggable": "^2.24.3",
"vuex": "^3.5.1" "vuex": "^3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.5.9", "@vue/cli-plugin-babel": "^4.5.10",
"@vue/cli-plugin-eslint": "^4.5.9", "@vue/cli-plugin-eslint": "^4.5.10",
"@vue/cli-service": "^4.5.9", "@vue/cli-service": "^4.5.10",
"@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-standard": "^6.0.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"eslint": "^7.14.0", "eslint": "^7.17.0",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.1.0", "eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^7.1.0", "eslint-plugin-vue": "^7.4.1",
"sass": "^1.29.0", "sass": "^1.32.2",
"sass-loader": "^10.1.0", "sass-loader": "^10.1.0",
"vue-template-compiler": "^2.6.12" "vue-template-compiler": "^2.6.12"
}, },

View File

@ -107,18 +107,18 @@ export default {
const vm = this const vm = this
var protocol = 'ws://' let protocol = 'ws://'
if (window.location.protocol === 'https:') { if (window.location.protocol === 'https:') {
protocol = 'wss://' protocol = 'wss://'
} }
var wsUrl = protocol + window.location.hostname + ':' + vm.$store.state.config.websocket_port let wsUrl = protocol + window.location.hostname + ':' + vm.$store.state.config.websocket_port
if (process.env.NODE_ENV === 'development' && process.env.VUE_APP_WEBSOCKET_SERVER) { if (process.env.NODE_ENV === 'development' && process.env.VUE_APP_WEBSOCKET_SERVER) {
// If we are running in the development server, use the websocket url configured in .env.development // If we are running in the development server, use the websocket url configured in .env.development
wsUrl = process.env.VUE_APP_WEBSOCKET_SERVER wsUrl = process.env.VUE_APP_WEBSOCKET_SERVER
} }
var socket = new ReconnectingWebSocket( const socket = new ReconnectingWebSocket(
wsUrl, wsUrl,
'notify', 'notify',
{ reconnectInterval: 3000 } { reconnectInterval: 3000 }
@ -146,7 +146,7 @@ export default {
vm.$store.dispatch('add_notification', { text: 'Connection lost. Reconnecting ... (' + vm.reconnect_attempts + ')', type: 'danger', topic: 'connection' }) vm.$store.dispatch('add_notification', { text: 'Connection lost. Reconnecting ... (' + vm.reconnect_attempts + ')', type: 'danger', topic: 'connection' })
} }
socket.onmessage = function (response) { socket.onmessage = function (response) {
var data = JSON.parse(response.data) const data = JSON.parse(response.data)
if (data.notify.includes('update') || data.notify.includes('database')) { if (data.notify.includes('update') || data.notify.includes('database')) {
vm.update_library_stats() vm.update_library_stats()
} }

View File

@ -10,7 +10,7 @@ export default {
// setup audio routing // setup audio routing
setupAudio () { setupAudio () {
var AudioContext = window.AudioContext || window.webkitAudioContext const AudioContext = window.AudioContext || window.webkitAudioContext
this._context = new AudioContext() this._context = new AudioContext()
this._source = this._context.createMediaElementSource(this._audio) this._source = this._context.createMediaElementSource(this._audio)
this._gain = this._context.createGain() this._gain = this._context.createGain()

View File

@ -7,7 +7,7 @@
<span class="icon fd-has-action" <span class="icon fd-has-action"
:class="{ 'has-text-grey-light': !output.selected }" :class="{ 'has-text-grey-light': !output.selected }"
v-on:click="set_enabled"> v-on:click="set_enabled">
<i class="mdi mdi-18px" :class="type_class"></i> <i class="mdi mdi-18px" :class="type_class" :title="output.type"></i>
</span> </span>
</a> </a>
</div> </div>
@ -42,7 +42,7 @@ export default {
computed: { computed: {
type_class () { type_class () {
if (this.output.type === 'AirPlay') { if (this.output.type.startsWith('AirPlay')) {
return 'mdi-airplay' return 'mdi-airplay'
} else if (this.output.type === 'Chromecast') { } else if (this.output.type === 'Chromecast') {
return 'mdi-cast' return 'mdi-cast'

View File

@ -0,0 +1,120 @@
<template>
<fieldset :disabled="disabled">
<div class="field">
<label class="label has-text-weight-normal">
<slot name="label"></slot>
<i class="is-size-7"
:class="{
'has-text-info': statusUpdate === 'success',
'has-text-danger': statusUpdate === 'error'
}"> {{ info }}</i>
</label>
<div class="control">
<input class="input"
type="number"
min="0"
style="width: 10em;"
:placeholder="placeholder"
:value="value"
@input="set_update_timer"
ref="settings_number">
</div>
<p class="help" v-if="$slots['info']">
<slot name="info"></slot>
</p>
</div>
</fieldset>
</template>
<script>
import webapi from '@/webapi'
import * as types from '@/store/mutation_types'
export default {
name: 'SettingsIntfield',
props: ['category_name', 'option_name', 'placeholder', 'disabled'],
data () {
return {
timerDelay: 2000,
timerId: -1,
statusUpdate: ''
}
},
computed: {
category () {
return this.$store.state.settings.categories.find(elem => elem.name === this.category_name)
},
option () {
if (!this.category) {
return {}
}
return this.category.options.find(elem => elem.name === this.option_name)
},
value () {
return this.option.value
},
info () {
if (this.statusUpdate === 'success') {
return '(setting saved)'
} else if (this.statusUpdate === 'error') {
return '(error saving setting)'
}
return ''
}
},
methods: {
set_update_timer () {
if (this.timerId > 0) {
window.clearTimeout(this.timerId)
this.timerId = -1
}
this.statusUpdate = ''
const newValue = this.$refs.settings_number.value
if (newValue !== this.value) {
this.timerId = window.setTimeout(this.update_setting, this.timerDelay)
}
},
update_setting () {
this.timerId = -1
const newValue = this.$refs.settings_number.value
if (newValue === this.value) {
this.statusUpdate = ''
return
}
const option = {
category: this.category.name,
name: this.option_name,
value: parseInt(newValue, 10)
}
webapi.settings_update(this.category.name, option).then(() => {
this.$store.commit(types.UPDATE_SETTINGS_OPTION, option)
this.statusUpdate = 'success'
}).catch(() => {
this.statusUpdate = 'error'
this.$refs.settings_number.value = this.value
}).finally(() => {
this.timerId = window.setTimeout(this.clear_status, this.timerDelay)
})
},
clear_status: function () {
this.statusUpdate = ''
}
}
}
</script>
<style>
</style>

View File

@ -19,6 +19,8 @@ export default class Albums {
getAlbumIndex (album) { getAlbumIndex (album) {
if (this.options.sort === 'Recently added') { if (this.options.sort === 'Recently added') {
return album.time_added.substring(0, 4) return album.time_added.substring(0, 4)
} else if (this.options.sort === 'Recently added (browse)') {
return this.getRecentlyAddedBrowseIndex(album.time_added)
} else if (this.options.sort === 'Recently released') { } else if (this.options.sort === 'Recently released') {
return album.date_released ? album.date_released.substring(0, 4) : '0000' return album.date_released ? album.date_released.substring(0, 4) : '0000'
} else if (this.options.sort === 'Release date') { } else if (this.options.sort === 'Release date') {
@ -27,6 +29,23 @@ export default class Albums {
return album.name_sort.charAt(0).toUpperCase() return album.name_sort.charAt(0).toUpperCase()
} }
getRecentlyAddedBrowseIndex (recentlyAdded) {
if (!recentlyAdded) {
return '0000'
}
const diff = new Date().getTime() - new Date(recentlyAdded).getTime()
if (diff < 86400000) { // 24h
return 'Today'
} else if (diff < 604800000) { // 7 days
return 'Last week'
} else if (diff < 2592000000) { // 30 days
return 'Last month'
}
return recentlyAdded.substring(0, 4)
}
isAlbumVisible (album) { isAlbumVisible (album) {
if (this.options.hideSingles && album.track_count <= 2) { if (this.options.hideSingles && album.track_count <= 2) {
return false return false
@ -43,11 +62,11 @@ export default class Albums {
} }
createSortedAndFilteredList () { createSortedAndFilteredList () {
var albumsSorted = this.items let albumsSorted = this.items
if (this.options.hideSingles || this.options.hideSpotify || this.options.hideOther) { if (this.options.hideSingles || this.options.hideSpotify || this.options.hideOther) {
albumsSorted = albumsSorted.filter(album => this.isAlbumVisible(album)) albumsSorted = albumsSorted.filter(album => this.isAlbumVisible(album))
} }
if (this.options.sort === 'Recently added') { if (this.options.sort === 'Recently added' || this.options.sort === 'Recently added (browse)') {
albumsSorted = [...albumsSorted].sort((a, b) => b.time_added.localeCompare(a.time_added)) albumsSorted = [...albumsSorted].sort((a, b) => b.time_added.localeCompare(a.time_added))
} else if (this.options.sort === 'Recently released') { } else if (this.options.sort === 'Recently released') {
albumsSorted = [...albumsSorted].sort((a, b) => { albumsSorted = [...albumsSorted].sort((a, b) => {

View File

@ -39,7 +39,7 @@ export default class Artists {
} }
createSortedAndFilteredList () { createSortedAndFilteredList () {
var artistsSorted = this.items let artistsSorted = this.items
if (this.options.hideSingles || this.options.hideSpotify || this.options.hideOther) { if (this.options.hideSingles || this.options.hideSpotify || this.options.hideOther) {
artistsSorted = artistsSorted.filter(artist => this.isArtistVisible(artist)) artistsSorted = artistsSorted.filter(artist => this.isArtistVisible(artist))
} }

View File

@ -8,7 +8,7 @@
<p class="heading">albums</p> <p class="heading">albums</p>
</template> </template>
<template slot="content"> <template slot="content">
<list-albums :albums="recently_added.items"></list-albums> <list-albums :albums="albums_list"></list-albums>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>
@ -20,13 +20,16 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsMusic from '@/components/TabsMusic' import TabsMusic from '@/components/TabsMusic'
import ListAlbums from '@/components/ListAlbums' import ListAlbums from '@/components/ListAlbums'
import webapi from '@/webapi' import webapi from '@/webapi'
import store from '@/store'
import Albums from '@/lib/Albums'
const browseData = { const browseData = {
load: function (to) { load: function (to) {
const limit = store.getters.settings_option_recently_added_limit
return webapi.search({ return webapi.search({
type: 'album', type: 'album',
expression: 'media_kind is music having track_count > 3 order by time_added desc', expression: 'media_kind is music having track_count > 3 order by time_added desc',
limit: 500 limit: limit
}) })
}, },
@ -42,7 +45,18 @@ export default {
data () { data () {
return { return {
recently_added: {} recently_added: { items: [] }
}
},
computed: {
albums_list () {
return new Albums(this.recently_added.items, {
hideSingles: false,
hideSpotify: false,
sort: 'Recently added (browse)',
group: true
})
} }
} }
} }

View File

@ -135,7 +135,7 @@ export default {
methods: { methods: {
open_parent_directory: function () { open_parent_directory: function () {
var parent = this.current_directory.slice(0, this.current_directory.lastIndexOf('/')) const parent = this.current_directory.slice(0, this.current_directory.lastIndexOf('/'))
if (parent === '' || this.$store.state.config.directories.includes(this.current_directory)) { if (parent === '' || this.$store.state.config.directories.includes(this.current_directory)) {
this.$router.push({ path: '/files' }) this.$router.push({ path: '/files' })
} else { } else {

View File

@ -124,9 +124,9 @@ export default {
}, },
move_item: function (e) { move_item: function (e) {
var oldPosition = !this.show_only_next_items ? e.oldIndex : e.oldIndex + this.current_position const oldPosition = !this.show_only_next_items ? e.oldIndex : e.oldIndex + this.current_position
var item = this.queue_items[oldPosition] const item = this.queue_items[oldPosition]
var newPosition = item.position + (e.newIndex - e.oldIndex) const newPosition = item.position + (e.newIndex - e.oldIndex)
if (newPosition !== oldPosition) { if (newPosition !== oldPosition) {
webapi.queue_move(item.id, newPosition) webapi.queue_move(item.id, newPosition)
} }

View File

@ -262,7 +262,7 @@ export default {
return return
} }
var searchParams = { const searchParams = {
type: query.type, type: query.type,
media_kind: 'music' media_kind: 'music'
} }
@ -291,7 +291,7 @@ export default {
return return
} }
var searchParams = { const searchParams = {
type: 'album', type: 'album',
media_kind: 'audiobook' media_kind: 'audiobook'
} }
@ -317,7 +317,7 @@ export default {
return return
} }
var searchParams = { const searchParams = {
type: 'album', type: 'album',
media_kind: 'podcast' media_kind: 'podcast'
} }

View File

@ -80,6 +80,18 @@
</settings-textfield> </settings-textfield>
</template> </template>
</content-with-heading> </content-with-heading>
<content-with-heading>
<template slot="heading-left">
<div class="title is-4">Recently added page</div>
</template>
<template slot="content">
<settings-intfield category_name="webinterface" option_name="recently_added_limit">
<template slot="label">Limit the number of albums shown on the "Recently Added" page</template>
</settings-intfield>
</template>
</content-with-heading>
</div> </div>
</template> </template>
@ -88,10 +100,11 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import TabsSettings from '@/components/TabsSettings' import TabsSettings from '@/components/TabsSettings'
import SettingsCheckbox from '@/components/SettingsCheckbox' import SettingsCheckbox from '@/components/SettingsCheckbox'
import SettingsTextfield from '@/components/SettingsTextfield' import SettingsTextfield from '@/components/SettingsTextfield'
import SettingsIntfield from '@/components/SettingsIntfield'
export default { export default {
name: 'SettingsPageWebinterface', name: 'SettingsPageWebinterface',
components: { ContentWithHeading, TabsSettings, SettingsCheckbox, SettingsTextfield }, components: { ContentWithHeading, TabsSettings, SettingsCheckbox, SettingsTextfield, SettingsIntfield },
computed: { computed: {
settings_option_show_composer_now_playing () { settings_option_show_composer_now_playing () {

View File

@ -278,10 +278,10 @@ export default {
return webapi.spotify().then(({ data }) => { return webapi.spotify().then(({ data }) => {
this.search_param.market = data.webapi_country this.search_param.market = data.webapi_country
var spotifyApi = new SpotifyWebApi() const spotifyApi = new SpotifyWebApi()
spotifyApi.setAccessToken(data.webapi_token) spotifyApi.setAccessToken(data.webapi_token)
var types = this.query.type.split(',').filter(type => this.validSearchTypes.includes(type)) const types = this.query.type.split(',').filter(type => this.validSearchTypes.includes(type))
return spotifyApi.search(this.query.query, types, this.search_param) return spotifyApi.search(this.query.query, types, this.search_param)
}) })
}, },

View File

@ -64,7 +64,7 @@ export default new Vuex.Store({
getters: { getters: {
now_playing: state => { now_playing: state => {
var item = state.queue.items.find(function (item) { const item = state.queue.items.find(function (item) {
return item.id === state.player.item_id return item.id === state.player.item_id
}) })
return (item === undefined) ? {} : item return (item === undefined) ? {} : item
@ -77,6 +77,16 @@ export default new Vuex.Store({
return null return null
}, },
settings_option_recently_added_limit: (state, getters) => {
if (getters.settings_webinterface) {
const option = getters.settings_webinterface.options.find(elem => elem.name === 'recently_added_limit')
if (option) {
return option.value
}
}
return 100
},
settings_option_show_composer_now_playing: (state, getters) => { settings_option_show_composer_now_playing: (state, getters) => {
if (getters.settings_webinterface) { if (getters.settings_webinterface) {
const option = getters.settings_webinterface.options.find(elem => elem.name === 'show_composer_now_playing') const option = getters.settings_webinterface.options.find(elem => elem.name === 'show_composer_now_playing')
@ -157,7 +167,7 @@ export default new Vuex.Store({
}, },
[types.ADD_NOTIFICATION] (state, notification) { [types.ADD_NOTIFICATION] (state, notification) {
if (notification.topic) { if (notification.topic) {
var index = state.notifications.list.findIndex(elem => elem.topic === notification.topic) const index = state.notifications.list.findIndex(elem => elem.topic === notification.topic)
if (index >= 0) { if (index >= 0) {
state.notifications.list.splice(index, 1, notification) state.notifications.list.splice(index, 1, notification)
return return
@ -173,7 +183,7 @@ export default new Vuex.Store({
} }
}, },
[types.ADD_RECENT_SEARCH] (state, query) { [types.ADD_RECENT_SEARCH] (state, query) {
var index = state.recent_searches.findIndex(elem => elem === query) const index = state.recent_searches.findIndex(elem => elem === query)
if (index >= 0) { if (index >= 0) {
state.recent_searches.splice(index, 1) state.recent_searches.splice(index, 1)
} }

View File

@ -63,7 +63,7 @@ export default {
}, },
queue_add_next (uri) { queue_add_next (uri) {
var position = 0 let position = 0
if (store.getters.now_playing && store.getters.now_playing.id) { if (store.getters.now_playing && store.getters.now_playing.id) {
position = store.getters.now_playing.position + 1 position = store.getters.now_playing.position + 1
} }
@ -74,7 +74,7 @@ export default {
}, },
queue_expression_add (expression) { queue_expression_add (expression) {
var options = {} const options = {}
options.expression = expression options.expression = expression
return axios.post('./api/queue/items/add', undefined, { params: options }).then((response) => { return axios.post('./api/queue/items/add', undefined, { params: options }).then((response) => {
@ -84,7 +84,7 @@ export default {
}, },
queue_expression_add_next (expression) { queue_expression_add_next (expression) {
var options = {} const options = {}
options.expression = expression options.expression = expression
options.position = 0 options.position = 0
if (store.getters.now_playing && store.getters.now_playing.id) { if (store.getters.now_playing && store.getters.now_playing.id) {
@ -109,7 +109,7 @@ export default {
}, },
player_play_uri (uris, shuffle, position = undefined) { player_play_uri (uris, shuffle, position = undefined) {
var options = {} const options = {}
options.uris = uris options.uris = uris
options.shuffle = shuffle ? 'true' : 'false' options.shuffle = shuffle ? 'true' : 'false'
options.clear = 'true' options.clear = 'true'
@ -120,7 +120,7 @@ export default {
}, },
player_play_expression (expression, shuffle, position = undefined) { player_play_expression (expression, shuffle, position = undefined) {
var options = {} const options = {}
options.expression = expression options.expression = expression
options.shuffle = shuffle ? 'true' : 'false' options.shuffle = shuffle ? 'true' : 'false'
options.clear = 'true' options.clear = 'true'
@ -159,12 +159,12 @@ export default {
}, },
player_shuffle (newState) { player_shuffle (newState) {
var shuffle = newState ? 'true' : 'false' const shuffle = newState ? 'true' : 'false'
return axios.put('./api/player/shuffle?state=' + shuffle) return axios.put('./api/player/shuffle?state=' + shuffle)
}, },
player_consume (newState) { player_consume (newState) {
var consume = newState ? 'true' : 'false' const consume = newState ? 'true' : 'false'
return axios.put('./api/player/consume?state=' + consume) return axios.put('./api/player/consume?state=' + consume)
}, },
@ -235,7 +235,7 @@ export default {
}, },
library_genre (genre) { library_genre (genre) {
var genreParams = { const genreParams = {
type: 'albums', type: 'albums',
media_kind: 'music', media_kind: 'music',
expression: 'genre is "' + genre + '"' expression: 'genre is "' + genre + '"'
@ -246,7 +246,7 @@ export default {
}, },
library_genre_tracks (genre) { library_genre_tracks (genre) {
var genreParams = { const genreParams = {
type: 'tracks', type: 'tracks',
media_kind: 'music', media_kind: 'music',
expression: 'genre is "' + genre + '"' expression: 'genre is "' + genre + '"'
@ -257,7 +257,7 @@ export default {
}, },
library_radio_streams () { library_radio_streams () {
var params = { const params = {
type: 'tracks', type: 'tracks',
media_kind: 'music', media_kind: 'music',
expression: 'data_kind is url and song_length = 0' expression: 'data_kind is url and song_length = 0'
@ -269,7 +269,7 @@ export default {
library_artist_tracks (artist) { library_artist_tracks (artist) {
if (artist) { if (artist) {
var artistParams = { const artistParams = {
type: 'tracks', type: 'tracks',
expression: 'songartistid is "' + artist + '"' expression: 'songartistid is "' + artist + '"'
} }
@ -280,7 +280,7 @@ export default {
}, },
library_podcasts_new_episodes () { library_podcasts_new_episodes () {
var episodesParams = { const episodesParams = {
type: 'tracks', type: 'tracks',
expression: 'media_kind is podcast and play_count = 0 ORDER BY time_added DESC' expression: 'media_kind is podcast and play_count = 0 ORDER BY time_added DESC'
} }
@ -290,7 +290,7 @@ export default {
}, },
library_podcast_episodes (albumId) { library_podcast_episodes (albumId) {
var episodesParams = { const episodesParams = {
type: 'tracks', type: 'tracks',
expression: 'media_kind is podcast and songalbumid is "' + albumId + '" ORDER BY date_released DESC' expression: 'media_kind is podcast and songalbumid is "' + albumId + '" ORDER BY date_released DESC'
} }
@ -336,7 +336,7 @@ export default {
}, },
library_files (directory = undefined) { library_files (directory = undefined) {
var filesParams = { directory: directory } const filesParams = { directory: directory }
return axios.get('./api/library/files', { return axios.get('./api/library/files', {
params: filesParams params: filesParams
}) })