Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdad033e

Browse files
fix(site): exclude workspace schedule settings for prebuilt workspaces (#18826)
## DescriptionThis PR updates the UI to avoid rendering workspace schedule settings(autostop, autostart, etc.) for prebuilt workspaces. Instead, itdisplays an informational message with a link to the relevantdocumentation.## Changes* Introduce `IsPrebuild` parameter to `convertWorkspace` to indicatewhether the workspace is a prebuild.* Prevent the Workspace Schedule settings form from rendering in the UIfor prebuilt workspaces.* Display an info alert with a link to documentation when viewing aprebuilt workspace.<img width="2980" height="864" alt="Screenshot 2025-07-10 at 13 16 13"src="https://github.com/user-attachments/assets/5f831c21-50bb-4e05-beea-dbeb930ddff8"/>Relates with:#18762---------Co-authored-by: BrunoQuaresma <bruno_nonato_quaresma@hotmail.com>
1 parente4d3453 commitdad033e

File tree

11 files changed

+220
-70
lines changed

11 files changed

+220
-70
lines changed

‎cli/testdata/coder_list_--output_json.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"automatic_updates": "never",
8787
"allow_renames": false,
8888
"favorite": false,
89-
"next_start_at": "====[timestamp]====="
89+
"next_start_at": "====[timestamp]=====",
90+
"is_prebuild": false
9091
}
9192
]

‎coderd/apidoc/docs.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/workspaces.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,6 +2231,7 @@ func convertWorkspace(
22312231
iflatestAppStatus.ID==uuid.Nil {
22322232
appStatus=nil
22332233
}
2234+
22342235
return codersdk.Workspace{
22352236
ID:workspace.ID,
22362237
CreatedAt:workspace.CreatedAt,
@@ -2265,6 +2266,7 @@ func convertWorkspace(
22652266
AllowRenames:allowRenames,
22662267
Favorite:requesterFavorite,
22672268
NextStartAt:nextStartAt,
2269+
IsPrebuild:workspace.IsPrebuild(),
22682270
},nil
22692271
}
22702272

‎codersdk/workspaces.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ type Workspace struct {
6666
AllowRenamesbool`json:"allow_renames"`
6767
Favoritebool`json:"favorite"`
6868
NextStartAt*time.Time`json:"next_start_at" format:"date-time"`
69+
// IsPrebuild indicates whether the workspace is a prebuilt workspace.
70+
// Prebuilt workspaces are owned by the prebuilds system user and have specific behavior,
71+
// such as being managed differently from regular workspaces.
72+
// Once a prebuilt workspace is claimed by a user, it transitions to a regular workspace,
73+
// and IsPrebuild returns false.
74+
IsPrebuildbool`json:"is_prebuild"`
6975
}
7076

7177
func (wWorkspace)FullName()string {

‎docs/reference/api/schemas.md

Lines changed: 35 additions & 32 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎docs/reference/api/workspaces.md

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎site/src/api/typesGenerated.ts

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{getAuthorizationKey}from"api/queries/authCheck";
3+
import{templateByNameKey}from"api/queries/templates";
4+
import{workspaceByOwnerAndNameKey}from"api/queries/workspaces";
5+
importtype{Workspace}from"api/typesGenerated";
6+
import{
7+
reactRouterNestedAncestors,
8+
reactRouterParameters,
9+
}from"storybook-addon-remix-react-router";
10+
import{
11+
MockPrebuiltWorkspace,
12+
MockTemplate,
13+
MockUserOwner,
14+
MockWorkspace,
15+
}from"testHelpers/entities";
16+
import{withAuthProvider,withDashboardProvider}from"testHelpers/storybook";
17+
import{WorkspaceSettingsLayout}from"../WorkspaceSettingsLayout";
18+
importWorkspaceSchedulePagefrom"./WorkspaceSchedulePage";
19+
20+
constmeta={
21+
title:"pages/WorkspaceSchedulePage",
22+
component:WorkspaceSchedulePage,
23+
decorators:[withAuthProvider,withDashboardProvider],
24+
parameters:{
25+
layout:"fullscreen",
26+
user:MockUserOwner,
27+
},
28+
}satisfiesMeta<typeofWorkspaceSchedulePage>;
29+
30+
exportdefaultmeta;
31+
typeStory=StoryObj<typeofWorkspaceSchedulePage>;
32+
33+
exportconstRegularWorkspace:Story={
34+
parameters:{
35+
reactRouter:workspaceRouterParameters(MockWorkspace),
36+
queries:workspaceQueries(MockWorkspace),
37+
},
38+
};
39+
40+
exportconstPrebuiltWorkspace:Story={
41+
parameters:{
42+
reactRouter:workspaceRouterParameters(MockPrebuiltWorkspace),
43+
queries:workspaceQueries(MockPrebuiltWorkspace),
44+
},
45+
};
46+
47+
functionworkspaceRouterParameters(workspace:Workspace){
48+
returnreactRouterParameters({
49+
location:{
50+
pathParams:{
51+
username:`@${workspace.owner_name}`,
52+
workspace:workspace.name,
53+
},
54+
},
55+
routing:reactRouterNestedAncestors(
56+
{
57+
path:"/:username/:workspace/settings/schedule",
58+
},
59+
<WorkspaceSettingsLayout/>,
60+
),
61+
});
62+
}
63+
64+
functionworkspaceQueries(workspace:Workspace){
65+
return[
66+
{
67+
key:workspaceByOwnerAndNameKey(workspace.owner_name,workspace.name),
68+
data:workspace,
69+
},
70+
{
71+
key:getAuthorizationKey({
72+
checks:{
73+
updateWorkspace:{
74+
object:{
75+
resource_type:"workspace",
76+
resource_id:MockWorkspace.id,
77+
owner_id:MockWorkspace.owner_id,
78+
},
79+
action:"update",
80+
},
81+
},
82+
}),
83+
data:{updateWorkspace:true},
84+
},
85+
{
86+
key:templateByNameKey(
87+
MockWorkspace.organization_id,
88+
MockWorkspace.template_name,
89+
),
90+
data:MockTemplate,
91+
},
92+
];
93+
}

‎site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Alert } from "components/Alert/Alert";
77
import{ErrorAlert}from"components/Alert/ErrorAlert";
88
import{ConfirmDialog}from"components/Dialogs/ConfirmDialog/ConfirmDialog";
99
import{displayError,displaySuccess}from"components/GlobalSnackbar/utils";
10+
import{Link}from"components/Link/Link";
1011
import{Loader}from"components/Loader/Loader";
1112
import{PageHeader,PageHeaderTitle}from"components/PageHeader/PageHeader";
1213
importdayjsfrom"dayjs";
@@ -20,6 +21,7 @@ import { type FC, useState } from "react";
2021
import{Helmet}from"react-helmet-async";
2122
import{useMutation,useQuery,useQueryClient}from"react-query";
2223
import{useNavigate,useParams}from"react-router-dom";
24+
import{docs}from"utils/docs";
2325
import{pageTitle}from"utils/page";
2426
import{WorkspaceScheduleForm}from"./WorkspaceScheduleForm";
2527
import{
@@ -32,7 +34,7 @@ const permissionsToCheck = (workspace: TypesGen.Workspace) =>
3234
updateWorkspace:{
3335
object:{
3436
resource_type:"workspace",
35-
resourceId:workspace.id,
37+
resource_id:workspace.id,
3638
owner_id:workspace.owner_id,
3739
},
3840
action:"update",
@@ -94,42 +96,62 @@ const WorkspaceSchedulePage: FC = () => {
9496
</Alert>
9597
)}
9698

97-
{template&&(
98-
<WorkspaceScheduleForm
99-
template={template}
100-
error={submitScheduleMutation.error}
101-
initialValues={{
102-
...getAutostart(workspace),
103-
...getAutostop(workspace),
104-
}}
105-
isLoading={submitScheduleMutation.isPending}
106-
defaultTTL={dayjs.duration(template.default_ttl_ms,"ms").asHours()}
107-
onCancel={()=>{
108-
navigate(`/@${username}/${workspaceName}`);
109-
}}
110-
onSubmit={async(values)=>{
111-
constdata={
112-
workspace,
113-
autostart:formValuesToAutostartRequest(values),
114-
ttl:formValuesToTTLRequest(values),
115-
autostartChanged:scheduleChanged(
116-
getAutostart(workspace),
117-
values,
118-
),
119-
autostopChanged:scheduleChanged(getAutostop(workspace),values),
120-
};
121-
122-
awaitsubmitScheduleMutation.mutateAsync(data);
123-
124-
if(
125-
data.autostopChanged&&
126-
getAutostop(workspace).autostopEnabled
127-
){
128-
setIsConfirmingApply(true);
129-
}
130-
}}
131-
/>
132-
)}
99+
{template&&
100+
(workspace.is_prebuild ?(
101+
<Alertseverity="info">
102+
Prebuilt workspaces ignore workspace-level scheduling until they are
103+
claimed. For prebuilt workspace specific scheduling refer to the{" "}
104+
<Link
105+
title="Prebuilt Workspaces Scheduling"
106+
href={docs(
107+
"/admin/templates/extending-templates/prebuilt-workspaces#scheduling",
108+
)}
109+
target="_blank"
110+
rel="noreferrer"
111+
>
112+
Prebuilt Workspaces Scheduling
113+
</Link>
114+
documentation page.
115+
</Alert>
116+
) :(
117+
<WorkspaceScheduleForm
118+
template={template}
119+
error={submitScheduleMutation.error}
120+
initialValues={{
121+
...getAutostart(workspace),
122+
...getAutostop(workspace),
123+
}}
124+
isLoading={submitScheduleMutation.isPending}
125+
defaultTTL={dayjs.duration(template.default_ttl_ms,"ms").asHours()}
126+
onCancel={()=>{
127+
navigate(`/@${username}/${workspaceName}`);
128+
}}
129+
onSubmit={async(values)=>{
130+
constdata={
131+
workspace,
132+
autostart:formValuesToAutostartRequest(values),
133+
ttl:formValuesToTTLRequest(values),
134+
autostartChanged:scheduleChanged(
135+
getAutostart(workspace),
136+
values,
137+
),
138+
autostopChanged:scheduleChanged(
139+
getAutostop(workspace),
140+
values,
141+
),
142+
};
143+
144+
awaitsubmitScheduleMutation.mutateAsync(data);
145+
146+
if(
147+
data.autostopChanged&&
148+
getAutostop(workspace).autostopEnabled
149+
){
150+
setIsConfirmingApply(true);
151+
}
152+
}}
153+
/>
154+
))}
133155

134156
<ConfirmDialog
135157
open={isConfirmingApply}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp