feat(front): new layout details for track detail page
This commit is contained in:
parent
4f37a52b9d
commit
d3e6e0a3e4
|
@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'
|
||||||
import { clone, uniqBy } from 'lodash-es'
|
import { clone, uniqBy } from 'lodash-es'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useStore } from '~/store'
|
import { useStore } from '~/store'
|
||||||
|
import { sortedUniq } from 'lodash-es'
|
||||||
|
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
@ -67,7 +68,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
filters: () => ({}),
|
filters: () => ({}),
|
||||||
nextUrl: null,
|
nextUrl: null,
|
||||||
|
|
||||||
paginateResults: true,
|
paginateResults: false,
|
||||||
total: 0,
|
total: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
paginateBy: 25,
|
paginateBy: 25,
|
||||||
|
@ -88,6 +89,8 @@ const allTracks = computed(() => {
|
||||||
: tracks
|
: tracks
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const paginateResults = computed(() => props.paginateResults && allTracks.value.length < props.paginateBy)
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
|
@ -243,18 +246,14 @@ const updatePage = (page: number) => {
|
||||||
:is-podcast="isPodcast"
|
:is-podcast="isPodcast"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<Pagination
|
||||||
v-if="tracks && paginateResults"
|
v-if="paginateResults && totalTracks > paginateBy"
|
||||||
class="ui center aligned basic segment desktop-and-up"
|
:paginate-by="paginateBy"
|
||||||
>
|
|
||||||
<pagination
|
|
||||||
:total="totalTracks"
|
:total="totalTracks"
|
||||||
:current="tracks !== undefined ? page : currentPage"
|
:current="tracks !== undefined ? page : currentPage"
|
||||||
:paginate-by="paginateBy"
|
|
||||||
@update:current="updatePage"
|
@update:current="updatePage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
:class="['track-table', 'ui', 'unstackable', 'grid', 'tablet-and-below']"
|
:class="['track-table', 'ui', 'unstackable', 'grid', 'tablet-and-below']"
|
||||||
|
|
|
@ -10,9 +10,12 @@ import { useStore } from '~/store'
|
||||||
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import ActorLink from '~/components/common/ActorLink.vue'
|
||||||
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
|
||||||
import TrackPlaylistIcon from '~/components/playlists/TrackPlaylistIcon.vue'
|
import TrackPlaylistIcon from '~/components/playlists/TrackPlaylistIcon.vue'
|
||||||
import EmbedWizard from '~/components/audio/EmbedWizard.vue'
|
import EmbedWizard from '~/components/audio/EmbedWizard.vue'
|
||||||
|
import HumanDuration from '~/components/common/HumanDuration.vue'
|
||||||
|
import TagsList from '~/components/tags/List.vue'
|
||||||
import Layout from '~/components/ui/Layout.vue'
|
import Layout from '~/components/ui/Layout.vue'
|
||||||
import Loader from '~/components/ui/Loader.vue'
|
import Loader from '~/components/ui/Loader.vue'
|
||||||
import Modal from '~/components/ui/Modal.vue'
|
import Modal from '~/components/ui/Modal.vue'
|
||||||
|
@ -75,6 +78,8 @@ const attributedToUrl = computed(() => router.resolve({
|
||||||
}
|
}
|
||||||
})?.href)
|
})?.href)
|
||||||
|
|
||||||
|
const totalDuration = computed(() => track.value?.uploads[0]?.duration ?? 0)
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const labels = computed(() => ({
|
const labels = computed(() => ({
|
||||||
title: t('components.library.TrackBase.title'),
|
title: t('components.library.TrackBase.title'),
|
||||||
|
@ -160,27 +165,14 @@ watch(showDeleteModal, (newValue) => {
|
||||||
</Button>
|
</Button>
|
||||||
</Layout>
|
</Layout>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<template v-if="track.attributed_to">
|
<span>{{ t('components.library.TrackBase.title') }}</span>
|
||||||
<Link
|
|
||||||
:to="attributedToUrl"
|
|
||||||
>
|
|
||||||
<i class="bi bi-at" />
|
|
||||||
{{ track.attributed_to.full_username }}
|
|
||||||
</Link>
|
|
||||||
<i class="bi bi-dot" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<time
|
|
||||||
:title="track.creation_date"
|
|
||||||
:datetime="track.creation_date"
|
|
||||||
>
|
|
||||||
{{ momentFormat(new Date(track.creation_date), 'LL') }}
|
|
||||||
</time>
|
|
||||||
|
|
||||||
<template v-if="track.album">
|
|
||||||
<i class="bi bi-dot" />
|
<i class="bi bi-dot" />
|
||||||
<span>{{ track.album.title }}</span>
|
<span>{{ track.album.title }}</span>
|
||||||
</template>
|
<i v-if="totalDuration > 0" class="bi bi-dot" />
|
||||||
|
<human-duration
|
||||||
|
v-if="totalDuration > 0"
|
||||||
|
:duration="totalDuration"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
|
@ -293,6 +285,34 @@ watch(showDeleteModal, (newValue) => {
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<Layout flex>
|
||||||
|
<div>
|
||||||
|
<span v-if="track.attributed_to">
|
||||||
|
{{ t('components.library.TrackBase.subtitle.with-uploader') }}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{ t('components.library.TrackBase.subtitle.without-uploader') }}
|
||||||
|
</span>
|
||||||
|
<ActorLink
|
||||||
|
v-if="track.attributed_to"
|
||||||
|
:actor="track.attributed_to"
|
||||||
|
:avatar="false"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<time
|
||||||
|
:title="track.creation_date"
|
||||||
|
:datetime="track.creation_date"
|
||||||
|
>
|
||||||
|
{{ momentFormat(new Date(track.creation_date), 'LL') }}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
<TagsList
|
||||||
|
v-if="track.tags && track.tags.length > 0"
|
||||||
|
:tags="track.tags"
|
||||||
|
/>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
v-if="isEmbedable"
|
v-if="isEmbedable"
|
||||||
v-model="showEmbedModal"
|
v-model="showEmbedModal"
|
||||||
|
@ -312,16 +332,6 @@ watch(showDeleteModal, (newValue) => {
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
<router-view
|
|
||||||
v-if="track"
|
|
||||||
:key="route.fullPath"
|
|
||||||
:track="track"
|
|
||||||
:object="track"
|
|
||||||
object-type="track"
|
|
||||||
@libraries-loaded="libraries = $event"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
v-model="showDeleteModal"
|
v-model="showDeleteModal"
|
||||||
:title="t('components.library.TrackBase.modal.delete.header')"
|
:title="t('components.library.TrackBase.modal.delete.header')"
|
||||||
|
@ -349,6 +359,16 @@ watch(showDeleteModal, (newValue) => {
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<router-view
|
||||||
|
v-if="track"
|
||||||
|
:key="route.fullPath"
|
||||||
|
:track="track"
|
||||||
|
:object="track"
|
||||||
|
object-type="track"
|
||||||
|
@libraries-loaded="libraries = $event"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -60,14 +60,13 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.ui.artist-track.mini.image {
|
.ui.artist-track.mini.image {
|
||||||
top: auto;
|
height: 40px;
|
||||||
bottom: 0;
|
margin-right: 8px;
|
||||||
position: absolute;
|
margin-top: 4px;
|
||||||
margin: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.image.left.floated.column {
|
.image.left.floated.column {
|
||||||
width: 51px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue