update role page

pull/289/head
vapao 2020-12-23 14:26:33 +08:00
parent 690b84584a
commit 4a856424b9
4 changed files with 92 additions and 73 deletions

View File

@ -84,9 +84,9 @@ class Role(models.Model, ModelMixin):
def to_dict(self, *args, **kwargs):
tmp = super().to_dict(*args, **kwargs)
tmp['page_perms'] = json.loads(self.page_perms) if self.page_perms else None
tmp['deploy_perms'] = json.loads(self.deploy_perms) if self.deploy_perms else None
tmp['host_perms'] = json.loads(self.host_perms) if self.host_perms else None
tmp['page_perms'] = json.loads(self.page_perms) if self.page_perms else {}
tmp['deploy_perms'] = json.loads(self.deploy_perms) if self.deploy_perms else {}
tmp['host_perms'] = json.loads(self.host_perms) if self.host_perms else []
tmp['used'] = self.user_set.count()
return tmp

View File

@ -3,82 +3,88 @@
* Copyright (c) <spug.dev@gmail.com>
* Released under the AGPL-3.0 License.
*/
import React from 'react';
import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react';
import { Modal, Form, Transfer, message, Alert } from 'antd';
import http from 'libs/http';
import { Modal, Form, Button, Tooltip, message, TreeSelect } from 'antd';
import { PlusOutlined, QuestionCircleOutlined, MinusCircleOutlined } from '@ant-design/icons';
import hostStore from 'pages/host/store';
import http from 'libs/http';
import store from './store';
import styles from './index.module.css';
@observer
class HostPerm extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
hosts: [],
apps: []
export default observer(function () {
const [loading, setLoading] = useState(false);
const [groups, setGroups] = useState([...store.record.host_perms]);
useEffect(() => {
if (hostStore.treeData.length === 0) {
hostStore.fetchGroups()
}
}
}, [])
componentDidMount() {
if (hostStore.records.length === 0) {
hostStore.fetchRecords().then(
() => this._updateRecords(hostStore.records)
)
} else {
this._updateRecords(hostStore.records)
}
}
_updateRecords = (records) => {
const hosts = records.map(x => {
return {...x, key: x.id}
});
this.setState({hosts})
};
handleSubmit = () => {
this.setState({loading: true});
http.patch('/api/account/role/', {id: store.record.id, host_perms: store.hostPerms})
function handleSubmit() {
setLoading(true);
http.patch('/api/account/role/', {id: store.record.id, host_perms: groups})
.then(res => {
message.success('操作成功');
store.hostPermVisible = false;
store.fetchRecords()
}, () => this.setState({loading: false}))
};
render() {
return (
<Modal
visible
width={800}
maskClosable={false}
title="主机权限设置"
onCancel={() => store.hostPermVisible = false}
confirmLoading={this.state.loading}
onOk={this.handleSubmit}>
<Alert
closable
showIcon
type="info"
message="小提示"
style={{width: 600, margin: '0 auto 20px', color: '#31708f !important'}}
description="主机权限将全局影响属于该角色的用户能够看到的主机。"/>
<Form.Item label="设置可访问的主机" style={{padding: '0 20px'}}>
<Transfer
showSearch
listStyle={{width: 325, maxHeight: 500, minHeight: 300}}
titles={['所有主机', '已选主机']}
dataSource={this.state.hosts}
targetKeys={store.hostPerms}
onChange={keys => store.hostPerms = keys}
filterOption={(inputValue, option) => `${option.zone}${option.name}`.toLowerCase().indexOf(inputValue.toLowerCase()) > -1}
render={item => `${item.zone} - ${item.name}(${item.hostname})`}/>
</Form.Item>
</Modal>
)
}, () => setLoading(false))
}
}
export default HostPerm
function handleChange(index, value) {
const tmp = [...groups];
if (index !== undefined) {
if (value) {
tmp[index] = value;
} else {
tmp.splice(index, 1)
}
} else {
tmp.push(undefined)
}
setGroups(tmp)
}
return (
<Modal
visible
width={400}
maskClosable={false}
title="主机权限设置"
onCancel={() => store.hostPermVisible = false}
confirmLoading={loading}
onOk={handleSubmit}>
<Form layout="vertical">
<Form.Item label={
<span>
授权访问主机组&nbsp;
<Tooltip title="主机权限将全局影响属于该角色的用户能够看到的主机。">
<QuestionCircleOutlined/>
</Tooltip>
</span>
}>
{groups.map((id, index) => (
<div className={styles.groupItem} key={index}>
<TreeSelect
value={id}
showSearch={false}
treeNodeLabelProp="name"
treeData={hostStore.treeData}
onChange={value => handleChange(index, value)}
placeholder="请选择分组"/>
{groups.length > 1 && (
<MinusCircleOutlined className={styles.delIcon} onClick={() => handleChange(index)}/>
)}
</div>
))}
</Form.Item>
<Form.Item>
<Button type="dashed" style={{width: '100%'}} onClick={() => handleChange()}>
<PlusOutlined/>添加授权主机组
</Button>
</Form.Item>
</Form>
</Modal>
)
})

View File

@ -21,4 +21,19 @@
.table td {
padding: 5px 15px;
}
.groupItem {
margin-bottom: 12px;
display: flex;
align-items: center;
}
.delIcon {
font-size: 24px;
margin-left: 10px;
}
.delIcon:hover {
color: #f5222d;
}

View File

@ -15,7 +15,6 @@ class Store {
@observable record = {};
@observable permissions = lds.cloneDeep(codes);
@observable deployRel = {};
@observable hostPerms = [];
@observable isFetching = false;
@observable formVisible = false;
@observable pagePermVisible = false;
@ -70,8 +69,7 @@ class Store {
showHostPerm = (info) => {
this.record = info;
this.hostPermVisible = true;
this.hostPerms = info['host_perms'] || []
this.hostPermVisible = true
}
}