refactor(front): Library Detail
This commit is contained in:
parent
43195f4533
commit
29cde0f864
|
@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n'
|
|||
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Input from '~/components/ui/Input.vue'
|
||||
import Alert from '~/components/ui/Alert.vue'
|
||||
|
||||
interface Props {
|
||||
value: string
|
||||
|
|
|
@ -11,6 +11,15 @@ import axios from 'axios'
|
|||
|
||||
import LibraryFollowButton from '~/components/audio/LibraryFollowButton.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 useReport from '~/composables/moderation/useReport'
|
||||
|
@ -84,208 +93,170 @@ const updateUploads = (count: number) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<main v-title="labels.title">
|
||||
<div class="ui vertical stripe segment container">
|
||||
/front/src/views/library/LibraryBase.vue
|
||||
<div
|
||||
v-if="isLoading"
|
||||
class="ui centered active inline loader"
|
||||
<Layout stack main v-title="labels.title">
|
||||
<Loader v-if="isLoading" />
|
||||
<Header :h1="object.name">
|
||||
<template #action>
|
||||
<Popover>
|
||||
<template #default="{ toggleOpen }">
|
||||
<OptionsButton
|
||||
@click="toggleOpen"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #items>
|
||||
<PopoverItem
|
||||
v-if="object.actor.domain != store.getters['instance/domain']"
|
||||
:to="object.fid"
|
||||
target="_blank"
|
||||
icon="bi-box-arrow-up-right"
|
||||
>
|
||||
{{ t('views.library.LibraryBase.link.domain', {domain: object.actor.domain}) }}
|
||||
</PopoverItem>
|
||||
<PopoverItem
|
||||
v-for="obj in getReportableObjects({library: object})"
|
||||
:key="obj.target.type + obj.target.id"
|
||||
icon="bi-share"
|
||||
@click.stop.prevent="report(obj)"
|
||||
>
|
||||
{{ obj.label }}
|
||||
</PopoverItem>
|
||||
|
||||
<hr>
|
||||
|
||||
<PopoverItem
|
||||
v-if="store.state.auth.availablePermissions['moderation']"
|
||||
icon="bi-wrench"
|
||||
:to="{name: 'manage.library.libraries.detail', params: {id: object.uuid}}"
|
||||
>
|
||||
{{ t('views.library.LibraryBase.link.moderation') }}
|
||||
</PopoverItem>
|
||||
</template>
|
||||
</Popover>
|
||||
</template>
|
||||
</Header>
|
||||
<div
|
||||
class="sub header ellipsis"
|
||||
:title="object.actor.full_username"
|
||||
>
|
||||
<actor-link
|
||||
:avatar="false"
|
||||
:actor="object.actor"
|
||||
:truncate-length="0"
|
||||
>
|
||||
{{ t('views.library.LibraryBase.link.owner', {username: object.actor.full_username}) }}
|
||||
</actor-link>
|
||||
</div>
|
||||
<Layout flex>
|
||||
<span
|
||||
v-if="object.privacy_level === 'me'"
|
||||
:title="labels.tooltips.me"
|
||||
>
|
||||
<i class="bi bi-lock" />
|
||||
{{ labels.visibility.me }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="object.privacy_level === 'instance'"
|
||||
:title="labels.tooltips.instance"
|
||||
>
|
||||
<i class="bi bi-lock-open" />
|
||||
{{ labels.visibility.instance }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="object.privacy_level === 'everyone'"
|
||||
:title="labels.tooltips.everyone"
|
||||
class="bi bi-dot"
|
||||
>
|
||||
<i class="bi bi-globe" />
|
||||
{{ labels.visibility.everyone }}
|
||||
</span>
|
||||
<span class="middledot icon">
|
||||
<i class="bi bi-music-note-list" />
|
||||
{{ t('views.library.LibraryBase.meta.tracks', object.uploads_count) }}
|
||||
</span>
|
||||
<span v-if="object.size">
|
||||
<i class="bi bi-database-fill" />
|
||||
{{ humanSize(object.size) }}
|
||||
</span>
|
||||
</Layout>
|
||||
|
||||
<Layout flex class="header-buttons">
|
||||
<radio-button
|
||||
:disabled="!isPlayable || null"
|
||||
type="library"
|
||||
:object-id="object.uuid"
|
||||
/>
|
||||
<div
|
||||
v-else-if="object"
|
||||
class="ui stackable grid"
|
||||
v-if="!isOwner"
|
||||
>
|
||||
<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']"
|
||||
:href="object.fid"
|
||||
target="_blank"
|
||||
class="basic item"
|
||||
>
|
||||
<i class="external icon" />
|
||||
{{ t('views.library.LibraryBase.link.domain', {domain: object.actor.domain}) }}
|
||||
</a>
|
||||
<div
|
||||
v-for="obj in getReportableObjects({library: object})"
|
||||
:key="obj.target.type + obj.target.id"
|
||||
role="button"
|
||||
class="basic item"
|
||||
@click.stop.prevent="report(obj)"
|
||||
>
|
||||
<i class="share icon" /> {{ obj.label }}
|
||||
</div>
|
||||
|
||||
<div class="divider" />
|
||||
<router-link
|
||||
v-if="store.state.auth.availablePermissions['moderation']"
|
||||
class="basic item"
|
||||
:to="{name: 'manage.library.libraries.detail', params: {id: object.uuid}}"
|
||||
>
|
||||
<i class="wrench icon" />
|
||||
{{ t('views.library.LibraryBase.link.moderation') }}
|
||||
</router-link>
|
||||
</div>
|
||||
</button>
|
||||
<h1 class="ui header">
|
||||
<div class="ui hidden divider" />
|
||||
<div class="ellipsis content">
|
||||
<i class="layer group small icon" />
|
||||
<span>{{ object.name }}</span>
|
||||
<div class="ui very small hidden divider" />
|
||||
<div
|
||||
class="sub header ellipsis"
|
||||
:title="object.actor.full_username"
|
||||
>
|
||||
<actor-link
|
||||
:avatar="false"
|
||||
:actor="object.actor"
|
||||
:truncate-length="0"
|
||||
>
|
||||
{{ t('views.library.LibraryBase.link.owner', {username: object.actor.full_username}) }}
|
||||
</actor-link>
|
||||
</div>
|
||||
</div>
|
||||
</h1>
|
||||
<p>
|
||||
<span
|
||||
v-if="object.privacy_level === 'me'"
|
||||
:title="labels.tooltips.me"
|
||||
>
|
||||
<i class="lock icon" />
|
||||
{{ labels.visibility.me }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="object.privacy_level === 'instance'"
|
||||
:title="labels.tooltips.instance"
|
||||
>
|
||||
<i class="lock open icon" />
|
||||
{{ labels.visibility.instance }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="object.privacy_level === 'everyone'"
|
||||
:title="labels.tooltips.everyone"
|
||||
class="middledot icon"
|
||||
>
|
||||
<i class="globe icon" />
|
||||
{{ labels.visibility.everyone }}
|
||||
</span>
|
||||
<span class="middledot icon">
|
||||
<i class="music icon" />
|
||||
{{ t('views.library.LibraryBase.meta.tracks', object.uploads_count) }}
|
||||
</span>
|
||||
<span v-if="object.size">
|
||||
<i class="database icon" />
|
||||
{{ humanSize(object.size) }}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div class="header-buttons">
|
||||
<div class="ui small buttons">
|
||||
<radio-button
|
||||
:disabled="!isPlayable || null"
|
||||
type="library"
|
||||
:object-id="object.uuid"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isOwner"
|
||||
class="ui small buttons"
|
||||
>
|
||||
<library-follow-button
|
||||
v-if="store.state.auth.authenticated"
|
||||
:library="object"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="store.getters['ui/layoutVersion'] === 'large'">
|
||||
<rendered-description
|
||||
:content="object.description ? {html: object.description} : null"
|
||||
:update-url="`channels/${object.uuid}/`"
|
||||
:can-update="false"
|
||||
/>
|
||||
<div class="ui hidden divider" />
|
||||
</template>
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label for="copy-input">
|
||||
{{ t('views.library.LibraryBase.label.sharingLink') }}
|
||||
</label>
|
||||
<p>
|
||||
{{ t('views.library.LibraryBase.description.sharingLink') }}
|
||||
</p>
|
||||
<copy-input :value="object.fid" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui eleven wide column">
|
||||
<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
|
||||
:is-owner="isOwner"
|
||||
:object="object"
|
||||
@updated="fetchData"
|
||||
@uploads-finished="updateUploads"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<library-follow-button
|
||||
v-if="store.state.auth.authenticated"
|
||||
:library="object"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<rendered-description
|
||||
:content="object.description ? {html: object.description} : null"
|
||||
:update-url="`channels/${object.uuid}/`"
|
||||
:can-update="false"
|
||||
/>
|
||||
<Layout form>
|
||||
<div class="field">
|
||||
<copy-input
|
||||
:value="object.fid"
|
||||
:label="t('views.library.LibraryBase.label.sharingLink')"
|
||||
/>
|
||||
<p>
|
||||
{{ t('views.library.LibraryBase.description.sharingLink') }}
|
||||
</p>
|
||||
</div>
|
||||
</Layout>
|
||||
<Tabs>
|
||||
<Tab :title="t('views.library.LibraryBase.link.artists')" :to="{name: 'library.detail'}">
|
||||
<router-view
|
||||
:is-owner="isOwner"
|
||||
:object="object"
|
||||
@updated="fetchData"
|
||||
@uploads-finished="updateUploads"
|
||||
/>
|
||||
</Tab>
|
||||
<Tab :title="t('views.library.LibraryBase.link.albums')" :to="{name: 'library.detail.albums'}">
|
||||
<router-view
|
||||
:is-owner="isOwner"
|
||||
:object="object"
|
||||
@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>
|
||||
|
|
Loading…
Reference in New Issue