Skip to content

Commit 7e8692b

Browse files
kylecarbspresleyp
andauthored
fix: Update routing for workspace schedule (#2113)
* fix: Update routing for workspace schedule This was broken as part of #2101. It was a silly mistake, but unfortunate our tests didn't catch it. This is a rare change so unlikely to occur again, so I won't make an issue adding tests. * Update site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx Co-authored-by: Presley Pizzo <1290996+presleyp@users.noreply.github.com> Co-authored-by: Presley Pizzo <1290996+presleyp@users.noreply.github.com>
1 parent a4e259e commit 7e8692b

File tree

11 files changed

+100
-46
lines changed

11 files changed

+100
-46
lines changed

coderd/workspacebuilds.go

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,16 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
3737
return
3838
}
3939

40-
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(workspace, workspaceBuild, job))
40+
owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID)
41+
if err != nil {
42+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
43+
Message: "Internal error fetching user",
44+
Detail: err.Error(),
45+
})
46+
return
47+
}
48+
49+
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(owner, workspace, workspaceBuild, job))
4150
}
4251

4352
func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
@@ -100,8 +109,8 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
100109
}
101110

102111
jobIDs := make([]uuid.UUID, 0, len(builds))
103-
for _, version := range builds {
104-
jobIDs = append(jobIDs, version.JobID)
112+
for _, build := range builds {
113+
jobIDs = append(jobIDs, build.JobID)
105114
}
106115
jobs, err := api.Database.GetProvisionerJobsByIDs(r.Context(), jobIDs)
107116
if errors.Is(err, sql.ErrNoRows) {
@@ -119,6 +128,15 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
119128
jobByID[job.ID.String()] = job
120129
}
121130

131+
owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID)
132+
if err != nil {
133+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
134+
Message: "Internal error fetching user",
135+
Detail: err.Error(),
136+
})
137+
return
138+
}
139+
122140
apiBuilds := make([]codersdk.WorkspaceBuild, 0)
123141
for _, build := range builds {
124142
job, exists := jobByID[build.JobID.String()]
@@ -128,7 +146,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
128146
})
129147
return
130148
}
131-
apiBuilds = append(apiBuilds, convertWorkspaceBuild(workspace, build, job))
149+
apiBuilds = append(apiBuilds, convertWorkspaceBuild(owner, workspace, build, job))
132150
}
133151

134152
httpapi.Write(rw, http.StatusOK, apiBuilds)
@@ -167,8 +185,16 @@ func (api *API) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
167185
})
168186
return
169187
}
188+
owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID)
189+
if err != nil {
190+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
191+
Message: "Internal error getting user",
192+
Detail: err.Error(),
193+
})
194+
return
195+
}
170196

171-
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(workspace, workspaceBuild, job))
197+
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(owner, workspace, workspaceBuild, job))
172198
}
173199

174200
func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
@@ -342,8 +368,17 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
342368
return
343369
}
344370

371+
owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID)
372+
if err != nil {
373+
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
374+
Message: "Internal error getting user",
375+
Detail: err.Error(),
376+
})
377+
return
378+
}
379+
345380
httpapi.Write(rw, http.StatusCreated,
346-
convertWorkspaceBuild(workspace, workspaceBuild, provisionerJob))
381+
convertWorkspaceBuild(owner, workspace, workspaceBuild, provisionerJob))
347382
}
348383

349384
func (api *API) patchCancelWorkspaceBuild(rw http.ResponseWriter, r *http.Request) {
@@ -473,6 +508,7 @@ func (api *API) workspaceBuildState(rw http.ResponseWriter, r *http.Request) {
473508
}
474509

475510
func convertWorkspaceBuild(
511+
workspaceOwner database.User,
476512
workspace database.Workspace,
477513
workspaceBuild database.WorkspaceBuild,
478514
job database.ProvisionerJob) codersdk.WorkspaceBuild {
@@ -481,18 +517,20 @@ func convertWorkspaceBuild(
481517
panic("workspace and build do not match")
482518
}
483519
return codersdk.WorkspaceBuild{
484-
ID: workspaceBuild.ID,
485-
CreatedAt: workspaceBuild.CreatedAt,
486-
UpdatedAt: workspaceBuild.UpdatedAt,
487-
WorkspaceID: workspaceBuild.WorkspaceID,
488-
WorkspaceName: workspace.Name,
489-
TemplateVersionID: workspaceBuild.TemplateVersionID,
490-
BuildNumber: workspaceBuild.BuildNumber,
491-
Name: workspaceBuild.Name,
492-
Transition: codersdk.WorkspaceTransition(workspaceBuild.Transition),
493-
InitiatorID: workspaceBuild.InitiatorID,
494-
Job: convertProvisionerJob(job),
495-
Deadline: workspaceBuild.Deadline,
520+
ID: workspaceBuild.ID,
521+
CreatedAt: workspaceBuild.CreatedAt,
522+
UpdatedAt: workspaceBuild.UpdatedAt,
523+
WorkspaceOwnerID: workspace.OwnerID,
524+
WorkspaceOwnerName: workspaceOwner.Username,
525+
WorkspaceID: workspaceBuild.WorkspaceID,
526+
WorkspaceName: workspace.Name,
527+
TemplateVersionID: workspaceBuild.TemplateVersionID,
528+
BuildNumber: workspaceBuild.BuildNumber,
529+
Name: workspaceBuild.Name,
530+
Transition: codersdk.WorkspaceTransition(workspaceBuild.Transition),
531+
InitiatorID: workspaceBuild.InitiatorID,
532+
Job: convertProvisionerJob(job),
533+
Deadline: workspaceBuild.Deadline,
496534
}
497535
}
498536

coderd/workspaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ func convertWorkspace(
807807
OwnerID: workspace.OwnerID,
808808
OwnerName: owner.Username,
809809
TemplateID: workspace.TemplateID,
810-
LatestBuild: convertWorkspaceBuild(workspace, workspaceBuild, job),
810+
LatestBuild: convertWorkspaceBuild(owner, workspace, workspaceBuild, job),
811811
TemplateName: template.Name,
812812
Outdated: workspaceBuild.TemplateVersionID.String() != template.ActiveVersionID.String(),
813813
Name: workspace.Name,

codersdk/workspacebuilds.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,20 @@ const (
2222
// WorkspaceBuild is an at-point representation of a workspace state.
2323
// BuildNumbers start at 1 and increase by 1 for each subsequent build
2424
type WorkspaceBuild struct {
25-
ID uuid.UUID `json:"id"`
26-
CreatedAt time.Time `json:"created_at"`
27-
UpdatedAt time.Time `json:"updated_at"`
28-
WorkspaceID uuid.UUID `json:"workspace_id"`
29-
WorkspaceName string `json:"workspace_name"`
30-
TemplateVersionID uuid.UUID `json:"template_version_id"`
31-
BuildNumber int32 `json:"build_number"`
32-
Name string `json:"name"`
33-
Transition WorkspaceTransition `json:"transition"`
34-
InitiatorID uuid.UUID `json:"initiator_id"`
35-
Job ProvisionerJob `json:"job"`
36-
Deadline time.Time `json:"deadline"`
25+
ID uuid.UUID `json:"id"`
26+
CreatedAt time.Time `json:"created_at"`
27+
UpdatedAt time.Time `json:"updated_at"`
28+
WorkspaceID uuid.UUID `json:"workspace_id"`
29+
WorkspaceName string `json:"workspace_name"`
30+
WorkspaceOwnerID uuid.UUID `json:"workspace_owner_id"`
31+
WorkspaceOwnerName string `json:"workspace_owner_name"`
32+
TemplateVersionID uuid.UUID `json:"template_version_id"`
33+
BuildNumber int32 `json:"build_number"`
34+
Name string `json:"name"`
35+
Transition WorkspaceTransition `json:"transition"`
36+
InitiatorID uuid.UUID `json:"initiator_id"`
37+
Job ProvisionerJob `json:"job"`
38+
Deadline time.Time `json:"deadline"`
3739
}
3840

3941
// WorkspaceBuild returns a single workspace build for a workspace.

site/src/api/typesGenerated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ export interface WorkspaceBuild {
440440
readonly updated_at: string
441441
readonly workspace_id: string
442442
readonly workspace_name: string
443+
readonly workspace_owner_id: string
444+
readonly workspace_owner_name: string
443445
readonly template_version_id: string
444446
readonly build_number: number
445447
readonly name: string

site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const WorkspaceBuildStats: FC<WorkspaceBuildStatsProps> = ({ build }) =>
2222
<span className={styles.statsLabel}>Workspace Name</span>
2323
<Link
2424
component={RouterLink}
25-
to={`/workspaces/${build.workspace_id}`}
25+
to={`/@${build.workspace_owner_name}/${build.workspace_name}`}
2626
className={combineClasses([styles.statsValue, styles.link])}
2727
>
2828
{build.workspace_name}

site/src/components/WorkspaceSchedule/WorkspaceSchedule.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ export const WorkspaceSchedule: FC<WorkspaceScheduleProps> = ({ workspace }) =>
9292
<span className={styles.scheduleValue}>{Language.autoStopDisplay(workspace)}</span>
9393
</div>
9494
<div>
95-
<Link className={styles.scheduleAction} component={RouterLink} to={`/workspaces/${workspace.id}/schedule`}>
95+
<Link
96+
className={styles.scheduleAction}
97+
component={RouterLink}
98+
to={`/@${workspace.owner_name}/${workspace.name}/schedule`}
99+
>
96100
{Language.editScheduleLink}
97101
</Link>
98102
</div>

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const CreateWorkspacePage: FC = () => {
1717
context: { organizationId, preSelectedTemplateName },
1818
actions: {
1919
onCreateWorkspace: (_, event) => {
20-
navigate("/workspaces/" + event.data.id)
20+
navigate(`/@${event.data.owner_name}/${event.data.name}`)
2121
},
2222
},
2323
})

site/src/pages/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,33 +142,39 @@ export const workspaceToInitialValues = (
142142
}
143143

144144
export const WorkspaceSchedulePage: React.FC = () => {
145+
const { username: usernameQueryParam, workspace: workspaceQueryParam } = useParams()
145146
const navigate = useNavigate()
146-
const { workspace: workspaceQueryParam } = useParams()
147-
const workspaceId = firstOrItem(workspaceQueryParam, null)
147+
const username = firstOrItem(usernameQueryParam, null)
148+
const workspaceName = firstOrItem(workspaceQueryParam, null)
148149
const [scheduleState, scheduleSend] = useMachine(workspaceSchedule)
149150
const { formErrors, getWorkspaceError, workspace } = scheduleState.context
150151

151-
// Get workspace on mount and whenever workspaceId changes.
152+
// Get workspace on mount and whenever the args for getting a workspace change.
152153
// scheduleSend should not change.
153154
useEffect(() => {
154-
workspaceId && scheduleSend({ type: "GET_WORKSPACE", workspaceId })
155-
}, [workspaceId, scheduleSend])
155+
username && workspaceName && scheduleSend({ type: "GET_WORKSPACE", username, workspaceName })
156+
}, [username, workspaceName, scheduleSend])
156157

157-
if (!workspaceId) {
158+
if (!username || !workspaceName) {
158159
navigate("/workspaces")
159160
return null
160161
} else if (scheduleState.matches("idle") || scheduleState.matches("gettingWorkspace") || !workspace) {
161162
return <FullScreenLoader />
162163
} else if (scheduleState.matches("error")) {
163-
return <ErrorSummary error={getWorkspaceError} retry={() => scheduleSend({ type: "GET_WORKSPACE", workspaceId })} />
164+
return (
165+
<ErrorSummary
166+
error={getWorkspaceError}
167+
retry={() => scheduleSend({ type: "GET_WORKSPACE", username, workspaceName })}
168+
/>
169+
)
164170
} else if (scheduleState.matches("presentForm") || scheduleState.matches("submittingSchedule")) {
165171
return (
166172
<WorkspaceScheduleForm
167173
fieldErrors={formErrors}
168174
initialValues={workspaceToInitialValues(workspace, dayjs.tz.guess())}
169175
isLoading={scheduleState.tags.has("loading")}
170176
onCancel={() => {
171-
navigate(`/workspaces/${workspaceId}`)
177+
navigate(`/@${username}/${workspaceName}`)
172178
}}
173179
onSubmit={(values) => {
174180
scheduleSend({
@@ -180,7 +186,7 @@ export const WorkspaceSchedulePage: React.FC = () => {
180186
/>
181187
)
182188
} else if (scheduleState.matches("submitSuccess")) {
183-
navigate(`/workspaces/${workspaceId}`)
189+
navigate(`/@${username}/${workspaceName}`)
184190
return <FullScreenLoader />
185191
} else {
186192
// Theoretically impossible - log and bail

site/src/testHelpers/entities.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ export const MockWorkspaceBuild: TypesGen.WorkspaceBuild = {
137137
transition: "start",
138138
updated_at: "2022-05-17T17:39:01.382927298Z",
139139
workspace_name: "test-workspace",
140+
workspace_owner_id: MockUser.id,
141+
workspace_owner_name: MockUser.username,
140142
workspace_id: "759f1d46-3174-453d-aa60-980a9c1442f3",
141143
deadline: "2022-05-17T23:39:00.00Z",
142144
}

site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface WorkspaceScheduleContext {
2626
}
2727

2828
export type WorkspaceScheduleEvent =
29-
| { type: "GET_WORKSPACE"; workspaceId: string }
29+
| { type: "GET_WORKSPACE"; username: string; workspaceName: string }
3030
| {
3131
type: "SUBMIT_SCHEDULE"
3232
autoStart: TypesGen.UpdateWorkspaceAutostartRequest
@@ -132,7 +132,7 @@ export const workspaceSchedule = createMachine(
132132

133133
services: {
134134
getWorkspace: async (_, event) => {
135-
return await API.getWorkspace(event.workspaceId)
135+
return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName)
136136
},
137137
submitSchedule: async (context, event) => {
138138
if (!context.workspace?.id) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy