Merge pull request #695 from chme/web_interface_v043

Update player web interface (v0.5.0)
This commit is contained in:
Christian Meffert 2019-02-21 16:37:59 +01:00 committed by GitHub
commit 4c2f178aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1061 additions and 1103 deletions

View File

@ -1,2 +1,2 @@
.fd-notifications{position:fixed;bottom:60px;z-index:20000;width:100%}.fd-notifications .notification{margin-bottom:10px;margin-left:24px;margin-right:24px;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.slider{min-width:250px;width:100%}.range-slider-fill{background-color:#363636}a.navbar-item{outline:0;line-height:1.5;padding:.5rem 1rem}.fd-expanded{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.fd-margin-left-auto{margin-left:auto}.fd-has-action{cursor:pointer}.fd-is-movable{cursor:move}.fd-has-margin-top{margin-top:24px}.fd-has-margin-bottom{margin-bottom:24px}.fd-remove-padding-bottom{padding-bottom:0}.fd-has-padding-left-right{padding-left:24px;padding-right:24px}.fd-is-square .button{height:27px;width:27px}.fd-is-text-clipped{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fd-is-fullheight{height:calc(100vh - 6.5rem)}.fd-is-fullheight-body{-ms-flex-negative:1;flex-shrink:1;overflow:hidden;height:100%}.fd-image-fullheight{height:100%;width:auto}.fd-tabs-section{padding-bottom:3px;padding-top:3px;background:#fff;top:3.25rem;z-index:20;position:fixed;width:100%}section.fd-tabs-section+section.fd-content{margin-top:24px}.fd-progress-bar{top:52px!important}.fd-has-shadow{-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.sortable-chosen .media-right{visibility:hidden}.sortable-ghost h1,.sortable-ghost h2{color:#ff3860!important}.media:first-of-type{padding-top:17px;margin-top:16px}.fade-enter-active,.fade-leave-active{-webkit-transition:opacity .4s;transition:opacity .4s}.fade-enter,.fade-leave-to{opacity:0}.seek-slider{min-width:250px;max-width:500px;width:100%!important}.seek-slider .range-slider-fill{background-color:#00d1b2;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.seek-slider .range-slider-knob{width:10px;height:10px;background-color:#00d1b2;border-color:#00d1b2}.title:not(.is-spaced)+.subtitle,.title:not(.is-spaced)+.subtitle+.subtitle{margin-top:-1.3rem!important}.fd-modal-card{overflow:visible}.fd-modal-card .card-content{max-height:calc(100vh - 200px);overflow:auto}.fd-modal-card .card{margin-left:16px;margin-right:16px} .fd-notifications{position:fixed;bottom:60px;z-index:20000;width:100%}.fd-notifications .notification{margin-bottom:10px;margin-left:24px;margin-right:24px;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.slider{min-width:250px;width:100%}.range-slider-fill{background-color:#363636}.track-progress{margin:0;padding:0;min-width:250px;width:100%}.track-progress .range-slider-knob{visibility:hidden}.track-progress .range-slider-fill{background-color:#3273dc;height:2px}.track-progress .range-slider-rail{background-color:#fff}.media.with-progress h2:last-of-type{margin-bottom:6px}.media.with-progress{margin-top:0}a.navbar-item{outline:0;line-height:1.5;padding:.5rem 1rem}.fd-expanded{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.fd-margin-left-auto{margin-left:auto}.fd-has-action{cursor:pointer}.fd-is-movable{cursor:move}.fd-has-margin-top{margin-top:24px}.fd-has-margin-bottom{margin-bottom:24px}.fd-remove-padding-bottom{padding-bottom:0}.fd-has-padding-left-right{padding-left:24px;padding-right:24px}.fd-is-square .button{height:27px;width:27px}.fd-is-text-clipped{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fd-is-fullheight{height:calc(100vh - 6.5rem)}.fd-is-fullheight-body{-ms-flex-negative:1;flex-shrink:1;overflow:hidden;height:100%}.fd-image-fullheight{height:100%;width:auto}.fd-tabs-section{padding-bottom:3px;padding-top:3px;background:#fff;top:3.25rem;z-index:20;position:fixed;width:100%}section.fd-tabs-section+section.fd-content{margin-top:24px}.fd-progress-bar{top:52px!important}.fd-has-shadow{-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.sortable-chosen .media-right{visibility:hidden}.sortable-ghost h1,.sortable-ghost h2{color:#ff3860!important}.media:first-of-type{padding-top:17px;margin-top:16px}.fade-enter-active,.fade-leave-active{-webkit-transition:opacity .4s;transition:opacity .4s}.fade-enter,.fade-leave-to{opacity:0}.seek-slider{min-width:250px;max-width:500px;width:100%!important}.seek-slider .range-slider-fill{background-color:#00d1b2;-webkit-box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.seek-slider .range-slider-knob{width:10px;height:10px;background-color:#00d1b2;border-color:#00d1b2}.title:not(.is-spaced)+.subtitle,.title:not(.is-spaced)+.subtitle+.subtitle{margin-top:-1.3rem!important}.fd-modal-card{overflow:visible}.fd-modal-card .card-content{max-height:calc(100vh - 200px);overflow:auto}.fd-modal-card .card{margin-left:16px;margin-right:16px}
/*# sourceMappingURL=app.css.map */ /*# sourceMappingURL=app.css.map */

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

1984
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.4.2", "version": "0.5.0",
"description": "forked-daapd web interface", "description": "forked-daapd web interface",
"author": "chme <christian.meffert@googlemail.com>", "author": "chme <christian.meffert@googlemail.com>",
"license": "GPL-2.0", "license": "GPL-2.0",
@ -13,14 +13,14 @@
}, },
"dependencies": { "dependencies": {
"axios": "^0.18.0", "axios": "^0.18.0",
"bulma": "^0.7.1", "bulma": "^0.7.4",
"mdi": "^2.1.99", "mdi": "^2.1.99",
"moment": "^2.24.0", "moment": "^2.24.0",
"moment-duration-format": "^2.2.2", "moment-duration-format": "^2.2.2",
"npm": "^6.6.0", "npm": "^6.8.0",
"reconnectingwebsocket": "^1.0.0", "reconnectingwebsocket": "^1.0.0",
"spotify-web-api-js": "^1.1.1", "spotify-web-api-js": "^1.2.0",
"vue": "^2.5.22", "vue": "^2.6.6",
"vue-infinite-loading": "^2.4.3", "vue-infinite-loading": "^2.4.3",
"vue-progressbar": "^0.7.4", "vue-progressbar": "^0.7.4",
"vue-range-slider": "^0.6.0", "vue-range-slider": "^0.6.0",
@ -29,10 +29,10 @@
"vuex": "^3.1.0" "vuex": "^3.1.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^3.3.0", "@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.3.0", "@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.3.1", "@vue/cli-service": "^3.4.0",
"@vue/eslint-config-standard": "^3.0.5", "@vue/eslint-config-standard": "^3.0.5",
"vue-template-compiler": "^2.5.22" "vue-template-compiler": "^2.6.6"
} }
} }

View File

@ -4,12 +4,14 @@
*/ */
export default { export default {
_audio: new Audio(), _audio: new Audio(),
_context: new AudioContext(), _context: null,
_source: null, _source: null,
_gain: null, _gain: null,
// setup audio routing // setup audio routing
setupAudio () { setupAudio () {
var AudioContext = window.AudioContext || window.webkitAudioContext
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()
@ -38,7 +40,6 @@ export default {
playSource (source) { playSource (source) {
this.stopAudio() this.stopAudio()
this._context.resume().then(() => { this._context.resume().then(() => {
console.log('playSource')
this._audio.src = String(source || '') + '?x=' + Date.now() this._audio.src = String(source || '') + '?x=' + Date.now()
this._audio.crossOrigin = 'anonymous' this._audio.crossOrigin = 'anonymous'
this._audio.load() this._audio.load()

View File

@ -98,7 +98,7 @@ export default {
}, },
open_genre: function () { open_genre: function () {
this.$router.push({ name: 'Genre', params: { genre: this.item.name } }) this.$router.push({ name: 'Genre', params: { genre: this.item.genre } })
} }
} }
} }

View File

@ -8,9 +8,14 @@
<p class="title is-4">{{ artist.name }}</p> <p class="title is-4">{{ artist.name }}</p>
</template> </template>
<template slot="heading-right"> <template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
</div>
</template> </template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_artist">{{ artist.album_count }} albums</a> | {{ artist.track_count }} tracks</p> <p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_artist">{{ artist.album_count }} albums</a> | {{ artist.track_count }} tracks</p>
@ -22,6 +27,7 @@
</template> </template>
</list-item-track> </list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" /> <modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
<modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>
@ -33,6 +39,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import IndexButtonList from '@/components/IndexButtonList' import IndexButtonList from '@/components/IndexButtonList'
import ListItemTrack from '@/components/ListItemTrack' import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack' import ModalDialogTrack from '@/components/ModalDialogTrack'
import ModalDialogArtist from '@/components/ModalDialogArtist'
import webapi from '@/webapi' import webapi from '@/webapi'
const tracksData = { const tracksData = {
@ -52,7 +59,7 @@ const tracksData = {
export default { export default {
name: 'PageArtistTracks', name: 'PageArtistTracks',
mixins: [ LoadDataBeforeEnterMixin(tracksData) ], mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
components: { ContentWithHeading, ListItemTrack, IndexButtonList, ModalDialogTrack }, components: { ContentWithHeading, ListItemTrack, IndexButtonList, ModalDialogTrack, ModalDialogArtist },
data () { data () {
return { return {
@ -60,7 +67,9 @@ export default {
tracks: { items: [] }, tracks: { items: [] },
show_details_modal: false, show_details_modal: false,
selected_track: {} selected_track: {},
show_artist_details_modal: false
} }
}, },

View File

@ -8,9 +8,14 @@
<p class="title is-4">{{ name }}</p> <p class="title is-4">{{ name }}</p>
</template> </template>
<template slot="heading-right"> <template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_genre_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
</div>
</template> </template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile">{{ genre_albums.total }} albums | <a class="has-text-link" @click="open_tracks">tracks</a></p> <p class="heading has-text-centered-mobile">{{ genre_albums.total }} albums | <a class="has-text-link" @click="open_tracks">tracks</a></p>
@ -22,6 +27,7 @@
</template> </template>
</list-item-albums> </list-item-albums>
<modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" /> <modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
<modal-dialog-genre :show="show_genre_details_modal" :genre="{ 'name': name }" @close="show_genre_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>
@ -34,6 +40,7 @@ import TabsMusic from '@/components/TabsMusic'
import IndexButtonList from '@/components/IndexButtonList' import IndexButtonList from '@/components/IndexButtonList'
import ListItemAlbums from '@/components/ListItemAlbum' import ListItemAlbums from '@/components/ListItemAlbum'
import ModalDialogAlbum from '@/components/ModalDialogAlbum' import ModalDialogAlbum from '@/components/ModalDialogAlbum'
import ModalDialogGenre from '@/components/ModalDialogGenre'
import webapi from '@/webapi' import webapi from '@/webapi'
const genreData = { const genreData = {
@ -50,7 +57,7 @@ const genreData = {
export default { export default {
name: 'PageGenre', name: 'PageGenre',
mixins: [ LoadDataBeforeEnterMixin(genreData) ], mixins: [ LoadDataBeforeEnterMixin(genreData) ],
components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbums, ModalDialogAlbum }, components: { ContentWithHeading, TabsMusic, IndexButtonList, ListItemAlbums, ModalDialogAlbum, ModalDialogGenre },
data () { data () {
return { return {
@ -58,7 +65,9 @@ export default {
genre_albums: { items: [] }, genre_albums: { items: [] },
show_details_modal: false, show_details_modal: false,
selected_album: {} selected_album: {},
show_genre_details_modal: false
} }
}, },

View File

@ -8,9 +8,14 @@
<p class="title is-4">{{ genre }}</p> <p class="title is-4">{{ genre }}</p>
</template> </template>
<template slot="heading-right"> <template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_genre_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
</div>
</template> </template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_genre">albums</a> | {{ tracks.total }} tracks</p> <p class="heading has-text-centered-mobile"><a class="has-text-link" @click="open_genre">albums</a> | {{ tracks.total }} tracks</p>
@ -22,6 +27,7 @@
</template> </template>
</list-item-track> </list-item-track>
<modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" /> <modal-dialog-track :show="show_details_modal" :track="selected_track" @close="show_details_modal = false" />
<modal-dialog-genre :show="show_genre_details_modal" :genre="{ 'name': genre }" @close="show_genre_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>
@ -33,6 +39,7 @@ import ContentWithHeading from '@/templates/ContentWithHeading'
import IndexButtonList from '@/components/IndexButtonList' import IndexButtonList from '@/components/IndexButtonList'
import ListItemTrack from '@/components/ListItemTrack' import ListItemTrack from '@/components/ListItemTrack'
import ModalDialogTrack from '@/components/ModalDialogTrack' import ModalDialogTrack from '@/components/ModalDialogTrack'
import ModalDialogGenre from '@/components/ModalDialogGenre'
import webapi from '@/webapi' import webapi from '@/webapi'
const tracksData = { const tracksData = {
@ -49,7 +56,7 @@ const tracksData = {
export default { export default {
name: 'PageGenreTracks', name: 'PageGenreTracks',
mixins: [ LoadDataBeforeEnterMixin(tracksData) ], mixins: [ LoadDataBeforeEnterMixin(tracksData) ],
components: { ContentWithHeading, ListItemTrack, IndexButtonList, ModalDialogTrack }, components: { ContentWithHeading, ListItemTrack, IndexButtonList, ModalDialogTrack, ModalDialogGenre },
data () { data () {
return { return {
@ -57,7 +64,9 @@ export default {
genre: '', genre: '',
show_details_modal: false, show_details_modal: false,
selected_track: {} selected_track: {},
show_genre_details_modal: false
} }
}, },

View File

@ -5,9 +5,14 @@
<a class="title is-4 has-text-link has-text-weight-normal" @click="open_artist">{{ album.artists[0].name }}</a> <a class="title is-4 has-text-link has-text-weight-normal" @click="open_artist">{{ album.artists[0].name }}</a>
</template> </template>
<template slot="heading-right"> <template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_album_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
</div>
</template> </template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile">{{ album.tracks.total }} tracks</p> <p class="heading has-text-centered-mobile">{{ album.tracks.total }} tracks</p>
@ -19,6 +24,7 @@
</template> </template>
</spotify-list-item-track> </spotify-list-item-track>
<spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="album" @close="show_track_details_modal = false" /> <spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="album" @close="show_track_details_modal = false" />
<spotify-modal-dialog-album :show="show_album_details_modal" :album="album" @close="show_album_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>
@ -28,6 +34,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading' import ContentWithHeading from '@/templates/ContentWithHeading'
import SpotifyListItemTrack from '@/components/SpotifyListItemTrack' import SpotifyListItemTrack from '@/components/SpotifyListItemTrack'
import SpotifyModalDialogTrack from '@/components/SpotifyModalDialogTrack' import SpotifyModalDialogTrack from '@/components/SpotifyModalDialogTrack'
import SpotifyModalDialogAlbum from '@/components/SpotifyModalDialogAlbum'
import store from '@/store' import store from '@/store'
import webapi from '@/webapi' import webapi from '@/webapi'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
@ -47,14 +54,16 @@ const albumData = {
export default { export default {
name: 'PageAlbum', name: 'PageAlbum',
mixins: [ LoadDataBeforeEnterMixin(albumData) ], mixins: [ LoadDataBeforeEnterMixin(albumData) ],
components: { ContentWithHeading, SpotifyListItemTrack, SpotifyModalDialogTrack }, components: { ContentWithHeading, SpotifyListItemTrack, SpotifyModalDialogTrack, SpotifyModalDialogAlbum },
data () { data () {
return { return {
album: { artists: [{}], tracks: {} }, album: { artists: [{}], tracks: {} },
show_track_details_modal: false, show_track_details_modal: false,
selected_track: {} selected_track: {},
show_album_details_modal: false
} }
}, },

View File

@ -3,6 +3,16 @@
<template slot="heading-left"> <template slot="heading-left">
<p class="title is-4">{{ artist.name }}</p> <p class="title is-4">{{ artist.name }}</p>
</template> </template>
<template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_artist_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a>
</div>
</template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile">{{ total }} albums</p> <p class="heading has-text-centered-mobile">{{ total }} albums</p>
<spotify-list-item-album v-for="album in albums" :key="album.id" :album="album"> <spotify-list-item-album v-for="album in albums" :key="album.id" :album="album">
@ -14,6 +24,7 @@
</spotify-list-item-album> </spotify-list-item-album>
<infinite-loading v-if="offset < total" @infinite="load_next"><span slot="no-more">.</span></infinite-loading> <infinite-loading v-if="offset < total" @infinite="load_next"><span slot="no-more">.</span></infinite-loading>
<spotify-modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" /> <spotify-modal-dialog-album :show="show_details_modal" :album="selected_album" @close="show_details_modal = false" />
<spotify-modal-dialog-artist :show="show_artist_details_modal" :artist="artist" @close="show_artist_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>
@ -23,7 +34,9 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading' import ContentWithHeading from '@/templates/ContentWithHeading'
import SpotifyListItemAlbum from '@/components/SpotifyListItemAlbum' import SpotifyListItemAlbum from '@/components/SpotifyListItemAlbum'
import SpotifyModalDialogAlbum from '@/components/SpotifyModalDialogAlbum' import SpotifyModalDialogAlbum from '@/components/SpotifyModalDialogAlbum'
import SpotifyModalDialogArtist from '@/components/SpotifyModalDialogArtist'
import store from '@/store' import store from '@/store'
import webapi from '@/webapi'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import InfiniteLoading from 'vue-infinite-loading' import InfiniteLoading from 'vue-infinite-loading'
@ -50,7 +63,7 @@ const artistData = {
export default { export default {
name: 'SpotifyPageArtist', name: 'SpotifyPageArtist',
mixins: [ LoadDataBeforeEnterMixin(artistData) ], mixins: [ LoadDataBeforeEnterMixin(artistData) ],
components: { ContentWithHeading, SpotifyListItemAlbum, SpotifyModalDialogAlbum, InfiniteLoading }, components: { ContentWithHeading, SpotifyListItemAlbum, SpotifyModalDialogAlbum, SpotifyModalDialogArtist, InfiniteLoading },
data () { data () {
return { return {
@ -60,7 +73,9 @@ export default {
offset: 0, offset: 0,
show_details_modal: false, show_details_modal: false,
selected_album: {} selected_album: {},
show_artist_details_modal: false
} }
}, },
@ -86,6 +101,11 @@ export default {
} }
}, },
play: function () {
this.show_details_modal = false
webapi.player_play_uri(this.artist.uri, true)
},
open_dialog: function (album) { open_dialog: function (album) {
this.selected_album = album this.selected_album = album
this.show_details_modal = true this.show_details_modal = true

View File

@ -4,9 +4,14 @@
<div class="title is-4">{{ playlist.name }}</div> <div class="title is-4">{{ playlist.name }}</div>
</template> </template>
<template slot="heading-right"> <template slot="heading-right">
<div class="buttons is-centered">
<a class="button is-small is-light is-rounded" @click="show_playlist_details_modal = true">
<span class="icon"><i class="mdi mdi-dots-horizontal mdi-18px"></i></span>
</a>
<a class="button is-small is-dark is-rounded" @click="play"> <a class="button is-small is-dark is-rounded" @click="play">
<span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span> <span class="icon"><i class="mdi mdi-shuffle"></i></span> <span>Shuffle</span>
</a> </a>
</div>
</template> </template>
<template slot="content"> <template slot="content">
<p class="heading has-text-centered-mobile">{{ playlist.tracks.total }} tracks</p> <p class="heading has-text-centered-mobile">{{ playlist.tracks.total }} tracks</p>
@ -19,6 +24,7 @@
</spotify-list-item-track> </spotify-list-item-track>
<infinite-loading v-if="offset < total" @infinite="load_next"><span slot="no-more">.</span></infinite-loading> <infinite-loading v-if="offset < total" @infinite="load_next"><span slot="no-more">.</span></infinite-loading>
<spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="selected_track.album" @close="show_track_details_modal = false" /> <spotify-modal-dialog-track :show="show_track_details_modal" :track="selected_track" :album="selected_track.album" @close="show_track_details_modal = false" />
<spotify-modal-dialog-playlist :show="show_playlist_details_modal" :playlist="playlist" @close="show_playlist_details_modal = false" />
</template> </template>
</content-with-heading> </content-with-heading>
</template> </template>
@ -28,6 +34,7 @@ import { LoadDataBeforeEnterMixin } from './mixin'
import ContentWithHeading from '@/templates/ContentWithHeading' import ContentWithHeading from '@/templates/ContentWithHeading'
import SpotifyListItemTrack from '@/components/SpotifyListItemTrack' import SpotifyListItemTrack from '@/components/SpotifyListItemTrack'
import SpotifyModalDialogTrack from '@/components/SpotifyModalDialogTrack' import SpotifyModalDialogTrack from '@/components/SpotifyModalDialogTrack'
import SpotifyModalDialogPlaylist from '@/components/SpotifyModalDialogPlaylist'
import store from '@/store' import store from '@/store'
import webapi from '@/webapi' import webapi from '@/webapi'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
@ -55,7 +62,7 @@ const playlistData = {
export default { export default {
name: 'SpotifyPagePlaylist', name: 'SpotifyPagePlaylist',
mixins: [ LoadDataBeforeEnterMixin(playlistData) ], mixins: [ LoadDataBeforeEnterMixin(playlistData) ],
components: { ContentWithHeading, SpotifyListItemTrack, SpotifyModalDialogTrack, InfiniteLoading }, components: { ContentWithHeading, SpotifyListItemTrack, SpotifyModalDialogTrack, SpotifyModalDialogPlaylist, InfiniteLoading },
data () { data () {
return { return {
@ -65,7 +72,9 @@ export default {
offset: 0, offset: 0,
show_track_details_modal: false, show_track_details_modal: false,
selected_track: {} selected_track: {},
show_playlist_details_modal: false
} }
}, },