Add fallback to generic album cover for tracks with no album

This commit is contained in:
Ciaran Ainsworth 2022-02-10 13:22:58 +01:00
parent 3a48ae7e51
commit 9b1865e43e
2 changed files with 361 additions and 359 deletions

View File

@ -0,0 +1 @@
Fixed an issue where you couldn't load the details page for tracks with no associated album (#1703)

View File

@ -1,368 +1,369 @@
<template> <template>
<div v-if="track"> <div v-if="track">
<section class="ui vertical stripe segment"> <section class="ui vertical stripe segment">
<div class="ui stackable grid row container"> <div class="ui stackable grid row container">
<div class="six wide column"> <div class="six wide column">
<template v-if="upload"> <template v-if="upload">
<img <img
v-if="track.cover && track.cover.urls.large_square_crop" v-if="track.cover && track.cover.urls.large_square_crop"
v-lazy="$store.getters['instance/absoluteUrl'](track.cover.urls.large_square_crop)" v-lazy="
alt="Cover Image" $store.getters['instance/absoluteUrl'](
class="ui fluid image track-cover-image" track.cover.urls.large_square_crop
> )
<img "
v-else-if="track.album.cover && track.album.cover.urls.large_square_crop" alt="Cover Image"
v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.large_square_crop)" class="ui fluid image track-cover-image"
alt="Cover Image" />
class="ui fluid image track-cover-image" <img
> v-else-if="
<h3 class="ui header"> track.album &&
<translate track.album.cover &&
v-if="track.artist.content_category === 'music'" track.album.cover.urls.large_square_crop
key="1" "
translate-context="Content/*/*" v-lazy="
> $store.getters['instance/absoluteUrl'](
Track Details track.album.cover.urls.large_square_crop
</translate> )
<translate "
v-else alt="Cover Image"
key="2" class="ui fluid image track-cover-image"
translate-context="Content/*/*" />
> <img
Episode Details v-else
</translate> src="../../assets/embed/default-cover.jpeg"
</h3> alt="Cover Image"
<table class="ui basic table"> class="ui fluid image track-cover-image"
<tbody> />
<tr> <h3 class="ui header">
<td> <translate
<translate translate-context="Content/*/*"> v-if="track.artist.content_category === 'music'"
Duration key="1"
</translate> translate-context="Content/*/*"
</td> >
<td class="right aligned"> Track Details
<template v-if="upload.duration"> </translate>
{{ upload.duration | duration }} <translate v-else key="2" translate-context="Content/*/*">
</template> Episode Details
<translate </translate>
v-else </h3>
translate-context="*/*/*" <table class="ui basic table">
> <tbody>
N/A <tr>
</translate> <td>
</td> <translate translate-context="Content/*/*">
</tr> Duration
<tr> </translate>
<td> </td>
<translate translate-context="Content/*/*/Noun"> <td class="right aligned">
Size <template v-if="upload.duration">
</translate> {{ upload.duration | duration }}
</td> </template>
<td class="right aligned"> <translate v-else translate-context="*/*/*">
<template v-if="upload.size"> N/A
{{ upload.size | humanSize }} </translate>
</template> </td>
<translate </tr>
v-else <tr>
translate-context="*/*/*" <td>
> <translate translate-context="Content/*/*/Noun">
N/A Size
</translate> </translate>
</td> </td>
</tr> <td class="right aligned">
<tr> <template v-if="upload.size">
<td> {{ upload.size | humanSize }}
<translate translate-context="Content/*/*/Noun"> </template>
Codec <translate v-else translate-context="*/*/*">
</translate> N/A
</td> </translate>
<td class="right aligned"> </td>
<template v-if="upload.extension"> </tr>
{{ upload.extension }} <tr>
</template> <td>
<translate <translate translate-context="Content/*/*/Noun">
v-else Codec
translate-context="*/*/*" </translate>
> </td>
N/A <td class="right aligned">
</translate> <template v-if="upload.extension">
</td> {{ upload.extension }}
</tr> </template>
<tr> <translate v-else translate-context="*/*/*">
<td> N/A
<translate translate-context="Content/Track/*/Noun"> </translate>
Bitrate </td>
</translate> </tr>
</td> <tr>
<td class="right aligned"> <td>
<template v-if="upload.bitrate"> <translate translate-context="Content/Track/*/Noun">
{{ upload.bitrate | humanSize }}/s Bitrate
</template> </translate>
<translate </td>
v-else <td class="right aligned">
translate-context="*/*/*" <template v-if="upload.bitrate">
> {{ upload.bitrate | humanSize }}/s
N/A </template>
</translate> <translate v-else translate-context="*/*/*">
</td> N/A
</tr> </translate>
<tr> </td>
<td> </tr>
<translate translate-context="Content/*/*"> <tr>
Downloads <td>
</translate> <translate translate-context="Content/*/*">
</td> Downloads
<td class="right aligned"> </translate>
{{ track.downloads_count }} </td>
</td> <td class="right aligned">
</tr> {{ track.downloads_count }}
</tbody> </td>
</table> </tr>
</template> </tbody>
</div> </table>
<div class="ten wide column"> </template>
<template v-if="track.tags && track.tags.length > 0"> </div>
<tags-list :tags="track.tags" /> <div class="ten wide column">
<div class="ui hidden divider" /> <template v-if="track.tags && track.tags.length > 0">
</template> <tags-list :tags="track.tags" />
<div class="ui hidden divider" />
</template>
<rendered-description <rendered-description
:content="track.description" :content="track.description"
:can-update="false" :can-update="false"
/> />
<h2 class="ui header"> <h2 class="ui header">
<translate translate-context="Content/*/*"> <translate translate-context="Content/*/*">
Release Details Release Details
</translate> </translate>
</h2> </h2>
<table class="ui basic table ellipsis-rows"> <table class="ui basic table ellipsis-rows">
<tbody> <tbody>
<tr> <tr>
<td> <td>
<translate translate-context="*/*/*/Noun"> <translate translate-context="*/*/*/Noun"> Artist </translate>
Artist </td>
</translate> <td class="right aligned">
</td> <router-link
<td class="right aligned"> :to="{
<router-link :to="{name: 'library.artists.detail', params: {id: track.artist.id}}"> name: 'library.artists.detail',
{{ track.artist.name }} params: { id: track.artist.id },
</router-link> }"
</td> >
</tr> {{ track.artist.name }}
<tr v-if="track.album"> </router-link>
<td> </td>
<translate </tr>
v-if="track.album.artist.content_category === 'music'" <tr v-if="track.album">
key="1" <td>
translate-context="*/*/*/Noun" <translate
> v-if="track.album.artist.content_category === 'music'"
Album key="1"
</translate> translate-context="*/*/*/Noun"
<translate >
v-else Album
key="2" </translate>
translate-context="*/*/*" <translate v-else key="2" translate-context="*/*/*">
> Serie
Serie </translate>
</translate> </td>
</td> <td class="right aligned">
<td class="right aligned"> <router-link
<router-link :to="{name: 'library.albums.detail', params: {id: track.album.id}}"> :to="{
{{ track.album.title }} name: 'library.albums.detail',
</router-link> params: { id: track.album.id },
</td> }"
</tr> >
<tr> {{ track.album.title }}
<td> </router-link>
<translate translate-context="*/*/*"> </td>
Year </tr>
</translate> <tr>
</td> <td>
<td class="right aligned"> <translate translate-context="*/*/*"> Year </translate>
<template v-if="track.album && track.album.release_date"> </td>
{{ track.album.release_date | moment('Y') }} <td class="right aligned">
</template> <template v-if="track.album && track.album.release_date">
<template v-else> {{ track.album.release_date | moment("Y") }}
<translate translate-context="*/*/*"> </template>
N/A <template v-else>
</translate> <translate translate-context="*/*/*"> N/A </translate>
</template> </template>
</td> </td>
</tr> </tr>
<tr> <tr>
<td> <td>
<translate translate-context="Content/Track/*/Noun"> <translate translate-context="Content/Track/*/Noun">
Copyright Copyright
</translate> </translate>
</td> </td>
<td class="right aligned"> <td class="right aligned">
<span <span v-if="track.copyright" :title="track.copyright">{{
v-if="track.copyright" track.copyright | truncate(50)
:title="track.copyright" }}</span>
>{{ track.copyright|truncate(50) }}</span> <template v-else>
<template v-else> <translate translate-context="*/*/*"> N/A </translate>
<translate translate-context="*/*/*"> </template>
N/A </td>
</translate> </tr>
</template> <tr>
</td> <td>
</tr> <translate translate-context="Content/*/*/Noun">
<tr> License
<td> </translate>
<translate translate-context="Content/*/*/Noun"> </td>
License <td class="right aligned">
</translate> <a
</td> v-if="license"
<td class="right aligned"> :href="license.url"
<a target="_blank"
v-if="license" rel="noopener noreferrer"
:href="license.url" >{{ license.name }}</a
target="_blank" >
rel="noopener noreferrer" <translate v-else translate-context="*/*/*"> N/A </translate>
>{{ license.name }}</a> </td>
<translate </tr>
v-else <tr v-if="!track.is_local">
translate-context="*/*/*" <td>
> <translate translate-context="Content/*/*/Noun">
N/A URL
</translate> </translate>
</td> </td>
</tr> <td :title="track.fid">
<tr v-if="!track.is_local"> <a
<td> :href="track.fid"
<translate translate-context="Content/*/*/Noun"> target="_blank"
URL rel="noopener noreferrer"
</translate> >
</td> {{ track.fid | truncate(65) }}
<td :title="track.fid"> </a>
<a </td>
:href="track.fid" </tr>
target="_blank" </tbody>
rel="noopener noreferrer" </table>
> <a
{{ track.fid|truncate(65) }} v-if="musicbrainzUrl"
</a> :href="musicbrainzUrl"
</td> target="_blank"
</tr> rel="noreferrer noopener"
</tbody> >
</table> <i class="external icon" />
<a <translate translate-context="Content/*/*/Clickable, Verb"
v-if="musicbrainzUrl" >View on MusicBrainz</translate
:href="musicbrainzUrl" >
target="_blank" </a>
rel="noreferrer noopener" <h2 class="ui header">
> <translate translate-context="Content/*/Title/Noun">
<i class="external icon" /> Related Playlists
<translate translate-context="Content/*/*/Clickable, Verb">View on MusicBrainz</translate> </translate>
</a> </h2>
<h2 class="ui header"> <playlist-widget
<translate translate-context="Content/*/Title/Noun"> :url="'playlists/'"
Related Playlists :filters="{
</translate> track: track.id,
</h2> playable: true,
<playlist-widget ordering: '-modification_date',
:url="'playlists/'" }"
:filters="{track: track.id, playable: true, ordering: '-modification_date'}" />
/>
<h2 class="ui header"> <h2 class="ui header">
<translate translate-context="Content/*/Title/Noun"> <translate translate-context="Content/*/Title/Noun">
Related Libraries Related Libraries
</translate> </translate>
</h2> </h2>
<library-widget <library-widget
:url="'tracks/' + id + '/libraries/'" :url="'tracks/' + id + '/libraries/'"
@loaded="$emit('libraries-loaded', $event)" @loaded="$emit('libraries-loaded', $event)"
> >
<translate <translate
slot="subtitle" slot="subtitle"
translate-context="Content/Track/Paragraph" translate-context="Content/Track/Paragraph"
> >
This track is present in the following libraries: This track is present in the following libraries:
</translate> </translate>
</library-widget> </library-widget>
</div> </div>
</div> </div>
</section> </section>
</div> </div>
</template> </template>
<script> <script>
import axios from 'axios' import axios from "axios";
import LibraryWidget from '@/components/federation/LibraryWidget' import LibraryWidget from "@/components/federation/LibraryWidget";
import TagsList from '@/components/tags/List' import TagsList from "@/components/tags/List";
import PlaylistWidget from '@/components/playlists/Widget' import PlaylistWidget from "@/components/playlists/Widget";
export default { export default {
components: { components: {
LibraryWidget, LibraryWidget,
TagsList, TagsList,
PlaylistWidget PlaylistWidget,
}, },
props: { props: {
track: { type: Object, required: true }, track: { type: Object, required: true },
libraries: { type: Array, default: null } libraries: { type: Array, default: null },
}, },
data () { data() {
return { return {
id: this.track.id, id: this.track.id,
licenseData: null licenseData: null,
} };
}, },
computed: { computed: {
labels () { labels() {
return { return {
title: this.$pgettext('*/*/*/Noun', 'Track') title: this.$pgettext("*/*/*/Noun", "Track"),
} };
}, },
musicbrainzUrl () { musicbrainzUrl() {
if (this.track.mbid) { if (this.track.mbid) {
return 'https://musicbrainz.org/recording/' + this.track.mbid return "https://musicbrainz.org/recording/" + this.track.mbid;
} }
return null return null;
}, },
upload () { upload() {
if (this.track.uploads) { if (this.track.uploads) {
return this.track.uploads[0] return this.track.uploads[0];
} }
return null return null;
}, },
license () { license() {
if (!this.track || !this.track.license) { if (!this.track || !this.track.license) {
return null return null;
} }
return this.licenseData return this.licenseData;
}, },
cover () { cover() {
if (this.track.cover && this.track.cover.urls.original) { if (this.track.cover && this.track.cover.urls.original) {
return this.track.cover return this.track.cover;
} }
if (this.track.album && this.track.album.cover) { if (this.track.album && this.track.album.cover) {
return this.track.album.cover return this.track.album.cover;
} }
return null return null;
} },
}, },
watch: { watch: {
track (v) { track(v) {
if (v && v.license) { if (v && v.license) {
this.fetchLicenseData(v.license) this.fetchLicenseData(v.license);
} }
} },
}, },
created () { created() {
if (this.track && this.track.license) { if (this.track && this.track.license) {
this.fetchLicenseData(this.track.license) this.fetchLicenseData(this.track.license);
} }
}, },
methods: { methods: {
fetchLicenseData (licenseId) { fetchLicenseData(licenseId) {
const self = this const self = this;
const url = `licenses/${licenseId}` const url = `licenses/${licenseId}`;
axios.get(url).then(response => { axios.get(url).then((response) => {
self.licenseData = response.data self.licenseData = response.data;
}) });
} },
} },
} };
</script> </script>