mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Component module related
This commit is contained in:
@@ -42,12 +42,6 @@ export default defineConfig({
|
||||
path: `/ApplicationList`,
|
||||
component: './ApplicationList',
|
||||
},
|
||||
{
|
||||
name: 'ApplicationList.ApplicationListDetail',
|
||||
hideInMenu: true,
|
||||
path: '/ApplicationList/ApplicationListDetail',
|
||||
component: './ApplicationList/ApplicationListDetail',
|
||||
},
|
||||
{
|
||||
name: 'ApplicationList.WorkloadDetail',
|
||||
icon: 'smile',
|
||||
@@ -62,12 +56,6 @@ export default defineConfig({
|
||||
component: './Traits/Detail',
|
||||
hideInMenu: true,
|
||||
},
|
||||
{
|
||||
name: 'ApplicationList.CreateApplication',
|
||||
hideInMenu: true,
|
||||
path: '/ApplicationList/CreateApplication',
|
||||
component: './ApplicationList/CreateApplication',
|
||||
},
|
||||
{
|
||||
name: 'ApplicationList.Components',
|
||||
hideInMenu: true,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
export default {
|
||||
dev: {
|
||||
'/api': {
|
||||
target: 'http://30.11.171.29:38081/',
|
||||
target: 'http://30.11.171.39:38081/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -30,6 +30,7 @@ class Trait extends React.Component {
|
||||
this.state = {
|
||||
visible: false,
|
||||
selectValue: null,
|
||||
compList: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,6 +38,19 @@ class Trait extends React.Component {
|
||||
this.getInitialData();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.currentEnv === this.props.currentEnv) {
|
||||
return true;
|
||||
}
|
||||
this.props.dispatch({
|
||||
type: 'applist/getList',
|
||||
payload: {
|
||||
url: `/api/envs/${nextProps.currentEnv}/apps/`,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
getInitialData = async () => {
|
||||
if (this.props.currentEnv) {
|
||||
await this.props.dispatch({
|
||||
@@ -71,7 +85,12 @@ class Trait extends React.Component {
|
||||
};
|
||||
const submitData = this.formRefStep2.current.getFieldValue();
|
||||
Object.keys(submitData).forEach((currentKey) => {
|
||||
if (currentKey !== 'name' && currentKey !== 'appName' && submitData[currentKey]) {
|
||||
if (
|
||||
currentKey !== 'name' &&
|
||||
currentKey !== 'appName' &&
|
||||
currentKey !== 'compName' &&
|
||||
submitData[currentKey]
|
||||
) {
|
||||
submitObj.flags.push({
|
||||
name: currentKey,
|
||||
value: submitData[currentKey].toString(),
|
||||
@@ -79,13 +98,14 @@ class Trait extends React.Component {
|
||||
}
|
||||
});
|
||||
const { currentEnv: envName } = this.props;
|
||||
const { appName } = submitData;
|
||||
if (envName && appName) {
|
||||
const { appName, compName } = submitData;
|
||||
if (envName && appName && compName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'trait/attachOneTraits',
|
||||
payload: {
|
||||
envName,
|
||||
appName,
|
||||
compName,
|
||||
params: submitObj,
|
||||
},
|
||||
});
|
||||
@@ -96,11 +116,8 @@ class Trait extends React.Component {
|
||||
message.success(res);
|
||||
const { history } = this.props.propsObj;
|
||||
history.push({
|
||||
pathname: '/ApplicationList/ApplicationListDetail',
|
||||
state: {
|
||||
appName,
|
||||
envName,
|
||||
},
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -113,10 +130,30 @@ class Trait extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
onChange = (value) => {
|
||||
onChange = async (value) => {
|
||||
this.setState({
|
||||
selectValue: value,
|
||||
compList: [],
|
||||
});
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/getAppDetail',
|
||||
payload: {
|
||||
envName: this.props.currentEnv,
|
||||
appName: value,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
const compData = _.get(res, 'components', []);
|
||||
const compList = [];
|
||||
compData.forEach((item) => {
|
||||
compList.push({
|
||||
compName: item.name,
|
||||
});
|
||||
});
|
||||
this.setState({
|
||||
compList,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onSearch = () => {};
|
||||
@@ -131,7 +168,11 @@ class Trait extends React.Component {
|
||||
}
|
||||
});
|
||||
}
|
||||
const appList = _.get(this.props, 'returnObj', []);
|
||||
let appList = _.get(this.props, 'returnObj', []);
|
||||
if (!appList) {
|
||||
appList = [];
|
||||
}
|
||||
const { compList = [] } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<div className="breadCrumb">
|
||||
@@ -212,13 +253,12 @@ class Trait extends React.Component {
|
||||
initialValues={initialObj}
|
||||
>
|
||||
<Form.Item
|
||||
label="Target"
|
||||
label="App"
|
||||
name="appName"
|
||||
rules={[{ required: true, message: 'Please Select a Application!' }]}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
allowClear
|
||||
value={this.state.selectValue}
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Select a Application"
|
||||
@@ -230,10 +270,34 @@ class Trait extends React.Component {
|
||||
}
|
||||
>
|
||||
{appList.length ? (
|
||||
appList.map((item) => {
|
||||
appList.map((item, index) => {
|
||||
return (
|
||||
<Option key={item.name} value={item.name}>
|
||||
{item.name}
|
||||
<Option key={index.toString()} value={item.app}>
|
||||
{item.app}
|
||||
</Option>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Fragment />
|
||||
)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Component"
|
||||
name="compName"
|
||||
rules={[{ required: true, message: 'Please Select a Component!' }]}
|
||||
>
|
||||
<Select
|
||||
allowClear
|
||||
// value={this.state.selectValue}
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Select a Component"
|
||||
>
|
||||
{compList.length ? (
|
||||
compList.map((item) => {
|
||||
return (
|
||||
<Option key={item.compName} value={item.compName}>
|
||||
{item.compName}
|
||||
</Option>
|
||||
);
|
||||
})
|
||||
|
||||
@@ -1,12 +1,108 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
import { Button, Row, Col, Breadcrumb } from 'antd';
|
||||
import { Button, Row, Col, Modal, Select, Breadcrumb, Form } from 'antd';
|
||||
import { connect } from 'dva';
|
||||
import { Link } from 'umi';
|
||||
import _ from 'lodash';
|
||||
import './index.less';
|
||||
|
||||
export default class Workload extends React.PureComponent {
|
||||
const { Option } = Select;
|
||||
|
||||
const layout = {
|
||||
labelCol: {
|
||||
span: 8,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 16,
|
||||
},
|
||||
};
|
||||
|
||||
@connect(({ loading, applist, globalData }) => ({
|
||||
loadingAll: loading.models.applist,
|
||||
currentEnv: globalData.currentEnv,
|
||||
returnObj: applist.returnObj,
|
||||
}))
|
||||
export default class Workload extends React.Component {
|
||||
formRefStep2 = React.createRef();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getInitialData();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.currentEnv === this.props.currentEnv) {
|
||||
return true;
|
||||
}
|
||||
this.props.dispatch({
|
||||
type: 'applist/getList',
|
||||
payload: {
|
||||
url: `/api/envs/${nextProps.currentEnv}/apps/`,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
getInitialData = async () => {
|
||||
if (this.props.currentEnv) {
|
||||
await this.props.dispatch({
|
||||
type: 'applist/getList',
|
||||
payload: {
|
||||
url: `/api/envs/${this.props.currentEnv}/apps/`,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
showModal = () => {
|
||||
this.setState(
|
||||
{
|
||||
visible: true,
|
||||
},
|
||||
() => {
|
||||
if (this.formRefStep2.current) {
|
||||
this.formRefStep2.current.resetFields();
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
handleOk = async () => {
|
||||
const submitData = await this.formRefStep2.current.validateFields();
|
||||
const { history } = this.props.propsObj;
|
||||
history.push({
|
||||
pathname: `/ApplicationList/${submitData.appName}/createComponent`,
|
||||
state: {
|
||||
...submitData,
|
||||
isCreate: false,
|
||||
envName: this.props.currentEnv,
|
||||
WorkloadType: this.props.propsObj.title,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
onChange = () => {};
|
||||
|
||||
onSearch = () => {};
|
||||
|
||||
render() {
|
||||
const { btnValue, pathname, title, crdInfo, state, settings, btnIsShow } = this.props.propsObj;
|
||||
const { btnValue, title, crdInfo, settings, btnIsShow } = this.props.propsObj;
|
||||
let appList = _.get(this.props, 'returnObj', []);
|
||||
if (!appList) {
|
||||
appList = [];
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="breadCrumb">
|
||||
@@ -56,13 +152,73 @@ export default class Workload extends React.PureComponent {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Link to={{ pathname, state }} style={{ display: btnIsShow ? 'block' : 'none' }}>
|
||||
{/* <Link to={{ pathname, state }} style={{ display: btnIsShow ? 'block' : 'none' }}>
|
||||
<Button type="primary" className="create-button">
|
||||
{btnValue}
|
||||
</Button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<Button
|
||||
type="primary"
|
||||
className="create-button"
|
||||
onClick={() => this.showModal()}
|
||||
style={{ display: btnIsShow ? 'block' : 'none' }}
|
||||
>
|
||||
{btnValue}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal
|
||||
title="Add Component"
|
||||
visible={this.state.visible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
footer={[
|
||||
<Button key="back" onClick={this.handleCancel}>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button key="submit" type="primary" onClick={this.handleOk}>
|
||||
Next
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Form
|
||||
labelAlign="left"
|
||||
{...layout}
|
||||
ref={this.formRefStep2}
|
||||
name="control-ref"
|
||||
className="traitItem"
|
||||
>
|
||||
<Form.Item
|
||||
label="App"
|
||||
name="appName"
|
||||
rules={[{ required: true, message: 'Please Select a Application!' }]}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
style={{ width: '100%' }}
|
||||
placeholder="Select a Application"
|
||||
optionFilterProp="children"
|
||||
onChange={this.onChange}
|
||||
onSearch={this.onSearch}
|
||||
filterOption={(input, option) =>
|
||||
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
>
|
||||
{appList.length ? (
|
||||
appList.map((item, index) => {
|
||||
return (
|
||||
<Option key={index.toString()} value={item.app}>
|
||||
{item.app}
|
||||
</Option>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Fragment />
|
||||
)}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</PageContainer>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -85,3 +85,19 @@ ol {
|
||||
.ant-breadcrumb a:hover {
|
||||
color: #1b58f4 !important;
|
||||
}
|
||||
// 对齐
|
||||
.ant-form-item-label > label::before {
|
||||
display: inline-block;
|
||||
width: 7.09px;
|
||||
height: 14px;
|
||||
margin-right: 4px;
|
||||
color: rgb(255, 77, 79);
|
||||
font-size: 14px;
|
||||
font-family: SimSun, sans-serif;
|
||||
line-height: 1;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.ant-spin-nested-loading {
|
||||
height: calc(100% - 46px) !important;
|
||||
}
|
||||
|
||||
22
dashboard/src/models/components.js
Normal file
22
dashboard/src/models/components.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { getComponentList, getComponentDetail, deleteComponent } from '@/services/components.js';
|
||||
|
||||
const TestModel = {
|
||||
namespace: 'components',
|
||||
state: {},
|
||||
effects: {
|
||||
*getComponentList({ payload }, { call }) {
|
||||
const res = yield call(getComponentList, payload);
|
||||
return res;
|
||||
},
|
||||
*getComponentDetail({ payload }, { call }) {
|
||||
const res = yield call(getComponentDetail, payload);
|
||||
return res;
|
||||
},
|
||||
*deleteComponent({ payload }, { call }) {
|
||||
const res = yield call(deleteComponent, payload);
|
||||
return res;
|
||||
},
|
||||
},
|
||||
reducers: {},
|
||||
};
|
||||
export default TestModel;
|
||||
@@ -15,12 +15,13 @@ class TableList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
appDetailData: {},
|
||||
compDetailData: {},
|
||||
visible: false,
|
||||
traitList: [],
|
||||
availableTraitList: [],
|
||||
envName: '',
|
||||
appName: '',
|
||||
compName: '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,98 +30,118 @@ class TableList extends React.Component {
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
if (this.props.appName !== nextProps.appName) {
|
||||
this.getInitialData(nextProps.appName);
|
||||
if (this.props.compName !== nextProps.compName) {
|
||||
this.getInitialData(nextProps.compName);
|
||||
}
|
||||
}
|
||||
|
||||
getInitialData = async (nextAppName) => {
|
||||
let appName = _.get(this.props, 'appName', '');
|
||||
getInitialData = async (nextCompName) => {
|
||||
const appName = _.get(this.props, 'appName', '');
|
||||
const envName = _.get(this.props, 'envName', '');
|
||||
appName = nextAppName || appName;
|
||||
if (appName && envName) {
|
||||
let compName = _.get(this.props, 'compName', '');
|
||||
compName = nextCompName || compName;
|
||||
if (appName && envName && compName) {
|
||||
this.setState({
|
||||
envName,
|
||||
appName,
|
||||
compName,
|
||||
});
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/getAppDetail',
|
||||
type: 'components/getComponentDetail',
|
||||
payload: {
|
||||
envName,
|
||||
appName,
|
||||
compName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
this.setState({
|
||||
appDetailData: res,
|
||||
compDetailData: res,
|
||||
});
|
||||
}
|
||||
const traits = await this.props.dispatch({
|
||||
type: 'trait/getTraits',
|
||||
});
|
||||
if (traits) {
|
||||
this.setState({
|
||||
traitList: traits,
|
||||
const traits = await this.props.dispatch({
|
||||
type: 'trait/getTraits',
|
||||
});
|
||||
}
|
||||
const workloadType = _.get(res, 'Workload.workload.kind', '');
|
||||
if (workloadType && workloadType === 'ContainerizedWorkload') {
|
||||
this.getAcceptTrait('containerized');
|
||||
} else if (workloadType && workloadType === 'Deployment') {
|
||||
this.getAcceptTrait('deployment');
|
||||
if (traits) {
|
||||
this.setState({
|
||||
traitList: traits,
|
||||
});
|
||||
}
|
||||
const workloadType = _.get(res, 'workload.kind', '');
|
||||
if (workloadType) {
|
||||
this.getAcceptTrait(workloadType.toLowerCase());
|
||||
}
|
||||
// if (workloadType && workloadType === '') {
|
||||
// this.getAcceptTrait('containerized');
|
||||
// } else if (workloadType && workloadType === 'Deployment') {
|
||||
// this.getAcceptTrait('deployment');
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getAcceptTrait = (workloadType) => {
|
||||
const res = this.state.traitList.filter((item) => {
|
||||
if (item.appliesTo.indexOf(workloadType) !== -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
// getAcceptTrait = (workloadType) => {
|
||||
// const res = this.state.traitList.filter((item) => {
|
||||
// if (item.appliesTo) {
|
||||
// if(item.appliesTo==='*'){
|
||||
// return true;
|
||||
// }
|
||||
// if (item.appliesTo.indexOf(workloadType) !== -1) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
// this.setState(() => ({
|
||||
// availableTraitList: res,
|
||||
// }));
|
||||
// };
|
||||
|
||||
getAcceptTrait = () => {
|
||||
const res = this.state.traitList;
|
||||
this.setState(() => ({
|
||||
availableTraitList: res,
|
||||
}));
|
||||
};
|
||||
|
||||
deleteApp = async (e) => {
|
||||
deleteComp = async (e) => {
|
||||
e.stopPropagation();
|
||||
const { envName } = this.state;
|
||||
const { appDetailData } = this.state;
|
||||
const appName = _.get(appDetailData, 'Workload.workload.metadata.name', '');
|
||||
if (appName && envName) {
|
||||
const { envName, appName, compName } = this.state;
|
||||
if (appName && envName && compName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/deleteApp',
|
||||
type: 'components/deleteComponent',
|
||||
payload: {
|
||||
appName,
|
||||
envName,
|
||||
compName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
message.success(res);
|
||||
this.props.history.push({ pathname: '/ApplicationList' });
|
||||
// 删除当前component成功后,刷新当前页面
|
||||
this.props.getInitCompList();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
deleteTrait = async (e, item) => {
|
||||
e.stopPropagation();
|
||||
const { appName, envName } = this.state;
|
||||
const { appName, envName, compName } = this.state;
|
||||
const traitNameObj = _.get(item, 'trait.metadata.annotations', '');
|
||||
const traitName = traitNameObj['vela.oam.dev/traitDef'] || traitNameObj['trait.oam.dev/name'];
|
||||
if (traitName && appName && envName) {
|
||||
if (traitName && appName && envName && compName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'trait/deleteOneTrait',
|
||||
payload: {
|
||||
envName,
|
||||
appName,
|
||||
traitName,
|
||||
compName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
message.success(res);
|
||||
this.getInitialData(2);
|
||||
this.getInitialData(compName);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -151,13 +172,14 @@ class TableList extends React.Component {
|
||||
});
|
||||
}
|
||||
});
|
||||
const { envName, appName } = this.state;
|
||||
if (envName && appName) {
|
||||
const { envName, appName, compName } = this.state;
|
||||
if (envName && appName && compName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'trait/attachOneTraits',
|
||||
payload: {
|
||||
envName,
|
||||
appName,
|
||||
compName,
|
||||
params: submitObj,
|
||||
},
|
||||
});
|
||||
@@ -166,7 +188,7 @@ class TableList extends React.Component {
|
||||
visible: false,
|
||||
});
|
||||
message.success(res);
|
||||
this.getInitialData(2);
|
||||
this.getInitialData(compName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -193,11 +215,16 @@ class TableList extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const status = _.get(this.state.appDetailData, 'Status', '');
|
||||
const Workload = _.get(this.state.appDetailData, 'Workload.workload', {});
|
||||
const Traits = _.get(this.state.appDetailData, 'Traits', []);
|
||||
const { compDetailData } = this.state;
|
||||
const status = _.get(compDetailData, 'status', '');
|
||||
const Workload = _.get(compDetailData, 'workload', {});
|
||||
const Traits = _.get(compDetailData, 'traits', []);
|
||||
let containers = {};
|
||||
containers = _.get(Workload, 'spec.containers[0]', {});
|
||||
if (_.get(Workload, 'kind', '') === 'Job') {
|
||||
containers = _.get(Workload, 'spec.template.spec.containers[0]', {});
|
||||
} else {
|
||||
containers = _.get(Workload, 'spec.podSpec.containers[0]', {});
|
||||
}
|
||||
let { loadingAll } = this.props;
|
||||
loadingAll = loadingAll || false;
|
||||
const colorObj = {
|
||||
@@ -238,6 +265,21 @@ class TableList extends React.Component {
|
||||
</p>
|
||||
<p className="title">Settings:</p>
|
||||
<Row>
|
||||
{_.get(Workload, 'kind', '') === 'Job' ? (
|
||||
<Fragment>
|
||||
<Col span="8">
|
||||
<p>count</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>
|
||||
{_.get(Workload, 'spec.completions', '') ||
|
||||
_.get(Workload, 'spec.parallelism', '')}
|
||||
</p>
|
||||
</Col>
|
||||
</Fragment>
|
||||
) : (
|
||||
<Fragment />
|
||||
)}
|
||||
{Object.keys(containers).map((currentKey) => {
|
||||
if (currentKey === 'ports') {
|
||||
return (
|
||||
@@ -280,8 +322,8 @@ class TableList extends React.Component {
|
||||
</Row>
|
||||
</div>
|
||||
<Popconfirm
|
||||
title="Are you sure delete this app?"
|
||||
onConfirm={(e) => this.deleteApp(e)}
|
||||
title="Are you sure delete this component?"
|
||||
onConfirm={(e) => this.deleteComp(e)}
|
||||
onCancel={this.cancel}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
@@ -295,11 +337,7 @@ class TableList extends React.Component {
|
||||
Traits.map((item, index) => {
|
||||
const traitItem = _.get(item, 'trait', {});
|
||||
const annotations = _.get(traitItem, 'metadata.annotations', {});
|
||||
let traitType = 1;
|
||||
const spec = _.get(traitItem, 'spec', {});
|
||||
if (traitItem.kind === 'Ingress') {
|
||||
traitType = 2;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className="summaryBox"
|
||||
@@ -338,53 +376,33 @@ class TableList extends React.Component {
|
||||
</Row>
|
||||
<p className="title">Properties:</p>
|
||||
<Row>
|
||||
{traitType === 2 ? (
|
||||
<Fragment>
|
||||
<Col span="8">
|
||||
<p>domain</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>{_.get(spec, 'rules[0].host', '')}</p>
|
||||
</Col>
|
||||
<Col span="8">
|
||||
<p>service</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>
|
||||
{_.get(
|
||||
spec,
|
||||
'rules[0].http.paths[0].backend.serviceName',
|
||||
'',
|
||||
)}
|
||||
</p>
|
||||
</Col>
|
||||
<Col span="8">
|
||||
<p>port</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>
|
||||
{_.get(
|
||||
spec,
|
||||
'rules[0].http.paths[0].backend.servicePort',
|
||||
'',
|
||||
)}
|
||||
</p>
|
||||
</Col>
|
||||
</Fragment>
|
||||
) : (
|
||||
Object.keys(spec).map((currentKey) => {
|
||||
return (
|
||||
<Fragment key={currentKey}>
|
||||
<Col span="8">
|
||||
<p>{currentKey}</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>{spec[currentKey]}</p>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
})
|
||||
)}
|
||||
{Object.keys(spec).map((currentKey) => {
|
||||
if (spec[currentKey].constructor === Object) {
|
||||
const backend = _.get(spec, `${currentKey}`, {});
|
||||
return Object.keys(backend).map((currentKey1) => {
|
||||
return (
|
||||
<Fragment key={currentKey1}>
|
||||
<Col span="8">
|
||||
<p>{currentKey1}</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>{backend[currentKey1]}</p>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Fragment key={currentKey}>
|
||||
<Col span="8">
|
||||
<p>{currentKey}</p>
|
||||
</Col>
|
||||
<Col span="16">
|
||||
<p>{spec[currentKey]}</p>
|
||||
</Col>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
<div style={{ clear: 'both', height: '32px' }}>
|
||||
<Popconfirm
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'umi';
|
||||
import { Breadcrumb, Button, Menu, Spin } from 'antd';
|
||||
import { Breadcrumb, Button, Menu, Spin, Popconfirm, message } from 'antd';
|
||||
import { connect } from 'dva';
|
||||
import _ from 'lodash';
|
||||
import './index.less';
|
||||
import ComponentDetail from '../ComponentDetail/index.jsx';
|
||||
|
||||
@connect(({ loading }) => ({
|
||||
@connect(({ loading, globalData }) => ({
|
||||
loadingAll: loading.models.applist,
|
||||
currentEnv: globalData.currentEnv,
|
||||
}))
|
||||
class TableList extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@@ -15,59 +16,94 @@ class TableList extends React.PureComponent {
|
||||
this.state = {
|
||||
envName: '',
|
||||
componentName: '',
|
||||
defaultSelectedKeys: 'a1',
|
||||
defaultSelectedKeys: '',
|
||||
appName: '',
|
||||
compList: [],
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.getInitData();
|
||||
}
|
||||
|
||||
getInitData = async () => {
|
||||
let appName = '';
|
||||
let envName = '';
|
||||
let description = '';
|
||||
let envName = this.props.currentEnv;
|
||||
if (this.props.location.state) {
|
||||
appName = _.get(this.props, 'location.state.appName', '');
|
||||
envName = _.get(this.props, 'location.state.envName', '');
|
||||
description = _.get(this.props, 'location.state.description', '');
|
||||
envName = _.get(this.props, 'location.state.envName', this.props.currentEnv);
|
||||
sessionStorage.setItem('appName', appName);
|
||||
sessionStorage.setItem('description', description);
|
||||
sessionStorage.setItem('envName', envName);
|
||||
} else {
|
||||
appName = sessionStorage.getItem('appName');
|
||||
description = sessionStorage.getItem('description');
|
||||
envName = sessionStorage.getItem('envName');
|
||||
}
|
||||
this.setState({
|
||||
appName,
|
||||
envName,
|
||||
componentName: appName,
|
||||
});
|
||||
if (appName === 'test33') {
|
||||
this.setState({
|
||||
defaultSelectedKeys: 'a1',
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/getAppDetail',
|
||||
payload: {
|
||||
envName,
|
||||
appName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
const compData = _.get(res, 'components', []);
|
||||
const compList = [];
|
||||
compData.forEach((item) => {
|
||||
compList.push({
|
||||
compName: item.name,
|
||||
});
|
||||
});
|
||||
} else if (appName === 'test01') {
|
||||
this.setState({
|
||||
defaultSelectedKeys: 'c2',
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
defaultSelectedKeys: 'c3',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
changeComponent = ({ key }) => {
|
||||
if (key === 'a1') {
|
||||
this.setState({
|
||||
componentName: 'test33',
|
||||
});
|
||||
} else if (key === 'c2') {
|
||||
this.setState({
|
||||
componentName: 'test01',
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
componentName: 'testoo',
|
||||
compList,
|
||||
});
|
||||
if (compList.length) {
|
||||
this.changeComponent({
|
||||
key: compList[0].compName,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
changeComponent = ({ key }) => {
|
||||
this.setState({
|
||||
componentName: key,
|
||||
defaultSelectedKeys: key,
|
||||
});
|
||||
};
|
||||
|
||||
deleteApp = async (e) => {
|
||||
e.stopPropagation();
|
||||
const { envName } = this.state;
|
||||
const { appName } = this.state;
|
||||
if (appName && envName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/deleteApp',
|
||||
payload: {
|
||||
appName,
|
||||
envName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
message.success(res);
|
||||
this.props.history.push({ pathname: '/ApplicationList' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cancel = (e) => {
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { envName, componentName, defaultSelectedKeys } = this.state;
|
||||
const { envName, componentName, defaultSelectedKeys, appName, compList } = this.state;
|
||||
const { loadingAll } = this.props;
|
||||
return (
|
||||
<div style={{ height: '100%' }}>
|
||||
@@ -79,7 +115,7 @@ class TableList extends React.PureComponent {
|
||||
<Breadcrumb.Item>
|
||||
<Link to="/ApplicationList">Applications</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>appname</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{appName}</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>Components</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{componentName}</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
@@ -91,31 +127,49 @@ class TableList extends React.PureComponent {
|
||||
mode="inline"
|
||||
onClick={this.changeComponent}
|
||||
defaultSelectedKeys={[defaultSelectedKeys]}
|
||||
selectedKeys={defaultSelectedKeys}
|
||||
>
|
||||
<Menu.ItemGroup key="g1" title="Components">
|
||||
<Menu.Item key="a1">a1(containerized)</Menu.Item>
|
||||
<Menu.Item key="c2">c2(deploy)</Menu.Item>
|
||||
<Menu.Item key="c3">c3(webserver)</Menu.Item>
|
||||
{compList.map((item) => {
|
||||
return <Menu.Item key={item.compName}>{item.compName}</Menu.Item>;
|
||||
})}
|
||||
</Menu.ItemGroup>
|
||||
</Menu>
|
||||
<div className="addComp">
|
||||
<Link
|
||||
to={{
|
||||
// pathname: '/ApplicationList/CreateApplication',
|
||||
pathname: `/ApplicationList/${componentName}/createComponent`,
|
||||
state: { appName: componentName, envName },
|
||||
pathname: `/ApplicationList/${appName}/createComponent`,
|
||||
state: { appName, envName, isCreate: false },
|
||||
}}
|
||||
>
|
||||
add a new comp
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="right">
|
||||
<div style={{ margin: '10px', float: 'right' }}>
|
||||
<Button type="primary">Delete App</Button>
|
||||
{defaultSelectedKeys ? (
|
||||
<div className="right">
|
||||
<div className="btn">
|
||||
<Popconfirm
|
||||
title="Are you sure delete this app?"
|
||||
placement="bottom"
|
||||
onConfirm={(e) => this.deleteApp(e)}
|
||||
onCancel={this.cancel}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<Button type="primary">Delete App</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
<ComponentDetail
|
||||
appName={appName}
|
||||
compName={componentName}
|
||||
envName={envName}
|
||||
getInitCompList={this.getInitData}
|
||||
/>
|
||||
</div>
|
||||
<ComponentDetail appName={componentName} envName={envName} />
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ width: '100%', height: '100%', background: '#FFFFFF' }} />
|
||||
)}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
.ant-spin-nested-loading {
|
||||
height: 100%;
|
||||
}
|
||||
.ant-spin-container {
|
||||
height: 100%;
|
||||
}
|
||||
.appComponent {
|
||||
display: flex;
|
||||
height: calc(100% - 46px);
|
||||
height: 100%;
|
||||
.left {
|
||||
width: 200px;
|
||||
background: #fff;
|
||||
@@ -24,12 +30,19 @@
|
||||
text-decoration: underline;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #efefef;
|
||||
border-right: 1px solid #efefef;
|
||||
border-bottom: 1px solid #efefef;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
// clear: both;
|
||||
.btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,12 @@ class TableList extends React.Component {
|
||||
workloadSettings: [],
|
||||
step1SubmitObj: {},
|
||||
step1InitialValues: {
|
||||
workload_type: '',
|
||||
workloadType: '',
|
||||
},
|
||||
step1Settings: [],
|
||||
appName: '',
|
||||
envName: '',
|
||||
isCreate: '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,18 +62,23 @@ class TableList extends React.Component {
|
||||
getInitalData = async () => {
|
||||
let appName = '';
|
||||
let envName = '';
|
||||
let isCreate = '';
|
||||
if (this.props.location.state) {
|
||||
appName = _.get(this.props, 'location.state.appName', '');
|
||||
envName = _.get(this.props, 'location.state.envName', '');
|
||||
isCreate = _.get(this.props, 'location.state.isCreate', false);
|
||||
sessionStorage.setItem('appName', appName);
|
||||
sessionStorage.setItem('envName', envName);
|
||||
sessionStorage.setItem('isCreate', isCreate);
|
||||
} else {
|
||||
appName = sessionStorage.getItem('appName');
|
||||
envName = sessionStorage.getItem('envName');
|
||||
isCreate = sessionStorage.getItem('isCreate');
|
||||
}
|
||||
this.setState({
|
||||
appName,
|
||||
envName,
|
||||
isCreate,
|
||||
});
|
||||
const res = await this.props.dispatch({
|
||||
type: 'workload/getWorkload',
|
||||
@@ -98,9 +104,9 @@ class TableList extends React.Component {
|
||||
WorkloadType = sessionStorage.getItem('WorkloadType');
|
||||
}
|
||||
this.formRefStep1.current.setFieldsValue({
|
||||
workload_type: WorkloadType || this.state.workloadList[0].name,
|
||||
workloadType: WorkloadType || this.state.workloadList[0].name,
|
||||
});
|
||||
this.workloadTypeChange(this.state.workloadList[0].name);
|
||||
this.workloadTypeChange(WorkloadType || this.state.workloadList[0].name);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -166,27 +172,31 @@ class TableList extends React.Component {
|
||||
};
|
||||
|
||||
createApp = async () => {
|
||||
const { traitNum } = this.state;
|
||||
const { traitNum, isCreate } = this.state;
|
||||
const { step1SubmitObj } = this.state;
|
||||
if (step1SubmitObj.env_name !== this.props.currentEnv) {
|
||||
step1SubmitObj.env_name = this.props.currentEnv;
|
||||
if (isCreate === true || isCreate === 'true') {
|
||||
step1SubmitObj.envName = this.props.currentEnv;
|
||||
} else {
|
||||
step1SubmitObj.envName = this.state.envName;
|
||||
}
|
||||
step1SubmitObj.appName = this.state.appName;
|
||||
const submitObj = _.cloneDeep(step1SubmitObj);
|
||||
const { workload_name: workloadName } = step1SubmitObj;
|
||||
const { workloadName, appName } = step1SubmitObj;
|
||||
submitObj.flags.push({
|
||||
name: 'name',
|
||||
value: workloadName.toString(),
|
||||
});
|
||||
// 处理数据为提交的格式
|
||||
if (traitNum.length) {
|
||||
const { env_name: envName } = step1SubmitObj;
|
||||
const { envName } = step1SubmitObj;
|
||||
const step2SubmitObj = [];
|
||||
traitNum.forEach(({ initialData }) => {
|
||||
if (initialData.name) {
|
||||
const initialObj = {
|
||||
name: initialData.name,
|
||||
env_name: envName,
|
||||
workload_name: workloadName,
|
||||
envName,
|
||||
workloadName,
|
||||
appName,
|
||||
flags: [],
|
||||
};
|
||||
Object.keys(initialData).forEach((key) => {
|
||||
@@ -210,10 +220,9 @@ class TableList extends React.Component {
|
||||
});
|
||||
if (res) {
|
||||
message.success(res);
|
||||
const { appName, envName } = this.state;
|
||||
this.props.history.push({
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
state: { appName, envName: step1SubmitObj.envName },
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -222,13 +231,13 @@ class TableList extends React.Component {
|
||||
await this.formRefStep1.current.validateFields();
|
||||
const currentData = this.formRefStep1.current.getFieldsValue();
|
||||
const submitObj = {
|
||||
env_name: this.props.currentEnv,
|
||||
workload_type: currentData.workload_type,
|
||||
workload_name: currentData.workload_name,
|
||||
envName: this.props.currentEnv,
|
||||
workloadType: currentData.workloadType,
|
||||
workloadName: currentData.workloadName,
|
||||
flags: [],
|
||||
};
|
||||
Object.keys(currentData).forEach((key) => {
|
||||
if (key !== 'workload_name' && key !== 'workload_type' && currentData[key]) {
|
||||
if (key !== 'workloadName' && key !== 'workloadType' && currentData[key]) {
|
||||
submitObj.flags.push({
|
||||
name: key,
|
||||
value: currentData[key].toString(),
|
||||
@@ -241,15 +250,15 @@ class TableList extends React.Component {
|
||||
step1Settings: submitObj.flags,
|
||||
step1SubmitObj: submitObj,
|
||||
});
|
||||
this.getAcceptTrait(currentData.workload_type);
|
||||
this.getAcceptTrait(currentData.workloadType);
|
||||
};
|
||||
|
||||
workloadTypeChange = (value) => {
|
||||
const content = this.formRefStep1.current.getFieldsValue();
|
||||
this.formRefStep1.current.resetFields();
|
||||
const initialObj = {
|
||||
workload_type: content.workload_type,
|
||||
workload_name: content.workload_name,
|
||||
workloadType: content.workloadType,
|
||||
workloadName: content.workloadName,
|
||||
};
|
||||
this.formRefStep1.current.setFieldsValue(initialObj);
|
||||
const currentWorkloadSetting = this.state.workloadList.filter((item) => {
|
||||
@@ -283,8 +292,14 @@ class TableList extends React.Component {
|
||||
|
||||
getAcceptTrait = (workloadType) => {
|
||||
const res = this.state.traitList.filter((item) => {
|
||||
if (item.appliesTo.indexOf(workloadType) !== -1) {
|
||||
return true;
|
||||
if (item.appliesTo) {
|
||||
if (item.appliesTo === '*') {
|
||||
return true;
|
||||
}
|
||||
if (item.appliesTo.indexOf(workloadType) !== -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -305,7 +320,7 @@ class TableList extends React.Component {
|
||||
|
||||
render() {
|
||||
const { appName, envName } = this.state;
|
||||
const { current, step1InitialValues, traitNum, workloadSettings } = this.state;
|
||||
const { current, step1InitialValues, traitNum, workloadSettings, isCreate } = this.state;
|
||||
let { workloadList } = this.state;
|
||||
workloadList = Array.isArray(workloadList) ? workloadList : [];
|
||||
let currentDetail;
|
||||
@@ -324,7 +339,7 @@ class TableList extends React.Component {
|
||||
>
|
||||
<div style={{ padding: '16px 48px 0px 16px' }}>
|
||||
<Form.Item
|
||||
name="workload_name"
|
||||
name="workloadName"
|
||||
label="Name"
|
||||
rules={[
|
||||
{
|
||||
@@ -341,7 +356,7 @@ class TableList extends React.Component {
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="workload_type"
|
||||
name="workloadType"
|
||||
label="Workload Type"
|
||||
rules={[
|
||||
{
|
||||
@@ -420,14 +435,24 @@ class TableList extends React.Component {
|
||||
<Button type="primary" className="floatRightGap" onClick={this.createWorkload}>
|
||||
Next
|
||||
</Button>
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
}}
|
||||
>
|
||||
<Button className="floatRightGap">Cancle</Button>
|
||||
</Link>
|
||||
{isCreate === true || isCreate === 'true' ? (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList`,
|
||||
}}
|
||||
>
|
||||
<Button className="floatRightGap">Cancle</Button>
|
||||
</Link>
|
||||
) : (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
}}
|
||||
>
|
||||
<Button className="floatRightGap">Cancle</Button>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
@@ -439,11 +464,11 @@ class TableList extends React.Component {
|
||||
<div className="minBox" style={{ width: '60%' }}>
|
||||
<div style={{ padding: '0px 48px 0px 16px', width: '60%' }}>
|
||||
<p style={{ fontSize: '18px', lineHeight: '32px' }}>
|
||||
Name:<span>{step1InitialValues.workload_name}</span>
|
||||
Name:<span>{step1InitialValues.workloadName}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ border: '1px solid #eee', padding: '16px 48px 16px 16px' }}>
|
||||
<p className="title">{step1InitialValues.workload_type}</p>
|
||||
<p className="title">{step1InitialValues.workloadType}</p>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span>apps/v1</span>
|
||||
<span
|
||||
@@ -517,14 +542,14 @@ class TableList extends React.Component {
|
||||
<div>
|
||||
<div className="minBox">
|
||||
<p>
|
||||
Name:<span>{step1InitialValues.workload_name}</span>
|
||||
Name:<span>{step1InitialValues.workloadName}</span>
|
||||
</p>
|
||||
<Row>
|
||||
<Col span="11">
|
||||
<div className="summaryBox1">
|
||||
<Row>
|
||||
<Col span="22">
|
||||
<p className="title">{step1InitialValues.workload_type}</p>
|
||||
<p className="title">{step1InitialValues.workloadType}</p>
|
||||
<p>apps/v1</p>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -611,15 +636,18 @@ class TableList extends React.Component {
|
||||
<Link to="/ApplicationList">Applications</Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
{appName}
|
||||
</Link>
|
||||
{isCreate === true || isCreate === 'true' ? (
|
||||
<span>{appName}</span>
|
||||
) : (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList/${appName}/Components`,
|
||||
state: { appName, envName },
|
||||
}}
|
||||
>
|
||||
{appName}
|
||||
</Link>
|
||||
)}
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>createComponent</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
import { BranchesOutlined, ApartmentOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Row, Col, Form, Spin, Empty, Breadcrumb, Modal, Input } from 'antd';
|
||||
import { Button, Form, Spin, Breadcrumb, Modal, Input, Table, Space, message } from 'antd';
|
||||
import { connect } from 'dva';
|
||||
import moment from 'moment';
|
||||
import './index.less';
|
||||
@@ -24,6 +23,63 @@ const layout = {
|
||||
class TableList extends React.Component {
|
||||
formRef = React.createRef();
|
||||
|
||||
columns = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'app',
|
||||
key: 'app',
|
||||
render: (text, record) => {
|
||||
return (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `/ApplicationList/${record.app}/Components`,
|
||||
state: { appName: record.app, envName: this.props.currentEnv },
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
render: (text) => {
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Components',
|
||||
dataIndex: 'components',
|
||||
key: 'components',
|
||||
render: (text) => {
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Created At',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
render: (text) => {
|
||||
return this.getFormatDate(text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
dataIndex: 'Actions',
|
||||
key: 'Actions',
|
||||
render: (text, record) => {
|
||||
return (
|
||||
<Space>
|
||||
<Button onClick={() => this.goToDetail(record)}>Details</Button>
|
||||
<Button onClick={() => this.deleteApp(record)}>Delete</Button>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -32,15 +88,7 @@ class TableList extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { currentEnv } = this.props;
|
||||
if (currentEnv) {
|
||||
this.props.dispatch({
|
||||
type: 'applist/getList',
|
||||
payload: {
|
||||
url: `/api/envs/${currentEnv}/apps/`,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.getInitData();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
@@ -56,6 +104,43 @@ class TableList extends React.Component {
|
||||
return true;
|
||||
}
|
||||
|
||||
getInitData = () => {
|
||||
const { currentEnv } = this.props;
|
||||
if (currentEnv) {
|
||||
this.props.dispatch({
|
||||
type: 'applist/getList',
|
||||
payload: {
|
||||
url: `/api/envs/${currentEnv}/apps/`,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
goToDetail = (record) => {
|
||||
this.props.history.push({
|
||||
pathname: `/ApplicationList/${record.app}/Components`,
|
||||
state: { appName: record.app, envName: this.props.currentEnv },
|
||||
});
|
||||
};
|
||||
|
||||
deleteApp = async (record) => {
|
||||
const appName = record.app;
|
||||
const envName = this.props.currentEnv;
|
||||
if (appName && envName) {
|
||||
const res = await this.props.dispatch({
|
||||
type: 'applist/deleteApp',
|
||||
payload: {
|
||||
appName,
|
||||
envName,
|
||||
},
|
||||
});
|
||||
if (res) {
|
||||
message.success(res);
|
||||
this.getInitData();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
showModal = () => {
|
||||
this.setState({
|
||||
visible: true,
|
||||
@@ -63,8 +148,11 @@ class TableList extends React.Component {
|
||||
};
|
||||
|
||||
handleOk = async () => {
|
||||
await this.formRef.current.validateFields();
|
||||
// const submitData = await this.formRef.current.validateFields();
|
||||
const submitData = await this.formRef.current.validateFields();
|
||||
this.props.history.push({
|
||||
pathname: `/ApplicationList/${submitData.appName}/createComponent`,
|
||||
state: { ...submitData, isCreate: true },
|
||||
});
|
||||
};
|
||||
|
||||
handleCancel = () => {
|
||||
@@ -91,14 +179,8 @@ class TableList extends React.Component {
|
||||
|
||||
render() {
|
||||
let { loadingAll, returnObj } = this.props;
|
||||
const { currentEnv } = this.props;
|
||||
loadingAll = loadingAll || false;
|
||||
returnObj = returnObj || [];
|
||||
const colorObj = {
|
||||
Deployed: 'first1',
|
||||
Staging: 'first2',
|
||||
UNKNOWN: 'first3',
|
||||
};
|
||||
loadingAll = loadingAll || false;
|
||||
return (
|
||||
<div>
|
||||
<div className="breadCrumb">
|
||||
@@ -114,74 +196,17 @@ class TableList extends React.Component {
|
||||
<div className="applist">
|
||||
<Form name="horizontal_login" layout="inline" onFinish={this.onFinish}>
|
||||
<Form.Item>
|
||||
<Link to="/ApplicationList/CreateApplication">
|
||||
<Button onClick={this.handleAdd} type="primary" style={{ marginBottom: 16 }}>
|
||||
create
|
||||
</Button>
|
||||
</Link>
|
||||
<Button onClick={this.showModal} type="primary" style={{ marginBottom: 16 }}>
|
||||
create
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
<Row gutter={16}>
|
||||
{Array.isArray(returnObj) && returnObj.length ? (
|
||||
returnObj.map((item, index) => {
|
||||
const { traits = [] } = item;
|
||||
return (
|
||||
<Col span={6} onClick={this.gotoDetail} key={index.toString()}>
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/ApplicationList/ApplicationListDetail',
|
||||
state: { appName: item.name, envName: currentEnv },
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
title={item.name}
|
||||
bordered={false}
|
||||
extra={this.getFormatDate(item.created)}
|
||||
>
|
||||
<div className="cardContent">
|
||||
<div
|
||||
className="box2"
|
||||
style={{ height: this.getHeight(traits.length) }}
|
||||
/>
|
||||
<div className="box1">
|
||||
{traits.length ? (
|
||||
<div className="box3" style={{ width: '30px' }} />
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<div
|
||||
className={['hasPadding', colorObj[item.status] || 'first3'].join(
|
||||
' ',
|
||||
)}
|
||||
>
|
||||
<ApartmentOutlined style={{ marginRight: '4px' }} />
|
||||
{item.workload}
|
||||
</div>
|
||||
</div>
|
||||
{traits.map((item1, index1) => {
|
||||
return (
|
||||
<div className="box1" key={index1.toString()}>
|
||||
<div className="box3" style={{ width: '50px' }} />
|
||||
<div className="other hasPadding">
|
||||
<BranchesOutlined style={{ marginRight: '4px' }} />
|
||||
{item1}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
</Col>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div style={{ width: '100%', height: '80%' }}>
|
||||
<Empty />
|
||||
</div>
|
||||
)}
|
||||
</Row>
|
||||
<Table
|
||||
rowKey={(record) => record.app + Math.random(1, 100)}
|
||||
columns={this.columns}
|
||||
dataSource={returnObj}
|
||||
/>
|
||||
</Spin>
|
||||
<Modal
|
||||
title="Create Application"
|
||||
@@ -196,7 +221,7 @@ class TableList extends React.Component {
|
||||
>
|
||||
<Form {...layout} ref={this.formRef} name="control-ref" labelAlign="left">
|
||||
<Form.Item
|
||||
name="name"
|
||||
name="appName"
|
||||
label="Name"
|
||||
rules={[
|
||||
{
|
||||
|
||||
@@ -58,6 +58,7 @@ class TableList extends React.PureComponent {
|
||||
btnValue: 'Create',
|
||||
hrefAddress: '#',
|
||||
btnIsShow: true,
|
||||
history: this.props.history,
|
||||
};
|
||||
this.setState({
|
||||
propsObj,
|
||||
|
||||
22
dashboard/src/services/components.js
Normal file
22
dashboard/src/services/components.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import request from '@/utils/request';
|
||||
/*
|
||||
* GET /api/envs/:envName/apps/:appName/components/ (component list)
|
||||
* Same as GET /api/envs/:envName/apps/:appName (app description).
|
||||
*/
|
||||
export async function getComponentList({ envName, appName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/`);
|
||||
}
|
||||
/*
|
||||
* GET /api/envs/:envName/apps/:appName/components/:compName (component details)
|
||||
*/
|
||||
export async function getComponentDetail({ envName, appName, compName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}`);
|
||||
}
|
||||
/*
|
||||
* DELETE /api/envs/:envName/apps/:appName/components/:compName (component delete)
|
||||
*/
|
||||
export async function deleteComponent({ envName, appName, compName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}`, {
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
@@ -12,10 +12,10 @@ export async function getTraits() {
|
||||
return request('/api/traits/');
|
||||
}
|
||||
/*
|
||||
* POST /api/envs/:envName/apps/:appName/traits/ (attach 单个 trait)
|
||||
* POST /api/envs/:envName/apps/:appName/components/:compName/traits/ (attach a trait)
|
||||
*/
|
||||
export async function attachOneTraits({ envName, appName, params }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/traits/`, {
|
||||
export async function attachOneTraits({ envName, appName, compName, params }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}/traits/`, {
|
||||
method: 'post',
|
||||
data: {
|
||||
...params,
|
||||
@@ -26,10 +26,13 @@ export async function attachOneTraits({ envName, appName, params }) {
|
||||
});
|
||||
}
|
||||
/*
|
||||
* DELETE /api/envs/:envName/apps/:appName/traits/:traitName (detach 单个 trait)
|
||||
* DELETE /api/envs/:envName/apps/:appName/components/:compName/traits/:traitName (detach a trait)
|
||||
*/
|
||||
export async function deleteOneTrait({ envName, appName, traitName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/traits/${traitName}`, {
|
||||
method: 'delete',
|
||||
});
|
||||
export async function deleteOneTrait({ envName, appName, compName, traitName }) {
|
||||
return request(
|
||||
`/api/envs/${envName}/apps/${appName}/components/${compName}/traits/${traitName}`,
|
||||
{
|
||||
method: 'delete',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user