refactor(front): Library Detail

This commit is contained in:
ArneBo 2025-01-29 22:05:58 +01:00
parent 43195f4533
commit 29cde0f864
2 changed files with 171 additions and 201 deletions

View File

@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n'
import Button from '~/components/ui/Button.vue' import Button from '~/components/ui/Button.vue'
import Input from '~/components/ui/Input.vue' import Input from '~/components/ui/Input.vue'
import Alert from '~/components/ui/Alert.vue'
interface Props { interface Props {
value: string value: string

View File

@ -11,6 +11,15 @@ import axios from 'axios'
import LibraryFollowButton from '~/components/audio/LibraryFollowButton.vue' import LibraryFollowButton from '~/components/audio/LibraryFollowButton.vue'
import RadioButton from '~/components/radios/Button.vue' import RadioButton from '~/components/radios/Button.vue'
import Layout from '~/components/ui/Layout.vue'
import Loader from '~/components/ui/Loader.vue'
import OptionsButton from '~/components/ui/button/Options.vue'
import Popover from '~/components/ui/Popover.vue'
import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
import Header from '~/components/ui/Header.vue'
import Tabs from '~/components/ui/Tabs.vue'
import Tab from '~/components/ui/Tab.vue'
import Button from '~/components/ui/Button.vue'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import useReport from '~/composables/moderation/useReport' import useReport from '~/composables/moderation/useReport'
@ -84,62 +93,48 @@ const updateUploads = (count: number) => {
</script> </script>
<template> <template>
<main v-title="labels.title"> <Layout stack main v-title="labels.title">
<div class="ui vertical stripe segment container"> <Loader v-if="isLoading" />
/front/src/views/library/LibraryBase.vue <Header :h1="object.name">
<div <template #action>
v-if="isLoading" <Popover>
class="ui centered active inline loader" <template #default="{ toggleOpen }">
<OptionsButton
@click="toggleOpen"
/> />
<div </template>
v-else-if="object"
class="ui stackable grid" <template #items>
> <PopoverItem
<div class="ui five wide column">
<button
ref="dropdown"
v-dropdown="{direction: 'downward'}"
class="ui pointing dropdown icon small basic right floated button"
style="position: absolute; right: 1em; top: 1em;"
>
<i class="ellipsis vertical icon" />
<div class="menu">
<a
v-if="object.actor.domain != store.getters['instance/domain']" v-if="object.actor.domain != store.getters['instance/domain']"
:href="object.fid" :to="object.fid"
target="_blank" target="_blank"
class="basic item" icon="bi-box-arrow-up-right"
> >
<i class="external icon" />
{{ t('views.library.LibraryBase.link.domain', {domain: object.actor.domain}) }} {{ t('views.library.LibraryBase.link.domain', {domain: object.actor.domain}) }}
</a> </PopoverItem>
<div <PopoverItem
v-for="obj in getReportableObjects({library: object})" v-for="obj in getReportableObjects({library: object})"
:key="obj.target.type + obj.target.id" :key="obj.target.type + obj.target.id"
role="button" icon="bi-share"
class="basic item"
@click.stop.prevent="report(obj)" @click.stop.prevent="report(obj)"
> >
<i class="share icon" /> {{ obj.label }} {{ obj.label }}
</div> </PopoverItem>
<div class="divider" /> <hr>
<router-link
<PopoverItem
v-if="store.state.auth.availablePermissions['moderation']" v-if="store.state.auth.availablePermissions['moderation']"
class="basic item" icon="bi-wrench"
:to="{name: 'manage.library.libraries.detail', params: {id: object.uuid}}" :to="{name: 'manage.library.libraries.detail', params: {id: object.uuid}}"
> >
<i class="wrench icon" />
{{ t('views.library.LibraryBase.link.moderation') }} {{ t('views.library.LibraryBase.link.moderation') }}
</router-link> </PopoverItem>
</div> </template>
</button> </Popover>
<h1 class="ui header"> </template>
<div class="ui hidden divider" /> </Header>
<div class="ellipsis content">
<i class="layer group small icon" />
<span>{{ object.name }}</span>
<div class="ui very small hidden divider" />
<div <div
class="sub header ellipsis" class="sub header ellipsis"
:title="object.actor.full_username" :title="object.actor.full_username"
@ -152,140 +147,116 @@ const updateUploads = (count: number) => {
{{ t('views.library.LibraryBase.link.owner', {username: object.actor.full_username}) }} {{ t('views.library.LibraryBase.link.owner', {username: object.actor.full_username}) }}
</actor-link> </actor-link>
</div> </div>
</div> <Layout flex>
</h1>
<p>
<span <span
v-if="object.privacy_level === 'me'" v-if="object.privacy_level === 'me'"
:title="labels.tooltips.me" :title="labels.tooltips.me"
> >
<i class="lock icon" /> <i class="bi bi-lock" />
{{ labels.visibility.me }} {{ labels.visibility.me }}
</span> </span>
<span <span
v-else-if="object.privacy_level === 'instance'" v-else-if="object.privacy_level === 'instance'"
:title="labels.tooltips.instance" :title="labels.tooltips.instance"
> >
<i class="lock open icon" /> <i class="bi bi-lock-open" />
{{ labels.visibility.instance }} {{ labels.visibility.instance }}
</span> </span>
<span <span
v-else-if="object.privacy_level === 'everyone'" v-else-if="object.privacy_level === 'everyone'"
:title="labels.tooltips.everyone" :title="labels.tooltips.everyone"
class="middledot icon" class="bi bi-dot"
> >
<i class="globe icon" /> <i class="bi bi-globe" />
{{ labels.visibility.everyone }} {{ labels.visibility.everyone }}
</span> </span>
<span class="middledot icon"> <span class="middledot icon">
<i class="music icon" /> <i class="bi bi-music-note-list" />
{{ t('views.library.LibraryBase.meta.tracks', object.uploads_count) }} {{ t('views.library.LibraryBase.meta.tracks', object.uploads_count) }}
</span> </span>
<span v-if="object.size"> <span v-if="object.size">
<i class="database icon" /> <i class="bi bi-database-fill" />
{{ humanSize(object.size) }} {{ humanSize(object.size) }}
</span> </span>
</p> </Layout>
<div class="header-buttons"> <Layout flex class="header-buttons">
<div class="ui small buttons">
<radio-button <radio-button
:disabled="!isPlayable || null" :disabled="!isPlayable || null"
type="library" type="library"
:object-id="object.uuid" :object-id="object.uuid"
/> />
</div>
<div <div
v-if="!isOwner" v-if="!isOwner"
class="ui small buttons"
> >
<library-follow-button <library-follow-button
v-if="store.state.auth.authenticated" v-if="store.state.auth.authenticated"
:library="object" :library="object"
/> />
</div> </div>
</div> </Layout>
<template v-if="store.getters['ui/layoutVersion'] === 'large'">
<rendered-description <rendered-description
:content="object.description ? {html: object.description} : null" :content="object.description ? {html: object.description} : null"
:update-url="`channels/${object.uuid}/`" :update-url="`channels/${object.uuid}/`"
:can-update="false" :can-update="false"
/> />
<div class="ui hidden divider" /> <Layout form>
</template>
<div class="ui form">
<div class="field"> <div class="field">
<label for="copy-input"> <copy-input
{{ t('views.library.LibraryBase.label.sharingLink') }} :value="object.fid"
</label> :label="t('views.library.LibraryBase.label.sharingLink')"
/>
<p> <p>
{{ t('views.library.LibraryBase.description.sharingLink') }} {{ t('views.library.LibraryBase.description.sharingLink') }}
</p> </p>
<copy-input :value="object.fid" />
</div> </div>
</div> </Layout>
</div> <Tabs>
<div class="ui eleven wide column"> <Tab :title="t('views.library.LibraryBase.link.artists')" :to="{name: 'library.detail'}">
<div class="ui head vertical stripe segment">
<div class="ui container">
<div class="ui secondary pointing center aligned menu">
<router-link
class="item"
exact-active-class="active"
active-class=""
:to="{name: 'library.detail'}"
>
{{ t('views.library.LibraryBase.link.artists') }}
</router-link>
<router-link
class="item"
exact-active-class="active"
active-class=""
:to="{name: 'library.detail.albums'}"
>
{{ t('views.library.LibraryBase.link.albums') }}
</router-link>
<router-link
class="item"
exact-active-class="active"
active-class=""
:to="{name: 'library.detail.tracks'}"
>
{{ t('views.library.LibraryBase.link.tracks') }}
</router-link>
<router-link
v-if="isOwner"
class="item"
exact-active-class="active"
active-class=""
:to="{name: 'library.detail.upload'}"
>
<i class="upload icon" />
{{ t('views.library.LibraryBase.button.upload') }}
</router-link>
<router-link
v-if="isOwner"
class="item"
exact-active-class="active"
active-class=""
:to="{name: 'library.detail.edit'}"
>
<i class="pencil icon" />
{{ t('views.library.LibraryBase.button.edit') }}
</router-link>
</div>
<div class="ui hidden divider" />
<router-view <router-view
:is-owner="isOwner" :is-owner="isOwner"
:object="object" :object="object"
@updated="fetchData" @updated="fetchData"
@uploads-finished="updateUploads" @uploads-finished="updateUploads"
/> />
</div> </Tab>
</div> <Tab :title="t('views.library.LibraryBase.link.albums')" :to="{name: 'library.detail.albums'}">
</div> <router-view
</div> :is-owner="isOwner"
</div> :object="object"
</main> @updated="fetchData"
@uploads-finished="updateUploads"
/>
</Tab>
<Tab :title="t('views.library.LibraryBase.link.tracks')" :to="{name: 'library.detail.tracks'}">
<router-view
:is-owner="isOwner"
:object="object"
@updated="fetchData"
@uploads-finished="updateUploads"
/>
</Tab>
<template #tabs-right>
<Layout flex>
<Button
secondary
tiny
icon="bi-upload"
:to="{name: 'library.detail.upload'}"
>
{{ t('views.library.LibraryBase.button.upload') }}
</Button>
<Button
primary
tiny
icon="bi-pencil"
:to="{name: 'library.detail.edit'}"
>
{{ t('views.library.LibraryBase.button.edit') }}
</Button>
</Layout>
</template>
</Tabs>
</Layout>
</template> </template>