mirror of
https://github.com/koel/koel
synced 2025-02-17 13:58:28 +00:00
feat: improve meta styles
This commit is contained in:
parent
5189eb7b68
commit
a1f48fe054
11 changed files with 136 additions and 84 deletions
|
@ -0,0 +1,15 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { albumStore } from '@/stores'
|
||||
import AlbumListScreen from './AlbumListScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders', () => {
|
||||
albumStore.state.albums = factory<Album[]>('album', 9)
|
||||
|
||||
expect(this.render(AlbumListScreen).getAllByTestId('album-card')).toHaveLength(9)
|
||||
})
|
||||
}
|
||||
}
|
39
resources/assets/js/components/screens/AlbumScreen.spec.ts
Normal file
39
resources/assets/js/components/screens/AlbumScreen.spec.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import AlbumScreen from './AlbumScreen.vue'
|
||||
import { commonStore, songStore } from '@/stores'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected async renderComponent () {
|
||||
commonStore.state.use_last_fm = true
|
||||
|
||||
const album = factory<Album>('album', {
|
||||
name: 'Led Zeppelin IV',
|
||||
artist_name: 'Led Zeppelin',
|
||||
song_count: 10,
|
||||
length: 1_603
|
||||
})
|
||||
|
||||
const songs = factory<Song[]>('song', 13)
|
||||
const fetchSongsMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
|
||||
const rendered = this.render(AlbumScreen, {
|
||||
props: {
|
||||
album
|
||||
}
|
||||
})
|
||||
|
||||
await waitFor(() => expect(fetchSongsMock).toHaveBeenCalledWith(album))
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { getAllByTestId, getByText } = await this.renderComponent()
|
||||
getByText(/10 songs.+26:43$/)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -9,27 +9,21 @@
|
|||
</template>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span>
|
||||
by
|
||||
<a v-if="isNormalArtist" :href="`#!/artist/${album.artist_id}`" class="artist">{{ album.artist_name }}</a>
|
||||
<span class="nope" v-else>{{ album.artist_name }}</span>
|
||||
•
|
||||
{{ pluralize(album.song_count, 'song') }}
|
||||
•
|
||||
{{ duration }}
|
||||
<a v-if="isNormalArtist" :href="`#!/artist/${album.artist_id}`" class="artist">{{ album.artist_name }}</a>
|
||||
<span class="nope" v-else>{{ album.artist_name }}</span>
|
||||
<span>{{ pluralize(album.song_count, 'song') }}</span>
|
||||
<span>{{ secondsToHis(album.length) }}</span>
|
||||
<a v-if="useLastfm" class="info" href title="View album's extra information" @click.prevent="showInfo">Info</a>
|
||||
|
||||
<template v-if="useLastfm">
|
||||
•
|
||||
<a class="info" href title="View album's extra information" @click.prevent="showInfo">Info</a>
|
||||
</template>
|
||||
|
||||
<template v-if="allowDownload && songs.length">
|
||||
•
|
||||
<a class="download" href role="button" title="Download all songs in album" @click.prevent="download">
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
</span>
|
||||
<a
|
||||
v-if="allowDownload"
|
||||
class="download"
|
||||
href role="button"
|
||||
title="Download all songs in album"
|
||||
@click.prevent="download"
|
||||
>
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
@ -89,8 +83,6 @@ const useLastfm = toRef(commonStore.state, 'use_last_fm')
|
|||
const allowDownload = toRef(commonStore.state, 'allow_download')
|
||||
const showingInfo = ref(false)
|
||||
|
||||
const duration = computed(() => secondsToHis(album.value.length))
|
||||
|
||||
const isNormalArtist = computed(() => {
|
||||
return !artistStore.isVarious(album.value.artist_id) && !artistStore.isUnknown(album.value.artist_id)
|
||||
})
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
All Songs
|
||||
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span v-if="totalSongCount">{{ pluralize(totalSongCount, 'song') }} • {{ totalDuration }}</span>
|
||||
<template v-slot:meta v-if="totalSongCount">
|
||||
<span>{{ pluralize(totalSongCount, 'song') }}</span>
|
||||
<span>{{ totalDuration }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -9,31 +9,21 @@
|
|||
</template>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span>
|
||||
{{ pluralize(artist.album_count, 'album') }}
|
||||
•
|
||||
{{ pluralize(artist.song_count, 'song') }}
|
||||
•
|
||||
{{ duration }}
|
||||
<span>{{ pluralize(artist.album_count, 'album') }}</span>
|
||||
<span>{{ pluralize(artist.song_count, 'song') }}</span>
|
||||
<span>{{ secondsToHis(artist.length) }}</span>
|
||||
<a v-if="useLastfm" class="info" href title="View artist's extra information" @click.prevent="showInfo">Info</a>
|
||||
|
||||
<template v-if="useLastfm">
|
||||
•
|
||||
<a class="info" href title="View artist's extra information" @click.prevent="showInfo">Info</a>
|
||||
</template>
|
||||
|
||||
<template v-if="allowDownload">
|
||||
•
|
||||
<a
|
||||
class="download"
|
||||
href
|
||||
role="button"
|
||||
title="Download all songs by this artist"
|
||||
@click.prevent="download"
|
||||
>
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
</span>
|
||||
<a
|
||||
v-if="allowDownload"
|
||||
class="download"
|
||||
href
|
||||
role="button"
|
||||
title="Download all songs by this artist"
|
||||
@click.prevent="download"
|
||||
>
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
@ -57,7 +47,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineAsyncComponent, onMounted, ref, toRef, toRefs } from 'vue'
|
||||
import { defineAsyncComponent, onMounted, ref, toRef, toRefs } from 'vue'
|
||||
import { eventBus, pluralize, secondsToHis } from '@/utils'
|
||||
import { artistStore, commonStore, songStore } from '@/stores'
|
||||
import { downloadService } from '@/services'
|
||||
|
@ -94,8 +84,6 @@ const allowDownload = toRef(commonStore.state, 'allow_download')
|
|||
|
||||
const showingInfo = ref(false)
|
||||
|
||||
const duration = computed(() => secondsToHis(artist.value.length))
|
||||
|
||||
const download = () => downloadService.fromArtist(artist.value)
|
||||
const showInfo = () => (showingInfo.value = true)
|
||||
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
Songs You Love
|
||||
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span v-if="songs.length">
|
||||
{{ pluralize(songs.length, 'song') }}
|
||||
•
|
||||
{{ duration }}
|
||||
<template v-if="allowDownload">
|
||||
•
|
||||
<a class="download" href role="button" title="Download all songs in playlist" @click.prevent="download">
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
</span>
|
||||
<template v-slot:meta v-if="songs.length">
|
||||
<span>{{ pluralize(songs.length, 'song') }}</span>
|
||||
<span>{{ duration }}</span>
|
||||
|
||||
<a
|
||||
v-if="allowDownload"
|
||||
class="download"
|
||||
href
|
||||
role="button"
|
||||
title="Download all songs in playlist"
|
||||
@click.prevent="download"
|
||||
>
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -4,16 +4,18 @@
|
|||
{{ playlist?.name }}
|
||||
<ControlsToggle v-if="songs.length" :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span class="meta" v-if="songs.length">
|
||||
{{ pluralize(songs.length, 'song') }}
|
||||
•
|
||||
{{ duration }}
|
||||
<template v-if="allowDownload">
|
||||
•
|
||||
<a href role="button" title="Download all songs in playlist" @click.prevent="download">Download All</a>
|
||||
</template>
|
||||
</span>
|
||||
<template v-slot:meta v-if="songs.length">
|
||||
<span>{{ pluralize(songs.length, 'song') }}</span>
|
||||
<span>{{ duration }}</span>
|
||||
<a
|
||||
v-if="allowDownload"
|
||||
href
|
||||
role="button"
|
||||
title="Download all songs in playlist"
|
||||
@click.prevent="download"
|
||||
>
|
||||
Download All
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
Current Queue
|
||||
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span v-if="songs.length">
|
||||
{{ pluralize(songs.length, 'song') }} • {{ duration }}
|
||||
</span>
|
||||
<template v-slot:meta v-if="songs.length">
|
||||
<span>{{ pluralize(songs.length, 'song') }}</span>
|
||||
<span>{{ duration }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
Recently Played
|
||||
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span v-if="songs.length">{{ pluralize(songs.length, 'song') }} • {{ duration }}</span>
|
||||
<template v-slot:meta v-if="songs.length">
|
||||
<span>{{ pluralize(songs.length, 'song') }}</span>
|
||||
<span>{{ duration }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<template>
|
||||
<section id="songResultsWrapper">
|
||||
<ScreenHeader>
|
||||
Showing Songs for <strong>{{ decodedQ }}</strong>
|
||||
Songs Matching <strong>{{ decodedQ }}</strong>
|
||||
<ControlsToggle :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||
|
||||
<template v-slot:meta>
|
||||
<span v-if="songs.length">{{ pluralize(songs.length, 'song') }} • {{ duration }}</span>
|
||||
<template v-slot:meta v-if="songs.length">
|
||||
<span>{{ pluralize(songs.length, 'song') }}</span>
|
||||
<span>{{ duration }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:controls>
|
||||
|
|
|
@ -24,8 +24,8 @@ const props = withDefaults(defineProps<{ hasThumbnail?: boolean }>(), { hasThumb
|
|||
const { hasThumbnail } = toRefs(props)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
header {
|
||||
<style lang="scss">
|
||||
header.screen-header {
|
||||
display: flex;
|
||||
font-weight: var(--font-weight-thin);
|
||||
padding: 1rem 1.8rem;
|
||||
|
@ -71,6 +71,18 @@ header {
|
|||
color: var(--color-highlight);
|
||||
}
|
||||
}
|
||||
|
||||
> * + * {
|
||||
margin-left: .2rem;
|
||||
display: inline-block;
|
||||
|
||||
&::before {
|
||||
content: '•';
|
||||
margin-right: .2rem;
|
||||
color: var(--color-text-secondary);
|
||||
font-weight: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
|
Loading…
Add table
Reference in a new issue