优化HostSelector组件

pull/605/head
vapao 2022-11-06 22:46:11 +08:00
parent 4cb86923d6
commit 06479a8e45
13 changed files with 190 additions and 196 deletions

View File

@ -9,7 +9,7 @@ import { Link } from 'react-router-dom';
import { Switch, Form, Input, Select, Button, Radio } from 'antd';
import Repo from './Repo';
import envStore from 'pages/config/environment/store';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import store from './store';
export default observer(function Ext1Setup1() {
@ -62,8 +62,7 @@ export default observer(function Ext1Setup1() {
</Form.Item>
</Form.Item>
<Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => store.selectorVisible = true}>选择主机</Button>
<HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
</Form.Item>
<Form.Item required label="Git仓库地址" extra={<span className="btn" onClick={() => setVisible(true)}>私有仓库</span>}>
<Input disabled={store.isReadOnly} value={info['git_repo']} onChange={e => info['git_repo'] = e.target.value}
@ -116,11 +115,6 @@ export default observer(function Ext1Setup1() {
disabled={!(info.env_id && info.git_repo && info.host_ids.length)}
onClick={() => store.page += 1}>下一步</Button>
</Form.Item>
<Selector
visible={store.selectorVisible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => store.selectorVisible = false}
onOk={(_, ids) => info.host_ids = ids}/>
{visible && <Repo url={info['git_repo']} onOk={v => info['git_repo'] = v} onCancel={() => setVisible(false)}/>}
</Form>
)

View File

@ -8,12 +8,11 @@ import { observer } from 'mobx-react';
import { Link } from 'react-router-dom';
import { Form, Switch, Select, Button, Input, Radio } from 'antd';
import envStore from 'pages/config/environment/store';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import store from './store';
export default observer(function Ext2Setup1() {
const [envs, setEnvs] = useState([]);
const [selectorVisible, setSelectorVisible] = useState(false);
function updateEnvs() {
const ids = store.currentRecord['deploys'].map(x => x.env_id);
@ -61,8 +60,7 @@ export default observer(function Ext2Setup1() {
</Form.Item>
</Form.Item>
<Form.Item required label="目标主机" tooltip="该发布配置作用于哪些目标主机。">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => setSelectorVisible(true)}>选择主机</Button>
<HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
</Form.Item>
<Form.Item label="发布模式" tooltip="串行即发布时一台完成后再发布下一台,期间出现异常则终止发布。并行则每个主机相互独立发布同时进行。">
<Radio.Group
@ -110,11 +108,6 @@ export default observer(function Ext2Setup1() {
disabled={!(info.env_id && info.host_ids.length)}
onClick={() => store.page += 1}>下一步</Button>
</Form.Item>
<Selector
visible={selectorVisible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => setSelectorVisible(false)}
onOk={(_, ids) => info.host_ids = ids}/>
</Form>
)
})

View File

@ -20,7 +20,6 @@ class Store {
@observable ext1Visible = false;
@observable ext2Visible = false;
@observable autoVisible = false;
@observable selectorVisible = false;
@observable f_name;
@observable f_desc;

View File

@ -6,9 +6,9 @@
import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react';
import { PlusOutlined, ThunderboltOutlined, BulbOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Form, Button, Alert, Radio, Tooltip } from 'antd';
import { Form, Button, Radio, Tooltip } from 'antd';
import { ACEditor, AuthDiv, Breadcrumb } from 'components';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import TemplateSelector from './TemplateSelector';
import Parameter from './Parameter';
import Output from './Output';
@ -87,17 +87,7 @@ function TaskIndex() {
<div className={style.index} hidden={store.showConsole}>
<Form layout="vertical" className={style.left}>
<Form.Item required label="目标主机">
{store.host_ids.length > 0 ? (
<Alert
type="info"
className={style.area}
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{store.host_ids.length}</b> </div>}
onClick={() => store.showHost = true}/>
) : (
<Button icon={<PlusOutlined/>} onClick={() => store.showHost = true}>
添加目标主机
</Button>
)}
<HostSelector type="button" value={store.host_ids} onChange={(_, ids) => store.host_ids = ids}/>
</Form.Item>
<Form.Item required label="执行命令" style={{position: 'relative'}}>
@ -144,12 +134,6 @@ function TaskIndex() {
{store.showTemplate && <TemplateSelector onCancel={store.switchTemplate} onOk={handleTemplate}/>}
{store.showConsole && <Output onBack={store.switchConsole}/>}
{visible && <Parameter parameters={parameters} onCancel={() => setVisible(false)} onOk={v => handleSubmit(v)}/>}
<Selector
visible={store.showHost}
selectedRowKeys={[...store.host_ids]}
onCancel={() => store.showHost = false}
onOk={(_, ids) => store.host_ids = ids}/>
</AuthDiv>
)
}

View File

@ -10,12 +10,6 @@
width: 60%;
border-right: 1px solid #dfdfdf;
.area {
cursor: pointer;
width: 200px;
height: 32px;
}
.tips {
position: absolute;
top: 10px;

View File

@ -11,7 +11,6 @@ class Store {
@observable tag = '';
@observable host_ids = [];
@observable token = null;
@observable showHost = false;
@observable showConsole = false;
@observable showTemplate = false;
@ -50,10 +49,6 @@ class Store {
}
}
switchHost = () => {
this.showHost = !this.showHost;
};
switchTemplate = () => {
this.showTemplate = !this.showTemplate
};

View File

@ -8,7 +8,7 @@ import { observer } from 'mobx-react';
import { ExclamationCircleOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import { Modal, Form, Input, Select, Button, Radio, Table, Tooltip, message } from 'antd';
import { ACEditor } from 'components';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import Parameter from './Parameter';
import { http, cleanCommand } from 'libs';
import lds from 'lodash';
@ -20,7 +20,6 @@ export default observer(function () {
const [body, setBody] = useState(S.record.body);
const [parameter, setParameter] = useState();
const [parameters, setParameters] = useState([]);
const [visible, setVisible] = useState(false);
useEffect(() => {
setParameters(S.record.parameters)
@ -136,18 +135,12 @@ export default observer(function () {
<Button type="link" style={{padding: 0}} onClick={() => setParameter({})}>添加参数</Button>
</Form.Item>
<Form.Item label="目标主机">
{info.host_ids.length > 0 && <span style={{marginRight: 16}}>已选择 {info.host_ids.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => setVisible(true)}>选择主机</Button>
<HostSelector value={info.host_ids} onChange={(_, ids) => info.host_ids = ids}/>
</Form.Item>
<Form.Item name="desc" label="备注信息">
<Input.TextArea placeholder="请输入模板备注信息"/>
</Form.Item>
</Form>
<Selector
visible={visible}
selectedRowKeys={[...info.host_ids]}
onCancel={() => setVisible(false)}
onOk={(_, ids) => info.host_ids = ids}/>
{parameter ? (
<Parameter
parameter={parameter}

View File

@ -6,16 +6,15 @@
import React, { useState, useEffect } from 'react';
import { observer } from 'mobx-react';
import {
PlusOutlined,
ThunderboltOutlined,
QuestionCircleOutlined,
UploadOutlined,
CloudServerOutlined,
BulbOutlined,
} from '@ant-design/icons';
import { Form, Button, Alert, Tooltip, Space, Card, Table, Input, Upload, message } from 'antd';
import { Form, Button, Tooltip, Space, Card, Table, Input, Upload, message } from 'antd';
import { AuthDiv, Breadcrumb } from 'components';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import Output from './Output';
import { http, uniqueId } from 'libs';
import moment from 'moment';
@ -27,7 +26,6 @@ function TransferIndex() {
const [files, setFiles] = useState([])
const [dir, setDir] = useState('')
const [hosts, setHosts] = useState([])
const [sProps, setSProps] = useState({visible: false})
const [percent, setPercent] = useState()
const [token, setToken] = useState()
const [histories, setHistories] = useState([])
@ -80,23 +78,14 @@ function TransferIndex() {
})
}
function handleAddHostFile() {
setSProps({
visible: true,
onlyOne: true,
selectedRowKeys: [],
onCancel: () => setSProps({visible: false}),
onOk: (_, __, row) => setFiles([{id: uniqueId(), type: 'host', name: row.name, path: '', host_id: row.id}]),
})
}
function handleAddHost() {
setSProps({
visible: true,
selectedRowKeys: hosts.map(x => x.id),
onCancel: () => setSProps({visible: false}),
onOk: (_, __, rows) => setHosts(rows),
})
function makeFile(row) {
setFiles([{
id: uniqueId(),
type: 'host',
name: row.name,
path: '',
host_id: row.id
}])
}
function handleUpload(_, fileList) {
@ -131,7 +120,9 @@ function TransferIndex() {
<Card type="inner" title={`数据源${files.length ? `${files.length}` : ''}`} extra={(<Space size={24}>
<Upload multiple beforeUpload={handleUpload}><Space
className="btn"><UploadOutlined/>上传本地文件</Space></Upload>
<Space className="btn" onClick={handleAddHostFile}><CloudServerOutlined/>添加主机文件</Space>
<HostSelector onlyOne onChange={(_, __, row) => makeFile(row)}>
<Space className="btn"><CloudServerOutlined/>添加主机文件</Space>
</HostSelector>
</Space>)}>
<Table rowKey="id" className={style.table} showHeader={false} pagination={false} size="small"
dataSource={files}>
@ -153,13 +144,7 @@ function TransferIndex() {
<Input value={dir} onChange={e => setDir(e.target.value)} placeholder="请输入目标路径"/>
</Form.Item>
<Form.Item required label="目标主机">
{hosts.length > 0 ? (<Alert
type="info"
className={style.area}
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{hosts.length}</b> </div>}
onClick={handleAddHost}/>) : (<Button icon={<PlusOutlined/>} onClick={handleAddHost}>
添加目标主机
</Button>)}
<HostSelector type="button" value={hosts.map(x => x.id)} onChange={(_, __, rows) => setHosts(rows)}/>
</Form.Item>
</Form>
</Card>
@ -191,7 +176,6 @@ function TransferIndex() {
</div>
</div>
</div>
<Selector {...sProps}/>
{token ? <Output token={token} onBack={handleCloseOutput}/> : null}
</AuthDiv>)
}

View File

@ -5,15 +5,15 @@
*/
import React, { useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import { Modal, Row, Col, Tree, Table, Button, Space, Input } from 'antd';
import { FolderOpenOutlined, FolderOutlined } from '@ant-design/icons';
import { Modal, Row, Col, Tree, Table, Button, Space, Input, Alert } from 'antd';
import { FolderOpenOutlined, FolderOutlined, PlusOutlined } from '@ant-design/icons';
import IPAddress from './IPAddress';
import hStore from './store';
import store from './store2';
import styles from './index.module.less';
import styles from './selector.module.less';
export default observer(function (props) {
function HostSelector(props) {
const [visible, setVisible] = useState(false)
const [isReady, setIsReady] = useState(false)
const [loading, setLoading] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
@ -42,8 +42,8 @@ export default observer(function (props) {
}, [store.treeData])
useEffect(() => {
setSelectedRowKeys(props.selectedRowKeys || [])
}, [props.selectedRowKeys])
setSelectedRowKeys([...props.value])
}, [props.value])
useEffect(() => {
if (props.onlySelf) {
@ -62,20 +62,19 @@ export default observer(function (props) {
}
function handleSubmit() {
if (props.onOk) {
if (props.onChange) {
setLoading(true);
let res
const selectedRows = store.rawRecords.filter(x => selectedRowKeys.includes(x.id))
if (props.onlyOne) {
res = props.onOk(store.group, selectedRowKeys[0], selectedRows[0])
res = props.onChange(store.group, selectedRowKeys[0], selectedRows[0])
} else {
res = props.onOk(store.group, selectedRowKeys, selectedRows);
res = props.onChange(store.group, selectedRowKeys, selectedRows);
}
if (res && res.then) {
res.then(props.onCancel, () => setLoading(false))
res.then(handleClose, () => setLoading(false))
} else {
props.onCancel();
setLoading(false)
handleClose()
}
}
}
@ -109,16 +108,45 @@ export default observer(function (props) {
)
}
function handleClose() {
setSelectedRowKeys([])
setLoading(false)
setVisible(false)
}
return (
<div className={styles.selector}>
{props.children ? (
<div onClick={() => setVisible(true)}>{props.children}</div>
) : (
props.type === 'button' ? (
props.value.length > 0 ? (
<Alert
type="info"
className={styles.area}
message={<div>已选择 <b style={{fontSize: 18, color: '#1890ff'}}>{props.value.length}</b> </div>}
onClick={() => setVisible(true)}/>
) : (
<Button icon={<PlusOutlined/>} onClick={() => setVisible(true)}>
添加目标主机
</Button>
)) : (
<div style={{display: 'flex', alignItems: 'center'}}>
{props.value.length > 0 && <span style={{marginRight: 16}}>已选择 {props.value.length} </span>}
<Button type="link" style={{padding: 0}} onClick={() => setVisible(true)}>选择主机</Button>
</div>
)
)}
<Modal
visible={[undefined, true].includes(props.visible)}
visible={visible}
width={1000}
className={styles.selector}
className={styles.modal}
title={props.title || '主机列表'}
onOk={handleSubmit}
okButtonProps={{disabled: selectedRowKeys.length === 0}}
confirmLoading={loading}
onCancel={props.onCancel}>
onCancel={handleClose}>
<Row>
<Col span={6} style={{borderRight: '8px solid #f0f0f0', paddingRight: 12}}>
<div className={styles.gTitle}>分组列表</div>
@ -171,5 +199,13 @@ export default observer(function (props) {
</Col>
</Row>
</Modal>
</div>
)
})
}
HostSelector.defaultProps = {
value: [],
type: 'text'
}
export default observer(HostSelector)

View File

@ -26,21 +26,6 @@
}
}
.selector {
:global(.ant-modal-footer) {
border-top: none
}
.gTitle {
height: 44px;
line-height: 44px;
padding-left: 12px;
font-weight: bold;
margin-bottom: 12px;
background: #fafafa;
}
}
.formAddress1 {
display: inline-block;

View File

@ -0,0 +1,46 @@
.modal {
:global(.ant-modal-footer) {
border-top: none
}
.gTitle {
height: 44px;
line-height: 44px;
padding-left: 12px;
font-weight: bold;
margin-bottom: 12px;
background: #fafafa;
}
}
.area {
cursor: pointer;
width: 200px;
height: 32px;
}
.treeNode {
display: flex;
flex-direction: row;
align-items: center;
.title {
margin-left: 8px;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.number {
width: 30px;
text-align: right;
}
}

View File

@ -8,7 +8,7 @@ import { observer } from 'mobx-react';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { Modal, Form, Input, Select, Button, message } from 'antd';
import TemplateSelector from '../exec/task/TemplateSelector';
import Selector from 'pages/host/Selector';
import HostSelector from 'pages/host/Selector';
import { LinkButton, ACEditor } from 'components';
import { http, cleanCommand } from 'libs';
import store from './store';
@ -22,7 +22,6 @@ const helpMap = {
export default observer(function () {
const [loading, setLoading] = useState(false);
const [showTmp, setShowTmp] = useState(false);
const [showSelector, setShowSelector] = useState(false);
function handleTest() {
setLoading(true)
@ -131,10 +130,7 @@ export default observer(function () {
notFoundContent={null}/>
</Form.Item>
<Form.Item required label="监控主机" style={getStyle(['3', '4'])}>
{store.record.targets?.length > 0 && (
<span style={{marginRight: 16}}>已选择 {store.record.targets.length} </span>
)}
<Button type="link" style={{padding: 0}} onClick={() => setShowSelector(true)}>选择主机</Button>
<HostSelector value={targets} onChange={(_, ids) => store.record.targets = ids}/>
</Form.Item>
<Form.Item label="响应时间" style={getStyle(['1'])}>
<Input suffix="ms" value={extra} placeholder="最长响应时间毫秒不设置则默认10秒超时"
@ -168,11 +164,6 @@ export default observer(function () {
<span style={{color: '#888', fontSize: 12}}>Tips: 仅测试第一个监控地址</span>
</Form.Item>
{showTmp && <TemplateSelector onOk={({body}) => store.record.extra = body} onCancel={() => setShowTmp(false)}/>}
<Selector
visible={showSelector}
selectedRowKeys={[...store.record.targets]}
onCancel={() => setShowSelector(false)}
onOk={(_, ids) => store.record.targets = ids}/>
</Form>
)
})

View File

@ -3,7 +3,7 @@
* Copyright (c) <spug.dev@gmail.com>
* Released under the AGPL-3.0 License.
*/
import React, { useState } from 'react';
import React from 'react';
import { observer } from 'mobx-react';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Form, Select, Button } from 'antd';
@ -13,7 +13,12 @@ import hostStore from 'pages/host/store';
import styles from './index.module.css';
export default observer(function () {
const [visible, setVisible] = useState(false)
function handleChange(_, ids) {
if (store.targets.includes('local')) {
ids.unshift('local')
}
store.targets = ids
}
return (
<React.Fragment>
@ -43,15 +48,10 @@ export default observer(function () {
))}
</Form.Item>
<Form.Item wrapperCol={{span: 14, offset: 6}}>
<Button type="dashed" style={{width: '80%'}} onClick={() => setVisible(true)}>
<PlusOutlined/>添加执行对象
</Button>
<HostSelector value={store.targets.filter(x => x !== 'local')} onChange={handleChange}>
<Button type="dashed" style={{width: '80%'}}><PlusOutlined/>添加执行对象</Button>
</HostSelector>
</Form.Item>
<HostSelector
visible={visible}
selectedRowKeys={[...store.targets]}
onCancel={() => setVisible(false)}
onOk={(_, ids) => store.targets = ids}/>
</Form>
<Form.Item wrapperCol={{span: 14, offset: 6}}>
<Button disabled={store.targets.filter(x => x).length === 0} type="primary"