U web update

pull/22/head
vapao 2020-01-13 20:53:42 +08:00
parent 6e26d56cf3
commit 6bfe26943f
22 changed files with 186 additions and 162 deletions

View File

@ -3,6 +3,9 @@ import { hasPermission } from "../libs";
export default function AuthDiv(props) { export default function AuthDiv(props) {
const disabled = props.auth && !hasPermission(props.auth); let disabled = props.disabled === undefined ? false : props.disabled;
if (props.auth && !hasPermission(props.auth)) {
disabled = true;
}
return disabled ? null : <div {...props}>{props.children}</div> return disabled ? null : <div {...props}>{props.children}</div>
} }

View File

@ -0,0 +1,12 @@
import React from 'react';
import {Link} from 'react-router-dom';
import { hasPermission } from 'libs';
export default function AuthLink(props) {
let disabled = props.disabled;
if (props.auth && !hasPermission(props.auth)) {
disabled = true;
}
return <Link {...props} disabled={disabled}>{props.children}</Link>
}

View File

@ -2,6 +2,7 @@ import StatisticsCard from './StatisticsCard';
import SearchForm from './SearchForm'; import SearchForm from './SearchForm';
import LinkButton from './LinkButton'; import LinkButton from './LinkButton';
import AuthButton from './AuthButton'; import AuthButton from './AuthButton';
import AuthLink from './AuthLink';
import AuthDiv from './AuthDiv'; import AuthDiv from './AuthDiv';
import ACEditor from './ACEditor'; import ACEditor from './ACEditor';
@ -10,6 +11,7 @@ export {
SearchForm, SearchForm,
LinkButton, LinkButton,
AuthButton, AuthButton,
AuthLink,
AuthDiv, AuthDiv,
ACEditor, ACEditor,
} }

View File

@ -2,23 +2,23 @@ export default [
{icon: 'desktop', title: '工作台', path: '/home'}, {icon: 'desktop', title: '工作台', path: '/home'},
{icon: 'cloud-server', title: '主机管理', auth: 'host.host.view', path: '/host'}, {icon: 'cloud-server', title: '主机管理', auth: 'host.host.view', path: '/host'},
{ {
icon: 'code', title: '批量执行', child: [ icon: 'code', title: '批量执行', auth: 'exec.task.do|exec.template.view', child: [
{title: '执行任务', path: '/exec/task'}, {title: '执行任务', auth: 'exec.task.do', path: '/exec/task'},
{title: '模板管理', path: '/exec/template'}, {title: '模板管理', auth: 'exec.template.view', path: '/exec/template'},
] ]
}, },
{ {
icon: 'flag', title: '应用发布', child: [ icon: 'flag', title: '应用发布', auth: 'deploy.app.view|deploy.request.view', child: [
{title: '应用管理', path: '/deploy/app'}, {title: '应用管理', auth: 'deploy.app.view', path: '/deploy/app'},
{title: '发布申请', path: '/deploy/request'}, {title: '发布申请', auth: 'deploy.request.view', path: '/deploy/request'},
] ]
}, },
{icon: 'schedule', title: '任务计划', path: '/schedule'}, {icon: 'schedule', title: '任务计划', auth: 'schedule.schedule.view', path: '/schedule'},
{ {
icon: 'deployment-unit', title: '配置中心', child: [ icon: 'deployment-unit', title: '配置中心', auth: 'config.env.view|config.src.view|config.app.view', child: [
{title: '环境管理', path: '/config/environment'}, {title: '环境管理', auth: 'config.env.view', path: '/config/environment'},
{title: '服务配置', path: '/config/service'}, {title: '服务配置', auth: 'config.src.view', path: '/config/service'},
{title: '应用配置', path: '/config/app'}, {title: '应用配置', auth: 'config.app.view', path: '/config/app'},
] ]
}, },
{icon: 'monitor', title: '监控中心', path: '/monitor'}, {icon: 'monitor', title: '监控中心', path: '/monitor'},

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import {observer} from 'mobx-react'; import {observer} from 'mobx-react';
import {Modal, Form, Transfer, message, Tabs, Alert} from 'antd'; import {Modal, Form, Transfer, message, Tabs, Alert} from 'antd';
import http from 'libs/http'; import { http, hasPermission } from 'libs';
import serviceStore from '../service/store'; import serviceStore from '../service/store';
import store from './store'; import store from './store';
@ -51,6 +51,7 @@ class Rel extends React.Component {
title="配置依赖关系" title="配置依赖关系"
onCancel={() => store.relVisible = false} onCancel={() => store.relVisible = false}
confirmLoading={this.state.loading} confirmLoading={this.state.loading}
footer={hasPermission('config.app.edit_config') ? undefined : null}
onOk={this.handleSubmit}> onOk={this.handleSubmit}>
<Alert <Alert
closable closable

View File

@ -1,10 +1,9 @@
import React from 'react'; import React from 'react';
import {observer} from 'mobx-react'; import { observer } from 'mobx-react';
import {Link} from 'react-router-dom'; import { Table, Divider, Modal, message } from 'antd';
import {Table, Divider, Modal, message} from 'antd';
import http from 'libs/http'; import http from 'libs/http';
import store from './store'; import store from './store';
import {LinkButton} from "components"; import { LinkButton, AuthLink } from 'components';
@observer @observer
class ComTable extends React.Component { class ComTable extends React.Component {
@ -31,13 +30,13 @@ class ComTable extends React.Component {
title: '操作', title: '操作',
render: info => ( render: info => (
<span> <span>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="config.app.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="config.app.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => store.showRel(info)}>依赖</LinkButton> <LinkButton auth="config.app.view_config" onClick={() => store.showRel(info)}>依赖</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<Link to={`/config/setting/app/${info.id}`}>配置</Link> <AuthLink auth="config.app.view_config" to={`/config/setting/app/${info.id}`}>配置</AuthLink>
</span> </span>
) )
}]; }];

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Card, Input, Button } from 'antd'; import { Card, Input, Button } from 'antd';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv } from 'components';
import ComTable from './Table'; import ComTable from './Table';
import ComForm from './Form'; import ComForm from './Form';
import Rel from './Rel'; import Rel from './Rel';
@ -18,9 +18,9 @@ export default observer(function () {
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
<div style={{marginBottom: 16}}> <AuthDiv auth="config.app.add" style={{marginBottom: 16}}>
<Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button> <Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button>
</div> </AuthDiv>
<ComTable/> <ComTable/>
{store.formVisible && <ComForm/>} {store.formVisible && <ComForm/>}
{store.relVisible && <Rel />} {store.relVisible && <Rel />}

View File

@ -1,9 +1,10 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Button, message} from 'antd'; import { Button, message } from 'antd';
import Editor from 'react-ace'; import Editor from 'react-ace';
import 'ace-builds/src-noconflict/mode-json'; import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-tomorrow'; import 'ace-builds/src-noconflict/theme-tomorrow';
import { AuthButton } from 'components';
import { http } from 'libs'; import { http } from 'libs';
import store from './store'; import store from './store';
@ -60,12 +61,13 @@ class JSONView extends React.Component {
style={{fontSize: 14}} style={{fontSize: 14}}
value={body} value={body}
onChange={v => this.setState({body: v})}/> onChange={v => this.setState({body: v})}/>
{readOnly && <Button {readOnly && <AuthButton
icon="edit" icon="edit"
type="link" type="link"
size="large" size="large"
auth={`config.${store.type}.edit_config`}
style={{position: 'absolute', top: 0, right: 0}} style={{position: 'absolute', top: 0, right: 0}}
onClick={() => this.setState({readOnly: false})}>编辑</Button>} onClick={() => this.setState({readOnly: false})}>编辑</AuthButton>}
{readOnly || <Button {readOnly || <Button
icon="save" icon="save"
type="link" type="link"

View File

@ -40,9 +40,9 @@ class TableView extends React.Component {
width: 120, width: 120,
render: info => ( render: info => (
<span> <span>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth={`config.${store.type}.edit_config`} onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth={`config.${store.type}.edit_config`} onClick={() => this.handleDelete(info)}>删除</LinkButton>
</span> </span>
) )
}]; }];

View File

@ -5,7 +5,8 @@ import 'ace-builds/src-noconflict/mode-space';
import 'ace-builds/src-noconflict/theme-tomorrow'; import 'ace-builds/src-noconflict/theme-tomorrow';
import store from './store'; import store from './store';
import { http } from "libs"; import { http } from "libs";
import { Button, message } from "antd"; import { Button, message } from 'antd';
import { AuthButton } from 'components';
@observer @observer
class TextView extends React.Component { class TextView extends React.Component {
@ -54,12 +55,13 @@ class TextView extends React.Component {
value={body} value={body}
readOnly={readOnly} readOnly={readOnly}
onChange={v => this.setState({body: v})}/> onChange={v => this.setState({body: v})}/>
{readOnly && <Button {readOnly && <AuthButton
icon="edit" icon="edit"
type="link" type="link"
size="large" size="large"
auth={`config.${store.type}.edit_config`}
style={{position: 'absolute', top: 0, right: 0}} style={{position: 'absolute', top: 0, right: 0}}
onClick={() => this.setState({readOnly: false})}>编辑</Button>} onClick={() => this.setState({readOnly: false})}>编辑</AuthButton>}
{readOnly || <Button {readOnly || <Button
icon="save" icon="save"
type="link" type="link"

View File

@ -4,7 +4,7 @@ import { Menu, Input, Button, Select, PageHeader, Icon } from 'antd';
import envStore from '../environment/store'; import envStore from '../environment/store';
import styles from './index.module.css'; import styles from './index.module.css';
import history from 'libs/history'; import history from 'libs/history';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv, AuthButton } from 'components';
import DiffConfig from './DiffConfig'; import DiffConfig from './DiffConfig';
import TableView from './TableView'; import TableView from './TableView';
import TextView from './TextView'; import TextView from './TextView';
@ -49,7 +49,7 @@ class Index extends React.Component {
render() { render() {
const {view} = this.state; const {view} = this.state;
return ( return (
<div className={styles.container}> <AuthDiv auth={`config.${store.type}.view_config`} className={styles.container}>
<div className={styles.left}> <div className={styles.left}>
<PageHeader <PageHeader
title="环境列表" title="环境列表"
@ -86,7 +86,7 @@ class Index extends React.Component {
onClick={store.showRecord}>更改历史</Button> onClick={store.showRecord}>更改历史</Button>
</SearchForm.Item> </SearchForm.Item>
<SearchForm.Item span={4} style={{textAlign: 'right'}}> <SearchForm.Item span={4} style={{textAlign: 'right'}}>
<Button disabled={view !== '1'} type="primary" icon="plus" onClick={() => store.showForm()}>新增配置</Button> <AuthButton auth="config.app.edit_config|config.service.edit_config" disabled={view !== '1'} type="primary" icon="plus" onClick={() => store.showForm()}>新增配置</AuthButton>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
@ -96,7 +96,7 @@ class Index extends React.Component {
</div> </div>
{store.recordVisible && <Record/>} {store.recordVisible && <Record/>}
{store.diffVisible && <DiffConfig/>} {store.diffVisible && <DiffConfig/>}
</div> </AuthDiv>
) )
} }
} }

View File

@ -36,11 +36,11 @@ class ComTable extends React.Component {
title: '操作', title: '操作',
render: info => ( render: info => (
<span> <span>
<LinkButton onClick={() => store.showExtForm(info.id)}>新建发布</LinkButton> <LinkButton auth="deploy.app.edit" onClick={() => store.showExtForm(info.id)}>新建发布</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="deploy.app.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="deploy.app.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</span> </span>
) )
}]; }];
@ -96,9 +96,9 @@ class ComTable extends React.Component {
title: '操作', title: '操作',
render: info => ( render: info => (
<span> <span>
<LinkButton onClick={() => store.showExtForm(record.id, info)}>编辑</LinkButton> <LinkButton auth="deploy.app.edit" onClick={() => store.showExtForm(record.id, info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDeployDelete(info)}>删除</LinkButton> <LinkButton auth="deploy.app.edit" onClick={() => this.handleDeployDelete(info)}>删除</LinkButton>
</span> </span>
) )
}]; }];

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Card, Input, Button } from 'antd'; import { Card, Input, Button } from 'antd';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv } from 'components';
import ComTable from './Table'; import ComTable from './Table';
import ComForm from './Form'; import ComForm from './Form';
import Ext1Form from './Ext1Form'; import Ext1Form from './Ext1Form';
@ -20,9 +20,9 @@ export default observer(function () {
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
<div style={{marginBottom: 16}}> <AuthDiv auth="deploy.app.add" style={{marginBottom: 16}}>
<Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button> <Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button>
</div> </AuthDiv>
<ComTable/> <ComTable/>
{store.formVisible && <ComForm />} {store.formVisible && <ComForm />}
{store.addVisible && <AddSelect />} {store.addVisible && <AddSelect />}

View File

@ -2,6 +2,7 @@ import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Steps, Collapse, PageHeader, Spin, Tag, Button, Icon } from 'antd'; import { Steps, Collapse, PageHeader, Spin, Tag, Button, Icon } from 'antd';
import http from 'libs/http'; import http from 'libs/http';
import { AuthDiv } from 'components';
import history from 'libs/history'; import history from 'libs/history';
import styles from './index.module.css'; import styles from './index.module.css';
import store from './store'; import store from './store';
@ -87,49 +88,51 @@ class Ext1Index extends React.Component {
render() { render() {
const {app_name, env_name, status} = store.request; const {app_name, env_name, status} = store.request;
return ( return (
<Spin spinning={this.state.fetching}> <AuthDiv auth="deploy.request.do">
<PageHeader <Spin spinning={this.state.fetching}>
title="应用发布" <PageHeader
subTitle={`${app_name} - ${env_name}`} title="应用发布"
style={{padding: 0}} subTitle={`${app_name} - ${env_name}`}
tags={this.getStatusAlias()} style={{padding: 0}}
extra={<Button loading={this.state.loading} type="primary" disabled={!['1', '-3'].includes(status)} tags={this.getStatusAlias()}
onClick={this.handleDeploy}>发布</Button>} extra={<Button loading={this.state.loading} type="primary" disabled={!['1', '-3'].includes(status)}
onBack={() => history.goBack()}/> onClick={this.handleDeploy}>发布</Button>}
<Collapse defaultActiveKey={1} className={styles.collapse}> onBack={() => history.goBack()}/>
<Collapse.Panel showArrow={false} key={1} header={ <Collapse defaultActiveKey={1} className={styles.collapse}>
<Steps> <Collapse.Panel showArrow={false} key={1} header={
<Steps.Step {...this.getStatus('local', 0)} title="建立连接"/> <Steps>
<Steps.Step {...this.getStatus('local', 1)} title="发布准备"/> <Steps.Step {...this.getStatus('local', 0)} title="建立连接"/>
<Steps.Step {...this.getStatus('local', 2)} title="检出前任务"/> <Steps.Step {...this.getStatus('local', 1)} title="发布准备"/>
<Steps.Step {...this.getStatus('local', 3)} title="执行检出"/> <Steps.Step {...this.getStatus('local', 2)} title="检出前任务"/>
<Steps.Step {...this.getStatus('local', 4)} title="检出后任务"/> <Steps.Step {...this.getStatus('local', 3)} title="执行检出"/>
<Steps.Step {...this.getStatus('local', 5)} title="执行打包"/> <Steps.Step {...this.getStatus('local', 4)} title="检出后任务"/>
</Steps>}> <Steps.Step {...this.getStatus('local', 5)} title="执行打包"/>
<pre className={styles.ext1Console}>{lds.get(store.outputs, 'local.data')}</pre> </Steps>}>
</Collapse.Panel> <pre className={styles.ext1Console}>{lds.get(store.outputs, 'local.data')}</pre>
</Collapse>
<Collapse
defaultActiveKey={'0'}
className={styles.collapse}
expandIcon={({isActive}) => <Icon type="caret-right" style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{store.request.targets.map((item, index) => (
<Collapse.Panel key={index} header={
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<b>{item.title}</b>
<Steps size="small" style={{maxWidth: 600}}>
<Steps.Step {...this.getStatus(item.id, 1)} title="数据准备"/>
<Steps.Step {...this.getStatus(item.id, 2)} title="发布前任务"/>
<Steps.Step {...this.getStatus(item.id, 3)} title="执行发布"/>
<Steps.Step {...this.getStatus(item.id, 4)} title="发布后任务"/>
</Steps>
</div>}>
<pre className={styles.ext1Console}>{lds.get(store.outputs, `${item.id}.data`)}</pre>
</Collapse.Panel> </Collapse.Panel>
))} </Collapse>
</Collapse>
</Spin> <Collapse
defaultActiveKey={'0'}
className={styles.collapse}
expandIcon={({isActive}) => <Icon type="caret-right" style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{store.request.targets.map((item, index) => (
<Collapse.Panel key={index} header={
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<b>{item.title}</b>
<Steps size="small" style={{maxWidth: 600}}>
<Steps.Step {...this.getStatus(item.id, 1)} title="数据准备"/>
<Steps.Step {...this.getStatus(item.id, 2)} title="发布前任务"/>
<Steps.Step {...this.getStatus(item.id, 3)} title="执行发布"/>
<Steps.Step {...this.getStatus(item.id, 4)} title="发布后任务"/>
</Steps>
</div>}>
<pre className={styles.ext1Console}>{lds.get(store.outputs, `${item.id}.data`)}</pre>
</Collapse.Panel>
))}
</Collapse>
</Spin>
</AuthDiv>
) )
} }
} }

View File

@ -2,6 +2,7 @@ import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Steps, Collapse, PageHeader, Spin, Tag, Button, Icon } from 'antd'; import { Steps, Collapse, PageHeader, Spin, Tag, Button, Icon } from 'antd';
import http from 'libs/http'; import http from 'libs/http';
import { AuthDiv } from 'components';
import history from 'libs/history'; import history from 'libs/history';
import styles from './index.module.css'; import styles from './index.module.css';
import store from './store'; import store from './store';
@ -87,53 +88,55 @@ class Ext1Index extends React.Component {
render() { render() {
const {app_name, env_name, status, server_actions, host_actions} = store.request; const {app_name, env_name, status, server_actions, host_actions} = store.request;
return ( return (
<Spin spinning={this.state.fetching}> <AuthDiv auth="deploy.request.do">
<PageHeader <Spin spinning={this.state.fetching}>
title="应用发布" <PageHeader
subTitle={`${app_name} - ${env_name}`} title="应用发布"
style={{padding: 0}} subTitle={`${app_name} - ${env_name}`}
tags={this.getStatusAlias()} style={{padding: 0}}
extra={<Button loading={this.state.loading} type="primary" disabled={!['1', '-3'].includes(status)} tags={this.getStatusAlias()}
onClick={this.handleDeploy}>发布</Button>} extra={<Button loading={this.state.loading} type="primary" disabled={!['1', '-3'].includes(status)}
onBack={() => history.goBack()}/> onClick={this.handleDeploy}>发布</Button>}
<Collapse defaultActiveKey={1} className={styles.collapse}> onBack={() => history.goBack()}/>
<Collapse.Panel showArrow={false} key={1} header={ <Collapse defaultActiveKey={1} className={styles.collapse}>
<Steps style={{maxWidth: 400 + server_actions.length * 200}}> <Collapse.Panel showArrow={false} key={1} header={
<Steps.Step {...this.getStatus('local', 0)} title="建立连接"/> <Steps style={{maxWidth: 400 + server_actions.length * 200}}>
<Steps.Step {...this.getStatus('local', 1)} title="发布准备"/> <Steps.Step {...this.getStatus('local', 0)} title="建立连接"/>
{server_actions.map((item, index) => ( <Steps.Step {...this.getStatus('local', 1)} title="发布准备"/>
<Steps.Step {...this.getStatus('local', 2 + index)} key={index} title={item.title}/> {server_actions.map((item, index) => (
))} <Steps.Step {...this.getStatus('local', 2 + index)} key={index} title={item.title}/>
</Steps>}> ))}
<pre className={styles.ext1Console}>{lds.get(store.outputs, 'local.data')}</pre> </Steps>}>
</Collapse.Panel> <pre className={styles.ext1Console}>{lds.get(store.outputs, 'local.data')}</pre>
</Collapse> </Collapse.Panel>
{host_actions.length > 0 && (
<Collapse
defaultActiveKey={'0'}
className={styles.collapse}
expandIcon={({isActive}) => <Icon type="caret-right" style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{store.request.targets.map((item, index) => (
<Collapse.Panel key={index} header={
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<b>{item.title}</b>
<Steps size="small" style={{maxWidth: 150 + host_actions.length * 150}}>
<Steps.Step {...this.getStatus(item.id, 1)} title="数据准备"/>
{host_actions.map((action, index) => (
<Steps.Step {...this.getStatus(item.id, 2 + index)} key={index} title={action.title}/>
))}
</Steps>
</div>}>
<pre className={styles.ext1Console}>{lds.get(store.outputs, `${item.id}.data`)}</pre>
</Collapse.Panel>
))}
</Collapse> </Collapse>
)}
{host_actions.length === 0 && this.state.fetching === false && ( {host_actions.length > 0 && (
<div className={styles.ext2Tips}>无目标主机动作</div> <Collapse
)} defaultActiveKey={'0'}
</Spin> className={styles.collapse}
expandIcon={({isActive}) => <Icon type="caret-right" style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{store.request.targets.map((item, index) => (
<Collapse.Panel key={index} header={
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<b>{item.title}</b>
<Steps size="small" style={{maxWidth: 150 + host_actions.length * 150}}>
<Steps.Step {...this.getStatus(item.id, 1)} title="数据准备"/>
{host_actions.map((action, index) => (
<Steps.Step {...this.getStatus(item.id, 2 + index)} key={index} title={action.title}/>
))}
</Steps>
</div>}>
<pre className={styles.ext1Console}>{lds.get(store.outputs, `${item.id}.data`)}</pre>
</Collapse.Panel>
))}
</Collapse>
)}
{host_actions.length === 0 && this.state.fetching === false && (
<div className={styles.ext2Tips}>无目标主机动作</div>
)}
</Spin>
</AuthDiv>
) )
} }
} }

View File

@ -1,10 +1,9 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Table, Divider, Modal, Icon, Popover, Tag, message } from 'antd'; import { Table, Divider, Modal, Icon, Popover, Tag, message } from 'antd';
import http from 'libs/http'; import http from 'libs/http';
import store from './store'; import store from './store';
import { LinkButton } from "components"; import { LinkButton, AuthLink } from "components";
@observer @observer
class ComTable extends React.Component { class ComTable extends React.Component {
@ -81,37 +80,39 @@ class ComTable extends React.Component {
switch (info.status) { switch (info.status) {
case '-3': case '-3':
return <React.Fragment> return <React.Fragment>
<Link to={`/deploy/do/ext${info['app_extend']}/${info.id}`}>发布</Link> <AuthLink auth="deploy.request.do" to={`/deploy/do/ext${info['app_extend']}/${info.id}`}>发布</AuthLink>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton <LinkButton
auth="deploy.request.do"
disabled={info.type === '2'} disabled={info.type === '2'}
loading={this.state.loading} loading={this.state.loading}
onClick={() => this.handleRollback(info)}>回滚</LinkButton> onClick={() => this.handleRollback(info)}>回滚</LinkButton>
</React.Fragment>; </React.Fragment>;
case '3': case '3':
return <LinkButton return <LinkButton
auth="deploy.request.do"
disabled={info.type === '2'} disabled={info.type === '2'}
loading={this.state.loading} loading={this.state.loading}
onClick={() => this.handleRollback(info)}>回滚</LinkButton>; onClick={() => this.handleRollback(info)}>回滚</LinkButton>;
case '-1': case '-1':
return <React.Fragment> return <React.Fragment>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="deploy.request.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="deploy.request.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</React.Fragment>; </React.Fragment>;
case '0': case '0':
return <React.Fragment> return <React.Fragment>
<LinkButton onClick={() => store.showApprove(info)}>审核</LinkButton> <LinkButton auth="deploy.request.approve" onClick={() => store.showApprove(info)}>审核</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="deploy.request.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="deploy.request.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</React.Fragment>; </React.Fragment>;
case '1': case '1':
return <React.Fragment> return <React.Fragment>
<Link to={`/deploy/do/ext${info['app_extend']}/${info.id}`}>发布</Link> <AuthLink auth="deploy.request.do" to={`/deploy/do/ext${info['app_extend']}/${info.id}`}>发布</AuthLink>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="deploy.request.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</React.Fragment>; </React.Fragment>;
default: default:
return null return null

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Card, Input, Button } from 'antd'; import { Card, Input, Button } from 'antd';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv } from 'components';
import SelectApp from './SelectApp'; import SelectApp from './SelectApp';
import Ext1Form from './Ext1Form'; import Ext1Form from './Ext1Form';
import Ext2Form from './Ext2Form'; import Ext2Form from './Ext2Form';
@ -23,9 +23,9 @@ export default observer(function () {
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
<div style={{marginBottom: 16}}> <AuthDiv auth="deploy.request.add" style={{marginBottom: 16}}>
<Button type="primary" icon="plus" onClick={() => store.addVisible = true}>新建发布申请</Button> <Button type="primary" icon="plus" onClick={() => store.addVisible = true}>新建发布申请</Button>
</div> </AuthDiv>
<ComTable/> <ComTable/>
{store.addVisible && <SelectApp/>} {store.addVisible && <SelectApp/>}
{store.ext1Visible && <Ext1Form/>} {store.ext1Visible && <Ext1Form/>}

View File

@ -13,11 +13,6 @@ class ComTable extends React.Component {
} }
columns = [{ columns = [{
title: '序号',
key: 'series',
render: (_, __, index) => index + 1,
width: 80,
}, {
title: '模版名称', title: '模版名称',
dataIndex: 'name', dataIndex: 'name',
}, { }, {
@ -35,9 +30,9 @@ class ComTable extends React.Component {
title: '操作', title: '操作',
render: info => ( render: info => (
<span> <span>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="exec.template.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="exec.template.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</span> </span>
) )
}]; }];

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Card, Input, Select, Button } from 'antd'; import { Card, Input, Select, Button } from 'antd';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv } from 'components';
import ComTable from './Table'; import ComTable from './Table';
import store from './store'; import store from './store';
@ -23,9 +23,9 @@ export default observer(function () {
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
<div style={{marginBottom: 16}}> <AuthDiv auth="exec.template.add" style={{marginBottom: 16}}>
<Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button> <Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button>
</div> </AuthDiv>
<ComTable/> <ComTable/>
</Card> </Card>
) )

View File

@ -19,11 +19,11 @@ class ComTable extends React.Component {
moreMenus = (info) => ( moreMenus = (info) => (
<Menu> <Menu>
<Menu.Item> <Menu.Item>
<LinkButton onClick={() => this.handleActive(info)}>{info.is_active ? '禁用' : '激活'}</LinkButton> <LinkButton auth="schedule.schedule.edit" onClick={() => this.handleActive(info)}>{info.is_active ? '禁用' : '激活'}</LinkButton>
</Menu.Item> </Menu.Item>
<Menu.Divider /> <Menu.Divider />
<Menu.Item> <Menu.Item>
<LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> <LinkButton auth="schedule.schedule.del" onClick={() => this.handleDelete(info)}>删除</LinkButton>
</Menu.Item> </Menu.Item>
</Menu> </Menu>
); );
@ -67,7 +67,7 @@ class ComTable extends React.Component {
<span> <span>
<LinkButton disabled={!info['latest_run_time']} onClick={() => store.showInfo(info)}>详情</LinkButton> <LinkButton disabled={!info['latest_run_time']} onClick={() => store.showInfo(info)}>详情</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> <LinkButton auth="schedule.schedule.edit" onClick={() => store.showForm(info)}>编辑</LinkButton>
<Divider type="vertical"/> <Divider type="vertical"/>
<Dropdown overlay={() => this.moreMenus(info)} trigger={['click']}> <Dropdown overlay={() => this.moreMenus(info)} trigger={['click']}>
<LinkButton> <LinkButton>

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Card, Input, Select, Button } from 'antd'; import { Card, Input, Select, Button } from 'antd';
import { SearchForm } from 'components'; import { SearchForm, AuthDiv } from 'components';
import ComTable from './Table'; import ComTable from './Table';
import store from './store'; import store from './store';
@ -33,9 +33,9 @@ export default observer(function () {
<Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button> <Button type="primary" icon="sync" onClick={store.fetchRecords}>刷新</Button>
</SearchForm.Item> </SearchForm.Item>
</SearchForm> </SearchForm>
<div style={{marginBottom: 16}}> <AuthDiv auth="schedule.schedule.add" style={{marginBottom: 16}}>
<Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button> <Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button>
</div> </AuthDiv>
<ComTable/> <ComTable/>
</Card> </Card>
) )

View File

@ -51,6 +51,7 @@ export default [{
{key: 'add', label: '新建申请'}, {key: 'add', label: '新建申请'},
{key: 'edit', label: '编辑申请'}, {key: 'edit', label: '编辑申请'},
{key: 'del', label: '删除申请'}, {key: 'del', label: '删除申请'},
{key: 'approve', label: '审核申请'},
{key: 'do', label: '执行发布'} {key: 'do', label: '执行发布'}
] ]
}] }]
@ -80,7 +81,7 @@ export default [{
{key: 'del', label: '删除环境'} {key: 'del', label: '删除环境'}
] ]
}, { }, {
key: 'service', key: 'src',
label: '服务管理', label: '服务管理',
perms: [ perms: [
{key: 'view', label: '查看服务'}, {key: 'view', label: '查看服务'},