anyproxy
Version:
A fully configurable HTTP/HTTPS proxy in Node.js
253 lines (219 loc) • 7.89 kB
JSX
/**
* The panel map request to local
*
*/
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { Tree, Form, Input, Button } from 'antd';
import ResizablePanel from 'component/resizable-panel';
import PromiseUtil from 'common/promiseUtil';
import { fetchDirectory, hideMapLocal, fetchMappedConfig, updateRemoteMappedConfig } from 'action/globalStatusAction';
import { MenuKeyMap } from 'common/constant';
import Style from './map-local.less';
import CommonStyle from '../style/common.less';
const TreeNode = Tree.TreeNode;
const createForm = Form.create;
const FormItem = Form.Item;
class MapLocal extends React.Component {
constructor () {
super();
this.state = {
selectedLocalPath: ''
};
this.loadTreeNode = this.loadTreeNode.bind(this);
this.onClose = this.onClose.bind(this);
this.getFormDiv = this.getFormDiv.bind(this);
this.onNodeSelect = this.onNodeSelect.bind(this);
this.getMappedConfigDiv = this.getMappedConfigDiv.bind(this);
this.loadMappedConfig = this.loadMappedConfig.bind(this);
this.addMappedConfig = this.addMappedConfig.bind(this);
this.removeMappedConfig = this.removeMappedConfig.bind(this);
}
static propTypes = {
dispatch: PropTypes.func,
globalStatus: PropTypes.object,
form: PropTypes.object
}
loadTreeNode(node) {
const d = PromiseUtil.defer();
const key = node ? node.props.eventKey : '';
this.props.dispatch(fetchDirectory(key));
setTimeout(function() {
d.resolve();
}, 500);
return d.promise;
}
loadMappedConfig() {
this.props.dispatch(fetchMappedConfig());
}
addMappedConfig () {
const config = this.props.globalStatus.mappedConfig.slice();
this.props.form.validateFieldsAndScroll((error, value) => {
config.push({
keyword: value.keyword,
local: value.local
});
this.props.dispatch(updateRemoteMappedConfig(config));
});
}
removeMappedConfig (index) {
const config = this.props.globalStatus.mappedConfig.slice();
config.splice(index, 1);
this.props.dispatch(updateRemoteMappedConfig(config));
}
loopTreeNode(nodes) {
const treeNodes = nodes.map((item) => {
if (item.children) {
return (
<TreeNode title={item.name} key={item.fullPath}>
{this.loopTreeNode(item.children)}
</TreeNode>
);
} else {
return <TreeNode title={item.name} key={item.fullPath} isLeaf={item.isLeaf} />;
}
});
return treeNodes;
}
onClose () {
this.props.dispatch(hideMapLocal());
}
onNodeSelect (selectedKeys, { selected, selectedNodes }) {
const node = selectedNodes[0];
// Only a file will be mapped
if (node && node.props.isLeaf) {
this.setState({
selectedLocalPath: selectedKeys[0]
});
}
}
getFormDiv () {
const { getFieldDecorator, getFieldError } = this.props.form;
const formItemLayout = {
labelCol: { span: 6 },
wrapperCol: { span: 18 },
};
const keywordProps = getFieldDecorator('keyword', {
initialValue: '',
validate: [
{
trigger: 'onBlur',
rules: [
{
type: 'string',
whitespace: true,
required: true,
message: '请录入需要映射的url匹配'
}
]
}
]
});
const localProps = getFieldDecorator('local', {
initialValue: this.state.selectedLocalPath,
validate: [
{
trigger: 'onBlur',
rules: [
{
type: 'string',
whitespace: true,
required: true,
message: '请输入本地文件路径'
}
]
}
]
});
return (
<div className={Style.form} >
<Form vertical >
<FormItem
label="Keyword"
>
{keywordProps(<Input placeholder="The pattern to map" />)}
</FormItem>
<FormItem
label="Local file"
>
{localProps(<Input placeholder="Local file for the mapped url" />)}
</FormItem>
</Form>
</div>
);
}
getMappedConfigDiv () {
const { mappedConfig } = this.props.globalStatus;
const mappedLiDiv = mappedConfig.map((item, index) => {
return (
<li key={index} >
<div>
<div className={Style.mappedKeyDiv} >
<strong>{item.keyword}</strong>
<a
href="javascript:void(0)"
onClick={this.removeMappedConfig.bind(this, index)}
>
Remove
</a>
</div>
<div className={Style.mappedLocal} >
{item.local}
</div>
</div>
</li>
);
});
return (
<div className={Style.mappedConfigWrapper} >
<div >
<span className={CommonStyle.sectionTitle}>Current Configuration</span>
</div>
<div className={CommonStyle.whiteSpace10} />
<ul className={Style.mappedList} >
{mappedLiDiv}
</ul>
</div>
);
}
componentDidMount () {
this.loadTreeNode();
this.loadMappedConfig();
}
render() {
const treeNodes = this.loopTreeNode(this.props.globalStatus.directory);
const panelVisible = this.props.globalStatus.activeMenuKey === MenuKeyMap.MAP_LOCAL;
return (
<ResizablePanel onClose={this.onClose} visible={panelVisible} >
<div className={Style.mapLocalWrapper} >
<div className={Style.title} >
Map Local
</div>
{this.getMappedConfigDiv()}
<div >
<span className={CommonStyle.sectionTitle}>Add Local Map</span>
</div>
<div className={CommonStyle.whiteSpace10} />
{this.getFormDiv()}
<div className={Style.treeWrapper} >
<Tree
loadData={this.loadTreeNode}
onSelect={this.onNodeSelect}
>
{treeNodes}
</Tree>
</div>
<div className={Style.operations} >
<Button type="primary" onClick={this.addMappedConfig} >Add</Button>
</div>
</div>
</ResizablePanel>
);
}
}
function select (state) {
return {
globalStatus: state.globalStatus
};
}
export default connect(select)(createForm()(MapLocal));