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

Commitdda6bdc

Browse files
authored
feat: group provisioners by authentication method (#14580)
1 parentd96adad commitdda6bdc

File tree

6 files changed

+382
-23
lines changed

6 files changed

+382
-23
lines changed

‎site/src/modules/provisioners/Provisioner.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export const Provisioner: FC<ProvisionerProps> = ({
6767
display:"flex",
6868
flexWrap:"wrap",
6969
gap:12,
70+
justifyContent:"right",
7071
}}
7172
>
7273
<Tooltiptitle="Scope">
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import{useTheme}from"@emotion/react";
2+
importBusinessfrom"@mui/icons-material/Business";
3+
importPersonfrom"@mui/icons-material/Person";
4+
importButtonfrom"@mui/material/Button";
5+
importTooltipfrom"@mui/material/Tooltip";
6+
importtype{BuildInfoResponse,ProvisionerDaemon}from"api/typesGenerated";
7+
import{DropdownArrow}from"components/DropdownArrow/DropdownArrow";
8+
import{Pill}from"components/Pill/Pill";
9+
import{typeFC,useState}from"react";
10+
import{createDayString}from"utils/createDayString";
11+
import{ProvisionerTag}from"./ProvisionerTag";
12+
13+
typeProvisionerGroupType="builtin"|"psk"|"key";
14+
15+
interfaceProvisionerGroupProps{
16+
readonlybuildInfo?:BuildInfoResponse;
17+
readonlykeyName?:string;
18+
readonlytype:ProvisionerGroupType;
19+
readonlyprovisioners:ProvisionerDaemon[];
20+
}
21+
22+
exportconstProvisionerGroup:FC<ProvisionerGroupProps>=({
23+
buildInfo,
24+
keyName,
25+
type,
26+
provisioners,
27+
})=>{
28+
const[provisioner]=provisioners;
29+
consttheme=useTheme();
30+
31+
const[showDetails,setShowDetails]=useState(false);
32+
33+
constdaemonScope=provisioner.tags.scope||"organization";
34+
consticonScope=daemonScope==="organization" ?<Business/> :<Person/>;
35+
36+
constprovisionerVersion=provisioner.version;
37+
constallProvisionersAreSameVersion=provisioners.every(
38+
(provisioner)=>provisioner.version===provisionerVersion,
39+
);
40+
constupToDate=
41+
allProvisionersAreSameVersion&&buildInfo?.version===provisioner.version;
42+
constprovisionerCount=
43+
provisioners.length===1
44+
?"1 provisioner"
45+
:`${provisioners.length} provisioners`;
46+
47+
constextraTags=Object.entries(provisioner.tags).filter(
48+
([key])=>key!=="scope"&&key!=="owner",
49+
);
50+
51+
return(
52+
<div
53+
css={{
54+
borderRadius:8,
55+
border:`1px solid${theme.palette.divider}`,
56+
fontSize:14,
57+
}}
58+
>
59+
<header
60+
css={{
61+
padding:24,
62+
display:"flex",
63+
alignItems:"center",
64+
justifyContenxt:"space-between",
65+
gap:24,
66+
}}
67+
>
68+
<div
69+
css={{
70+
display:"flex",
71+
alignItems:"center",
72+
gap:24,
73+
objectFit:"fill",
74+
}}
75+
>
76+
{type==="builtin"&&(
77+
<divcss={{lineHeight:"160%"}}>
78+
<h4css={{fontWeight:500,margin:0}}>
79+
Built-in provisioners
80+
</h4>
81+
<spancss={{color:theme.palette.text.secondary}}>
82+
{provisionerCount} &mdash; Built-in
83+
</span>
84+
</div>
85+
)}
86+
{type==="psk"&&(
87+
<divcss={{lineHeight:"160%"}}>
88+
<h4css={{fontWeight:500,margin:0}}>PSK provisioners</h4>
89+
<spancss={{color:theme.palette.text.secondary}}>
90+
{provisionerCount} &mdash;{" "}
91+
{allProvisionersAreSameVersion ?(
92+
<code>{provisionerVersion}</code>
93+
) :(
94+
<span>Multiple versions</span>
95+
)}
96+
</span>
97+
</div>
98+
)}
99+
{type==="key"&&(
100+
<divcss={{lineHeight:"160%"}}>
101+
<h4css={{fontWeight:500,margin:0}}>
102+
Key group &ndash;{keyName}
103+
</h4>
104+
<spancss={{color:theme.palette.text.secondary}}>
105+
{provisionerCount} &mdash;{" "}
106+
{allProvisionersAreSameVersion ?(
107+
<code>{provisionerVersion}</code>
108+
) :(
109+
<span>Multiple versions</span>
110+
)}
111+
</span>
112+
</div>
113+
)}
114+
</div>
115+
<div
116+
css={{
117+
marginLeft:"auto",
118+
display:"flex",
119+
flexWrap:"wrap",
120+
gap:12,
121+
justifyContent:"right",
122+
}}
123+
>
124+
<Tooltiptitle="Scope">
125+
<Pillsize="lg"icon={iconScope}>
126+
<span
127+
css={{
128+
":first-letter":{textTransform:"uppercase"},
129+
}}
130+
>
131+
{daemonScope}
132+
</span>
133+
</Pill>
134+
</Tooltip>
135+
{type==="key"&&
136+
extraTags.map(([key,value])=>(
137+
<ProvisionerTagkey={key}tagName={key}tagValue={value}/>
138+
))}
139+
</div>
140+
</header>
141+
142+
{showDetails&&(
143+
<div
144+
css={{
145+
padding:"0 24px 24px",
146+
display:"flex",
147+
gap:12,
148+
flexWrap:"wrap",
149+
}}
150+
>
151+
{provisioners.map((provisioner)=>(
152+
<div
153+
key={provisioner.id}
154+
css={{
155+
borderRadius:8,
156+
border:`1px solid${theme.palette.divider}`,
157+
fontSize:14,
158+
padding:"12px 18px",
159+
width:310,
160+
}}
161+
>
162+
<divcss={{lineHeight:"160%"}}>
163+
<h4css={{fontWeight:500,margin:0}}>{provisioner.name}</h4>
164+
<spancss={{color:theme.palette.text.secondary}}>
165+
{type==="builtin" ?(
166+
<span>Built-in</span>
167+
) :(
168+
<>
169+
{upToDate ?"Up to date" :provisioner.version} &mdash;{" "}
170+
{provisioner.last_seen_at&&(
171+
<spandata-chromatic="ignore">
172+
Last seen{createDayString(provisioner.last_seen_at)}
173+
</span>
174+
)}
175+
</>
176+
)}
177+
</span>
178+
</div>
179+
</div>
180+
))}
181+
</div>
182+
)}
183+
184+
<div
185+
css={{
186+
borderTop:`1px solid${theme.palette.divider}`,
187+
display:"flex",
188+
alignItems:"center",
189+
justifyContent:"space-between",
190+
padding:"8px 8px 8px 24px",
191+
fontSize:12,
192+
color:theme.palette.text.secondary,
193+
}}
194+
>
195+
<span>No warnings from{provisionerCount}</span>
196+
<Button
197+
variant="text"
198+
css={{
199+
display:"flex",
200+
alignItems:"center",
201+
gap:4,
202+
color:theme.roles.info.text,
203+
fontSize:"inherit",
204+
}}
205+
onClick={()=>setShowDetails((it)=>!it)}
206+
>
207+
{showDetails ?"Hide" :"Show"} provisioner details{" "}
208+
<DropdownArrowclose={showDetails}/>
209+
</Button>
210+
</div>
211+
</div>
212+
);
213+
};

‎site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,72 @@
1+
import{buildInfo}from"api/queries/buildInfo";
12
import{
23
organizationsPermissions,
34
provisionerDaemons,
45
}from"api/queries/organizations";
5-
importtype{Organization}from"api/typesGenerated";
6+
importtype{Organization,ProvisionerDaemon}from"api/typesGenerated";
67
import{ErrorAlert}from"components/Alert/ErrorAlert";
78
import{EmptyState}from"components/EmptyState/EmptyState";
89
import{Loader}from"components/Loader/Loader";
10+
import{useEmbeddedMetadata}from"hooks/useEmbeddedMetadata";
911
importNotFoundPagefrom"pages/404Page/404Page";
1012
importtype{FC}from"react";
1113
import{useQuery}from"react-query";
1214
import{useParams}from"react-router-dom";
1315
import{useOrganizationSettings}from"./ManagementSettingsLayout";
14-
import{OrganizationProvisionersPageView}from"./OrganizationProvisionersPageView";
16+
import{
17+
OrganizationProvisionersPageView,
18+
typeProvisionersByGroup,
19+
}from"./OrganizationProvisionersPageView";
20+
21+
constProvisionerKeyIDBuiltIn="00000000-0000-0000-0000-000000000001";
22+
constProvisionerKeyIDUserAuth="00000000-0000-0000-0000-000000000002";
23+
constProvisionerKeyIDPSK="00000000-0000-0000-0000-000000000003";
24+
25+
functiongroupProvisioners(
26+
provisioners:readonlyProvisionerDaemon[],
27+
):ProvisionersByGroup{
28+
constgroups:ProvisionersByGroup={
29+
builtin:[],
30+
psk:[],
31+
userAuth:[],
32+
keys:newMap(),
33+
};
34+
// NOTE: I'll fix this at the end of the PR chain
35+
constkeyName="TODO";
36+
37+
for(constitofprovisioners){
38+
if(it.key_id===ProvisionerKeyIDBuiltIn){
39+
groups.builtin.push(it);
40+
continue;
41+
}
42+
if(it.key_id===ProvisionerKeyIDPSK){
43+
groups.psk.push(it);
44+
continue;
45+
}
46+
if(it.key_id===ProvisionerKeyIDUserAuth){
47+
groups.userAuth.push(it);
48+
continue;
49+
}
50+
51+
constkeyGroup=groups.keys.get(keyName)??[];
52+
if(!groups.keys.has(keyName)){
53+
groups.keys.set(keyName,keyGroup);
54+
}
55+
keyGroup.push(it);
56+
}
57+
58+
returngroups;
59+
}
1560

1661
constOrganizationProvisionersPage:FC=()=>{
1762
const{organization:organizationName}=useParams()as{
1863
organization:string;
1964
};
2065
const{ organizations}=useOrganizationSettings();
2166

67+
const{ metadata}=useEmbeddedMetadata();
68+
constbuildInfoQuery=useQuery(buildInfo(metadata["build-info"]));
69+
2270
constorganization=organizations
2371
?getOrganizationByName(organizations,organizationName)
2472
:undefined;
@@ -54,7 +102,12 @@ const OrganizationProvisionersPage: FC = () => {
54102
return<NotFoundPage/>;
55103
}
56104

57-
return<OrganizationProvisionersPageViewprovisioners={provisioners}/>;
105+
return(
106+
<OrganizationProvisionersPageView
107+
buildInfo={buildInfoQuery.data}
108+
provisioners={groupProvisioners(provisioners)}
109+
/>
110+
);
58111
};
59112

60113
exportdefaultOrganizationProvisionersPage;
Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,49 @@
11
importtype{Meta,StoryObj}from"@storybook/react";
2-
import{MockProvisioner,MockUserProvisioner}from"testHelpers/entities";
2+
import{
3+
MockBuildInfo,
4+
MockProvisioner,
5+
MockProvisioner2,
6+
MockProvisionerWithTags,
7+
MockUserProvisioner,
8+
}from"testHelpers/entities";
39
import{OrganizationProvisionersPageView}from"./OrganizationProvisionersPageView";
410

511
constmeta:Meta<typeofOrganizationProvisionersPageView>={
612
title:"pages/OrganizationProvisionersPage",
713
component:OrganizationProvisionersPageView,
14+
args:{
15+
buildInfo:MockBuildInfo,
16+
},
817
};
918

1019
exportdefaultmeta;
1120
typeStory=StoryObj<typeofOrganizationProvisionersPageView>;
1221

1322
exportconstProvisioners:Story={
1423
args:{
15-
provisioners:[
16-
MockProvisioner,
17-
MockUserProvisioner,
18-
{
19-
...MockProvisioner,
20-
tags:{
21-
...MockProvisioner.tags,
22-
都市:"ユタ",
23-
きっぷ:"yes",
24-
ちいさい:"no",
25-
},
26-
},
27-
],
24+
provisioners:{
25+
builtin:[MockProvisioner,MockProvisioner2],
26+
psk:[MockProvisioner,MockUserProvisioner,MockProvisionerWithTags],
27+
userAuth:[],
28+
keys:newMap([
29+
[
30+
"ケイラ",
31+
[
32+
{
33+
...MockProvisioner,
34+
tags:{
35+
...MockProvisioner.tags,
36+
都市:"ユタ",
37+
きっぷ:"yes",
38+
ちいさい:"no",
39+
},
40+
warnings:[
41+
{code:"EUNKNOWN",message:"私は日本語が話せません"},
42+
],
43+
},
44+
],
45+
],
46+
]),
47+
},
2848
},
2949
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp