feat(ui-workspace): support manual flat-list ordering
This commit is contained in:
@@ -102,6 +102,7 @@ describe('WorkspaceBrowser.module.css list', () => {
|
||||
expect(declarations('.searchExpanded')?.get('height')).toBe('30px')
|
||||
expect(rowDeclarations('.projectRow')?.get('height')).toBe('34px')
|
||||
expect(rowDeclarations('.sessionRow')?.get('height')).toBe('32px')
|
||||
expect(rowDeclarations('.flatSessionRowWithoutStatus .title')?.get('margin-left')).toBe('0')
|
||||
expect(rowDeclarations('.searchResultRow')?.get('min-height')).toBe('48px')
|
||||
expect(rowDeclarations('.sessionRow.selected')?.get('background'))
|
||||
.toBe('var(--dsw-alias-interactive-bg-hover)')
|
||||
|
||||
@@ -57,6 +57,21 @@ function fireDrag(row: HTMLElement, kind: 'dragOver' | 'drop', clientY: number):
|
||||
}
|
||||
|
||||
describe('workspace browser rows', () => {
|
||||
it('omits only an empty leading status slot in the hierarchy-free flat list', () => {
|
||||
const idle: SessionNode = {
|
||||
id: sid('flat'), title: 'Flat Session', blank: false, running: false,
|
||||
runningSubagentCount: 0, completed: false, updatedAt: 0,
|
||||
}
|
||||
const view = render(<SessionNodeItem node={idle} currentId={undefined} now={0} onOpen={vi.fn()}
|
||||
onRename={vi.fn()} onFork={vi.fn()} onArchive={vi.fn()} flat t={t} />)
|
||||
const title = screen.getByText('Flat Session')
|
||||
expect(title.previousElementSibling).toBeNull()
|
||||
|
||||
view.rerender(<SessionNodeItem node={{ ...idle, running: true }} currentId={undefined} now={0}
|
||||
onOpen={vi.fn()} onRename={vi.fn()} onFork={vi.fn()} onArchive={vi.fn()} flat t={t} />)
|
||||
expect(screen.getByText('Flat Session').previousElementSibling?.querySelector('[data-state="ongoing"]')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders a selected content-search row and opens only its session', () => {
|
||||
const onOpen = vi.fn()
|
||||
const result: SearchResultNode = {
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
|
||||
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
|
||||
import type { WorkspaceBrowserProps } from '../src/client/contract/slots.ts'
|
||||
import { createWorkspaceViewStore } from '../src/client/stores.ts'
|
||||
import { createWorkspaceViewStore, FLAT_SESSION_ORDER_KEY } from '../src/client/stores.ts'
|
||||
import { UNGROUPED_KEY } from '../src/client/tree.ts'
|
||||
import { WorkspaceBrowser } from '../src/client/WorkspaceBrowser.tsx'
|
||||
import { zh } from '../src/client/locales.ts'
|
||||
@@ -130,6 +130,7 @@ describe('WorkspaceBrowser', () => {
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
expect(screen.getByText('分组方式')).toBeTruthy() // the menu heading label
|
||||
expect(screen.getByRole('separator')).toBeTruthy()
|
||||
expect(screen.getAllByRole('menuitem').map(item => item.textContent)).toEqual([
|
||||
'按工作区', '单列表', '手动排序', '最近更新',
|
||||
])
|
||||
@@ -145,6 +146,7 @@ describe('WorkspaceBrowser', () => {
|
||||
|
||||
// Back to workspace grouping through the same menu.
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
expect(screen.getByRole('menuitem', { name: '手动排序' }).hasAttribute('disabled')).toBe(false)
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '按工作区' }))
|
||||
expect(b.store.getSnapshot().groupBy).toBe('workspace')
|
||||
expect(screen.getByText('工作区')).toBeTruthy()
|
||||
@@ -156,6 +158,60 @@ describe('WorkspaceBrowser', () => {
|
||||
expect(b.store.getSnapshot().groupBy).toBe('workspace')
|
||||
})
|
||||
|
||||
it('persists flat-list drag order locally and applies Last updated within that account', async () => {
|
||||
const insertSessionBefore = vi.fn(async () => {})
|
||||
const sessions = sessionState([summary('one', 3), summary('two', 2), summary('three', 1)])
|
||||
const workspaces = workspaceState([
|
||||
workspace('alpha', ['one']),
|
||||
workspace('beta', ['two']),
|
||||
])
|
||||
const b = mount({
|
||||
useSessions: hook(sessions),
|
||||
useWorkspaces: hook(workspaces),
|
||||
insertSessionBefore,
|
||||
})
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '单列表' }))
|
||||
await waitFor(() => {
|
||||
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
|
||||
.toEqual(['one', 'two', 'three'])
|
||||
})
|
||||
|
||||
const one = screen.getByText('one').closest('[role="treeitem"]') as HTMLElement
|
||||
const three = screen.getByText('three').closest('[role="treeitem"]') as HTMLElement
|
||||
three.getBoundingClientRect = () => ({
|
||||
top: 150, bottom: 184, left: 0, right: 200, width: 200, height: 34,
|
||||
x: 0, y: 150, toJSON: () => ({}),
|
||||
})
|
||||
fireEvent.dragStart(one, { dataTransfer: dragData() })
|
||||
fireDrag(three, 'drop', 180)
|
||||
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
|
||||
.toEqual(['two', 'three', 'one'])
|
||||
expect(insertSessionBefore).not.toHaveBeenCalled()
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '最近更新' }))
|
||||
await waitFor(() => {
|
||||
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
|
||||
.toEqual(['one', 'two', 'three'])
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
|
||||
fireEvent.click(screen.getByRole('menuitem', { name: '手动排序' }))
|
||||
fireEvent.dragStart(one, { dataTransfer: dragData() })
|
||||
fireDrag(three, 'drop', 180)
|
||||
b.view.unmount()
|
||||
|
||||
const restored = mount({ useSessions: hook(sessions), useWorkspaces: hook(workspaces) })
|
||||
expect(restored.store.getSnapshot().groupBy).toBe('flat')
|
||||
expect(restored.store.getSnapshot().orderBy).toBe('manual')
|
||||
expect(screen.getAllByRole('treeitem').map(row => row.textContent)).toEqual([
|
||||
expect.stringContaining('two'),
|
||||
expect.stringContaining('three'),
|
||||
expect.stringContaining('one'),
|
||||
])
|
||||
})
|
||||
|
||||
it('expands a group on click and opens a session row', () => {
|
||||
const open = vi.fn()
|
||||
mount({
|
||||
|
||||
Reference in New Issue
Block a user