mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-11 02:20:08 +00:00
feat: sort workspaces (#8770)
## Summary Sort workspaces so that the personal workspace appears first, followed by the rest in ascending order (oldest first) by created_at / joined_at. ## Changes - **What**: teamWorkspaceStore.ts, teamWorkspaceStore.test.ts - **Breaking**: <!-- Any breaking changes (if none, remove this line) --> - **Dependencies**: <!-- New dependencies (if none, remove this line) -->
This commit is contained in:
@@ -53,7 +53,9 @@ describe('useWorkspaceSwitch', () => {
|
||||
id: 'workspace-1',
|
||||
name: 'Test Workspace',
|
||||
type: 'personal',
|
||||
role: 'owner'
|
||||
role: 'owner',
|
||||
created_at: '2026-01-01T00:00:00Z',
|
||||
joined_at: '2026-01-01T00:00:00Z'
|
||||
}
|
||||
mockModifiedWorkflows.length = 0
|
||||
})
|
||||
|
||||
@@ -11,6 +11,8 @@ interface Workspace {
|
||||
id: string
|
||||
name: string
|
||||
type: WorkspaceType
|
||||
created_at: string
|
||||
joined_at: string
|
||||
}
|
||||
|
||||
export interface WorkspaceWithRole extends Workspace {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createTestingPinia } from '@pinia/testing'
|
||||
import { setActivePinia } from 'pinia'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { useTeamWorkspaceStore } from './teamWorkspaceStore'
|
||||
import { sortWorkspaces, useTeamWorkspaceStore } from './teamWorkspaceStore'
|
||||
|
||||
// Mock workspaceAuthStore
|
||||
const mockWorkspaceAuthStore = vi.hoisted(() => ({
|
||||
@@ -93,21 +93,27 @@ const mockPersonalWorkspace = {
|
||||
id: 'ws-personal-123',
|
||||
name: 'Personal',
|
||||
type: 'personal' as const,
|
||||
role: 'owner' as const
|
||||
role: 'owner' as const,
|
||||
created_at: '2026-01-01T00:00:00Z',
|
||||
joined_at: '2026-01-01T00:00:00Z'
|
||||
}
|
||||
|
||||
const mockTeamWorkspace = {
|
||||
id: 'ws-team-456',
|
||||
name: 'Team Alpha',
|
||||
type: 'team' as const,
|
||||
role: 'owner' as const
|
||||
role: 'owner' as const,
|
||||
created_at: '2026-02-01T00:00:00Z',
|
||||
joined_at: '2026-02-01T00:00:00Z'
|
||||
}
|
||||
|
||||
const mockMemberWorkspace = {
|
||||
id: 'ws-team-789',
|
||||
name: 'Team Beta',
|
||||
type: 'team' as const,
|
||||
role: 'member' as const
|
||||
role: 'member' as const,
|
||||
created_at: '2026-03-01T00:00:00Z',
|
||||
joined_at: '2026-03-01T00:00:00Z'
|
||||
}
|
||||
|
||||
describe('useTeamWorkspaceStore', () => {
|
||||
@@ -309,7 +315,9 @@ describe('useTeamWorkspaceStore', () => {
|
||||
id: 'ws-new-999',
|
||||
name: 'New Workspace',
|
||||
type: 'team' as const,
|
||||
role: 'member' as const
|
||||
role: 'member' as const,
|
||||
created_at: '2026-04-01T00:00:00Z',
|
||||
joined_at: '2026-04-01T00:00:00Z'
|
||||
}
|
||||
|
||||
mockWorkspaceApi.list
|
||||
@@ -347,7 +355,9 @@ describe('useTeamWorkspaceStore', () => {
|
||||
id: 'ws-new-created',
|
||||
name: 'Created Workspace',
|
||||
type: 'team' as const,
|
||||
role: 'owner' as const
|
||||
role: 'owner' as const,
|
||||
created_at: '2026-05-01T00:00:00Z',
|
||||
joined_at: '2026-05-01T00:00:00Z'
|
||||
}
|
||||
mockWorkspaceApi.create.mockResolvedValue(newWorkspace)
|
||||
|
||||
@@ -386,7 +396,9 @@ describe('useTeamWorkspaceStore', () => {
|
||||
id: 'ws-new',
|
||||
name: 'New Workspace',
|
||||
type: 'team',
|
||||
role: 'owner'
|
||||
role: 'owner',
|
||||
created_at: '2026-06-01T00:00:00Z',
|
||||
joined_at: '2026-06-01T00:00:00Z'
|
||||
})
|
||||
await resultPromise
|
||||
})
|
||||
@@ -572,7 +584,9 @@ describe('useTeamWorkspaceStore', () => {
|
||||
id: `ws-owned-${i}`,
|
||||
name: `Owned ${i}`,
|
||||
type: 'team' as const,
|
||||
role: 'owner' as const
|
||||
role: 'owner' as const,
|
||||
created_at: `2026-${String(i + 1).padStart(2, '0')}-01T00:00:00Z`,
|
||||
joined_at: `2026-${String(i + 1).padStart(2, '0')}-01T00:00:00Z`
|
||||
}))
|
||||
|
||||
mockWorkspaceApi.list.mockResolvedValue({
|
||||
@@ -916,3 +930,49 @@ describe('useTeamWorkspaceStore', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('sortWorkspaces', () => {
|
||||
it('places personal first, then sorts ascending by created_at for owners and joined_at for members', () => {
|
||||
const input = [
|
||||
{
|
||||
created_at: '2026-06-01T00:00:00Z',
|
||||
id: 'w-team-new-owner',
|
||||
joined_at: '2026-01-01T00:00:00Z',
|
||||
name: 'Newest Owner Team',
|
||||
role: 'owner' as const,
|
||||
type: 'team' as const
|
||||
},
|
||||
{
|
||||
created_at: '2026-12-01T00:00:00Z',
|
||||
id: 'w-personal',
|
||||
joined_at: '2026-12-01T00:00:00Z',
|
||||
name: 'Personal Workspace',
|
||||
role: 'owner' as const,
|
||||
type: 'personal' as const
|
||||
},
|
||||
{
|
||||
created_at: '2026-01-01T00:00:00Z',
|
||||
id: 'w-team-member',
|
||||
joined_at: '2026-04-01T00:00:00Z',
|
||||
name: 'Member Team',
|
||||
role: 'member' as const,
|
||||
type: 'team' as const
|
||||
},
|
||||
{
|
||||
created_at: '2026-02-01T00:00:00Z',
|
||||
id: 'w-team-old-owner',
|
||||
joined_at: '2026-09-01T00:00:00Z',
|
||||
name: 'Oldest Owner Team',
|
||||
role: 'owner' as const,
|
||||
type: 'team' as const
|
||||
}
|
||||
]
|
||||
|
||||
expect(sortWorkspaces(input).map((w) => w.id)).toEqual([
|
||||
'w-personal',
|
||||
'w-team-old-owner',
|
||||
'w-team-member',
|
||||
'w-team-new-owner'
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -76,6 +76,16 @@ function createWorkspaceState(workspace: WorkspaceWithRole): WorkspaceState {
|
||||
}
|
||||
}
|
||||
|
||||
export function sortWorkspaces<T extends WorkspaceWithRole>(list: T[]): T[] {
|
||||
return [...list].sort((a, b) => {
|
||||
if (a.type === 'personal') return -1
|
||||
if (b.type === 'personal') return 1
|
||||
const dateA = a.role === 'owner' ? a.created_at : a.joined_at
|
||||
const dateB = b.role === 'owner' ? b.created_at : b.joined_at
|
||||
return dateA.localeCompare(dateB)
|
||||
})
|
||||
}
|
||||
|
||||
function getLastWorkspaceId(): string | null {
|
||||
try {
|
||||
return localStorage.getItem(WORKSPACE_STORAGE_KEYS.LAST_WORKSPACE_ID)
|
||||
@@ -205,7 +215,9 @@ export const useTeamWorkspaceStore = defineStore('teamWorkspace', () => {
|
||||
if (hasValidSession && workspaceAuthStore.currentWorkspace) {
|
||||
// Valid session exists - fetch workspace list and verify access
|
||||
const response = await workspaceApi.list()
|
||||
workspaces.value = response.workspaces.map(createWorkspaceState)
|
||||
workspaces.value = sortWorkspaces(
|
||||
response.workspaces.map(createWorkspaceState)
|
||||
)
|
||||
|
||||
if (workspaces.value.length === 0) {
|
||||
throw new Error('No workspaces available')
|
||||
@@ -247,7 +259,9 @@ export const useTeamWorkspaceStore = defineStore('teamWorkspace', () => {
|
||||
|
||||
// 2. No valid session - fetch workspaces and pick default
|
||||
const response = await workspaceApi.list()
|
||||
workspaces.value = response.workspaces.map(createWorkspaceState)
|
||||
workspaces.value = sortWorkspaces(
|
||||
response.workspaces.map(createWorkspaceState)
|
||||
)
|
||||
|
||||
if (workspaces.value.length === 0) {
|
||||
throw new Error('No workspaces available')
|
||||
@@ -315,7 +329,9 @@ export const useTeamWorkspaceStore = defineStore('teamWorkspace', () => {
|
||||
isFetchingWorkspaces.value = true
|
||||
try {
|
||||
const response = await workspaceApi.list()
|
||||
workspaces.value = response.workspaces.map(createWorkspaceState)
|
||||
workspaces.value = sortWorkspaces(
|
||||
response.workspaces.map(createWorkspaceState)
|
||||
)
|
||||
} finally {
|
||||
isFetchingWorkspaces.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user