diff --git a/src/locales/ar/main.json b/src/locales/ar/main.json index edd8989edd..fe97f4f530 100644 --- a/src/locales/ar/main.json +++ b/src/locales/ar/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "تمت إضافتك إلى {workspaceName}", "inviteAccepted": "تم قبول الدعوة", "inviteFailed": "فشل في قبول الدعوة", - "unsavedChanges": { - "message": "لديك تغييرات غير محفوظة. هل تريد تجاهلها والانتقال إلى مساحة عمل أخرى؟", - "title": "تغييرات غير محفوظة" - }, "viewWorkspace": "عرض مساحة العمل" }, "workspaceAuth": { diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 9e19cb6de5..317946b995 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -3405,14 +3405,11 @@ "retryDownload": "Retry download" }, "workspace": { - "unsavedChanges": { - "title": "Unsaved Changes", - "message": "You have unsaved changes. Do you want to discard them and switch workspaces?" - }, "inviteAccepted": "Invite Accepted", "addedToWorkspace": "You have been added to:", "inviteFailed": "Failed to Accept Invite", - "viewWorkspace": "View workspace" + "viewWorkspace": "View workspace", + "switchFailed": "Failed to switch workspace. Please try again." }, "workspaceAuth": { "errors": { diff --git a/src/locales/es/main.json b/src/locales/es/main.json index 680d555c76..25551d03e6 100644 --- a/src/locales/es/main.json +++ b/src/locales/es/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "Has sido añadido a {workspaceName}", "inviteAccepted": "Invitación aceptada", "inviteFailed": "No se pudo aceptar la invitación", - "unsavedChanges": { - "message": "Tienes cambios no guardados. ¿Quieres descartarlos y cambiar de espacio de trabajo?", - "title": "Cambios no guardados" - }, "viewWorkspace": "Ver espacio de trabajo" }, "workspaceAuth": { diff --git a/src/locales/fa/main.json b/src/locales/fa/main.json index ca32e54d98..77cefea779 100644 --- a/src/locales/fa/main.json +++ b/src/locales/fa/main.json @@ -3385,10 +3385,6 @@ "addedToWorkspace": "شما به {workspaceName} اضافه شدید", "inviteAccepted": "دعوت پذیرفته شد", "inviteFailed": "پذیرش دعوت ناموفق بود", - "unsavedChanges": { - "message": "شما تغییرات ذخیره‌نشده دارید. آیا می‌خواهید آن‌ها را رها کرده و فضای کاری را تغییر دهید؟", - "title": "تغییرات ذخیره‌نشده" - }, "viewWorkspace": "مشاهده workspace" }, "workspaceAuth": { diff --git a/src/locales/fr/main.json b/src/locales/fr/main.json index 909db73f2b..5756ae4bb7 100644 --- a/src/locales/fr/main.json +++ b/src/locales/fr/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "Vous avez été ajouté à {workspaceName}", "inviteAccepted": "Invitation acceptée", "inviteFailed": "Échec de l'acceptation de l'invitation", - "unsavedChanges": { - "message": "Vous avez des modifications non enregistrées. Voulez-vous les abandonner et changer d’espace de travail ?", - "title": "Modifications non enregistrées" - }, "viewWorkspace": "Voir l’espace de travail" }, "workspaceAuth": { diff --git a/src/locales/ja/main.json b/src/locales/ja/main.json index b15483cb04..124e877006 100644 --- a/src/locales/ja/main.json +++ b/src/locales/ja/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "{workspaceName}に追加されました", "inviteAccepted": "招待を承諾しました", "inviteFailed": "招待の承諾に失敗しました", - "unsavedChanges": { - "message": "未保存の変更があります。破棄してワークスペースを切り替えますか?", - "title": "未保存の変更" - }, "viewWorkspace": "ワークスペースを見る" }, "workspaceAuth": { diff --git a/src/locales/ko/main.json b/src/locales/ko/main.json index 8c0c23753a..7077753b1e 100644 --- a/src/locales/ko/main.json +++ b/src/locales/ko/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "{workspaceName} 워크스페이스에 추가되었습니다", "inviteAccepted": "초대 수락됨", "inviteFailed": "초대 수락에 실패했습니다", - "unsavedChanges": { - "message": "저장되지 않은 변경 사항이 있습니다. 변경 사항을 취소하고 워크스페이스를 전환하시겠습니까?", - "title": "저장되지 않은 변경 사항" - }, "viewWorkspace": "워크스페이스 보기" }, "workspaceAuth": { diff --git a/src/locales/pt-BR/main.json b/src/locales/pt-BR/main.json index 9e016e13d1..25be413fc9 100644 --- a/src/locales/pt-BR/main.json +++ b/src/locales/pt-BR/main.json @@ -3385,10 +3385,6 @@ "addedToWorkspace": "Você foi adicionado ao {workspaceName}", "inviteAccepted": "Convite aceito", "inviteFailed": "Falha ao aceitar convite", - "unsavedChanges": { - "message": "Você tem alterações não salvas. Deseja descartá-las e trocar de espaço de trabalho?", - "title": "Alterações não salvas" - }, "viewWorkspace": "Ver workspace" }, "workspaceAuth": { diff --git a/src/locales/ru/main.json b/src/locales/ru/main.json index 5f60165232..73643396d6 100644 --- a/src/locales/ru/main.json +++ b/src/locales/ru/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "Вы были добавлены в {workspaceName}", "inviteAccepted": "Приглашение принято", "inviteFailed": "Не удалось принять приглашение", - "unsavedChanges": { - "message": "У вас есть несохранённые изменения. Хотите их отменить и переключиться на другое рабочее пространство?", - "title": "Несохранённые изменения" - }, "viewWorkspace": "Просмотреть рабочее пространство" }, "workspaceAuth": { diff --git a/src/locales/tr/main.json b/src/locales/tr/main.json index ff1fcb85dd..34793e6ff5 100644 --- a/src/locales/tr/main.json +++ b/src/locales/tr/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "{workspaceName} çalışma alanına eklendiniz", "inviteAccepted": "Davet kabul edildi", "inviteFailed": "Davet kabul edilemedi", - "unsavedChanges": { - "message": "Kaydedilmemiş değişiklikleriniz var. Bunları iptal edip çalışma alanlarını değiştirmek istiyor musunuz?", - "title": "Kaydedilmemiş Değişiklikler" - }, "viewWorkspace": "Çalışma alanını görüntüle" }, "workspaceAuth": { diff --git a/src/locales/zh-TW/main.json b/src/locales/zh-TW/main.json index 1d319c576c..322ec428e8 100644 --- a/src/locales/zh-TW/main.json +++ b/src/locales/zh-TW/main.json @@ -3373,10 +3373,6 @@ "addedToWorkspace": "你已被加入 {workspaceName}", "inviteAccepted": "已接受邀請", "inviteFailed": "接受邀請失敗", - "unsavedChanges": { - "message": "您有未儲存的變更。是否要捨棄這些變更並切換工作區?", - "title": "未儲存的變更" - }, "viewWorkspace": "檢視工作區" }, "workspaceAuth": { diff --git a/src/locales/zh/main.json b/src/locales/zh/main.json index 715f09952b..f1eaf44984 100644 --- a/src/locales/zh/main.json +++ b/src/locales/zh/main.json @@ -3385,10 +3385,6 @@ "addedToWorkspace": "您已被加入 {workspaceName}", "inviteAccepted": "邀请已接受", "inviteFailed": "接受邀请失败", - "unsavedChanges": { - "message": "您有未保存的更改。是否要放弃这些更改并切换工作区?", - "title": "未保存的更改" - }, "viewWorkspace": "查看工作区" }, "workspaceAuth": { diff --git a/src/platform/workspace/components/WorkspaceSwitcherPopover.vue b/src/platform/workspace/components/WorkspaceSwitcherPopover.vue index 555aff44ed..560d9d71c1 100644 --- a/src/platform/workspace/components/WorkspaceSwitcherPopover.vue +++ b/src/platform/workspace/components/WorkspaceSwitcherPopover.vue @@ -139,7 +139,7 @@ const emit = defineEmits<{ }>() const { t } = useI18n() -const { switchWithConfirmation } = useWorkspaceSwitch() +const { switchWorkspace } = useWorkspaceSwitch() const { subscription } = useBillingContext() const tierKeyMap: Record = { @@ -226,7 +226,7 @@ function getTierLabel(workspace: AvailableWorkspace): string | null { } async function handleSelectWorkspace(workspace: AvailableWorkspace) { - const success = await switchWithConfirmation(workspace.id) + const success = await switchWorkspace(workspace.id) if (success) { emit('select', workspace) } diff --git a/src/platform/workspace/components/toasts/InviteAcceptedToast.vue b/src/platform/workspace/components/toasts/InviteAcceptedToast.vue index 6c0fd26d59..3a72f8f890 100644 --- a/src/platform/workspace/components/toasts/InviteAcceptedToast.vue +++ b/src/platform/workspace/components/toasts/InviteAcceptedToast.vue @@ -33,10 +33,18 @@ import { useWorkspaceSwitch } from '@/platform/workspace/composables/useWorkspac const { t } = useI18n() const toast = useToast() -const { switchWithConfirmation } = useWorkspaceSwitch() +const { switchWorkspace } = useWorkspaceSwitch() -function viewWorkspace(workspaceId: string) { - void switchWithConfirmation(workspaceId) - toast.removeGroup('invite-accepted') +async function viewWorkspace(workspaceId: string) { + const success = await switchWorkspace(workspaceId) + if (success) { + toast.removeGroup('invite-accepted') + } else { + toast.add({ + severity: 'error', + summary: t('workspace.switchFailed'), + life: 5000 + }) + } } diff --git a/src/platform/workspace/composables/useWorkspaceSwitch.test.ts b/src/platform/workspace/composables/useWorkspaceSwitch.test.ts index b3a76bcafc..50c69bd1b8 100644 --- a/src/platform/workspace/composables/useWorkspaceSwitch.test.ts +++ b/src/platform/workspace/composables/useWorkspaceSwitch.test.ts @@ -20,32 +20,6 @@ vi.mock('pinia', () => ({ }) })) -const mockModifiedWorkflows = vi.hoisted( - () => [] as Array<{ isModified: boolean }> -) - -vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({ - useWorkflowStore: () => ({ - get modifiedWorkflows() { - return mockModifiedWorkflows - } - }) -})) - -const mockConfirm = vi.hoisted(() => vi.fn()) - -vi.mock('@/services/dialogService', () => ({ - useDialogService: () => ({ - confirm: mockConfirm - }) -})) - -vi.mock('vue-i18n', () => ({ - useI18n: () => ({ - t: (key: string) => key - }) -})) - describe('useWorkspaceSwitch', () => { beforeEach(() => { vi.clearAllMocks() @@ -57,103 +31,37 @@ describe('useWorkspaceSwitch', () => { created_at: '2026-01-01T00:00:00Z', joined_at: '2026-01-01T00:00:00Z' } - mockModifiedWorkflows.length = 0 }) afterEach(() => { vi.unstubAllGlobals() }) - describe('hasUnsavedChanges', () => { - it('returns true when there are modified workflows', () => { - mockModifiedWorkflows.push({ isModified: true }) - const { hasUnsavedChanges } = useWorkspaceSwitch() - - expect(hasUnsavedChanges()).toBe(true) - }) - - it('returns true when multiple workflows are modified', () => { - mockModifiedWorkflows.push({ isModified: true }, { isModified: true }) - const { hasUnsavedChanges } = useWorkspaceSwitch() - - expect(hasUnsavedChanges()).toBe(true) - }) - - it('returns false when no workflows are modified', () => { - mockModifiedWorkflows.length = 0 - const { hasUnsavedChanges } = useWorkspaceSwitch() - - expect(hasUnsavedChanges()).toBe(false) - }) - }) - - describe('switchWithConfirmation', () => { + describe('switchWorkspace', () => { it('returns true immediately if switching to the same workspace', async () => { - const { switchWithConfirmation } = useWorkspaceSwitch() + const { switchWorkspace } = useWorkspaceSwitch() - const result = await switchWithConfirmation('workspace-1') + const result = await switchWorkspace('workspace-1') expect(result).toBe(true) expect(mockSwitchWorkspace).not.toHaveBeenCalled() - expect(mockConfirm).not.toHaveBeenCalled() }) - it('switches directly without dialog when no unsaved changes', async () => { - mockModifiedWorkflows.length = 0 + it('switches directly to the new workspace', async () => { mockSwitchWorkspace.mockResolvedValue(undefined) - const { switchWithConfirmation } = useWorkspaceSwitch() + const { switchWorkspace } = useWorkspaceSwitch() - const result = await switchWithConfirmation('workspace-2') - - expect(result).toBe(true) - expect(mockConfirm).not.toHaveBeenCalled() - expect(mockSwitchWorkspace).toHaveBeenCalledWith('workspace-2') - }) - - it('shows confirmation dialog when there are unsaved changes', async () => { - mockModifiedWorkflows.push({ isModified: true }) - mockConfirm.mockResolvedValue(true) - mockSwitchWorkspace.mockResolvedValue(undefined) - const { switchWithConfirmation } = useWorkspaceSwitch() - - await switchWithConfirmation('workspace-2') - - expect(mockConfirm).toHaveBeenCalledWith({ - title: 'workspace.unsavedChanges.title', - message: 'workspace.unsavedChanges.message', - type: 'dirtyClose' - }) - }) - - it('returns false if user cancels the confirmation dialog', async () => { - mockModifiedWorkflows.push({ isModified: true }) - mockConfirm.mockResolvedValue(false) - const { switchWithConfirmation } = useWorkspaceSwitch() - - const result = await switchWithConfirmation('workspace-2') - - expect(result).toBe(false) - expect(mockSwitchWorkspace).not.toHaveBeenCalled() - }) - - it('calls switchWorkspace after user confirms', async () => { - mockModifiedWorkflows.push({ isModified: true }) - mockConfirm.mockResolvedValue(true) - mockSwitchWorkspace.mockResolvedValue(undefined) - const { switchWithConfirmation } = useWorkspaceSwitch() - - const result = await switchWithConfirmation('workspace-2') + const result = await switchWorkspace('workspace-2') expect(result).toBe(true) expect(mockSwitchWorkspace).toHaveBeenCalledWith('workspace-2') }) it('returns false if switchWorkspace throws an error', async () => { - mockModifiedWorkflows.length = 0 mockSwitchWorkspace.mockRejectedValue(new Error('Switch failed')) - const { switchWithConfirmation } = useWorkspaceSwitch() + const { switchWorkspace } = useWorkspaceSwitch() - const result = await switchWithConfirmation('workspace-2') + const result = await switchWorkspace('workspace-2') expect(result).toBe(false) }) diff --git a/src/platform/workspace/composables/useWorkspaceSwitch.ts b/src/platform/workspace/composables/useWorkspaceSwitch.ts index e8983ce41e..45f0e81aa0 100644 --- a/src/platform/workspace/composables/useWorkspaceSwitch.ts +++ b/src/platform/workspace/composables/useWorkspaceSwitch.ts @@ -1,41 +1,18 @@ import { storeToRefs } from 'pinia' -import { useI18n } from 'vue-i18n' -import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore' import { useTeamWorkspaceStore } from '@/platform/workspace/stores/teamWorkspaceStore' -import { useDialogService } from '@/services/dialogService' export function useWorkspaceSwitch() { - const { t } = useI18n() const workspaceStore = useTeamWorkspaceStore() const { activeWorkspace } = storeToRefs(workspaceStore) - const workflowStore = useWorkflowStore() - const dialogService = useDialogService() - function hasUnsavedChanges(): boolean { - return workflowStore.modifiedWorkflows.length > 0 - } - - async function switchWithConfirmation(workspaceId: string): Promise { + async function switchWorkspace(workspaceId: string): Promise { if (activeWorkspace.value?.id === workspaceId) { return true } - if (hasUnsavedChanges()) { - const confirmed = await dialogService.confirm({ - title: t('workspace.unsavedChanges.title'), - message: t('workspace.unsavedChanges.message'), - type: 'dirtyClose' - }) - - if (!confirmed) { - return false - } - } - try { await workspaceStore.switchWorkspace(workspaceId) - // Note: switchWorkspace triggers page reload internally return true } catch { return false @@ -43,7 +20,6 @@ export function useWorkspaceSwitch() { } return { - hasUnsavedChanges, - switchWithConfirmation + switchWorkspace } }