From babe9891f3d30021c5a09348c32324cc6de24c9f Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Tue, 15 Nov 2022 10:22:47 +0100 Subject: [PATCH 1/6] feat: expose template.display_name via Workspaces endpoint --- coderd/workspaces.go | 29 +++++++++++++++-------------- coderd/workspaces_test.go | 30 ++++++++++++++++++++++++++++++ codersdk/workspaces.go | 29 +++++++++++++++-------------- site/src/api/typesGenerated.ts | 1 + 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 540fd42665761..0f77f5a172e53 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -1011,20 +1011,21 @@ func convertWorkspace( ttlMillis := convertWorkspaceTTLMillis(workspace.Ttl) return codersdk.Workspace{ - ID: workspace.ID, - CreatedAt: workspace.CreatedAt, - UpdatedAt: workspace.UpdatedAt, - OwnerID: workspace.OwnerID, - OwnerName: owner.Username, - TemplateID: workspace.TemplateID, - LatestBuild: workspaceBuild, - TemplateName: template.Name, - TemplateIcon: template.Icon, - Outdated: workspaceBuild.TemplateVersionID.String() != template.ActiveVersionID.String(), - Name: workspace.Name, - AutostartSchedule: autostartSchedule, - TTLMillis: ttlMillis, - LastUsedAt: workspace.LastUsedAt, + ID: workspace.ID, + CreatedAt: workspace.CreatedAt, + UpdatedAt: workspace.UpdatedAt, + OwnerID: workspace.OwnerID, + OwnerName: owner.Username, + TemplateID: workspace.TemplateID, + LatestBuild: workspaceBuild, + TemplateName: template.Name, + TemplateIcon: template.Icon, + TemplateDisplayName: template.DisplayName, + Outdated: workspaceBuild.TemplateVersionID.String() != template.ActiveVersionID.String(), + Name: workspace.Name, + AutostartSchedule: autostartSchedule, + TTLMillis: ttlMillis, + LastUsedAt: workspace.LastUsedAt, } } diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 73a7ce19dd013..f4ced10d53034 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -115,6 +115,36 @@ func TestWorkspace(t *testing.T) { }) require.Error(t, err, "workspace rename should have failed") }) + + t.Run("TemplateProperties", func(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + + const templateIcon = "/img/icon.svg" + const templateDisplayName = "This is template" + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { + ctr.Icon = templateIcon + ctr.DisplayName = templateDisplayName + }) + require.NotEmpty(t, template.Name) + require.NotEmpty(t, template.DisplayName) + require.NotEmpty(t, template.Icon) + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) + + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() + + ws, err := client.Workspace(ctx, workspace.ID) + require.NoError(t, err) + assert.Equal(t, user.UserID, ws.LatestBuild.InitiatorID) + assert.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) + assert.Equal(t, template.Name, ws.TemplateName) + assert.Equal(t, templateIcon, ws.TemplateIcon) + assert.Equal(t, templateDisplayName, ws.TemplateDisplayName) + }) } func TestAdminViewAllWorkspaces(t *testing.T) { diff --git a/codersdk/workspaces.go b/codersdk/workspaces.go index 084fb66e96132..24cfc6b96e072 100644 --- a/codersdk/workspaces.go +++ b/codersdk/workspaces.go @@ -17,20 +17,21 @@ import ( // Workspace is a deployment of a template. It references a specific // version and can be updated. type Workspace struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - OwnerID uuid.UUID `json:"owner_id"` - OwnerName string `json:"owner_name"` - TemplateID uuid.UUID `json:"template_id"` - TemplateName string `json:"template_name"` - TemplateIcon string `json:"template_icon"` - LatestBuild WorkspaceBuild `json:"latest_build"` - Outdated bool `json:"outdated"` - Name string `json:"name"` - AutostartSchedule *string `json:"autostart_schedule,omitempty"` - TTLMillis *int64 `json:"ttl_ms,omitempty"` - LastUsedAt time.Time `json:"last_used_at"` + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + OwnerID uuid.UUID `json:"owner_id"` + OwnerName string `json:"owner_name"` + TemplateID uuid.UUID `json:"template_id"` + TemplateName string `json:"template_name"` + TemplateDisplayName string `json:"template_display_name"` + TemplateIcon string `json:"template_icon"` + LatestBuild WorkspaceBuild `json:"latest_build"` + Outdated bool `json:"outdated"` + Name string `json:"name"` + AutostartSchedule *string `json:"autostart_schedule,omitempty"` + TTLMillis *int64 `json:"ttl_ms,omitempty"` + LastUsedAt time.Time `json:"last_used_at"` } type WorkspacesRequest struct { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index d92fd82213ca9..b5b6505bcf205 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -785,6 +785,7 @@ export interface Workspace { readonly owner_name: string readonly template_id: string readonly template_name: string + readonly template_display_name: string readonly template_icon: string readonly latest_build: WorkspaceBuild readonly outdated: boolean From c5ed79d179efbd5bf846e39dae59074b2a168016 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Tue, 15 Nov 2022 10:26:42 +0100 Subject: [PATCH 2/6] Fix: MockWorkspace --- site/src/testHelpers/entities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 8842c49ac9c20..c43d7a64d19a8 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -434,6 +434,7 @@ export const MockWorkspace: TypesGen.Workspace = { template_id: MockTemplate.id, template_name: MockTemplate.name, template_icon: MockTemplate.icon, + template_display_name: MockTemplate.display_name, outdated: false, owner_id: MockUser.id, owner_name: MockUser.username, From 1d2e1ca34da9ed267a81e4fb8c13580bd6ca1a88 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Tue, 15 Nov 2022 11:19:24 +0100 Subject: [PATCH 3/6] UI: Workspace stats and row --- site/src/components/WorkspaceStats/WorkspaceStats.tsx | 2 +- site/src/components/WorkspacesTable/WorkspacesRow.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/components/WorkspaceStats/WorkspaceStats.tsx b/site/src/components/WorkspaceStats/WorkspaceStats.tsx index b68bb33431e87..b0db34f2a6e84 100644 --- a/site/src/components/WorkspaceStats/WorkspaceStats.tsx +++ b/site/src/components/WorkspaceStats/WorkspaceStats.tsx @@ -46,7 +46,7 @@ export const WorkspaceStats: FC = ({ to={`/templates/${workspace.template_name}`} className={combineClasses([styles.statsValue, styles.link])} > - {workspace.template_name} + {workspace.template_display_name.length > 0 ? workspace.template_display_name : workspace.template_name}
diff --git a/site/src/components/WorkspacesTable/WorkspacesRow.tsx b/site/src/components/WorkspacesTable/WorkspacesRow.tsx index 97e21ed5d4ae9..b54d616e1c380 100644 --- a/site/src/components/WorkspacesTable/WorkspacesRow.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesRow.tsx @@ -61,7 +61,7 @@ export const WorkspacesRow: FC< - {workspace.template_name} + {workspace.template_display_name.length > 0 ? workspace.template_display_name : workspace.template_name} From f30032c96206beb5af0459085904090847a68a72 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Tue, 15 Nov 2022 12:53:21 +0100 Subject: [PATCH 4/6] Show template.display_name on pages --- site/src/components/WorkspaceStats/WorkspaceStats.tsx | 4 +++- site/src/components/WorkspacesTable/WorkspacesRow.tsx | 6 +++++- site/src/pages/WorkspacePage/WorkspacePage.test.tsx | 4 ++++ site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx | 9 ++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/site/src/components/WorkspaceStats/WorkspaceStats.tsx b/site/src/components/WorkspaceStats/WorkspaceStats.tsx index b0db34f2a6e84..edaffc059ff87 100644 --- a/site/src/components/WorkspaceStats/WorkspaceStats.tsx +++ b/site/src/components/WorkspaceStats/WorkspaceStats.tsx @@ -46,7 +46,9 @@ export const WorkspaceStats: FC = ({ to={`/templates/${workspace.template_name}`} className={combineClasses([styles.statsValue, styles.link])} > - {workspace.template_display_name.length > 0 ? workspace.template_display_name : workspace.template_name} + {workspace.template_display_name.length > 0 + ? workspace.template_display_name + : workspace.template_name}
diff --git a/site/src/components/WorkspacesTable/WorkspacesRow.tsx b/site/src/components/WorkspacesTable/WorkspacesRow.tsx index b54d616e1c380..b4f312ffdb867 100644 --- a/site/src/components/WorkspacesTable/WorkspacesRow.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesRow.tsx @@ -61,7 +61,11 @@ export const WorkspacesRow: FC< - {workspace.template_display_name.length > 0 ? workspace.template_display_name : workspace.template_name} + + {workspace.template_display_name.length > 0 + ? workspace.template_display_name + : workspace.template_name} + diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index c05090d02622f..e7efb78554b9e 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -271,6 +271,10 @@ describe("WorkspacePage", () => { t("workspaceStatus.deleted", { ns: "common" }), ) }) + it("renders the template display name", async () => { + await renderWorkspacePage() + await screen.findByText(MockWorkspace.template_display_name) + }) describe("Timeline", () => { it("shows the timeline build", async () => { diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx index 14e056f52d4c2..3d73efa33518a 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx @@ -1,7 +1,10 @@ import { screen, waitFor } from "@testing-library/react" import { rest } from "msw" import * as CreateDayString from "util/createDayString" -import { MockWorkspace } from "../../testHelpers/entities" +import { + MockWorkspace, + MockWorkspacesResponse, +} from "../../testHelpers/entities" import { history, render } from "../../testHelpers/renderHelpers" import { server } from "../../testHelpers/server" import WorkspacesPage from "./WorkspacesPage" @@ -54,5 +57,9 @@ describe("WorkspacesPage", () => { { timeout: 2000 }, ) await screen.findByText(`${MockWorkspace.name}1`) + const templateDisplayNames = await screen.findAllByText( + `${MockWorkspace.template_display_name}`, + ) + expect(templateDisplayNames).toHaveLength(MockWorkspacesResponse.count) }) }) From c63b6f8e4c88a885e3fcb0024d3ab6edb52bca1e Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 16 Nov 2022 15:21:34 +0100 Subject: [PATCH 5/6] Fix: address PR comments --- site/src/pages/WorkspacePage/WorkspacePage.test.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index e7efb78554b9e..c05090d02622f 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -271,10 +271,6 @@ describe("WorkspacePage", () => { t("workspaceStatus.deleted", { ns: "common" }), ) }) - it("renders the template display name", async () => { - await renderWorkspacePage() - await screen.findByText(MockWorkspace.template_display_name) - }) describe("Timeline", () => { it("shows the timeline build", async () => { From ccbc60e1f6b004fed5d17c41705f00fcd8e8bc3f Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 16 Nov 2022 15:38:26 +0100 Subject: [PATCH 6/6] Add helper function: getDisplayWorkspaceTemplateName --- .../WorkspaceStats/WorkspaceStats.tsx | 10 ++++++---- .../WorkspacesTable/WorkspacesRow.tsx | 8 +++----- site/src/util/workspace.test.ts | 19 +++++++++++++++++++ site/src/util/workspace.ts | 8 ++++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/site/src/components/WorkspaceStats/WorkspaceStats.tsx b/site/src/components/WorkspaceStats/WorkspaceStats.tsx index edaffc059ff87..bbed761056ef4 100644 --- a/site/src/components/WorkspaceStats/WorkspaceStats.tsx +++ b/site/src/components/WorkspaceStats/WorkspaceStats.tsx @@ -5,7 +5,10 @@ import { FC } from "react" import { Link as RouterLink } from "react-router-dom" import { combineClasses } from "util/combineClasses" import { createDayString } from "util/createDayString" -import { getDisplayWorkspaceBuildInitiatedBy } from "util/workspace" +import { + getDisplayWorkspaceBuildInitiatedBy, + getDisplayWorkspaceTemplateName, +} from "util/workspace" import { Workspace } from "../../api/typesGenerated" const Language = { @@ -36,6 +39,7 @@ export const WorkspaceStats: FC = ({ const initiatedBy = getDisplayWorkspaceBuildInitiatedBy( workspace.latest_build, ) + const displayTemplateName = getDisplayWorkspaceTemplateName(workspace) return (
@@ -46,9 +50,7 @@ export const WorkspaceStats: FC = ({ to={`/templates/${workspace.template_name}`} className={combineClasses([styles.statsValue, styles.link])} > - {workspace.template_display_name.length > 0 - ? workspace.template_display_name - : workspace.template_name} + {displayTemplateName}
diff --git a/site/src/components/WorkspacesTable/WorkspacesRow.tsx b/site/src/components/WorkspacesTable/WorkspacesRow.tsx index b4f312ffdb867..07beb72528337 100644 --- a/site/src/components/WorkspacesTable/WorkspacesRow.tsx +++ b/site/src/components/WorkspacesTable/WorkspacesRow.tsx @@ -7,6 +7,7 @@ import { AvatarData } from "components/AvatarData/AvatarData" import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge" import { FC } from "react" import { useNavigate } from "react-router-dom" +import { getDisplayWorkspaceTemplateName } from "util/workspace" import { WorkspaceItemMachineRef } from "../../xServices/workspaces/workspacesXService" import { LastUsed } from "../LastUsed/LastUsed" import { @@ -32,6 +33,7 @@ export const WorkspacesRow: FC< const workspacePageLink = `/@${workspace.owner_name}/${workspace.name}` const hasTemplateIcon = workspace.template_icon && workspace.template_icon !== "" + const displayTemplateName = getDisplayWorkspaceTemplateName(workspace) return ( - - {workspace.template_display_name.length > 0 - ? workspace.template_display_name - : workspace.template_name} - + {displayTemplateName} diff --git a/site/src/util/workspace.test.ts b/site/src/util/workspace.test.ts index 333eebfd13e3f..26bb223c6b566 100644 --- a/site/src/util/workspace.test.ts +++ b/site/src/util/workspace.test.ts @@ -5,6 +5,7 @@ import { defaultWorkspaceExtension, getDisplayVersionStatus, getDisplayWorkspaceBuildInitiatedBy, + getDisplayWorkspaceTemplateName, isWorkspaceOn, } from "./workspace" @@ -120,4 +121,22 @@ describe("util > workspace", () => { }, ) }) + + describe("getDisplayWorkspaceTemplateName", () => { + it("display name is not set", async () => { + const workspace: TypesGen.Workspace = { + ...Mocks.MockWorkspace, + template_display_name: "", + } + const displayed = getDisplayWorkspaceTemplateName(workspace) + expect(displayed).toEqual(workspace.template_name) + }) + it("display name is set", async () => { + const workspace: TypesGen.Workspace = { + ...Mocks.MockWorkspace, + } + const displayed = getDisplayWorkspaceTemplateName(workspace) + expect(displayed).toEqual(workspace.template_display_name) + }) + }) }) diff --git a/site/src/util/workspace.ts b/site/src/util/workspace.ts index 22d74d826f7f1..7d81e644d9d6d 100644 --- a/site/src/util/workspace.ts +++ b/site/src/util/workspace.ts @@ -182,3 +182,11 @@ export const getFaviconByStatus = ( return "favicon" } } + +export const getDisplayWorkspaceTemplateName = ( + workspace: TypesGen.Workspace, +): string => { + return workspace.template_display_name.length > 0 + ? workspace.template_display_name + : workspace.template_name +}