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

Commit564b387

Browse files
feat: add provisioner jobs into the UI (#16867)
- Add provisioner jobs back, but as a sub page of the organizationsettings- Add missing storybook tests to the componentsRelated to#15192.
1 parentcf7d143 commit564b387

21 files changed

+455
-515
lines changed

‎site/src/components/Badge/Badge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const badgeVariants = cva(
1212
variants:{
1313
variant:{
1414
default:
15-
"border-transparent bg-surface-secondary text-content-secondary shadow hover:bg-surface-tertiary",
15+
"border-transparent bg-surface-secondary text-content-secondary shadow",
1616
},
1717
size:{
1818
sm:"text-2xs font-regular",

‎site/src/modules/management/OrganizationSettingsLayout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const OrganizationSettingsContext = createContext<
2424
OrganizationSettingsValue|undefined
2525
>(undefined);
2626

27-
typeOrganizationSettingsValue=Readonly<{
27+
exporttypeOrganizationSettingsValue=Readonly<{
2828
organizations:readonlyOrganization[];
2929
organizationPermissionsByOrganizationId:Record<
3030
string,
@@ -36,9 +36,10 @@ type OrganizationSettingsValue = Readonly<{
3636

3737
exportconstuseOrganizationSettings=():OrganizationSettingsValue=>{
3838
constcontext=useContext(OrganizationSettingsContext);
39+
3940
if(!context){
4041
thrownewError(
41-
"useOrganizationSettings should be used inside of OrganizationSettingsLayout",
42+
"useOrganizationSettings should be used inside of OrganizationSettingsLayout or with the default values in case of testing.",
4243
);
4344
}
4445

‎site/src/modules/management/OrganizationSidebarView.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,18 @@ const OrganizationSettingsNavigation: FC<
186186
)}
187187
{orgPermissions.viewProvisioners&&
188188
orgPermissions.viewProvisionerJobs&&(
189-
<SettingsSidebarNavItem
190-
href={urlForSubpage(organization.name,"provisioners")}
191-
>
192-
Provisioners
193-
</SettingsSidebarNavItem>
189+
<>
190+
<SettingsSidebarNavItem
191+
href={urlForSubpage(organization.name,"provisioners")}
192+
>
193+
Provisioners
194+
</SettingsSidebarNavItem>
195+
<SettingsSidebarNavItem
196+
href={urlForSubpage(organization.name,"provisioner-jobs")}
197+
>
198+
Provisioner Jobs
199+
</SettingsSidebarNavItem>
200+
</>
194201
)}
195202
{orgPermissions.viewIdpSyncSettings&&(
196203
<SettingsSidebarNavItem

‎site/src/pages/OrganizationSettingsPage/ProvisionersPage/CancelJobButton.stories.tsxrenamed to‎site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/CancelJobButton.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { MockProvisionerJob } from "testHelpers/entities";
44
import{CancelJobButton}from"./CancelJobButton";
55

66
constmeta:Meta<typeofCancelJobButton>={
7-
title:"pages/OrganizationSettingsPage/ProvisionersPage/CancelJobButton",
7+
title:"pages/OrganizationProvisionerJobsPage/CancelJobButton",
88
component:CancelJobButton,
99
args:{
1010
job:{
@@ -28,7 +28,7 @@ export const NotCancellable: Story = {
2828
},
2929
};
3030

31-
exportconstOnClick:Story={
31+
exportconstConfirmOnClick:Story={
3232
parameters:{
3333
chromatic:{disableSnapshot:true},
3434
},

‎site/src/pages/OrganizationSettingsPage/ProvisionersPage/CancelJobConfirmationDialog.stories.tsxrenamed to‎site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/CancelJobConfirmationDialog.stories.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import { withGlobalSnackbar } from "testHelpers/storybook";
66
import{CancelJobConfirmationDialog}from"./CancelJobConfirmationDialog";
77

88
constmeta:Meta<typeofCancelJobConfirmationDialog>={
9-
title:
10-
"pages/OrganizationSettingsPage/ProvisionersPage/CancelJobConfirmationDialog",
9+
title:"pages/OrganizationProvisionerJobsPage/CancelJobConfirmationDialog",
1110
component:CancelJobConfirmationDialog,
1211
args:{
1312
open:true,
@@ -40,7 +39,7 @@ export const OnCancel: Story = {
4039
},
4140
};
4241

43-
exportconstonConfirmSuccess:Story={
42+
exportconstOnConfirmSuccess:Story={
4443
parameters:{
4544
chromatic:{disableSnapshot:true},
4645
},
@@ -60,7 +59,7 @@ export const onConfirmSuccess: Story = {
6059
},
6160
};
6261

63-
exportconstonConfirmFailure:Story={
62+
exportconstOnConfirmFailure:Story={
6463
parameters:{
6564
chromatic:{disableSnapshot:true},
6665
},
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{expect,userEvent,waitFor,within}from"@storybook/test";
3+
import{Table,TableBody}from"components/Table/Table";
4+
import{MockProvisionerJob}from"testHelpers/entities";
5+
import{daysAgo}from"utils/time";
6+
import{JobRow}from"./JobRow";
7+
8+
constmeta:Meta<typeofJobRow>={
9+
title:"pages/OrganizationProvisionerJobsPage/JobRow",
10+
component:JobRow,
11+
args:{
12+
job:{
13+
...MockProvisionerJob,
14+
created_at:daysAgo(2),
15+
},
16+
},
17+
render:(args)=>{
18+
return(
19+
<Table>
20+
<TableBody>
21+
<JobRow{...args}/>
22+
</TableBody>
23+
</Table>
24+
);
25+
},
26+
};
27+
28+
exportdefaultmeta;
29+
typeStory=StoryObj<typeofJobRow>;
30+
31+
exportconstClose:Story={};
32+
33+
exportconstOpenOnClick:Story={
34+
play:async({ canvasElement, args})=>{
35+
constcanvas=within(canvasElement);
36+
constshowMoreButton=canvas.getByRole("button",{name:/showmore/i});
37+
38+
awaituserEvent.click(showMoreButton);
39+
40+
constjobId=canvas.getByText(args.job.id);
41+
expect(jobId).toBeInTheDocument();
42+
},
43+
};
44+
45+
exportconstHideOnClick:Story={
46+
play:async({ canvasElement, args})=>{
47+
constcanvas=within(canvasElement);
48+
49+
constshowMoreButton=canvas.getByRole("button",{name:/showmore/i});
50+
awaituserEvent.click(showMoreButton);
51+
52+
consthideButton=canvas.getByRole("button",{name:/hide/i});
53+
awaituserEvent.click(hideButton);
54+
55+
constjobId=canvas.queryByText(args.job.id);
56+
expect(jobId).not.toBeInTheDocument();
57+
},
58+
};

‎site/src/pages/OrganizationSettingsPage/ProvisionersPage/ProvisionerJobsPage.tsxrenamed to‎site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/JobRow.tsx

Lines changed: 20 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,24 @@
1-
import{provisionerJobs}from"api/queries/organizations";
21
importtype{ProvisionerJob}from"api/typesGenerated";
32
import{Avatar}from"components/Avatar/Avatar";
43
import{Badge}from"components/Badge/Badge";
5-
import{Button}from"components/Button/Button";
6-
import{EmptyState}from"components/EmptyState/EmptyState";
7-
import{Link}from"components/Link/Link";
8-
import{Loader}from"components/Loader/Loader";
9-
import{
10-
Table,
11-
TableBody,
12-
TableCell,
13-
TableHead,
14-
TableHeader,
15-
TableRow,
16-
}from"components/Table/Table";
4+
import{TableCell,TableRow}from"components/Table/Table";
175
import{
186
ChevronDownIcon,
197
ChevronRightIcon,
208
TriangleAlertIcon,
219
}from"lucide-react";
2210
import{typeFC,useState}from"react";
23-
import{useQuery}from"react-query";
2411
import{cn}from"utils/cn";
25-
import{docs}from"utils/docs";
2612
import{relativeTime}from"utils/time";
2713
import{CancelJobButton}from"./CancelJobButton";
28-
import{DataGrid}from"./DataGrid";
2914
import{JobStatusIndicator}from"./JobStatusIndicator";
3015
import{Tag,Tags,TruncateTags}from"./Tags";
3116

32-
typeProvisionerJobsPageProps={
33-
orgId:string;
34-
};
35-
36-
exportconstProvisionerJobsPage:FC<ProvisionerJobsPageProps>=({
37-
orgId,
38-
})=>{
39-
const{
40-
data:jobs,
41-
isLoadingError,
42-
refetch,
43-
}=useQuery(provisionerJobs(orgId));
44-
45-
return(
46-
<sectionclassName="flex flex-col gap-8">
47-
<h2className="sr-only">Provisioner jobs</h2>
48-
<pclassName="text-sm text-content-secondary m-0 mt-2">
49-
Provisioner Jobs are the individual tasks assigned to Provisioners when
50-
the workspaces are being built.{" "}
51-
<Linkhref={docs("/admin/provisioners")}>View docs</Link>
52-
</p>
53-
54-
<Table>
55-
<TableHeader>
56-
<TableRow>
57-
<TableHead>Created</TableHead>
58-
<TableHead>Type</TableHead>
59-
<TableHead>Template</TableHead>
60-
<TableHead>Tags</TableHead>
61-
<TableHead>Status</TableHead>
62-
<TableHead/>
63-
</TableRow>
64-
</TableHeader>
65-
<TableBody>
66-
{jobs ?(
67-
jobs.length>0 ?(
68-
jobs.map((j)=><JobRowkey={j.id}job={j}/>)
69-
) :(
70-
<TableRow>
71-
<TableCellcolSpan={999}>
72-
<EmptyStatemessage="No provisioner jobs found"/>
73-
</TableCell>
74-
</TableRow>
75-
)
76-
) :isLoadingError ?(
77-
<TableRow>
78-
<TableCellcolSpan={999}>
79-
<EmptyState
80-
message="Error loading the provisioner jobs"
81-
cta={<ButtononClick={()=>refetch()}>Retry</Button>}
82-
/>
83-
</TableCell>
84-
</TableRow>
85-
) :(
86-
<TableRow>
87-
<TableCellcolSpan={999}>
88-
<Loader/>
89-
</TableCell>
90-
</TableRow>
91-
)}
92-
</TableBody>
93-
</Table>
94-
</section>
95-
);
96-
};
97-
9817
typeJobRowProps={
9918
job:ProvisionerJob;
10019
};
10120

102-
constJobRow:FC<JobRowProps>=({ job})=>{
21+
exportconstJobRow:FC<JobRowProps>=({ job})=>{
10322
constmetadata=job.metadata;
10423
const[isOpen,setIsOpen]=useState(false);
10524

@@ -133,20 +52,16 @@ const JobRow: FC<JobRowProps> = ({ job }) => {
13352
<Badgesize="sm">{job.type}</Badge>
13453
</TableCell>
13554
<TableCell>
136-
{job.metadata.template_name ?(
137-
<divclassName="flex items-center gap-1 whitespace-nowrap">
138-
<Avatar
139-
variant="icon"
140-
src={metadata.template_icon}
141-
fallback={
142-
metadata.template_display_name||metadata.template_name
143-
}
144-
/>
145-
{metadata.template_display_name??metadata.template_name}
146-
</div>
147-
) :(
148-
<spanclassName="whitespace-nowrap">Not linked</span>
149-
)}
55+
<divclassName="flex items-center gap-1 whitespace-nowrap">
56+
<Avatar
57+
variant="icon"
58+
src={metadata.template_icon}
59+
fallback={
60+
metadata.template_display_name||metadata.template_name
61+
}
62+
/>
63+
{metadata.template_display_name||metadata.template_name}
64+
</div>
15065
</TableCell>
15166
<TableCell>
15267
<TruncateTagstags={job.tags}/>
@@ -173,7 +88,13 @@ const JobRow: FC<JobRowProps> = ({ job }) => {
17388
<spanclassName="[&:first-letter]:uppercase">{job.error}</span>
17489
</div>
17590
)}
176-
<DataGrid>
91+
<dl
92+
className={cn([
93+
"text-xs text-content-secondary",
94+
"m-0 grid grid-cols-[auto_1fr] gap-x-4 items-center",
95+
"[&_dd]:text-content-primary [&_dd]:font-mono [&_dd]:leading-[22px] [&_dt]:font-medium",
96+
])}
97+
>
17798
<dt>Job ID:</dt>
17899
<dd>{job.id}</dd>
179100

@@ -206,7 +127,7 @@ const JobRow: FC<JobRowProps> = ({ job }) => {
206127
))}
207128
</Tags>
208129
</dd>
209-
</DataGrid>
130+
</dl>
210131
</TableCell>
211132
</TableRow>
212133
)}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{MockProvisionerJob}from"testHelpers/entities";
3+
import{JobStatusIndicator}from"./JobStatusIndicator";
4+
5+
constmeta:Meta<typeofJobStatusIndicator>={
6+
title:"pages/OrganizationProvisionerJobsPage/JobStatusIndicator",
7+
component:JobStatusIndicator,
8+
};
9+
10+
exportdefaultmeta;
11+
typeStory=StoryObj<typeofJobStatusIndicator>;
12+
13+
exportconstSucceeded:Story={
14+
args:{
15+
job:{
16+
...MockProvisionerJob,
17+
status:"succeeded",
18+
},
19+
},
20+
};
21+
22+
exportconstFailed:Story={
23+
args:{
24+
job:{
25+
...MockProvisionerJob,
26+
status:"failed",
27+
},
28+
},
29+
};
30+
31+
exportconstPending:Story={
32+
args:{
33+
job:{
34+
...MockProvisionerJob,
35+
status:"pending",
36+
queue_position:1,
37+
queue_size:1,
38+
},
39+
},
40+
};
41+
42+
exportconstRunning:Story={
43+
args:{
44+
job:{
45+
...MockProvisionerJob,
46+
status:"running",
47+
},
48+
},
49+
};
50+
51+
exportconstCanceling:Story={
52+
args:{
53+
job:{
54+
...MockProvisionerJob,
55+
status:"canceling",
56+
},
57+
},
58+
};
59+
60+
exportconstCanceled:Story={
61+
args:{
62+
job:{
63+
...MockProvisionerJob,
64+
status:"canceled",
65+
},
66+
},
67+
};
68+
69+
exportconstUnknown:Story={
70+
args:{
71+
job:{
72+
...MockProvisionerJob,
73+
status:"unknown",
74+
},
75+
},
76+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp