style(front): Section components on explore
This commit is contained in:
parent
bbc239b96c
commit
16c74b4078
|
@ -10,6 +10,7 @@ import axios from 'axios'
|
||||||
|
|
||||||
import AlbumCard from '~/components/album/Card.vue'
|
import AlbumCard from '~/components/album/Card.vue'
|
||||||
import Button from '~/components/ui/Button.vue'
|
import Button from '~/components/ui/Button.vue'
|
||||||
|
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'
|
||||||
|
|
||||||
|
@ -72,49 +73,50 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h2
|
<div class="album-widget">
|
||||||
v-if="!!$slots.title"
|
<h2
|
||||||
class="ui header"
|
v-if="!!$slots.title"
|
||||||
>
|
|
||||||
<slot name="title" />
|
|
||||||
<span
|
|
||||||
v-if="showCount"
|
|
||||||
class="ui tiny circular label"
|
|
||||||
>{{ count }}</span>
|
|
||||||
</h2>
|
|
||||||
<slot />
|
|
||||||
<inline-search-bar
|
|
||||||
v-if="search"
|
|
||||||
v-model="query"
|
|
||||||
@search="performSearch"
|
|
||||||
/>
|
|
||||||
<template v-if="!isLoading && albums.length >= 0">
|
|
||||||
<Layout flex>
|
|
||||||
<Loader v-if="isLoading" />
|
|
||||||
<album-card
|
|
||||||
v-for="album in albums"
|
|
||||||
:key="album.id"
|
|
||||||
:album="album"
|
|
||||||
/>
|
|
||||||
</Layout>
|
|
||||||
</template>
|
|
||||||
<slot
|
|
||||||
v-if="!isLoading && albums.length === 0"
|
|
||||||
name="empty-state"
|
|
||||||
>
|
|
||||||
<empty-state
|
|
||||||
:refresh="true"
|
|
||||||
@refresh="fetchData"
|
|
||||||
/>
|
|
||||||
</slot>
|
|
||||||
<template v-if="nextPage">
|
|
||||||
<Spacer />
|
|
||||||
<Button
|
|
||||||
v-if="nextPage"
|
|
||||||
primary
|
|
||||||
@click="fetchData(nextPage)"
|
|
||||||
>
|
>
|
||||||
{{ t('components.audio.album.Widget.button.more') }}
|
<slot name="title" />
|
||||||
</Button>
|
<span
|
||||||
</template>
|
v-if="showCount"
|
||||||
|
class="ui tiny circular label"
|
||||||
|
>{{ count }}</span>
|
||||||
|
</h2>
|
||||||
|
<slot />
|
||||||
|
<inline-search-bar
|
||||||
|
v-if="search"
|
||||||
|
v-model="query"
|
||||||
|
@search="performSearch"
|
||||||
|
/>
|
||||||
|
<Loader v-if="isLoading" />
|
||||||
|
<template v-if="!isLoading && albums.length > 0">
|
||||||
|
<Layout flex>
|
||||||
|
<album-card
|
||||||
|
v-for="album in albums"
|
||||||
|
:key="album.id"
|
||||||
|
:album="album"
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
</template>
|
||||||
|
<slot
|
||||||
|
v-if="!isLoading && albums.length === 0"
|
||||||
|
name="empty-state"
|
||||||
|
>
|
||||||
|
<empty-state
|
||||||
|
:refresh="true"
|
||||||
|
@refresh="fetchData"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
<template v-if="nextPage">
|
||||||
|
<Spacer />
|
||||||
|
<Button
|
||||||
|
v-if="nextPage"
|
||||||
|
primary
|
||||||
|
@click="fetchData(nextPage)"
|
||||||
|
>
|
||||||
|
{{ t('components.audio.album.Widget.button.more') }}
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -61,7 +61,12 @@ fetchData()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="channel-widget">
|
||||||
|
<h2
|
||||||
|
v-if="!!$slots.title"
|
||||||
|
>
|
||||||
|
<slot name="title" />
|
||||||
|
</h2>
|
||||||
<slot />
|
<slot />
|
||||||
<Layout flex>
|
<Layout flex>
|
||||||
<Loader v-if="isLoading" />
|
<Loader v-if="isLoading" />
|
||||||
|
|
|
@ -109,117 +109,121 @@ watch(() => props.websocketHandlers.includes('Listen'), (to) => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<!-- TODO: Use activity.vue -->
|
<!-- TODO: Use activity.vue -->
|
||||||
<h2 v-if="!!$slots.title">
|
<div class="track-widget">
|
||||||
<slot name="title" />
|
<h2 v-if="!!$slots.title">
|
||||||
<span
|
<slot name="title" />
|
||||||
v-if="showCount"
|
<span
|
||||||
class="ui tiny circular label"
|
v-if="showCount"
|
||||||
>{{ count }}</span>
|
class="ui tiny circular label"
|
||||||
</h2>
|
>{{ count }}</span>
|
||||||
<Alert
|
</h2>
|
||||||
v-if="count === 0"
|
<Spacer :size="8" />
|
||||||
blue
|
<Alert
|
||||||
style="text-align: center;"
|
v-if="count === 0"
|
||||||
>
|
blue
|
||||||
<i class="bi bi-music-note-list" />
|
style="text-align: center;"
|
||||||
{{ t('components.audio.track.Widget.empty.noResults') }}
|
|
||||||
<Loader v-if="isLoading" />
|
|
||||||
</Alert>
|
|
||||||
<template
|
|
||||||
v-if="count > 0"
|
|
||||||
medium-items
|
|
||||||
>
|
|
||||||
<div class="funkwhale activity"
|
|
||||||
v-for="object in objects"
|
|
||||||
:key="object.id"
|
|
||||||
:class="['item', itemClasses]"
|
|
||||||
>
|
>
|
||||||
<div class="activity-image">
|
<i class="bi bi-music-note-list" />
|
||||||
<img
|
{{ t('components.audio.track.Widget.empty.noResults') }}
|
||||||
v-if="object.track.album && object.track.album.cover"
|
<Loader v-if="isLoading" />
|
||||||
v-lazy="store.getters['instance/absoluteUrl'](object.track.album.cover.urls.medium_square_crop)"
|
</Alert>
|
||||||
alt=""
|
<Section
|
||||||
>
|
v-if="count > 0"
|
||||||
<img
|
medium-items
|
||||||
v-else-if="object.track.cover"
|
alignLeft
|
||||||
v-lazy="store.getters['instance/absoluteUrl'](object.track.cover.urls.medium_square_crop)"
|
>
|
||||||
alt=""
|
<div class="funkwhale activity"
|
||||||
>
|
v-for="object in objects"
|
||||||
<img
|
:key="object.id"
|
||||||
v-else-if="object.track.artist_credit && object.track.artist_credit.length > 1"
|
:class="['item', itemClasses]"
|
||||||
v-lazy="getArtistCoverUrl(object.track.artist_credit)"
|
>
|
||||||
alt=""
|
<div class="activity-image">
|
||||||
>
|
<img
|
||||||
<i
|
v-if="object.track.album && object.track.album.cover"
|
||||||
v-else
|
v-lazy="store.getters['instance/absoluteUrl'](object.track.album.cover.urls.medium_square_crop)"
|
||||||
class="bi bi-vinyl-fill"
|
alt=""
|
||||||
/>
|
|
||||||
<!-- TODO: Add Playbutton overlay -->
|
|
||||||
</div>
|
|
||||||
<div class="activity-content">
|
|
||||||
<router-link
|
|
||||||
class="funkwhale link artist"
|
|
||||||
:to="{name: 'library.tracks.detail', params: {id: object.track.id}}"
|
|
||||||
>
|
>
|
||||||
<Heading :h3="object.track.title" title />
|
<img
|
||||||
</router-link>
|
v-else-if="object.track.cover"
|
||||||
<Spacer :size="2"/>
|
v-lazy="store.getters['instance/absoluteUrl'](object.track.cover.urls.medium_square_crop)"
|
||||||
<div
|
alt=""
|
||||||
v-if="object.track.artist_credit"
|
>
|
||||||
class="funkwhale link artist"
|
<img
|
||||||
>
|
v-else-if="object.track.artist_credit && object.track.artist_credit.length > 1"
|
||||||
<span
|
v-lazy="getArtistCoverUrl(object.track.artist_credit)"
|
||||||
v-for="ac in object.track.artist_credit"
|
alt=""
|
||||||
:key="ac.artist.id"
|
>
|
||||||
|
<i
|
||||||
|
v-else
|
||||||
|
class="bi bi-vinyl-fill"
|
||||||
|
/>
|
||||||
|
<!-- TODO: Add Playbutton overlay -->
|
||||||
|
</div>
|
||||||
|
<div class="activity-content">
|
||||||
|
<router-link
|
||||||
|
class="funkwhale link artist"
|
||||||
|
:to="{name: 'library.tracks.detail', params: {id: object.track.id}}"
|
||||||
|
>
|
||||||
|
<Heading :h3="object.track.title" title />
|
||||||
|
</router-link>
|
||||||
|
<Spacer :size="2"/>
|
||||||
|
<div
|
||||||
|
v-if="object.track.artist_credit"
|
||||||
|
class="funkwhale link artist"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="ac in object.track.artist_credit"
|
||||||
|
:key="ac.artist.id"
|
||||||
|
>
|
||||||
|
<router-link
|
||||||
|
class="discrete link"
|
||||||
|
:to="{ name: 'library.artists.detail', params: { id: ac.artist.id } }"
|
||||||
|
>
|
||||||
|
{{ ac.credit }}
|
||||||
|
</router-link>
|
||||||
|
<span v-if="ac.joinphrase">{{ ac.joinphrase }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<TagsList
|
||||||
|
label-classes="tiny"
|
||||||
|
:truncate-size="20"
|
||||||
|
:limit="2"
|
||||||
|
:show-more="false"
|
||||||
|
:tags="object.track.tags"
|
||||||
|
/>
|
||||||
|
<Spacer :size="4"/>
|
||||||
|
<div
|
||||||
|
v-if="isActivity"
|
||||||
|
class="extra"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
class="discrete link"
|
class="funkwhale link user"
|
||||||
:to="{ name: 'library.artists.detail', params: { id: ac.artist.id } }"
|
:to="{name: 'profile.overview', params: {username: object.actor.name}}"
|
||||||
>
|
>
|
||||||
{{ ac.credit }}
|
<span class="at symbol" />{{ object.actor.name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<span v-if="ac.joinphrase">{{ ac.joinphrase }}</span>
|
<span class="right floated"><human-date :date="object.creation_date" /></span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TagsList
|
<play-button
|
||||||
label-classes="tiny"
|
:account="object.actor"
|
||||||
:truncate-size="20"
|
:dropdown-only="true"
|
||||||
:limit="2"
|
:track="object.track"
|
||||||
:show-more="false"
|
square-small
|
||||||
:tags="object.track.tags"
|
|
||||||
/>
|
/>
|
||||||
<Spacer :size="4"/>
|
|
||||||
<div
|
|
||||||
v-if="isActivity"
|
|
||||||
class="extra"
|
|
||||||
>
|
|
||||||
<router-link
|
|
||||||
class="funkwhale link user"
|
|
||||||
:to="{name: 'profile.overview', params: {username: object.actor.name}}"
|
|
||||||
>
|
|
||||||
<span class="at symbol" />{{ object.actor.name }}
|
|
||||||
</router-link>
|
|
||||||
<span class="right floated"><human-date :date="object.creation_date" /></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<play-button
|
</Section>
|
||||||
:account="object.actor"
|
<Loader v-if="isLoading" />
|
||||||
:dropdown-only="true"
|
<template v-if="nextPage">
|
||||||
:track="object.track"
|
<Spacer />
|
||||||
square-small
|
<Button
|
||||||
/>
|
primary
|
||||||
</div>
|
@click="fetchData(nextPage as string)"
|
||||||
</template>
|
>
|
||||||
<Loader v-if="isLoading" />
|
{{ t('components.audio.track.Widget.button.more') }}
|
||||||
<template v-if="nextPage">
|
</Button>
|
||||||
<Spacer :size="16"/>
|
</template>
|
||||||
<Button
|
</div>
|
||||||
primary
|
|
||||||
@click="fetchData(nextPage as string)"
|
|
||||||
>
|
|
||||||
{{ t('components.audio.track.Widget.button.more') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ fetchData()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Layout main stack gap-64
|
<Layout main stack
|
||||||
:key="route?.name ?? undefined"
|
:key="route?.name ?? undefined"
|
||||||
v-title="labels.title"
|
v-title="labels.title"
|
||||||
>
|
>
|
||||||
|
@ -77,39 +77,40 @@ fetchData()
|
||||||
</template>
|
</template>
|
||||||
</playlist-widget>
|
</playlist-widget>
|
||||||
|
|
||||||
<Section
|
|
||||||
v-if="scope === 'all'"
|
|
||||||
alignLeft
|
|
||||||
:h2="t('components.library.Home.header.newChannels')"
|
|
||||||
/>
|
|
||||||
<channels-widget
|
<channels-widget
|
||||||
|
v-if="scope === 'all'"
|
||||||
:show-modification-date="true"
|
:show-modification-date="true"
|
||||||
:limit="12"
|
:limit="12"
|
||||||
:filters="{ordering: '-creation_date', external: 'true'}"
|
:filters="{ordering: '-creation_date', external: 'true'}"
|
||||||
/>
|
|
||||||
<Section
|
|
||||||
alignLeft
|
|
||||||
:h2="t('components.library.Home.header.recentlyListened')"
|
|
||||||
>
|
>
|
||||||
<track-widget
|
<template #title>
|
||||||
:url="'history/listenings/'"
|
{{ t('components.library.Home.header.newChannels') }}
|
||||||
:filters="{ scope, ordering: '-creation_date', ...qualityFilters}"
|
</template>
|
||||||
:websocket-handlers="['Listen']"
|
</channels-widget>
|
||||||
/>
|
|
||||||
</Section>
|
<track-widget
|
||||||
<Section
|
:url="'history/listenings/'"
|
||||||
alignLeft
|
:filters="{ scope, ordering: '-creation_date', ...qualityFilters}"
|
||||||
:h2="t('components.library.Home.header.recentlyFavorited')"
|
:websocket-handlers="['Listen']"
|
||||||
>
|
>
|
||||||
<track-widget
|
<template #title>
|
||||||
:url="'favorites/tracks/'"
|
{{ t('components.library.Home.header.recentlyListened') }}
|
||||||
:filters="{scope: scope, ordering: '-creation_date'}"
|
</template>
|
||||||
/>
|
</track-widget>
|
||||||
</Section>
|
|
||||||
<Section
|
<track-widget
|
||||||
alignLeft
|
:url="'favorites/tracks/'"
|
||||||
:h2="t('components.library.Home.header.recentlyAdded')"
|
:filters="{scope: scope, ordering: '-creation_date'}"
|
||||||
/>
|
>
|
||||||
<album-widget :filters="{scope: scope, playable: true, ordering: '-creation_date', ...qualityFilters}"/>
|
<template #title>
|
||||||
|
{{ t('components.library.Home.header.recentlyFavorited') }}
|
||||||
|
</template>
|
||||||
|
</track-widget>
|
||||||
|
|
||||||
|
<album-widget :filters="{scope: scope, playable: true, ordering: '-creation_date', ...qualityFilters}">
|
||||||
|
<template #title>
|
||||||
|
{{ t('components.library.Home.header.recentlyAdded') }}
|
||||||
|
</template>
|
||||||
|
</album-widget>
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -58,7 +58,7 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Layout stack>
|
<div class="playlist-widget">
|
||||||
<h2 v-if="!!$slots.title">
|
<h2 v-if="!!$slots.title">
|
||||||
<slot name="title" />
|
<slot name="title" />
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -68,7 +68,7 @@ watch(
|
||||||
<Layout
|
<Layout
|
||||||
v-else-if="objects.length > 0"
|
v-else-if="objects.length > 0"
|
||||||
flex
|
flex
|
||||||
style="gap: 16px; flex-wrap: wrap;"
|
gap-16
|
||||||
>
|
>
|
||||||
<PlaylistCard
|
<PlaylistCard
|
||||||
v-for="playlist in objects"
|
v-for="playlist in objects"
|
||||||
|
@ -97,6 +97,7 @@ watch(
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
<template v-if="nextPage">
|
<template v-if="nextPage">
|
||||||
|
<Spacer />
|
||||||
<Button
|
<Button
|
||||||
v-if="nextPage"
|
v-if="nextPage"
|
||||||
primary
|
primary
|
||||||
|
@ -105,5 +106,5 @@ watch(
|
||||||
{{ t('components.playlists.Widget.button.more') }}
|
{{ t('components.playlists.Widget.button.more') }}
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</Layout>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue