diff --git a/src/Page.tsx b/src/Page.tsx index 50982d1f..07799fb0 100644 --- a/src/Page.tsx +++ b/src/Page.tsx @@ -16,7 +16,7 @@ export default function Page() { } /> } /> } /> - } /> + } /> } /> } /> navigate("/workspaces"), + onError: (err) => { + toast.error(err.detail ? `${err.detail}` : "Failed to archive workspace"); + }, + }); +} diff --git a/src/features/workspace/components/__tests__/archive-workspace.test.tsx b/src/features/workspace/components/__tests__/archive-workspace.test.tsx new file mode 100644 index 00000000..2aa85525 --- /dev/null +++ b/src/features/workspace/components/__tests__/archive-workspace.test.tsx @@ -0,0 +1,35 @@ +import { render } from "@/lib/test-utils"; +import { ArchiveWorkspace } from "../archive-workspace"; +import userEvent from "@testing-library/user-event"; +import { screen, waitFor } from "@testing-library/react"; + +const mockNavigate = vi.fn(); +const mockToast = vi.fn(); +vi.mock("react-router-dom", async () => { + const original = + await vi.importActual( + "react-router-dom", + ); + return { + ...original, + useNavigate: () => mockNavigate, + }; +}); + +vi.mock("@stacklok/ui-kit", async () => { + const original = + await vi.importActual( + "@stacklok/ui-kit", + ); + return { + ...original, + toast: { error: () => mockToast }, + }; +}); + +test("archive workspace", async () => { + render(); + + await userEvent.click(screen.getByRole("button", { name: /archive/i })); + await waitFor(() => expect(mockNavigate).toBeCalled()); +}); diff --git a/src/features/workspace/components/archive-workspace.tsx b/src/features/workspace/components/archive-workspace.tsx new file mode 100644 index 00000000..5f8f1402 --- /dev/null +++ b/src/features/workspace/components/archive-workspace.tsx @@ -0,0 +1,35 @@ +import { Card, CardBody, Button, Text } from "@stacklok/ui-kit"; +import { twMerge } from "tailwind-merge"; +import { useArchiveWorkspace } from "../../workspace-system-prompt/hooks/use-archive-workspace"; + +export function ArchiveWorkspace({ + className, + workspaceName, +}: { + workspaceName: string; + className?: string; +}) { + const { mutate, isPending } = useArchiveWorkspace(); + + return ( + + + Archive Workspace +
+ + Archiving this workspace removes it from the main workspaces list, + though it can be restored if needed. + + +
+
+
+ ); +} diff --git a/src/features/workspace/components/workspace-name.tsx b/src/features/workspace/components/workspace-name.tsx index df3626f2..95220967 100644 --- a/src/features/workspace/components/workspace-name.tsx +++ b/src/features/workspace/components/workspace-name.tsx @@ -1,11 +1,17 @@ import { Card, CardBody, Input, Label, TextField } from "@stacklok/ui-kit"; import { twMerge } from "tailwind-merge"; -export function WorkspaceName({ className }: { className?: string }) { +export function WorkspaceName({ + className, + workspaceName, +}: { + workspaceName: string; + className?: string; +}) { return ( - + diff --git a/src/mocks/msw/handlers.ts b/src/mocks/msw/handlers.ts index c0c0f548..a8700bdb 100644 --- a/src/mocks/msw/handlers.ts +++ b/src/mocks/msw/handlers.ts @@ -36,4 +36,7 @@ export const handlers = [ http.post("*/api/v1/workspaces", () => { return HttpResponse.json(mockedWorkspaces); }), + http.delete("*/api/v1/workspaces/:workspace_name", () => + HttpResponse.json({ status: 204 }), + ), ]; diff --git a/src/routes/__tests__/route-workspace.test.tsx b/src/routes/__tests__/route-workspace.test.tsx index 30235726..97828fbc 100644 --- a/src/routes/__tests__/route-workspace.test.tsx +++ b/src/routes/__tests__/route-workspace.test.tsx @@ -2,7 +2,13 @@ import { render, within } from "@/lib/test-utils"; import { test, expect } from "vitest"; import { RouteWorkspace } from "../route-workspace"; -const renderComponent = () => render(); +const renderComponent = () => + render(, { + routeConfig: { + initialEntries: ["/workspace/foo"], + }, + pathConfig: "/workspace/:name", + }); vi.mock("@monaco-editor/react", () => { const FakeEditor = vi.fn((props) => { diff --git a/src/routes/route-workspace-creation.tsx b/src/routes/route-workspace-creation.tsx index 31ae5ef6..1229bcfc 100644 --- a/src/routes/route-workspace-creation.tsx +++ b/src/routes/route-workspace-creation.tsx @@ -8,6 +8,7 @@ export function RouteWorkspaceCreation() { <> + Manage Workspaces Create Workspace diff --git a/src/routes/route-workspace.tsx b/src/routes/route-workspace.tsx index c9f0c4a2..1a887ecf 100644 --- a/src/routes/route-workspace.tsx +++ b/src/routes/route-workspace.tsx @@ -1,10 +1,16 @@ import { BreadcrumbHome } from "@/components/BreadcrumbHome"; +import { ArchiveWorkspace } from "@/features/workspace/components/archive-workspace"; import { SystemPromptEditor } from "@/features/workspace-system-prompt/components/system-prompt-editor"; import { WorkspaceHeading } from "@/features/workspace/components/workspace-heading"; import { WorkspaceName } from "@/features/workspace/components/workspace-name"; import { Breadcrumb, Breadcrumbs } from "@stacklok/ui-kit"; +import { useParams } from "react-router-dom"; export function RouteWorkspace() { + const { name } = useParams(); + + if (!name) throw Error("Workspace name is required"); + return ( <> @@ -14,8 +20,9 @@ export function RouteWorkspace() { - + + ); }