Add fallback to generic album cover for tracks with no album
This commit is contained in:
parent
3a48ae7e51
commit
9b1865e43e
|
@ -0,0 +1 @@
|
||||||
|
Fixed an issue where you couldn't load the details page for tracks with no associated album (#1703)
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue