smallstonesk
4 years ago
10 changed files with 240 additions and 14 deletions
@ -0,0 +1,29 @@ |
|||
export interface ILocalConfig { |
|||
ip: string; |
|||
port: string; |
|||
} |
|||
|
|||
export const localConfig: ILocalConfig = { |
|||
ip: '127.0.0.1', |
|||
port: '3500' |
|||
}; |
|||
|
|||
export const updateLocalConfig = (config: ILocalConfig) => { |
|||
localConfig.ip = config.ip || localConfig.ip; |
|||
localConfig.port = config.port || localConfig.port; |
|||
} |
|||
|
|||
export const localConnect = () => { |
|||
return fetch(`http://${localConfig.ip}:${localConfig.port}/api/connect`, { |
|||
method: 'GET', |
|||
headers: {'content-type': 'application/json'} |
|||
}); |
|||
} |
|||
|
|||
export const localSave = (data: any) => { |
|||
fetch(`http://${localConfig.ip}:${localConfig.port}/api/save`, { |
|||
method: 'POST', |
|||
headers: {'content-type': 'application/json'}, |
|||
body: JSON.stringify(data) |
|||
}); |
|||
} |
@ -0,0 +1,64 @@ |
|||
import React, {useState, useEffect, useRef} from 'react'; |
|||
|
|||
import 'antd/es/form/style'; |
|||
import 'antd/es/modal/style'; |
|||
import 'antd/es/input/style'; |
|||
import styles from './index.module.less'; |
|||
|
|||
import {Input, Form, Modal} from 'antd'; |
|||
import {FormInstance} from 'antd/lib/form'; |
|||
import {ILocalConfig, localConfig, updateLocalConfig} from '../../../api'; |
|||
|
|||
const PORT_REGEX = /^\d{1,5}$/; |
|||
const IP_REGEX = /^(localhost)|(((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3})$/; |
|||
const makeRules = (regex: RegExp, errTip: string) => { |
|||
return [ |
|||
{required: true, message: '不能为空!'}, |
|||
{validator: (_: any, val: string) => regex.test(val) ? Promise.resolve() : Promise.reject(errTip)} |
|||
]; |
|||
} |
|||
|
|||
interface IEditorModalProps { |
|||
visible: boolean; |
|||
onOk: () => void; |
|||
onCancel: () => void; |
|||
} |
|||
|
|||
const EditModal: React.FC<IEditorModalProps> = props => { |
|||
|
|||
const {visible, onOk, onCancel} = props; |
|||
const formRef = useRef<FormInstance>(null); |
|||
|
|||
// events
|
|||
const onClickOk = (): void => { |
|||
formRef.current && formRef.current.validateFields().then((formValues) => { |
|||
onOk(); |
|||
updateLocalConfig(formValues as ILocalConfig); |
|||
}).catch(err => { |
|||
console.log(err.message); |
|||
}); |
|||
}; |
|||
|
|||
return ( |
|||
<Modal |
|||
className={styles.editModal} |
|||
visible={visible} |
|||
okText={'保存'} |
|||
cancelText={'取消'} |
|||
title={'本地连接配置'} |
|||
onOk={onClickOk} |
|||
onCancel={onCancel} |
|||
> |
|||
<Form ref={formRef} labelCol={{span: 4}} initialValues={localConfig}> |
|||
<Form.Item label={'ip'} name={'ip'} rules={makeRules(IP_REGEX, 'IP格式不合法')}> |
|||
<Input/> |
|||
</Form.Item> |
|||
<Form.Item label={'port'} name={'port'} rules={makeRules(PORT_REGEX, 'port格式不合法')}> |
|||
<Input/> |
|||
</Form.Item> |
|||
</Form> |
|||
</Modal> |
|||
); |
|||
}; |
|||
|
|||
export default EditModal; |
@ -0,0 +1,22 @@ |
|||
.container { |
|||
|
|||
display: flex; |
|||
flex-direction: row; |
|||
align-items: center; |
|||
margin-right: 20px; |
|||
|
|||
.error { |
|||
cursor: pointer; |
|||
} |
|||
} |
|||
|
|||
.editModal { |
|||
|
|||
width: 450px; |
|||
|
|||
:global { |
|||
.ant-form-item:last-child { |
|||
margin-bottom: 0; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,100 @@ |
|||
import React, {useState, useEffect} from 'react'; |
|||
|
|||
import 'antd/es/tag/style'; |
|||
import 'antd/es/modal/style'; |
|||
import 'antd/es/message/style'; |
|||
import styles from './index.module.less'; |
|||
|
|||
import {Graph} from '@antv/x6'; |
|||
import EditModal from './editModal'; |
|||
import {Tag, Modal, message} from 'antd'; |
|||
import {localConnect} from '../../../api'; |
|||
|
|||
enum Status { |
|||
connected = 'success', |
|||
disconnected = 'error' |
|||
} |
|||
|
|||
interface IProps { |
|||
flowChart: Graph | undefined; |
|||
} |
|||
|
|||
const PULSE_RATE = 10 * 1000; // try to connect to local servet per 10 seconds
|
|||
|
|||
const ConnectStatus: React.FC<IProps> = (props) => { |
|||
|
|||
const {flowChart} = props; |
|||
const [visible, setVisible] = useState<boolean>(false); |
|||
const [projectName, setProjectName] = useState<string>(''); |
|||
const [status, setStatus] = useState<Status>(Status.disconnected); |
|||
|
|||
// life
|
|||
useEffect(() => { |
|||
confirmToSync(); |
|||
const timer = setInterval(syncLocal, PULSE_RATE); |
|||
return () => clearInterval(timer); |
|||
}, []); |
|||
|
|||
// network
|
|||
const syncLocal = () => { |
|||
return localConnect().then(res => res.json()).then((data = {}) => { |
|||
const {projectName} = data; |
|||
setStatus(Status.connected); |
|||
setProjectName(projectName); |
|||
return data; |
|||
}).catch((err) => { |
|||
setStatus(Status.disconnected); |
|||
console.log('connect local failed, the error is:', err.message); |
|||
}); |
|||
}; |
|||
const confirmToSync = () => { |
|||
syncLocal().then(data => { |
|||
const {dsl} = data; |
|||
dsl && Modal.confirm({ |
|||
title: '本地连接成功,是否将数据同步至当前项目?', |
|||
onOk() { |
|||
try { |
|||
console.log(props.flowChart); |
|||
flowChart && flowChart.fromJSON(dsl); |
|||
} catch(err) { |
|||
message.error('同步失败!'); |
|||
} |
|||
} |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
// events
|
|||
const onOpenEditModal = (): void => { |
|||
setVisible(true); |
|||
}; |
|||
const onCloseEditModal = (): void => { |
|||
setVisible(false); |
|||
}; |
|||
const onOk = (): void => { |
|||
onCloseEditModal(); |
|||
confirmToSync(); |
|||
}; |
|||
|
|||
return ( |
|||
<div className={styles.container}> |
|||
{status === Status.connected && ( |
|||
<Tag color={'success'}> |
|||
{[projectName, '本地连接成功'].join(' ')} |
|||
</Tag> |
|||
)} |
|||
{status === Status.disconnected && ( |
|||
<Tag className={styles.error} color={'error'} onClick={onOpenEditModal}> |
|||
本地连接失败 点击修改配置 |
|||
</Tag> |
|||
)} |
|||
<EditModal |
|||
visible={visible} |
|||
onOk={onOk} |
|||
onCancel={onCloseEditModal} |
|||
/> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default ConnectStatus; |
Loading…
Reference in new issue