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

See #432: added tag detail page

parent 3e9bda24
No related branches found
No related tags found
No related merge requests found
......@@ -2,10 +2,11 @@
<div class="wrapper">
<h3 class="ui header">
<slot name="title"></slot>
<span v-if="showCount" class="ui tiny circular label">{{ count }}</span>
</h3>
<button :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle left', 'icon']"></i></button>
<button :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle right', 'icon']"></i></button>
<button @click="fetchData('albums/')" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
<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('albums/')" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
<div class="ui hidden divider"></div>
<div class="ui five cards">
<div v-if="isLoading" class="ui inverted active dimmer">
......@@ -33,6 +34,7 @@
</div>
</div>
</div>
<div v-if="!isLoading && albums.length === 0">No results matching your query.</div>
</div>
</template>
......@@ -43,7 +45,9 @@ import PlayButton from '@/components/audio/PlayButton'
export default {
props: {
filters: {type: Object, required: true}
filters: {type: Object, required: true},
controls: {type: Boolean, default: true},
showCount: {type: Boolean, default: false},
},
components: {
PlayButton
......@@ -52,6 +56,7 @@ export default {
return {
albums: [],
limit: 12,
count: 0,
isLoading: false,
errors: null,
previousPage: null,
......@@ -76,6 +81,7 @@ export default {
self.nextPage = response.data.next
self.isLoading = false
self.albums = response.data.results
self.count = response.data.count
}, error => {
self.isLoading = false
self.errors = error.backendErrors
......
......@@ -142,8 +142,14 @@ export default {
right: 0;
bottom: 0;
}
.ui.three.cards .card {
width: 25em;
width: 100%;
}
@include media(">tablet") {
.ui.three.cards .card {
width: 25em;
}
}
.with-overlay {
background-size: cover !important;
......
......@@ -2,12 +2,13 @@
<div>
<h3 class="ui header">
<slot name="title"></slot>
<span v-if="showCount" class="ui tiny circular label">{{ count }}</span>
</h3>
<button :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle up', 'icon']"></i></button>
<button :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle down', 'icon']"></i></button>
<button @click="fetchData(url)" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
<div class="ui divided unstackable items">
<div class="item" v-for="object in objects" :key="object.id">
<div :class="['item', itemClasses]" v-for="object in objects" :key="object.id">
<div class="ui tiny image">
<img v-if="object.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.medium_square_crop)">
<img v-else src="../../../assets/audio/default-cover.png">
......@@ -28,7 +29,9 @@
</router-link>
</span>
</div>
<div class="extra">
<tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="object.track.tags"></tags-list>
<div class="extra" v-if="isActivity">
<span class="left floated">@{{ object.user.username }}</span>
<span class="right floated"><human-date :date="object.creation_date" /></span>
</div>
......@@ -50,19 +53,25 @@
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},
url: {type: String, required: true}
url: {type: String, required: true},
isActivity: {type: Boolean, default: true},
showCount: {type: Boolean, default: false},
limit: {type: Number, default: 5},
itemClasses: {type: String, default: ''},
},
components: {
PlayButton
PlayButton,
TagsList
},
data () {
return {
objects: [],
limit: 5,
count: 0,
isLoading: false,
errors: null,
previousPage: null,
......@@ -86,7 +95,15 @@ export default {
self.previousPage = response.data.previous
self.nextPage = response.data.next
self.isLoading = false
self.objects = response.data.results
self.count = response.data.count
if (self.isActivity) {
// we have listening/favorites objects, not directly tracks
self.objects = response.data.results
} else {
self.objects = response.data.results.map((r) => {
return {track: r}
})
}
}, error => {
self.isLoading = false
self.errors = error.backendErrors
......@@ -129,4 +146,18 @@ export default {
.ui.divided.items > .item:last-child {
padding-bottom: 1em !important;
}
@include media(">tablet") {
.divided.items > .track-item.inline {
width: 25em;
float: left;
border-top: none;
&,
&:first-child {
margin-top: 0.5em !important;
margin-right: 0.5em !important;
padding: 1em 0 !important;
}
}
}
</style>
<template>
<main v-title="labels.title">
<section class="ui vertical stripe segment">
<h2 class="ui header">
<span class="ui circular huge hashtag label">
{{ labels.title }}
</span>
</h2>
<div class="ui hidden divider"></div>
<div class="ui row">
<artist-widget :controls="false" :filters="{playable: true, ordering: '-creation_date', tag: id}">
<template slot="title">
<router-link :to="{name: 'library.artists.browse', query: {tag: id}}">
<translate translate-context="*/*/*">Artists</translate>
</router-link>
</template>
</artist-widget>
<div class="ui hidden divider"></div>
<div class="ui hidden divider"></div>
<album-widget :show-count="true" :controls="false" :filters="{playable: true, ordering: '-creation_date', tag: id}">
<template slot="title">
<router-link :to="{name: 'library.albums.browse', query: {tag: id}}">
<translate translate-context="*/*/*">Albums</translate>
</router-link>
</template>
</album-widget>
<div class="ui hidden divider"></div>
<div class="ui hidden divider"></div>
<track-widget :show-count="true" :limit="12" item-classes="track-item inline" :url="'/tracks/'" :is-activity="false" :filters="{playable: true, ordering: '-creation_date', tag: id}">
<template slot="title">
<translate translate-context="*/*/*">Tracks</translate>
</template>
</track-widget>
<div class="ui clearing hidden divider"></div>
</div>
</section>
</main>
</template>
<script>
import TrackWidget from "@/components/audio/track/Widget"
import AlbumWidget from "@/components/audio/album/Widget"
import ArtistWidget from "@/components/audio/artist/Widget"
export default {
props: {
id: { type: String, required: true }
},
components: {
ArtistWidget,
AlbumWidget,
TrackWidget,
},
computed: {
labels() {
let title = `#${this.id}`
return {
title
}
},
isAuthenticated () {
return this.$store.state.auth.authenticated
},
hasFavorites () {
return this.$store.state.favorites.count > 0
},
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.ui.circular.label {
padding-left: 1em !important;
padding-right: 1em !important;
}
</style>
......@@ -473,6 +473,13 @@ export default new Router({
id: route.params.id,
defaultEdit: route.query.mode === 'edit' })
},
{
path: 'tags/:id',
name: 'library.tags.detail',
component: () =>
import(/* webpackChunkName: "core" */ "@/components/library/TagDetail"),
props: true,
},
{
path: 'artists/:id',
component: () =>
......
......@@ -370,7 +370,7 @@ input + .help {
.tag-list {
margin-top: 1em;
margin-top: 0.5em;
}
@import "./themes/_light.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