refactor(front): [WIP] implement new layout for Album base page
This commit is contained in:
parent
4b167437c0
commit
be492901dc
|
@ -7,10 +7,12 @@ import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { sum } from 'lodash-es'
|
import { sum } from 'lodash-es'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
import { useQueue } from '~/composables/audio/queue'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import ArtistCreditLabel from '~/components/audio/ArtistCreditLabel.vue'
|
import ArtistCreditLabel from '~/components/audio/ArtistCreditLabel.vue'
|
||||||
|
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
||||||
import PlayButton from '~/components/audio/PlayButton.vue'
|
import PlayButton from '~/components/audio/PlayButton.vue'
|
||||||
import TagsList from '~/components/tags/List.vue'
|
import TagsList from '~/components/tags/List.vue'
|
||||||
import AlbumDropdown from './AlbumDropdown.vue'
|
import AlbumDropdown from './AlbumDropdown.vue'
|
||||||
|
@ -18,6 +20,7 @@ import Layout from '~/components/ui/Layout.vue'
|
||||||
import Spacer from '~/components/ui/Spacer.vue'
|
import Spacer from '~/components/ui/Spacer.vue'
|
||||||
import Loader from '~/components/ui/Loader.vue'
|
import Loader from '~/components/ui/Loader.vue'
|
||||||
import Section from '~/components/ui/Section.vue'
|
import Section from '~/components/ui/Section.vue'
|
||||||
|
import Button from '~/components/ui/Button.vue'
|
||||||
|
|
||||||
import useErrorHandler from '~/composables/useErrorHandler'
|
import useErrorHandler from '~/composables/useErrorHandler'
|
||||||
import useLogger from '~/composables/useLogger'
|
import useLogger from '~/composables/useLogger'
|
||||||
|
@ -58,10 +61,17 @@ const publicLibraries = computed(() => libraries.value?.filter(library => librar
|
||||||
const logger = useLogger()
|
const logger = useLogger()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const labels = computed(() => ({
|
const labels = computed(() => ({
|
||||||
title: t('components.library.AlbumBase.title')
|
title: t('components.library.AlbumBase.title'),
|
||||||
|
shuffle: t('components.audio.Player.label.shuffleQueue')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const {
|
||||||
|
isShuffled,
|
||||||
|
shuffle,
|
||||||
|
} = useQueue()
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
@ -146,7 +156,6 @@ const remove = async () => {
|
||||||
v-title="labels.title"
|
v-title="labels.title"
|
||||||
/>
|
/>
|
||||||
<template v-if="object">
|
<template v-if="object">
|
||||||
<!-- Image -->
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<img
|
<img
|
||||||
v-if="object.cover && object.cover.urls.original"
|
v-if="object.cover && object.cover.urls.original"
|
||||||
|
@ -176,19 +185,65 @@ const remove = async () => {
|
||||||
/>
|
/>
|
||||||
<!-- Metadata: -->
|
<!-- Metadata: -->
|
||||||
<div>
|
<div>
|
||||||
<!-- EP -->
|
<template v-if="object.release_date">
|
||||||
·
|
{{ momentFormat(new Date(object.release_date ?? '1970-01-01'), 'Y') }}
|
||||||
<!-- 2022 -->
|
<i class="bi bi-dot" />
|
||||||
·
|
</template>
|
||||||
<!-- 7 tracks -->
|
<template v-if="totalTracks > 0">
|
||||||
|
<span v-if="isSerie">
|
||||||
|
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<i v-if="totalDuration > 0" class="bi bi-dot" />
|
||||||
|
<human-duration
|
||||||
|
v-if="totalDuration > 0"
|
||||||
|
:duration="totalDuration"
|
||||||
|
/>
|
||||||
|
<i v-if="object.tags && object.tags.length > 0" class="bi bi-dot" />
|
||||||
|
<!--TODO: License -->
|
||||||
|
<TagsList
|
||||||
|
v-if="object.tags && object.tags.length > 0"
|
||||||
|
:tags="object.tags"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<!-- Pause -->
|
<rendered-description
|
||||||
<!-- Shuffle -->
|
v-if="object.description"
|
||||||
|
:content="object.description"
|
||||||
|
:can-update="false"
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
<Layout flex>
|
||||||
|
<PlayButton
|
||||||
|
class="vibrant"
|
||||||
|
:tracks="object.tracks"
|
||||||
|
:is-playable="object.is_playable"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
primary
|
||||||
|
icon="bi-shuffle"
|
||||||
|
:disabled="object.tracks.length < 2"
|
||||||
|
:aria-label="labels.shuffle"
|
||||||
|
@click.prevent.stop="shuffle()"
|
||||||
|
>
|
||||||
|
{{ labels.shuffle }}
|
||||||
|
</Button>
|
||||||
<Spacer h grow />
|
<Spacer h grow />
|
||||||
<!-- Herzchen -->
|
<TrackFavoriteIcon v-if="store.state.auth.authenticated" :album="object" />
|
||||||
<!-- Button mit Pfeilchen -->
|
<!-- Button mit Pfeilchen -->
|
||||||
<!-- OptionsButton / -->
|
<album-dropdown
|
||||||
|
:object="object"
|
||||||
|
:public-libraries="publicLibraries"
|
||||||
|
:is-loading="isLoading"
|
||||||
|
:is-album="isAlbum"
|
||||||
|
:is-serie="isSerie"
|
||||||
|
:is-channel="isChannel"
|
||||||
|
:artist-credit="artistCredit"
|
||||||
|
@remove="remove"
|
||||||
|
/>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Section>
|
</Section>
|
||||||
|
@ -202,208 +257,6 @@ const remove = async () => {
|
||||||
<!-- 1 selected -->
|
<!-- 1 selected -->
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
<!-- hier die einzelnen Tracks -->
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Reference: -->
|
|
||||||
<section class="segment channel-serie">
|
|
||||||
<Layout flex gap-64 style="align-content: stretch;">
|
|
||||||
<div style="flex: 2;">
|
|
||||||
<div
|
|
||||||
v-if="isSerie"
|
|
||||||
class="padded basic segment"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="isSerie"
|
|
||||||
class="ui two column grid"
|
|
||||||
>
|
|
||||||
<div class="column">
|
|
||||||
<div class="large two-images">
|
|
||||||
<img
|
|
||||||
v-if="object.cover && object.cover.urls.original"
|
|
||||||
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-else
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
src="../../assets/audio/default-cover.png"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-if="object.cover && object.cover.urls.original"
|
|
||||||
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-else
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
src="../../assets/audio/default-cover.png"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ui column right aligned">
|
|
||||||
<TagsList
|
|
||||||
v-if="object.tags && object.tags.length > 0"
|
|
||||||
:tags="object.tags"
|
|
||||||
/>
|
|
||||||
<div class="ui small hidden divider" />
|
|
||||||
<human-duration
|
|
||||||
v-if="totalDuration > 0"
|
|
||||||
:duration="totalDuration"
|
|
||||||
/>
|
|
||||||
<template v-if="totalTracks > 0">
|
|
||||||
<div class="ui hidden very small divider" />
|
|
||||||
<span v-if="isSerie">
|
|
||||||
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<PlayButton
|
|
||||||
class="vibrant"
|
|
||||||
:tracks="object.tracks"
|
|
||||||
:is-playable="object.is_playable"
|
|
||||||
/>
|
|
||||||
<div class="ui hidden horizontal divider" />
|
|
||||||
<album-dropdown
|
|
||||||
:object="object"
|
|
||||||
:public-libraries="publicLibraries"
|
|
||||||
:is-loading="isLoading"
|
|
||||||
:is-album="isAlbum"
|
|
||||||
:is-serie="isSerie"
|
|
||||||
:is-channel="isChannel"
|
|
||||||
:artist-credit="artistCredit"
|
|
||||||
@remove="remove"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<header>
|
|
||||||
<h2
|
|
||||||
class="ui header"
|
|
||||||
:title="object.title"
|
|
||||||
>
|
|
||||||
{{ object.title }}
|
|
||||||
</h2>
|
|
||||||
<artist-credit-label
|
|
||||||
v-if="artistCredit"
|
|
||||||
:artist-credit="artistCredit"
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else
|
|
||||||
class="ui center aligned text padded basic segment"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-if="object.cover && object.cover.urls.original"
|
|
||||||
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
v-else
|
|
||||||
alt=""
|
|
||||||
class="channel-image"
|
|
||||||
src="../../assets/audio/default-cover.png"
|
|
||||||
>
|
|
||||||
<div class="ui hidden divider" />
|
|
||||||
<header>
|
|
||||||
<h2
|
|
||||||
class="ui header"
|
|
||||||
:title="object.title"
|
|
||||||
>
|
|
||||||
{{ object.title }}
|
|
||||||
</h2>
|
|
||||||
<artist-credit-label
|
|
||||||
v-if="artistCredit"
|
|
||||||
:artist-credit="artistCredit"
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
<Spacer :size="16"/>
|
|
||||||
<div
|
|
||||||
v-if="object.release_date || (totalTracks > 0)"
|
|
||||||
class="ui small hidden divider"
|
|
||||||
/>
|
|
||||||
<template v-if="object.release_date">
|
|
||||||
{{ momentFormat(new Date(object.release_date ?? '1970-01-01'), 'Y') }}
|
|
||||||
<span class="middle middledot symbol" />
|
|
||||||
</template>
|
|
||||||
<template v-if="totalTracks > 0">
|
|
||||||
<span v-if="isSerie">
|
|
||||||
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
|
|
||||||
</span>
|
|
||||||
<span class="middle middledot symbol" />
|
|
||||||
</template>
|
|
||||||
<human-duration
|
|
||||||
v-if="totalDuration > 0"
|
|
||||||
:duration="totalDuration"
|
|
||||||
/>
|
|
||||||
<div class="ui small hidden divider" />
|
|
||||||
<play-button
|
|
||||||
class="vibrant"
|
|
||||||
:album="object"
|
|
||||||
:is-playable="object.is_playable"
|
|
||||||
/>
|
|
||||||
<div class="ui horizontal hidden divider" />
|
|
||||||
<album-dropdown
|
|
||||||
:object="object"
|
|
||||||
:public-libraries="publicLibraries"
|
|
||||||
:is-loading="isLoading"
|
|
||||||
:is-album="isAlbum"
|
|
||||||
:is-serie="isSerie"
|
|
||||||
:is-channel="isChannel"
|
|
||||||
:artist-credit="artistCredit"
|
|
||||||
@remove="remove"
|
|
||||||
/>
|
|
||||||
<div v-if="(object.tags && object.tags.length > 0) || object.description || store.state.auth.authenticated && object.is_local">
|
|
||||||
<div class="ui small hidden divider" />
|
|
||||||
<div class="ui divider" />
|
|
||||||
<div class="ui small hidden divider" />
|
|
||||||
<template v-if="object.tags && object.tags.length > 0">
|
|
||||||
<TagsList :tags="object.tags" />
|
|
||||||
<div class="ui small hidden divider" />
|
|
||||||
</template>
|
|
||||||
<rendered-description
|
|
||||||
v-if="object.description"
|
|
||||||
:content="object.description"
|
|
||||||
:can-update="false"
|
|
||||||
/>
|
|
||||||
<router-link
|
|
||||||
v-else-if="store.state.auth.authenticated && object.is_local"
|
|
||||||
:to="{name: 'library.albums.edit', params: {id: object.id }}"
|
|
||||||
>
|
|
||||||
<i class="pencil icon" />
|
|
||||||
{{ t('components.library.AlbumBase.link.addDescription') }}
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template v-if="isSerie">
|
|
||||||
<div class="ui hidden divider" />
|
|
||||||
<rendered-description
|
|
||||||
v-if="object.description"
|
|
||||||
:content="object.description"
|
|
||||||
:can-update="false"
|
|
||||||
/>
|
|
||||||
<router-link
|
|
||||||
v-else-if="store.state.auth.authenticated && object.is_local"
|
|
||||||
:to="{name: 'library.albums.edit', params: {id: object.id }}"
|
|
||||||
>
|
|
||||||
<i class="pencil icon" />
|
|
||||||
{{ t('components.library.AlbumBase.link.addDescription') }}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<div style="flex 1;">
|
<div style="flex 1;">
|
||||||
<router-view
|
<router-view
|
||||||
v-if="object"
|
v-if="object"
|
||||||
|
@ -418,8 +271,6 @@ const remove = async () => {
|
||||||
@libraries-loaded="libraries = $event"
|
@libraries-loaded="libraries = $event"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
|
||||||
</section>
|
|
||||||
</template>
|
</template>
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue