Skip to content
Snippets Groups Projects
Verified Commit 5d1d5489 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Enhance artists list by using our new artist card and remove masonry

parent c885c10b
No related branches found
No related tags found
No related merge requests found
<template> <template>
<div class="ui card"> <div class="flat inline card">
<div :class="['ui', 'image', 'with-overlay', {'default-cover': !cover.original}]" v-lazy:background-image="imageUrl">
<play-button class="play-overlay" :icon-only="true" :is-playable="artist.is_playable" :button-classes="['ui', 'circular', 'large', 'orange', 'icon', 'button']" :artist="artist"></play-button>
</div>
<div class="content"> <div class="content">
<div class="header"> <router-link :title="artist.name" :to="{name: 'library.artists.detail', params: {id: artist.id}}">
<router-link class="discrete link" :to="{name: 'library.artists.detail', params: {id: artist.id }}"> {{ artist.name|truncate(30) }}
{{ artist.name }}
</router-link> </router-link>
</div> <div>
<div class="description"> <i class="small sound icon"></i>
<table class="ui compact very basic fixed single line unstackable table">
<tbody>
<tr v-for="album in albums">
<td>
<img class="ui mini image" v-if="album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](album.cover.small_square_crop)">
<img class="ui mini image" v-else src="../../../assets/audio/default-cover.png">
</td>
<td colspan="4">
<router-link :title="album.title" class="discrete link" :to="{name: 'library.albums.detail', params: {id: album.id }}">
<strong>{{ album.title }}</strong>
</router-link><br />
{{ album.tracks_count }} tracks
</td>
<td>
<play-button class="right floated basic icon" :is-playable="album.is_playable" :discrete="true" :album="album"></play-button>
</td>
</tr>
</tbody>
</table>
<div class="center aligned segment" v-if="artist.albums.length > initialAlbums">
<em v-if="!showAllAlbums" @click="showAllAlbums = true" class="expand">
<translate translate-context="Content/Artist/Card.Link" :translate-params="{count: artist.albums.length - initialAlbums}" :translate-n="artist.albums.length - initialAlbums" translate-plural="Show %{ count } more albums">Show 1 more album</translate>
</em>
<em v-else @click="showAllAlbums = false" class="expand">
<translate translate-context="Content/*/Card.Link/Verb">Collapse</translate>
</em>
</div>
</div>
</div>
<div class="extra content">
<span>
<i class="sound icon"></i>
<translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate> <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
</span> </div>
<play-button :is-playable="isPlayable" class="mini basic orange right floated" :artist="artist"> <tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="artist.tags"></tags-list>
<translate translate-context="Content/Queue/Button.Label/Short, Verb">Play all</translate>
</play-button> <play-button
class="play-button basic icon"
:dropdown-only="true"
:is-playable="artist.is_playable"
:dropdown-icon-classes="['ellipsis', 'vertical', 'large', 'grey']"
:artist="artist"></play-button>
</div> </div>
</div> </div>
</template> </template>
...@@ -51,11 +26,13 @@ ...@@ -51,11 +26,13 @@
<script> <script>
import backend from '@/audio/backend' import backend from '@/audio/backend'
import PlayButton from '@/components/audio/PlayButton' import PlayButton from '@/components/audio/PlayButton'
import TagsList from "@/components/tags/List"
export default { export default {
props: ['artist'], props: ['artist'],
components: { components: {
PlayButton PlayButton,
TagsList
}, },
data () { data () {
return { return {
...@@ -65,16 +42,23 @@ export default { ...@@ -65,16 +42,23 @@ export default {
} }
}, },
computed: { computed: {
albums () {
if (this.showAllAlbums) { imageUrl () {
return this.artist.albums let url = '../../../assets/audio/default-cover.png'
let cover = this.cover
if (cover.original) {
url = this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
} else {
return null
} }
return this.artist.albums.slice(0, this.initialAlbums) return url
}, },
isPlayable () { cover () {
return this.artist.albums.filter((a) => { return this.artist.albums.map((a) => {
return a.is_playable return a.cover
}).length > 0 }).filter((c) => {
return !!c
})[0] || {}
} }
} }
} }
...@@ -82,4 +66,27 @@ export default { ...@@ -82,4 +66,27 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> <style scoped>
.default-cover {
background-image: url("../../../assets/audio/default-cover.png") !important;
}
.play-button {
position: absolute;
right: 0;
bottom: 0;
}
.with-overlay {
background-size: cover !important;
background-position: center !important;
height: 8em;
width: 8em;
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.flat.card .with-overlay.image {
border-radius: 50% !important;
margin: 0 auto;
}
</style> </style>
<template> <template>
<div class="wrapper"> <div class="wrapper">
<h3 class="ui header"> <h3 v-if="header" class="ui header">
<slot name="title"></slot> <slot name="title"></slot>
<span class="ui tiny circular label">{{ count }}</span> <span class="ui tiny circular label">{{ count }}</span>
</h3> </h3>
...@@ -12,28 +12,7 @@ ...@@ -12,28 +12,7 @@
<div v-if="isLoading" class="ui inverted active dimmer"> <div v-if="isLoading" class="ui inverted active dimmer">
<div class="ui loader"></div> <div class="ui loader"></div>
</div> </div>
<div class="flat inline card" v-for="object in objects" :key="object.id"> <artist-card :artist="artist" v-for="artist in objects" :key="artist.id"></artist-card>
<div :class="['ui', 'image', 'with-overlay', {'default-cover': !getCover(object).original}]" v-lazy:background-image="getImageUrl(object)">
<play-button class="play-overlay" :icon-only="true" :is-playable="object.is_playable" :button-classes="['ui', 'circular', 'large', 'orange', 'icon', 'button']" :artist="object"></play-button>
</div>
<div class="content">
<router-link :title="object.name" :to="{name: 'library.artists.detail', params: {id: object.id}}">
{{ object.name|truncate(30) }}
</router-link>
<div>
<i class="small sound icon"></i>
<translate translate-context="Content/Artist/Card" :translate-params="{count: object.albums.length}" :translate-n="object.albums.length" translate-plural="%{ count } albums">1 album</translate>
</div>
<tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="object.tags"></tags-list>
<play-button
class="play-button basic icon"
:dropdown-only="true"
:is-playable="object.is_playable"
:dropdown-icon-classes="['ellipsis', 'vertical', 'large', 'grey']"
:artist="object"></play-button>
</div>
</div>
</div> </div>
<div v-if="!isLoading && objects.length === 0">No results matching your query.</div> <div v-if="!isLoading && objects.length === 0">No results matching your query.</div>
</div> </div>
...@@ -42,17 +21,16 @@ ...@@ -42,17 +21,16 @@
<script> <script>
import _ from '@/lodash' import _ from '@/lodash'
import axios from 'axios' import axios from 'axios'
import PlayButton from '@/components/audio/PlayButton' import ArtistCard from "@/components/audio/artist/Card"
import TagsList from "@/components/tags/List"
export default { export default {
props: { props: {
filters: {type: Object, required: true}, filters: {type: Object, required: true},
controls: {type: Boolean, default: true}, controls: {type: Boolean, default: true},
header: {type: Boolean, default: true},
}, },
components: { components: {
PlayButton, ArtistCard,
TagsList
}, },
data () { data () {
return { return {
...@@ -96,23 +74,6 @@ export default { ...@@ -96,23 +74,6 @@ export default {
this.offset = Math.max(this.offset - this.limit, 0) this.offset = Math.max(this.offset - this.limit, 0)
} }
}, },
getImageUrl (object) {
let url = '../../../assets/audio/default-cover.png'
let cover = this.getCover(object)
if (cover.original) {
url = this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
} else {
return null
}
return url
},
getCover (object) {
return object.albums.map((a) => {
return a.cover
}).filter((c) => {
return !!c
})[0] || {}
}
}, },
watch: { watch: {
offset () { offset () {
...@@ -127,21 +88,12 @@ export default { ...@@ -127,21 +88,12 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
@import "../../../style/vendor/media"; @import "../../../style/vendor/media";
.default-cover {
background-image: url("../../../assets/audio/default-cover.png") !important;
}
.wrapper { .wrapper {
width: 100%; width: 100%;
} }
.ui.cards { .ui.cards {
justify-content: flex-start; justify-content: flex-start;
} }
.play-button {
position: absolute;
right: 0;
bottom: 0;
}
.ui.three.cards .card { .ui.three.cards .card {
width: 100%; width: 100%;
...@@ -151,19 +103,6 @@ export default { ...@@ -151,19 +103,6 @@ export default {
width: 25em; width: 25em;
} }
} }
.with-overlay {
background-size: cover !important;
background-position: center !important;
height: 8em;
width: 8em;
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.flat.card .with-overlay.image {
border-radius: 50% !important;
margin: 0 auto;
}
</style> </style>
<style> <style>
.ui.cards .ui.button { .ui.cards .ui.button {
......
...@@ -35,27 +35,18 @@ ...@@ -35,27 +35,18 @@
<label><translate translate-context="Content/Search/Dropdown.Label/Noun">Results per page</translate></label> <label><translate translate-context="Content/Search/Dropdown.Label/Noun">Results per page</translate></label>
<select class="ui dropdown" v-model="paginateBy"> <select class="ui dropdown" v-model="paginateBy">
<option :value="parseInt(12)">12</option> <option :value="parseInt(12)">12</option>
<option :value="parseInt(25)">25</option> <option :value="parseInt(30)">30</option>
<option :value="parseInt(50)">50</option> <option :value="parseInt(50)">50</option>
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<div class="ui hidden divider"></div> <div class="ui hidden divider"></div>
<div <div v-if="result && result.results.length > 0" class="ui three cards">
v-if="result" <div v-if="isLoading" class="ui inverted active dimmer">
v-masonry <div class="ui loader"></div>
transition-duration="0"
item-selector=".card"
percent-position="true"
stagger="0">
<div v-if="result.results.length > 0" class="ui cards">
<artist-card
v-masonry-tile
v-for="artist in result.results"
:key="artist.id"
:artist="artist"></artist-card>
</div> </div>
<artist-card :artist="artist" v-for="artist in result.results" :key="artist.id"></artist-card>
</div> </div>
<div class="ui center aligned basic segment"> <div class="ui center aligned basic segment">
<pagination <pagination
...@@ -108,7 +99,7 @@ export default { ...@@ -108,7 +99,7 @@ export default {
page: parseInt(this.defaultPage), page: parseInt(this.defaultPage),
query: this.defaultQuery, query: this.defaultQuery,
tags: this.defaultTags.filter((t) => { return t.length > 0 }) || [], tags: this.defaultTags.filter((t) => { return t.length > 0 }) || [],
paginateBy: parseInt(this.defaultPaginateBy || 12), paginateBy: parseInt(this.defaultPaginateBy || 30),
orderingDirection: defaultOrdering.direction || "+", orderingDirection: defaultOrdering.direction || "+",
ordering: defaultOrdering.field, ordering: defaultOrdering.field,
orderingOptions: [["creation_date", "creation_date"], ["name", "name"]] orderingOptions: [["creation_date", "creation_date"], ["name", "name"]]
...@@ -205,5 +196,22 @@ export default { ...@@ -205,5 +196,22 @@ export default {
</script> </script>
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> <style scoped lang="scss">
@import "../../style/vendor/media";
.wrapper {
width: 100%;
}
.ui.cards {
justify-content: flex-start;
}
.ui.three.cards .card {
width: 100%;
}
@include media(">tablet") {
.ui.three.cards .card {
width: 25em;
}
}
</style> </style>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment