re commit

This commit is contained in:
Jay
2017-03-22 13:35:45 +08:00
commit 8947715671
109 changed files with 161369 additions and 0 deletions
@@ -0,0 +1,123 @@
import React from 'react';
import {Modal, Grid, Divider} from 'semantic-ui-react';
function randomColor() {
var colors = [
'red',
'orange',
'yellow',
'olive',
'green',
'teal',
'blue',
'violet',
'purple',
'pink',
'brown',
'grey'
];
colors.sort(function () {
return 0.5 - Math.random();
});
return colors.shift();
}
function ParseTree(props) {
let {root, ln, lc} = props;
let ops = {
"0": "等於",
"1": "大於",
"2": "小於",
"3": "大於等於",
"4": "小於等於",
"5": "不等於",
"8": "AND",
"9": "OR"
};
function GenLN(props) {
let {data, isRoot} = props;
return (
<Grid.Column color={randomColor()} width={isRoot
? 16
: 8}>
<div>{`ID:${data.jcioclntuid || ''} / Name:${data.lnname || ''} / Action:${data.lnaction || ''}`}</div>
<Divider horizontal={true}>{ops[data.lnlcop]}</Divider>
<GenNode ids={[data.lnlcid1, data.lnlcid2]}/>
</Grid.Column>
)
}
function GenLC(props) {
let {data} = props;
return (
<Grid.Column color={randomColor()} width={8}>
<div>{`ID:${data.jcioclctuid || ''} / Name:${data.lcname || ''} / Action:${data.lcaction || ''}`}</div>
<hr/>
<div>{`${data.lcioid} ${ops[data.lcioop]} ${data.lciovalue}`}</div>
</Grid.Column>
)
}
function GenNode(props) {
let {ids} = props;
let isRoot = ids.length == 1 && ids[0].substr(2) == root
? true
: false;
let arr = [];
for (let i in ids) {
let id = ids[i];
if (/^ln/.test(id)) {
let idn = id.match(/^ln(\d+)$/);
if (!idn || idn.length < 1)
continue;
let num = idn[1];
for (let j in ln) {
if (ln[j].jcioclntuid == num) {
arr.push(<GenLN key={`ln${ln[j].kcioclntuid}`} data={ln[j]} isRoot={isRoot}/>)
}
}
} else if (/^lc/.test(id)) {
let idn = id.match(/^lc(\d+)$/);
if (!idn || idn.length < 1)
continue;
let num = idn[1];
for (let j in lc) {
if (lc[j].jcioclctuid == num) {
arr.push(<GenLC key={`lc${lc[j].jcioclctuid}`} data={lc[j]}/>)
}
}
}
}
return (
<Grid>
{arr.map(t => t)
}
</Grid>
)
}
return <GenNode ids={[`ln${root}`]}/>
}
const LinkInfo = ({
i18n,
open,
root,
ln,
lc,
onClose
}) => {
return (
<Modal size="fullscreen" open={open} onClose={() => {
onClose()
}}>
<Modal.Content>
<ParseTree root={root} ln={ln} lc={lc}/>
</Modal.Content>
</Modal>
)
}
export default LinkInfo;
@@ -0,0 +1,22 @@
import React from 'react';
import {Table, Button} from 'semantic-ui-react';
const ListItem = ({i18n, data, swActive, delItem, showInfo}) => {
return (
<Table.Row>
<Table.Cell>
<Button type="button" size="tiny" basic content="Delete" onClick={()=>{delItem(data.jcioclntuid || '')}}/>
<Button type="button" size="tiny" basic content={data.lnactive == 1 ? 'Disable' : 'Enable'} onClick={()=>{swActive(data.jcioclntuid || '')}} />
</Table.Cell>
<Table.Cell>{data.jcioclntuid || ''}</Table.Cell>
<Table.Cell>{data.lnname || ''}</Table.Cell>
<Table.Cell>{data.lnactive == 1 ? '啟用' : '停用'}</Table.Cell>
<Table.Cell>
<Button type="button" size="tiny" basic content="顯示資訊" onClick={()=>{showInfo(data.jcioclntuid)}} />
</Table.Cell>
</Table.Row>
)
}
export default ListItem ;
@@ -0,0 +1,100 @@
import React from 'react';
import {Container, Segment, Table, Button} from 'semantic-ui-react';
import {getRequest} from '../../../actions';
import {Link} from 'react-router';
import ListItem from './ListItem';
import LinkInfoModal from './LinkInfoModal';
const defState = {
infoModal: {
open: false,
ln: [],
lc: [],
root: ''
}
}
class ActionLinkPage extends React.Component {
state = {
...defState
}
componentDidMount(){
this.props.getList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
swLinkActive = (id) => {
if(!id) return ;
this.props.swLink({id});
}
delLink = (id) => {
if(!id) return ;
this.props.delLink({id});
}
openInfoModal = (id) => {
if(!id) return ;
fetch('/api/link/getlink', getRequest({id}))
.then(response=>response.json())
.then(json => {
if(json.status != 1 ) return this.props.showDialog(json.message);
this.setState({
infoModal:{
open: true,
root: id,
ln: json.data.rt.ln || [],
lc: json.data.rt.lc || []
}
})
})
}
closeInfoModal = () => {
this.setState({
infoModal:{
...defState.infoModal
}
})
}
render(){
let {i18n, list} = this.props;
return (
<Container>
<Segment className="clearfix">
<Button as={Link} to="/admin/addlink" basic color="green" floated="right" icon="plus" content="新增" style={{marginBottom: '10px'}} />
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>操作</Table.HeaderCell>
<Table.HeaderCell>ID</Table.HeaderCell>
<Table.HeaderCell>名稱</Table.HeaderCell>
<Table.HeaderCell>啟用狀態</Table.HeaderCell>
<Table.HeaderCell>觸發內容</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
list.map((t,idx) => (
<ListItem key={idx} i18n={i18n} data={t} swActive={this.swLinkActive} delItem={this.delLink} showInfo={this.openInfoModal} />
))
}
</Table.Body>
</Table>
</Segment>
<LinkInfoModal i18n={i18n}
open={this.state.infoModal.open}
root={this.state.infoModal.root}
ln={this.state.infoModal.ln}
lc={this.state.infoModal.lc}
onClose={this.closeInfoModal} />
</Container>
)
}
}
export default ActionLinkPage;
@@ -0,0 +1,132 @@
import React from 'react';
import {Grid, Form, Segment, Input} from 'semantic-ui-react';
const ops = [
{
"code": "0",
"name": "等於"
}, {
"code": "1",
"name": "大於"
}, {
"code": "2",
"name": "小於"
}, {
"code": "3",
"name": "大於等於"
}, {
"code": "4",
"name": "小於等於"
}, {
"code": "5",
"name": "不等於"
}, {
"code": "8",
"name": "AND"
}, {
"code": "9",
"name": "OR"
}
]
class UnitItem extends React.Component {
render() {
let {unit, data, getList} = this.props;
return (
<Grid.Column>
<Segment>
<Form.Field>
<label>選擇元件</label>
<select
value={data.st}
onChange={e => {
getList(unit, e.target.value);
}}>
<option value="">請選擇元件</option>
<option value="leone">LeOne</option>
<option value="di">DigitInput</option>
<option value="time">時間</option>
<option value="unit">已建立群組</option>
</select>
</Form.Field>
{
!data.st
? null
: (<UnitPanel data={data}/>)
}
</Segment>
</Grid.Column>
)
}
}
const UnitPanel = ({data}) => {
if (data.st == 'di') {
return (
<div>
<LC_List data={data} />
<select>
<option value="">選擇狀態</option>
<option value="0">0</option>
<option value="1">1</option>
</select>
</div>
)
}
if(data.st == 'leone') {
return (
<div>
<LC_List data={data} />
<select>
<option value="">選擇感測器</option>
<option value="leone_ttrigger1">溫度</option>
<option value="leone_htrigger1">濕度</option>
</select>
<Input size="mini" placeholder="請輸入數值" />
</div>
)
}
if(data.st == 'unit') {
return (
<div>
<select>
<option value="">選擇群組</option>
{
data.list.map((t,idx) => (
<option key={idx} value={t.id}>{t.name}</option>
))
}
</select>
</div>
)
}
return null;
}
const LC_List = ({data}) => {
return (
<div>
<select>
<option value="">選擇裝置</option>
{
data.list.map((t, idx) => (
<option key={idx} value={t.id}>{t.name}</option>
))
}
</select>
<select>
<option value="">選擇條件</option>
{
ops.map((t,idx) => {
if(t.code == 8 || t.code == 9) return ;
return (<option key={idx} value={t.code}>{t.name}</option>)
})
}
</select>
</div>
)
}
export default UnitItem;
@@ -0,0 +1,138 @@
import React from 'react';
import {
Container,
Segment,
Form,
Input,
Button,
Checkbox,
Grid
} from 'semantic-ui-react';
import {getRequest} from '../../../actions';
import UnitItem from './UnitItem';
const defState = {
groups: {},
edit: {
active: false,
name: '',
type: 'ln',
op: '',
id1: {
st: '',
list: [],
data: {}
},
id2: {
st: '',
list: [],
data: {}
}
}
}
const gtype = {
lc: {
type: 'lc',
id: '',
op: '',
value: ''
},
ln: {
type: 'ln'
}
}
class ActionLinkAdd extends React.Component {
state = {
...defState
}
getSelectList = (unit, type = '') => {
if (!unit) {
return;
}
let edit = {
...this.state.edit
};
if (!(unit in edit)) {
return;
}
edit[unit].st = type;
edit[unit].data = {
...gtype.lc
}
if (type != 'di' && type != 'leone') {
return this.setState({edit});
}
if (type == 'di' || type == 'leone') {
this.props.toggleLoading(1);
let json = {
type
};
fetch('/api/system/getselectlist', getRequest(json))
.then(response => response.json())
.then(json => {
if (json.status != 1)
return this.props.showDialog(json.message);
edit[unit].list = json.data.record || [];
this.setState({edit}, () => {
this.props.toggleLoading(0);
});
});
}
if(type == 'unit') {
let list = [];
for(let i in this.state.groups){
list.push({id: i, name: this.state.groups[i].name});
}
edit[unit].list = list;
edit[unit].data = {
...gtype.ln
}
this.setState({edit})
}
}
render() {
return (
<Container>
<Form as={Segment}>
<Form.Field>
<Checkbox label="啟用連動"/>
</Form.Field>
<Form.Field>
<label>建立條件群組</label>
<Segment color="red">
<Form.Field>
<Input label="節點名稱"/>
</Form.Field>
<Form.Field>
<label>觸發條件</label>
<select>
<option value="">請選擇觸發條件</option>
<option value="8">AND</option>
<option value="9">OR</option>
</select>
</Form.Field>
<Grid columns={2} padded>
<UnitItem unit="id1" data={this.state.edit.id1} getList={this.getSelectList}/>
<UnitItem unit="id2" data={this.state.edit.id2} getList={this.getSelectList}/>
</Grid>
<div
style={{
textAlign: 'right'
}}>
<Button type="button" basic size="tiny" color="blue" content="加入"/>
<Button type="button" basic size="tiny" color="green" content="清除"/>
</div>
</Segment>
</Form.Field>
</Form>
</Container>
)
}
}
export default ActionLinkAdd;
+28
View File
@@ -0,0 +1,28 @@
import React from 'react';
import {Table, Input, Checkbox, Label} from 'semantic-ui-react';
const DiItem = ({i18n, cusKey, data, onNameChange, onLogicChange, status}) => {
return (
<Table.Row>
<Table.Cell>
<Label content={cusKey}/>
</Table.Cell>
<Table.Cell width={4}>
<Input fluid name="diname" value={data.diname || ''} onChange={(e) => onNameChange(cusKey, e.target.value)} />
</Table.Cell>
<Table.Cell>
<Checkbox toggle={true} label={i18n&&i18n.t ? i18n.t('page.dio.form.label.logic') : ''} checked={data.dilogic == 1 ? true : false} onChange={(e, d) => onLogicChange(cusKey, d.checked)}/>
</Table.Cell>
<Table.Cell>
<span>{i18n&&i18n.t ? i18n.t('page.dio.form.label.di_status') : ''} <Label color={status == 0 ? 'green' : 'red'} size="tiny" content={
i18n&&i18n.t ?
(status == 0 ? i18n.t('page.dio.form.label.di_not_triggered') : i18n.t('page.dio.form.label.di_triggered')) :
"Loading..."
}/></span>
</Table.Cell>
</Table.Row>
)
}
export default DiItem;
+24
View File
@@ -0,0 +1,24 @@
import React from 'react';
import {Table, Input, Checkbox, Label} from 'semantic-ui-react';
const DoItem = ({i18n, cusKey, data, onNameChange, onLogicChange, status, onDoRun}) => {
return (
<Table.Row>
<Table.Cell>
<Label content={cusKey}/>
</Table.Cell>
<Table.Cell width={4}>
<Input fluid name="doname" value={data.doname || ''} onChange={(e) => {onNameChange(cusKey, e.target.value)}} />
</Table.Cell>
<Table.Cell>
<Checkbox toggle={true} label={i18n&&i18n.t ? i18n.t('page.dio.form.label.logic') : ''} checked={data.dologic == 1 ? true : false } onChange={(e, d)=>{onLogicChange(cusKey, d.checked)}} />
</Table.Cell>
<Table.Cell>
<Checkbox toggle={true} label={i18n&&i18n.t ? i18n.t('page.dio.form.label.do_ctrl') : ''} checked={status == 1} onChange={(e,d) => { onDoRun(cusKey, d.checked) }} />
</Table.Cell>
</Table.Row>
)
}
export default DoItem;
+175
View File
@@ -0,0 +1,175 @@
import React from 'react';
import {Container, Grid, Segment, Header, CheckBox, Table, Input, Button} from 'semantic-ui-react';
import DoItem from './DoItem';
import DiItem from './DiItem';
class DIO extends React.Component {
state = {
do: [],
di: [],
doSt: {},
diSt: {}
}
tick = null
onNameChange = (key, name) => {
let reg = new RegExp(`^${key}$`, 'i');
if(/^do/i.test(key)) {
let dos = [...this.state.do];
for(let i in dos){
if(reg.test(dos[i].doid)){
dos[i].doname = name;
this.setState({
do: dos
});
break;
}
}
}else{
let dis = [...this.state.di];
for(let i in dis){
if(reg.test(dis[i].diid)){
dis[i].diname = name;
this.setState({
di: dis
});
break;
}
}
}
}
onLogicChange = (key, st) => {
let reg = new RegExp(`^${key}$`, 'i');
if(/^do/i.test(key)) {
let dos = [...this.state.do];
for(let i in dos){
if(reg.test(dos[i].doid)){
dos[i].dologic = st ? 1 : 0;
this.setState({
do: dos
});
break;
}
}
}else{
let dis = [...this.state.di];
for(let i in dis){
if(reg.test(dis[i].diid)){
dis[i].dilogic = st ? 1 : 0;
this.setState({
di: dis
});
break;
}
}
}
}
updateSetting = () => {
let dos = [...this.state.do];
let dis = [...this.state.di];
let json = {};
json.do = {};
json.di = {};
for(let i in dos) {
json.do[dos[i].doid] = {
name: dos[i].doname,
logic: dos[i].dologic
}
}
for(let i in dis){
json.di[dis[i].diid] ={
name: dis[i].diname,
logic: dis[i].dilogic
}
}
this.props.setDIOInfo(json);
}
doRun = (key, val) => {
let reg = /^do([0-9]+)$/i;
let m = key.match(reg);
if(!m || !m[1]) return ;
let pin = m[1];
if(pin in this.state.doSt){
let tmp = {...this.state.doSt};
tmp[pin] = val ? 1 : 0;
this.setState({
doSt: tmp
})
}
this.props.dotRun(pin, val ? 1 : 0);
}
componentWillReceiveProps(nextProps) {
this.setState({
do: nextProps.dio.do,
di: nextProps.dio.di,
diSt: nextProps.dio.diSt,
doSt: nextProps.dio.doSt
});
}
updateTick = () => {
this.props.getIO();
}
componentDidMount() {
this.props.getDIOInfo();
this.props.getIO();
this.tick = setInterval(this.updateTick, 5000);
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
componentWillUnmount() {
clearInterval(this.tick);
}
render () {
let {i18n} = this.props;
return (
<Container>
<Grid columns={2}>
<Grid.Column>
<Header as="h4" color="blue" content={i18n&&i18n.t ? i18n.t('page.dio.title.do'): ''}/>
<Table>
<Table.Body>
{
[1,2,3,4,5,6,7,8].map(t => {
let tmp = this.state.do.filter(tt => tt.doid == `do${t}`);
let dost = this.state.doSt[t] || 0;
return <DoItem i18n={i18n} key={t} cusKey={`Do${t}`} data={tmp[0] || {}} onLogicChange={this.onLogicChange} onNameChange={this.onNameChange} status={dost} onDoRun={this.doRun}/>
})
}
</Table.Body>
</Table>
</Grid.Column>
<Grid.Column>
<Header as="h4" color="blue" content={i18n&&i18n.t ? i18n.t('page.dio.title.di'): ''}/>
<Table>
<Table.Body>
{
[1,2,3,4,5,6,7,8].map(t => {
let tmp = this.state.di.filter(tt => tt.diid == `di${t}`);
let dist = this.state.diSt[t] || 0;
return <DiItem i18n={i18n} key={t} cusKey={`Di${t}`} data={tmp[0] || {}} onLogicChange={this.onLogicChange} onNameChange={this.onNameChange} status={dist} />
})
}
</Table.Body>
</Table>
</Grid.Column>
</Grid>
<Button type="button" style={{marginTop: '10px'}} fluid content={i18n&&i18n.t ? i18n.t('page.dio.form.button.update_setting') : ''} onClick={() => {this.updateSetting()}} />
</Container>
)
}
}
export default DIO;
@@ -0,0 +1,17 @@
import React from 'react';
import {List, Button, Label} from 'semantic-ui-react';
const SelectedItem = ({i18n, data, idx, removeSelect}) => {
return (
<List.Item>
<List.Content floated="right">
<Button type="button" size="mini" content={i18n&&i18n.t ? i18n.t('page.iogroup.form.button.remove') : ''} onClick={() => {removeSelect(idx)}} />
</List.Content>
<Label content={data.type || ''} />
{data.name || ''}
</List.Item>
)
}
export default SelectedItem;
+129
View File
@@ -0,0 +1,129 @@
import React from 'react';
import {Container, Segment, Form, Button, List, Input} from 'semantic-ui-react';
import DeviceSelect from '../../Common/DeviceSelect';
import SelectedItem from './SelectedItem';
class IOCmdPage extends React.Component {
state = {
showTemp: false,
selectItem: []
}
querySelectList = (type) => {
this.props.clearSelectList();
if(!type) return ;
this.props.getSelectList({type});
}
checkShowTemp = (cmd) => {
this.setState({
showTemp: cmd == 2 ? true : false
})
}
addSelect = (data) => {
let tmp = this.state.selectItem.filter(t => t.id == data.id);
if(tmp.length > 0) return ;
this.setState({
selectItem: [...this.state.selectItem, data]
});
}
removeSelect = (idx) => {
this.state.selectItem.splice(idx, 1);
this.setState({
selectItem: this.state.selectItem
})
}
runCmd = (data) => {
let {i18n} = this.props;
if(!data.cmd) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.select_action') : '');
if(data.cmd == 2){
if(!data.temp) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty_temp') : '');
if(!(data.temp > 16 && data.temp < 30)) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.temp_format') : '');
data.cmd = `${data.cmd} ${data.temp}`;
}
let ids = this.state.selectItem.map(t => t.id);
let json = {
...data,
devs: ids.join(',')
}
this.props.runCmd(json);
this.setState({
showTemp: false,
selectItem: []
}, ()=>{
this.props.clearSelectList();
})
}
componentDidMount() {
this.props.clearSelectList();
}
render() {
let {i18n,permissions,devs} = this.props;
let actlist = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.action_list') : [];
return (
<Container>
<Segment>
<Form onSubmit={(e,d) => {
e.preventDefault();
this.runCmd(d.formData);
}} serializer={e => {
let json = {
cmd: '',
temp: ''
};
let sel = e.querySelector('select[name="cmd"]');
if(sel && 'value' in sel) json.cmd = sel.value;
let temp = e.querySelector('input[name="temp"]');
if(temp && 'value' in temp) json.temp = temp.value;
if(e.reset) e.reset();
return json;
}}>
<Form.Field>
<label>{i18n&&i18n.t ? i18n.t('page.iocmd.form.label.action') : ''}</label>
<select name="cmd" onChange={e => {
this.checkShowTemp(e.target.value);
}}>
<option value="">{i18n&&i18n.t ? i18n.t('select.action') : ''}</option>
{
actlist.map((t,idx) => <option key={idx} value={t.cmd}>{t.name}</option>)
}
</select>
</Form.Field>
{
this.state.showTemp ?
(<Form.Field>
<Input name="temp" label={i18n&&i18n.t ? i18n.t('page.iocmd.form.label.temp') : ''} />
</Form.Field>) : null
}
<DeviceSelect i18n={i18n} devs={devs} page="iocmd" showGroup={true} permissions={permissions} querySelectList={this.querySelectList} addSelect={this.addSelect} />
<Form.Field>
<label>{i18n&&i18n.t ? i18n.t('page.iocmd.form.label.selected_device') : ''}</label>
<Segment>
<List divided relaxed={true}>
{
this.state.selectItem.map((t,idx) => <SelectedItem key={idx} i18n={i18n} data={t} idx={idx} removeSelect={this.removeSelect} />)
}
</List>
</Segment>
</Form.Field>
<Button type="submit" fluid content={i18n&&i18n.t ? i18n.t('page.iocmd.form.button.submit') : ''} />
</Form>
</Segment>
</Container>
)
}
}
export default IOCmdPage;
@@ -0,0 +1,51 @@
import React from 'react';
import {Modal, Form, Input, Segment, Grid, Button, Header, List} from 'semantic-ui-react';
import SelectedItem from './SelectedItem';
import DeviceSelect from '../../Common/DeviceSelect';
const GroupModal = ({i18n, open, type, data, devs, permissions, onClose, onSubmit, selected, removeSelect, addSelect, querySelectList}) => {
return (
<Modal open={open}>
<Modal.Header content={i18n&&i18n.t ? (type == 1 ? i18n.t('page.iogroup.form.title.edit') : i18n.t('page.iogroup.form.title.add')) : ''} />
<Modal.Content>
<Form onSubmit={(e,d) => {
e.preventDefault();
onSubmit(type, d.formData);
}} serializer={e => {
let json = {
name: '',
id: data.iogroupuid || 0
};
let n = e.querySelector('input[name="name"]');
if(n && 'value' in n) json.name = n.value;
return json;
}}>
<Form.Field>
<Input label={i18n&&i18n.t?i18n.t('page.iogroup.form.label.name') : ''} name="name" defaultValue={data.iogroupname || ''} />
</Form.Field>
<DeviceSelect i18n={i18n} devs={devs} page="iogroup" showGroup={false} permissions={permissions} addSelect={addSelect} querySelectList={querySelectList} />
<Segment>
<Header as="h4" content={i18n&&i18n.t ? i18n.t('page.iogroup.form.label.selected_device') : ''} />
<List divided verticalAlign="middle">
{
selected.map((t, idx) => <SelectedItem i18n={i18n} key={idx} data={t} idx={idx} removeSelect={removeSelect}/>)
}
</List>
</Segment>
<Grid columns={2}>
<Grid.Column>
<Button fluid type="submit" content={i18n&&i18n.t?i18n.t('page.leone.form.button.submit'):''}/>
</Grid.Column>
<Grid.Column>
<Button fluid type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.cancel'):''} onClick={() => {onClose()}}/>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default GroupModal;
@@ -0,0 +1,55 @@
import React from 'react';
import {Table, Button, Label, Item} from 'semantic-ui-react';
const ListItem = ({i18n, data, dos, les, openItemModal, onDelete, openModal}) => {
let devs = data.iogroupid || '';
let dev = devs.split(',');
let items = [];
if(dev.length > 0){
for(let i in dev){
if(/^do/i.test(dev[i])){
for(let j in dos){
if(`do${dos[j].douid}` == dev[i]) {
items.push({
type: 'DigitOutput',
name: dos[j].doname,
id: dev[i]
});
break;
}
}
}else if(/^le/i.test(dev[i])){
for(let j in les){
if(`le${les[j].leonelistuid}` == dev[i]) {
items.push({
type: 'LeOne',
name: les[j].leonename,
id: dev[i]
});
break;
}
}
}
}
}
return (
<Table.Row>
<Table.Cell>
<Button type="button" basic size="tiny" color="red" content={i18n&&i18n.t ? i18n.t('page.iogroup.table.button.del') : ''} onClick={()=>{onDelete(data.iogroupuid)}} />
<Button type="button" basic size="tiny" color="blue" content={i18n&&i18n.t ? i18n.t('page.iogroup.table.button.edit') : ''} onClick={() => {openModal(1, data, items)}}/>
</Table.Cell>
<Table.Cell>{data.iogroupname}</Table.Cell>
<Table.Cell>
{
items.length > 0 ?
(items.length == 1 ?
<Item><Label content={items[0].type} />{items[0].name}</Item>:
<Button size="tiny" basic content={i18n&&i18n.t ? i18n.t('page.iogroup.table.button.showgroup') : ''} onClick={()=>{openItemModal(items)}}/> ) :
''
}
</Table.Cell>
</Table.Row>
)
}
export default ListItem;
@@ -0,0 +1,17 @@
import React from 'react';
import {List, Button, Label} from 'semantic-ui-react';
const SelectedItem = ({i18n, data, idx, removeSelect}) => {
return (
<List.Item>
<List.Content floated="right">
<Button type="button" size="mini" content={i18n&&i18n.t ? i18n.t('page.iogroup.form.button.remove') : ''} onClick={() => {removeSelect(idx)}} />
</List.Content>
<Label content={data.type || ''} />
{data.name || ''}
</List.Item>
)
}
export default SelectedItem;
+152
View File
@@ -0,0 +1,152 @@
import React from 'react';
import {Container, Table, Button, Segment, Modal, Item, Label} from 'semantic-ui-react';
import ListItem from './ListItem';
import GroupModal from './GroupModal';
class IOGroupPage extends React.Component {
state = {
modal: false,
modalType: 0,
modalData: {},
modalSelect: [],
showItem: false,
items: []
}
showGroupItems = (items = []) => {
this.setState({
showItem: true,
items
})
}
closeItemModal = () => {
this.setState({
showItem: false,
items: []
})
}
openModal = (type, data= {}, items=[]) => {
this.props.clearSelectList();
this.setState({
modal: true,
modalType: type,
modalData: data,
modalSelect: items
})
}
closeModal = () => {
this.setState({
modal: false,
modalData: {},
modalSelect: []
})
}
submitModal = (type, data ={}) => {
let {i18n} = this.props;
if(!data.name || (type == 1 && !data.id)) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
let ids = this.state.modalSelect.map(t => t.id);
let json = {
...data,
devs: ids.join(',')
};
if(type == 1) {
this.props.editIOGroup(json);
}else {
this.props.addIOGroup(json);
}
this.closeModal()
}
querySelectList = (type) => {
this.props.clearSelectList();
if(!type) return ;
this.props.getSelectList({type});
}
removeSelect = (idx) => {
this.state.modalSelect.splice(idx, 1);
this.setState({
modalSelect: this.state.modalSelect
})
}
addSelect = (data = {}) => {
let tmp = this.state.modalSelect.filter(t => t.id == data.id);
if(tmp.length > 0) return ;
this.setState({
modalSelect: [...this.state.modalSelect, data]
})
}
delIOGroup = (id) => {
if(!id) return ;
this.props.delIOGroup({id});
}
componentDidMount() {
this.props.getIOGroupList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
render () {
let {i18n, list, dos, leones, permissions, devs} = this.props;
return (
<Container>
<Segment className="clearfix">
<Button basic type="button" color="green" floated="right" style={{marginBottom: '15px'}} icon="plus" content={i18n&&i18n.t ? i18n.t('page.iogroup.table.button.add') : ''} onClick={() => {this.openModal(0)}} />
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.iogroup.table.operate') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.iogroup.table.name') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.iogroup.table.groups') : ''}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
list.map((t, idx) => <ListItem i18n={i18n} key={idx} data={t} dos={dos} les={leones} openItemModal={this.showGroupItems} onDelete={this.delIOGroup} openModal={this.openModal}/>)
}
</Table.Body>
</Table>
</Segment>
<ShowGroupItem open={this.state.showItem} items={this.state.items} onClose={this.closeItemModal} />
<GroupModal i18n={i18n}
open={this.state.modal}
data={this.state.modalData}
type={this.state.modalType}
onClose={this.closeModal}
onSubmit={this.submitModal}
permissions={permissions}
devs={devs}
selected={this.state.modalSelect}
removeSelect={this.removeSelect}
addSelect={this.addSelect}
querySelectList={this.querySelectList} />
</Container>
)
}
}
const ShowGroupItem = ({i18n,open,items, onClose}) => {
return (
<Modal open={open} onClose={() => {onClose()}} size="small">
<Modal.Content>
{
items.map((t, idx) => <Item key={idx}><Label content={t.type}/>{t.name}</Item>)
}
</Modal.Content>
</Modal>
)
}
export default IOGroupPage;
@@ -0,0 +1,52 @@
import React from 'react';
import {Modal, Form, Header, Grid, Button, Input} from 'semantic-ui-react';
const CmdModal = ({i18n, open, id, devname, cmd, onSubmit, onClose}) => {
let actlist = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.action_list') : [];
let act = actlist.filter(t => t.cmd == cmd);
return (
<Modal open={open} closeOnDimmerClick={false}>
<Modal.Content>
<Form onSubmit={(e, d) => {
e.preventDefault();
onSubmit(d.formData);
}} serializer={e => {
let json = {
devs: `le${id}`
};
json.cmd = cmd;
if(json.cmd == 2){
let el = e.querySelector('input[name="temp"]');
if(el && 'value' in el){
json.cmd = `${json.cmd} ${el.value}`
}
}
return json;
}}>
<Header as="h4" content={devname || ''}/>
<Header as="h4" content={`${i18n&&i18n.t?i18n.t('page.leone.form.label.run_command'):''} ${act[0] ? act[0].name : ''}`} />
{
cmd && cmd == '2' ?
(<Form.Field>
<Input fluid name="temp" label={i18n&&i18n.t ? i18n.t('page.leone.form.label.temp') : ''}/>
</Form.Field>) :
null
}
<Grid columns={2} style={{marginTop: '15px'}}>
<Grid.Column>
<Button fluid type="submit" content={i18n&&i18n.t?i18n.t('page.leone.form.button.submit'):''}/>
</Grid.Column>
<Grid.Column>
<Button fluid type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.cancel'):''} onClick={() => {onClose()}}/>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default CmdModal;
@@ -0,0 +1,46 @@
import React from 'react';
import {Modal, Form, Input, Grid, Button} from 'semantic-ui-react';
const LeOneModal = ({i18n, open, type, data, onSubmit, onClose}) => {
return (
<Modal open={open}>
<Modal.Header content={i18n&&i18n.t ? (type == 1 ? i18n.t('page.leone.form.title.edit') : i18n.t('page.leone.form.title.add')) : '' } />
<Modal.Content>
<Form onSubmit={(e,d) => {
e.preventDefault();
onSubmit(type, d.formData);
}} serializer={e => {
let json = {
id: data.leonelistuid || 0,
name: e.querySelector('input[name="name"]').value,
ip: e.querySelector('input[name="ip"]').value,
password: e.querySelector('input[name="password"]').value
};
return json ;
}}>
<Form.Field>
<Input label={i18n&&i18n.t?i18n.t('page.leone.form.label.name'):''} name="name" defaultValue={data.leonename || ''} />
</Form.Field>
<Form.Field>
<Input label={i18n&&i18n.t?i18n.t('page.leone.form.label.ip'):''} name="ip" disabled={type == 1} defaultValue={data.leoneip || ''} />
</Form.Field>
<Form.Field>
<Input label={i18n&&i18n.t?i18n.t('page.leone.form.label.password'):''} name="password" defaultValue={data.leonepassword || ''} />
</Form.Field>
<Grid columns={2}>
<Grid.Column>
<Button fluid type="submit" content={i18n&&i18n.t?i18n.t('page.leone.form.button.submit'):''}/>
</Grid.Column>
<Grid.Column>
<Button fluid type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.cancel'):''} onClick={() => {onClose()}}/>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default LeOneModal;
@@ -0,0 +1,46 @@
import React from 'react';
import {Table, Button} from 'semantic-ui-react';
const ListItem = ({i18n, data, status, delLeone, editLeone, runCmd}) => {
let stats = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.leone_stats') : [];
let actlist = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.action_list') : [];
let st = stats.filter(t => t.mode == status.mode);
let tunit = i18n&&i18n.t ? [i18n.t('time_unit.sec'), i18n.t('time_unit.min'), i18n.t('time_unit.hour'), i18n.t('time_unit.day')] : [];
let idx = 0;
let mtime = Math.floor(Date.now() / 1000) - status.mtime;
while(idx < 3){
if(mtime >= 60){
mtime = Math.floor(mtime / 60);
idx++;
}else{
break;
}
}
return (
<Table.Row>
<Table.Cell>
<Button type="button" basic size="tiny" color="red" content={i18n&&i18n.t ? i18n.t('page.leone.table.button.del') : ''} onClick={() => {delLeone(data.leonelistuid)}} />
<Button type="button" basic size="tiny" color="blue" content={i18n&&i18n.t ? i18n.t('page.leone.table.button.edit') : ''} onClick={() => {editLeone(1, data)}} />
</Table.Cell>
<Table.Cell>{data.leonename}</Table.Cell>
<Table.Cell>{data.leoneip}</Table.Cell>
<Table.Cell>{`${status.ts == '9999' || !isFinite(status.ts) ? '-' : `${status.ts} ${String.fromCharCode(8451)}`} / ${status.hs == '9999' || !isFinite(status.hs) ? '-' : `${status.hs} %`}`}</Table.Cell>
<Table.Cell>{st[0]&&st[0].name ? st[0].name : status.mode}</Table.Cell>
<Table.Cell>{data.leonepassword}</Table.Cell>
<Table.Cell>{`${mtime}${tunit[idx]}${i18n&&i18n.t? i18n.t('time_unit.ago') : ''}`}</Table.Cell>
<Table.Cell>
<select onChange={(e)=>{
runCmd(data.leonelistuid, data.leonename, e.target.value);
e.target.selectedIndex = 0;
}}>
<option value="">{i18n&&i18n.t ? i18n.t('tip.select_action') : ''}</option>
{
actlist.map((t, idx) => <option key={idx} value={t.cmd}>{t.name}</option>)
}
</select>
</Table.Cell>
</Table.Row>
)
}
export default ListItem;
@@ -0,0 +1,52 @@
import React from 'react';
import {Container, Table, Segment, Form, Grid, Button, Input} from 'semantic-ui-react';
const ScanForm = ({i18n, onSubmit}) => {
return (
<Form onSubmit={(e, data) => {
e.preventDefault();
onSubmit(data.formData);
}} serializer={e => {
let json = {
ip1: e.querySelector('input[name="ip1"]').value,
ip2: e.querySelector('input[name="ip2"]').value,
ip3: e.querySelector('input[name="ip3"]').value,
password: e.querySelector('input[name="pass"]').value
};
return json;
}}>
<Grid verticalAlign="middle">
<Grid.Column computer={8} mobile={16}>
<Form.Group inline={true}>
<Form.Field>
<label>{i18n&&i18n.t ? i18n.t('page.leone.form.label.ip') : ''}</label>
<Input style={{width: '60px'}} defaultValue="192" name="ip1"/>
</Form.Field>
<Form.Field>
<Input style={{width: '60px'}} defaultValue="168" name="ip2"/>
</Form.Field>
<Form.Field>
<Input style={{width: '60px'}} defaultValue="1" name="ip3"/>
</Form.Field>
<Form.Field>
<Input style={{width: '60px'}} defaultValue="*" disabled/>
</Form.Field>
</Form.Group>
<Form.Group inline={true}>
<Form.Field>
<label>{i18n&&i18n.t ? i18n.t('page.leone.form.label.password') : ''}</label>
<Input name="pass" />
</Form.Field>
</Form.Group>
</Grid.Column>
<Grid.Column computer={8} mobile={16}>
<Button type="submit" fluid icon="search" content={i18n&&i18n.t ? i18n.t('page.leone.form.button.scan') : ''} />
</Grid.Column>
</Grid>
</Form>
)
}
export default ScanForm;
@@ -0,0 +1,123 @@
import React from 'react';
import {Modal, Grid, Label, Button, Table, Checkbox} from 'semantic-ui-react';
import ScanItem from './SelectScanItem';
class SelectScan extends React.Component {
state = {
list: [],
page: 1,
per: 10,
totalpage: 1
}
componentWillReceiveProps(nextProps) {
if(this.state.list.length !== nextProps.list) {
let totalpage = Math.ceil( nextProps.list.length / this.state.per ) || 1;
this.setState({
list: nextProps.list,
totalpage
});
}
}
onItemSelect = (idx, checked) => {
let list = [...this.state.list];
if(list[idx]){
list[idx].checked = checked;
this.setState({
list
});
}
}
changePage = (p = 1) => {
p = p < 1 ? 1 : p;
p = p > this.state.totalpage ? this.state.totalpage : p;
this.setState({
page: p
});
}
calSelect = () => {
let a = this.state.list.filter(t => t.checked);
return a.length;
}
checkAllSelect = (s, e) => {
let arr = this.state.list.slice(s,e);
let tmp = arr.filter(t => !t.checked);
if(tmp.length > 0) return false;
return true;
}
changeAllCheck = (s, e, chk) => {
let arr = [...this.state.list];
for(let i=s; i<e; i++){
arr[i].checked = chk;
}
this.setState({
list: arr
});
}
submitData = () => {
let json = {
id: []
};
for(let i in this.state.list) {
if(this.state.list[i].leonelistuid) json.id.push(this.state.list[i].leonelistuid)
}
this.props.onSubmit(json);
}
render () {
let {i18n, onClose} = this.props;
let sIdx = this.state.per * (this.state.page - 1);
let eIdx = sIdx + this.state.per;
eIdx = eIdx > this.state.list.length ? this.state.list.length : eIdx;
let arr = this.state.list.slice(sIdx, eIdx);
return (
<Modal open={this.state.list.length > 0 ? true : false} closeOnDimmerClick={false} >
<Modal.Header content={i18n&&i18n.t ? i18n.t('page.leone.form.title.select-dev') : ''} />
<Modal.Content>
<div className="clearfix">
<Label content={`${i18n&&i18n.t?i18n.t('page.leone.form.label.select_num') : ''} ${this.calSelect()}`} basic color="blue"/>
<div style={{float: 'right'}}>
<Button type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.prevpage') : ''} onClick={() => {this.changePage(this.state.page - 1)}} size="tiny" basic color="blue"/>
<Label basic content={`${this.state.page} / ${this.state.totalpage}`}/>
<Button type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.nextpage') : ''} onClick={() => {this.changePage(this.state.page + 1)}} size="tiny" basic color="blue"/>
</div>
</div>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell><Checkbox checked={this.checkAllSelect(sIdx, eIdx)} onChange={(e,d)=>{ this.changeAllCheck(sIdx, eIdx, d.checked) }} /></Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.form.label.name') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.form.label.name') : ''}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
arr.map((t, idx) => <ScanItem key={idx} i18n={i18n} data={t} idx={idx} onChange={this.onItemSelect}/>)
}
</Table.Body>
</Table>
<Grid columns={2}>
<Grid.Column>
<Button content={i18n&&i18n.t ? i18n.t('page.leone.form.button.submit') : ''} fluid onClick={() => {this.submitData()}}/>
</Grid.Column>
<Grid.Column>
<Button content={i18n&&i18n.t ? i18n.t('page.leone.form.button.cancel') : ''} fluid onClick={() => {onClose()}} />
</Grid.Column>
</Grid>
</Modal.Content>
</Modal>
)
}
}
export default SelectScan;
@@ -0,0 +1,12 @@
import React from 'react';
import {Table, Checkbox} from 'semantic-ui-react';
const ScanItem = ({i18n, data, idx, onChange}) => (
<Table.Row>
<Table.Cell><Checkbox onChange={(e,d) => {onChange(idx, d.checked)}} checked={data.checked} /></Table.Cell>
<Table.Cell>{data.leonename}</Table.Cell>
<Table.Cell>{data.leoneip}</Table.Cell>
</Table.Row>
)
export default ScanItem;
+174
View File
@@ -0,0 +1,174 @@
import React from 'react';
import {Container, Table, Segment, Form, Grid, Button} from 'semantic-ui-react';
import ScanForm from './ScanForm';
import {add_dialog_msg} from '../../../actions';
import SelectScan from './SelectScan';
import ListItem from './ListItem';
import LeOneModal from './LeOneModal';
import CmdModal from './CmdModal';
class LeOnePage extends React.Component {
state = {
modal: false,
modalType: 0,
modalData: {},
cmd: false,
cmdData: {
id: 0,
name: '',
cmd: ''
}
}
scanSubmit = (data) => {
let {i18n} = this.props;
if(!data.ip1.trim() || !data.ip2.trim() || !data.ip3.trim() || !data.password.trim())
return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
// send to scan
let json = {
ip: `${data.ip1}.${data.ip2}.${data.ip3}`,
password: data.password
};
this.props.scanLeOne(json);
}
doDelLeOne = (id) => {
let {i18n} = this.props;
if(!id) return;
this.props.delLeOne({id});
}
openModal = (type, data = {}) => {
this.setState({
modal: true,
modalType: type == 1 ? 1 : 0,
modalData: data
});
}
closeModal = () => {
this.setState({
modal: false,
modalData: {}
});
}
submitModal = (type, data ={}) => {
let {i18n} = this.props;
if((type == 1 && !data.id) || !data.name || !data.password || (type == 0 && !data.ip)) return this.props.showDialog(i18n&&i18n.t?i18n.t('tip.input_empty') : '')
if(type == 0){
this.props.addLeOne(data);
}else{
this.props.editLeOne(data);
}
this.closeModal();
}
openCmdModal = (id, name, cmd) => {
this.setState({
cmd: true,
cmdData: {
id,name,cmd
}
})
}
closeCmdModal = () => {
this.setState({
cmd: false,
cmdData: {
id: 0,
name: '',
cmd: ''
}
})
}
submitCmdModal = (data) => {
let {i18n} = this.props;
if(!data.devs || !data.cmd) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if(data.cmd.trim() == 2) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty_temp') : '');
let cmds = data.cmd.split(' ');
if(cmds.length != 2) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if(cmds[0] == 2 && (cmds[1] <16 || cmds[1] > 30) ) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.temp_format') : '');
this.props.runCmd(data);
this.closeCmdModal()
}
tick = null;
runTick = () => {
if(!this.props.scanning){
this.props.getLeOneList(0);
}
}
componentDidMount() {
this.props.getLeOneList();
this.tick = setInterval(this.runTick, 10000);
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
componentWillUnmount() {
clearInterval(this.tick);
}
componentWillReceiveProps(nextProps) {
}
render () {
let {i18n, scanList, clearScan, addScanLeOne, list, status} = this.props;
return (
<Container>
<Segment>
<ScanForm i18n={i18n} onSubmit={this.scanSubmit} />
</Segment>
<Segment className="clearfix">
<Button type="button" basic color="green" content={i18n&&i18n.t ? i18n.t('page.leone.table.button.add') : ''} style={{marginBottom: '10px'}} icon="plus" floated="right" onClick={() => {this.openModal(0)}} />
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.operate') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.name') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.ip') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.hsts') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.mode') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.password') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.update_time') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.leone.table.control') : ''}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
list.map(t => {
let st = {};
for(let i in status){
if(status[i].ip == t.leoneip) {
st = status[i];
break;
}
}
return <ListItem i18n={i18n} key={t.leonelistuid} status={st} data={t} delLeone={this.doDelLeOne} editLeone={this.openModal} runCmd={this.openCmdModal}/>
})
}
</Table.Body>
</Table>
</Segment>
<SelectScan i18n={i18n} list={scanList} onClose={clearScan} onSubmit={addScanLeOne}/>
<LeOneModal i18n={i18n} open={this.state.modal} type={this.state.modalType} data={this.state.modalData} onSubmit={this.submitModal} onClose={this.closeModal} />
<CmdModal i18n={i18n} open={this.state.cmd} id={this.state.cmdData.id} devname={this.state.cmdData.name} cmd={this.state.cmdData.cmd} onSubmit={this.submitCmdModal} onClose={this.closeCmdModal} />
</Container>
)
}
}
export default LeOnePage;
+32
View File
@@ -0,0 +1,32 @@
import React from 'react';
import {Table} from 'semantic-ui-react';
import {convertTime} from '../../../tools';
const LogItem = ({i18n, data}) => {
if(!(i18n && i18n.t)) return null;
let defMsg = '';
if(/^(do|di)/i.test(data.iolabel)){
defMsg = i18n.t('page.log.description.dio');
}else if(/^leone/i.test(data.iolabel)){
defMsg = i18n.t('page.log.description.leone');
}else if(/^iogroup/i.test(data.iolabel)){
defMsg = i18n.t('page.log.description.iogroup');
}
let msg = defMsg
.replace(/\$io_label\$/, data.iolabel)
.replace(/\$io_name\$/, data.ioname)
.replace(/\$io_logic\$/, data.iosetting1)
.replace(/\$io_trigger_time\$/, convertTime(data.ioeventtst))
.replace(/\$io_trigger_status\$/, data.ioevent);
return (
<Table.Row>
<Table.Cell>{convertTime(data.ioeventtst)}</Table.Cell>
<Table.Cell>{data.iosetting3}</Table.Cell>
<Table.Cell>{data.iosetting2}</Table.Cell>
<Table.Cell>{data.ioevent}</Table.Cell>
<Table.Cell>{msg}</Table.Cell>
</Table.Row>
)
}
export default LogItem;
+46
View File
@@ -0,0 +1,46 @@
import React from 'react';
import {Container, Table, Button, Label} from 'semantic-ui-react';
import LogItem from './LogItem';
class LogPage extends React.Component {
componentDidMount(){
this.props.getList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
loadPage = (p = 1) => {
this.props.getList(p);
}
render () {
let {i18n, list, page} = this.props;
return (
<Container>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.log.table.datetime') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.log.table.username') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.log.table.status') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.log.table.event') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.log.table.description') : ''}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{ list.map(t => <LogItem key={t.jciocertuid} i18n={i18n} data={t} />) }
</Table.Body>
</Table>
<div style={{textAlign: 'center'}}>
<Button content={i18n&&i18n.t ? i18n.t('page.log.table.button.prevpage') : ''} size="small" labelPosition="left" basic={true} color="black" icon="arrow left" onClick={() => {this.loadPage(page.prevpage)}} />
<Label basic={true} color="blue" content={`${page.page || 1} / ${page.totalpage || 1}`} />
<Button content={i18n&&i18n.t ? i18n.t('page.log.table.button.nextpage') : ''} size="small" labelPosition="right" basic={true} color="black" icon="arrow right" onClick={() => {this.loadPage(page.nextpage)}} />
</div>
</Container>
)
}
}
export default LogPage;
@@ -0,0 +1,40 @@
import React from 'react';
import {Table, Input, Form, Button} from 'semantic-ui-react';
const AIOForm = ({i18n, open, type, data, onSubmit, onClose}) => {
if(!open) return null;
let input = {
name: data.name || '',
portnum: data.portnum || '',
scale_min: data.scale_min || 0,
scale_max: data.scale_max || 0,
range_min: data.range_min || 0,
range_max: data.range_max || 0
}
return (
<Table.Row>
<Table.Cell><Input name="name" onChange={(e,d)=>{input.name = d.value}} defaultValue={data.name || ''}/></Table.Cell>
<Table.Cell><Input name="portnum" onChange={(e,d)=>{input.portnum = d.value}} defaultValue={data.portnum || ''}/></Table.Cell>
<Table.Cell>
<Input name="range_min" size="small" label="Min" onChange={(e,d)=>{input.range_min = d.value}} defaultValue={data.range_min || '0'}/>
<Input name="range_max" size="small" label="Max" onChange={(e,d)=>{input.range_max = d.value}} defaultValue={data.range_max || '0'}/>
</Table.Cell>
<Table.Cell>
<Input name="scale_min" size="small" label="Min" onChange={(e,d)=>{input.scale_min = d.value}} defaultValue={data.scale_min || '0'}/>
<Input name="scale_max" size="small" label="Max" onChange={(e,d)=>{input.scale_max = d.value}} defaultValue={data.scale_max || '0'}/>
</Table.Cell>
<Table.Cell>
<Button basic size="tiny" content="Submit" type="button" onClick={()=>{
let json = {
...input,
id: data.uid || ''
}
onSubmit(type, json);
}} />
<Button basic size="tiny" content="Cancel" type="button" onClick={()=>{onClose()}} />
</Table.Cell>
</Table.Row>
)
}
export default AIOForm;
@@ -0,0 +1,20 @@
import React from 'react';
import {Table, Button} from 'semantic-ui-react';
const AIOListItem = ({i18n, data, editAIO, delAIO}) => {
return (
<Table.Row>
<Table.Cell>{data.name || ''}</Table.Cell>
<Table.Cell>{data.portnum || ''}</Table.Cell>
<Table.Cell>{data.range_min || 0} ~ {data.range_max || 0}</Table.Cell>
<Table.Cell>{data.scale_min || 0} ~ {data.scale_max || 0}</Table.Cell>
<Table.Cell>
<Button type="button" basic size="tiny" content="Edit" onClick={()=>{editAIO(1, data)}} />
<Button type="button" basic size="tiny" content="Delete" onClick={()=>{delAIO(data.uid || '')}} />
</Table.Cell>
</Table.Row>
)
}
export default AIOListItem;
@@ -0,0 +1,72 @@
import React from 'react';
import {Modal, Table, Button, Input, Form} from 'semantic-ui-react';
import ListItem from './AIOListItem';
import AIOForm from './AIOForm';
class AIOModal extends React.Component {
state = {
editMode: false,
data: {},
type: 0
}
openEditField = (type, data = {}) => {
this.closeEditField(()=>{
this.setState({
editMode: true,
data,
type
});
});
}
closeEditField = (cb) => {
this.setState({
editMode: false,
data: {}
}, ()=>{
if(cb && typeof cb == 'function') cb()
});
}
submitAIO = (type, data) => {
data.iouid = this.props.iouid;
this.props.onSubmit(type, data);
this.closeEditField();
}
render() {
let {i18n, iouid, open, list, onClose, delAIO} = this.props;
return (
<Modal size="large" open={open} onClose={()=>{onClose()}}>
<Modal.Content className="clearfix">
<Button basic size="tiny" color="green" floated="right" style={{marginBottom: '10px'}} icon="plus" content="Add Set" onClick={()=>{
this.openEditField(0);
}}/>
<Table size="small">
<Table.Header>
<Table.Row>
<Table.HeaderCell>名稱</Table.HeaderCell>
<Table.HeaderCell>接口號碼</Table.HeaderCell>
<Table.HeaderCell>Range(Min-Max)</Table.HeaderCell>
<Table.HeaderCell>Scale(Min-Max)</Table.HeaderCell>
<Table.HeaderCell>操作</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
list.map((t,idx) => (
<ListItem key={idx} i18n={i18n} data={t} editAIO={this.openEditField} delAIO={delAIO}/>
))
}
</Table.Body>
<Table.Footer>
<AIOForm i18n={i18n} open={this.state.editMode} type={this.state.type} data={this.state.data} onSubmit={this.submitAIO} onClose={this.closeEditField}/>
</Table.Footer>
</Table>
</Modal.Content>
</Modal>
)
}
}
export default AIOModal;
@@ -0,0 +1,25 @@
import React from 'react';
import {Menu, Header} from 'semantic-ui-react';
import DevListItem from './DeviceListItem';
const DeviceList = ({i18n, list, delModbus, editModbus, showDev, selectDevToShow}) => {
return (
<Menu vertical={true}>
<Menu.Item>
<Menu.Header content="裝置列表" />
<Menu.Menu>
{
list.map((t, idx) => {
return (
<DevListItem key={idx} i18n={i18n} idx={idx} data={t} delModbus={delModbus} editModbus={editModbus} showDev={showDev} selectDevToShow={selectDevToShow}/>
)
})
}
</Menu.Menu>
</Menu.Item>
</Menu>
)
}
export default DeviceList;
@@ -0,0 +1,19 @@
import React from 'react';
import {List, Button, Icon} from 'semantic-ui-react';
const DeviceListItem = ({i18n, idx, data, delModbus, editModbus, showDev, selectDevToShow}) =>{
return (
<List.Item active={data.uid == showDev}>
<span style={{cursor: 'pointer'}} onClick={() => {
selectDevToShow(data.uid);
}}>
{data.name} / Node:{data.node}
</span>
<Icon style={{cursor: 'pointer'}} name="trash" onClick={()=>{delModbus(data.uid || '')}}/>
<Icon style={{cursor: 'pointer'}} name="write" onClick={()=>{editModbus(1, data)}}/>
</List.Item>
)
}
export default DeviceListItem;
@@ -0,0 +1,63 @@
import React from 'react';
import {Modal, Form, Button, Grid, Input } from 'semantic-ui-react';
const IOModal = ({i18n, open, type, data, onSubmit, onClose}) => {
let iotype = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.porttype') : [];
return (
<Modal open={open}>
<Modal.Header content={type == 1 ? '修改資料' : '新增資料'} />
<Modal.Content>
<Form onSubmit={(e,d)=>{
e.preventDefault();
onSubmit(type, d.formData);
}} serializer={e=>{
let json = {
id: data.uid || '',
addr: '',
num: '',
type: ''
};
let addr = e.querySelector('input[name="addr"]');
if(addr && 'value' in addr) json.addr = addr.value;
let num = e.querySelector('input[name="num"]');
if(num && 'value' in num) json.num = num.value;
let type = e.querySelector('select[name="io_type"]');
if(type && 'value' in type) json.type = type.value;
return json;
}}>
<Form.Field>
<label>接口類型</label>
<select name="io_type" defaultValue={data.type || ''} disabled={type == 1}>
<option value="">請選擇類型</option>
{
iotype.map((t,idx) => (
<option key={idx} value={t.code}>{t.name}</option>
))
}
</select>
</Form.Field>
<Form.Field>
<Input name="addr" label="起始位址" defaultValue={data.addr || ''} />
</Form.Field>
<Form.Field>
<Input name="num" label="數量" defaultValue={data.num || ''} />
</Form.Field>
<Grid columns={2}>
<Grid.Column>
<Button type="submit" fluid content="Submit" />
</Grid.Column>
<Grid.Column>
<Button type="button" fluid content="Cancel" onClick={()=>{onClose()}}/>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default IOModal ;
@@ -0,0 +1,89 @@
import React from 'react';
import {Menu, Segment, Table, Header, Label} from 'semantic-ui-react';
import {convertTime} from '../../../tools';
import IOPanelListItem from './IOPanelListItem';
class IOPanel extends React.Component {
state = {
tabIdx: '1'
}
tabItemClick = (e, el) => {
this.setState({
tabIdx: el.name
}, ()=>{
this.props.getStatus({id: this.props.data.uid || '', type: this.state.tabIdx});
});
}
componentWillReceiveProps(nprops) {
if(nprops.data && nprops.data.uid) {
if(this.props.data && this.props.data.uid){
if(this.props.data.uid != nprops.data.uid) {
this.props.getStatus({id: nprops.data.uid, type: this.state.tabIdx});
}
}else{
this.props.getStatus({id: nprops.data.uid, type: this.state.tabIdx});
}
}
}
render(){
let {i18n, show, data, ioModal, delIOList, showAIOSet} = this.props;
if(!show) return null;
let iolist = data.iolist || [];
let ios = iolist.filter(t => {
if(t.type == this.state.tabIdx) return t;
});
let status = data.status || {};
let ss = status[this.state.tabIdx] || [];
return (
<div>
<Menu attached="top" tabular>
<Menu.Item content="DigitOutput" name="1" active={this.state.tabIdx == "1"} onClick={this.tabItemClick} />
<Menu.Item content="DigitInput" name="2" active={this.state.tabIdx == "2"} onClick={this.tabItemClick} />
<Menu.Item content="AnalogyOutput" name="3" active={this.state.tabIdx == "3"} onClick={this.tabItemClick} />
<Menu.Item content="AnalogyInput" name="4" active={this.state.tabIdx == "4"} onClick={this.tabItemClick} />
<Menu.Menu position="right">
<Menu.Item content="AddIO" icon="plus" onClick={()=>{ioModal(0)}}/>
</Menu.Menu>
</Menu>
<Segment attached="bottom">
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>起始位置</Table.HeaderCell>
<Table.HeaderCell>接口數量</Table.HeaderCell>
<Table.HeaderCell>操作</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
ios.map((t,idx) => (
<IOPanelListItem key={idx} i18n={i18n} data={t} ioModal={ioModal} delIOList={delIOList} showAIOSet={showAIOSet} />
))
}
</Table.Body>
</Table>
<Segment>
<Header as="h3" content="接口資訊"/>
{
ss.map((t,idx) => (
<div key={idx}>
<Label basic color="blue" content={`PortNum:${t.port}`}/>
<Label basic color="blue" content={`原始數值:${t.value}`}/>
<Label basic color="blue" content={`轉換數值:${t.value2}`}/>
<Label basic color="green" content={`最後更新於:${convertTime(t.tst, true)}`}/>
</div>
))
}
</Segment>
</Segment>
</div>
)
}
}
export default IOPanel;
@@ -0,0 +1,24 @@
import React from 'react';
import {Table, Button} from 'semantic-ui-react';
const IOPanelListItem = ({i18n, data, ioModal, delIOList, showAIOSet}) => {
return (
<Table.Row>
<Table.Cell>{data.addr || ''}</Table.Cell>
<Table.Cell>{data.num || ''}</Table.Cell>
<Table.Cell>
<Button type="button" basic content="修改" onClick={()=>{ioModal(1, data)}}/>
<Button type="button" basic content="刪除" onClick={()=>{delIOList(data.uid || '')}}/>
{
data.type == 3 || data.type == 4 ?
(
<Button type="button" basic content="顯示設定" onClick={()=>{showAIOSet(data.uid)}} />
):null
}
</Table.Cell>
</Table.Row>
)
}
export default IOPanelListItem;
@@ -0,0 +1,49 @@
import React from 'react';
import {Modal, Form, Input, Grid, Button} from 'semantic-ui-react';
const ModbusModal = ({i18n, open, type, data, onSubmit, onClose}) => {
if(!i18n || Object.keys(i18n).length == 0) return null;
return (
<Modal open={open}>
<Modal.Header content={type == 1 ? '修改裝置' : '新增裝置'} />
<Modal.Content>
<Form onSubmit={(e, d) => {
e.preventDefault();
onSubmit(type, d.formData);
}} serializer={e => {
let json = {
name: '',
node: '',
id: data.uid || '',
original_node: data.node || ''
};
let n = e.querySelector('input[name="name"]');
if(n && 'value' in n) json.name = n.value;
let nn = e.querySelector('input[name="node"]');
if(nn && 'value' in nn) json.node = nn.value;
return json ;
}}>
<Form.Field>
<Input name="name" defaultValue={data.name || ''} label="Name"/>
</Form.Field>
<Form.Field>
<Input name="node" defaultValue={data.node || ''} label="Node"/>
</Form.Field>
<Grid columns={2}>
<Grid.Column>
<Button content="Submit" fluid type="submit" />
</Grid.Column>
<Grid.Column>
<Button content="Cancel" fluid type="button" onClick={()=>{onClose()}} />
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default ModbusModal;
+210
View File
@@ -0,0 +1,210 @@
import React from 'react';
import {Container, Segment, List, Menu, Item, Grid} from 'semantic-ui-react';
import DeviceList from './DeviceList';
import ModbusModal from './ModbusModal';
import IOPanel from './IOPanel';
import IOModal from './IOModal';
import AIOModal from './AIOModal';
const defIOModalState = {
open: false,
data: {},
type: 0
}
const defAIOModalState = {
open: false,
list: [],
iouid: 0
}
class ModbusPage extends React.Component {
state = {
mbModal: false,
mbType: 0,
mbData: {},
showDev: "",
ioModal:{
...defIOModalState
},
aioModal:{
...defAIOModalState
}
}
componentDidMount() {
this.props.getList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
});
}
componentWillReceiveProps(nprop) {
if(this.state.aioModal.open) {
this.openAIOModal(this.state.aioModal.iouid, nprop.list);
}
}
delModbus = id => {
if(!id) return ;
this.props.delModbus({id});
}
openModbusModal = (type, data = {}) => {
this.setState({
mbModal: true,
mbType: type,
mbData: data
});
}
closeModbusModal = () => {
this.setState({
mbModal: false,
mbData: {}
})
}
submitModbusModal = (type, data = {}) => {
let {i18n} = this.props;
if(type == 1 && (!data.id)) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if(!data.name || !('node' in data) || data.node.length == 0) return this.props.showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if(type == 1){
this.props.editModbus(data);
}else{
this.props.addModbus(data);
}
this.closeModbusModal();
}
selectDevToShow = (uid) => {
this.setState({
showDev: uid
});
this.props.getMBData({id: uid});
}
openIOModal = (type, data = {}) => {
this.setState({
ioModal: {
open: true,
type,
data
}
});
}
closeIOModal = () =>{
this.setState({
ioModal: {
...defIOModalState
}
})
}
submitIOModal = (type, data) => {
let {i18n} = this.props;
if((type == 1 && !data.id) || !('addr' in data) || !('num' in data) || !('type' in data)) return this.props.showDialog(i18n.t('tip.input_empty'));
data.devuid = this.state.showDev;
if(type == 1){
this.props.editIOList(data);
}else{
data.id = this.state.showDev;
this.props.addIOList(data);
}
this.closeIOModal();
}
delIOList = (id) => {
if(!id) return ;
this.props.delIOList({id, devuid: this.state.showDev});
}
openAIOModal = (id, nlist = []) => {
if(!id) return ;
let slist = nlist.length == 0 ? this.props.list : nlist;
let dev = slist.filter(t => {
if(t.uid == this.state.showDev) return t;
});
if(dev.length == 0) return ;
let aio = dev[0].aioset || [];
let list = aio.filter(t => {
if(t.iouid == id) return t;
});
this.setState({
aioModal:{
open: true,
list,
iouid: id
}
});
}
closeAIOModal = () => {
this.setState({
aioModal:{
...defAIOModalState
}
});
}
submitAIO = (type, data) => {
data.devuid = this.state.showDev;
if(type == 1){
this.props.editAIO(data);
}else{
this.props.addAIO(data);
}
// this.closeAIOModal();
}
delAIO = (id) => {
if(!id) return ;
this.props.delAIO({id, devuid: this.state.showDev});
}
render() {
let {i18n, list} = this.props;
let dev = list.filter(t => {
if(t.uid == this.state.showDev) return t;
});
return (
<Container>
<Menu>
<Menu.Menu position="right">
<Menu.Item name="新增裝置" icon="plus" onClick={()=>{this.openModbusModal(0)}}/>
</Menu.Menu>
</Menu>
<Grid>
<Grid.Column width={4}>
<DeviceList i18n={i18n}
list={list}
delModbus={this.delModbus}
editModbus={this.openModbusModal}
showDev={this.state.showDev}
selectDevToShow={this.selectDevToShow}/>
</Grid.Column>
<Grid.Column width={12}>
<IOPanel i18n={i18n}
show={dev.length > 0}
data={dev[0]}
ioModal={this.openIOModal}
delIOList={this.delIOList}
getStatus={this.props.getMBIOStatus}
showAIOSet={this.openAIOModal} />
</Grid.Column>
</Grid>
<ModbusModal i18n={i18n} open={this.state.mbModal} data={this.state.mbData} type={this.state.mbType} onSubmit={this.submitModbusModal} onClose={this.closeModbusModal} />
<IOModal i18n={i18n}
open={this.state.ioModal.open}
type={this.state.ioModal.type}
data={this.state.ioModal.data}
onClose={this.closeIOModal}
onSubmit={this.submitIOModal} />
<AIOModal i18n={i18n}
open={this.state.aioModal.open}
iouid={this.state.aioModal.iouid}
list={this.state.aioModal.list}
onSubmit={this.submitAIO}
delAIO={this.delAIO}
onClose={this.closeAIOModal} />
</Container>
)
}
}
export default ModbusPage;
@@ -0,0 +1,120 @@
import React from 'react';
import {Table, Button, Item, Label} from 'semantic-ui-react';
const ListItem = ({i18n, idx, data, dos, les, ios, changeActive, openModal, delItem, showGroup}) => {
let actlist = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.action_list') : [];
let weekArr = i18n&&i18n.t ? [
i18n.t('week.mon'),
i18n.t('week.tue'),
i18n.t('week.wed'),
i18n.t('week.thu'),
i18n.t('week.fri'),
i18n.t('week.sat'),
i18n.t('week.sun')
] : [];
let timeStr = '';
let min = data.ioscheduleparam1 || '';
let hour = data.ioscheduleparam2 || '';
let day = data.ioscheduleparam3 || '';
let month = data.ioscheduleparam4 || '';
let week = data.ioscheduleparam5 || '';
if(week != '-'){
let w = week.split(',');
let ws = [];
w.sort();
for(let i in w){
ws.push(weekArr[w[i] - 1] || '');
}
timeStr = `${ws.join(',')} ${hour}:${min}`;
}else{
timeStr = `${month}/${day} ${hour}:${min}`;
}
let act = data.ioschedulecmd || '';
act = act.split(',');
let actcmd = '';
let actname = '';
if(act.length == 2){
if(act[0] == 2){
actcmd = '2'
}else{
actcmd = act.join(' ');
}
}
if(actcmd.length > 0){
for(let i in actlist){
if(actlist[i].cmd == actcmd){
actname = actlist[i].name;
}
}
}
let devs = data.ioscheduleio || '';
let dev = devs.split(',');
let items = [];
if(dev.length > 0){
for(let i in dev){
if(/^do/i.test(dev[i])){
for(let j in dos){
if(`do${dos[j].douid}` == dev[i]) {
items.push({
type: 'DigitOutput',
name: dos[j].doname,
id: dev[i]
});
break;
}
}
}else if(/^le/i.test(dev[i])){
for(let j in les){
if(`le${les[j].leonelistuid}` == dev[i]) {
items.push({
type: 'LeOne',
name: les[j].leonename,
id: dev[i]
});
break;
}
}
}else if(/^iogroup/i.test(dev[i])){
for(let j in ios){
if(`iogroup${ios[j].iogroupuid}` == dev[i]){
items.push({
type: 'IOGroup',
name: ios[j].iogroupname,
id: dev[i]
});
}
}
}
}
}
return (
<Table.Row>
<Table.Cell>
<Button basic size="tiny" color={data.ioscheduleactive == 1 ? 'orange' : 'olive'}
content={i18n&&i18n.t ? (data.ioscheduleactive == 1 ? i18n.t('page.schedule.table.button.disable') : i18n.t('page.schedule.table.button.enable')) : ''}
onClick={()=>{ changeActive(data.ioscheduleuid || ''); }} />
<Button basic size="tiny" color="red" content={i18n&&i18n.t ? i18n.t('page.schedule.table.button.del') : ''} onClick={() => {delItem(data.ioscheduleuid || '')}} />
<Button basic size="tiny" color="blue" content={i18n&&i18n.t ? i18n.t('page.schedule.table.button.edit') : ''} onClick={() => {openModal(1, data, items);}} />
</Table.Cell>
<Table.Cell>{data.ioschedulename || ''}</Table.Cell>
<Table.Cell>{timeStr}</Table.Cell>
<Table.Cell>{actname}</Table.Cell>
<Table.Cell>{i18n&&i18n.t ? (data.ioscheduleactive == 1 ? i18n.t('page.schedule.table.button.enable') : i18n.t('page.schedule.table.button.disable')) : ''}</Table.Cell>
<Table.Cell>
{
items.length > 0 ?
(items.length == 1 ?
<Item><Label content={items[0].type} />{items[0].name}</Item>:
<Button size="tiny" basic content={i18n&&i18n.t ? i18n.t('page.schedule.table.button.showgroup') : ''} onClick={()=>{showGroup(items)}}/> ) :
''
}
</Table.Cell>
</Table.Row>
)
}
export default ListItem;
@@ -0,0 +1,158 @@
import React from 'react';
import {Modal, Form, Checkbox, Input, Radio, Segment, Header, List, Grid, Button} from 'semantic-ui-react';
import DateTime from 'react-datetime';
import DeviceSelect from '../../Common/DeviceSelect';
import SelectedItem from './SelectedItem';
class ScheduleModal extends React.Component {
render(){
let {i18n, open, data, type, devs, permissions, querySelectList, onSubmit, onClose} = this.props;
let {showTemp, week, cmd, temp, dateType, selected, addSelect, removeSelected, changeDateType, checkShowTemp, changeWeek} = this.props;
let actlist = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.action_list') : [];
let act = data.ioschedulecmd || '';
act = act.split(',');
let defcmd = '';
let deftemp = '';
if(act.length == 2){
if(act[0] == '2') {
defcmd = act[0];
deftemp = act[1];
}else {
defcmd = act.join(' ');
}
}
return (
<Modal open={open}>
<Modal.Header content={i18n&&i18n.t ? (type == 1 ? i18n.t('page.schedule.form.title.edut') : i18n.t('page.schedule.form.title.add')) : ''}/>
<Modal.Content>
<Form onSubmit={(e, d) => {
e.preventDefault();
onSubmit(type, d.formData);
}} serializer={e => {
let json = {
active: false,
name: '',
cmd: '',
temp: '',
time: '',
date: '',
id: data.ioscheduleuid || ''
};
let active = e.querySelector('input[name="active"]');
if(active && 'checked' in active) json.active = active.checked;
let name = e.querySelector('input[name="name"]');
if(name && 'value' in name) json.name = name.value;
let cmd = e.querySelector('select[name="act"]');
if(cmd && 'value' in cmd) json.cmd = cmd.value;
let time = e.querySelector('#timeDiv input');
if(time && 'value' in time) json.time = time.value;
let date = e.querySelector('#dateDiv input');
if(date && 'value' in date) json.date = date.value;
let temp = e.querySelector('input[name="temp"]');
if(temp && 'value' in temp) json.temp = temp.value;
return json;
}}>
<Form.Field>
{/*<label>{i18n&&i18n.t ? i18n.t('page.schedule.form.label.enable') : ''}</label>*/}
<Checkbox defaultChecked={data.ioscheduleactive == 1 ? true : false} name="active" label={i18n&&i18n.t ? i18n.t('page.schedule.form.label.enable') : ''} />
</Form.Field>
<Form.Field>
<Input label={i18n&&i18n.t ? i18n.t('page.schedule.form.label.name') : ''} name="name" defaultValue={data.ioschedulename} />
</Form.Field>
<Form.Field>
<label>{i18n&&i18n.t?i18n.t('page.schedule.form.label.action') : ''}</label>
<select name="act" value={cmd} onChange={(e) => { checkShowTemp(e.target.value); }}>
<option value="">{i18n&&i18n.t ? i18n.t('select.select_action') : ''}</option>
{
actlist.map((t, idx) => {
{/*let selected = defcmd == t.cmd ? 'selected' : 'false';*/}
return (
<option key={idx} value={t.cmd} >{t.name}</option>
)
})
}
</select>
</Form.Field>
{
showTemp ?
(<Form.Field>
<Input label={i18n&&i18n.t ? i18n.t('page.schedule.form.label.temp') : ''} name="temp" defaultValue={temp} />
</Form.Field>)
: null
}
<Form.Field id="timeDiv">
<label>{i18n&&i18n.t?i18n.t('page.schedule.form.label.time') : ''}</label>
<DateTime dateFormat={false} timeFormat="HH:mm" defaultValue={data.ioscheduleparam1&&data.ioscheduleparam2 ? `${data.ioscheduleparam2}:${data.ioscheduleparam1}` : ''} />
</Form.Field>
<Form.Field>
<label>{i18n&&i18n.t ? i18n.t('page.schedule.form.label.datetype') : ''}</label>
<Radio label={i18n&&i18n.t ? i18n.t('page.schedule.form.label.type_week') : ''} name="dtRadio" value="w" checked={dateType == 'w'} onChange={(e, {value}) => {changeDateType(value)}} />
<Radio label={i18n&&i18n.t ? i18n.t('page.schedule.form.label.type_date') : ''} name="dtRadio" value="d" checked={dateType == 'd'} onChange={(e, {value}) => {changeDateType(value)}} />
</Form.Field>
{
dateType == 'w' ?
(
<Form.Group inline>
<label>{i18n&&i18n.t ? i18n.t('page.schedule.form.label.week') : ''}</label>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.mon') : ''} value="1" checked={week.find(t => t == 1) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.tue') : ''} value="2" checked={week.find(t => t == 2) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.wed') : ''} value="3" checked={week.find(t => t == 3) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.thu') : ''} value="4" checked={week.find(t => t == 4) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.fri') : ''} value="5" checked={week.find(t => t == 5) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.sat') : ''} value="6" checked={week.find(t => t == 6) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
<Form.Field>
<Checkbox label={i18n&&i18n.t ? i18n.t('week.sun') : ''} value="7" checked={week.find(t => t == 7) ? true : false} onChange={(e, {value, checked}) => {changeWeek(checked, value)}}/>
</Form.Field>
</Form.Group>
) :
(
<Form.Field id="dateDiv">
<label>{i18n&&i18n.t?i18n.t('page.schedule.form.label.date'):''}</label>
<DateTime timeFormat={false} dateFormat="MM-DD" defaultValue={`${data.ioscheduleparam4}-${data.ioscheduleparam3}`} />
</Form.Field>
)
}
<DeviceSelect i18n={i18n} devs={devs} addSelect={addSelect} showGroup={true} permissions={permissions} querySelectList={querySelectList} page="schedule" />
<Segment>
<Header as="h4" content={i18n&&i18n.t ? i18n.t('page.schedule.form.label.selected_device') : ''} />
<List verticalAlign="middle" divided>
{
selected.map((t, idx) => (
<SelectedItem key={idx} i18n={i18n} data={t} idx={idx} removeSelected={removeSelected} />
))
}
</List>
</Segment>
<Grid columns={2}>
<Grid.Column>
<Button fluid type="submit" content={i18n&&i18n.t?i18n.t('page.leone.form.button.submit'):''}/>
</Grid.Column>
<Grid.Column>
<Button fluid type="button" content={i18n&&i18n.t?i18n.t('page.leone.form.button.cancel'):''} onClick={() => {onClose()}}/>
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
}
export default ScheduleModal;
@@ -0,0 +1,17 @@
import React from 'react';
import {List, Button, Label} from 'semantic-ui-react';
const SelectedItem = ({i18n, idx, data, removeSelected}) => {
return(
<List.Item>
<List.Content floated="right">
<Button type="button" size="mini" content={i18n&&i18n.t ? i18n.t('page.schedule.form.button.remove') : ''} onClick={() => {removeSelected(idx)}} />
</List.Content>
<Label content={data.type || ''} />
{data.name || ''}
</List.Item>
)
}
export default SelectedItem;
+297
View File
@@ -0,0 +1,297 @@
import React from 'react';
import {Container, Segment, Table, Button, Modal, Item, Label} from 'semantic-ui-react';
import ListItem from './ListItem';
import ScheduleModal from './ScheduleModal';
class SchedulePage extends React.Component {
state ={
modal: false,
modalType: 0,
modalData: {},
modalWeek: [],
modalShowTemp: false,
modalDateType: 'w',
modalSelected: [],
modalCmd: '',
modalTemp: '',
itemModal: false,
itemModalData: []
}
componentDidMount() {
this.props.getScheduleList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
changeActive = (id) => {
if(!id) return ;
this.props.swSchedule({id});
}
delItem = (id) => {
if(!id) return ;
this.props.delSchedule({id});
}
openModal = (type, data = {}, items = []) => {
let json = {
modal: true,
modalType: type,
modalData: data,
modalSelected: [...items]
}
if(type == 1){
let dtype = '';
if(data.ioscheduleparam5 && data.ioscheduleparam5 != '-'){
let ws = data.ioscheduleparam5.split(',');
let arr = [];
dtype = 'w';
for(let i in ws){
if(isFinite(ws[i]) && ws[i] >= 1 && ws[i] <= 7){
arr = [...arr, ws[i]];
}
}
json = {
...json,
modalWeek: [...arr]
};
// this.setState({
// week: [...arr]
// });
}else{
dtype = 'd';
}
let act = data.ioschedulecmd || '';
act = act.split(',');
if(act.length == 2){
if(act[0] == '2') {
json = {
...json,
modalShowTemp: true,
modalCmd: act[0],
modalTemp: act[1]
}
}else {
json ={
...json,
modalShowTemp: false,
modalCmd: act.join(' '),
modalTemp: ''
}
}
}
json = {
...json,
modalDateType: dtype
}
// this.setState({
// modalDateType: dtype
// })
}
this.setState({
...json
});
}
closeModal = () => {
this.setState({
modal: false,
modalType: 0,
modalData: {},
modalWeek: [],
modalShowTemp: false,
modalDateType: 'w',
modalSelected: [],
modalCmd: '',
modalTemp: ''
})
}
submitModal = (type, data) => {
let {i18n, showDialog} = this.props;
let json = {};
if(type == 1 && !data.id) return showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if(!data.name || !data.time || !data.cmd || (data.cmd == 2 && !data.temp) || (this.state.modalDateType == 'd' && !data.date))
return showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty') : '');
if((this.state.modalDateType == 'w' && this.state.modalWeek.length == 0)) return showDialog(i18n&&i18n.t ? i18n.t('tip.select_week') : '');
json.name = data.name;
json.active = data.active ? 1 : 0;
if(!/^\d{1,2}:\d{1,2}$/.test(data.time)) return showDialog(i18n&&i18n.t ? i18n.t('tip.input_format') : '');
let tarr = data.time.split(':');
if(tarr[0] < 0 || tarr[0] > 23 || tarr[1] < 0 || tarr[1] > 59) return showDialog(i18n&&i18n.t ? i18n.t('tip.time_range') : '');
json.min = tarr[1];
json.hour = tarr[0];
if(this.state.modalDateType == 'w'){
json.week = this.state.modalWeek.join(',');
}else{
json.day = '';
json.month = '';
if(!/^\d{1,2}\-\d{1,2}$/.test(data.date)) return showDialog(i18n&&i18n.t ? i18n.t('tip.date_format') : '');
let darr = data.date.split('-');
if(darr[0] < 1 || darr[0] > 12 || darr[1] < 1 || darr[1] > 31) return showDialog(i18n&&i18n.t ? i18n.t('tip.date_range') : '');
json.day = darr[1];
json.month = darr[0];
}
let tmp = this.state.modalSelected.map(t => t.id);
json.devs = tmp.join(',');
if(data.cmd == 2){
if(!data.temp) return showDialog(i18n&&i18n.t ? i18n.t('tip.input_empty_temp') : '');
if(!(data.temp >= 16 && data.temp <= 30)) return showDialog(i18n&&i18n.t ? i18n.t('tip.temp_format') : '');
json.action = `${data.cmd},${data.temp}`;
}else{
json.action = data.cmd.replace(' ', ',');
}
json.id = data.id;
if(type == 0){
this.props.addSchedule(json);
}else{
this.props.editSchedule(json);
}
this.closeModal();
}
showGroup = (items) => {
this.setState({
itemModal: true,
itemModalData: [...items]
});
}
closeGroupModal = () => {
this.setState({
itemModal: false,
itemModalData: []
});
}
querySelectList = (type) => {
this.props.getSelectList({type});
}
// ================================
addSelect = (data) => {
if(!data) return;
this.setState({
modalSelected: [...this.state.modalSelected, data]
})
}
removeSelected = (idx) => {
let items = [...this.state.modalSelected];
items.splice(idx, 1);
this.setState({
modalSelected: [...items]
});
}
checkShowTemp = (val) => {
this.setState({
modalShowTemp: val == 2 ? true : false,
modalCmd: val
});
}
changeDateType = (type) => {
if(!type) return;
this.setState({
modalDateType: type
})
}
changeWeek = (checked, value) => {
let week = this.state.modalWeek;
if(checked){
if(week.indexOf(value) == -1){
week.push(value);
}
}else{
if(week.indexOf(value) != -1){
week.splice(week.indexOf(value), 1);
}
}
this.setState({
modalWeek: [...week]
});
}
// ================================
render() {
let {i18n, devs, list, dos, les, ios, permissions} = this.props;
return (
<Container>
<Segment className="clearfix">
<Button type="button" floated="right" icon="plus" basic color="green" content={i18n&&i18n.t ? i18n.t('page.schedule.table.button.add') : ''} style={{marginBottom: '15px'}} onClick={() => {this.openModal(0)}}/>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.operate') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.name') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.schedule_time') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.action') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.active_status') : ''}</Table.HeaderCell>
<Table.HeaderCell>{i18n&&i18n.t ? i18n.t('page.schedule.table.device') : ''}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
list.map((t,idx) => (<ListItem key={idx} i18n={i18n} data={t} idx={idx} dos={dos} ios={ios} les={les} openModal={this.openModal} changeActive={this.changeActive} delItem={this.delItem} showGroup={this.showGroup} />))
}
</Table.Body>
</Table>
</Segment>
<ShowGroupItem i18n={i18n} open={this.state.itemModal} items={this.state.itemModalData} onClose={this.closeGroupModal} />
<ScheduleModal i18n={i18n}
open={this.state.modal}
data={this.state.modalData}
type={this.state.modalType}
querySelectList={this.querySelectList}
permissions={permissions}
devs={devs}
selected={this.state.modalSelected}
week={this.state.modalWeek}
showTemp={this.state.modalShowTemp}
dateType={this.state.modalDateType}
cmd={this.state.modalCmd}
temp={this.state.modalTemp}
addSelect={this.addSelect}
checkShowTemp={this.checkShowTemp}
removeSelected={this.removeSelected}
changeDateType={this.changeDateType}
changeWeek={this.changeWeek}
onClose={this.closeModal}
onSubmit={this.submitModal} />
</Container>
)
}
}
const ShowGroupItem = ({i18n,open,items, onClose}) => {
return (
<Modal open={open} onClose={() => {onClose()}} size="small">
<Modal.Content>
{
items.map((t, idx) => <Item key={idx}><Label content={t.type}/>{t.name}</Item>)
}
</Modal.Content>
</Modal>
)
}
export default SchedulePage;
@@ -0,0 +1,159 @@
import React from 'react';
import {} from '../../../actions';
import Datetime from 'react-datetime';
import {Container, Segment, Form, Header, Menu, Grid, Table, Input, Button} from 'semantic-ui-react';
class NetForm extends React.Component {
state = {
input: this.props.network && 'NETWORKMODE' in this.props.network && this.props.network['NETWORKMODE'] == 1 ? false : true,
ip: '',
netmask: '',
gateway: '',
dns: ''
}
changeActive = (active) => {
this.setState({input: active});
}
setInputState = (name, val) => {
let json = {};
json[name] = val;
this.setState(json);
}
componentWillReceiveProps(nextProps) {
// if(this.props.network['IP'] != nextProps.network['IP']){
// this.setState({ip: nextProps.network.ip});
this.setInputState('ip', nextProps.network['IP']);
// }
// if(this.props.network['NETMASK'] != nextProps.network['NETMASK']){
// this.setState({netmask: nextProps.network.netmask});
this.setInputState('netmask', nextProps.network['NETMASK']);
// }
// if(this.props.network['GATEWAY'] != nextProps.network['GATEWAY']){
// this.setState({gateway: nextProps.network['GATEWAY]});
this.setInputState('gateway', nextProps.network['GATEWAY']);
// }
// if(this.props.network['DNS'] !== nextProps.network['DNS']){
// this.setState({dns: nextProps.network['DNS]});
this.setInputState('dns', nextProps.network['DNS']);
// }
}
render() {
let {i18n, network, onSubmit} = this.props;
return (
<div>
<Menu widths={2}>
<Menu.Item active={this.state.input} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.button.dhcpip') : ''} onClick={()=>{this.changeActive(true)}}/>
<Menu.Item active={!this.state.input} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.button.manualip') : ''} onClick={()=>{this.changeActive(false)}}/>
</Menu>
<Form onSubmit={(e,data) => {
e.preventDefault();
onSubmit(data.formData);
}} serializer={e => {
let json = {
ip: e.querySelector('input[name="ip"]').value,
netmask: e.querySelector('input[name="netmask"]').value,
gateway: e.querySelector('input[name="gateway"]').value,
dns: e.querySelector('input[name="dns"]').value,
dhcpMode: this.state.input
}
return json;
}}>
<Table>
<Table.Body>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.ip') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="ip" value={this.state.ip} disabled={this.state.input} onChange={e=>{this.setInputState('ip', e.target.value)}}/>
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.netmask') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="netmask" value={this.state.netmask} disabled={this.state.input} onChange={e=>{this.setInputState('netmask', e.target.value)}}/>
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.gateway') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="gateway" value={this.state.gateway} disabled={this.state.input} onChange={e=>{this.setInputState('gateway', e.target.value)}}/>
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.dns') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="dns" value={this.state.dns} disabled={this.state.input} onChange={e=>{this.setInputState('dns', e.target.value)}}/>
</Table.Cell>
</Table.Row>
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.Cell colSpan="2">
<Button type="submit" fluid content={i18n && 't' in i18n ? i18n.t('page.system_info.form.button.update_network') :''}/>
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table>
</Form>
</div>
)
}
}
/*const NetForm = ({i18n, onSubmit, network}) => (
<Form onSubmit={(e,data) => {
e.preventDefault();
onSubmit(data.formData);
}} serializer={e => {
let json = {
ip: e.querySelector('input[name="ip"]').value,
netmask: e.querySelector('input[name="netmask"]').value,
gateway: e.querySelector('input[name="gateway"]').value,
dns: e.querySelector('input[name="dns"]').value
}
return json;
}}>
<Table>
<Table.Body>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.ip') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="ip" value={network['IP'] || ''} />
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.netmask') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="netmask" value={network['NETMASK'] || ''} />
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.gateway') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="gateway" value={network['GATEWAY'] || ''} />
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.dns') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Input fluid name="dns" value={network['DNS'] || ''} />
</Table.Cell>
</Table.Row>
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.Cell colSpan="2">
<Button type="submit" fluid content={i18n && 't' in i18n ? i18n.t('page.system_info.form.button.update_network') :''}/>
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table>
</Form>
)*/
export default NetForm;
@@ -0,0 +1,40 @@
import React from 'react';
import {} from '../../../actions';
import Datetime from 'react-datetime';
import {Container, Segment, Form, Header, Menu, Grid, Table, Input, Button} from 'semantic-ui-react';
import {convertTime} from '../../../tools';
const TimeForm = ({i18n, time, onSubmit}) => {
return (
<Form onSubmit={(e,data) => {
e.preventDefault();
onSubmit(data.formData);
}} serializer={e => {
let json = {};
json.time = e.querySelector('input').value || '';
return json;
}}>
<Table>
<Table.Body>
<Table.Row>
<Table.Cell width={8} content={i18n && 't' in i18n ? i18n.t('page.system_info.form.label.sysdate') : ''} textAlign="center"/>
<Table.Cell width={8} textAlign="center" >
<Datetime dateFormat="YYYY-MM-DD" timeFormat="HH:mm" value={convertTime(time)} input={true} />
</Table.Cell>
</Table.Row>
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.Cell colSpan="2">
<Button type="submit" fluid content={i18n && 't' in i18n ? i18n.t('page.system_info.form.button.update_time') :''} />
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table>
</Form>
)
}
export default TimeForm;
@@ -0,0 +1,57 @@
import React from 'react';
import {toggle_loading, get_network_info, get_system_time, add_dialog_msg,set_network_info, set_system_time} from '../../../actions';
import Datetime from 'react-datetime';
import {Container, Segment, Form, Header, Menu, Grid, Table, Input} from 'semantic-ui-react';
import NetForm from './NetForm';
import TimeForm from './TimeForm';
import {convertTime,padding} from '../../../tools';
class SysInfo extends React.Component {
componentDidMount(){
let {dispatch} = this.props;
// get network
dispatch(get_network_info());
//get time
dispatch(get_system_time());
}
netSubmit = (data) => {
let {dispatch, i18n} = this.props;
if(!data.dhcpMode){
if(!data.ip || !data.netmask || !data.gateway || !data.dns) return dispatch(add_dialog_msg(i18n && 't' in i18n ? i18n.t('tip.input_empty') : ''));
}
dispatch(set_network_info(data.dhcpMode, data.ip, data.netmask, data.gateway, data.dns));
}
timeSubmit = (data) => {
let {dispatch, i18n} = this.props;
let regex_date = /^([0-9]{4})\-([0-9]{2})\-([0-9]{2})\s([0-9]{1,2}):([0-9]{1,2})$/;
if(!('time' in data) || !data.time.trim() || !regex_date.test(data.time.trim())) return dispatch(add_dialog_msg(i18n && 't' in i18n ? i18n.t('tip.datetime_format') : ''));
let m = data.time.trim().match(regex_date);
if(!m) return dispatch(add_dialog_msg(i18n && 't' in i18n ? i18n.t('tip.datetime_format') : ''));
// MMDDHHmmYYYY
let dstr = `${m[2]}${m[3]}${padding(m[4], 2)}${padding(m[5], 2)}${m[1]}`;
dispatch(set_system_time(dstr));
}
render() {
let {i18n, network, time} = this.props;
return (
<Container>
<Segment>
<Header as="h2" content={i18n && 't' in i18n ? i18n.t('page.system_info.title.sysinfo') : ''} />
<NetForm i18n={i18n} network={network} onSubmit={this.netSubmit}/>
</Segment>
<Segment style={{marginBottom: '100px'}}>
<Header as="h2" content={i18n && 't' in i18n ? i18n.t('page.system_info.title.timeinfo') : ''} />
<TimeForm i18n={i18n} time={time} onSubmit={this.timeSubmit}/>
</Segment>
</Container>
)
}
}
export default SysInfo;
@@ -0,0 +1,26 @@
import React from 'react';
import {Table, Button} from 'semantic-ui-react';
const ListItem = ({i18n, user, openModal, delUser}) => {
let write = sessionStorage.getItem('write_privilege');
let account = sessionStorage.getItem('account');
return (
<Table.Row>
<Table.Cell>{user.account}</Table.Cell>
<Table.Cell>
{user.write_privilege == 1 ? 'W' : ''}{user.write_privilege == 1 && user.read_privilege == 1 ? ' / ' : ''}{user.read_privilege == 1 ? 'R' : ''}
</Table.Cell>
<Table.Cell>
{
(write == 1 && (user.account != 'admin' || (account == 'admin') ) ) || account == user.account ?
<Button type="button" content={i18n && i18n.t ? i18n.t('page.userlist.table.button.edit') : ''} onClick={() => openModal(user.account)}/> :
null
}
{write == 1 && user.account != 'admin' ? <Button type="button" content={i18n && i18n.t ? i18n.t('page.userlist.table.button.del') : ''} onClick={()=>delUser(user.account)}/> : null }
</Table.Cell>
</Table.Row>
)
}
export default ListItem;
@@ -0,0 +1,50 @@
import React from 'react';
import {Modal, Form, Input, Grid, Button, Checkbox} from 'semantic-ui-react';
const UModal = ({i18n, open, type, data, closeModal, onSubmit}) => {
return (
<Modal closeOnDimmerClick={false} open={open}>
<Modal.Content>
<Form onSubmit={(e, data) => {
e.preventDefault();
onSubmit(data.formData);
}}
serializer={e=>{
let json = {
type,
account: e.querySelector('input[name="account"]').value,
password: e.querySelector('input[name="password"]').value,
read_privilege: e.querySelector('input[name="read_privilege"]').checked ? 1 : 0,
write_privilege: e.querySelector('input[name="write_privilege"]').checked ? 1 : 0
};
return json;
}}>
<Form.Field>
<Input label={i18n && i18n.t ? i18n.t('page.userlist.form.label.account') : ''} name="account" disabled={type == 1} defaultValue={type == 1 ? data.account : ''} />
</Form.Field>
<Form.Field>
<Input type="password" label={i18n && i18n.t ? i18n.t('page.userlist.form.label.password') : ''} name="password" />
</Form.Field>
<Form.Field>
<Checkbox label={i18n && i18n.t ? i18n.t('page.userlist.form.label.read_privilege') : ''} defaultChecked={data.read_privilege == 1} name="read_privilege" />
</Form.Field>
<Form.Field>
<Checkbox label={i18n && i18n.t ? i18n.t('page.userlist.form.label.write_privilege') : ''} defaultChecked={data.write_privilege == 1} name="write_privilege" />
</Form.Field>
<Grid>
<Grid.Column width={8}>
<Button type="submit" fluid content={i18n && i18n.t ? i18n.t('page.userlist.form.button.submit') : ''} />
</Grid.Column>
<Grid.Column width={8}>
<Button type="button" fluid content={i18n && i18n.t ? i18n.t('page.userlist.form.button.cancel') : ''} onClick={() => closeModal()} />
</Grid.Column>
</Grid>
</Form>
</Modal.Content>
</Modal>
)
}
export default UModal;
@@ -0,0 +1,89 @@
import React from 'react';
import {Container, Segment, Header, Table, Button, Modal} from 'semantic-ui-react';
import ListItem from './ListItem';
import {get_user_list, add_dialog_msg, edit_user, add_user, del_user} from '../../../actions';
import UModal from './UserModal';
class UList extends React.Component {
state ={
edit: false,
// 0 is add , 1 is edit
editType: 0,
editData: {}
}
openModal = (acc) => {
if(!acc) return this.setState({edit: true, editType: 0});
let {users} = this.props;
let user = users.filter(t => t.account == acc);
this.setState({
edit: true,
editType: 1,
editData: user[0] || {}
});
}
closeModal = () => {
this.setState({edit: false, editData: {}});
}
onModalSubmit = (data) => {
let {i18n} = this.props;
if(data.type == 0 && (!data.account || !data.password)) return this.props.showDialog(i18n && i18n.t ? i18n.t('tip.input_empty') : '');
this.setState({edit: false, editData: {}});
if(data.type == 1){
this.props.editUser(data);
}else{
this.props.addUser(data);
}
}
delUser = (acc) => {
if(!acc) return ;
this.props.delUser({account: acc});
}
componentDidMount(){
this.props.getList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
})
}
render () {
let {i18n, users} = this.props;
return (
<Container>
<Segment>
<Header as="h2" content={i18n && 't' in i18n ? i18n.t('page.userlist.title.userlist') : ''} />
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={6} content={i18n && i18n.t ? i18n.t('page.userlist.table.account') : ''} />
<Table.HeaderCell width={6} content={i18n && i18n.t ? i18n.t('page.userlist.table.privilege') : ''} />
<Table.HeaderCell width={4} content={i18n && i18n.t ? i18n.t('page.userlist.table.operate') : ''} />
</Table.Row>
</Table.Header>
<Table.Body>
{
users.map(t => <ListItem key={t.account} i18n={i18n} user={t} openModal={this.openModal} delUser={this.delUser}/>)
}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.Cell colSpan="3">
<Button type="button" fluid content={i18n && i18n.t ? i18n.t('page.userlist.table.button.add') : ''} onClick={()=>this.openModal()}/>
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table>
</Segment>
<UModal i18n={i18n} open={this.state.edit} type={this.state.editType} data={this.state.editData} closeModal={this.closeModal} onSubmit={this.onModalSubmit}/>
</Container>
)
}
}
export default UList;