From da2f8a9a81df7de6b1ec37a40faad0f67e1d409f Mon Sep 17 00:00:00 2001 From: hanxie Date: Fri, 21 Aug 2020 17:49:26 +0800 Subject: [PATCH] Update Capability static page docking with env and workload part of the interface --- .gitignore | 7 +- .../GlobalHeader/workSpaceDropDown.jsx | 45 +- dashboard/src/locales/en-US/menu.js | 2 +- .../models/{getAppList.js => application.js} | 6 +- dashboard/src/models/env.js | 20 + dashboard/src/models/global.js | 2 +- dashboard/src/models/trait.js | 20 + dashboard/src/models/workload.js | 24 + dashboard/src/pages/Addon/index.jsx | 16 - .../CreateApplication/index.jsx | 469 ++++++++++++------ .../ApplicationList/createTrait/index.jsx | 108 ++++ dashboard/src/pages/ApplicationList/index.jsx | 25 +- .../src/pages/Traits/Autoscaling/index.jsx | 2 +- dashboard/src/pages/Traits/Rollout/index.jsx | 2 +- .../{Task => Containerized}/index.jsx | 4 +- .../src/pages/Workload/Deployment/index.jsx | 13 + .../{getAppList.js => application.js} | 10 +- dashboard/src/services/env.js | 37 ++ dashboard/src/services/trait.js | 13 + dashboard/src/services/workload.js | 27 + dashboard/src/utils/request.js | 29 +- 21 files changed, 650 insertions(+), 231 deletions(-) rename dashboard/src/models/{getAppList.js => application.js} (87%) create mode 100644 dashboard/src/models/env.js create mode 100644 dashboard/src/models/trait.js create mode 100644 dashboard/src/models/workload.js delete mode 100644 dashboard/src/pages/Addon/index.jsx create mode 100644 dashboard/src/pages/ApplicationList/createTrait/index.jsx rename dashboard/src/pages/Workload/{Task => Containerized}/index.jsx (92%) rename dashboard/src/services/{getAppList.js => application.js} (77%) create mode 100644 dashboard/src/services/env.js create mode 100644 dashboard/src/services/trait.js create mode 100644 dashboard/src/services/workload.js diff --git a/.gitignore b/.gitignore index 91db5d1be..ac436dd7e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - # Binaries for programs and plugins *.exe *.exe~ @@ -33,3 +32,9 @@ vendor/ pkg/test/vela tmp/ + +# Dashboard +dashboard/node_modules/ +dashboard/package-lock.json +dashboard/src/.umi/ +package-lock.json \ No newline at end of file diff --git a/dashboard/src/components/GlobalHeader/workSpaceDropDown.jsx b/dashboard/src/components/GlobalHeader/workSpaceDropDown.jsx index 6bf3f2409..7f1e364ec 100644 --- a/dashboard/src/components/GlobalHeader/workSpaceDropDown.jsx +++ b/dashboard/src/components/GlobalHeader/workSpaceDropDown.jsx @@ -1,4 +1,4 @@ -import { Menu, Dropdown, Button } from 'antd'; +import { Menu, Dropdown, Button, message } from 'antd'; import { DownOutlined } from '@ant-design/icons'; import React from 'react'; import { connect } from 'dva'; @@ -15,29 +15,42 @@ export default class WorkSpaceDropDown extends React.Component { async componentDidMount() { const envs = await this.props.dispatch({ - type: 'applist/getEnvs', // applist对应models层的命名空间namespace - }); - const { name = 'test' } = envs.find((a) => { - return a.current === '*'; - }); - this.setState({ - envs, - workSpaceName: name, - }); - this.props.dispatch({ - type: 'globalData/currentEnv', - payload: { - currentEnv: name, - }, + type: 'envs/getEnvs', // applist对应models层的命名空间namespace }); + if (envs) { + const { name = 'test' } = envs.find((a) => { + return a.current === '*'; + }); + this.setState({ + envs, + workSpaceName: name, + }); + this.props.dispatch({ + type: 'globalData/currentEnv', + payload: { + currentEnv: name, + }, + }); + } } - handleMenuClick = (e) => { + handleMenuClick = async (e) => { + // 发送切换envs的接口 + const switchResult = await this.props.dispatch({ + type: 'envs/switchEnv', + payload: { + currentEnv: e.key, + }, + }); + if (switchResult) { + message.success(switchResult); + } this.setState( { workSpaceName: e.key, }, () => { + // 值切换存储 this.props.dispatch({ type: 'globalData/currentEnv', payload: { diff --git a/dashboard/src/locales/en-US/menu.js b/dashboard/src/locales/en-US/menu.js index 9b4362e4e..728f5cfae 100644 --- a/dashboard/src/locales/en-US/menu.js +++ b/dashboard/src/locales/en-US/menu.js @@ -13,7 +13,7 @@ export default { 'menu.Capability.Detail': 'Detail', 'menu.Workload': 'Workloads', 'menu.Workload.Deployment': 'Deployment', - 'menu.Workload.Task': 'Task', + 'menu.Workload.Containerized': 'Containerized', 'menu.Workload.Detail': 'Detail', 'menu.Release': 'Release', 'menu.admin': 'Admin', diff --git a/dashboard/src/models/getAppList.js b/dashboard/src/models/application.js similarity index 87% rename from dashboard/src/models/getAppList.js rename to dashboard/src/models/application.js index 47f6865ed..6bf29a7ba 100644 --- a/dashboard/src/models/getAppList.js +++ b/dashboard/src/models/application.js @@ -1,4 +1,4 @@ -import { getapplist, createApp, getEnvs } from '@/services/getAppList'; +import { getapplist, createApp } from '@/services/application'; const TestModel = { namespace: 'applist', @@ -22,10 +22,6 @@ const TestModel = { const res = yield call(createApp, payload); return res; }, - *getEnvs({ payload }, { call }) { - const res = yield call(getEnvs, payload); - return res; - }, }, reducers: { addList(state, { payload: { returnObj } }) { diff --git a/dashboard/src/models/env.js b/dashboard/src/models/env.js new file mode 100644 index 000000000..938b8fd5f --- /dev/null +++ b/dashboard/src/models/env.js @@ -0,0 +1,20 @@ +import { getEnvs, switchEnv } from '@/services/env'; + +const TestModel = { + namespace: 'envs', + state: { + // initailState: '8880' + }, + effects: { + *getEnvs({ payload }, { call }) { + const res = yield call(getEnvs, payload); + return res; + }, + *switchEnv({ payload }, { call }) { + const res = yield call(switchEnv, payload); + return res; + }, + }, + reducers: {}, +}; +export default TestModel; diff --git a/dashboard/src/models/global.js b/dashboard/src/models/global.js index ff10d9e8c..74cf45565 100644 --- a/dashboard/src/models/global.js +++ b/dashboard/src/models/global.js @@ -1,7 +1,7 @@ const globalModel = { namespace: 'globalData', state: { - currentEnv: 'test', + currentEnv: '', }, effects: { *currentEnv({ payload }, { put }) { diff --git a/dashboard/src/models/trait.js b/dashboard/src/models/trait.js new file mode 100644 index 000000000..9a6e25d83 --- /dev/null +++ b/dashboard/src/models/trait.js @@ -0,0 +1,20 @@ +import { getTraitByName, getTraits } from '@/services/trait.js'; + +const TestModel = { + namespace: 'trait', + state: { + // initailState: '8880' + }, + effects: { + *getTraitByName({ payload }, { call }) { + const res = yield call(getTraitByName, payload); + return res; + }, + *getTraits({ payload }, { call }) { + const res = yield call(getTraits, payload); + return res; + }, + }, + reducers: {}, +}; +export default TestModel; diff --git a/dashboard/src/models/workload.js b/dashboard/src/models/workload.js new file mode 100644 index 000000000..22390aa6a --- /dev/null +++ b/dashboard/src/models/workload.js @@ -0,0 +1,24 @@ +import { createWorkload, getWorkload, getWorkloadByName } from '@/services/workload.js'; + +const TestModel = { + namespace: 'workload', + state: { + // initailState: '8880' + }, + effects: { + *createWorkload({ payload }, { call }) { + const res = yield call(createWorkload, payload); + return res; + }, + *getWorkload({ payload }, { call }) { + const res = yield call(getWorkload, payload); + return res; + }, + *getWorkloadByName({ payload }, { call }) { + const res = yield call(getWorkloadByName, payload); + return res; + }, + }, + reducers: {}, +}; +export default TestModel; diff --git a/dashboard/src/pages/Addon/index.jsx b/dashboard/src/pages/Addon/index.jsx deleted file mode 100644 index 8a646e83c..000000000 --- a/dashboard/src/pages/Addon/index.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; -import { PageContainer } from "@ant-design/pro-layout"; - -class TableList extends React.Component { - render() { - return ( - -
- Addon -
-
- ); - } -} - -export default TableList; \ No newline at end of file diff --git a/dashboard/src/pages/ApplicationList/CreateApplication/index.jsx b/dashboard/src/pages/ApplicationList/CreateApplication/index.jsx index cb8a2d1d0..5ff489cb2 100644 --- a/dashboard/src/pages/ApplicationList/CreateApplication/index.jsx +++ b/dashboard/src/pages/ApplicationList/CreateApplication/index.jsx @@ -1,9 +1,11 @@ -import React from 'react'; +import React, { Fragment } from 'react'; import { PageContainer } from '@ant-design/pro-layout'; import './index.less'; -import { Button, Row, Col, Form, Input, Select, Steps } from 'antd'; +import { Button, Row, Col, Form, Input, Select, Steps, message } 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; @@ -17,42 +19,93 @@ const layout = { }, }; -@connect(() => ({})) +@connect(({ loading, globalData }) => ({ + loadingAll: loading.models.workload, + currentEnv: globalData.currentEnv, +})) class TableList extends React.Component { formRefStep1 = React.createRef(); - formRefStep2 = React.createRef(); + formRefStep2All = React.createRef(); constructor(props) { super(props); this.state = { current: 0, isShowMore: false, - traitNum: [1], + traitNum: [ + { + refname: null, + initialData: {}, + }, + ], + traitList: [], + availableTraitList: [], + workloadList: [], + workloadSettings: [], step1InitialValues: { - WorkloadType: 'Deployment', - }, - step2InitialValues: { - TraitType0: 'Autoscaling', + workload_type: '', }, + step1Settings: [], }; } UNSAFE_componentWillMount() { - if (this.props.location.state) { - const WorkloadType = this.props.location.state.WorkloadType || 'Deployment'; - const TraitType = this.props.location.state.TraitType || 'Autoscaling'; - const activeStep = this.props.location.state.activeStep || 0; - const tempState1 = { ...this.state.step1InitialValues, WorkloadType }; - const tempState2 = { ...this.state.step2InitialValues, TraitType0: TraitType }; - this.setState(() => ({ - current: activeStep, - step1InitialValues: tempState1, - step2InitialValues: tempState2, - })); - } + const activeStep = _.get(this.props, 'location.state.activeStep', 0); + this.setState(() => ({ + current: activeStep, + })); } + 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, + }); + // 如果直接跳转到第二步,需要设置值 + const traitType = _.get(this.props, 'location.state.TraitType', ''); + if (traitType) { + // let availableTraitList = traits.filter((item)=>{ + // return item.name === traitType + // }) + this.setState({ + availableTraitList: traits, + traitNum: [ + { + refname: null, + initialData: { name: traitType }, + }, + ], + }); + } + + if (Array.isArray(res) && res.length) { + this.setState( + () => ({ + workloadList: res, + }), + () => { + if (this.state.current === 0) { + const WorkloadType = _.get(this.props, 'location.state.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, @@ -61,11 +114,17 @@ class TableList extends React.Component { }); }; - onFinishStep2 = (values) => { - this.setState({ - current: 2, - step2InitialValues: values, + onFinishStep2 = () => { + 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 = () => { @@ -90,22 +149,103 @@ class TableList extends React.Component { addMore = (e) => { e.preventDefault(); this.setState((prev) => ({ - traitNum: prev.traitNum.concat([1]), + traitNum: prev.traitNum.concat([ + { + refname: null, + initialData: {}, + }, + ]), })); }; - createApp = async () => { - await this.props.dispatch({ - type: 'applist/createApp', // applist对应models层的命名空间namespace + createApp = () => {}; + + 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(), + }); + } + }); + const res = await this.props.dispatch({ + type: 'workload/createWorkload', payload: { - a: 1, - b: 3, + params: submitObj, }, }); + if (res) { + message.success(res); + } + this.setState({ + current: 1, + step1InitialValues: currentData, + step1Settings: submitObj.flags, + }); + 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: {}, + }, + ], + }); + }; + + getAcceptTrait = (workloadType) => { + const res = this.state.traitList.filter((item) => { + if (item.appliesTo.indexOf(workloadType) !== -1) { + return true; + } + return false; + }); + this.setState(() => ({ + availableTraitList: res, + })); }; render() { - const { current, step1InitialValues, step2InitialValues, traitNum } = this.state; + const { current, step1InitialValues, traitNum, workloadSettings } = this.state; + let { workloadList } = this.state; + workloadList = Array.isArray(workloadList) ? workloadList : []; let currentDetail; if (current === 0) { currentDetail = ( @@ -122,7 +262,7 @@ class TableList extends React.Component { >
- + {workloadList.length ? ( + workloadList.map((item) => { + return ( + + ); + }) + ) : ( + <> + )}

?

- - - - - - - - - - - - - - - + {Array.isArray(workloadSettings) && workloadSettings.length ? ( + workloadSettings.map((item) => { + return ( + + + + ); + }) + ) : ( + <> + )}
- @@ -183,101 +342,78 @@ class TableList extends React.Component { } else if (current === 1) { currentDetail = (
-
+

- Name:{step1InitialValues.WorkloadName} + Name:{step1InitialValues.workload_name}

-
-
-

{step1InitialValues.WorkloadType}

-
- apps/v1 - - more... - -
- {this.state.isShowMore ? ( -
-

- Settings: -

- - -

Deployment Strategy

-

Rolling Update Strategy

-

Min Ready Seconds

-

Revision History Limit

-

Replicas

- - -

{step1InitialValues.setting1}

-

{step1InitialValues.setting2}

-

{step1InitialValues.setting3}

-

{step1InitialValues.setting4}

-

{step1InitialValues.setting5}

- -
-
- ) : ( - '' - )} +
+

{step1InitialValues.workload_type}

+
+ apps/v1 + + more... +
+ {this.state.isShowMore ? ( +
+

+ Settings: +

+ + {this.state.step1Settings.map((item) => { + return ( + + +

{item.name}:

+ + +

{item.value}

+ +
+ ); + })} +
+
+ ) : ( + '' + )} +
+
{traitNum.map((item, index) => { return ( -
{ + // eslint-disable-next-line no-param-reassign + item.refname = ref; + }} key={index.toString()} - > -
- - - - -
-
-

?

- - - - - - -
-
+ availableTraitList={this.state.availableTraitList} + index={index} + initialValues={item.initialData} + /> ); })} - -
- - -
- +
+ +
+ + +
); @@ -286,57 +422,62 @@ class TableList extends React.Component {

- Name:{step1InitialValues.WorkloadName} + Name:{step1InitialValues.workload_name}

-

{step1InitialValues.WorkloadType}

+

{step1InitialValues.workload_type}

apps/v1

Settings:

- -

Deployment Strategy

-

Rolling Update Strategy

-

Min Ready Seconds

-

Revision History Limit

-

Replicas

- - -

{step1InitialValues.setting1}

-

{step1InitialValues.setting2}

-

{step1InitialValues.setting3}

-

{step1InitialValues.setting4}

-

{step1InitialValues.setting5}

- + {this.state.step1Settings.map((item) => { + return ( + + +

{item.name}:

+ + +

{item.value}

+ +
+ ); + })}
- {traitNum.map((item, index) => { + {traitNum.map(({ initialData }, index) => { return (
-

{step2InitialValues[`TraitType${index}`]}

+

{initialData.name}

core.oam.dev/v1alpha2

Properties:

- -

Min Instances

-

Max Instances

- - -

{step2InitialValues[`setting1${index}`]}

-

{step2InitialValues[`setting2${index}`]}

- + {Object.keys(initialData).map((currentKey) => { + if (currentKey !== 'name') { + return ( + + +

{currentKey}:

+ + +

{initialData[currentKey]}

+ +
+ ); + } + return ; + })}
); diff --git a/dashboard/src/pages/ApplicationList/createTrait/index.jsx b/dashboard/src/pages/ApplicationList/createTrait/index.jsx new file mode 100644 index 000000000..7fc85e6c9 --- /dev/null +++ b/dashboard/src/pages/ApplicationList/createTrait/index.jsx @@ -0,0 +1,108 @@ +import { Form, Input, Select } from 'antd'; +import { connect } from 'dva'; +import React from 'react'; +import _ from 'lodash'; + +const { Option } = Select; +const layout = { + labelCol: { + span: 8, + }, + wrapperCol: { + span: 16, + }, +}; + +@connect(() => ({})) +export default class CreateTraitItem extends React.PureComponent { + formRefStep2 = React.createRef(); + + constructor(props) { + super(props); + this.state = { + parameters: [], + }; + } + + componentDidMount() { + this.props.onRef(this); + if (this.props.initialValues && this.props.initialValues.name) { + this.traitSelectChange(this.props.initialValues.name, 2); + } + } + + getSelectValue = () => { + return this.formRefStep2.current.getFieldsValue(); + }; + + traitSelectChange = async (value, isType = 1) => { + const res = await this.props.dispatch({ + type: 'trait/getTraitByName', + payload: { + traitName: value, + }, + }); + this.setState({ + parameters: res.parameters, + }); + if (isType === 2) { + this.formRefStep2.current.setFieldsValue(this.props.initialValues); + } else { + // 进行默认值填写 + const parameters = _.get(res, 'parameters', []); + if (parameters.length) { + const initialObj = {}; + parameters.forEach((item) => { + if (item.default) { + initialObj[item.name] = item.default; + } + }); + this.formRefStep2.current.setFieldsValue(initialObj); + } + } + }; + + render() { + const { availableTraitList } = this.props; + return ( +
+
+
+ + + + +
+
+ {/*

?

*/} + {this.state.parameters ? ( + this.state.parameters.map((item) => { + return ( + + + + ); + }) + ) : ( + <> + )} +
+
+
+ ); + } +} diff --git a/dashboard/src/pages/ApplicationList/index.jsx b/dashboard/src/pages/ApplicationList/index.jsx index 5fb69c6b3..3756bd145 100644 --- a/dashboard/src/pages/ApplicationList/index.jsx +++ b/dashboard/src/pages/ApplicationList/index.jsx @@ -18,18 +18,35 @@ const { Option } = Select; currentEnv: globalData.currentEnv, })) class TableList extends React.Component { + constructor(props) { + super(props); + this.state = {}; + } + componentDidMount() { const { currentEnv } = this.props; + if (currentEnv) { + this.props.dispatch({ + type: 'applist/getList', // applist对应models层的命名空间namespace + payload: { + url: `/api/envs/${currentEnv}/apps/`, + }, + }); + } + } + + shouldComponentUpdate(nextProps) { + if (nextProps.currentEnv === this.props.currentEnv) { + return true; + } this.props.dispatch({ type: 'applist/getList', // applist对应models层的命名空间namespace payload: { - url: `/api/envs/${currentEnv}/apps/`, + url: `/api/envs/${nextProps.currentEnv}/apps/`, }, }); - } - - shouldComponentUpdate() { return true; + // return true; } onFinish = () => { diff --git a/dashboard/src/pages/Traits/Autoscaling/index.jsx b/dashboard/src/pages/Traits/Autoscaling/index.jsx index cb1df628d..a060d64e5 100644 --- a/dashboard/src/pages/Traits/Autoscaling/index.jsx +++ b/dashboard/src/pages/Traits/Autoscaling/index.jsx @@ -18,7 +18,7 @@ class TableList extends React.PureComponent { pathname: '/ApplicationList/CreateApplication', state: { activeStep: 1, - TraitType: 'Autoscaling', + TraitType: 'autoscaling', }, btnValue: 'Attach to', hrefAddress: '#', diff --git a/dashboard/src/pages/Traits/Rollout/index.jsx b/dashboard/src/pages/Traits/Rollout/index.jsx index 6b3ae6207..4d1988d28 100644 --- a/dashboard/src/pages/Traits/Rollout/index.jsx +++ b/dashboard/src/pages/Traits/Rollout/index.jsx @@ -18,7 +18,7 @@ class TableList extends React.PureComponent { pathname: '/ApplicationList/CreateApplication', state: { activeStep: 1, - TraitType: 'Rollout', + TraitType: 'rollout', }, btnValue: 'Attach to', hrefAddress: '#', diff --git a/dashboard/src/pages/Workload/Task/index.jsx b/dashboard/src/pages/Workload/Containerized/index.jsx similarity index 92% rename from dashboard/src/pages/Workload/Task/index.jsx rename to dashboard/src/pages/Workload/Containerized/index.jsx index a634c775f..ee367d9be 100644 --- a/dashboard/src/pages/Workload/Task/index.jsx +++ b/dashboard/src/pages/Workload/Containerized/index.jsx @@ -4,7 +4,7 @@ import Workload from '../../../components/Workload'; class TableList extends React.PureComponent { render() { const propsObj = { - title: 'Task', + title: 'containerized', settings: [ { name: 'Deployment Strategy', @@ -29,7 +29,7 @@ class TableList extends React.PureComponent { ], pathname: '/ApplicationList/CreateApplication', state: { - WorkloadType: 'Task', + WorkloadType: 'containerized', }, btnValue: 'Create', hrefAddress: '#', diff --git a/dashboard/src/pages/Workload/Deployment/index.jsx b/dashboard/src/pages/Workload/Deployment/index.jsx index 15cd5dbcf..92d8a745a 100644 --- a/dashboard/src/pages/Workload/Deployment/index.jsx +++ b/dashboard/src/pages/Workload/Deployment/index.jsx @@ -1,7 +1,20 @@ import React from 'react'; +import { connect } from 'dva'; import Workload from '../../../components/Workload'; +@connect(({ loading }) => ({ + loadingAll: loading.models.applist, +})) class TableList extends React.PureComponent { + // async componentDidMount(){ + // await this.props.dispatch({ + // type:'workload/getWorkloadByName', + // payload: { + // workloadName: 'containerized' + // } + // }) + // }; + render() { const propsObj = { title: 'Deployment', diff --git a/dashboard/src/services/getAppList.js b/dashboard/src/services/application.js similarity index 77% rename from dashboard/src/services/getAppList.js rename to dashboard/src/services/application.js index a8f9c0df6..287ed6dbd 100644 --- a/dashboard/src/services/getAppList.js +++ b/dashboard/src/services/application.js @@ -1,8 +1,13 @@ import request from '@/utils/request'; - +/* + * 应用列表:/api/envs/default/apps/ + */ export async function getapplist({ url }) { return request(url); } +/* + * 创建应用:/api/envs/default/apps/ + */ export async function createApp({ params, url }) { return request(url, { method: 'POST', @@ -15,6 +20,3 @@ export async function createApp({ params, url }) { }, }); } -export async function getEnvs() { - return request('/api/envs/'); -} diff --git a/dashboard/src/services/env.js b/dashboard/src/services/env.js new file mode 100644 index 000000000..7e091aced --- /dev/null +++ b/dashboard/src/services/env.js @@ -0,0 +1,37 @@ +import request from '@/utils/request'; +/* + * 初始化 env:Post /api/envs/ + */ +export async function initialEnvs() { + return request('/api/envs/', { + method: 'post', + }); +} +/* + * env 列表:Get /api/envs/ + */ +export async function getEnvs() { + return request('/api/envs/'); +} +/* + * 查询 env:Get /api/envs/:envName + */ +export async function searchEnvs({ envName }) { + return request(`/api/envs/${envName}`); +} +/* + * 删除 env:Delete /api/envs/:envName + */ +export async function deleteEnv({ envName }) { + return request(`/api/envs/${envName}`, { + method: 'delete', + }); +} +/* + * 切换 env:Patch /api/envs/:envName + */ +export async function switchEnv({ currentEnv }) { + return request(`/api/envs/${currentEnv}`, { + method: 'Patch', + }); +} diff --git a/dashboard/src/services/trait.js b/dashboard/src/services/trait.js new file mode 100644 index 000000000..cd25ed005 --- /dev/null +++ b/dashboard/src/services/trait.js @@ -0,0 +1,13 @@ +import request from '@/utils/request'; +/* + * 获取单个 trait: GET /api/traits/:traitName + */ +export async function getTraitByName({ traitName }) { + return request(`/api/traits/${traitName}`); +} +/* + * traits 列表:GET /api/traits/ + */ +export async function getTraits() { + return request('/api/traits/'); +} diff --git a/dashboard/src/services/workload.js b/dashboard/src/services/workload.js new file mode 100644 index 000000000..4c3a89f1d --- /dev/null +++ b/dashboard/src/services/workload.js @@ -0,0 +1,27 @@ +import request from '@/utils/request'; +/* + * 创建 workload:POST /api/workloads/ + */ +export async function createWorkload({ params }) { + return request('/api/workloads/', { + method: 'post', + data: { + ...params, + }, + headers: { + 'Content-Type': 'application/json', + }, + }); +} +/* + * workloads 列表 GET /api/workloads/ + */ +export async function getWorkload() { + return request('/api/workloads/'); +} +/* + * GET /api/workloads/:workloadName + */ +export async function getWorkloadByName({ workloadName }) { + return request(`/api/workloads/${workloadName}`); +} diff --git a/dashboard/src/utils/request.js b/dashboard/src/utils/request.js index 0c1548593..d878b8dc1 100644 --- a/dashboard/src/utils/request.js +++ b/dashboard/src/utils/request.js @@ -3,7 +3,7 @@ * 更详细的 api 文档: https://github.com/umijs/umi-request */ import { extend } from 'umi-request'; -import { notification, message } from 'antd'; +import { message } from 'antd'; const codeMessage = { 200: '服务器成功返回请求的数据。', @@ -28,26 +28,18 @@ const codeMessage = { const errorHandler = async (error) => { const { response } = error; - const { error: errorMessage } = await error.response.clone().json(); if (response && response.status) { const errorText = codeMessage[response.status] || response.statusText; - const { status } = response; - // const { status, url } = response; - // notification.error({ - // message: `请求错误 ${status}: ${url}`, - // description: errorMessage || errorText, - // }); - message.error(`请求错误 ${status} ${errorMessage || errorText}`); + const { status, url } = response; + message.error(`请求错误 ${status}:${url} ${errorText}`); } else if (!response) { - notification.error({ - description: '您的网络发生异常,无法连接服务器', - message: '网络异常', - }); + message.error('网络异常: 您的网络发生异常,无法连接服务器'); } + // throw error; // 如果throw. 错误将继续抛出. // 如果return, 则将值作为返回. 'return;' 相当于return undefined, 在处理结果时判断response是否有值即可. // return {some: 'data'}; - return response; + // return response; }; /** @@ -68,12 +60,19 @@ const request = extend({ * 否则,data 类型 = string,存储的是操作成功的信息 */ request.interceptors.response.use(async (response) => { + if (response.status !== 200 && response.status !== 500) { + errorHandler({ response }); + return; + } const data = await response.clone().json(); if (data && data.error) { message.error(`请求错误${response.status} :${data.error}`); return; + // eslint-disable-next-line no-else-return + } else if (data && data.code === 500) { + message.error(`请求错误${response.status} :${data.data}`); + return; } - // console.log(data) // eslint-disable-next-line consistent-return return data.data; // return response;