Today let perform the right and role in news-publish-management
1. Use the Table Basic  component in src/views/sandbox/right-manage/RightList.js  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import  { Table } from  'antd' ;import  axios from  'axios' ;import  React, { useEffect, useState } from  'react' export  default  function  RightList ( )  {    const  [dataSource, setDataSource] = useState([]);     const  columns = [         {             title : 'ID' ,             dataIndex : 'id' ,         },         {             title : '权限名称' ,             dataIndex : 'title' ,         },         {             title : '权限名称' ,             dataIndex : 'key' ,         },     ];     useEffect(() =>  {         axios.get("/api/rights" ).then(res  =>  {                          setDataSource(res.data);         })     }, []);     return  (         <div >              <Table  dataSource ={dataSource}  columns ={columns}  /> ;         </div >      ) } 
 
2.Custom some column, we can use render property, render proeprty must a function. function first in Ant 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const  columns = [        {             title : 'ID' ,             dataIndex : 'id' ,             render : (id )=>  <b > {id}</b >          },         {             title : '权限名称' ,             dataIndex : 'title' ,         },         {             title : '权限路径' ,             dataIndex : 'key' ,             render : (key )=> {                 return  <Tag  color ='orange' > {key}</Tag >              }         },     ]; 
 
3. Add operation column in the table component 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import  {    DeleteOutlined,     EditOutlined, } from  '@ant-design/icons' ; ...     {             title : '操作' ,             render : () =>  {                 return  <div >                      <Button  danger  shape ='circle'  icon ={ <DeleteOutlined  /> } />                     <Button  type ='primary'  shape ='circle'  icon ={ <EditOutlined  /> } />                 </div >              }         } 
 
4. Add pagenition for Table 1 <Table dataSource={dataSource} columns={columns} pagination={{ pageSize : 5  }} />; 
 
5. use Tree to display children, it is pretty easy, change the useEffect to 1 2 3 4 5 6 7 useEffect(() =>  {     axios.get("/api/rights?_embed=children" ).then(res  =>  {                  res.data.forEach((item ) =>  item.children?.length === 0  ? item.children = ""  : item.children);         setDataSource(res.data);     }) }, []); 
 
Here the Tree is not the Tree antd component, it is one of the column in RightList. 
 
6. Get and Edit in RightList.js Because delete is danger,so we popup a Model Basic  information for confirming.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const  confirmDelete = (item ) =>  {    confirm({         title : 'Do you Want to delete these items?' ,         icon : <ExclamationCircleOutlined  />  ,         onOk ( )  {                          realDelete(item)         },         onCancel ( )  {             console .log('Cancel' );         },     }); } const  realDelete = (item ) =>  {         setDataSource(dataSource.filter(data  =>  data.id !== item.id));     axios.delete(`/api/rights/${item.id} ` ); } 
 
above command can delete level 1 menu, but when we try to delete level 2 menu, then we wil encountered an issue says the data not found. How to delete level 2 menu? Let’s look back the response data. We can get the first level data according the rightId, and then filter the children, and then send delete in children table.
1 2 3 4 5 6 7 8 9 10 11 12 13 const  realDelete = (item ) =>  {         if  (item.grade === 1 ) {         setDataSource(dataSource.filter(data  =>  data.id !== item.id));         axios.delete(`/api/rights/${item.id} ` );     } else  {         const  list = dataSource.filter(data  =>  data.id === item.rightId);         list[0 ].children = list[0 ].children.filter(data  =>  data.id !== item.id);         setDataSource([...dataSource]);         axios.delete(`/api/children/${item.id} ` );     } } 
 
Another button is Edit button, edit button control the page configuration. We will chose Popover to perform this feature.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <Popover     content={<div  style ={{  textAlign:  'center ' }}>          <Switch  checked ={item.pagepermission}  onChange ={()  =>  swithPageConfiguration(item)}></Switch >      </div >  }    title="Page configuration"  trigger={item.pagepermission === undefined  ? ''  : 'click' }>     <Button  type ='primary'  shape ='circle'  icon ={ <EditOutlined  /> } disabled={item.pagepermission === undefined} /> </Popover> ... const  swithPageConfiguration = item  =>  {         item.pagepermission = item.pagepermission === 1  ? 0  : 1 ;     setDataSource([...dataSource])     if  (item.grade === 1 ) {         axios.patch(`/api/rights/${item.id} ` , { pagepermission : item.pagepermission });     } else  {         axios.patch(`/api/children/${item.id} ` , { pagepermission : item.pagepermission });     } } 
 
We already implemented the RightList, so we can refer that implement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import  { Button, Table, Modal } from  'antd' ;import  {    DeleteOutlined,     EditOutlined,     ExclamationCircleOutlined, } from  '@ant-design/icons' ; import  axios from  'axios' ;import  React, { useEffect, useState } from  'react' const  { confirm } = Modal;export  default  function  RoleList ( )  {    const  [dataSource, setDataSource] = useState([]);     const  columns = [         {             title : 'ID' ,             dataIndex : 'id' ,             render : (id ) =>  <b > {id}</b >          },         {             title : '角色名称' ,             dataIndex : 'roleName' ,         },         {             title : '操作' ,             render : item  =>  {                 return  <div >                      <Button  danger  shape ='circle'  icon ={ <DeleteOutlined  /> } onClick={() => confirmDelete(item)} />                     <Button  type ='primary'  shape ='circle'  icon ={ <EditOutlined  /> } />                 </div >              }         },     ];     const  confirmDelete = item  =>  {         confirm({             title : 'Do you Want to delete these items?' ,             icon : <ExclamationCircleOutlined  />  ,             onOk ( )  {                                  realDelete(item)             },             onCancel ( )  {                 console .log('Cancel' );             },         });     }     const  realDelete = (item ) =>  {                  setDataSource(dataSource.filter(data  =>  data.id !== item.id));         axios.delete(`/api/roles/${item.id} ` );     }     useEffect(() =>  {         axios.get("/api/roles" ).then(res  =>  {                          setDataSource(res.data);         })     }, []);     return  (         <div >              <Table  dataSource ={dataSource}  columns ={columns}  pagination ={{  pageSize:  5  }} rowKey ={item  =>  item.id} />;         </div >      ) } 
 
use Tree Basic  component to perform edit feature in RoleList.js
Also we use Modal Basic  to popup the tree.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <Modal title="Permisson Configuration"  visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}>                 <Tree                       checkable                      checkedKeys ={currentRights}                      onCheck ={handleCheck}                      checkStrictly ={true}                      treeData ={treeData}                  /> </Modal> ...     const  [treeData, setTreeData] = useState([]);     const  [currentRights, setCurrentRights] = useState([]);     const  [currentId, setCurrentId] = useState(0 );     const  [isModalVisible, setIsModalVisible] = useState(false ); ...         const  editPermission = item  =>  {         setIsModalVisible(true );         setCurrentRights(item.rights);         setCurrentId(item.id);     }     const  handleOk = () =>  {         setIsModalVisible(false );         setDataSource(dataSource.map(item => {             if (item.id == currentId) {                 return  {                     ...item,                     rights : currentRights                 }             }             return  item;         }));         axios.patch(`/api/roles/${currentId} ` ,{rights :currentRights});     }     const  handleCancel = () =>  {         setIsModalVisible(false );     }       const  handleCheck = (checkedKeys ) =>  {                  setCurrentRights(checkedKeys);     } ...     useEffect(() =>  {         axios.get(`/api/rights?_embed=children` ).then(res  =>  {                          setTreeData(res.data)         })     }, []);   
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 import  { Button, Table, Modal, Switch } from  'antd' ;import  {    DeleteOutlined,     EditOutlined,     ExclamationCircleOutlined, } from  '@ant-design/icons' ; import  axios from  'axios' ;import  React, { useEffect, useState } from  'react' const  { confirm } = Modal;export  default  function  UserList ( )  {    const  [dataSource, setDataSource] = useState([]);     const  columns = [         {             title : '区域' ,             dataIndex : 'region' ,             render : (region ) =>  <b > {region === '' ? 'Global' : region}</b >          },         {             title : '角色名称' ,             dataIndex : 'role' ,             render : role  =>  {                 return  role?.roleName             }         },         {             title : '用户名' ,             dataIndex : 'username' ,         },         {             title : '用户状态' ,             dataIndex : 'roleState' ,             render : (roleState, item ) =>  {                 return  <Switch  checked ={roleState}  disabled ={item.default}  > </Switch >              }         },         {             title : '操作' ,             render : item  =>  {                 return  <div >                      <Button  danger  shape ='circle'  icon ={ <DeleteOutlined  /> } disabled={item.default} onClick={() => confirmDelete(item)} />                     <Button  type ='primary'  shape ='circle'  icon ={ <EditOutlined  /> } disabled={item.default} />                 </div >              }         },     ];     const  confirmDelete = item  =>  {         confirm({             title : 'Do you Want to delete these items?' ,             icon : <ExclamationCircleOutlined  />  ,             onOk ( )  {                                  realDelete(item)             },             onCancel ( )  {                 console .log('Cancel' );             },         });     }     const  realDelete = (item ) =>  {              }     useEffect(() =>  {         axios.get(`/api/users?_expand=role` ).then(res  =>  {                          res.data.forEach((item ) =>  item.children?.length === 0  ? item.children = ""  : item.children);             setDataSource(res.data);         })     }, []);     return  (         <div >              <Table  dataSource ={dataSource}  columns ={columns}  pagination ={{  pageSize:  5  }} rowKey ={item  =>  item.id} />;         </div >      ) } 
 
9. CRUD user in UserList.js use Form in Modal  component to perform this feature.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 import  { Button, Table, Modal, Switch, Form, Input, Select } from  'antd' ;import  {    DeleteOutlined,     EditOutlined,     ExclamationCircleOutlined, } from  '@ant-design/icons' ; import  axios from  'axios' ;import  React, { useEffect, useState } from  'react' const  { confirm } = Modal;const  { Option } = Select;export  default  function  UserList ( )  {    const  [dataSource, setDataSource] = useState([]);     const  [regionList, setRegionList] = useState([]);     const  [roleList, setRoleList] = useState([]);     const  [addFormVisible, setAddFormVisible] = useState(false )     const  columns = [         {             title : '区域' ,             dataIndex : 'region' ,             render : (region ) =>  <b > {region === '' ? 'Global' : region}</b >          },         {             title : '角色名称' ,             dataIndex : 'role' ,             render : role  =>  {                 return  role?.roleName             }         },         {             title : '用户名' ,             dataIndex : 'username' ,         },         {             title : '用户状态' ,             dataIndex : 'roleState' ,             render : (roleState, item ) =>  {                 return  <Switch  checked ={roleState}  disabled ={item.default}  > </Switch >              }         },         {             title : '操作' ,             render : item  =>  {                 return  <div >                      <Button  danger  shape ='circle'  icon ={ <DeleteOutlined  /> } disabled={item.default} onClick={() => confirmDelete(item)} />                     <Button  type ='primary'  shape ='circle'  icon ={ <EditOutlined  /> } disabled={item.default} />                 </div >              }         },     ];     const  confirmDelete = item  =>  {         confirm({             title : 'Do you Want to delete these items?' ,             icon : <ExclamationCircleOutlined  />  ,             onOk ( )  {                                  realDelete(item)             },             onCancel ( )  {                 console .log('Cancel' );             },         });     }     const  realDelete = (item ) =>  {              }     useEffect(() =>  {         axios.get(`/api/users?_expand=role` ).then(res  =>  {                          setDataSource(res.data);         })     }, []);     useEffect(() =>  {         axios.get(`/api/regions` ).then(res  =>  {                          setRegionList(res.data);         })     }, []);     useEffect(() =>  {         axios.get(`/api/roles` ).then(res  =>  {                          setRoleList(res.data);         })     }, []);     return  (         <div >              <Button  type ='primary'  onClick ={()  =>  setAddFormVisible(true)}>Add new user</Button >              <Table  dataSource ={dataSource}  columns ={columns}  pagination ={{  pageSize:  5  }} rowKey ={item  =>  item.id} />;             <Modal                   visible ={addFormVisible}                  title ="Create a new user"                  okText ="Create"                  cancelText ="Cancel"                  onCancel ={()  =>  setAddFormVisible(false)}                onOk={() => {                     setAddFormVisible(false);                 }}>                 <Form  layout ="vertical" >                      <Form.Item                           name ="username"                          label ="User Name"                          rules ={[{  required:  true , message:  'Please  input  the  user  name !' }]}>                         <Input  />                      </Form.Item >                      <Form.Item                           name ="password"                          label ="Password"                          rules ={[{  required:  true , message:  'Please  input  the  password !' }]}>                         <Input  />                      </Form.Item >                      <Form.Item                           name ="region"                          label ="Region"                          rules ={[{  required:  true , message:  'Please  input  the  region !' }]}>                         <Select >                              {                                 regionList.map(item =>                                     <Option  value ={item.value}  key ={item.id} > {item.title}</Option >                                  )                             }                         </Select >                      </Form.Item >                      <Form.Item                           name ="roleId"                          label ="Role"                          rules ={[{  required:  true , message:  'Please  input  the  role !' }]}>                         <Select >                              {                                 roleList.map(item =>                                     <Option  value ={item.id}  key ={item.id} > {item.roleName}</Option >                                  )                             }                         </Select >                      </Form.Item >                  </Form >              </Modal >          </div >      ) } 
 
1 2 mkdir src/components/user-manage touch src/components/user-manage/UserForm.js 
 
Copy the Form section to this file.
use forwardRef for exporting UserForm.js for communicating with UserList.js
 
create a ref in UserList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import  React, { useRef } from  'react' ... const  addForm = useRef(null );... <Modal     visible={addFormVisible}     title="Create a new user"      okText="Create"      cancelText="Cancel"      onCancel={() =>  setAddFormVisible(false )}     onOk={() =>  {                  addForm.current.validateFields().then(value  =>  {             console .log(value)         }).catch(err  =>  {             console .log(err);         })     }}>     <UserForm  regionList ={regionList}  roleList ={roleList}  ref ={addForm}  />  </Modal>     
 
The UserForm.js we change the definition formation
1 2 3 4 5 6 7 8 const  UserForm = forwardRef((props, ref ) =>  {    return  (         <Form  layout ="vertical"  ref ={ref}  >          ...         </Form >      ) }); export  default  UserForm;        
 
we can set the modalOk as below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const  addFormOk = () =>  {                 addForm.current.validateFields().then(value  =>  {                          setAddFormVisible(false );             addForm.current.resetFields();             axios.post(`/api/users` ,{                 ...value,                 'roleState' : true ,                 'default' : false ,             }).then(res => {                                  setDataSource([...dataSource, {...res.data,                 role : roleList.filter(item => item.id=value.roleId)[0 ]}])             })         }).catch(err  =>  {             console .log(err);         })     } 
 
Delete user in UserList.js
1 2 3 4 5 const  realDelete = (item ) =>  {           setDataSource(dataSource.filter(data => data.id!==item.id));      axios.delete(`/api/users/${item.id} ` );  } 
 
Update user status in UserList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14     {         title : '用户状态' ,         dataIndex : 'roleState' ,         render : (roleState, item ) =>  {             return  <Switch  checked ={roleState}  disabled ={item.default}  onChange ={()  =>  handleUserState(item)} ></Switch >          }     },     .... const  handleUserState = (item )=>  {         item.roleState = !item.roleState;     setDataSource([...dataSource])     axios.patch(`/api/users/${item.id} ` ,{roleState :item.roleState}); } 
 
Update user in UserList.js It is very similar with addForm, so copy an updateForm modal.
 
Filter data in region field  in UserList.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const  columns = [    {         title : '区域' ,         dataIndex : 'region' ,         filters : [             ...regionList.map(item  =>  ({                 text : item.title,                 value : item.value             })),             {                 text : 'Global' ,                 value : ''              }         ],         onFilter : (value, item ) =>  item.region === value,         render : (region ) =>  <b > {region === '' ? 'Global' : region}</b >      },     ...     }