mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-13 21:12:56 -04:00
[web-src] Show album cover artwork in album page
This commit is contained in:
parent
a2ec7ee28f
commit
d2b5e82837
1442
web-src/package-lock.json
generated
1442
web-src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "forked-daapd-web",
|
"name": "forked-daapd-web",
|
||||||
"version": "0.7.1",
|
"version": "0.7.2",
|
||||||
"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>",
|
||||||
@ -15,11 +15,11 @@
|
|||||||
"bulma": "^0.8.2",
|
"bulma": "^0.8.2",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"mdi": "^2.2.43",
|
"mdi": "^2.2.43",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.25.3",
|
||||||
"moment-duration-format": "^2.3.2",
|
"moment-duration-format": "^2.3.2",
|
||||||
"npm": "^6.14.4",
|
"npm": "^6.14.5",
|
||||||
"reconnectingwebsocket": "^1.0.0",
|
"reconnectingwebsocket": "^1.0.0",
|
||||||
"spotify-web-api-js": "^1.2.0",
|
"spotify-web-api-js": "^1.4.0",
|
||||||
"string-to-color": "^2.1.3",
|
"string-to-color": "^2.1.3",
|
||||||
"v-click-outside": "^3.0.1",
|
"v-click-outside": "^3.0.1",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
@ -27,8 +27,9 @@
|
|||||||
"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.1.6",
|
"vue-router": "^3.1.6",
|
||||||
|
"vue-tiny-lazyload-img": "^0.1.0",
|
||||||
"vuedraggable": "^2.23.2",
|
"vuedraggable": "^2.23.2",
|
||||||
"vuex": "^3.1.3"
|
"vuex": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.3.1",
|
"@vue/cli-plugin-babel": "^4.3.1",
|
||||||
@ -42,6 +43,8 @@
|
|||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"eslint-plugin-standard": "^4.0.1",
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
|
"sass": "^1.26.5",
|
||||||
|
"sass-loader": "^8.0.2",
|
||||||
"vue-template-compiler": "^2.6.11"
|
"vue-template-compiler": "^2.6.11"
|
||||||
},
|
},
|
||||||
"license": "GPL-2.0"
|
"license": "GPL-2.0"
|
||||||
|
@ -1,15 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<figure>
|
<figure>
|
||||||
<img
|
<img v-lazyload
|
||||||
v-show="artwork_visible"
|
|
||||||
:src="artwork_url_with_size"
|
|
||||||
@load="artwork_loaded"
|
|
||||||
@error="artwork_error"
|
|
||||||
@click="$emit('click')">
|
|
||||||
<img
|
|
||||||
v-show="!artwork_visible"
|
|
||||||
:src="dataURI"
|
:src="dataURI"
|
||||||
:alt="alt_text"
|
:data-src="artwork_url_with_size"
|
||||||
|
:data-err="dataURI"
|
||||||
@click="$emit('click')">
|
@click="$emit('click')">
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
@ -30,9 +24,7 @@ export default {
|
|||||||
height: 600,
|
height: 600,
|
||||||
font_family: 'sans-serif',
|
font_family: 'sans-serif',
|
||||||
font_size: 200,
|
font_size: 200,
|
||||||
font_weight: 600,
|
font_weight: 600
|
||||||
|
|
||||||
artwork_visible: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -95,16 +87,6 @@ export default {
|
|||||||
dataURI () {
|
dataURI () {
|
||||||
return this.svg.render(this.rendererParams)
|
return this.svg.render(this.rendererParams)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
artwork_loaded: function () {
|
|
||||||
this.artwork_visible = true
|
|
||||||
},
|
|
||||||
|
|
||||||
artwork_error: function () {
|
|
||||||
this.artwork_visible = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
<template functional>
|
<template functional>
|
||||||
<div class="media" :id="'index_' + props.album.name_sort.charAt(0).toUpperCase()">
|
<div class="media" :id="'index_' + props.album.name_sort.charAt(0).toUpperCase()">
|
||||||
|
<slot name="artwork"></slot>
|
||||||
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
<div class="media-content fd-has-action is-clipped" @click="listeners.click">
|
||||||
<h1 class="title is-6">{{ props.album.name }}</h1>
|
<div style="margin-top:0.7rem;">
|
||||||
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2>
|
<h1 class="title is-6">{{ props.album.name }}</h1>
|
||||||
|
<h2 class="subtitle is-7 has-text-grey"><b>{{ props.album.artist }}</b></h2>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-right">
|
<div class="media-right" style="padding-top:0.7rem;">
|
||||||
<slot name="actions"></slot>
|
<slot name="actions"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,14 +7,14 @@ import store from './store'
|
|||||||
import './filter'
|
import './filter'
|
||||||
import './progress'
|
import './progress'
|
||||||
import vClickOutside from 'v-click-outside'
|
import vClickOutside from 'v-click-outside'
|
||||||
import 'bulma/css/bulma.css'
|
import VueTinyLazyloadImg from 'vue-tiny-lazyload-img'
|
||||||
import 'mdi/css/materialdesignicons.css'
|
import 'mdi/css/materialdesignicons.css'
|
||||||
import 'vue-range-slider/dist/vue-range-slider.css'
|
import 'vue-range-slider/dist/vue-range-slider.css'
|
||||||
import './mystyles.css'
|
import './mystyles.scss'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
Vue.use(vClickOutside)
|
Vue.use(vClickOutside)
|
||||||
|
Vue.use(VueTinyLazyloadImg)
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
new Vue({
|
new Vue({
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
@import 'bulma';
|
||||||
|
|
||||||
|
|
||||||
.slider {
|
.slider {
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -246,4 +249,32 @@ hr.fd-navbar-divider {
|
|||||||
.fd-bottom-navbar .navbar-menu {
|
.fd-bottom-navbar .navbar-menu {
|
||||||
max-height: calc(100vh - 3.25rem - 3.25rem - 1rem);
|
max-height: calc(100vh - 3.25rem - 3.25rem - 1rem);
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
@include mobile {
|
||||||
|
&.fd-is-centered-mobile {
|
||||||
|
justify-content: center;
|
||||||
|
&:not(.has-addons) {
|
||||||
|
.button:not(.is-fullwidth) {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
&.fd-has-cover {
|
||||||
|
max-height: 256px;
|
||||||
|
max-width: 256px;
|
||||||
|
@include mobile {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
@include from($tablet) {
|
||||||
|
margin: auto 0 auto auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,21 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<content-with-heading>
|
<content-with-hero>
|
||||||
<template slot="heading-left">
|
<template slot="heading-left">
|
||||||
<div class="title is-4">{{ album.name }}</div>
|
<h1 class="title is-4 fd-has-margin-top">{{ album.name }}</h1>
|
||||||
<a class="title is-4 has-text-link has-text-weight-normal" @click="open_artist">{{ album.artist }}</a>
|
<h2 class="subtitle is-4 has-text-link has-text-weight-normal"><a class="has-text-link" @click="open_artist">{{ album.artist }}</a></h2>
|
||||||
</template>
|
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
|
||||||
<template slot="heading-right">
|
|
||||||
<div class="buttons is-centered">
|
<div class="buttons fd-is-centered-mobile fd-has-margin-top">
|
||||||
<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>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template slot="heading-right">
|
||||||
|
<p class="image is-square fd-has-shadow">
|
||||||
|
<cover-artwork
|
||||||
|
:artwork_url="album.artwork_url"
|
||||||
|
:artist="album.artist"
|
||||||
|
:album="album.name"
|
||||||
|
class="" />
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<p class="heading has-text-centered-mobile">{{ album.track_count }} tracks</p>
|
|
||||||
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" @click="play_track(index)">
|
<list-item-track v-for="(track, index) in tracks" :key="track.id" :track="track" @click="play_track(index)">
|
||||||
<template slot="actions">
|
<template slot="actions">
|
||||||
<a @click="open_dialog(track)">
|
<a @click="open_dialog(track)">
|
||||||
@ -26,15 +34,16 @@
|
|||||||
<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-album :show="show_album_details_modal" :album="album" @close="show_album_details_modal = false" />
|
<modal-dialog-album :show="show_album_details_modal" :album="album" @close="show_album_details_modal = false" />
|
||||||
</template>
|
</template>
|
||||||
</content-with-heading>
|
</content-with-hero>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { LoadDataBeforeEnterMixin } from './mixin'
|
import { LoadDataBeforeEnterMixin } from './mixin'
|
||||||
import ContentWithHeading from '@/templates/ContentWithHeading'
|
import ContentWithHero from '@/templates/ContentWithHero'
|
||||||
import ListItemTrack from '@/components/ListItemTrack'
|
import ListItemTrack from '@/components/ListItemTrack'
|
||||||
import ModalDialogTrack from '@/components/ModalDialogTrack'
|
import ModalDialogTrack from '@/components/ModalDialogTrack'
|
||||||
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
|
import ModalDialogAlbum from '@/components/ModalDialogAlbum'
|
||||||
|
import CoverArtwork from '@/components/CoverArtwork'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
const albumData = {
|
const albumData = {
|
||||||
@ -54,7 +63,7 @@ const albumData = {
|
|||||||
export default {
|
export default {
|
||||||
name: 'PageAlbum',
|
name: 'PageAlbum',
|
||||||
mixins: [LoadDataBeforeEnterMixin(albumData)],
|
mixins: [LoadDataBeforeEnterMixin(albumData)],
|
||||||
components: { ContentWithHeading, ListItemTrack, ModalDialogTrack, ModalDialogAlbum },
|
components: { ContentWithHero, ListItemTrack, ModalDialogTrack, ModalDialogAlbum, CoverArtwork },
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
44
web-src/src/templates/ContentWithHero.vue
Normal file
44
web-src/src/templates/ContentWithHero.vue
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<section class="hero is-light is-bold fd-content">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-four-fifths">
|
||||||
|
<div class="columns" style="flex-direction: row-reverse;">
|
||||||
|
<div class="column fd-has-cover">
|
||||||
|
<!-- Slot heading right -->
|
||||||
|
<slot name="heading-right"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="column is-three-fifths has-text-centered-mobile">
|
||||||
|
<!-- Slot heading left -->
|
||||||
|
<slot name="heading-left"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="section fd-content">
|
||||||
|
<div class="container">
|
||||||
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-four-fifths">
|
||||||
|
<!-- Slot content -->
|
||||||
|
<slot name="content"></slot>
|
||||||
|
<div style="margin-top: 16px;">
|
||||||
|
<!-- Slot footer -->
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user