|
|
@@ -1,93 +1,102 @@
|
|
|
import React, {Component} from 'react';
|
|
|
-import {Layout, Button, notification, Spin} from 'antd';
|
|
|
+import {Layout, Button, notification, Spin, Row, Col, Icon, message, Input, Radio, Modal} from 'antd';
|
|
|
import {getCookie} from "../../../cookie";
|
|
|
import {graphqlUrl, storeFile} from "../../../config";
|
|
|
-import {SHOW_CLOUD} from "../../../gql";
|
|
|
+import {SEARCH_APIGROUP, SHOW_CLOUD} from "../../../gql";
|
|
|
import {request} from 'graphql-request'
|
|
|
import axios from 'axios';
|
|
|
import {deployAll} from "../../../config";
|
|
|
import {ADD_APIGWPATH, ADD_APIGROUP, ADD_DEPLOY, ADD_PROJECT} from "../../../gql";
|
|
|
import {idGen} from "../../../func";
|
|
|
+import {FormattedMessage} from 'react-intl';
|
|
|
+import copy from 'copy-to-clipboard';
|
|
|
+import {CloudConfig} from '../../../login/CloudConfig';
|
|
|
|
|
|
const {Content} = Layout;
|
|
|
+const RadioGroup = Radio.Group;
|
|
|
axios.defaults.withCredentials = true;
|
|
|
|
|
|
class DeployCloudChoose extends Component {
|
|
|
constructor() {
|
|
|
super();
|
|
|
this.state = {
|
|
|
- userID: 'demo',
|
|
|
- dbKind: 'mongodb', // mongodb fc-db
|
|
|
+ userID: '',
|
|
|
+ check: new Date().getTime(),
|
|
|
+
|
|
|
+ disableDeployButton: false,
|
|
|
+ domain: '',
|
|
|
+
|
|
|
cloudName: 'tencent',
|
|
|
- cloudID: 'tencent_CloudID',
|
|
|
+ cloudID: '',
|
|
|
secretID: '',
|
|
|
secretKey: '',
|
|
|
appId: '',
|
|
|
+
|
|
|
+ customName: '',
|
|
|
bucketName: '',
|
|
|
- disabled: false
|
|
|
+ dbKind: 'fc-db', // mongodb fc-db
|
|
|
}
|
|
|
}
|
|
|
|
|
|
componentWillMount() {
|
|
|
this._isMounted = true;
|
|
|
- let userID = getCookie('user_id') || this.state.userID;
|
|
|
+
|
|
|
+ // 查询是否登录
|
|
|
+ let userID = getCookie('user_id');
|
|
|
if (userID !== undefined && userID !== '') {
|
|
|
this.setState({
|
|
|
userID
|
|
|
});
|
|
|
-
|
|
|
- // 查询是否设置 cloud
|
|
|
- request(graphqlUrl, SHOW_CLOUD, {user_id: userID}).then(data => {
|
|
|
- data.cloud_by_props.forEach(cloud => {
|
|
|
- switch (cloud.cloudName) {
|
|
|
- case 'tencent':
|
|
|
- this.setState({
|
|
|
- cloudID: cloud.id,
|
|
|
- secretID: cloud.secretId,
|
|
|
- secretKey: cloud.secretKey,
|
|
|
- appId: cloud.appId,
|
|
|
- cloudName: 'tencent'
|
|
|
- });
|
|
|
- break;
|
|
|
- case 'aliyun':
|
|
|
- // 没写
|
|
|
- break;
|
|
|
- case 'amazon':
|
|
|
- // 没写
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- )
|
|
|
}
|
|
|
+
|
|
|
+ // 查询跳转来的案例,转成 apigroup id
|
|
|
+ let groupID = '';
|
|
|
if (this.props.location && this.props.location.state) {
|
|
|
switch (this.props.location.state.schemaID) {
|
|
|
case 'order_schemaID':
|
|
|
this.setState({
|
|
|
bucketName: 'appointment'
|
|
|
});
|
|
|
+ groupID = 'order';
|
|
|
break;
|
|
|
case 'ecommerce_schemaID':
|
|
|
this.setState({
|
|
|
bucketName: 'e-commerce'
|
|
|
});
|
|
|
+ groupID = 'ecommerce';
|
|
|
+ break;
|
|
|
+ case 'bills_schemaID':
|
|
|
+ this.setState({
|
|
|
+ bucketName: 'bills'
|
|
|
+ });
|
|
|
+ groupID = 'bills';
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 查询该案例的 domain
|
|
|
+ request(graphqlUrl, SEARCH_APIGROUP, {id: groupID}).then(res => {
|
|
|
+ let caseDeploy = res.apiGWGroupbyid;
|
|
|
+ let domain = caseDeploy.defaultDomain;
|
|
|
+ if (this._isMounted) {
|
|
|
+ this.setState({
|
|
|
+ domain
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
}
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
this._isMounted = false;
|
|
|
}
|
|
|
|
|
|
- deploy() {
|
|
|
+ deploy = () => {
|
|
|
this._isMounted = true;
|
|
|
let _this = this;
|
|
|
- let {userID, dbKind, bucketName} = this.state;
|
|
|
+ let {userID, dbKind, bucketName, customName} = this.state;
|
|
|
|
|
|
if (bucketName === '') {
|
|
|
console.log('state, 没有传值');
|
|
|
@@ -96,12 +105,12 @@ class DeployCloudChoose extends Component {
|
|
|
// 开始调用
|
|
|
console.log('开始调用');
|
|
|
this.setState({
|
|
|
- disabled: true
|
|
|
+ disableDeployButton: true
|
|
|
});
|
|
|
|
|
|
let now = new Date().getTime(),
|
|
|
- functionName = this.state.userID + '_' + bucketName.substr(0, 2) + '_' + now,
|
|
|
- serviceName = this.state.userID + '_' + bucketName.substr(0, 2) + '_' + now,
|
|
|
+ functionName = this.state.userID + '_' + customName,
|
|
|
+ serviceName = this.state.userID + '_' + customName,
|
|
|
resources = [`${bucketName}/schema.edn`, `${bucketName}/resolve-map.edn`, `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`];
|
|
|
|
|
|
if (dbKind === 'mongodb') {
|
|
|
@@ -113,7 +122,7 @@ class DeployCloudChoose extends Component {
|
|
|
axios.post(deployAll,
|
|
|
{
|
|
|
'fc-name': functionName,
|
|
|
- 'bucket': dbKind === 'mongodb'? 'native-fc' : 'fcdb-deploy',
|
|
|
+ 'bucket': dbKind === 'mongodb' ? 'native-fc' : 'fcdb-deploy',
|
|
|
'object-file': 'fc-only.zip',
|
|
|
'res-bucket': 'case',
|
|
|
'resources': resources,
|
|
|
@@ -122,7 +131,7 @@ class DeployCloudChoose extends Component {
|
|
|
})
|
|
|
.then(function (response) {
|
|
|
console.log('response', response);
|
|
|
- if(response['data']['apigw-result'] && response['data']['fc-result']) {
|
|
|
+ if (response['data']['apigw-result'] && response['data']['fc-result']) {
|
|
|
// 处理数据
|
|
|
let result = response['data']['apigw-result'];
|
|
|
let apiData = result['api-info'];
|
|
|
@@ -219,9 +228,9 @@ class DeployCloudChoose extends Component {
|
|
|
console.log(value);
|
|
|
|
|
|
// 展示数据
|
|
|
- if(_this._isMounted) {
|
|
|
+ if (_this._isMounted) {
|
|
|
_this.setState({
|
|
|
- disabled: false
|
|
|
+ disableDeployButton: false
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -246,33 +255,58 @@ class DeployCloudChoose extends Component {
|
|
|
console.log('axios error', error);
|
|
|
});
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
+
|
|
|
+ getCloudDetail = (cloudID, secretID, secretKey, appId) => {
|
|
|
+ this.setState({
|
|
|
+ cloudID,
|
|
|
+ secretID,
|
|
|
+ secretKey,
|
|
|
+ appId
|
|
|
+ })
|
|
|
+ };
|
|
|
|
|
|
render() {
|
|
|
- let {userID, disabled, appId, secretID, secretKey, bucketName, dbKind} = this.state;
|
|
|
+ let {userID, disableDeployButton, appId, secretID, secretKey, bucketName, dbKind, domain, showCustom, cloudName, check} = this.state;
|
|
|
return (
|
|
|
<div className={'deploy-choose-cloud'}>
|
|
|
<Layout style={{padding: '24px', minHeight: '300px'}}>
|
|
|
<Content style={{padding: '20px 50px', background: '#fff'}}>
|
|
|
- <div className={'choose-cloud'}>
|
|
|
- <span className={'choose-cloud-title'}>系统默认设置</span><span
|
|
|
- className={'choose-cloud-content'}>部署在系统云服务商,部署成功后返回结果</span>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <div className={'schema-name'}><FormattedMessage id='case graphql domain'/></div>
|
|
|
+ <div className={'schema-table-list-title'}>
|
|
|
+ <Row>
|
|
|
+ <Col span={15}><span className={'schema-table-title'}><FormattedMessage
|
|
|
+ id='defaultDomain'/></span></Col>
|
|
|
+ </Row>
|
|
|
+ </div>
|
|
|
+ <div className={'schema-table-list-content'}>
|
|
|
+ <Row>
|
|
|
+ <Col span={15}>
|
|
|
+ <span className={'schema-table-content'}>{domain} </span>
|
|
|
+ <Icon type="copy" theme="twoTone" onClick={() => {
|
|
|
+ copy(domain);
|
|
|
+ message.success('复制成功.');
|
|
|
+ }}/>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div className={'choose-cloud'}>
|
|
|
- <span className={'choose-cloud-title'}>自定义设置</span><span
|
|
|
- className={'choose-cloud-content'}>部署在自有云服务商,部署成功后返回结果,可登陆云服务商后台查看部署结果</span>
|
|
|
+
|
|
|
+
|
|
|
+ <div style={{marginTop: 20, fontSize: 20}}>
|
|
|
+ <div className={'schema-name'}><FormattedMessage id='detail'/></div>
|
|
|
+ 这里巴拉巴拉
|
|
|
</div>
|
|
|
- <div className={'choose-cloud-button-group'}>
|
|
|
+
|
|
|
+
|
|
|
+ <div style={{marginTop: 20}}>
|
|
|
{
|
|
|
- disabled ?
|
|
|
- <Spin/>
|
|
|
- :
|
|
|
- <div>
|
|
|
- <Button className={'choose-cloud-button'} type='primary' onClick={() => {
|
|
|
- this.deploy();
|
|
|
- }}>系统默认部署</Button>
|
|
|
+ !showCustom ?
|
|
|
+ <div className={'choose-cloud-button-group'}>
|
|
|
<Button className={'choose-cloud-button'} type='primary' onClick={() => {
|
|
|
- if (userID === 'demo') {
|
|
|
+ if (userID === '') {
|
|
|
notification['warning']({
|
|
|
message: '需要登录',
|
|
|
description: '后续使用,需要先登录',
|
|
|
@@ -282,75 +316,123 @@ class DeployCloudChoose extends Component {
|
|
|
pathname: `/login`
|
|
|
})
|
|
|
} else {
|
|
|
- if (appId && secretID && secretKey) {
|
|
|
- this.setState({
|
|
|
- disabled: true
|
|
|
- });
|
|
|
-
|
|
|
- // store *.edn to cos
|
|
|
- let deployConf = dbKind === 'mongodb' ?
|
|
|
- ` {:secretId "${secretID}"\n` +
|
|
|
- ` :secretKey "${secretKey}"\n` +
|
|
|
- ` :appId "${appId}"\n` +
|
|
|
- ' :region "ap-beijing" \n' +
|
|
|
- ' }\n'
|
|
|
- :
|
|
|
- ` {:secretId "${secretID}"\n` +
|
|
|
- ` :secretKey "${secretKey}"\n` +
|
|
|
- ` :appId "${appId}"\n` +
|
|
|
- ' :region "ap-beijing"\n' +
|
|
|
- ' :bucket "fc-db"\n' +
|
|
|
- ' :trustStore "/etc/ssl/certs/java/cacerts"\n' +
|
|
|
- ` :fc-db-store "save/${bucketName}.dat"\n` +
|
|
|
- ' :fc-db-dir "fc-db"\n' +
|
|
|
- ' :graphql-url "http://orderfcdb.ioobot.cn/graphql"\n' +
|
|
|
- ' :local-tmp-dir "/tmp"\n' +
|
|
|
- ' :local-db-file "fcdb.dat"\n' +
|
|
|
- ' :update-tx? true \n' +
|
|
|
- ' :force-down? true\n' +
|
|
|
- ' }';
|
|
|
-
|
|
|
- let a = axios.post(storeFile, {
|
|
|
- 'file-name': `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`,
|
|
|
- bucket: 'case',
|
|
|
- cont: deployConf
|
|
|
- });
|
|
|
-
|
|
|
- let cont = '{:uri {\n' +
|
|
|
- ':auth {:admin-db "order"\n' +
|
|
|
- ' :u "ly"\n' +
|
|
|
- ' :p "autorunC1705"\n' +
|
|
|
- ' :host "119.27.174.13"}}\n' +
|
|
|
- ' :db-name "order"}';
|
|
|
-
|
|
|
- let b = dbKind === 'mongodb' ?
|
|
|
- axios.post(storeFile, {
|
|
|
- 'file-name': `${bucketName}/${dbKind}/${userID}/mongo-config.edn`,
|
|
|
- bucket: 'case',
|
|
|
- cont
|
|
|
- })
|
|
|
- :
|
|
|
- Promise.resolve({status: 200});
|
|
|
-
|
|
|
- Promise.all([a, b]).then(value=> {
|
|
|
- if(value.every(res=> res.status === 200)) {
|
|
|
- console.log('store file success , start deploying');
|
|
|
- this.deploy();
|
|
|
- }
|
|
|
- });
|
|
|
- } else {
|
|
|
- notification['warning']({
|
|
|
- message: '需要填写配置',
|
|
|
- description: '后续使用,需要先填写配置',
|
|
|
- });
|
|
|
-
|
|
|
- this.props.history.push({
|
|
|
- pathname: `/login/cloud`
|
|
|
- })
|
|
|
- }
|
|
|
+ this.setState({
|
|
|
+ showCustom: true
|
|
|
+ })
|
|
|
}
|
|
|
}}>自定义参数设置</Button>
|
|
|
</div>
|
|
|
+ :
|
|
|
+ <div>
|
|
|
+ <hr/>
|
|
|
+ <div>
|
|
|
+ <div className={'schema-name'}><FormattedMessage id='Name'/></div>
|
|
|
+ <div>
|
|
|
+ <span className='item-title-cloud'><FormattedMessage id='name'/>:</span>
|
|
|
+ <Input style={{width: 250}} value={this.state.customName}
|
|
|
+ onChange={(e) => {
|
|
|
+ this.setState({customName: e.target.value})
|
|
|
+ }}/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style={{marginTop: 20}}>
|
|
|
+ <div className={'schema-name'}><FormattedMessage id='Cloud Setting'/></div>
|
|
|
+ <RadioGroup onChange={(e) => {
|
|
|
+ this.setState({cloudName: e.target.value})
|
|
|
+ }} value={this.state.cloudName}>
|
|
|
+ <Radio value={'tencent'}><FormattedMessage id='tencent cloud'/></Radio>
|
|
|
+ <Radio value={'aliyun'}><FormattedMessage id='aliyun'/></Radio>
|
|
|
+ <Radio value={'amazon'}><FormattedMessage id='amazon cloud'/></Radio>
|
|
|
+ </RadioGroup>
|
|
|
+ <CloudQueryAndConfig cloudName={cloudName} userID={userID}
|
|
|
+ getCloudDetail={this.getCloudDetail} check={check}
|
|
|
+ reCheck={() => {
|
|
|
+ this.setState({check: new Date().getTime()})
|
|
|
+ }}/>
|
|
|
+ </div>
|
|
|
+ <div style={{marginTop: 20}}>
|
|
|
+ <div className={'schema-name'}><FormattedMessage id='DB Choose'/></div>
|
|
|
+ <RadioGroup onChange={(e) => {
|
|
|
+ this.setState({dbKind: e.target.value})
|
|
|
+ }} value={this.state.dbKind}>
|
|
|
+ <Radio value='fc-db'>fc-db</Radio>
|
|
|
+ <Radio value='mongodb'>mongodb</Radio>
|
|
|
+ </RadioGroup>
|
|
|
+ </div>
|
|
|
+ {
|
|
|
+ disableDeployButton ?
|
|
|
+ <Spin/>
|
|
|
+ :
|
|
|
+ <Button style={{marginTop: 20}} type='primary' onClick={() => {
|
|
|
+ if (appId && secretID && secretKey) {
|
|
|
+ this.setState({
|
|
|
+ disableDeployButton: true
|
|
|
+ });
|
|
|
+
|
|
|
+ // store *.edn to cos
|
|
|
+ let deployConf = dbKind === 'mongodb' ?
|
|
|
+ ` {:secretId "${secretID}"\n` +
|
|
|
+ ` :secretKey "${secretKey}"\n` +
|
|
|
+ ` :appId "${appId}"\n` +
|
|
|
+ ' :region "ap-beijing" \n' +
|
|
|
+ ' }\n'
|
|
|
+ :
|
|
|
+ ` {:secretId "${secretID}"\n` +
|
|
|
+ ` :secretKey "${secretKey}"\n` +
|
|
|
+ ` :appId "${appId}"\n` +
|
|
|
+ ' :region "ap-beijing"\n' +
|
|
|
+ ' :bucket "fc-db"\n' +
|
|
|
+ ' :trustStore "/etc/ssl/certs/java/cacerts"\n' +
|
|
|
+ ` :fc-db-store "save/${bucketName}.dat"\n` +
|
|
|
+ ' :fc-db-dir "fc-db"\n' +
|
|
|
+ ' :graphql-url "http://orderfcdb.ioobot.cn/graphql"\n' +
|
|
|
+ ' :local-tmp-dir "/tmp"\n' +
|
|
|
+ ' :local-db-file "fcdb.dat"\n' +
|
|
|
+ ' :update-tx? true \n' +
|
|
|
+ ' :force-down? true\n' +
|
|
|
+ ' }';
|
|
|
+
|
|
|
+ let a = axios.post(storeFile, {
|
|
|
+ 'file-name': `${bucketName}/${dbKind}/${userID}/deploy-conf.edn`,
|
|
|
+ bucket: 'case',
|
|
|
+ cont: deployConf
|
|
|
+ });
|
|
|
+
|
|
|
+ let cont = '{:uri {\n' +
|
|
|
+ ':auth {:admin-db "order"\n' +
|
|
|
+ ' :u "ly"\n' +
|
|
|
+ ' :p "autorunC1705"\n' +
|
|
|
+ ' :host "119.27.174.13"}}\n' +
|
|
|
+ ' :db-name "order"}';
|
|
|
+
|
|
|
+ let b = dbKind === 'mongodb' ?
|
|
|
+ axios.post(storeFile, {
|
|
|
+ 'file-name': `${bucketName}/${dbKind}/${userID}/mongo-config.edn`,
|
|
|
+ bucket: 'case',
|
|
|
+ cont
|
|
|
+ })
|
|
|
+ :
|
|
|
+ Promise.resolve({status: 200});
|
|
|
+
|
|
|
+ Promise.all([a, b]).then(value => {
|
|
|
+ if (value.every(res => res.status === 200)) {
|
|
|
+ console.log('store file success , start deploying');
|
|
|
+ this.deploy();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ notification['warning']({
|
|
|
+ message: '需要填写配置',
|
|
|
+ description: '后续使用,需要先填写配置',
|
|
|
+ });
|
|
|
+
|
|
|
+ this.props.history.push({
|
|
|
+ pathname: `/login/cloud`
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }}>部署</Button>
|
|
|
+ }
|
|
|
+ </div>
|
|
|
}
|
|
|
</div>
|
|
|
</Content>
|
|
|
@@ -360,4 +442,104 @@ class DeployCloudChoose extends Component {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export default DeployCloudChoose
|
|
|
+export default DeployCloudChoose
|
|
|
+
|
|
|
+class CloudQueryAndConfig extends Component {
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ this.state = {
|
|
|
+ cloudName: props.cloudName,
|
|
|
+ userID: props.userID,
|
|
|
+ cloudID: '',
|
|
|
+ secretID: '',
|
|
|
+ secretKey: '',
|
|
|
+ appId: '',
|
|
|
+ showCloudConfigTip: false,
|
|
|
+
|
|
|
+ visible: false,
|
|
|
+ confirmLoading: false,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ searchCloud = () => {
|
|
|
+ let {userID, cloudName} = this.state;
|
|
|
+ // 如果登录,查询该用户是否设置 cloud
|
|
|
+ request(graphqlUrl, SHOW_CLOUD, {user_id: userID}).then(data => {
|
|
|
+ let clouds = data.cloud_by_props.filter(cloud => cloud.cloudName === cloudName);
|
|
|
+ // 如果限制一个云服务商一个 cloud,那么就是clouds[0]
|
|
|
+ if (clouds.length === 1) {
|
|
|
+ let cloud = clouds[0];
|
|
|
+ let {id, secretId, secretKey, appId} = cloud;
|
|
|
+ this.setState({
|
|
|
+ cloudID: id,
|
|
|
+ secretID: secretId,
|
|
|
+ secretKey,
|
|
|
+ appId
|
|
|
+ });
|
|
|
+ this.props.getCloudDetail(id, secretId, secretKey, appId);
|
|
|
+ this.setState({
|
|
|
+ showCloudConfigTip: false
|
|
|
+ })
|
|
|
+ } else if (clouds.length > 1) {
|
|
|
+ console.log('数据库有多个同一云服务商的 key');
|
|
|
+ } else {
|
|
|
+ this.setState({
|
|
|
+ showCloudConfigTip: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ };
|
|
|
+
|
|
|
+ componentWillMount() {
|
|
|
+ this.searchCloud()
|
|
|
+ }
|
|
|
+
|
|
|
+ componentWillReceiveProps(next) {
|
|
|
+ this.setState({
|
|
|
+ cloudName: next.cloudName,
|
|
|
+ userID: next.userID,
|
|
|
+ }, this.searchCloud);
|
|
|
+ }
|
|
|
+
|
|
|
+ showModal = () => {
|
|
|
+ this.setState({
|
|
|
+ visible: true,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ handleCancel = () => {
|
|
|
+ this.setState({
|
|
|
+ visible: false,
|
|
|
+ });
|
|
|
+ this.props.reCheck();
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ render() {
|
|
|
+ let {showCloudConfigTip, visible, confirmLoading} = this.state;
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {
|
|
|
+ showCloudConfigTip ?
|
|
|
+ <div>
|
|
|
+ <Button type="danger" size="small" onClick={this.showModal}>
|
|
|
+ <FormattedMessage id='no this cloud, click to save'/>
|
|
|
+ </Button>
|
|
|
+ <Modal
|
|
|
+ title="设置 cloud"
|
|
|
+ visible={visible}
|
|
|
+ confirmLoading={confirmLoading}
|
|
|
+ footer={null}
|
|
|
+ onCancel={this.handleCancel}
|
|
|
+ >
|
|
|
+ <CloudConfig/>
|
|
|
+ </Modal>
|
|
|
+ </div>
|
|
|
+ :
|
|
|
+ ''
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|