From 4ee5c9c682e9e5074b4669809bc848ca4aea334a Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Sat, 16 May 2026 16:50:17 +0100 Subject: [PATCH 1/8] fix electric create sync txids --- .../DashboardSidebarWorkspaceItem.tsx | 130 ++++++------- ...shboardSidebarCollapsedWorkspaceButton.tsx | 3 - .../DashboardSidebarExpandedWorkspaceRow.tsx | 165 +++++++---------- .../DashboardSidebarWorkspaceIcon.tsx | 7 +- .../utils/getCreationStatusText.ts | 17 -- .../utils/index.ts | 1 - .../useDashboardSidebarData.ts | 117 +----------- .../useDashboardSidebarShortcuts.ts | 6 +- .../components/DashboardSidebar/types.ts | 1 - .../V2WorkspaceTitle/V2WorkspaceTitle.tsx | 16 +- .../_authenticated/_dashboard/layout.tsx | 2 - .../WorkspaceCreateErrorState.tsx | 79 -------- .../WorkspaceCreateErrorState/index.ts | 1 - .../WorkspaceCreatingState.css | 60 ------ .../WorkspaceCreatingState.tsx | 173 ----------------- .../WorkspaceCreatingState/index.ts | 1 - .../_dashboard/v2-workspace/layout.tsx | 33 +--- .../useBranchPickerController.ts | 5 +- .../useSubmitWorkspace/useSubmitWorkspace.ts | 10 +- .../CollectionsProvider/collections.ts | 105 ++++++++--- .../stores/workspace-creates/Manager.tsx | 30 --- .../stores/workspace-creates/index.ts | 7 +- .../stores/workspace-creates/store.ts | 69 ------- .../workspace-creates/useWorkspaceCreates.ts | 175 +++++++++--------- apps/electric-proxy/package.json | 1 + apps/electric-proxy/src/electric.ts | 19 +- bun.lock | 1 + .../shared/adopt-existing-worktree.ts | 2 +- .../src/trpc/router/workspaces/workspaces.ts | 2 +- packages/trpc/src/router/chat/chat.ts | 29 ++- .../src/router/v2-project/v2-project.test.ts | 30 ++- .../trpc/src/router/v2-project/v2-project.ts | 36 ++-- .../src/router/v2-workspace/v2-workspace.ts | 19 +- 33 files changed, 383 insertions(+), 969 deletions(-) delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/getCreationStatusText.ts delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/index.ts delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/WorkspaceCreateErrorState.tsx delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/index.ts delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.css delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.tsx delete mode 100644 apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/index.ts delete mode 100644 apps/desktop/src/renderer/stores/workspace-creates/Manager.tsx delete mode 100644 apps/desktop/src/renderer/stores/workspace-creates/store.ts diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx index 0f4a79be2bb..4ff91ddc5de 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx @@ -4,7 +4,6 @@ import { useOptimisticCollectionActions } from "renderer/routes/_authenticated/h import { useDeletingWorkspaces } from "renderer/routes/_authenticated/providers/DeletingWorkspacesProvider"; import { RenameBranchDialog } from "renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components"; import { useV2WorkspaceNotificationStatus } from "renderer/stores/v2-notifications"; -import { useWorkspaceCreatesStore } from "renderer/stores/workspace-creates"; import { useDashboardSidebarHover } from "../../providers/DashboardSidebarHoverProvider"; import type { DashboardSidebarWorkspace } from "../../types"; import { DashboardSidebarDeleteDialog } from "../DashboardSidebarDeleteDialog"; @@ -36,7 +35,6 @@ export function DashboardSidebarWorkspaceItem({ hostIsOnline, name, branch, - creationStatus, pullRequest, } = workspace; const isMainWorkspace = workspace.type === "main"; @@ -77,16 +75,10 @@ export function DashboardSidebarWorkspaceItem({ const handleAfterBranchRename = (newBranchName: string) => { v2WorkspaceActions.updateWorkspace(id, { branch: newBranchName }); }; - const isPending = !!creationStatus; - const isFailedInFlight = creationStatus === "failed"; // Keep the delete dialog outside the hidden wrapper below — the destroy // flow reopens it into an error pane on conflict/teardown-failed. const isDeleting = useDeletingWorkspaces().isDeleting(id); - const handleDismissInFlight = useCallback(() => { - useWorkspaceCreatesStore.getState().remove(id); - }, [id]); - const { hoveredId: hoverHoveredId, requestOpen: hoverRequestOpen, @@ -94,20 +86,18 @@ export function DashboardSidebarWorkspaceItem({ syncIfHovered: hoverSyncIfHovered, } = useDashboardSidebarHover(); const rowRef = useRef(null); - const hoverEligible = !isPending; const hoverPayload = useMemo( () => ({ workspace, onEditBranchClick: setRenameBranchTarget }), [workspace], ); const handleMouseEnter = useCallback(() => { - if (!hoverEligible || !rowRef.current) return; + if (!rowRef.current) return; hoverRequestOpen(id, rowRef.current, hoverPayload); - }, [hoverEligible, hoverRequestOpen, id, hoverPayload]); + }, [hoverRequestOpen, id, hoverPayload]); const handleMouseLeave = useCallback(() => { - if (!hoverEligible) return; hoverRequestClose(id); - }, [hoverEligible, hoverRequestClose, id]); + }, [hoverRequestClose, id]); const isHovered = hoverHoveredId === id; useEffect(() => { @@ -142,11 +132,7 @@ export function DashboardSidebarWorkspaceItem({ isActive={isActive} workspaceStatus={workspaceStatus} onClick={handleClick} - creationStatus={creationStatus} pullRequestState={pullRequest?.state ?? null} - aria-label={ - creationStatus ? `Creating workspace: ${name}` : undefined - } /> ); @@ -154,35 +140,31 @@ export function DashboardSidebarWorkspaceItem({ return ( <> - {!isPending && !isMainWorkspace && ( + {!isMainWorkspace && ( setIsDeleteDialogOpen(true) - } + onCloseWorkspaceClick={() => setIsDeleteDialogOpen(true)} onRenameValueChange={setRenameValue} onSubmitRename={submitRename} onCancelRename={cancelRename} @@ -240,35 +218,31 @@ export function DashboardSidebarWorkspaceItem({ return ( <> - {!isPending && !isMainWorkspace && ( + {!isMainWorkspace && ( diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx index 2eda5ee39c1..e9d11a0dcbe 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx @@ -4,7 +4,6 @@ import { type ComponentPropsWithoutRef, forwardRef, useEffect, - useMemo, useRef, } from "react"; import { HiMiniMinus, HiMiniXMark } from "react-icons/hi2"; @@ -17,7 +16,6 @@ import type { DashboardSidebarWorkspace, DashboardSidebarWorkspacePullRequest, } from "../../../../types"; -import { getCreationStatusText } from "../../utils/getCreationStatusText"; import { DashboardSidebarWorkspaceDiffStats } from "../DashboardSidebarWorkspaceDiffStats"; import { DashboardSidebarWorkspaceIcon } from "../DashboardSidebarWorkspaceIcon"; @@ -83,7 +81,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< name, branch, pullRequest, - creationStatus, } = workspace; const showsStandaloneActiveStripe = accentColor == null; const localRef = useRef(null); @@ -98,10 +95,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< } }, [isActive]); - const creationStatusText = useMemo( - () => getCreationStatusText(creationStatus), - [creationStatus], - ); const isMainWorkspace = workspace.type === "main"; const workspaceKindTitle = isMainWorkspace ? "Main workspace" @@ -115,7 +108,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef<
{ localRef.current = node; if (typeof ref === "function") ref(node); @@ -174,7 +166,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< isActive={isActive} variant="expanded" workspaceStatus={workspaceStatus} - creationStatus={creationStatus} pullRequestState={pullRequest.state} /> @@ -187,7 +178,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< isActive={isActive} variant="expanded" workspaceStatus={workspaceStatus} - creationStatus={creationStatus} pullRequestState={null} />
@@ -255,104 +245,81 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< )}
- {creationStatusText ? ( - - {creationStatusText} - - ) : ( - diffStats && + {diffStats && (diffStats.additions > 0 || diffStats.deletions > 0) && ( - ) - )} - {(!creationStatus || creationStatus === "failed") && ( -
- {shortcutLabel && !creationStatus && ( - - {shortcutLabel} - - )} - {isMainWorkspace ? ( - - - - - - - - - ) : ( - - - + + + + + + ) : ( + + + - - - {creationStatus === "failed" ? ( - "Dismiss" - ) : ( - - )} - - - )} -
- )} + }} + className="flex items-center justify-center text-muted-foreground hover:text-foreground" + aria-label="Close workspace" + > + + + + + + + + )} +
diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx index ed268448037..3f6d920e8d6 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx @@ -1,6 +1,5 @@ import { cn } from "@superset/ui/utils"; import { CgLaptop } from "react-icons/cg"; -import { HiExclamationTriangle } from "react-icons/hi2"; import { LuGitMerge, LuGitPullRequest, @@ -25,7 +24,6 @@ interface DashboardSidebarWorkspaceIconProps { isActive: boolean; variant: "collapsed" | "expanded"; workspaceStatus?: ActivePaneStatus | null; - creationStatus?: "preparing" | "generating-branch" | "creating" | "failed"; pullRequestState?: DashboardSidebarWorkspacePullRequest["state"] | null; } @@ -55,7 +53,6 @@ export function DashboardSidebarWorkspaceIcon({ isActive, variant, workspaceStatus = null, - creationStatus, pullRequestState = null, }: DashboardSidebarWorkspaceIconProps) { const overlayPosition = OVERLAY_POSITION[variant]; @@ -103,9 +100,7 @@ export function DashboardSidebarWorkspaceIcon({ return ( <> - {creationStatus === "failed" ? ( - - ) : creationStatus || workspaceStatus === "working" ? ( + {workspaceStatus === "working" ? ( ) : ( renderPrimaryIcon() diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/getCreationStatusText.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/getCreationStatusText.ts deleted file mode 100644 index d98c17efbf8..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/getCreationStatusText.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { DashboardSidebarWorkspace } from "../../../types"; - -const CREATION_STATUS_LABELS: Record< - NonNullable, - string -> = { - preparing: "Preparing...", - "generating-branch": "Generating...", - creating: "Creating...", - failed: "Failed", -} as const; - -export function getCreationStatusText( - status: DashboardSidebarWorkspace["creationStatus"], -): string | null { - return status ? CREATION_STATUS_LABELS[status] : null; -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/index.ts deleted file mode 100644 index 5298c6aa549..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { getCreationStatusText } from "./getCreationStatusText"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts index cfa7f03fbff..bb7e2e0632a 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/useDashboardSidebarData.ts @@ -8,7 +8,6 @@ import { useDashboardSidebarState } from "renderer/routes/_authenticated/hooks/u import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider"; import { getVisibleSidebarWorkspaces } from "renderer/routes/_authenticated/providers/CollectionsProvider/dashboardSidebarLocal"; import { useLocalHostService } from "renderer/routes/_authenticated/providers/LocalHostServiceProvider"; -import { useWorkspaceCreatesStore } from "renderer/stores/workspace-creates"; import type { DashboardSidebarProject, DashboardSidebarProjectChild, @@ -21,9 +20,6 @@ import { type PullRequestQueryTarget, } from "./derivePullRequestQueryTargets"; -// Sits above every real workspace so the pending row lines up with the real one, -// which is inserted via getPrependTabOrder. -const PENDING_WORKSPACE_TAB_ORDER = Number.MIN_SAFE_INTEGER; const MAIN_WORKSPACE_TAB_ORDER = Number.MIN_SAFE_INTEGER; type SidebarPullRequest = DashboardSidebarWorkspace["pullRequest"]; @@ -133,33 +129,6 @@ export function useDashboardSidebarData() { const { toggleProjectCollapsed } = useDashboardSidebarState(); const queryClient = useQueryClient(); - // In-flight workspace.create operations. These don't have a backing DB row - // — they're kept in renderer memory until the real v2Workspaces row arrives - // via Electric sync (or until error/dismiss). Entries that have already - // resolved on the host service carry `cloudRow`; those are surfaced as - // real synced rows below so the sidebar doesn't stick on "creating" when - // Electric is slow. - const inFlightEntries = useWorkspaceCreatesStore((store) => store.entries); - const inFlightSidebarRows = useMemo( - () => - inFlightEntries - .filter((entry) => entry.snapshot.id !== undefined) - // Entries with a cloudRow are rendered via the synced fallback below. - .filter((entry) => !(entry.state === "creating" && entry.cloudRow)) - .map((entry) => ({ - id: entry.snapshot.id as string, - projectId: entry.snapshot.projectId, - name: entry.snapshot.name ?? "New workspace", - branchName: - entry.snapshot.branch ?? entry.snapshot.name ?? "New workspace", - status: - entry.state === "creating" - ? ("creating" as const) - : ("failed" as const), - })), - [inFlightEntries], - ); - const { data: hosts = [] } = useLiveQuery( (q) => q.from({ hosts: collections.v2Hosts }).select(({ hosts }) => ({ @@ -307,42 +276,6 @@ export function useDashboardSidebarData() { [hostsByMachineId, rawLocalMainWorkspaces], ); - // Cloud-row fallback: when workspaces.create has resolved on the host - // service but Electric hasn't yet delivered the v2Workspaces row, surface - // the cloud row cached on the in-flight entry so the sidebar renders the - // workspace as fully synced. Manager.tsx removes the entry once Electric - // catches up, at which point the live query takes over seamlessly. - const cloudRowFallbackWorkspaces = useMemo(() => { - if (inFlightEntries.length === 0) return []; - const rows = inFlightEntries.flatMap((entry) => { - const cloudRow = entry.cloudRow; - if (!cloudRow) return []; - // Electric already delivered; let the live query own this row. - if (localStateWorkspaceIds.has(cloudRow.id)) return []; - const localState = collections.v2WorkspaceLocalState.get(cloudRow.id); - const host = hostsByMachineId.get(cloudRow.hostId); - return [ - { - id: cloudRow.id, - projectId: localState?.sidebarState.projectId ?? cloudRow.projectId, - hostId: cloudRow.hostId, - type: cloudRow.type, - hostIsOnline: host?.isOnline ?? false, - name: cloudRow.name, - branch: cloudRow.branch, - taskId: cloudRow.taskId, - createdAt: cloudRow.createdAt, - updatedAt: cloudRow.updatedAt, - tabOrder: - localState?.sidebarState.tabOrder ?? PENDING_WORKSPACE_TAB_ORDER, - sectionId: localState?.sidebarState.sectionId ?? null, - isHidden: localState?.sidebarState.isHidden ?? false, - }, - ]; - }); - return getVisibleSidebarWorkspaces(rows); - }, [collections, hostsByMachineId, inFlightEntries, localStateWorkspaceIds]); - const visibleSidebarWorkspaces = useMemo(() => { const sidebarProjectIds = new Set( sidebarProjects.map((project) => project.id), @@ -354,13 +287,8 @@ export function useDashboardSidebarData() { sidebarProjectIds.has(workspace.projectId), ); - return [ - ...autoLocalMainWorkspaces, - ...sidebarWorkspaces, - ...cloudRowFallbackWorkspaces, - ]; + return [...autoLocalMainWorkspaces, ...sidebarWorkspaces]; }, [ - cloudRowFallbackWorkspaces, localMainWorkspaces, localStateWorkspaceIds, machineId, @@ -526,47 +454,6 @@ export function useDashboardSidebarData() { }); } - // Inject in-flight workspaces (creating / failed) from the renderer-side - // in-flight store. - for (const pw of inFlightSidebarRows) { - if (localStateWorkspaceIds.has(pw.id)) continue; - const project = projectsById.get(pw.projectId); - if (!project) continue; - - const pendingItem: DashboardSidebarWorkspace = { - id: pw.id, - projectId: pw.projectId, - hostId: "", - hostType: "local-device", - type: "worktree", - hostIsOnline: null, - accentColor: null, - name: pw.name, - branch: pw.branchName, - pullRequest: null, - repoUrl: - project.githubOwner && project.githubRepoName - ? `https://github.com/${project.githubOwner}/${project.githubRepoName}` - : null, - branchExistsOnRemote: false, - previewUrl: null, - needsRebase: null, - behindCount: null, - createdAt: new Date(), - updatedAt: new Date(), - taskId: null, - creationStatus: pw.status, - }; - - project.childEntries.push({ - tabOrder: PENDING_WORKSPACE_TAB_ORDER, - child: { - type: "workspace", - workspace: pendingItem, - }, - }); - } - return sidebarProjects.flatMap((project) => { const resolvedProject = projectsById.get(project.id); if (!resolvedProject) return []; @@ -617,8 +504,6 @@ export function useDashboardSidebarData() { }, [ machineId, pullRequestsByWorkspaceId, - inFlightSidebarRows, - localStateWorkspaceIds, sidebarProjects, sidebarSections, visibleSidebarWorkspaces, diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts index 82413df4232..e08c4132a6e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarShortcuts/useDashboardSidebarShortcuts.ts @@ -55,9 +55,9 @@ export function useDashboardSidebarShortcuts( useDashboardSidebarState(); const flattenedWorkspaces = useMemo( () => - groups - .flatMap((project) => getProjectChildrenWorkspaces(project.children)) - .filter((workspace) => !workspace.creationStatus), + groups.flatMap((project) => + getProjectChildrenWorkspaces(project.children), + ), [groups], ); const workspaceShortcutLabels = diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts index c9be0b9edd1..e7e31b58be5 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/types.ts @@ -41,7 +41,6 @@ export interface DashboardSidebarWorkspace { createdAt: Date; updatedAt: Date; taskId: string | null; - creationStatus?: "preparing" | "generating-branch" | "creating" | "failed"; } export interface DashboardSidebarSection { diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/V2WorkspaceTitle/V2WorkspaceTitle.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/V2WorkspaceTitle/V2WorkspaceTitle.tsx index e2552fddd92..25b023e7ee0 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/V2WorkspaceTitle/V2WorkspaceTitle.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/TopBar/components/V2WorkspaceTitle/V2WorkspaceTitle.tsx @@ -3,7 +3,6 @@ import { eq } from "@tanstack/db"; import { useLiveQuery } from "@tanstack/react-db"; import { ChevronRight, GitBranch } from "lucide-react"; import { useCollections } from "renderer/routes/_authenticated/providers/CollectionsProvider"; -import { useWorkspaceCreatesStore } from "renderer/stores/workspace-creates"; interface V2WorkspaceTitleProps { workspaceId: string; @@ -23,19 +22,8 @@ export function V2WorkspaceTitle({ workspaceId }: V2WorkspaceTitleProps) { [collections, workspaceId], ); const syncedWorkspace = workspaces[0] ?? null; - const inFlight = useWorkspaceCreatesStore((store) => - store.entries.find((entry) => entry.snapshot.id === workspaceId), - ); - const name = - syncedWorkspace?.name ?? - inFlight?.cloudRow?.name ?? - inFlight?.snapshot.name ?? - null; - const branch = - syncedWorkspace?.branch ?? - inFlight?.cloudRow?.branch ?? - inFlight?.snapshot.branch ?? - null; + const name = syncedWorkspace?.name ?? null; + const branch = syncedWorkspace?.branch ?? null; if (!name && !branch) { return null; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx index 07dd12a22c1..1c74364a7ae 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx @@ -15,7 +15,6 @@ import { ResizablePanel } from "renderer/screens/main/components/ResizablePanel" import { WorkspaceSidebar } from "renderer/screens/main/components/WorkspaceSidebar"; import { DeleteWorkspaceDialog } from "renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/components"; import { useOpenNewWorkspaceModal } from "renderer/stores/new-workspace-modal"; -import { WorkspaceCreatesManager } from "renderer/stores/workspace-creates"; import { COLLAPSED_WORKSPACE_SIDEBAR_WIDTH, DEFAULT_WORKSPACE_SIDEBAR_WIDTH, @@ -139,7 +138,6 @@ function DashboardLayout() { return (
- {sidebarOutsideColumn && sidebarPanel}
diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/WorkspaceCreateErrorState.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/WorkspaceCreateErrorState.tsx deleted file mode 100644 index 282c9f5c5c9..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/WorkspaceCreateErrorState.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { Button } from "@superset/ui/button"; -import { useNavigate } from "@tanstack/react-router"; -import { AlertCircle, GitBranch } from "lucide-react"; -import { useWorkspaceCreates } from "renderer/stores/workspace-creates"; - -interface WorkspaceCreateErrorStateProps { - workspaceId: string; - name?: string; - branch?: string; - error: string; -} - -export function WorkspaceCreateErrorState({ - workspaceId, - name, - branch, - error, -}: WorkspaceCreateErrorStateProps) { - const navigate = useNavigate(); - const { retry, dismiss } = useWorkspaceCreates(); - - const handleDismiss = () => { - dismiss(workspaceId); - void navigate({ to: "/v2-workspaces" }); - }; - - return ( -
-
-
-
- ); -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/index.ts b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/index.ts deleted file mode 100644 index 39b3ccfa90c..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreateErrorState/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { WorkspaceCreateErrorState } from "./WorkspaceCreateErrorState"; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.css b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.css deleted file mode 100644 index a3ebf3d4fda..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.css +++ /dev/null @@ -1,60 +0,0 @@ -.wcs-bar-track { - position: relative; - height: 1px; - width: 100%; - overflow: hidden; - background: hsl(var(--border) / 0.6); -} - -.wcs-bar-fill { - position: absolute; - inset-block: 0; - left: 0; - background: hsl(var(--foreground) / 0.75); - transition: width 0.7s cubic-bezier(0.22, 1, 0.36, 1); -} - -.wcs-bar-sweep { - position: absolute; - inset: 0; - background: linear-gradient( - 90deg, - transparent, - hsl(var(--foreground) / 0.25) 50%, - transparent - ); - transform: translateX(-100%); - animation: wcs-sweep 2.4s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -@keyframes wcs-sweep { - 0% { - transform: translateX(-100%); - } - 100% { - transform: translateX(100%); - } -} - -.wcs-active-ring { - animation: wcs-pulse 1.6s cubic-bezier(0.4, 0, 0.2, 1) infinite; -} - -@keyframes wcs-pulse { - 0%, - 100% { - opacity: 0.35; - transform: scale(1); - } - 50% { - opacity: 0.85; - transform: scale(1.4); - } -} - -@media (prefers-reduced-motion: reduce) { - .wcs-bar-sweep, - .wcs-active-ring { - animation: none; - } -} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.tsx deleted file mode 100644 index e74404b030d..00000000000 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/components/WorkspaceCreatingState/WorkspaceCreatingState.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { cn } from "@superset/ui/utils"; -import { Check, GitBranch, Loader2 } from "lucide-react"; -import { useEffect, useState } from "react"; -import "./WorkspaceCreatingState.css"; - -interface Step { - id: string; - label: string; - /** Cumulative seconds at which this step is considered complete. */ - doneAt: number; -} - -// Mirrors the v1 init step order in shared/types/workspace-init.ts so the -// labels feel real — v2 workspaces.create runs the same git work server-side -// without streaming progress events, so timings here are estimates. -const STEPS: readonly Step[] = [ - { id: "preparing", label: "Preparing", doneAt: 1 }, - { id: "syncing", label: "Syncing with remote", doneAt: 4 }, - { id: "verifying", label: "Verifying base branch", doneAt: 5 }, - { id: "fetching", label: "Fetching latest changes", doneAt: 15 }, - { id: "creating_worktree", label: "Creating git worktree", doneAt: 18 }, - { id: "copying_config", label: "Copying configuration", doneAt: 20 }, - { id: "finalizing", label: "Finalizing setup", doneAt: 23 }, -] as const; - -const TOTAL_SECONDS = STEPS[STEPS.length - 1].doneAt; -// Cap synthetic progress so the bar never claims completion before the real -// workspaces.create mutation resolves. -const PROGRESS_CAP = 0.94; - -interface WorkspaceCreatingStateProps { - name?: string; - branch?: string; - startedAt?: number; -} - -export function WorkspaceCreatingState({ - name, - branch, - startedAt, -}: WorkspaceCreatingStateProps) { - const elapsed = useElapsedSeconds(startedAt); - const activeIndex = getActiveIndex(elapsed); - const progress = Math.min(elapsed / TOTAL_SECONDS, PROGRESS_CAP); - - return ( -
-
-