mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-18 22:10:03 +00:00
Merge branch 'main' into refactor/setting-dialog
This commit is contained in:
@@ -309,7 +309,10 @@ test.describe('Settings', () => {
|
||||
await input.press('Alt+n')
|
||||
|
||||
const requestPromise = comfyPage.page.waitForRequest(
|
||||
'**/api/settings/Comfy.Keybinding.NewBindings'
|
||||
(req) =>
|
||||
req.url().includes('/api/settings') &&
|
||||
!req.url().includes('/api/settings/') &&
|
||||
req.method() === 'POST'
|
||||
)
|
||||
|
||||
// Save keybinding
|
||||
|
||||
@@ -197,6 +197,7 @@ describe('useCoreCommands', () => {
|
||||
addSetting: vi.fn(),
|
||||
load: vi.fn(),
|
||||
set: vi.fn(),
|
||||
setMany: vi.fn(),
|
||||
exists: vi.fn(),
|
||||
getDefaultValue: vi.fn(),
|
||||
isReady: true,
|
||||
|
||||
@@ -73,6 +73,28 @@ describe('LinkConnector SubgraphInput connection validation', () => {
|
||||
expect(toTargetNode.onConnectionsChange).toHaveBeenCalledTimes(1)
|
||||
expect(fromTargetNode.onConnectionsChange).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
it('should allow reconnection to same target', () => {
|
||||
const subgraph = createTestSubgraph({
|
||||
inputs: [{ name: 'number_input', type: 'number' }]
|
||||
})
|
||||
|
||||
const node = new LGraphNode('TargetNode')
|
||||
node.addInput('number_in', 'number')
|
||||
subgraph.add(node)
|
||||
|
||||
const link = subgraph.inputNode.slots[0].connect(node.inputs[0], node)
|
||||
|
||||
const renderLink = new ToInputFromIoNodeLink(
|
||||
subgraph,
|
||||
subgraph.inputNode,
|
||||
subgraph.inputNode.slots[0],
|
||||
undefined,
|
||||
LinkDirection.CENTER,
|
||||
link
|
||||
)
|
||||
renderLink.connectToInput(node, node.inputs[0], connector.events)
|
||||
expect(node.inputs[0].link).not.toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('MovingOutputLink validation', () => {
|
||||
|
||||
@@ -58,6 +58,12 @@ export class ToInputFromIoNodeLink implements RenderLink {
|
||||
events: CustomEventTarget<LinkConnectorEventMap>
|
||||
) {
|
||||
const { fromSlot, fromReroute, existingLink } = this
|
||||
if (
|
||||
existingLink &&
|
||||
node.id === existingLink.target_id &&
|
||||
node.inputs[existingLink.target_slot] === input
|
||||
)
|
||||
return
|
||||
|
||||
const newLink = fromSlot.connect(input, node, fromReroute?.id)
|
||||
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -137,14 +137,14 @@ export function useKeybindingService() {
|
||||
}
|
||||
|
||||
async function persistUserKeybindings() {
|
||||
await settingStore.set(
|
||||
'Comfy.Keybinding.NewBindings',
|
||||
Object.values(keybindingStore.getUserKeybindings())
|
||||
)
|
||||
await settingStore.set(
|
||||
'Comfy.Keybinding.UnsetBindings',
|
||||
Object.values(keybindingStore.getUserUnsetKeybindings())
|
||||
)
|
||||
await settingStore.setMany({
|
||||
'Comfy.Keybinding.NewBindings': Object.values(
|
||||
keybindingStore.getUserKeybindings()
|
||||
),
|
||||
'Comfy.Keybinding.UnsetBindings': Object.values(
|
||||
keybindingStore.getUserUnsetKeybindings()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -170,13 +170,15 @@ export const CORE_SETTINGS: SettingParams[] = [
|
||||
const settingStore = useSettingStore()
|
||||
|
||||
if (newValue === 'standard') {
|
||||
// Update related settings to match standard mode - select + panning
|
||||
await settingStore.set('Comfy.Canvas.LeftMouseClickBehavior', 'select')
|
||||
await settingStore.set('Comfy.Canvas.MouseWheelScroll', 'panning')
|
||||
await settingStore.setMany({
|
||||
'Comfy.Canvas.LeftMouseClickBehavior': 'select',
|
||||
'Comfy.Canvas.MouseWheelScroll': 'panning'
|
||||
})
|
||||
} else if (newValue === 'legacy') {
|
||||
// Update related settings to match legacy mode - panning + zoom
|
||||
await settingStore.set('Comfy.Canvas.LeftMouseClickBehavior', 'panning')
|
||||
await settingStore.set('Comfy.Canvas.MouseWheelScroll', 'zoom')
|
||||
await settingStore.setMany({
|
||||
'Comfy.Canvas.LeftMouseClickBehavior': 'panning',
|
||||
'Comfy.Canvas.MouseWheelScroll': 'zoom'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15,7 +15,8 @@ import { app } from '@/scripts/app'
|
||||
vi.mock('@/scripts/api', () => ({
|
||||
api: {
|
||||
getSettings: vi.fn(),
|
||||
storeSetting: vi.fn()
|
||||
storeSetting: vi.fn(),
|
||||
storeSettings: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -503,6 +504,85 @@ describe('useSettingStore', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('setMany', () => {
|
||||
it('should set multiple values and make a single API call', async () => {
|
||||
const onChange1 = vi.fn()
|
||||
const onChange2 = vi.fn()
|
||||
store.addSetting({
|
||||
id: 'Comfy.Release.Version',
|
||||
name: 'Release Version',
|
||||
type: 'hidden',
|
||||
defaultValue: '',
|
||||
onChange: onChange1
|
||||
})
|
||||
store.addSetting({
|
||||
id: 'Comfy.Release.Status',
|
||||
name: 'Release Status',
|
||||
type: 'hidden',
|
||||
defaultValue: 'skipped',
|
||||
onChange: onChange2
|
||||
})
|
||||
vi.clearAllMocks()
|
||||
|
||||
await store.setMany({
|
||||
'Comfy.Release.Version': '1.0.0',
|
||||
'Comfy.Release.Status': 'changelog seen'
|
||||
})
|
||||
|
||||
expect(store.get('Comfy.Release.Version')).toBe('1.0.0')
|
||||
expect(store.get('Comfy.Release.Status')).toBe('changelog seen')
|
||||
expect(onChange1).toHaveBeenCalledWith('1.0.0', '')
|
||||
expect(onChange2).toHaveBeenCalledWith('changelog seen', 'skipped')
|
||||
expect(api.storeSettings).toHaveBeenCalledTimes(1)
|
||||
expect(api.storeSettings).toHaveBeenCalledWith({
|
||||
'Comfy.Release.Version': '1.0.0',
|
||||
'Comfy.Release.Status': 'changelog seen'
|
||||
})
|
||||
expect(api.storeSetting).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should skip unchanged values', async () => {
|
||||
store.addSetting({
|
||||
id: 'Comfy.Release.Version',
|
||||
name: 'Release Version',
|
||||
type: 'hidden',
|
||||
defaultValue: ''
|
||||
})
|
||||
store.addSetting({
|
||||
id: 'Comfy.Release.Status',
|
||||
name: 'Release Status',
|
||||
type: 'hidden',
|
||||
defaultValue: 'skipped'
|
||||
})
|
||||
await store.set('Comfy.Release.Version', 'existing')
|
||||
vi.clearAllMocks()
|
||||
|
||||
await store.setMany({
|
||||
'Comfy.Release.Version': 'existing',
|
||||
'Comfy.Release.Status': 'changelog seen'
|
||||
})
|
||||
|
||||
expect(api.storeSettings).toHaveBeenCalledWith({
|
||||
'Comfy.Release.Status': 'changelog seen'
|
||||
})
|
||||
})
|
||||
|
||||
it('should not call API when all values are unchanged', async () => {
|
||||
store.addSetting({
|
||||
id: 'Comfy.Release.Version',
|
||||
name: 'Release Version',
|
||||
type: 'hidden',
|
||||
defaultValue: ''
|
||||
})
|
||||
await store.set('Comfy.Release.Version', 'existing')
|
||||
vi.clearAllMocks()
|
||||
|
||||
await store.setMany({ 'Comfy.Release.Version': 'existing' })
|
||||
|
||||
expect(api.storeSettings).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getSettingInfo', () => {
|
||||
|
||||
@@ -92,23 +92,58 @@ export const useSettingStore = defineStore('setting', () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a setting value.
|
||||
* @param key - The key of the setting to set.
|
||||
* @param value - The value to set.
|
||||
* Apply a setting value locally: clone, migrate, fire onChange, and
|
||||
* update the in-memory store. Returns the migrated value, or
|
||||
* `undefined` when the value is unchanged and was skipped.
|
||||
*/
|
||||
async function set<K extends keyof Settings>(key: K, value: Settings[K]) {
|
||||
// Clone the incoming value to prevent external mutations
|
||||
function applySettingLocally<K extends keyof Settings>(
|
||||
key: K,
|
||||
value: Settings[K]
|
||||
): Settings[K] | undefined {
|
||||
const clonedValue = _.cloneDeep(value)
|
||||
const newValue = tryMigrateDeprecatedValue(
|
||||
settingsById.value[key],
|
||||
clonedValue
|
||||
)
|
||||
const oldValue = get(key)
|
||||
if (newValue === oldValue) return
|
||||
if (newValue === oldValue) return undefined
|
||||
|
||||
onChange(settingsById.value[key], newValue, oldValue)
|
||||
settingValues.value[key] = newValue
|
||||
await api.storeSetting(key, newValue)
|
||||
return newValue as Settings[K]
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a setting value.
|
||||
* @param key - The key of the setting to set.
|
||||
* @param value - The value to set.
|
||||
*/
|
||||
async function set<K extends keyof Settings>(key: K, value: Settings[K]) {
|
||||
const applied = applySettingLocally(key, value)
|
||||
if (applied === undefined) return
|
||||
await api.storeSetting(key, applied)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set multiple setting values in a single API call.
|
||||
* @param settings - A partial settings object with key-value pairs to set.
|
||||
*/
|
||||
async function setMany(settings: Partial<Settings>) {
|
||||
const updatedSettings: Partial<Settings> = {}
|
||||
|
||||
for (const key of Object.keys(settings) as (keyof Settings)[]) {
|
||||
const applied = applySettingLocally(
|
||||
key,
|
||||
settings[key] as Settings[typeof key]
|
||||
)
|
||||
if (applied !== undefined) {
|
||||
updatedSettings[key] = applied
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(updatedSettings).length > 0) {
|
||||
await api.storeSettings(updatedSettings)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,6 +306,7 @@ export const useSettingStore = defineStore('setting', () => {
|
||||
load,
|
||||
addSetting,
|
||||
set,
|
||||
setMany,
|
||||
get,
|
||||
exists,
|
||||
getDefaultValue
|
||||
|
||||
@@ -46,8 +46,9 @@ vi.mock('@/platform/settings/settingStore', () => {
|
||||
return null
|
||||
})
|
||||
const set = vi.fn()
|
||||
const setMany = vi.fn()
|
||||
return {
|
||||
useSettingStore: () => ({ get, set })
|
||||
useSettingStore: () => ({ get, set, setMany })
|
||||
}
|
||||
})
|
||||
|
||||
@@ -534,18 +535,11 @@ describe('useReleaseStore', () => {
|
||||
const settingStore = useSettingStore()
|
||||
await store.handleSkipRelease('1.2.0')
|
||||
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Version',
|
||||
'1.2.0'
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Status',
|
||||
'skipped'
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Timestamp',
|
||||
expect.any(Number)
|
||||
)
|
||||
expect(settingStore.setMany).toHaveBeenCalledWith({
|
||||
'Comfy.Release.Version': '1.2.0',
|
||||
'Comfy.Release.Status': 'skipped',
|
||||
'Comfy.Release.Timestamp': expect.any(Number)
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle show changelog', async () => {
|
||||
@@ -554,18 +548,11 @@ describe('useReleaseStore', () => {
|
||||
const settingStore = useSettingStore()
|
||||
await store.handleShowChangelog('1.2.0')
|
||||
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Version',
|
||||
'1.2.0'
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Status',
|
||||
'changelog seen'
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Timestamp',
|
||||
expect.any(Number)
|
||||
)
|
||||
expect(settingStore.setMany).toHaveBeenCalledWith({
|
||||
'Comfy.Release.Version': '1.2.0',
|
||||
'Comfy.Release.Status': 'changelog seen',
|
||||
'Comfy.Release.Timestamp': expect.any(Number)
|
||||
})
|
||||
})
|
||||
|
||||
it('should handle whats new seen', async () => {
|
||||
@@ -574,18 +561,11 @@ describe('useReleaseStore', () => {
|
||||
const settingStore = useSettingStore()
|
||||
await store.handleWhatsNewSeen('1.2.0')
|
||||
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Version',
|
||||
'1.2.0'
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Status',
|
||||
"what's new seen"
|
||||
)
|
||||
expect(settingStore.set).toHaveBeenCalledWith(
|
||||
'Comfy.Release.Timestamp',
|
||||
expect.any(Number)
|
||||
)
|
||||
expect(settingStore.setMany).toHaveBeenCalledWith({
|
||||
'Comfy.Release.Version': '1.2.0',
|
||||
'Comfy.Release.Status': "what's new seen",
|
||||
'Comfy.Release.Timestamp': expect.any(Number)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -208,9 +208,11 @@ export const useReleaseStore = defineStore('release', () => {
|
||||
return
|
||||
}
|
||||
|
||||
await settingStore.set('Comfy.Release.Version', version)
|
||||
await settingStore.set('Comfy.Release.Status', 'skipped')
|
||||
await settingStore.set('Comfy.Release.Timestamp', Date.now())
|
||||
await settingStore.setMany({
|
||||
'Comfy.Release.Version': version,
|
||||
'Comfy.Release.Status': 'skipped',
|
||||
'Comfy.Release.Timestamp': Date.now()
|
||||
})
|
||||
}
|
||||
|
||||
async function handleShowChangelog(version: string): Promise<void> {
|
||||
@@ -218,9 +220,11 @@ export const useReleaseStore = defineStore('release', () => {
|
||||
return
|
||||
}
|
||||
|
||||
await settingStore.set('Comfy.Release.Version', version)
|
||||
await settingStore.set('Comfy.Release.Status', 'changelog seen')
|
||||
await settingStore.set('Comfy.Release.Timestamp', Date.now())
|
||||
await settingStore.setMany({
|
||||
'Comfy.Release.Version': version,
|
||||
'Comfy.Release.Status': 'changelog seen',
|
||||
'Comfy.Release.Timestamp': Date.now()
|
||||
})
|
||||
}
|
||||
|
||||
async function handleWhatsNewSeen(version: string): Promise<void> {
|
||||
@@ -228,9 +232,11 @@ export const useReleaseStore = defineStore('release', () => {
|
||||
return
|
||||
}
|
||||
|
||||
await settingStore.set('Comfy.Release.Version', version)
|
||||
await settingStore.set('Comfy.Release.Status', "what's new seen")
|
||||
await settingStore.set('Comfy.Release.Timestamp', Date.now())
|
||||
await settingStore.setMany({
|
||||
'Comfy.Release.Version': version,
|
||||
'Comfy.Release.Status': "what's new seen",
|
||||
'Comfy.Release.Timestamp': Date.now()
|
||||
})
|
||||
}
|
||||
|
||||
// Fetch releases from API
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1047,7 +1047,7 @@ export class ComfyApi extends EventTarget {
|
||||
/**
|
||||
* Stores a dictionary of settings for the current user
|
||||
*/
|
||||
async storeSettings(settings: Settings) {
|
||||
async storeSettings(settings: Partial<Settings>) {
|
||||
return this.fetchApi(`/settings`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(settings)
|
||||
|
||||
Reference in New Issue
Block a user