This commit is contained in:
Jay 2017-05-25 13:37:16 +08:00
parent c934490047
commit 432ff46ecd
8 changed files with 452 additions and 75 deletions

View File

@ -132,10 +132,168 @@ router
if (!arr.data.id) return n('ERR0028'); if (!arr.data.id) return n('ERR0028');
try { try {
let query = "delete from ??.?? where `devuid` = ?";
let param = [config.db.db11, 'dev', arr.data.id];
await tool.promiseQuery(res, query, param);
} catch (err) { } catch (err) {
return rt.err(res, err, n, 'ERR8003'); return rt.err(res, err, n, 'ERR8003');
} }
res.api_res = {
record: []
}
return n();
})
.post('/addipmi', async(req, res, n) => {
if (!config.permission.server) return n('ERR9000');
if (!tool.checkPermission(req)) return n('ERR9000');
let arr = req.body;
if (!arr.data) return n('ERR0000');
if (!arr.data.devuid) return n('ERR0028');
if (!arr.data.account) return n('ERR0016');
if (!arr.data.password) return n('ERR0017');
if (!arr.data.ip) return n('ERR0010');
try {
let query = "select count(*) as c from ??.?? where `ip` = ?";
let param = [config.db.db11, 'ipmi', arr.data.ip];
let c = await tool.promiseQuery(res, query, param);
if (c.data.length > 0 && c.data.c > 0) return n('ERR0027');
} catch (err) {
return rt.err(res, err, n, 'ERR8000');
}
let u = '';
let obj = so.get(req.headers['x-auth-token'] || '');
if (obj != null && 'user' in obj && 'account' in obj.user) u = obj.user.account;
try {
let query = "insert into ??.?? (`devuid`, `ip`, `account`, `password`, `cuser`, `ctime`, `muser`, `mtime`) values \
(?, ?, ?, ?, ?, unix_timestamp(), ?, unix_timestamp())";
let param = [config.db.db11, 'ipmi', arr.data.devuid, arr.data.ip, arr.data.account, arr.data.password, u, u];
await tool.promiseQuery(res, query, param);
} catch (err) {
return rt.err(res, err, n, 'ERR8001');
}
res.api_res = {
record: []
};
return n();
})
.post('/editipmi', async(req, res, n) => {
if (!config.permission.server) return n('ERR9000');
if (!tool.checkPermission(req)) return n('ERR9000');
let arr = req.body;
if (!arr.data) return n('ERR0000');
if (!arr.data.id) return n('ERR0028');
if (!arr.data.account) return n('ERR0016');
if (!arr.data.password) return n('ERR0017');
if (!arr.data.ip) return n('ERR0010');
try {
let query = "select count(*) as c from ??.?? where `ipmuid` != ? and `ip` = ?";
let param = [config.db.db11, 'ipmi', arr.data.id, arr.data.ip];
let c = await tool.promiseQuery(res, query, param);
if (c.data.length > 0 && c.data.c > 0) return n('ERR0027');
} catch (err) {
return rt.err(res, err, n, 'ERR8000');
}
let u = '';
let obj = so.get(req.headers['x-auth-token'] || '');
if (obj != null && 'user' in obj && 'account' in obj.user) u = obj.user.account;
try {
let query = "update ??.?? set \
`account` = ?, \
`password` = ?, \
`ip` = ?, \
`muser` = ?, \
`mtime` = unix_timestamp() \
where \
`ipmuid` = ?";
let param = [config.db.db11, 'ipmi', arr.data.account, arr.data.password, arr.data.ip, u, arr.data.id];
await tool.promiseQuery(res, query, param);
} catch (err) {
return rt.err(res, err, n, 'ERR8002');
}
res.api_res = {
record: []
};
return n();
})
.post('/delipmi', async(req, res, n) => {
if (!config.permission.server) return n('ERR9000');
if (!tool.checkPermission(req)) return n('ERR9000');
let arr = req.body;
if (!arr.data) return n('ERR0000');
if (!arr.data.id) return n('ERR0028');
try {
let query = "delete from ??.?? where `ipmuid` = ?";
let param = [config.db.db11, 'ipmi', arr.data.id];
await tool.promiseQuery(res, query, param);
} catch (err) {
return rt.err(res, err, n, 'ERR8003');
}
res.api_res = {
record: []
};
return n();
})
.post('/getipmiinfo', async(req, res, n) => {
if (!config.permission.server) return n('ERR9000');
let arr = req.body;
if (!arr.data) return n('ERR0000');
if (!arr.data.id) return n('ERR0028');
res.api_res = {
record: [],
rt: {
log: [],
sensor: [],
bmcgroup: [],
bmcdata: []
}
};
try {
let query = "select * from ??.?? where `ipmuid` = ?";
let param = [config.db.db11, 'ipmi', arr.data.id];
let ipmi = await tool.promiseQuery(res, query, param);
if (ipmi.data.length == 0) return n('ERR8000');
delete ipmi.data[0].password;
res.api_res.record = tool.checkArray(ipmi.data);
query = "select * from ??.?? order by `guid`";
param = [config.db.db11, 'bmg'];
let bmg = await tool.promiseQuery(res, query, param);
res.api_res.rt.bmcgroup = tool.checkArray(bmg.data);
query = "select * from ??.?? where `ipmuid` = ?";
param = [config.db.db11, 'bmrt', arr.data.id];
let bmrt = await tool.promiseQuery(res, query, param);
res.api_res.rt.bmcdata = tool.checkArray(bmrt.data);
query = "select * from ??.?? where `ipmuid` = ?";
param = [config.db.db11, 'ipmilogrt', arr.data.id];
let log = await tool.promiseQuery(res, query, param);
res.api_res.rt.log = tool.checkArray(log.data);
query = "select * from ??.?? where `ipmuid` = ?";
param = [config.db.db11, 'ipmisenrt', arr.data.id];
let sensor = await tool.promiseQuery(res, query, param);
res.api_res.rt.sensor = tool.checkArray(sensor.data);
} catch (err) {
return rt.err(res, err, n, 'ERR8000');
}
return n();
}) })
.all('*', rt.send); .all('*', rt.send);

View File

@ -6,7 +6,7 @@ class DevList extends React.Component {
render() { render() {
let {list, sel,selectDevice, openModal} = this.props; let {list, sel,selectDevice, openModal, delData} = this.props;
return ( return (
<Menu vertical> <Menu vertical>
<Menu.Item> <Menu.Item>
@ -23,7 +23,7 @@ class DevList extends React.Component {
<span style={{cursor:'pointer'}} onClick={()=>selectDevice(t.devuid)}>{t.name}</span> <span style={{cursor:'pointer'}} onClick={()=>selectDevice(t.devuid)}>{t.name}</span>
<Icon name="trash" <Icon name="trash"
style={{cursor:'pointer'}} style={{cursor:'pointer'}}
onClick={()=>null} /> onClick={()=>delData('device', t.devuid)} />
<Icon name="edit" <Icon name="edit"
style={{cursor:'pointer'}} style={{cursor:'pointer'}}
onClick={()=>openModal('device', 1, t)} /> onClick={()=>openModal('device', 1, t)} />

View File

@ -1,14 +1,14 @@
import React from 'react'; import React from 'react';
import {Table, Button} from 'semantic-ui-react'; import {Table, Button} from 'semantic-ui-react';
const SetListItem = ({ i18n, data, openModal }) => { const SetListItem = ({ i18n, data, openModal, delData }) => {
return ( return (
<Table.Row> <Table.Row>
<Table.Cell> <Table.Cell>
<Button content="修改" basic onClick={()=>null} /> <Button content="修改" basic onClick={()=>openModal('ipmi', 1, data)} />
<Button content="刪除" basic onClick={()=>null} /> <Button content="刪除" basic onClick={()=>delData('ipmi', data.ipmuid)} />
<Button content="ShowInfo" basic onClick={()=>null} /> <Button content="ShowInfo" basic onClick={()=>openModal('ipmiinfo', 0, {id: data.ipmuid})} />
</Table.Cell> </Table.Cell>
<Table.Cell>{data.ip}</Table.Cell> <Table.Cell>{data.ip}</Table.Cell>
<Table.Cell>{data.account}</Table.Cell> <Table.Cell>{data.account}</Table.Cell>

View File

@ -2,46 +2,42 @@ import React from 'react';
import {Container, Segment, Button, Table} from 'semantic-ui-react'; import {Container, Segment, Button, Table} from 'semantic-ui-react';
import SelListItem from './SetListItem'; import SelListItem from './SetListItem';
const IPMIPage = ({ i18n, list, openModal }) => { const IPMIPage = ({i18n, list, openModal, delData}) => {
return ( < return (
Container > <Container>
< <Segment className="clearfix">
Segment className = "clearfix" > <Button content="新增設定"
<
Button content = "新增設定"
icon="plus" icon="plus"
floated="right" floated="right"
basic color = "green" basic
style = { color="green"
{ marginBottom: '15px' } } style={{marginBottom: '15px'}}
/> < onClick={()=>openModal('ipmi')} />
Table > <Table>
< <Table.Header>
Table.Header > <Table.Row>
< <Table.HeaderCell>操作</Table.HeaderCell>
Table.Row > <Table.HeaderCell>IP</Table.HeaderCell>
< <Table.HeaderCell>帳號</Table.HeaderCell>
Table.HeaderCell > 操作 < /Table.HeaderCell> < <Table.HeaderCell>MAC Address</Table.HeaderCell>
Table.HeaderCell > IP < /Table.HeaderCell> < </Table.Row>
Table.HeaderCell > 帳號 < /Table.HeaderCell> < </Table.Header>
Table.HeaderCell > MAC Address < /Table.HeaderCell> < <Table.Body>
/Table.Row> < {
/Table.Header> <
Table.Body > {
list.map((t,idx) => { list.map((t,idx) => {
return ( < return (
SelListItem key = { idx } <SelListItem key={idx}
i18n={i18n} i18n={i18n}
data={t} data={t}
openModal={openModal} openModal={openModal}
/> delData={delData} />
) )
}) })
} < }
/Table.Body> < </Table.Body>
/Table> < </Table>
/Segment> < </Segment>
/Container> </Container>
) )
} }

View File

@ -1,13 +1,24 @@
import React from 'react'; import React from 'react';
import {Modal, Form, Input, Button, Grid} from 'semantic-ui-react'; import {Modal, Form, Input, Button, Grid} from 'semantic-ui-react';
const DevModel = ({ i18n, open, type, data, closeModal }) => { const DevModel = ({ i18n, open, type, data, closeModal, submitModal }) => {
return ( return (
<Modal open={open}> <Modal open={open}>
<Modal.Header content={type == 1 ? '修改裝置' : '新增裝置'} /> <Modal.Header content={type == 1 ? '修改裝置' : '新增裝置'} />
<Modal.Content> <Modal.Content>
<Form> <Form onSubmit={(e,d) => {
e.preventDefault();
submitModal('device', type, d.formData);
}} serializer={e=>{
let json = {};
let name = e.querySelector('input[name="name"]');
if(name && 'value' in name) json.name = name.value;
if(type == 1) json.id = data.devuid;
return json;
}}>
<Form.Field> <Form.Field>
<Input label="裝置名稱" name="name" defaultValue={data.name} /> <Input label="裝置名稱" name="name" defaultValue={data.name} />
</Form.Field> </Form.Field>

View File

@ -0,0 +1,34 @@
import React from 'react';
import {Modal, Segment} from 'semantic-ui-react';
const stateDefault = () => ({
open: false,
tabIdx: 1
})
class IPMIInfoModal extends React.Component {
componentWillReceiveProps(nextProps){
if(nextProps.open != this.state.open){
if(nextProps.open == false){
this.setState({...stateDefault()})
}else{
this.setState({
open: true
})
}
}
}
render() {
return (
<Modal fluid open={this.state.open} onClose={()=>null}>
<Modal.Header content="IPMI Info" />
<Modal.Content>
</Modal.Content>
</Modal>
)
}
}
export default IPMIInfoModal;

View File

@ -0,0 +1,50 @@
import React from 'react';
import {Modal, Form, Grid, Input, Button } from 'semantic-ui-react';
const IPMIModal = ({ i18n, open, type, data, closeModal, submitModal }) => {
return (
<Modal open={open}>
<Modal.Header content={type == 1 ? '修改設定' : '新增設定'} />
<Modal.Content>
<Form onSubmit={(e,d) => {
e.preventDefault();
submitModal('ipmi', type, d.formData);
}} serializer={e=>{
let json ={};
let ip = e.querySelector('input[name="ip"]');
if(ip && 'value' in ip) json.ip = ip.value;
let account = e.querySelector('input[name="account"]');
if(account && 'value' in account) json.account = account.value;
let pass = e.querySelector('input[name="password"]');
if(pass && 'value' in pass) json.password = pass.value;
if(type == 1 ) json.id = data.ipmuid;
return json;
}}>
<Form.Field>
<Input label="IP" name="ip" defaultValue={data.ip} />
</Form.Field>
<Form.Field>
<Input label="帳號" name="account" defaultValue={data.account} />
</Form.Field>
<Form.Field>
<Input label="密碼" name="password" defaultValue={data.password} />
</Form.Field>
<Grid columns={2}>
<Grid.Column>
<Button type="submit" content="送出" basic fluid/>
</Grid.Column>
<Grid.Column>
<Button type="button" fluid content="取消" basic onClick={()=>closeModal('ipmi')} />
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default IPMIModal;

View File

@ -3,7 +3,9 @@ import { Container, Segment, Menu, List, Grid } from 'semantic-ui-react';
import {getRequest} from '../../../actions'; import {getRequest} from '../../../actions';
import DevList from './DevList'; import DevList from './DevList';
import IPMIPage from './IPMIPage'; import IPMIPage from './IPMIPage';
import DevModal from './Models/DevModal'; import DevModal from './Modals/DevModal';
import IPMIModal from './Modals/IPMIModal';
import IPMIInfoModal from './Modals'
const stateDefault = ()=>({ const stateDefault = ()=>({
list: [], list: [],
@ -20,17 +22,29 @@ const stateDefault = ()=>({
type: 0, type: 0,
data: {} data: {}
}, },
openedModal: null ipmiModal: {
open: false,
type: 0,
data: {}
},
ipmiInfo: {
open: false,
ipmi: [],
log: [],
sensor: [],
bmcdata: [],
bmcgroup: []
}
}) })
class ServerPage extends React.Component { class ServerPage extends React.Component {
state = {...stateDefault()} state = {...stateDefault()}
componentDidMount(){ componentDidMount(){
this.getList(); this.getDevList();
} }
getList = () => { getDevList = () => {
let {showDialog, toggleLoading} = this.props; let {showDialog, toggleLoading} = this.props;
toggleLoading(1); toggleLoading(1);
fetch('/api/server/getdevicelist', getRequest()) fetch('/api/server/getdevicelist', getRequest())
@ -44,7 +58,7 @@ class ServerPage extends React.Component {
}) })
} }
selectDevice = (id) => { selectDevice = (id, refresh = false) => {
if(!id) return ; if(!id) return ;
let {showDialog, toggleLoading} = this.props; let {showDialog, toggleLoading} = this.props;
toggleLoading(1); toggleLoading(1);
@ -56,15 +70,19 @@ class ServerPage extends React.Component {
let ipmi = json.data.rt.ipmi || []; let ipmi = json.data.rt.ipmi || [];
let snmp = json.data.rt.snmp || []; let snmp = json.data.rt.snmp || [];
this.setState({ let jdata = {
devSel: {
...stateDefault().devSel, ...stateDefault().devSel,
id, id,
data: { data: {
ipmi, ipmi,
snmp snmp
} }
} };
if(refresh) jdata.type = this.state.devSel.type;
this.setState({
devSel: jdata
}) })
}) })
} }
@ -87,7 +105,8 @@ class ServerPage extends React.Component {
callConfirm={callConfirm} callConfirm={callConfirm}
list={this.state.devSel.data.ipmi} list={this.state.devSel.data.ipmi}
openModal={this.openModal} openModal={this.openModal}
closeModal={this.closeModal} /> closeModal={this.closeModal}
delData={this.delData} />
default: default:
return null; return null;
@ -102,28 +121,129 @@ class ServerPage extends React.Component {
open: true, open: true,
type, type,
data data
}, }
openedModal: mtype
}) })
break; break;
default: case 'ipmi':
return null; this.setState({
ipmiModal:{
open: true,
type,
data
} }
} });
break;
closeModal = (mtype) => { case 'ipmiinfo':
switch(mtype){ this.getIPMIData(data.id);
case 'device':
this.setState({devModal: {...stateDefault().devModal}, openedModal: null});
break; break;
default: default:
return null; return null;
} }
} }
submitModal = (type, data) => { closeModal = (mtype, cb = null) => {
let open = this.state.openedModal; switch(mtype){
if(open == null) return ; case 'device':
this.setState({devModal: {...stateDefault().devModal}});
break;
case 'ipmi':
this.setState({ipmiModal:{...stateDefault().ipmiModal}});
break;
case 'ipmiinfo':
this.setState({ipmiInfo: {...stateDefault().ipmiInfo}});
break;
}
if(cb && typeof cb == 'function') cb();
}
submitModal = (mtype, type = 0, data = {}) => {
if(!mtype) return ;
let {i18n, showDialog, toggleLoading, callConfirm} = this.props;
let url = '';
switch(mtype){
case 'device':
if(type == 1 && !data.id) return showDialog('資料讀取錯誤');
if(!data.name) return showDialog('請填寫設備名稱');
url = type == 1 ? '/api/server/editdevice' : '/api/server/adddevice';
fetch(url, getRequest(data))
.then(response => response.json())
.then(json => {
if(json.status != 1) return showDialog(json.message);
this.closeModal(mtype, ()=>{this.getDevList()});
});
break;
case 'ipmi':
if(type == 1 && !data.id) return showDialog('資料讀取錯誤');
if(!data.ip) return showDialog('請填寫IP');
if(!data.account) return showDialog('請填寫帳號');
if(!data.password) return showDialog('請填寫密碼');
data.devuid = this.state.devSel.id;
url = type == 1 ? '/api/server/editipmi' : '/api/server/addipmi';
fetch(url, getRequest(data))
.then(response=>response.json())
.then(json => {
if(json.status != 1) return showDialog(json.message);
this.closeModal(mtype, ()=>{ this.selectDevice(this.state.devSel.id, true); })
})
default :
return null;
}
}
delData = (mtype, id) => {
if(!mtype || !id) return ;
let {i18n, showDialog, toggleLoading, callConfirm} = this.props;
switch(mtype) {
case 'device':
callConfirm('確定刪除此裝置?', ()=>{
fetch('/api/server/deldevice', getRequest({id}))
.then(response=>response.json())
.then(json => {
if(json.status != 1) return showDialog(json.message);
this.getDevList();
})
});
break;
case 'ipmi':
callConfirm('確定刪除此筆設定?', ()=>{
fetch('/api/server/delipmi', getRequest({id}))
.then(response=>response.json())
.then(json => {
if(json.status != 1) return showDialog(json.message);
this.selectDevice(this.state.devSel.id, true);
});
});
break;
}
}
getIPMIData = (id) => {
if(!id) return ;
let {i18n, showDialog, toggleLoading, callConfirm} = this.props;
toggleLoading(1);
fetch('/api/server/getipmiinfo', getRequest({id}))
.then(response=>response.json())
.then(json => {
toggleLoading(0);
if(json.status != 1) return showDialog(json.message);
let ipmi = json.data.record || [];
let sensor = json.data.rt.sensor || [];
let log = json.data.rt.log || [];
let bmcgroup = json.data.rt.bmcgroup || [];
let bmcdata = json.data.rt.bmcdata || [];
this.setState({
ipmiInfo: {
open: true,
log,
sensor,
ipmi,
bmcdata,
bmcgroup
}
})
})
} }
render() { render() {
@ -139,7 +259,8 @@ class ServerPage extends React.Component {
sel={this.state.devSel.id} sel={this.state.devSel.id}
selectDevice={this.selectDevice} selectDevice={this.selectDevice}
list={this.state.list} list={this.state.list}
openModal={this.openModal} /> openModal={this.openModal}
delData={this.delData} />
</Grid.Column> </Grid.Column>
<Grid.Column width={13}> <Grid.Column width={13}>
{ {
@ -164,7 +285,14 @@ class ServerPage extends React.Component {
open={this.state.devModal.open} open={this.state.devModal.open}
type={this.state.devModal.type} type={this.state.devModal.type}
data={this.state.devModal.data} data={this.state.devModal.data}
closeModal={this.closeModal} /> closeModal={this.closeModal}
submitModal={this.submitModal} />
<IPMIModal i18n={i18n}
open={this.state.ipmiModal.open}
type={this.state.ipmiModal.type}
data={this.state.ipmiModal.data}
closeModal={this.closeModal}
submitModal={this.submitModal} />
</Container> </Container>
) )
} }