From ff56fb7e235f48c53a15871c81bd61aeace261b8 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Thu, 2 Jul 2026 19:14:35 +0800 Subject: [PATCH] fix(workspace): expose last opened in contract (#38323) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/controllers/console/workspace/workspace.py | 5 +++-- api/openapi/markdown/console-openapi.md | 1 + .../generated/api/console/workspaces/types.gen.ts | 1 + .../generated/api/console/workspaces/zod.gen.ts | 1 + .../main-nav/components/workspace-switcher.tsx | 11 ++++------- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/api/controllers/console/workspace/workspace.py b/api/controllers/console/workspace/workspace.py index 0afd7e06bf7..746e971bce8 100644 --- a/api/controllers/console/workspace/workspace.py +++ b/api/controllers/console/workspace/workspace.py @@ -102,6 +102,7 @@ class TenantListItemResponse(ResponseModel): plan: str | None = None status: str | None = None created_at: int | None = None + last_opened_at: int | None = None current: bool @field_validator("plan", "status", mode="before") @@ -113,9 +114,9 @@ class TenantListItemResponse(ResponseModel): return value return str(getattr(value, "value", value)) - @field_validator("created_at", mode="before") + @field_validator("created_at", "last_opened_at", mode="before") @classmethod - def _normalize_created_at(cls, value: datetime | int | None): + def _normalize_timestamp(cls, value: datetime | int | None): return to_timestamp(value) diff --git a/api/openapi/markdown/console-openapi.md b/api/openapi/markdown/console-openapi.md index dda9c32a296..434315914aa 100644 --- a/api/openapi/markdown/console-openapi.md +++ b/api/openapi/markdown/console-openapi.md @@ -21199,6 +21199,7 @@ Tag type | created_at | integer | | No | | current | boolean | | Yes | | id | string | | Yes | +| last_opened_at | integer | | No | | name | string | | No | | plan | string | | No | | status | string | | No | diff --git a/packages/contracts/generated/api/console/workspaces/types.gen.ts b/packages/contracts/generated/api/console/workspaces/types.gen.ts index f829280b984..de5199273f9 100644 --- a/packages/contracts/generated/api/console/workspaces/types.gen.ts +++ b/packages/contracts/generated/api/console/workspaces/types.gen.ts @@ -939,6 +939,7 @@ export type TenantListItemResponse = { created_at?: number | null current: boolean id: string + last_opened_at?: number | null name?: string | null plan?: string | null status?: string | null diff --git a/packages/contracts/generated/api/console/workspaces/zod.gen.ts b/packages/contracts/generated/api/console/workspaces/zod.gen.ts index 6b1017f3afa..be04fa4e526 100644 --- a/packages/contracts/generated/api/console/workspaces/zod.gen.ts +++ b/packages/contracts/generated/api/console/workspaces/zod.gen.ts @@ -684,6 +684,7 @@ export const zTenantListItemResponse = z.object({ created_at: z.int().nullish(), current: z.boolean(), id: z.string(), + last_opened_at: z.int().nullish(), name: z.string().nullish(), plan: z.string().nullish(), status: z.string().nullish(), diff --git a/web/app/components/main-nav/components/workspace-switcher.tsx b/web/app/components/main-nav/components/workspace-switcher.tsx index a0f7f3f8cc2..c93ac3525dc 100644 --- a/web/app/components/main-nav/components/workspace-switcher.tsx +++ b/web/app/components/main-nav/components/workspace-switcher.tsx @@ -21,13 +21,10 @@ const workspaceSwitchActionIconClassName = 'size-3.5 shrink-0' const workspaceSwitchListClassName = 'max-h-[240px] overflow-y-auto overscroll-contain scroll-py-1' const workspaceSwitchI18nKey = (key: string) => key as 'mainNav.workspace.settings' type WorkspaceSort = 'lastOpened' | 'createdAt' -type WorkspaceListItem = TenantListItemResponse & { - last_opened_at?: number | null -} -const getWorkspaceName = (workspace: WorkspaceListItem) => workspace.name || workspace.id -const getWorkspaceCreatedAt = (workspace: WorkspaceListItem) => workspace.created_at ?? 0 -const getWorkspaceLastOpenedAt = (workspace: WorkspaceListItem) => workspace.last_opened_at ?? 0 +const getWorkspaceName = (workspace: TenantListItemResponse) => workspace.name || workspace.id +const getWorkspaceCreatedAt = (workspace: TenantListItemResponse) => workspace.created_at ?? 0 +const getWorkspaceLastOpenedAt = (workspace: TenantListItemResponse) => workspace.last_opened_at ?? 0 function WorkspaceSwitchControls({ searchText, @@ -123,7 +120,7 @@ function WorkspaceSwitchControls({ } type WorkspaceSwitcherProps = { - workspaces: WorkspaceListItem[] + workspaces: TenantListItemResponse[] onSwitchWorkspace: (workspaceId: string) => void }