U both add host categories

pull/22/head
雷二猛 2019-11-19 14:23:12 +08:00
parent 7925e4ce0b
commit 18f5d07d76
5 changed files with 61 additions and 11 deletions

View File

@ -9,7 +9,8 @@ from libs import human_time
class HostView(View): class HostView(View):
def get(self, request): def get(self, request):
hosts = Host.objects.filter(deleted_by_id__isnull=True) hosts = Host.objects.filter(deleted_by_id__isnull=True)
return json_response(hosts) zones = [x['zone'] for x in hosts.order_by('zone').values('zone').distinct()]
return json_response({'zones': zones, 'hosts': [x.to_dict() for x in hosts]})
def post(self, request): def post(self, request):
form, error = JsonParser( form, error = JsonParser(

View File

@ -1,14 +1,17 @@
import React from 'react'; import React from 'react';
import { Modal, Form, Input, message } from 'antd'; import { observer } from 'mobx-react';
import { Modal, Form, Input, Select, Col, Button, message } from 'antd';
import http from 'libs/http'; import http from 'libs/http';
import store from './store'; import store from './store';
@observer
class ComForm extends React.Component { class ComForm extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
loading: false, loading: false,
password: null, password: null,
zone: null,
} }
} }
@ -56,6 +59,28 @@ class ComForm extends React.Component {
) )
}; };
handleAddZone = () => {
Modal.confirm({
icon: 'exclamation-circle',
title: '添加主机类别',
content: this.addZoneForm,
onOk: () => {
if (this.state.zone) {
store.zones.push(this.state.zone);
this.props.form.setFieldsValue({'zone': this.state.zone})
}
},
})
};
addZoneForm = (
<Form>
<Form.Item required label="主机类别">
<Input onChange={val => this.setState({zone: val.target.value})}/>
</Form.Item>
</Form>
);
render() { render() {
const info = store.record; const info = store.record;
const {getFieldDecorator} = this.props.form; const {getFieldDecorator} = this.props.form;
@ -79,9 +104,18 @@ class ComForm extends React.Component {
onOk={this.handleSubmit}> onOk={this.handleSubmit}>
<Form> <Form>
<Form.Item {...itemLayout} required label="主机类别"> <Form.Item {...itemLayout} required label="主机类别">
<Col span={16}>
{getFieldDecorator('zone', {initialValue: info['zone']})( {getFieldDecorator('zone', {initialValue: info['zone']})(
<Input placeholder="请输入主机类别/区域/分组"/> <Select placeholder="请选择主机类别/区域/分组">
{store.zones.map(item => (
<Select.Option value={item} key={item}>{item}</Select.Option>
))}
</Select>
)} )}
</Col>
<Col span={6} offset={2}>
<Button type="link" onClick={this.handleAddZone}>添加类别</Button>
</Col>
</Form.Item> </Form.Item>
<Form.Item {...itemLayout} required label="主机别名"> <Form.Item {...itemLayout} required label="主机别名">
{getFieldDecorator('name', {initialValue: info['name']})( {getFieldDecorator('name', {initialValue: info['name']})(

View File

@ -61,6 +61,9 @@ class ComTable extends React.Component {
if (store.f_name) { if (store.f_name) {
data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase())) data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase()))
} }
if (store.f_zone) {
data = data.filter(item => item['zone'].toLowerCase().includes(store.f_zone.toLowerCase()))
}
return ( return (
<React.Fragment> <React.Fragment>
<Table rowKey="id" loading={store.isFetching} dataSource={data} columns={this.columns}/> <Table rowKey="id" loading={store.isFetching} dataSource={data} columns={this.columns}/>

View File

@ -1,15 +1,23 @@
import React from 'react'; import React from 'react';
import { Card, Input, Button } from 'antd'; import { observer } from 'mobx-react';
import { Card, Input, Button, Select } from 'antd';
import { SearchForm } from 'components'; import { SearchForm } from 'components';
import ComTable from './Table'; import ComTable from './Table';
import store from './store'; import store from './store';
export default function () { export default observer(function () {
return ( return (
<Card> <Card>
<SearchForm> <SearchForm>
<SearchForm.Item span={8} title="主机类别">
<Select allowClear placeholder="请选择" onChange={v => store.f_zone = v}>
{store.zones.map(item => (
<Select.Option value={item} key={item}>{item}</Select.Option>
))}
</Select>
</SearchForm.Item>
<SearchForm.Item span={8} title="主机别名"> <SearchForm.Item span={8} title="主机别名">
<Input onChange={e => store.f_name = e.target.value} placeholder="请输入"/> <Input allowClear onChange={e => store.f_name = e.target.value} placeholder="请输入"/>
</SearchForm.Item> </SearchForm.Item>
<SearchForm.Item span={8}> <SearchForm.Item span={8}>
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
@ -21,4 +29,4 @@ export default function () {
<ComTable/> <ComTable/>
</Card> </Card>
) )
} })

View File

@ -3,17 +3,21 @@ import http from 'libs/http';
class Store { class Store {
@observable records = []; @observable records = [];
@observable zones = [];
@observable record = {}; @observable record = {};
@observable isFetching = false; @observable isFetching = false;
@observable formVisible = false; @observable formVisible = false;
@observable f_name; @observable f_name;
@observable f_status; @observable f_zone;
fetchRecords = () => { fetchRecords = () => {
this.isFetching = true; this.isFetching = true;
http.get('/api/host/') http.get('/api/host/')
.then(res => this.records = res) .then(({hosts, zones}) => {
this.records = hosts;
this.zones = zones;
})
.finally(() => this.isFetching = false) .finally(() => this.isFetching = false)
}; };