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

Commit9c8079b

Browse files
authored
refactor: Extract workspace filter into a separate component (#2601)
1 parent929227d commit9c8079b

File tree

3 files changed

+172
-113
lines changed

3 files changed

+172
-113
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import{ComponentMeta,Story}from"@storybook/react"
2+
import{workspaceFilterQuery}from"../../util/workspace"
3+
import{SearchBarWithFilter,SearchBarWithFilterProps}from"./SearchBarWithFilter"
4+
5+
exportdefault{
6+
title:"components/SearchBarWithFilter",
7+
component:SearchBarWithFilter,
8+
argTypes:{
9+
filter:{
10+
defaultValue:workspaceFilterQuery.me,
11+
},
12+
},
13+
}asComponentMeta<typeofSearchBarWithFilter>
14+
15+
constTemplate:Story<SearchBarWithFilterProps>=(args)=><SearchBarWithFilter{...args}/>
16+
17+
exportconstWithoutPresetFilters=Template.bind({})
18+
19+
exportconstWithPresetFilters=Template.bind({})
20+
WithPresetFilters.args={
21+
presetFilters:[
22+
{query:workspaceFilterQuery.me,name:"Your workspaces"},
23+
{query:"random query",name:"Random query"},
24+
],
25+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
importButtonfrom"@material-ui/core/Button"
2+
importFadefrom"@material-ui/core/Fade"
3+
importInputAdornmentfrom"@material-ui/core/InputAdornment"
4+
importMenufrom"@material-ui/core/Menu"
5+
importMenuItemfrom"@material-ui/core/MenuItem"
6+
import{makeStyles}from"@material-ui/core/styles"
7+
importTextFieldfrom"@material-ui/core/TextField"
8+
importSearchIconfrom"@material-ui/icons/Search"
9+
import{FormikErrors,useFormik}from"formik"
10+
import{useState}from"react"
11+
import{getFormHelpers,onChangeTrimmed}from"../../util/formUtils"
12+
import{CloseDropdown,OpenDropdown}from"../DropdownArrows/DropdownArrows"
13+
import{Stack}from"../Stack/Stack"
14+
15+
exportconstLanguage={
16+
filterName:"Filters",
17+
}
18+
19+
exportinterfaceSearchBarWithFilterProps{
20+
filter?:string
21+
onFilter:(query:string)=>void
22+
presetFilters?:PresetFilter[]
23+
}
24+
25+
exportinterfacePresetFilter{
26+
name:string
27+
query:string
28+
}
29+
30+
interfaceFilterFormValues{
31+
query:string
32+
}
33+
34+
exporttypeFilterFormErrors=FormikErrors<FilterFormValues>
35+
36+
exportconstSearchBarWithFilter:React.FC<SearchBarWithFilterProps>=({ filter, onFilter, presetFilters})=>{
37+
conststyles=useStyles()
38+
39+
constform=useFormik<FilterFormValues>({
40+
enableReinitialize:true,
41+
initialValues:{
42+
query:filter??"",
43+
},
44+
onSubmit:({ query})=>{
45+
onFilter(query)
46+
},
47+
})
48+
49+
constgetFieldHelpers=getFormHelpers<FilterFormValues>(form)
50+
51+
const[anchorEl,setAnchorEl]=useState<null|HTMLElement>(null)
52+
53+
consthandleClick=(event:React.MouseEvent<HTMLButtonElement>)=>{
54+
setAnchorEl(event.currentTarget)
55+
}
56+
57+
consthandleClose=()=>{
58+
setAnchorEl(null)
59+
}
60+
61+
constsetPresetFilter=(query:string)=>()=>{
62+
voidform.setFieldValue("query",query)
63+
voidform.submitForm()
64+
handleClose()
65+
}
66+
67+
return(
68+
<Stackdirection="row"spacing={0}className={styles.filterContainer}>
69+
{presetFilters&&presetFilters.length>0&&(
70+
<Buttonaria-controls="filter-menu"aria-haspopup="true"onClick={handleClick}className={styles.buttonRoot}>
71+
{Language.filterName}{anchorEl ?<CloseDropdown/> :<OpenDropdown/>}
72+
</Button>
73+
)}
74+
75+
<formonSubmit={form.handleSubmit}className={styles.filterForm}>
76+
<TextField
77+
{...getFieldHelpers("query")}
78+
className={styles.textFieldRoot}
79+
onChange={onChangeTrimmed(form)}
80+
fullWidth
81+
variant="outlined"
82+
InputProps={{
83+
startAdornment:(
84+
<InputAdornmentposition="start">
85+
<SearchIconfontSize="small"/>
86+
</InputAdornment>
87+
),
88+
}}
89+
/>
90+
</form>
91+
92+
{presetFilters&&presetFilters.length>0&&(
93+
<Menu
94+
id="filter-menu"
95+
anchorEl={anchorEl}
96+
keepMounted
97+
open={Boolean(anchorEl)}
98+
onClose={handleClose}
99+
TransitionComponent={Fade}
100+
anchorOrigin={{
101+
vertical:"bottom",
102+
horizontal:"left",
103+
}}
104+
transformOrigin={{
105+
vertical:"top",
106+
horizontal:"left",
107+
}}
108+
>
109+
{presetFilters.map((presetFilter)=>(
110+
<MenuItemkey={presetFilter.name}onClick={setPresetFilter(presetFilter.query)}>
111+
{presetFilter.name}
112+
</MenuItem>
113+
))}
114+
</Menu>
115+
)}
116+
</Stack>
117+
)
118+
}
119+
120+
constuseStyles=makeStyles((theme)=>({
121+
filterContainer:{
122+
border:`1px solid${theme.palette.divider}`,
123+
borderRadius:theme.shape.borderRadius,
124+
marginBottom:theme.spacing(2),
125+
},
126+
filterForm:{
127+
width:"100%",
128+
},
129+
buttonRoot:{
130+
border:"none",
131+
borderRight:`1px solid${theme.palette.divider}`,
132+
borderRadius:`${theme.shape.borderRadius}px 0px 0px${theme.shape.borderRadius}px`,
133+
},
134+
textFieldRoot:{
135+
margin:"0px",
136+
"& fieldset":{
137+
border:"none",
138+
},
139+
},
140+
}))

‎site/src/pages/WorkspacesPage/WorkspacesPageView.tsx

Lines changed: 7 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,25 @@
11
importButtonfrom"@material-ui/core/Button"
2-
importFadefrom"@material-ui/core/Fade"
3-
importInputAdornmentfrom"@material-ui/core/InputAdornment"
42
importLinkfrom"@material-ui/core/Link"
5-
importMenufrom"@material-ui/core/Menu"
6-
importMenuItemfrom"@material-ui/core/MenuItem"
73
import{fade,makeStyles,Theme}from"@material-ui/core/styles"
84
importTablefrom"@material-ui/core/Table"
95
importTableBodyfrom"@material-ui/core/TableBody"
106
importTableCellfrom"@material-ui/core/TableCell"
117
importTableHeadfrom"@material-ui/core/TableHead"
128
importTableRowfrom"@material-ui/core/TableRow"
13-
importTextFieldfrom"@material-ui/core/TextField"
149
importAddCircleOutlinefrom"@material-ui/icons/AddCircleOutline"
1510
importKeyboardArrowRightfrom"@material-ui/icons/KeyboardArrowRight"
1611
importRefreshIconfrom"@material-ui/icons/Refresh"
17-
importSearchIconfrom"@material-ui/icons/Search"
1812
importuseThemefrom"@material-ui/styles/useTheme"
1913
import{useActor}from"@xstate/react"
2014
importdayjsfrom"dayjs"
2115
importrelativeTimefrom"dayjs/plugin/relativeTime"
22-
import{FormikErrors,useFormik}from"formik"
23-
import{FC,useState}from"react"
16+
import{FC}from"react"
2417
import{LinkasRouterLink,useNavigate}from"react-router-dom"
2518
import{AvatarData}from"../../components/AvatarData/AvatarData"
26-
import{CloseDropdown,OpenDropdown}from"../../components/DropdownArrows/DropdownArrows"
2719
import{EmptyState}from"../../components/EmptyState/EmptyState"
2820
import{Margins}from"../../components/Margins/Margins"
2921
import{PageHeader,PageHeaderSubtitle,PageHeaderTitle}from"../../components/PageHeader/PageHeader"
22+
import{SearchBarWithFilter}from"../../components/SearchBarWithFilter/SearchBarWithFilter"
3023
import{Stack}from"../../components/Stack/Stack"
3124
import{TableCellLink}from"../../components/TableCellLink/TableCellLink"
3225
import{TableLoader}from"../../components/TableLoader/TableLoader"
@@ -38,7 +31,6 @@ import {
3831
HelpTooltipText,
3932
HelpTooltipTitle,
4033
}from"../../components/Tooltips/HelpTooltip/HelpTooltip"
41-
import{getFormHelpers,onChangeTrimmed}from"../../util/formUtils"
4234
import{getDisplayStatus,workspaceFilterQuery}from"../../util/workspace"
4335
import{WorkspaceItemMachineRef}from"../../xServices/workspaces/workspacesXService"
4436

@@ -49,7 +41,6 @@ export const Language = {
4941
emptyCreateWorkspaceMessage:"Create your first workspace",
5042
emptyCreateWorkspaceDescription:"Start editing your source code and building your software",
5143
emptyResultsMessage:"No results matched your search",
52-
filterName:"Filters",
5344
yourWorkspacesButton:"Your workspaces",
5445
allWorkspacesButton:"All workspaces",
5546
workspaceTooltipTitle:"What is a workspace?",
@@ -154,12 +145,6 @@ const WorkspaceRow: React.FC<{ workspaceRef: WorkspaceItemMachineRef }> = ({ wor
154145
)
155146
}
156147

157-
interfaceFilterFormValues{
158-
query:string
159-
}
160-
161-
exporttypeFilterFormErrors=FormikErrors<FilterFormValues>
162-
163148
exportinterfaceWorkspacesPageViewProps{
164149
loading?:boolean
165150
workspaceRefs?:WorkspaceItemMachineRef[]
@@ -168,41 +153,10 @@ export interface WorkspacesPageViewProps {
168153
}
169154

170155
exportconstWorkspacesPageView:FC<WorkspacesPageViewProps>=({ loading, workspaceRefs, filter, onFilter})=>{
171-
conststyles=useStyles()
172-
173-
constform=useFormik<FilterFormValues>({
174-
enableReinitialize:true,
175-
initialValues:{
176-
query:filter??"",
177-
},
178-
onSubmit:({ query})=>{
179-
onFilter(query)
180-
},
181-
})
182-
183-
constgetFieldHelpers=getFormHelpers<FilterFormValues>(form)
184-
185-
const[anchorEl,setAnchorEl]=useState<null|HTMLElement>(null)
186-
187-
consthandleClick=(event:React.MouseEvent<HTMLButtonElement>)=>{
188-
setAnchorEl(event.currentTarget)
189-
}
190-
191-
consthandleClose=()=>{
192-
setAnchorEl(null)
193-
}
194-
195-
constsetYourWorkspaces=()=>{
196-
voidform.setFieldValue("query","owner:me")
197-
voidform.submitForm()
198-
handleClose()
199-
}
200-
201-
constsetAllWorkspaces=()=>{
202-
voidform.setFieldValue("query","")
203-
voidform.submitForm()
204-
handleClose()
205-
}
156+
constpresetFilters=[
157+
{query:workspaceFilterQuery.me,name:Language.yourWorkspacesButton},
158+
{query:workspaceFilterQuery.all,name:Language.allWorkspacesButton},
159+
]
206160

207161
return(
208162
<Margins>
@@ -223,48 +177,7 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({ loading, works
223177
</PageHeaderSubtitle>
224178
</PageHeader>
225179

226-
<Stackdirection="row"spacing={0}className={styles.filterContainer}>
227-
<Buttonaria-controls="filter-menu"aria-haspopup="true"onClick={handleClick}className={styles.buttonRoot}>
228-
{Language.filterName}{anchorEl ?<CloseDropdown/> :<OpenDropdown/>}
229-
</Button>
230-
231-
<formonSubmit={form.handleSubmit}className={styles.filterForm}>
232-
<TextField
233-
{...getFieldHelpers("query")}
234-
className={styles.textFieldRoot}
235-
onChange={onChangeTrimmed(form)}
236-
fullWidth
237-
variant="outlined"
238-
InputProps={{
239-
startAdornment:(
240-
<InputAdornmentposition="start">
241-
<SearchIconfontSize="small"/>
242-
</InputAdornment>
243-
),
244-
}}
245-
/>
246-
</form>
247-
248-
<Menu
249-
id="filter-menu"
250-
anchorEl={anchorEl}
251-
keepMounted
252-
open={Boolean(anchorEl)}
253-
onClose={handleClose}
254-
TransitionComponent={Fade}
255-
anchorOrigin={{
256-
vertical:"bottom",
257-
horizontal:"left",
258-
}}
259-
transformOrigin={{
260-
vertical:"top",
261-
horizontal:"left",
262-
}}
263-
>
264-
<MenuItemonClick={setYourWorkspaces}>{Language.yourWorkspacesButton}</MenuItem>
265-
<MenuItemonClick={setAllWorkspaces}>{Language.allWorkspacesButton}</MenuItem>
266-
</Menu>
267-
</Stack>
180+
<SearchBarWithFilterfilter={filter}onFilter={onFilter}presetFilters={presetFilters}/>
268181

269182
<Table>
270183
<TableHead>
@@ -328,25 +241,6 @@ const useStyles = makeStyles((theme) => ({
328241
lineHeight:`${theme.spacing(3)}px`,
329242
},
330243
},
331-
filterContainer:{
332-
border:`1px solid${theme.palette.divider}`,
333-
borderRadius:theme.shape.borderRadius,
334-
marginBottom:theme.spacing(2),
335-
},
336-
filterForm:{
337-
width:"100%",
338-
},
339-
buttonRoot:{
340-
border:"none",
341-
borderRight:`1px solid${theme.palette.divider}`,
342-
borderRadius:`${theme.shape.borderRadius}px 0px 0px${theme.shape.borderRadius}px`,
343-
},
344-
textFieldRoot:{
345-
margin:"0px",
346-
"& fieldset":{
347-
border:"none",
348-
},
349-
},
350244
clickableTableRow:{
351245
"&:hover td":{
352246
backgroundColor:fade(theme.palette.primary.light,0.1),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp