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

Commitb831390

Browse files
committed
feat: add component stories
1 parentaaeddf6 commitb831390

File tree

5 files changed

+709
-0
lines changed

5 files changed

+709
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{chromatic}from"testHelpers/chromatic";
3+
import{
4+
MockTemplate,
5+
}from"testHelpers/entities";
6+
import{TemplateCard}from"./TemplateCard";
7+
8+
constmeta:Meta<typeofTemplateCard>={
9+
title:"modules/templates/TemplateCard",
10+
parameters:{ chromatic},
11+
component:TemplateCard,
12+
args:{
13+
template:MockTemplate,
14+
},
15+
};
16+
17+
exportdefaultmeta;
18+
typeStory=StoryObj<typeofTemplateCard>;
19+
20+
exportconstTemplate:Story={};
21+
22+
exportconstDeprecatedTemplate:Story={args:{
23+
template:{
24+
...MockTemplate,
25+
deprecated:true
26+
}
27+
},};
28+
29+
exportconstLongContentTemplate:Story={
30+
args:{
31+
template:{
32+
...MockTemplate,
33+
display_name:'Very Long Template Name',
34+
organization_name:'Very Long Organization Name',
35+
description:'This is a very long test description. This is a very long test description. This is a very long test description. This is a very long test description',
36+
active_user_count:999
37+
}
38+
},
39+
};
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{chromaticWithTablet}from"testHelpers/chromatic";
3+
import{
4+
mockApiError,
5+
MockTemplate,
6+
MockTemplateExample,
7+
MockTemplateExample2,
8+
}from"testHelpers/entities";
9+
import{TemplatesPageView}from"./TemplatesPageView";
10+
11+
constmeta:Meta<typeofTemplatesPageView>={
12+
title:"pages/MultiOrgTemplatesPage",
13+
parameters:{chromatic:chromaticWithTablet},
14+
component:TemplatesPageView,
15+
};
16+
17+
exportdefaultmeta;
18+
typeStory=StoryObj<typeofTemplatesPageView>;
19+
20+
exportconstWithTemplates:Story={
21+
args:{
22+
canCreateTemplates:true,
23+
error:undefined,
24+
templates:[
25+
MockTemplate,
26+
{
27+
...MockTemplate,
28+
active_user_count:-1,
29+
description:"🚀 Some new template that has no activity data",
30+
icon:"/icon/goland.svg",
31+
},
32+
{
33+
...MockTemplate,
34+
active_user_count:150,
35+
description:"😮 Wow, this one has a bunch of usage!",
36+
icon:"",
37+
},
38+
{
39+
...MockTemplate,
40+
description:
41+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ",
42+
},
43+
{
44+
...MockTemplate,
45+
name:"template-without-icon",
46+
display_name:"No Icon",
47+
description:"This one has no icon",
48+
icon:"",
49+
},
50+
{
51+
...MockTemplate,
52+
name:"template-without-icon-deprecated",
53+
display_name:"Deprecated No Icon",
54+
description:"This one has no icon and is deprecated",
55+
deprecated:true,
56+
deprecation_message:"This template is so old, it's deprecated",
57+
icon:"",
58+
},
59+
{
60+
...MockTemplate,
61+
name:"deprecated-template",
62+
display_name:"Deprecated",
63+
description:"Template is incompatible",
64+
},
65+
],
66+
examples:[],
67+
},
68+
};
69+
70+
exportconstEmptyCanCreate:Story={
71+
args:{
72+
canCreateTemplates:true,
73+
error:undefined,
74+
templates:[],
75+
examples:[MockTemplateExample,MockTemplateExample2],
76+
},
77+
};
78+
79+
exportconstEmptyCannotCreate:Story={
80+
args:{
81+
error:undefined,
82+
templates:[],
83+
examples:[MockTemplateExample,MockTemplateExample2],
84+
canCreateTemplates:false,
85+
},
86+
};
87+
88+
exportconstError:Story={
89+
args:{
90+
error:mockApiError({
91+
message:"Something went wrong fetching templates.",
92+
}),
93+
templates:undefined,
94+
examples:undefined,
95+
canCreateTemplates:false,
96+
},
97+
};
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
importtype{Interpolation,Theme}from"@emotion/react";
2+
importtype{FC}from"react";
3+
import{Link,useNavigate,useSearchParams}from"react-router-dom";
4+
importtype{Template,TemplateExample}from"api/typesGenerated";
5+
import{ErrorAlert}from"components/Alert/ErrorAlert";
6+
import{
7+
HelpTooltip,
8+
HelpTooltipContent,
9+
HelpTooltipLink,
10+
HelpTooltipLinksGroup,
11+
HelpTooltipText,
12+
HelpTooltipTitle,
13+
HelpTooltipTrigger,
14+
}from"components/HelpTooltip/HelpTooltip";
15+
import{Margins}from"components/Margins/Margins";
16+
import{
17+
PageHeader,
18+
PageHeaderSubtitle,
19+
PageHeaderTitle,
20+
}from"components/PageHeader/PageHeader";
21+
import{Stack}from"components/Stack/Stack";
22+
import{TemplateCard}from"modules/templates/TemplateCard/TemplateCard";
23+
import{docs}from"utils/docs";
24+
import{CreateTemplateButton}from"../CreateTemplateButton";
25+
import{EmptyTemplates}from"../EmptyTemplates";
26+
27+
exportconstLanguage={
28+
templateTooltipTitle:"What is template?",
29+
templateTooltipText:
30+
"With templates you can create a common configuration for your workspaces using Terraform.",
31+
templateTooltipLink:"Manage templates",
32+
};
33+
34+
constTemplateHelpTooltip:FC=()=>{
35+
return(
36+
<HelpTooltip>
37+
<HelpTooltipTrigger/>
38+
<HelpTooltipContent>
39+
<HelpTooltipTitle>{Language.templateTooltipTitle}</HelpTooltipTitle>
40+
<HelpTooltipText>{Language.templateTooltipText}</HelpTooltipText>
41+
<HelpTooltipLinksGroup>
42+
<HelpTooltipLinkhref={docs("/templates")}>
43+
{Language.templateTooltipLink}
44+
</HelpTooltipLink>
45+
</HelpTooltipLinksGroup>
46+
</HelpTooltipContent>
47+
</HelpTooltip>
48+
);
49+
};
50+
51+
exportinterfaceTemplatesPageViewProps{
52+
templates:Template[]|undefined;
53+
examples:TemplateExample[]|undefined;
54+
canCreateTemplates:boolean;
55+
error?:unknown;
56+
}
57+
58+
exporttypeTemplatesByOrg=Record<string,number>;
59+
60+
constgetTemplatesByOrg=(templates:Template[]):TemplatesByOrg=>{
61+
constorgs:TemplatesByOrg={
62+
all:0
63+
}
64+
65+
templates.forEach((template)=>{
66+
if(orgs[template.organization_name]){
67+
orgs[template.organization_name]+=1
68+
}else{
69+
orgs[template.organization_name]=1;
70+
}
71+
72+
orgs.all+=1;
73+
})
74+
75+
returnorgs;
76+
}
77+
78+
exportconstTemplatesPageView:FC<TemplatesPageViewProps>=({
79+
templates,
80+
examples,
81+
canCreateTemplates,
82+
error,
83+
})=>{
84+
const[urlParams]=useSearchParams();
85+
constisEmpty=templates&&templates.length===0;
86+
constnavigate=useNavigate();
87+
88+
constactiveOrg=urlParams.get("org")??"all";
89+
90+
consttemplatesByOrg=getTemplatesByOrg(templates??[]);
91+
92+
return(
93+
<Margins>
94+
<PageHeader
95+
actions={
96+
canCreateTemplates&&<CreateTemplateButtononNavigate={navigate}/>
97+
}
98+
>
99+
<PageHeaderTitle>
100+
<Stackspacing={1}direction="row"alignItems="center">
101+
Templates
102+
<TemplateHelpTooltip/>
103+
</Stack>
104+
</PageHeaderTitle>
105+
{templates&&templates.length>0&&(
106+
<PageHeaderSubtitle>
107+
Select a template to create a workspace.
108+
</PageHeaderSubtitle>
109+
)}
110+
</PageHeader>
111+
112+
{Boolean(error)&&<ErrorAlerterror={error}/>}
113+
114+
<Stackdirection="row"spacing={4}alignItems="flex-start">
115+
<Stack
116+
css={{width:208,flexShrink:0,position:"sticky",top:48}}
117+
>
118+
<spancss={styles.filterCaption}>ORGANIZATION</span>
119+
{Object.keys(templatesByOrg).map((org)=>(
120+
<Link
121+
key={org}
122+
to={`?org=${org}`}
123+
css={[
124+
styles.tagLink,
125+
org===activeOrg&&styles.tagLinkActive,
126+
]}
127+
>
128+
{org==='all' ?'All Organizations' :org} ({templatesByOrg[org]??0})
129+
</Link>
130+
))}
131+
</Stack>
132+
133+
134+
<div
135+
css={{
136+
display:"flex",
137+
flexWrap:"wrap",
138+
gap:32,
139+
height:"max-content",
140+
}}
141+
>
142+
{isEmpty ?(
143+
<EmptyTemplates
144+
canCreateTemplates={canCreateTemplates}
145+
examples={examples??[]}
146+
/>
147+
) :(templates&&
148+
templates.map((template)=>(
149+
<TemplateCard
150+
css={(theme)=>({
151+
backgroundColor:theme.palette.background.paper,
152+
})}
153+
template={template}
154+
key={template.id}
155+
/>
156+
)))}
157+
</div>
158+
</Stack>
159+
</Margins>
160+
);
161+
};
162+
163+
conststyles={
164+
filterCaption:(theme)=>({
165+
textTransform:"uppercase",
166+
fontWeight:600,
167+
fontSize:12,
168+
color:theme.palette.text.secondary,
169+
letterSpacing:"0.1em",
170+
}),
171+
tagLink:(theme)=>({
172+
color:theme.palette.text.secondary,
173+
textDecoration:"none",
174+
fontSize:14,
175+
textTransform:"capitalize",
176+
177+
"&:hover":{
178+
color:theme.palette.text.primary,
179+
},
180+
}),
181+
tagLinkActive:(theme)=>({
182+
color:theme.palette.text.primary,
183+
fontWeight:600,
184+
}),
185+
secondary:(theme)=>({
186+
color:theme.palette.text.secondary,
187+
}),
188+
actionButton:(theme)=>({
189+
transition:"none",
190+
color:theme.palette.text.secondary,
191+
"&:hover":{
192+
borderColor:theme.palette.text.primary,
193+
},
194+
}),
195+
}satisfiesRecord<string,Interpolation<Theme>>;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp