news-pubish-management(2)--right, role and user

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 => {
// console.log(res.data);
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 => {
// console.log(res.data);
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
//show confirm modal
const confirmDelete = (item) => {
confirm({
title: 'Do you Want to delete these items?',
icon: <ExclamationCircleOutlined />,
onOk() {
// console.log('OK');
realDelete(item)
},
onCancel() {
console.log('Cancel');
},
});
}

//delete item in both frontEnd and backEnd
const realDelete = (item) => {
// console.log(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) => {
// console.log(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 => {
// console.log(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 });
}
}

7. Use Table to perform role in RoleList.js

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() {
// console.log('OK');
realDelete(item)
},
onCancel() {
console.log('Cancel');
},
});
}

const realDelete = (item) => {
// console.log(item);
setDataSource(dataSource.filter(data => data.id !== item.id));
axios.delete(`/api/roles/${item.id}`);
}

useEffect(() => {
axios.get("/api/roles").then(res => {
// console.log(res.data);
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) => {
// console.log(checkedKeys);
setCurrentRights(checkedKeys);
}
...
useEffect(() => {
axios.get(`/api/rights?_embed=children`).then(res => {
// console.log(res.data);
setTreeData(res.data)
})
}, []);

8. Use Table to perform user in UserList.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
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() {
// console.log('OK');
realDelete(item)
},
onCancel() {
console.log('Cancel');
},
});
}

const realDelete = (item) => {
// console.log(item);
}

useEffect(() => {
axios.get(`/api/users?_expand=role`).then(res => {
// console.log(res.data);
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() {
// console.log('OK');
realDelete(item)
},
onCancel() {
console.log('Cancel');
},
});
}

const realDelete = (item) => {
// console.log(item);
}

useEffect(() => {
axios.get(`/api/users?_expand=role`).then(res => {
// console.log(res.data);
setDataSource(res.data);
})
}, []);

useEffect(() => {
axios.get(`/api/regions`).then(res => {
// console.log(res.data);
setRegionList(res.data);
})
}, []);

useEffect(() => {
axios.get(`/api/roles`).then(res => {
// console.log(res.data);
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>
)
}

10. Wrapper addForm as component

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={() => {
// console.log(addForm);
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 = () => {
// console.log(addForm);
addForm.current.validateFields().then(value => {
// console.log(value)
setAddFormVisible(false);
addForm.current.resetFields();
axios.post(`/api/users`,{
...value,
'roleState': true,
'default': false,
}).then(res=>{
// console.log(res.data);
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) => {
// console.log(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)=> {
// console.log(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.

1
omit

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>
},
...
}