update applist

This commit is contained in:
hanxie
2020-09-29 19:08:04 +08:00
parent 351049b74f
commit 6c04af02cb
9 changed files with 16 additions and 1339 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
export default {
dev: {
'/api': {
target: 'http://30.11.171.39:38081/',
target: 'http://127.0.0.1:38081/',
changeOrigin: true,
},
},
@@ -1,108 +0,0 @@
import React, { useEffect } from 'react';
import G6 from '@antv/g6';
const Topology = () => {
let graph = null;
const data = {
nodes: [
{
id: 'node1',
x: 150,
y: 50,
label: 'node1',
},
{
id: 'node2',
x: 250,
y: 200,
label: 'node2',
},
{
id: 'node3',
x: 100,
y: 350,
label: 'node3',
},
],
edges: [
{
source: 'node1',
target: 'node2',
label: 'edge 1',
},
{
source: 'node2',
target: 'node3',
label: 'edge 2',
},
{
source: 'node3',
target: 'node1',
label: 'edge 3',
},
],
};
const width = 1000;
const height = 400;
useEffect(() => {
if (!graph) {
graph = new G6.Graph({
container: 'container',
width,
height,
// translate the graph to align the canvas's center, support by v3.5.1
fitCenter: true,
defaultNode: {
type: 'circle',
size: [40],
color: '#5B8FF9',
style: {
fill: '#9EC9FF',
lineWidth: 3,
},
labelCfg: {
style: {
fill: '#1890ff',
fontSize: 14,
},
position: 'bottom',
},
},
defaultEdge: {
labelCfg: {
autoRotate: true,
style: {
background: {
fill: '#ffffff',
stroke: '#9EC9FF',
padding: [2, 2, 2, 2],
radius: 2,
},
},
},
},
modes: {
default: ['drag-canvas', 'drag-node'],
},
nodeStateStyles: {
// style configurations for hover state
hover: {
fillOpacity: 0.8,
},
// style configurations for selected state
selected: {
lineWidth: 5,
},
},
});
}
graph.data(data);
graph.render();
}, []);
return <div id="container" style={{ overflow: 'auto', width: '100%', height: '400px' }} />;
};
export default Topology;
@@ -1,490 +0,0 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import './index.less';
import {
Button,
Row,
Col,
Tabs,
Popconfirm,
message,
Tooltip,
Modal,
Spin,
Breadcrumb,
} from 'antd';
import { connect } from 'dva';
import _ from 'lodash';
import { Link } from 'umi';
import CreateTraitItem from '../../../components/AttachOneTrait/index.jsx';
const { TabPane } = Tabs;
@connect(({ loading, globalData }) => ({
loadingAll: loading.models.applist,
currentEnv: globalData.currentEnv,
}))
class TableList extends React.Component {
constructor(props) {
super(props);
this.state = {
appDetailData: {},
visible: false,
traitList: [],
availableTraitList: [],
envName: '',
appName: '',
};
}
componentDidMount() {
this.getInitialData();
}
getInitialData = async () => {
let appName = '';
let envName = '';
if (this.props.location.state) {
appName = _.get(this.props, 'location.state.appName', '');
envName = _.get(this.props, 'location.state.envName', '');
sessionStorage.setItem('appName', appName);
sessionStorage.setItem('envName', envName);
} else {
appName = sessionStorage.getItem('appName');
envName = sessionStorage.getItem('envName');
}
this.setState({
appName,
envName,
});
if (appName && envName) {
const res = await this.props.dispatch({
type: 'applist/getAppDetail',
payload: {
envName,
appName,
},
});
if (res) {
this.setState({
appDetailData: res,
});
}
const traits = await this.props.dispatch({
type: 'trait/getTraits',
});
if (traits) {
this.setState({
traitList: traits,
});
}
const workloadType = _.get(res, 'Workload.workload.kind', '');
if (workloadType && workloadType === 'ContainerizedWorkload') {
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;
});
this.setState(() => ({
availableTraitList: res,
}));
};
deleteApp = async (e) => {
e.stopPropagation();
const { envName } = this.state;
const { appDetailData } = this.state;
const appName = _.get(appDetailData, 'Workload.workload.metadata.name', '');
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' });
}
}
};
deleteTrait = async (e, item) => {
e.stopPropagation();
const { appName, envName } = 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) {
const res = await this.props.dispatch({
type: 'trait/deleteOneTrait',
payload: {
envName,
appName,
traitName,
},
});
if (res) {
message.success(res);
this.getInitialData(2);
}
}
};
cancel = (e) => {
e.stopPropagation();
};
createTrait = async () => {
await this.setState({
visible: true,
});
};
handleOk = async () => {
await this.child.validateFields();
const submitData = this.child.getSelectValue();
if (submitData.name) {
const submitObj = {
name: submitData.name,
flags: [],
};
Object.keys(submitData).forEach((currentKey) => {
if (currentKey !== 'name' && submitData[currentKey]) {
submitObj.flags.push({
name: currentKey,
value: submitData[currentKey].toString(),
});
}
});
const { envName, appName } = this.state;
if (envName && appName) {
const res = await this.props.dispatch({
type: 'trait/attachOneTraits',
payload: {
envName,
appName,
params: submitObj,
},
});
if (res) {
this.setState({
visible: false,
});
message.success(res);
this.getInitialData(2);
}
}
} else {
message.warning('please select a trait type');
}
};
handleCancel = () => {
this.setState({
visible: false,
});
};
hrefClick = (e) => {
e.stopPropagation();
};
gotoWorkloadDetail = (e) => {
e.stopPropagation();
};
gotoTraitDetail = (e) => {
e.stopPropagation();
};
render() {
const status = _.get(this.state.appDetailData, 'Status', '');
const Workload = _.get(this.state.appDetailData, 'Workload.workload', {});
const Traits = _.get(this.state.appDetailData, 'Traits', []);
let containers = {};
containers = _.get(Workload, 'spec.containers[0]', {});
let { loadingAll } = this.props;
loadingAll = loadingAll || false;
const colorObj = {
Deployed: '#4CAF51',
Staging: '#F44337',
UNKNOWN: '#1890ff',
};
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>ApplicationListDetail</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<Spin spinning={loadingAll}>
<div className="card-container app-detial">
<h2>{_.get(Workload, 'metadata.name')}</h2>
<p style={{ marginBottom: '20px' }}>
{Workload.apiVersion}, Kind={Workload.kind}
</p>
<Tabs>
<TabPane tab="Summary" key="1">
<Row>
<Col span="11">
<div
className="summaryBox1"
onClick={(e) => this.gotoWorkloadDetail(e)}
style={{ background: colorObj[status] || '#1890ff' }}
>
<Row>
<Col span="22">
<p className="title">{Workload.kind}</p>
<p>{Workload.apiVersion}</p>
</Col>
<Col span="2">
<p className="title hasCursor" onClick={this.hrefClick}>
?
</p>
</Col>
</Row>
<p className="title">
Name:<span>{_.get(Workload, 'metadata.name')}</span>
</p>
<p className="title">Settings:</p>
<Row>
{Object.keys(containers).map((currentKey) => {
if (currentKey === 'ports') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>port</p>
</Col>
<Col span="16">
<p>{_.get(containers[currentKey], '[0].containerPort', '')}</p>
</Col>
</Fragment>
);
// eslint-disable-next-line no-else-return
} else if (currentKey === 'name') {
return <Fragment key={currentKey} />;
// eslint-disable-next-line no-else-return
} else if (currentKey === 'env') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>env</p>
</Col>
<Col span="16">
<p>{_.get(containers[currentKey], '[0].value', '')}</p>
</Col>
</Fragment>
);
}
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}</p>
</Col>
<Col span="16">
<p>{containers[currentKey]}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
<Popconfirm
title="Are you sure delete this app?"
onConfirm={(e) => this.deleteApp(e)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
>
<Button danger>Delete</Button>
</Popconfirm>
</Col>
<Col span="1" />
<Col span="10">
{Traits.length ? (
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"
onClick={(e) => this.gotoTraitDetail(e, traitItem)}
key={index.toString()}
>
<Row>
<Col span="22">
<p className="title">{traitItem.kind}</p>
<p>{traitItem.apiVersion}</p>
</Col>
<Col span="2">
<p
className="title hasCursor"
onClick={(e) => {
e.stopPropagation();
}}
>
?
</p>
</Col>
</Row>
<Row>
{Object.keys(annotations).map((currentKey3) => {
return (
<Fragment key={currentKey3}>
<Col span="8">
<p>{currentKey3}:</p>
</Col>
<Col span="8">
<p>{annotations[currentKey3]}</p>
</Col>
</Fragment>
);
})}
</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>
);
})
)}
</Row>
<div style={{ clear: 'both', height: '32px' }}>
<Popconfirm
title="Are you sure delete this trait?"
onConfirm={(e) => this.deleteTrait(e, item)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
>
<Button
danger
className="floatRight"
onClick={(e) => {
e.stopPropagation();
}}
>
Delete
</Button>
</Popconfirm>
</div>
</div>
);
})
) : (
<Fragment />
)}
<Tooltip placement="top" title="Attach Trait">
<p
className="hasCursor"
style={{
fontSize: '30px',
display: 'inline-flex',
}}
onClick={this.createTrait}
>
+
</p>
</Tooltip>
</Col>
</Row>
</TabPane>
<TabPane tab="Topology" key="2">
<p>Topology</p>
</TabPane>
</Tabs>
</div>
<Modal
title="Attach a Trait"
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}>
Confirm
</Button>,
]}
>
<CreateTraitItem
onRef={(ref) => {
this.child = ref;
}}
availableTraitList={this.state.availableTraitList}
initialValues={{}}
/>
</Modal>
</Spin>
</PageContainer>
</div>
);
}
}
export default TableList;
@@ -1,49 +0,0 @@
.app-detial {
.ant-tabs {
height: 800px;
min-height: 800px;
padding: 10px 20px;
overflow: auto;
background-color: #fff;
.ant-tabs-content-holder {
background: #fff;
}
}
.summaryBox1,
.summaryBox2,
.summaryBox {
clear: both;
margin-bottom: 20px;
padding: 0 10px 10px;
.title {
font-weight: 500;
font-size: 16px;
line-height: 36px;
}
p {
margin: 0;
font-size: 12px;
line-height: 20px;
}
}
.summaryBox1 {
color: #fff;
background: #0097a7;
cursor: pointer;
}
.summaryBox2 {
color: #fff;
background: #92c47c;
}
.summaryBox {
border: 1px solid black;
cursor: pointer;
}
.hasCursor {
font-size: 20px;
cursor: pointer;
}
.floatRight {
float: right;
}
}
@@ -1,606 +0,0 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import './index.less';
import { Button, Row, Col, Form, Input, Select, Steps, message, Breadcrumb } from 'antd';
import { connect } from 'dva';
import { Link } from 'umi';
import _ from 'lodash';
import CreateTraitItem from '../createTrait/index.jsx';
const { Option } = Select;
const { Step } = Steps;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
@connect(({ loading, globalData }) => ({
loadingAll: loading.models.workload,
currentEnv: globalData.currentEnv,
}))
class TableList extends React.Component {
formRefStep1 = React.createRef();
formRefStep2All = React.createRef();
constructor(props) {
super(props);
this.state = {
current: 0,
isShowMore: false,
traitNum: [
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
],
traitList: [],
availableTraitList: [],
workloadList: [],
workloadSettings: [],
step1SubmitObj: {},
step1InitialValues: {
workload_type: '',
},
step1Settings: [],
};
}
componentDidMount() {
this.getInitalData();
}
getInitalData = async () => {
const res = await this.props.dispatch({
type: 'workload/getWorkload',
});
const traits = await this.props.dispatch({
type: 'trait/getTraits',
});
this.setState({
traitList: traits,
});
if (Array.isArray(res) && res.length) {
this.setState(
() => ({
workloadList: res,
}),
() => {
if (this.state.current === 0) {
let WorkloadType = '';
if (this.props.location.state) {
WorkloadType = _.get(this.props, 'location.state.WorkloadType', '');
sessionStorage.setItem('WorkloadType', WorkloadType);
} else {
WorkloadType = sessionStorage.getItem('WorkloadType');
}
this.formRefStep1.current.setFieldsValue({
workload_type: WorkloadType || this.state.workloadList[0].name,
});
this.workloadTypeChange(this.state.workloadList[0].name);
}
},
);
}
};
onFinishStep1 = (values) => {
this.setState({
current: 1,
step1InitialValues: values,
isShowMore: false,
});
};
onFinishStep2 = async () => {
const asyncValidateArray = [];
this.state.traitNum.forEach((item) => {
asyncValidateArray.push(item.refname.validateFields());
});
await Promise.all(asyncValidateArray);
const newTraitNum = this.state.traitNum.map((item) => {
// eslint-disable-next-line no-param-reassign
item.initialData = item.refname.getSelectValue();
return item;
});
// 进行trait数据整理,便于第三步展示
this.setState(() => ({
traitNum: newTraitNum,
current: 2,
}));
};
gotoStep2 = () => {
this.setState({
current: 1,
isShowMore: false,
});
};
gotoStep1 = () => {
this.setState({
current: 0,
});
};
changeShowMore = () => {
this.setState({
isShowMore: true,
});
};
addMore = (e) => {
e.preventDefault();
this.setState((prev) => ({
traitNum: prev.traitNum.concat([
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
]),
}));
};
createApp = async () => {
const { traitNum } = this.state;
const { step1SubmitObj } = this.state;
if (step1SubmitObj.env_name !== this.props.currentEnv) {
step1SubmitObj.env_name = this.props.currentEnv;
}
const submitObj = _.cloneDeep(step1SubmitObj);
const { workload_name: workloadName } = step1SubmitObj;
submitObj.flags.push({
name: 'name',
value: workloadName.toString(),
});
// 处理数据为提交的格式
if (traitNum.length) {
const { env_name: envName } = step1SubmitObj;
const step2SubmitObj = [];
traitNum.forEach(({ initialData }) => {
if (initialData.name) {
const initialObj = {
name: initialData.name,
env_name: envName,
workload_name: workloadName,
flags: [],
};
Object.keys(initialData).forEach((key) => {
if (key !== 'name' && initialData[key]) {
initialObj.flags.push({
name: key,
value: initialData[key].toString(),
});
}
});
step2SubmitObj.push(initialObj);
}
});
submitObj.traits = step2SubmitObj;
}
const res = await this.props.dispatch({
type: 'workload/createWorkload',
payload: {
params: submitObj,
},
});
if (res) {
message.success(res);
this.props.history.push({
pathname: '/ApplicationList',
});
}
};
createWorkload = async () => {
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,
flags: [],
};
Object.keys(currentData).forEach((key) => {
if (key !== 'workload_name' && key !== 'workload_type' && currentData[key]) {
submitObj.flags.push({
name: key,
value: currentData[key].toString(),
});
}
});
this.setState({
current: 1,
step1InitialValues: currentData,
step1Settings: submitObj.flags,
step1SubmitObj: submitObj,
});
this.getAcceptTrait(currentData.workload_type);
};
workloadTypeChange = (value) => {
const content = this.formRefStep1.current.getFieldsValue();
this.formRefStep1.current.resetFields();
const initialObj = {
workload_type: content.workload_type,
workload_name: content.workload_name,
};
this.formRefStep1.current.setFieldsValue(initialObj);
const currentWorkloadSetting = this.state.workloadList.filter((item) => {
return item.name === value;
});
if (currentWorkloadSetting.length) {
this.setState(
{
workloadSettings: currentWorkloadSetting[0].parameters,
},
() => {
this.state.workloadSettings.forEach((item) => {
if (item.default) {
initialObj[item.name] = item.default;
}
});
this.formRefStep1.current.setFieldsValue(initialObj);
},
);
}
this.setState({
traitNum: [
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
],
});
};
getAcceptTrait = (workloadType) => {
const res = this.state.traitList.filter((item) => {
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
});
this.setState(() => ({
availableTraitList: res,
}));
};
deleteTraitItem = (uniq) => {
// 删除的时候不要依据数组的index删除,要一个唯一性的值
this.state.traitNum = this.state.traitNum.filter((item) => {
return item.uniq !== uniq;
});
this.setState((prev) => ({
traitNum: prev.traitNum,
}));
};
render() {
const { current, step1InitialValues, traitNum, workloadSettings } = this.state;
let { workloadList } = this.state;
workloadList = Array.isArray(workloadList) ? workloadList : [];
let currentDetail;
if (current === 0) {
currentDetail = (
<div>
<div className="minBox">
<Form
initialValues={step1InitialValues}
labelAlign="left"
{...layout}
ref={this.formRefStep1}
name="control-ref"
onFinish={this.onFinishStep1}
style={{ width: '60%' }}
>
<div style={{ padding: '16px 48px 0px 16px' }}>
<Form.Item
name="workload_name"
label="Name"
rules={[
{
pattern: /^[a-z0-9-_]+$/,
message:
'Names can only use digits(0-9),lowercase letters(a-z),and dashes(-),Underline.',
},
{
required: true,
message: 'Please input name!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="workload_type"
label="Workload Type"
rules={[
{
required: true,
message: 'Please select Workload Type!',
},
]}
>
<Select
placeholder="Select a Workload Type"
allowClear
onChange={this.workloadTypeChange}
>
{workloadList.length ? (
workloadList.map((item) => {
return (
<Option value={item.name} key={item.name}>
{item.name}
</Option>
);
})
) : (
<></>
)}
</Select>
</Form.Item>
</div>
<Form.Item
label="Settings"
style={{ background: 'rgba(0, 0, 0, 0.04)', paddingLeft: '16px' }}
/>
<div className="relativeBox">
<p className="hasMore">?</p>
{Array.isArray(workloadSettings) && workloadSettings.length ? (
workloadSettings.map((item) => {
if (item.name === 'name') {
return <Fragment key={item.name} />;
}
return item.type === 4 ? (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required,
message: `Please input ${item.name}!`,
},
{ pattern: /^[0-9]*$/, message: `${item.name} only use digits(0-9).` },
]}
>
<Input />
</Form.Item>
) : (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required,
message: `Please input ${item.name}!`,
},
{ pattern: /^[^\s]*$/, message: 'Spaces are not allowed!' },
]}
>
<Input />
</Form.Item>
);
})
) : (
<></>
)}
</div>
<div className="buttonBox">
<Button type="primary" className="floatRightGap" onClick={this.createWorkload}>
Next
</Button>
<Link to="/ApplicationList">
<Button className="floatRightGap">Cancle</Button>
</Link>
</div>
</Form>
</div>
</div>
);
} else if (current === 1) {
currentDetail = (
<div>
<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>
</p>
</div>
<div style={{ border: '1px solid #eee', padding: '16px 48px 16px 16px' }}>
<p className="title">{step1InitialValues.workload_type}</p>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>apps/v1</span>
<span
style={{
color: '#1890ff',
cursor: 'pointer',
display: this.state.isShowMore ? 'none' : 'black',
}}
onClick={this.changeShowMore}
>
more...
</span>
</div>
{this.state.isShowMore ? (
<div>
<p className="title" style={{ marginTop: '16px' }}>
Settings:
</p>
<Row>
{this.state.step1Settings.map((item) => {
return (
<Fragment key={item.name}>
<Col span="8">
<p>{item.name}:</p>
</Col>
<Col span="16">
<p>{item.value}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
) : (
''
)}
</div>
<div ref={this.formRefStep2All}>
{traitNum.map((item) => {
return (
<CreateTraitItem
onRef={(ref) => {
// eslint-disable-next-line no-param-reassign
item.refname = ref;
}}
key={item.uniq.toString()}
availableTraitList={this.state.availableTraitList}
uniq={item.uniq}
initialValues={item.initialData}
deleteTraitItem={this.deleteTraitItem}
/>
);
})}
</div>
<button style={{ marginTop: '16px' }} onClick={this.addMore} type="button">
Add More...
</button>
<div className="buttonBox">
<Button type="primary" className="floatRight" onClick={this.onFinishStep2}>
Next
</Button>
<Button className="floatRightGap" onClick={this.gotoStep1}>
Back
</Button>
</div>
</div>
</div>
);
} else {
currentDetail = (
<div>
<div className="minBox">
<p>
Name:<span>{step1InitialValues.workload_name}</span>
</p>
<Row>
<Col span="11">
<div className="summaryBox1">
<Row>
<Col span="22">
<p className="title">{step1InitialValues.workload_type}</p>
<p>apps/v1</p>
</Col>
</Row>
<p className="title hasMargin">Settings:</p>
<Row>
{this.state.step1Settings.map((item) => {
return (
<Fragment key={item.name}>
<Col span="8">
<p>{item.name}:</p>
</Col>
<Col span="16">
<p>{item.value}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
</Col>
<Col span="1" />
<Col span="10">
{traitNum.map(({ initialData }, index) => {
if (initialData.name) {
return (
<div className="summaryBox" key={index.toString()}>
<Row>
<Col span="22">
<p className="title">{initialData.name}</p>
<p>core.oam.dev/v1alpha2</p>
</Col>
</Row>
<p className="title hasMargin">Properties:</p>
<Row>
{Object.keys(initialData).map((currentKey) => {
if (currentKey !== 'name') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}:</p>
</Col>
<Col span="16">
<p>{initialData[currentKey]}</p>
</Col>
</Fragment>
);
}
return <Fragment key={currentKey} />;
})}
</Row>
</div>
);
}
return <Fragment key={index.toString()} />;
})}
</Col>
</Row>
</div>
<div className="buttonBox">
<Button
type="primary"
className="floatRight"
onClick={() => {
this.createApp();
}}
>
Confirm
</Button>
<Button className="floatRightGap" onClick={this.gotoStep2}>
Back
</Button>
</div>
</div>
);
}
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>CreateApplication</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<div className="create-container create-app">
<Steps current={current}>
<Step title="Step 1" description="Choose Workload" />
<Step title="Step 2" description="Attach Trait" />
<Step title="Step 3" description="Review and confirm" />
</Steps>
{currentDetail}
</div>
</PageContainer>
</div>
);
}
}
export default TableList;
@@ -1,66 +0,0 @@
.create-container {
padding: 10px;
background: #fff;
}
.create-app {
.minBox {
margin: 20px 10px;
padding: 10px;
border: 1px solid #eee;
.title {
font-size: 16px;
line-height: 36px;
}
}
.buttonBox {
clear: both;
height: 42px;
margin: 0 10px;
padding: 10px;
}
.floatRight {
float: right;
}
.floatRightGap {
float: right;
margin-right: 16px;
}
.relativeBox {
position: relative;
padding: 0 48px 0 16px;
.hasMore {
position: absolute;
top: 0;
right: 16px;
padding: 4px;
color: rgb(24, 144, 255);
font-size: 16px;
cursor: pointer;
}
}
.summaryBox1,
.summaryBox2,
.summaryBox {
clear: both;
margin-bottom: 20px;
padding: 0 10px 10px;
p {
margin: 0;
font-size: 12px;
line-height: 20px;
}
}
.summaryBox1 {
color: #fff;
background: rgb(24, 144, 255);
}
.summaryBox2 {
background: yellow;
}
.summaryBox {
border: 1px solid black;
}
.hasMargin {
padding: 8px 0;
}
}
@@ -386,7 +386,11 @@ class TableList extends React.Component {
</div>
<Form.Item
label="Settings"
style={{ background: 'rgba(0, 0, 0, 0.04)', paddingLeft: '16px' }}
style={{
background: 'rgba(0, 0, 0, 0.04)',
paddingLeft: '16px',
marginLeft: '-10px',
}}
/>
<div className="relativeBox">
<p className="hasMore">?</p>
@@ -99,7 +99,7 @@ export default class CreateTraitItem extends React.PureComponent {
})}
</Select>
</Form.Item>
<Form.Item label="Properties" />
<Form.Item label="Properties" style={{ marginLeft: '-10px' }} />
</div>
<div className="relativeBox">
{this.state.parameters ? (
+9 -17
View File
@@ -26,14 +26,14 @@ class TableList extends React.Component {
columns = [
{
title: 'Name',
dataIndex: 'app',
key: 'app',
dataIndex: 'name',
key: 'name',
render: (text, record) => {
return (
<Link
to={{
pathname: `/ApplicationList/${record.app}/Components`,
state: { appName: record.app, envName: this.props.currentEnv },
pathname: `/ApplicationList/${record.name}/Components`,
state: { appName: record.name, envName: this.props.currentEnv },
}}
>
{text}
@@ -50,15 +50,7 @@ class TableList extends React.Component {
},
},
{
title: 'Components',
dataIndex: 'components',
key: 'components',
render: (text) => {
return text;
},
},
{
title: 'Created At',
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
render: (text) => {
@@ -118,13 +110,13 @@ class TableList extends React.Component {
goToDetail = (record) => {
this.props.history.push({
pathname: `/ApplicationList/${record.app}/Components`,
state: { appName: record.app, envName: this.props.currentEnv },
pathname: `/ApplicationList/${record.name}/Components`,
state: { appName: record.name, envName: this.props.currentEnv },
});
};
deleteApp = async (record) => {
const appName = record.app;
const appName = record.name;
const envName = this.props.currentEnv;
if (appName && envName) {
const res = await this.props.dispatch({
@@ -203,7 +195,7 @@ class TableList extends React.Component {
</Form>
</div>
<Table
rowKey={(record) => record.app + Math.random(1, 100)}
rowKey={(record) => record.name + Math.random(1, 100)}
columns={this.columns}
dataSource={returnObj}
/>