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

Commit7534328

Browse files
feat: Add user menu on users table (#1222)
1 parenta71f393 commit7534328

File tree

5 files changed

+116
-7
lines changed

5 files changed

+116
-7
lines changed

‎site/src/components/Table/Table.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,21 @@ export interface TableProps<T> {
4040
* Optional empty state UI when the data is empty
4141
*/
4242
emptyState?:React.ReactElement
43+
/**
44+
* Optional element to render row actions like delete, update, etc
45+
*/
46+
rowMenu?:(data:T)=>React.ReactElement
4347
}
4448

45-
exportconstTable=<T,>({ columns, data, emptyState, title}:TableProps<T>):React.ReactElement=>{
49+
exportconstTable=<T,>({ columns, data, emptyState, title, rowMenu}:TableProps<T>):React.ReactElement=>{
4650
constcolumnNames=columns.map(({ name})=>name)
47-
constbody=renderTableBody(data,columns,emptyState)
51+
constbody=renderTableBody(data,columns,emptyState,rowMenu)
4852

4953
return(
5054
<MuiTable>
5155
<TableHead>
5256
{title&&<TableTitletitle={title}/>}
53-
<TableHeaderscolumns={columnNames}/>
57+
<TableHeaderscolumns={columnNames}hasMenu={!!rowMenu}/>
5458
</TableHead>
5559
{body}
5660
</MuiTable>
@@ -60,7 +64,12 @@ export const Table = <T,>({ columns, data, emptyState, title }: TableProps<T>):
6064
/**
6165
* Helper function to render the table data, falling back to an empty state if available
6266
*/
63-
constrenderTableBody=<T,>(data:T[],columns:Column<T>[],emptyState?:React.ReactElement)=>{
67+
constrenderTableBody=<T,>(
68+
data:T[],
69+
columns:Column<T>[],
70+
emptyState?:React.ReactElement,
71+
rowMenu?:(data:T)=>React.ReactElement,
72+
)=>{
6473
if(data.length>0){
6574
constrows=data.map((item:T,index)=>{
6675
constcells=columns.map((column)=>{
@@ -70,7 +79,12 @@ const renderTableBody = <T,>(data: T[], columns: Column<T>[], emptyState?: React
7079
return<TableCellkey={String(column.key)}>{String(item[column.key]).toString()}</TableCell>
7180
}
7281
})
73-
return<TableRowkey={index}>{cells}</TableRow>
82+
return(
83+
<TableRowkey={index}>
84+
{cells}
85+
{rowMenu&&<TableCell>{rowMenu(item)}</TableCell>}
86+
</TableRow>
87+
)
7488
})
7589
return<TableBody>{rows}</TableBody>
7690
}else{

‎site/src/components/TableHeaders/TableHeaders.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import React from "react"
55

66
exportinterfaceTableHeadersProps{
77
columns:string[]
8+
hasMenu?:boolean
89
}
910

10-
exportconstTableHeaders:React.FC<TableHeadersProps>=({ columns})=>{
11+
exportconstTableHeaders:React.FC<TableHeadersProps>=({ columns, hasMenu})=>{
1112
conststyles=useStyles()
1213
return(
1314
<TableRowclassName={styles.root}>
@@ -16,6 +17,8 @@ export const TableHeaders: React.FC<TableHeadersProps> = ({ columns }) => {
1617
{c}
1718
</TableCell>
1819
))}
20+
{/* 1% is a trick to make the table cell width fit the content */}
21+
{hasMenu&&<TableCellwidth="1%"/>}
1922
</TableRow>
2023
)
2124
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import{ComponentMeta,Story}from"@storybook/react"
2+
importReactfrom"react"
3+
import{TableRowMenu,TableRowMenuProps}from"./TableRowMenu"
4+
5+
exportdefault{
6+
title:"components/TableRowMenu",
7+
component:TableRowMenu,
8+
}asComponentMeta<typeofTableRowMenu>
9+
10+
typeDataType={
11+
id:string
12+
}
13+
14+
constTemplate:Story<TableRowMenuProps<DataType>>=(args)=><TableRowMenu{...args}/>
15+
16+
exportconstExample=Template.bind({})
17+
Example.args={
18+
data:{id:"123"},
19+
menuItems:[
20+
{label:"Suspend",onClick:(data)=>alert(data.id)},
21+
{label:"Update",onClick:(data)=>alert(data.id)},
22+
{label:"Delete",onClick:(data)=>alert(data.id)},
23+
],
24+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
importIconButtonfrom"@material-ui/core/IconButton"
2+
importMenu,{MenuProps}from"@material-ui/core/Menu"
3+
importMenuItemfrom"@material-ui/core/MenuItem"
4+
importMoreVertIconfrom"@material-ui/icons/MoreVert"
5+
importReactfrom"react"
6+
7+
exportinterfaceTableRowMenuProps<TData>{
8+
data:TData
9+
menuItems:Array<{
10+
label:string
11+
onClick:(data:TData)=>void
12+
}>
13+
}
14+
15+
exportconstTableRowMenu=<T,>({ data, menuItems}:TableRowMenuProps<T>):JSX.Element=>{
16+
const[anchorEl,setAnchorEl]=React.useState<MenuProps["anchorEl"]>(null)
17+
18+
consthandleClick=(event:React.MouseEvent)=>{
19+
setAnchorEl(event.currentTarget)
20+
}
21+
22+
consthandleClose=()=>{
23+
setAnchorEl(null)
24+
}
25+
26+
return(
27+
<>
28+
<IconButtonsize="small"aria-label="more"aria-controls="long-menu"aria-haspopup="true"onClick={handleClick}>
29+
<MoreVertIcon/>
30+
</IconButton>
31+
<Menuid="simple-menu"anchorEl={anchorEl}keepMountedopen={Boolean(anchorEl)}onClose={handleClose}>
32+
{menuItems.map((item)=>(
33+
<MenuItem
34+
key={item.label}
35+
onClick={()=>{
36+
handleClose()
37+
item.onClick(data)
38+
}}
39+
>
40+
{item.label}
41+
</MenuItem>
42+
))}
43+
</Menu>
44+
</>
45+
)
46+
}

‎site/src/components/UsersTable/UsersTable.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import React from "react"
22
import{UserResponse}from"../../api/types"
33
import{EmptyState}from"../EmptyState/EmptyState"
44
import{Column,Table}from"../Table/Table"
5+
import{TableRowMenu}from"../TableRowMenu/TableRowMenu"
56
import{UserCell}from"../UserCell/UserCell"
67

78
constLanguage={
89
pageTitle:"Users",
910
usersTitle:"All users",
1011
emptyMessage:"No users found",
1112
usernameLabel:"User",
13+
suspendMenuItem:"Suspend",
1214
}
1315

1416
constemptyState=<EmptyStatemessage={Language.emptyMessage}/>
@@ -28,5 +30,25 @@ export interface UsersTableProps {
2830
}
2931

3032
exportconstUsersTable:React.FC<UsersTableProps>=({ users})=>{
31-
return<Tablecolumns={columns}data={users}title={Language.usersTitle}emptyState={emptyState}/>
33+
return(
34+
<Table
35+
columns={columns}
36+
data={users}
37+
title={Language.usersTitle}
38+
emptyState={emptyState}
39+
rowMenu={(user)=>(
40+
<TableRowMenu
41+
data={user}
42+
menuItems={[
43+
{
44+
label:Language.suspendMenuItem,
45+
onClick:()=>{
46+
// TO-DO: Add suspend action here
47+
},
48+
},
49+
]}
50+
/>
51+
)}
52+
/>
53+
)
3254
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp