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

See #432: added artist widget

parent be91b56f
No related branches found
No related tags found
No related merge requests found
<template>
<div class="wrapper">
<h3 class="ui header">
<slot name="title"></slot>
<span class="ui tiny circular label">{{ count }}</span>
</h3>
<button v-if="controls" :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle left', 'icon']"></i></button>
<button v-if="controls" :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle right', 'icon']"></i></button>
<button v-if="controls" @click="fetchData('artists/')" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
<div class="ui hidden divider"></div>
<div class="ui three cards">
<div v-if="isLoading" class="ui inverted active dimmer">
<div class="ui loader"></div>
</div>
<div class="flat inline card" v-for="object in objects" :key="object.id">
<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 v-if="!isLoading && objects.length === 0">No results matching your query.</div>
</div>
</template>
<script>
import _ from '@/lodash'
import axios from 'axios'
import PlayButton from '@/components/audio/PlayButton'
import TagsList from "@/components/tags/List"
export default {
props: {
filters: {type: Object, required: true},
controls: {type: Boolean, default: true},
},
components: {
PlayButton,
TagsList
},
data () {
return {
objects: [],
limit: 12,
count: 0,
isLoading: false,
errors: null,
previousPage: null,
nextPage: null
}
},
created () {
this.fetchData('artists/')
},
methods: {
fetchData (url) {
if (!url) {
return
}
this.isLoading = true
let self = this
let params = _.clone(this.filters)
params.page_size = this.limit
params.offset = this.offset
axios.get(url, {params: params}).then((response) => {
self.previousPage = response.data.previous
self.nextPage = response.data.next
self.isLoading = false
self.objects = response.data.results
self.count = response.data.count
}, error => {
self.isLoading = false
self.errors = error.backendErrors
})
},
updateOffset (increment) {
if (increment) {
this.offset += this.limit
} else {
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: {
offset () {
this.fetchData()
},
"$store.state.moderation.lastUpdate": function () {
this.fetchData('objects/')
}
}
}
</script>
<style scoped lang="scss">
@import "../../../style/vendor/media";
.default-cover {
background-image: url("../../../assets/audio/default-cover.png") !important;
}
.wrapper {
width: 100%;
}
.ui.cards {
justify-content: flex-start;
}
.play-button {
position: absolute;
right: 0;
bottom: 0;
}
.ui.three.cards .card {
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>
.ui.cards .ui.button {
margin-right: 0px;
}
</style>
<template>
<div>
<div class="tag-list">
<router-link
:to="{name: 'library.tags.detail', params: {id: tag}}"
class="ui circular hashtag label"
:class="['ui', 'circular', 'hashtag', 'label', labelClasses]"
v-for="tag in toDisplay"
:title="tag"
:key="tag">
#{{ tag }}
#{{ tag|truncate(truncateSize) }}
</router-link>
<div role="button" @click.prevent="honorLimit = false" class="ui circular inverted teal label" v-if="toDisplay.length < tags.length">
<div role="button" @click.prevent="honorLimit = false" class="ui circular inverted teal label" v-if="showMore && toDisplay.length < tags.length">
<translate translate-context="Content/*/Button/Label/Verb" :translate-params="{count: tags.length - toDisplay.length}" :translate-n="tags.length - toDisplay.length" translate-plural="Show %{ count } more tags">Show 1 more tag</translate>
</div>
</div>
</template>
<script>
export default {
props: ['tags'],
props: {
tags: {type: Array, required: true},
showMore: {type: Boolean, default: true},
truncateSize: {type: Number, default: 25},
limit: {type: Number, default: 5},
labelClasses: {type: String, default: ''},
},
data () {
return {
limit: 5,
honorLimit: true,
}
},
......@@ -36,4 +42,7 @@ export default {
padding-left: 1em !important;
padding-right: 1em !important;
}
.hashtag {
margin: 0.25em;
}
</style>
......@@ -342,6 +342,20 @@ td.align.right {
word-wrap: break-word;
}
.ui.cards > .flat.card, .flat.card {
box-shadow: none;
.content {
border: none;
}
}
.ui.cards > .inline.card {
flex-direction: row;
.content {
padding: 0.5em 0.75em;
}
}
.ui.checkbox label {
cursor: pointer;
}
......@@ -355,6 +369,9 @@ input + .help {
}
.tag-list {
margin-top: 1em;
}
@import "./themes/_light.scss";
@import "./themes/_dark.scss";
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment