From c02273315c8971d1f6e7917718564126b71d4d80 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 15:08:32 +0000 Subject: [PATCH 01/13] chore: remove bottom padding --- site/src/modules/dashboard/DashboardLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/modules/dashboard/DashboardLayout.tsx b/site/src/modules/dashboard/DashboardLayout.tsx index 140d8602b2b32..5b96f84f8806d 100644 --- a/site/src/modules/dashboard/DashboardLayout.tsx +++ b/site/src/modules/dashboard/DashboardLayout.tsx @@ -26,7 +26,7 @@ export const DashboardLayout: FC = () => {
-
+
}> From b1952f9b06870c1a0394e8ff001609891cb23407 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 16:53:35 +0000 Subject: [PATCH 02/13] chore: convert to tailwind --- site/src/pages/WorkspacePage/Workspace.tsx | 289 ++++++++------------- 1 file changed, 114 insertions(+), 175 deletions(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 07c5ec26d0766..4cbf7728d5e91 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -16,6 +16,7 @@ import type { WorkspacePermissions } from "../../modules/workspaces/permissions" import { HistorySidebar } from "./HistorySidebar"; import { ResourceMetadata } from "./ResourceMetadata"; import { ResourcesSidebar } from "./ResourcesSidebar"; +import { resourceOptionValue, useResourcesNav } from "./useResourcesNav"; import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection"; import { ActiveTransition, @@ -23,7 +24,6 @@ import { } from "./WorkspaceBuildProgress"; import { WorkspaceDeletedBanner } from "./WorkspaceDeletedBanner"; import { WorkspaceTopbar } from "./WorkspaceTopbar"; -import { resourceOptionValue, useResourcesNav } from "./useResourcesNav"; interface WorkspaceProps { workspace: TypesGen.Workspace; @@ -100,18 +100,7 @@ export const Workspace: FC = ({ workspacePending && !haveBuildLogs && !provisionersHealthy && !isRestarting; return ( -
+
= ({ handleToggleFavorite={handleToggleFavorite} /> -
- { - setSidebarOption("resources"); - }} - > - - - { - setSidebarOption("history"); - }} - > - - -
+
+
+
+ { + setSidebarOption("resources"); + }} + > + + + { + setSidebarOption("history"); + }} + > + + +
- {sidebarOption.value === "resources" && ( - - )} - {sidebarOption.value === "history" && ( - - )} + {sidebarOption.value === "resources" && ( + + )} + {sidebarOption.value === "history" && ( + + )} +
-
- {selectedResource && ( - - )}
- {workspace.latest_build.status === "deleted" && ( - navigate("/templates")} + {selectedResource && ( + )} +
+ {workspace.latest_build.status === "deleted" && ( + navigate("/templates")} + /> + )} - {shouldShowProvisionerAlert && ( - - )} + {shouldShowProvisionerAlert && ( + + )} - {workspace.latest_build.job.error && ( - - Workspace build failed - {workspace.latest_build.job.error} - - )} + {workspace.latest_build.job.error && ( + + Workspace build failed + {workspace.latest_build.job.error} + + )} - {transitionStats !== undefined && ( - - )} + {transitionStats !== undefined && ( + + )} - {shouldShowBuildLogs && ( - - )} + {shouldShowBuildLogs && ( + + )} - {selectedResource && ( -
- {selectedResource.agents - // If an agent has a `parent_id`, that means it is - // child of another agent. We do not want these agents - // to be displayed at the top-level on this page. We - // want them to display _as children_ of their parents. - ?.filter((agent) => agent.parent_id === null) - .map((agent) => ( - a.parent_id === agent.id, - )} - workspace={workspace} - template={template} - onUpdateAgent={handleUpdate} // On updating the workspace the agent version is also updated - /> - ))} + {selectedResource && ( +
+ {selectedResource.agents + // If an agent has a `parent_id`, that means it is + // child of another agent. We do not want these agents + // to be displayed at the top-level on this page. We + // want them to display _as children_ of their parents. + ?.filter((agent) => agent.parent_id === null) + .map((agent) => ( + a.parent_id === agent.id, + )} + workspace={workspace} + template={template} + onUpdateAgent={handleUpdate} // On updating the workspace the agent version is also updated + /> + ))} - {(!selectedResource.agents || - selectedResource.agents?.length === 0) && ( -
-
-

- No agents are currently assigned to this resource. -

+ {(!selectedResource.agents || + selectedResource.agents?.length === 0) && ( +
+
+

+ No agents are currently assigned to this resource. +

+
-
- )} -
- )} + )} +
+ )} - + +
@@ -286,33 +255,3 @@ export const Workspace: FC = ({ const countAgents = (resource: TypesGen.WorkspaceResource) => { return resource.agents ? resource.agents.length : 0; }; - -const styles = { - content: { - padding: 32, - gridArea: "content", - overflowY: "auto", - position: "relative", - }, - - dotsBackground: (theme) => ({ - "--d": "1px", - background: ` - radial-gradient( - circle at - var(--d) - var(--d), - - ${theme.palette.dots} calc(var(--d) - 1px), - ${theme.palette.background.default} var(--d) - ) - -2px -2px / 16px 16px - `, - }), - - actions: (theme) => ({ - [theme.breakpoints.down("md")]: { - flexDirection: "column", - }, - }), -} satisfies Record>; From 699700f5871e2c8e69211a47f7d1a0ef8939f3f6 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 16:55:47 +0000 Subject: [PATCH 03/13] fix: workspace width --- site/src/pages/WorkspacePage/Workspace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 4cbf7728d5e91..a475c884333f8 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -161,7 +161,7 @@ export const Workspace: FC = ({ transparent 1px ) -2px -2px / 16px 16px;`, }} - className="p-8 overflow-y-auto relative" + className="p-8 overflow-y-auto relative w-full" > {selectedResource && ( Date: Wed, 13 Aug 2025 17:01:42 +0000 Subject: [PATCH 04/13] chore: use consistent whitespace --- site/src/pages/WorkspacePage/Workspace.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index a475c884333f8..ce65fea6efdc1 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -156,10 +156,10 @@ export const Workspace: FC = ({
From 39e4321476df1cb1e04a3a86347cccac83797711 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 17:02:06 +0000 Subject: [PATCH 05/13] chore: remove unused import --- .../src/components/FullPageLayout/Sidebar.tsx | 14 +- .../pages/WorkspacePage/HistorySidebar.tsx | 904 +++++++++++++++++- site/src/pages/WorkspacePage/Workspace.tsx | 1 - 3 files changed, 904 insertions(+), 15 deletions(-) diff --git a/site/src/components/FullPageLayout/Sidebar.tsx b/site/src/components/FullPageLayout/Sidebar.tsx index 8a5eaf9b4f6be..a25ebe04c70d2 100644 --- a/site/src/components/FullPageLayout/Sidebar.tsx +++ b/site/src/components/FullPageLayout/Sidebar.tsx @@ -4,20 +4,10 @@ import { Link, type LinkProps } from "react-router"; import { TopbarIconButton } from "./Topbar"; export const Sidebar: FC> = (props) => { - const theme = useTheme(); return (
); diff --git a/site/src/pages/WorkspacePage/HistorySidebar.tsx b/site/src/pages/WorkspacePage/HistorySidebar.tsx index 2d978fb2a7d83..e2ab4044088a3 100644 --- a/site/src/pages/WorkspacePage/HistorySidebar.tsx +++ b/site/src/pages/WorkspacePage/HistorySidebar.tsx @@ -1,6 +1,6 @@ import ArrowDownwardOutlined from "@mui/icons-material/ArrowDownwardOutlined"; import { infiniteWorkspaceBuilds } from "api/queries/workspaceBuilds"; -import type { Workspace } from "api/typesGenerated"; +import type { Workspace, WorkspaceBuild } from "api/typesGenerated"; import { Button } from "components/Button/Button"; import { Sidebar, @@ -25,7 +25,7 @@ export const HistorySidebar: FC = ({ workspace }) => { ...infiniteWorkspaceBuilds(workspace?.id ?? ""), enabled: workspace !== undefined, }); - const builds = buildsQuery.data?.pages.flat(); + // const builds = buildsQuery.data?.pages.flat(); return ( @@ -63,3 +63,903 @@ export const HistorySidebar: FC = ({ workspace }) => { ); }; + +const builds: WorkspaceBuild[] = [ + { + id: "01234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T10:30:00Z", + updated_at: "2024-01-15T10:45:00Z", + workspace_id: "workspace-001", + workspace_name: "dev-environment", + workspace_owner_id: "user-001", + workspace_owner_name: "alice.smith", + workspace_owner_avatar_url: "https://example.com/avatars/alice.jpg", + template_version_id: "template-v1", + template_version_name: "Ubuntu 22.04 Dev", + build_number: 1, + transition: "start", + initiator_id: "user-001", + initiator_name: "alice.smith", + job: { + id: "job-001", + created_at: "2024-01-15T10:30:00Z", + status: "succeeded", + file_id: "file-001", + tags: { env: "dev" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "01234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Ubuntu 22.04 Dev", + template_id: "template-001", + template_name: "dev-template", + template_display_name: "Development Template", + template_icon: "๐Ÿ–ฅ๏ธ", + workspace_id: "workspace-001", + workspace_name: "dev-environment", + }, + logs_overflowed: false, + }, + reason: "dashboard", + resources: [], + deadline: "2024-01-15T18:30:00Z", + max_deadline: "2024-01-16T10:30:00Z", + status: "running", + daily_cost: 50, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "11234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T11:00:00Z", + updated_at: "2024-01-15T11:15:00Z", + workspace_id: "workspace-002", + workspace_name: "staging-env", + workspace_owner_id: "user-002", + workspace_owner_name: "bob.jones", + workspace_owner_avatar_url: "https://example.com/avatars/bob.jpg", + template_version_id: "template-v2", + template_version_name: "Node.js Production", + build_number: 3, + transition: "stop", + initiator_id: "user-002", + initiator_name: "bob.jones", + job: { + id: "job-002", + created_at: "2024-01-15T11:00:00Z", + status: "running", + file_id: "file-002", + tags: { env: "staging" }, + queue_position: 1, + queue_size: 2, + organization_id: "org-001", + input: { workspace_build_id: "11234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Node.js Production", + template_id: "template-002", + template_name: "nodejs-template", + template_display_name: "Node.js Template", + template_icon: "โšก", + workspace_id: "workspace-002", + workspace_name: "staging-env", + }, + logs_overflowed: false, + }, + reason: "autostop", + resources: [], + status: "stopping", + daily_cost: 75, + template_version_preset_id: "preset-001", + has_ai_task: true, + ai_task_sidebar_app_id: "ai-app-001", + }, + { + id: "21234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T12:00:00Z", + updated_at: "2024-01-15T12:20:00Z", + workspace_id: "workspace-003", + workspace_name: "ml-research", + workspace_owner_id: "user-003", + workspace_owner_name: "carol.white", + template_version_id: "template-v3", + template_version_name: "Python ML Stack", + build_number: 7, + transition: "start", + initiator_id: "user-003", + initiator_name: "carol.white", + job: { + id: "job-003", + created_at: "2024-01-15T12:00:00Z", + status: "succeeded", + file_id: "file-003", + tags: { env: "research", gpu: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-002", + input: { workspace_build_id: "21234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Python ML Stack", + template_id: "template-003", + template_name: "ml-template", + template_display_name: "Machine Learning Template", + template_icon: "๐Ÿค–", + workspace_id: "workspace-003", + workspace_name: "ml-research", + }, + logs_overflowed: false, + }, + reason: "cli", + resources: [], + deadline: "2024-01-15T20:00:00Z", + status: "running", + daily_cost: 120, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "31234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T13:30:00Z", + updated_at: "2024-01-15T13:35:00Z", + workspace_id: "workspace-004", + workspace_name: "frontend-dev", + workspace_owner_id: "user-004", + workspace_owner_name: "david.brown", + workspace_owner_avatar_url: "https://example.com/avatars/david.jpg", + template_version_id: "template-v4", + template_version_name: "React Development", + build_number: 2, + transition: "delete", + initiator_id: "user-004", + initiator_name: "david.brown", + job: { + id: "job-004", + created_at: "2024-01-15T13:30:00Z", + status: "failed", + error: "Resource allocation failed", + file_id: "file-004", + tags: { env: "dev", framework: "react" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "31234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "React Development", + template_id: "template-004", + template_name: "react-template", + template_display_name: "React Template", + template_icon: "โš›๏ธ", + workspace_id: "workspace-004", + workspace_name: "frontend-dev", + }, + logs_overflowed: false, + }, + reason: "dashboard", + resources: [], + status: "failed", + daily_cost: 40, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "41234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T14:00:00Z", + updated_at: "2024-01-15T14:10:00Z", + workspace_id: "workspace-005", + workspace_name: "backend-api", + workspace_owner_id: "user-005", + workspace_owner_name: "eve.davis", + template_version_id: "template-v5", + template_version_name: "Go Microservices", + build_number: 5, + transition: "start", + initiator_id: "user-005", + initiator_name: "eve.davis", + job: { + id: "job-005", + created_at: "2024-01-15T14:00:00Z", + status: "pending", + file_id: "file-005", + tags: { env: "dev", language: "go" }, + queue_position: 2, + queue_size: 3, + organization_id: "org-001", + input: { workspace_build_id: "41234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Go Microservices", + template_id: "template-005", + template_name: "go-template", + template_display_name: "Go Template", + template_icon: "๐Ÿน", + workspace_id: "workspace-005", + workspace_name: "backend-api", + }, + logs_overflowed: false, + }, + reason: "vscode_connection", + resources: [], + status: "pending", + daily_cost: 60, + template_version_preset_id: "preset-002", + has_ai_task: true, + }, + { + id: "51234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T15:15:00Z", + updated_at: "2024-01-15T15:25:00Z", + workspace_id: "workspace-006", + workspace_name: "database-admin", + workspace_owner_id: "user-006", + workspace_owner_name: "frank.miller", + workspace_owner_avatar_url: "https://example.com/avatars/frank.jpg", + template_version_id: "template-v6", + template_version_name: "PostgreSQL Admin", + build_number: 1, + transition: "start", + initiator_id: "user-006", + initiator_name: "frank.miller", + job: { + id: "job-006", + created_at: "2024-01-15T15:15:00Z", + status: "running", + file_id: "file-006", + tags: { env: "prod", database: "postgresql" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-003", + input: { workspace_build_id: "51234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "PostgreSQL Admin", + template_id: "template-006", + template_name: "postgres-template", + template_display_name: "PostgreSQL Template", + template_icon: "๐Ÿ˜", + workspace_id: "workspace-006", + workspace_name: "database-admin", + }, + logs_overflowed: false, + }, + reason: "ssh_connection", + resources: [], + deadline: "2024-01-15T23:15:00Z", + status: "starting", + daily_cost: 80, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "61234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T16:00:00Z", + updated_at: "2024-01-15T16:05:00Z", + workspace_id: "workspace-007", + workspace_name: "mobile-dev", + workspace_owner_id: "user-007", + workspace_owner_name: "grace.wilson", + template_version_id: "template-v7", + template_version_name: "Flutter Development", + build_number: 4, + transition: "stop", + initiator_id: "user-007", + initiator_name: "grace.wilson", + job: { + id: "job-007", + created_at: "2024-01-15T16:00:00Z", + status: "canceled", + canceled_at: "2024-01-15T16:05:00Z", + file_id: "file-007", + tags: { env: "dev", platform: "mobile" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "61234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Flutter Development", + template_id: "template-007", + template_name: "flutter-template", + template_display_name: "Flutter Template", + template_icon: "๐Ÿ“ฑ", + workspace_id: "workspace-007", + workspace_name: "mobile-dev", + }, + logs_overflowed: false, + }, + reason: "jetbrains_connection", + resources: [], + status: "canceled", + daily_cost: 45, + template_version_preset_id: "preset-003", + has_ai_task: false, + }, + { + id: "71234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T17:30:00Z", + updated_at: "2024-01-15T17:45:00Z", + workspace_id: "workspace-008", + workspace_name: "devops-tools", + workspace_owner_id: "user-008", + workspace_owner_name: "henry.taylor", + workspace_owner_avatar_url: "https://example.com/avatars/henry.jpg", + template_version_id: "template-v8", + template_version_name: "Kubernetes Admin", + build_number: 6, + transition: "start", + initiator_id: "user-008", + initiator_name: "henry.taylor", + job: { + id: "job-008", + created_at: "2024-01-15T17:30:00Z", + status: "succeeded", + completed_at: "2024-01-15T17:45:00Z", + file_id: "file-008", + tags: { env: "ops", orchestration: "k8s" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-002", + input: { workspace_build_id: "71234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Kubernetes Admin", + template_id: "template-008", + template_name: "k8s-template", + template_display_name: "Kubernetes Template", + template_icon: "โ˜ธ๏ธ", + workspace_id: "workspace-008", + workspace_name: "devops-tools", + }, + logs_overflowed: false, + }, + reason: "autostart", + resources: [], + deadline: "2024-01-16T01:30:00Z", + status: "running", + daily_cost: 95, + template_version_preset_id: null, + has_ai_task: true, + ai_task_sidebar_app_id: "ai-app-002", + }, + { + id: "81234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T18:00:00Z", + updated_at: "2024-01-15T18:02:00Z", + workspace_id: "workspace-009", + workspace_name: "data-science", + workspace_owner_id: "user-009", + workspace_owner_name: "iris.anderson", + template_version_id: "template-v9", + template_version_name: "Jupyter Notebook", + build_number: 8, + transition: "delete", + initiator_id: "user-009", + initiator_name: "iris.anderson", + job: { + id: "job-009", + created_at: "2024-01-15T18:00:00Z", + status: "running", + file_id: "file-009", + tags: { env: "research", notebook: "jupyter" }, + queue_position: 1, + queue_size: 2, + organization_id: "org-002", + input: { workspace_build_id: "81234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Jupyter Notebook", + template_id: "template-009", + template_name: "jupyter-template", + template_display_name: "Jupyter Template", + template_icon: "๐Ÿ“Š", + workspace_id: "workspace-009", + workspace_name: "data-science", + }, + logs_overflowed: false, + }, + reason: "dormancy", + resources: [], + status: "deleting", + daily_cost: 110, + template_version_preset_id: "preset-004", + has_ai_task: false, + }, + { + id: "91234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T19:15:00Z", + updated_at: "2024-01-15T19:20:00Z", + workspace_id: "workspace-010", + workspace_name: "security-audit", + workspace_owner_id: "user-010", + workspace_owner_name: "jack.thomas", + workspace_owner_avatar_url: "https://example.com/avatars/jack.jpg", + template_version_id: "template-v10", + template_version_name: "Security Tools", + build_number: 2, + transition: "start", + initiator_id: "user-010", + initiator_name: "jack.thomas", + job: { + id: "job-010", + created_at: "2024-01-15T19:15:00Z", + status: "pending", + file_id: "file-010", + tags: { env: "security", audit: "true" }, + queue_position: 3, + queue_size: 4, + organization_id: "org-003", + input: { workspace_build_id: "91234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Security Tools", + template_id: "template-010", + template_name: "security-template", + template_display_name: "Security Template", + template_icon: "๐Ÿ”’", + workspace_id: "workspace-010", + workspace_name: "security-audit", + }, + logs_overflowed: false, + }, + reason: "initiator", + resources: [], + status: "pending", + daily_cost: 70, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "a1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T20:00:00Z", + updated_at: "2024-01-15T20:15:00Z", + workspace_id: "workspace-011", + workspace_name: "testing-env", + workspace_owner_id: "user-011", + workspace_owner_name: "kate.jackson", + template_version_id: "template-v11", + template_version_name: "Test Automation", + build_number: 3, + transition: "stop", + initiator_id: "user-011", + initiator_name: "kate.jackson", + job: { + id: "job-011", + created_at: "2024-01-15T20:00:00Z", + status: "succeeded", + completed_at: "2024-01-15T20:15:00Z", + file_id: "file-011", + tags: { env: "test", automation: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "a1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Test Automation", + template_id: "template-011", + template_name: "test-template", + template_display_name: "Test Template", + template_icon: "๐Ÿงช", + workspace_id: "workspace-011", + workspace_name: "testing-env", + }, + logs_overflowed: false, + }, + reason: "dashboard", + resources: [], + status: "stopped", + daily_cost: 35, + template_version_preset_id: "preset-005", + has_ai_task: true, + }, + { + id: "b1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T21:30:00Z", + updated_at: "2024-01-15T21:35:00Z", + workspace_id: "workspace-012", + workspace_name: "docs-site", + workspace_owner_id: "user-012", + workspace_owner_name: "liam.white", + workspace_owner_avatar_url: "https://example.com/avatars/liam.jpg", + template_version_id: "template-v12", + template_version_name: "Documentation Site", + build_number: 1, + transition: "start", + initiator_id: "user-012", + initiator_name: "liam.white", + job: { + id: "job-012", + created_at: "2024-01-15T21:30:00Z", + status: "failed", + error: "Template validation failed", + error_code: "REQUIRED_TEMPLATE_VARIABLES", + file_id: "file-012", + tags: { env: "docs", static: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "b1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Documentation Site", + template_id: "template-012", + template_name: "docs-template", + template_display_name: "Documentation Template", + template_icon: "๐Ÿ“š", + workspace_id: "workspace-012", + workspace_name: "docs-site", + }, + logs_overflowed: false, + }, + reason: "cli", + resources: [], + status: "failed", + daily_cost: 25, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "c1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T22:00:00Z", + updated_at: "2024-01-15T22:10:00Z", + workspace_id: "workspace-013", + workspace_name: "ai-playground", + workspace_owner_id: "user-013", + workspace_owner_name: "mia.harris", + template_version_id: "template-v13", + template_version_name: "AI Development", + build_number: 5, + transition: "start", + initiator_id: "user-013", + initiator_name: "mia.harris", + job: { + id: "job-013", + created_at: "2024-01-15T22:00:00Z", + status: "running", + started_at: "2024-01-15T22:05:00Z", + file_id: "file-013", + tags: { env: "ai", gpu: "true", memory: "high" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-002", + input: { workspace_build_id: "c1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "AI Development", + template_id: "template-013", + template_name: "ai-template", + template_display_name: "AI Template", + template_icon: "๐Ÿง ", + workspace_id: "workspace-013", + workspace_name: "ai-playground", + }, + logs_overflowed: false, + }, + reason: "vscode_connection", + resources: [], + deadline: "2024-01-16T06:00:00Z", + max_deadline: "2024-01-16T22:00:00Z", + status: "starting", + daily_cost: 150, + template_version_preset_id: "preset-006", + has_ai_task: true, + ai_task_sidebar_app_id: "ai-app-003", + }, + { + id: "d1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-15T23:15:00Z", + updated_at: "2024-01-15T23:20:00Z", + workspace_id: "workspace-014", + workspace_name: "monitoring-stack", + workspace_owner_id: "user-014", + workspace_owner_name: "noah.martin", + workspace_owner_avatar_url: "https://example.com/avatars/noah.jpg", + template_version_id: "template-v14", + template_version_name: "Observability Stack", + build_number: 4, + transition: "stop", + initiator_id: "user-014", + initiator_name: "noah.martin", + job: { + id: "job-014", + created_at: "2024-01-15T23:15:00Z", + status: "canceling", + file_id: "file-014", + tags: { env: "monitoring", observability: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-003", + input: { workspace_build_id: "d1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Observability Stack", + template_id: "template-014", + template_name: "monitoring-template", + template_display_name: "Monitoring Template", + template_icon: "๐Ÿ“ˆ", + workspace_id: "workspace-014", + workspace_name: "monitoring-stack", + }, + logs_overflowed: false, + }, + reason: "autostop", + resources: [], + status: "canceling", + daily_cost: 85, + template_version_preset_id: null, + has_ai_task: false, + }, + { + id: "e1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-16T00:30:00Z", + updated_at: "2024-01-16T00:45:00Z", + workspace_id: "workspace-015", + workspace_name: "game-dev", + workspace_owner_id: "user-015", + workspace_owner_name: "olivia.garcia", + template_version_id: "template-v15", + template_version_name: "Unity Development", + build_number: 2, + transition: "start", + initiator_id: "user-015", + initiator_name: "olivia.garcia", + job: { + id: "job-015", + created_at: "2024-01-16T00:30:00Z", + status: "succeeded", + completed_at: "2024-01-16T00:45:00Z", + file_id: "file-015", + tags: { env: "gamedev", engine: "unity" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "e1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Unity Development", + template_id: "template-015", + template_name: "unity-template", + template_display_name: "Unity Template", + template_icon: "๐ŸŽฎ", + workspace_id: "workspace-015", + workspace_name: "game-dev", + }, + logs_overflowed: false, + }, + reason: "jetbrains_connection", + resources: [], + deadline: "2024-01-16T08:30:00Z", + status: "running", + daily_cost: 90, + template_version_preset_id: "preset-007", + has_ai_task: false, + }, + { + id: "f1234567-89ab-cdef-0123-456789abcdef", + created_at: "2024-01-16T01:00:00Z", + updated_at: "2024-01-16T01:05:00Z", + workspace_id: "workspace-016", + workspace_name: "blockchain-dev", + workspace_owner_id: "user-016", + workspace_owner_name: "paul.rodriguez", + workspace_owner_avatar_url: "https://example.com/avatars/paul.jpg", + template_version_id: "template-v16", + template_version_name: "Solidity Development", + build_number: 6, + transition: "delete", + initiator_id: "user-016", + initiator_name: "paul.rodriguez", + job: { + id: "job-016", + created_at: "2024-01-16T01:00:00Z", + status: "pending", + file_id: "file-016", + tags: { env: "blockchain", language: "solidity" }, + queue_position: 2, + queue_size: 3, + organization_id: "org-002", + input: { workspace_build_id: "f1234567-89ab-cdef-0123-456789abcdef" }, + type: "workspace_build", + metadata: { + template_version_name: "Solidity Development", + template_id: "template-016", + template_name: "solidity-template", + template_display_name: "Solidity Template", + template_icon: "โ›“๏ธ", + workspace_id: "workspace-016", + workspace_name: "blockchain-dev", + }, + logs_overflowed: false, + }, + reason: "dashboard", + resources: [], + status: "pending", + daily_cost: 65, + template_version_preset_id: null, + has_ai_task: true, + }, + { + id: "01234567-89ab-cdef-0123-456789abcde0", + created_at: "2024-01-16T02:15:00Z", + updated_at: "2024-01-16T02:30:00Z", + workspace_id: "workspace-017", + workspace_name: "iot-development", + workspace_owner_id: "user-017", + workspace_owner_name: "quinn.lee", + template_version_id: "template-v17", + template_version_name: "IoT Development", + build_number: 3, + transition: "start", + initiator_id: "user-017", + initiator_name: "quinn.lee", + job: { + id: "job-017", + created_at: "2024-01-16T02:15:00Z", + status: "running", + started_at: "2024-01-16T02:20:00Z", + file_id: "file-017", + tags: { env: "iot", embedded: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-003", + input: { workspace_build_id: "01234567-89ab-cdef-0123-456789abcde0" }, + type: "workspace_build", + metadata: { + template_version_name: "IoT Development", + template_id: "template-017", + template_name: "iot-template", + template_display_name: "IoT Template", + template_icon: "๐ŸŒ", + workspace_id: "workspace-017", + workspace_name: "iot-development", + }, + logs_overflowed: false, + }, + reason: "ssh_connection", + resources: [], + deadline: "2024-01-16T10:15:00Z", + status: "starting", + daily_cost: 55, + template_version_preset_id: "preset-008", + has_ai_task: false, + }, + { + id: "01234567-89ab-cdef-0123-456789abcde1", + created_at: "2024-01-16T03:00:00Z", + updated_at: "2024-01-16T03:02:00Z", + workspace_id: "workspace-018", + workspace_name: "analytics-lab", + workspace_owner_id: "user-018", + workspace_owner_name: "ruby.clark", + workspace_owner_avatar_url: "https://example.com/avatars/ruby.jpg", + template_version_id: "template-v18", + template_version_name: "Data Analytics", + build_number: 7, + transition: "stop", + initiator_id: "user-018", + initiator_name: "ruby.clark", + job: { + id: "job-018", + created_at: "2024-01-16T03:00:00Z", + status: "failed", + error: "Network timeout during provisioning", + file_id: "file-018", + tags: { env: "analytics", bigdata: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-002", + input: { workspace_build_id: "01234567-89ab-cdef-0123-456789abcde1" }, + type: "workspace_build", + metadata: { + template_version_name: "Data Analytics", + template_id: "template-018", + template_name: "analytics-template", + template_display_name: "Analytics Template", + template_icon: "๐Ÿ“Š", + workspace_id: "workspace-018", + workspace_name: "analytics-lab", + }, + logs_overflowed: true, + }, + reason: "autostart", + resources: [], + status: "failed", + daily_cost: 100, + template_version_preset_id: null, + has_ai_task: true, + ai_task_sidebar_app_id: "ai-app-004", + }, + { + id: "01234567-89ab-cdef-0123-456789abcde2", + created_at: "2024-01-16T04:30:00Z", + updated_at: "2024-01-16T04:45:00Z", + workspace_id: "workspace-019", + workspace_name: "design-studio", + workspace_owner_id: "user-019", + workspace_owner_name: "sam.lewis", + template_version_id: "template-v19", + template_version_name: "Design Tools", + build_number: 1, + transition: "start", + initiator_id: "user-019", + initiator_name: "sam.lewis", + job: { + id: "job-019", + created_at: "2024-01-16T04:30:00Z", + status: "succeeded", + completed_at: "2024-01-16T04:45:00Z", + file_id: "file-019", + tags: { env: "design", creative: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-001", + input: { workspace_build_id: "01234567-89ab-cdef-0123-456789abcde2" }, + type: "workspace_build", + metadata: { + template_version_name: "Design Tools", + template_id: "template-019", + template_name: "design-template", + template_display_name: "Design Template", + template_icon: "๐ŸŽจ", + workspace_id: "workspace-019", + workspace_name: "design-studio", + }, + logs_overflowed: false, + }, + reason: "cli", + resources: [], + deadline: "2024-01-16T12:30:00Z", + status: "running", + daily_cost: 70, + template_version_preset_id: "preset-009", + has_ai_task: false, + }, + { + id: "01234567-89ab-cdef-0123-456789abcde3", + created_at: "2024-01-16T05:00:00Z", + updated_at: "2024-01-16T05:10:00Z", + workspace_id: "workspace-020", + workspace_name: "legacy-migration", + workspace_owner_id: "user-020", + workspace_owner_name: "tara.walker", + workspace_owner_avatar_url: "https://example.com/avatars/tara.jpg", + template_version_id: "template-v20", + template_version_name: "Legacy System Migration", + build_number: 9, + transition: "delete", + initiator_id: "user-020", + initiator_name: "tara.walker", + job: { + id: "job-020", + created_at: "2024-01-16T05:00:00Z", + status: "succeeded", + completed_at: "2024-01-16T05:10:00Z", + file_id: "file-020", + tags: { env: "migration", legacy: "true" }, + queue_position: 0, + queue_size: 1, + organization_id: "org-003", + input: { workspace_build_id: "01234567-89ab-cdef-0123-456789abcde3" }, + type: "workspace_build", + metadata: { + template_version_name: "Legacy System Migration", + template_id: "template-020", + template_name: "migration-template", + template_display_name: "Migration Template", + template_icon: "๐Ÿ”„", + workspace_id: "workspace-020", + workspace_name: "legacy-migration", + }, + logs_overflowed: false, + }, + reason: "dormancy", + resources: [], + status: "deleted", + daily_cost: 30, + template_version_preset_id: null, + has_ai_task: false, + }, +]; diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index ce65fea6efdc1..579448824240c 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -1,4 +1,3 @@ -import type { Interpolation, Theme } from "@emotion/react"; import { useTheme } from "@emotion/react"; import HistoryOutlined from "@mui/icons-material/HistoryOutlined"; import HubOutlined from "@mui/icons-material/HubOutlined"; From b23645580a2934b14923f393b7b99192c864469a Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 17:12:14 +0000 Subject: [PATCH 06/13] fix: bring back the dots --- site/src/pages/WorkspacePage/Workspace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 579448824240c..1e15d41e1679e 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -158,7 +158,7 @@ export const Workspace: FC = ({ circle at 1px 1px, hsl(var(--surface-invert-secondary)) 0, transparent 1px - ) -2px -2px / 16px 16px;`, + ) -2px -2px / 16px 16px`, }} className="p-8 overflow-y-auto relative w-full" > From 804daf40ce30462d5e8692ddd93531a381fa370d Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 13 Aug 2025 17:43:51 +0000 Subject: [PATCH 07/13] chore: convert to tailwind --- .../src/components/FullPageLayout/Sidebar.tsx | 86 ++++++------------- 1 file changed, 25 insertions(+), 61 deletions(-) diff --git a/site/src/components/FullPageLayout/Sidebar.tsx b/site/src/components/FullPageLayout/Sidebar.tsx index a25ebe04c70d2..521ac0375d0b6 100644 --- a/site/src/components/FullPageLayout/Sidebar.tsx +++ b/site/src/components/FullPageLayout/Sidebar.tsx @@ -1,6 +1,7 @@ -import { type Interpolation, type Theme, useTheme } from "@emotion/react"; +import type { Interpolation, Theme } from "@emotion/react"; import type { ComponentProps, FC, HTMLAttributes } from "react"; import { Link, type LinkProps } from "react-router"; +import { cn } from "utils/cn"; import { TopbarIconButton } from "./Topbar"; export const Sidebar: FC> = (props) => { @@ -13,8 +14,16 @@ export const Sidebar: FC> = (props) => { ); }; -export const SidebarLink: FC = (props) => { - return ; +export const SidebarLink: FC = ({ className, ...props }) => { + return ( + + ); }; interface SidebarItemProps extends HTMLAttributes { @@ -23,21 +32,16 @@ interface SidebarItemProps extends HTMLAttributes { export const SidebarItem: FC = ({ isActive, + className, ...buttonProps }) => { - const theme = useTheme(); - return ( + +
+ {builds + ? builds.map((build) => ( + + + + )) + : Array.from({ length: 15 }, (_, i) => ( + + + + ))} + {buildsQuery.hasNextPage && ( +
+ +
+ )}
- )} +
); };