mirror of https://github.com/openspug/spug
style migrate v3
parent
a1a9792f1d
commit
97bbe7ddf0
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Modal, Card, Icon } from 'antd';
|
||||
import { BuildOutlined, OrderedListOutlined } from '@ant-design/icons';
|
||||
import { Modal, Card } from 'antd';
|
||||
import store from './store';
|
||||
import styles from './index.module.css';
|
||||
|
||||
|
@ -58,7 +59,7 @@ class AddSelect extends React.Component {
|
|||
bodyStyle={{display: 'flex'}}
|
||||
onClick={this.switchExt1}>
|
||||
<div style={{marginRight: 16}}>
|
||||
<Icon type="ordered-list" style={{fontSize: 36, color: '#1890ff'}}/>
|
||||
<OrderedListOutlined style={{fontSize: 36, color: '#1890ff'}} />
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.cardTitle}>常规发布</div>
|
||||
|
@ -72,7 +73,7 @@ class AddSelect extends React.Component {
|
|||
bodyStyle={{display: 'flex'}}
|
||||
onClick={this.switchExt2}>
|
||||
<div style={{marginRight: 16}}>
|
||||
<Icon type="build" style={{fontSize: 36, color: '#1890ff'}}/>
|
||||
<BuildOutlined style={{fontSize: 36, color: '#1890ff'}} />
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.cardTitle}>自定义发布</div>
|
||||
|
|
|
@ -49,7 +49,7 @@ class CloneConfirm extends React.Component {
|
|||
render() {
|
||||
const options = this.handleData(Object.values(toJS(store.records)));
|
||||
return (
|
||||
<Form>
|
||||
<Form layout="vertical" style={{marginTop: 24}}>
|
||||
<Form.Item
|
||||
required
|
||||
label="应用及环境"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Switch, Col, Form, Input, Select, Button } from "antd";
|
||||
import { Switch, Form, Input, Select, Button } from 'antd';
|
||||
import envStore from 'pages/config/environment/store';
|
||||
import store from './store';
|
||||
|
||||
|
@ -29,17 +29,17 @@ export default observer(function Ext1Setup1() {
|
|||
const info = store.deploy;
|
||||
return (
|
||||
<Form labelCol={{span: 6}} wrapperCol={{span: 14}}>
|
||||
<Form.Item required label="发布环境">
|
||||
<Col span={16}>
|
||||
<Form.Item required label="发布环境" style={{marginBottom: 0}}>
|
||||
<Form.Item style={{display: 'inline-block', width: '80%'}}>
|
||||
<Select disabled={store.isReadOnly} value={info.env_id} onChange={v => info.env_id = v} placeholder="请选择发布环境">
|
||||
{envStore.records.map(item => (
|
||||
<Select.Option disabled={envs.includes(item.id)} value={item.id} key={item.id}>{item.name}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={6} offset={2}>
|
||||
</Form.Item>
|
||||
<Form.Item style={{display: 'inline-block', width: '20%', textAlign: 'right'}}>
|
||||
<Link disabled={store.isReadOnly} to="/config/environment">新建环境</Link>
|
||||
</Col>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
<Form.Item required label="Git仓库地址">
|
||||
<Input disabled={store.isReadOnly} value={info['git_repo']} onChange={e => info['git_repo'] = e.target.value}
|
||||
|
@ -58,20 +58,21 @@ export default observer(function Ext1Setup1() {
|
|||
<a target="_blank" rel="noopener noreferrer"
|
||||
href="https://spug.dev/docs/install-error/#%E9%92%89%E9%92%89%E6%94%B6%E4%B8%8D%E5%88%B0%E9%80%9A%E7%9F%A5%EF%BC%9F">钉钉收不到通知?</a>
|
||||
</span>}>
|
||||
<Input addonBefore={(
|
||||
<Select disabled={store.isReadOnly}
|
||||
value={info['rst_notify']['mode']} style={{width: 100}}
|
||||
onChange={v => info['rst_notify']['mode'] = v}>
|
||||
<Select.Option value="0">关闭</Select.Option>
|
||||
<Select.Option value="1">钉钉</Select.Option>
|
||||
<Select.Option value="3">企业微信</Select.Option>
|
||||
<Select.Option value="2">Webhook</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
disabled={store.isReadOnly || info['rst_notify']['mode'] === '0'}
|
||||
value={info['rst_notify']['value']}
|
||||
onChange={e => info['rst_notify']['value'] = e.target.value}
|
||||
placeholder="请输入"/>
|
||||
<Input
|
||||
addonBefore={(
|
||||
<Select disabled={store.isReadOnly}
|
||||
value={info['rst_notify']['mode']} style={{width: 100}}
|
||||
onChange={v => info['rst_notify']['mode'] = v}>
|
||||
<Select.Option value="0">关闭</Select.Option>
|
||||
<Select.Option value="1">钉钉</Select.Option>
|
||||
<Select.Option value="3">企业微信</Select.Option>
|
||||
<Select.Option value="2">Webhook</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
disabled={store.isReadOnly || info['rst_notify']['mode'] === '0'}
|
||||
value={info['rst_notify']['value']}
|
||||
onChange={e => info['rst_notify']['value'] = e.target.value}
|
||||
placeholder="请输入"/>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Form, Input, Select, Button, Icon, message } from "antd";
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { Form, Input, Select, Button, message } from "antd";
|
||||
import { hasHostPermission } from 'libs';
|
||||
import store from './store';
|
||||
import hostStore from 'pages/host/store';
|
||||
|
@ -55,7 +56,7 @@ class Ext1Setup2 extends React.Component {
|
|||
showSearch
|
||||
placeholder="请选择"
|
||||
disabled={store.isReadOnly}
|
||||
style={{width: '80%', marginRight: 10}}
|
||||
style={{width: '80%', marginRight: 10, marginBottom: 12}}
|
||||
optionFilterProp="children"
|
||||
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
||||
onChange={v => store.editHost(index, v)}>
|
||||
|
@ -66,14 +67,14 @@ class Ext1Setup2 extends React.Component {
|
|||
))}
|
||||
</Select>
|
||||
{!store.isReadOnly && info['host_ids'].length > 1 && (
|
||||
<Icon className={styles.delIcon} type="minus-circle-o" onClick={() => store.delHost(index)}/>
|
||||
<MinusCircleOutlined className={styles.delIcon} onClick={() => store.delHost(index)} />
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button disabled={store.isReadOnly} type="dashed" style={{width: '80%'}} onClick={store.addHost}>
|
||||
<Icon type="plus"/>添加目标主机
|
||||
<PlusOutlined />添加目标主机
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Form, Row, Col, Button, Radio, Icon, Tooltip, message } from "antd";
|
||||
import { GitlabOutlined, InfoCircleOutlined, SettingOutlined, SwapOutlined } from '@ant-design/icons';
|
||||
import { Form, Row, Col, Button, Radio, Tooltip, message } from 'antd';
|
||||
import { LinkButton } from 'components';
|
||||
import Editor from 'react-ace';
|
||||
import 'ace-builds/src-noconflict/mode-text';
|
||||
|
@ -51,9 +52,17 @@ class Ext1Setup3 extends React.Component {
|
|||
}, () => this.setState({loading: false}))
|
||||
};
|
||||
|
||||
handleFullscreen = (id) => {
|
||||
if (this.state.full) {
|
||||
this.setState({full: ''})
|
||||
} else {
|
||||
this.setState({full: id})
|
||||
}
|
||||
}
|
||||
|
||||
FilterLabel = (props) => (
|
||||
<div style={{display: 'inline-block', height: 39, width: 390}}>
|
||||
<span style={{float: 'left'}}>文件过滤<span style={{margin: '0 8px 0 2px'}}>:</span></span>
|
||||
<div style={{display: 'flex', alignItems: 'center', height: 40}}>
|
||||
<div>文件过滤 :</div>
|
||||
<Radio.Group
|
||||
disabled={store.isReadOnly}
|
||||
style={{marginLeft: 20, float: 'left'}}
|
||||
|
@ -61,36 +70,30 @@ class Ext1Setup3 extends React.Component {
|
|||
onChange={e => store.deploy['filter_rule']['type'] = e.target.value}>
|
||||
<Radio value="contain">包含
|
||||
<Tooltip title="请输入相对于项目根目录的文件路径,仅将匹配到文件传输至要发布的目标主机。">
|
||||
<Icon type="info-circle" style={{color: '#515151', marginLeft: 8}}/>
|
||||
<InfoCircleOutlined style={{color: '#515151', marginLeft: 8}}/>
|
||||
</Tooltip>
|
||||
</Radio>
|
||||
<Radio value="exclude">排除
|
||||
<Tooltip title="支持模糊匹配,如果路径以 / 开头则基于项目根目录匹配,匹配到文件将不会被传输。">
|
||||
<Icon type="info-circle" style={{color: '#515151', marginLeft: 8}}/>
|
||||
<InfoCircleOutlined style={{color: '#515151', marginLeft: 8}}/>
|
||||
</Tooltip>
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
{this.state.full === '1' ? (
|
||||
<LinkButton onClick={() => this.setState({full: ''})}>退出全屏</LinkButton>
|
||||
) : (
|
||||
<LinkButton onClick={() => this.setState({full: '1'})}>全屏</LinkButton>
|
||||
)}
|
||||
<div style={{flex: 1, textAlign: 'right'}}>
|
||||
<LinkButton onClick={() => this.handleFullscreen('1')}>{this.state.full ? '退出全屏' : '全屏'}</LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
NormalLabel = (props) => (
|
||||
<div style={{display: 'inline-block', height: 39, width: 390}}>
|
||||
<span style={{float: 'left'}}>
|
||||
{props.title}<span style={{margin: '0 8px 0 2px'}}>:</span>
|
||||
<Tooltip title={this.helpMap[props.id]}>
|
||||
<Icon type="info-circle" style={{color: '#515151'}}/>
|
||||
</Tooltip>
|
||||
</span>
|
||||
{this.state.full ? (
|
||||
<span style={{color: '#1890ff', cursor: 'pointer'}} onClick={() => this.setState({full: ''})}>退出全屏</span>
|
||||
) : (
|
||||
<span style={{color: '#1890ff', cursor: 'pointer'}} onClick={() => this.setState({full: props.id})}>全屏</span>
|
||||
)}
|
||||
<div style={{display: 'flex', alignItems: 'center', height: 40}}>
|
||||
<div style={{marginRight: 8}}>{props.title} :</div>
|
||||
<Tooltip title={this.helpMap[props.id]}>
|
||||
<InfoCircleOutlined style={{color: '#515151'}}/>
|
||||
</Tooltip>
|
||||
<div style={{flex: 1, textAlign: 'right'}}>
|
||||
<LinkButton onClick={() => this.handleFullscreen(props.id)}>{this.state.full ? '退出全屏' : '全屏'}</LinkButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -101,10 +104,8 @@ class Ext1Setup3 extends React.Component {
|
|||
<React.Fragment>
|
||||
<Row>
|
||||
<Col span={11}>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '1' ? styles.fullScreen : null}
|
||||
label={<this.FilterLabel type={info['filter_rule']['type']}/>}>
|
||||
<div className={full === '1' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.FilterLabel type={info['filter_rule']['type']}/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="text"
|
||||
|
@ -115,11 +116,9 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['filter_rule']['data']}
|
||||
onChange={v => info['filter_rule']['data'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '3' ? styles.fullScreen : null}
|
||||
label={<this.NormalLabel title="代码检出前执行" id="3"/>}>
|
||||
</div>
|
||||
<div className={full === '3' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.NormalLabel title="代码检出前执行" id="3"/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="sh"
|
||||
|
@ -130,11 +129,9 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['hook_pre_server']}
|
||||
onChange={v => info['hook_pre_server'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '5' ? styles.fullScreen : null}
|
||||
label={<this.NormalLabel title="应用发布前执行" id="5"/>}>
|
||||
</div>
|
||||
<div className={full === '5' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.NormalLabel title="应用发布前执行" id="5"/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="sh"
|
||||
|
@ -145,27 +142,25 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['hook_pre_host']}
|
||||
onChange={v => info['hook_pre_host'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={2}>
|
||||
<div className={styles.deployBlock} style={{marginTop: 39}}>
|
||||
<Icon type="setting" style={{fontSize: 32}}/>
|
||||
<SettingOutlined style={{fontSize: 32}}/>
|
||||
<span style={{fontSize: 12, marginTop: 5}}>基础设置</span>
|
||||
</div>
|
||||
<div className={styles.deployBlock}>
|
||||
<Icon type="gitlab" style={{fontSize: 32}}/>
|
||||
<GitlabOutlined style={{fontSize: 32}}/>
|
||||
<span style={{fontSize: 12, marginTop: 5}}>检出代码</span>
|
||||
</div>
|
||||
<div className={styles.deployBlock}>
|
||||
<Icon type="swap" style={{fontSize: 32}}/>
|
||||
<SwapOutlined style={{fontSize: 32}}/>
|
||||
<span style={{fontSize: 12, marginTop: 5}}>版本切换</span>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={11}>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '2' ? styles.fullScreen : null}
|
||||
label={<this.NormalLabel title="自定义全局变量" id="2"/>}>
|
||||
<div className={full === '2' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.NormalLabel title="自定义全局变量" id="2"/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="text"
|
||||
|
@ -176,11 +171,9 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['custom_envs']}
|
||||
onChange={v => info['custom_envs'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '4' ? styles.fullScreen : null}
|
||||
label={<this.NormalLabel title="代码检出后执行" id="4"/>}>
|
||||
</div>
|
||||
<div className={full === '4' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.NormalLabel title="代码检出后执行" id="4"/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="sh"
|
||||
|
@ -191,11 +184,9 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['hook_post_server']}
|
||||
onChange={v => info['hook_post_server'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
colon={false}
|
||||
className={full === '6' ? styles.fullScreen : null}
|
||||
label={<this.NormalLabel title="应用发布后执行" id="6"/>}>
|
||||
</div>
|
||||
<div className={full === '6' ? styles.fullScreen : null} style={{marginBottom: 24}}>
|
||||
<this.NormalLabel title="应用发布后执行" id="6"/>
|
||||
<Editor
|
||||
readOnly={store.isReadOnly}
|
||||
mode="sh"
|
||||
|
@ -206,7 +197,7 @@ class Ext1Setup3 extends React.Component {
|
|||
value={info['hook_post_host']}
|
||||
onChange={v => info['hook_post_host'] = cleanCommand(v)}
|
||||
style={{border: '1px solid #e8e8e8'}}/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Switch, Col, Form, Select, Button, Input } from "antd";
|
||||
import { Form, Switch, Select, Button, Input } from "antd";
|
||||
import envStore from 'pages/config/environment/store';
|
||||
import store from './store';
|
||||
|
||||
|
@ -29,17 +29,17 @@ export default observer(function Ext2Setup1() {
|
|||
const info = store.deploy;
|
||||
return (
|
||||
<Form labelCol={{span: 6}} wrapperCol={{span: 14}}>
|
||||
<Form.Item required label="发布环境">
|
||||
<Col span={16}>
|
||||
<Form.Item required label="发布环境" style={{marginBottom: 0}}>
|
||||
<Form.Item style={{display: 'inline-block', width: '80%'}}>
|
||||
<Select disabled={store.isReadOnly} value={info.env_id} onChange={v => info.env_id = v} placeholder="请选择发布环境">
|
||||
{envStore.records.map(item => (
|
||||
<Select.Option disabled={envs.includes(item.id)} value={item.id} key={item.id}>{item.name}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={6} offset={2}>
|
||||
</Form.Item>
|
||||
<Form.Item style={{display: 'inline-block', width: '20%', textAlign: 'right'}}>
|
||||
<Link disabled={store.isReadOnly} to="/config/environment">新建环境</Link>
|
||||
</Col>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
<Form.Item label="发布审核">
|
||||
<Switch
|
||||
|
@ -54,20 +54,21 @@ export default observer(function Ext2Setup1() {
|
|||
<a target="_blank" rel="noopener noreferrer"
|
||||
href="https://spug.dev/docs/install-error/#%E9%92%89%E9%92%89%E6%94%B6%E4%B8%8D%E5%88%B0%E9%80%9A%E7%9F%A5%EF%BC%9F">钉钉收不到通知?</a>
|
||||
</span>}>
|
||||
<Input addonBefore={(
|
||||
<Select disabled={store.isReadOnly}
|
||||
value={info['rst_notify']['mode']} style={{width: 100}}
|
||||
onChange={v => info['rst_notify']['mode'] = v}>
|
||||
<Select.Option value="0">关闭</Select.Option>
|
||||
<Select.Option value="1">钉钉</Select.Option>
|
||||
<Select.Option value="3">企业微信</Select.Option>
|
||||
<Select.Option value="2">Webhook</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
disabled={store.isReadOnly || info['rst_notify']['mode'] === '0'}
|
||||
value={info['rst_notify']['value']}
|
||||
onChange={e => info['rst_notify']['value'] = e.target.value}
|
||||
placeholder="请输入"/>
|
||||
<Input
|
||||
addonBefore={(
|
||||
<Select disabled={store.isReadOnly}
|
||||
value={info['rst_notify']['mode']} style={{width: 100}}
|
||||
onChange={v => info['rst_notify']['mode'] = v}>
|
||||
<Select.Option value="0">关闭</Select.Option>
|
||||
<Select.Option value="1">钉钉</Select.Option>
|
||||
<Select.Option value="3">企业微信</Select.Option>
|
||||
<Select.Option value="2">Webhook</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
disabled={store.isReadOnly || info['rst_notify']['mode'] === '0'}
|
||||
value={info['rst_notify']['value']}
|
||||
onChange={e => info['rst_notify']['value'] = e.target.value}
|
||||
placeholder="请输入"/>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Form, Select, Button, Icon } from "antd";
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { Form, Select, Button } from 'antd';
|
||||
import { hasHostPermission } from 'libs';
|
||||
import store from './store';
|
||||
import hostStore from 'pages/host/store';
|
||||
|
@ -32,7 +33,7 @@ class Ext2Setup2 extends React.Component {
|
|||
disabled={store.isReadOnly}
|
||||
placeholder="请选择"
|
||||
optionFilterProp="children"
|
||||
style={{width: '80%', marginRight: 10}}
|
||||
style={{width: '80%', marginRight: 10, marginBottom: 12}}
|
||||
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
||||
onChange={v => store.editHost(index, v)}>
|
||||
{hostStore.records.filter(x => hasHostPermission(x.id)).map(item => (
|
||||
|
@ -42,14 +43,14 @@ class Ext2Setup2 extends React.Component {
|
|||
))}
|
||||
</Select>
|
||||
{!store.isReadOnly && info['host_ids'].length > 1 && (
|
||||
<Icon className={styles.delIcon} type="minus-circle-o" onClick={() => store.delHost(index)}/>
|
||||
<MinusCircleOutlined className={styles.delIcon} onClick={() => store.delHost(index)} />
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button disabled={store.isReadOnly} type="dashed" style={{width: '80%'}} onClick={store.addHost}>
|
||||
<Icon type="plus"/>添加目标主机
|
||||
<PlusOutlined />添加目标主机
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Form, Input, Button, message, Divider, Alert, Icon, Select } from 'antd';
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { Form, Input, Button, message, Divider, Alert, Select } from 'antd';
|
||||
import Editor from 'react-ace';
|
||||
import 'ace-builds/src-noconflict/mode-sh';
|
||||
import 'ace-builds/src-noconflict/theme-tomorrow';
|
||||
|
@ -81,7 +82,7 @@ class Ext2Setup3 extends React.Component {
|
|||
</Form.Item>
|
||||
{!store.isReadOnly && (
|
||||
<div className={styles.delAction} onClick={() => server_actions.splice(index, 1)}>
|
||||
<Icon type="minus-circle"/>移除
|
||||
<MinusCircleOutlined />移除
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -89,7 +90,7 @@ class Ext2Setup3 extends React.Component {
|
|||
{!store.isReadOnly && (
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button type="dashed" block onClick={() => server_actions.push({})}>
|
||||
<Icon type="plus"/>添加本地执行动作(在服务端本地执行)
|
||||
<PlusOutlined />添加本地执行动作(在服务端本地执行)
|
||||
</Button>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
@ -159,7 +160,7 @@ class Ext2Setup3 extends React.Component {
|
|||
)}
|
||||
{!store.isReadOnly && (
|
||||
<div className={styles.delAction} onClick={() => host_actions.splice(index, 1)}>
|
||||
<Icon type="minus-circle"/>移除
|
||||
<MinusCircleOutlined />移除
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -167,14 +168,15 @@ class Ext2Setup3 extends React.Component {
|
|||
{!store.isReadOnly && (
|
||||
<Form.Item wrapperCol={{span: 14, offset: 6}}>
|
||||
<Button disabled={store.isReadOnly} type="dashed" block onClick={() => host_actions.push({})}>
|
||||
<Icon type="plus"/>添加目标主机执行动作(在部署目标主机执行)
|
||||
<PlusOutlined />添加目标主机执行动作(在部署目标主机执行)
|
||||
</Button>
|
||||
<Button
|
||||
block
|
||||
type="dashed"
|
||||
style={{marginTop: 8}}
|
||||
disabled={store.isReadOnly || lds.findIndex(host_actions, x => x.type === 'transfer') !== -1}
|
||||
onClick={() => host_actions.push({type: 'transfer', title: '数据传输', mode: '0', src_mode: '0'})}>
|
||||
<Icon type="plus"/>添加数据传输动作(仅能添加一个)
|
||||
<PlusOutlined />添加数据传输动作(仅能添加一个)
|
||||
</Button>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
|
|
@ -3,65 +3,48 @@
|
|||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Modal, Form, Input, message } from 'antd';
|
||||
import http from 'libs/http';
|
||||
import store from './store';
|
||||
|
||||
@observer
|
||||
class ComForm extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
loading: false,
|
||||
}
|
||||
}
|
||||
export default observer(function () {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
handleSubmit = () => {
|
||||
this.setState({loading: true});
|
||||
const formData = this.props.form.getFieldsValue();
|
||||
function handleSubmit() {
|
||||
setLoading(true);
|
||||
const formData = form.getFieldsValue();
|
||||
formData['id'] = store.record.id;
|
||||
http.post('/api/app/', formData)
|
||||
.then(res => {
|
||||
message.success('操作成功');
|
||||
store.formVisible = false;
|
||||
store.fetchRecords()
|
||||
}, () => this.setState({loading: false}))
|
||||
};
|
||||
|
||||
render() {
|
||||
const info = store.record;
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
return (
|
||||
<Modal
|
||||
visible
|
||||
width={800}
|
||||
maskClosable={false}
|
||||
title={store.record.id ? '编辑应用' : '新建应用'}
|
||||
onCancel={() => store.formVisible = false}
|
||||
confirmLoading={this.state.loading}
|
||||
onOk={this.handleSubmit}>
|
||||
<Form labelCol={{span: 6}} wrapperCol={{span: 14}}>
|
||||
<Form.Item required label="应用名称">
|
||||
{getFieldDecorator('name', {initialValue: info['name']})(
|
||||
<Input placeholder="请输入应用名称,例如:订单服务"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item required label="唯一标识符">
|
||||
{getFieldDecorator('key', {initialValue: info['key']})(
|
||||
<Input placeholder="请输入唯一标识符,例如:api_order"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="备注信息">
|
||||
{getFieldDecorator('desc', {initialValue: info['desc']})(
|
||||
<Input.TextArea placeholder="请输入备注信息"/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
}, () => setLoading(false))
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create()(ComForm)
|
||||
return (
|
||||
<Modal
|
||||
visible
|
||||
width={800}
|
||||
maskClosable={false}
|
||||
title={store.record.id ? '编辑应用' : '新建应用'}
|
||||
onCancel={() => store.formVisible = false}
|
||||
confirmLoading={loading}
|
||||
onOk={handleSubmit}>
|
||||
<Form form={form} initialValues={store.record} labelCol={{span: 6}} wrapperCol={{span: 14}}>
|
||||
<Form.Item required name="name" label="应用名称">
|
||||
<Input placeholder="请输入应用名称,例如:订单服务"/>
|
||||
</Form.Item>
|
||||
<Form.Item required name="key" label="唯一标识符">
|
||||
<Input placeholder="请输入唯一标识符,例如:api_order"/>
|
||||
</Form.Item>
|
||||
<Form.Item name="desc" label="备注信息">
|
||||
<Input.TextArea placeholder="请输入备注信息"/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
)
|
||||
})
|
|
@ -4,12 +4,19 @@
|
|||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { toJS } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Table, Modal, Tag, Icon, Divider, message } from 'antd';
|
||||
import {
|
||||
BuildOutlined,
|
||||
DownSquareOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
OrderedListOutlined,
|
||||
UpSquareOutlined,
|
||||
PlusOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { Table, Modal, Tag, Divider, message } from 'antd';
|
||||
import { http, hasPermission } from 'libs';
|
||||
import store from './store';
|
||||
import { Action } from "components";
|
||||
import { Action, TableCard, AuthButton } from "components";
|
||||
import CloneConfirm from './CloneConfirm';
|
||||
import envStore from 'pages/config/environment/store';
|
||||
import lds from 'lodash';
|
||||
|
@ -32,7 +39,7 @@ class ComTable extends React.Component {
|
|||
e.stopPropagation();
|
||||
this.cloneObj = null;
|
||||
Modal.confirm({
|
||||
icon: 'exclamation-circle',
|
||||
icon: <ExclamationCircleOutlined/>,
|
||||
title: '选择克隆对象',
|
||||
content: <CloneConfirm onChange={v => this.cloneObj = v[1]}/>,
|
||||
onOk: () => {
|
||||
|
@ -88,49 +95,51 @@ class ComTable extends React.Component {
|
|||
store.loadDeploys(record.id)
|
||||
}
|
||||
|
||||
return <Table
|
||||
rowKey="id"
|
||||
loading={record['deploys'] === undefined}
|
||||
dataSource={record['deploys']}
|
||||
pagination={false}>
|
||||
<Table.Column width={80} title="模式" dataIndex="extend" render={value => value === '1' ?
|
||||
<Icon style={{fontSize: 20, color: '#1890ff'}} type="ordered-list"/> :
|
||||
<Icon style={{fontSize: 20, color: '#1890ff'}} type="build"/>}/>
|
||||
<Table.Column title="发布环境" dataIndex="env_id" render={value => lds.get(envStore.idMap, `${value}.name`)}/>
|
||||
<Table.Column title="关联主机" dataIndex="host_ids" render={value => `${value.length} 台`}/>
|
||||
<Table.Column title="发布审核" dataIndex="is_audit"
|
||||
render={value => value ? <Tag color="green">开启</Tag> : <Tag color="red">关闭</Tag>}/>
|
||||
{hasPermission('deploy.app.config|deploy.app.edit') && (
|
||||
<Table.Column title="操作" render={info => (
|
||||
<Action>
|
||||
<Action.Button
|
||||
auth="deploy.app.config"
|
||||
onClick={e => store.showExtForm(e, record.id, info, false, true)}>查看</Action.Button>
|
||||
<Action.Button auth="deploy.app.edit"
|
||||
onClick={e => store.showExtForm(e, record.id, info)}>编辑</Action.Button>
|
||||
<Action.Button auth="deploy.app.edit" onClick={() => this.handleDeployDelete(info)}>删除</Action.Button>
|
||||
</Action>
|
||||
)}/>
|
||||
)}
|
||||
</Table>
|
||||
};
|
||||
|
||||
render() {
|
||||
let data = Object.values(toJS(store.records));
|
||||
if (store.f_name) {
|
||||
data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase()))
|
||||
}
|
||||
if (store.f_desc) {
|
||||
data = data.filter(item => item['desc'] && item['desc'].toLowerCase().includes(store.f_desc.toLowerCase()))
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
rowKey="id"
|
||||
expandRowByClick
|
||||
loading={record['deploys'] === undefined}
|
||||
dataSource={record['deploys']}
|
||||
pagination={false}>
|
||||
<Table.Column width={80} title="模式" dataIndex="extend" render={value => value === '1' ?
|
||||
<OrderedListOutlined style={{fontSize: 20, color: '#1890ff'}}/> :
|
||||
<BuildOutlined style={{fontSize: 20, color: '#1890ff'}}/>}/>
|
||||
<Table.Column title="发布环境" dataIndex="env_id" render={value => lds.get(envStore.idMap, `${value}.name`)}/>
|
||||
<Table.Column title="关联主机" dataIndex="host_ids" render={value => `${value.length} 台`}/>
|
||||
<Table.Column title="发布审核" dataIndex="is_audit"
|
||||
render={value => value ? <Tag color="green">开启</Tag> : <Tag color="red">关闭</Tag>}/>
|
||||
{hasPermission('deploy.app.config|deploy.app.edit') && (
|
||||
<Table.Column title="操作" render={info => (
|
||||
<Action>
|
||||
<Action.Button
|
||||
auth="deploy.app.config"
|
||||
onClick={e => store.showExtForm(e, record.id, info, false, true)}>查看</Action.Button>
|
||||
<Action.Button auth="deploy.app.edit"
|
||||
onClick={e => store.showExtForm(e, record.id, info)}>编辑</Action.Button>
|
||||
<Action.Button auth="deploy.app.edit" onClick={() => this.handleDeployDelete(info)}>删除</Action.Button>
|
||||
</Action>
|
||||
)}/>
|
||||
)}
|
||||
</Table>
|
||||
)
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TableCard
|
||||
title="应用列表"
|
||||
rowKey="id"
|
||||
loading={store.isFetching}
|
||||
dataSource={data}
|
||||
expandedRowRender={this.expandedRowRender}
|
||||
dataSource={store.dataSource}
|
||||
expandable={{expandRowByClick: true, expandedRowRender: this.expandedRowRender}}
|
||||
onReload={store.fetchRecords}
|
||||
actions={[
|
||||
<AuthButton
|
||||
auth="deploy.app.add"
|
||||
type="primary"
|
||||
icon={<PlusOutlined/>}
|
||||
onClick={() => store.showForm()}>新建</AuthButton>
|
||||
]}
|
||||
pagination={{
|
||||
showSizeChanger: true,
|
||||
showLessItems: true,
|
||||
|
@ -140,11 +149,13 @@ class ComTable extends React.Component {
|
|||
}}>
|
||||
<Table.Column width={80} title="排序" key="series" render={(info) => (
|
||||
<div>
|
||||
<Icon onClick={e => this.handleSort(e, info, 'up')} type="up-square"
|
||||
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||
<UpSquareOutlined
|
||||
onClick={e => this.handleSort(e, info, 'up')}
|
||||
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||
<Divider type="vertical"/>
|
||||
<Icon onClick={e => this.handleSort(e, info, 'down')} type="down-square"
|
||||
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||
<DownSquareOutlined
|
||||
onClick={e => this.handleSort(e, info, 'down')}
|
||||
style={{cursor: 'pointer', color: '#1890ff'}}/>
|
||||
</div>
|
||||
)}/>
|
||||
<Table.Column title="应用名称" dataIndex="name"/>
|
||||
|
@ -160,7 +171,7 @@ class ComTable extends React.Component {
|
|||
</Action>
|
||||
)}/>
|
||||
)}
|
||||
</Table>
|
||||
</TableCard>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Input, Button } from 'antd';
|
||||
import { SearchForm, AuthDiv, AuthCard } from 'components';
|
||||
import { Input } from 'antd';
|
||||
import { SearchForm, AuthDiv, Breadcrumb } from 'components';
|
||||
import ComTable from './Table';
|
||||
import ComForm from './Form';
|
||||
import Ext1Form from './Ext1Form';
|
||||
|
@ -16,26 +16,25 @@ import store from './store';
|
|||
|
||||
export default observer(function () {
|
||||
return (
|
||||
<AuthCard auth="deploy.app.view">
|
||||
<AuthDiv auth="deploy.app.view">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>应用发布</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>应用管理</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<SearchForm>
|
||||
<SearchForm.Item span={6} title="应用名称">
|
||||
<SearchForm.Item span={7} title="应用名称">
|
||||
<Input allowClear value={store.f_name} onChange={e => store.f_name = e.target.value} placeholder="请输入"/>
|
||||
</SearchForm.Item>
|
||||
<SearchForm.Item span={6} title="描述信息">
|
||||
<SearchForm.Item span={7} title="描述信息">
|
||||
<Input allowClear value={store.f_desc} onChange={e => store.f_desc = e.target.value} placeholder="请输入"/>
|
||||
</SearchForm.Item>
|
||||
<SearchForm.Item span={8}>
|
||||
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
|
||||
</SearchForm.Item>
|
||||
</SearchForm>
|
||||
<AuthDiv auth="deploy.app.add" style={{marginBottom: 16}}>
|
||||
<Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button>
|
||||
</AuthDiv>
|
||||
<ComTable/>
|
||||
{store.formVisible && <ComForm />}
|
||||
{store.addVisible && <AddSelect />}
|
||||
{store.ext1Visible && <Ext1Form />}
|
||||
{store.ext2Visible && <Ext2Form />}
|
||||
</AuthCard>
|
||||
)
|
||||
</AuthDiv>
|
||||
);
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) <spug.dev@gmail.com>
|
||||
* Released under the AGPL-3.0 License.
|
||||
*/
|
||||
import { observable, computed } from "mobx";
|
||||
import { observable, computed, toJS } from 'mobx';
|
||||
import http from 'libs/http';
|
||||
|
||||
class Store {
|
||||
|
@ -22,6 +22,13 @@ class Store {
|
|||
@observable f_name;
|
||||
@observable f_desc;
|
||||
|
||||
@computed get dataSource() {
|
||||
let records = Object.values(toJS(this.records));
|
||||
if (this.f_name) records = records.filter(x => x.name.toLowerCase().includes(this.f_name.toLowerCase()));
|
||||
if (this.f_desc) records = records.filter(x => x.desc && x.desc.toLowerCase().includes(this.f_desc.toLowerCase()));
|
||||
return records
|
||||
}
|
||||
|
||||
@computed get currentRecord() {
|
||||
return this.records[`a${this.app_id}`]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue