mirror of
https://github.com/koel/koel
synced 2024-11-14 00:17:13 +00:00
feat: always show song list header action menu (#1869)
This commit is contained in:
parent
3848e8b52d
commit
5d9d75111a
5 changed files with 30 additions and 10 deletions
|
@ -70,7 +70,7 @@ new class extends UnitTestCase {
|
|||
},
|
||||
global: {
|
||||
stubs: {
|
||||
SongListSorter: this.stub('song-list-sorter'),
|
||||
ActionMenu: this.stub('song-list-header-action-menu'),
|
||||
},
|
||||
provide: {
|
||||
[<symbol>SelectedPlayablesKey]: [ref(selectedPlayables), (value: Playable[]) => (selectedPlayables = value)],
|
||||
|
|
|
@ -66,8 +66,8 @@
|
|||
</template>
|
||||
</span>
|
||||
<span class="extra">
|
||||
<SongListSorter
|
||||
v-if="config.sortable"
|
||||
<ActionMenu
|
||||
:sortable="config.sortable"
|
||||
:field="sortField"
|
||||
:has-custom-order-sort="config.hasCustomOrderSort"
|
||||
:order="sortOrder"
|
||||
|
@ -87,10 +87,10 @@ import { PlayableListConfigKey, PlayableListSortFieldKey, SongListSortOrderKey }
|
|||
import type { getPlayableCollectionContentType } from '@/utils/typeGuards'
|
||||
import { usePlayableListColumnVisibility } from '@/composables/usePlayableListColumnVisibility'
|
||||
|
||||
import SongListSorter from '@/components/song/song-list/SongListSorter.vue'
|
||||
import ActionMenu from '@/components/song/song-list/SongListHeaderActionMenu.vue'
|
||||
|
||||
withDefaults(defineProps<{
|
||||
contentType?: ReturnType<getPlayableCollectionContentType>
|
||||
contentType?: ReturnType<typeof getPlayableCollectionContentType>
|
||||
}>(), {
|
||||
contentType: 'songs',
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ import { screen } from '@testing-library/vue'
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { useLocalStorage } from '@/composables/useLocalStorage'
|
||||
import Component from './SongListSorter.vue'
|
||||
import Component from './SongListHeaderActionMenu.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
|
@ -15,6 +15,12 @@ new class extends UnitTestCase {
|
|||
)
|
||||
})
|
||||
|
||||
it ('emits the sort event when an item is clicked', async () => {
|
||||
const { emitted } = this.render(Component)
|
||||
await this.user.click(screen.getByText('Title'))
|
||||
expect(emitted().sort[0]).toEqual(['title'])
|
||||
})
|
||||
|
||||
it('contains proper items for episode-only lists', () => {
|
||||
this.render(Component, {
|
||||
props: {
|
||||
|
@ -49,6 +55,17 @@ new class extends UnitTestCase {
|
|||
screen.getByText('Custom Order')
|
||||
})
|
||||
|
||||
it('does not sort if the list is not sortable', async () => {
|
||||
const { emitted } = this.render(Component, {
|
||||
props: {
|
||||
sortable: false,
|
||||
},
|
||||
})
|
||||
|
||||
await this.user.click(screen.getByText('Title'))
|
||||
expect(emitted().sort).toBeUndefined()
|
||||
})
|
||||
|
||||
it('has a checkbox to toggle the column visibility', async () => {
|
||||
this.be().render(Component)
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<article>
|
||||
<button ref="button" class="w-full focus:text-k-highlight" title="Sort" @click.stop="trigger">
|
||||
<Icon :icon="faSort" />
|
||||
<Icon v-if="sortable" :icon="faSort" />
|
||||
<Icon v-else :icon="faEllipsis" />
|
||||
</button>
|
||||
<OnClickOutside @trigger="hide">
|
||||
<menu ref="menu" class="context-menu normal-case tracking-normal">
|
||||
|
@ -10,7 +11,7 @@
|
|||
:key="item.label"
|
||||
:class="currentlySortedBy(item.field) && 'active'"
|
||||
class="cursor-pointer flex justify-between !pl-3 hover:!bg-white/10"
|
||||
@click="sort(item.field)"
|
||||
@click="sortable && sort(item.field)"
|
||||
>
|
||||
<label
|
||||
v-if="shouldShowColumnVisibilityCheckboxes()"
|
||||
|
@ -39,7 +40,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { isEqual } from 'lodash'
|
||||
import { faArrowDown, faArrowUp, faCheck, faSort } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faArrowDown, faArrowUp, faCheck, faEllipsis, faSort } from '@fortawesome/free-solid-svg-icons'
|
||||
import { OnClickOutside } from '@vueuse/components'
|
||||
import { computed, onBeforeUnmount, onMounted, ref, toRefs } from 'vue'
|
||||
import { useFloatingUi } from '@/composables/useFloatingUi'
|
||||
|
@ -48,11 +49,13 @@ import type { getPlayableCollectionContentType } from '@/utils/typeGuards'
|
|||
import { usePlayableListColumnVisibility } from '@/composables/usePlayableListColumnVisibility'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
sortable?: boolean
|
||||
field?: MaybeArray<PlayableListSortField> // the current field(s) being sorted by
|
||||
order?: SortOrder
|
||||
hasCustomOrderSort?: boolean // whether to provide "custom order" sort (like for playlists)
|
||||
contentType?: ReturnType<typeof getPlayableCollectionContentType>
|
||||
}>(), {
|
||||
sortable: true,
|
||||
field: 'title',
|
||||
order: 'asc',
|
||||
hasCustomOrderSort: false,
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
exports[`renders 1`] = `
|
||||
<div class="sortable song-list-header flex z-[2] bg-k-bg-secondary pl-5"><span class="track-number" data-testid="header-track-number" role="button" title="Sort by track number"> # <!--v-if--><!--v-if--></span><span class="title-artist" data-testid="header-title" role="button" title="Sort by title"> Title <br data-testid="Icon" icon="[object Object]" class="text-k-highlight"><!--v-if--></span><span title="Sort by album" class="album" data-testid="header-album" role="button">Album<span class="ml-2"><!--v-if--><!--v-if--></span></span>
|
||||
<!--v-if--><span class="time" data-testid="header-length" role="button" title="Sort by duration"> Time <!--v-if--><!--v-if--></span><span class="extra"><br data-testid="song-list-sorter" field="title" order="asc" content-type="songs"></span>
|
||||
<!--v-if--><span class="time" data-testid="header-length" role="button" title="Sort by duration"> Time <!--v-if--><!--v-if--></span><span class="extra"><br data-testid="song-list-header-action-menu" sortable="true" field="title" order="asc" content-type="songs"></span>
|
||||
</div>
|
||||
`;
|
||||
|
|
Loading…
Reference in a new issue