409 lines
8.6 KiB
JavaScript
409 lines
8.6 KiB
JavaScript
// Copyright 2021 99cloud
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import React from 'react';
|
|
import { cloneDeep, isEmpty } from 'lodash';
|
|
import Notify from 'components/Notify';
|
|
import { Button, Steps, Spin } from 'antd';
|
|
import classnames from 'classnames';
|
|
import { firstUpperCase, unescapeHtml } from 'utils/index';
|
|
import { parse } from 'qs';
|
|
import NotFound from 'components/Cards/NotFound';
|
|
import styles from './index.less';
|
|
|
|
export default class BaseStepForm extends React.Component {
|
|
constructor(props, options = {}) {
|
|
super(props);
|
|
|
|
this.options = options;
|
|
|
|
this.state = {
|
|
// eslint-disable-next-line react/no-unused-state
|
|
formTemplate: cloneDeep(this.formTemplate),
|
|
current: 0,
|
|
data: {},
|
|
};
|
|
|
|
this.values = {};
|
|
this.setFormRefs();
|
|
this.init();
|
|
}
|
|
|
|
componentDidMount() {}
|
|
|
|
// componentWillReceiveProps(nextProps) {
|
|
// formPersist.set(
|
|
// `${nextProps.module}_step_form`,
|
|
// this.state.formTemplate
|
|
// );
|
|
// }
|
|
|
|
componentWillUnmount() {
|
|
this.unsubscribe && this.unsubscribe();
|
|
this.disposer && this.disposer();
|
|
this.unMountActions && this.unMountActions();
|
|
}
|
|
|
|
get hasConfirmStep() {
|
|
return false;
|
|
}
|
|
|
|
get name() {
|
|
return '';
|
|
}
|
|
|
|
get title() {
|
|
return `${this.name}s`;
|
|
}
|
|
|
|
get className() {
|
|
return '';
|
|
}
|
|
|
|
get prefix() {
|
|
return this.props.match.url;
|
|
}
|
|
|
|
get routing() {
|
|
return this.props.rootStore.routing;
|
|
}
|
|
|
|
get location() {
|
|
return this.props.location || {};
|
|
}
|
|
|
|
get locationParams() {
|
|
return parse(this.location.search.slice(1));
|
|
}
|
|
|
|
get match() {
|
|
return this.props.match || {};
|
|
}
|
|
|
|
get listUrl() {
|
|
return '/base/tmp';
|
|
}
|
|
|
|
get checkEndpoint() {
|
|
return false;
|
|
}
|
|
|
|
get endpoint() {
|
|
return '';
|
|
}
|
|
|
|
get endpointError() {
|
|
return this.checkEndpoint && !this.endpoint;
|
|
}
|
|
|
|
get currentUser() {
|
|
const { user } = this.props.rootStore || {};
|
|
return user || {};
|
|
}
|
|
|
|
get currentProjectId() {
|
|
return this.props.rootStore.projectId;
|
|
}
|
|
|
|
get labelCol() {
|
|
return {
|
|
xs: { span: 4 },
|
|
sm: { span: 2 },
|
|
};
|
|
}
|
|
|
|
get wrapperCol() {
|
|
return {
|
|
xs: { span: 16 },
|
|
sm: { span: 12 },
|
|
};
|
|
}
|
|
|
|
get steps() {
|
|
return [];
|
|
}
|
|
|
|
get formTemplate() {
|
|
return {};
|
|
}
|
|
|
|
get okBtnText() {
|
|
return t('Confirm');
|
|
}
|
|
|
|
get instanceName() {
|
|
const { name } = this.values || {};
|
|
return name;
|
|
}
|
|
|
|
get successText() {
|
|
return firstUpperCase(
|
|
t('{action} successfully, instance: {name}.', {
|
|
action: this.name.toLowerCase(),
|
|
name: this.instanceName,
|
|
})
|
|
);
|
|
}
|
|
|
|
get errorText() {
|
|
return t('Unable to {action}, instance: {name}.', {
|
|
action: this.name.toLowerCase(),
|
|
name: this.instanceName,
|
|
});
|
|
}
|
|
|
|
get isSubmitting() {
|
|
return (this.store && this.store.isSubmitting) || false;
|
|
}
|
|
|
|
get isLoading() {
|
|
if (this.hasExtraProps && isEmpty(this.state.extra)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
get currentComponent() {
|
|
const { current } = this.state;
|
|
return this.steps[current].component;
|
|
}
|
|
|
|
get currentRef() {
|
|
const { current } = this.state;
|
|
return this.formRefs[current];
|
|
}
|
|
|
|
get isAdminPage() {
|
|
return this.props.isAdminPage || false;
|
|
}
|
|
|
|
get hasExtraProps() {
|
|
return false;
|
|
}
|
|
|
|
setFormRefs() {
|
|
this.formRefs = this.steps.map(() => React.createRef());
|
|
}
|
|
|
|
getUrl(path, adminStr) {
|
|
return this.isAdminPage ? `${path}${adminStr || '-admin'}` : path;
|
|
}
|
|
|
|
getPrevBtn() {
|
|
const { current } = this.state;
|
|
if (current === 0) {
|
|
return null;
|
|
}
|
|
const preTitle = this.steps[current - 1].title;
|
|
return (
|
|
<Button style={{ margin: '0 8px' }} onClick={() => this.prev()}>
|
|
{`${t('Previous')}: ${preTitle}`}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
onSubmit = (values) => Promise.resolve();
|
|
|
|
onOk = () => {
|
|
const { data } = this.state;
|
|
// eslint-disable-next-line no-console
|
|
console.log('onOk', data);
|
|
this.values = data;
|
|
this.onSubmit(data).then(
|
|
() => {
|
|
this.routing.push(this.listUrl);
|
|
Notify.success(this.successText);
|
|
},
|
|
(err) => {
|
|
this.responseError = err;
|
|
const { response: { data: responseData } = {} } = err;
|
|
console.log('err', err, responseData);
|
|
Notify.errorWithDetail(responseData, this.errorText);
|
|
}
|
|
);
|
|
};
|
|
|
|
onCancel = () => {};
|
|
|
|
onClickSubmit = () => {
|
|
if (!this.hasConfirmStep) {
|
|
this.currentRef.current.wrappedInstance.checkFormInput((values) => {
|
|
this.updateData(values, this.onOk);
|
|
});
|
|
return;
|
|
}
|
|
this.onOk();
|
|
};
|
|
|
|
onClickCancel = () => {
|
|
this.routing.push(this.listUrl);
|
|
};
|
|
|
|
getNextBtn() {
|
|
const { current } = this.state;
|
|
if (current >= this.steps.length - 1) {
|
|
return null;
|
|
}
|
|
const { title } = this.steps[current + 1];
|
|
return (
|
|
<Button type="primary" onClick={() => this.next()}>
|
|
{`${t('Next')}: ${title}`}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
updateDataOnPrev = (values) => {
|
|
this.updateData(values, () => {
|
|
// const current = this.state.current - 1;
|
|
this.setState((pre) => ({ current: pre.current - 1 }));
|
|
});
|
|
};
|
|
|
|
updateData = (values, callback) => {
|
|
const { data } = this.state;
|
|
this.setState(
|
|
{
|
|
data: {
|
|
...data,
|
|
...values,
|
|
},
|
|
},
|
|
() => {
|
|
callback && callback();
|
|
}
|
|
);
|
|
};
|
|
|
|
unescape = (message) => unescapeHtml(message);
|
|
|
|
goStep = (index) => {
|
|
this.setState({
|
|
current: index,
|
|
});
|
|
};
|
|
|
|
prev() {
|
|
this.currentRef.current.wrappedInstance.checkFormInput(
|
|
this.updateDataOnPrev,
|
|
this.updateDataOnPrev
|
|
);
|
|
}
|
|
|
|
next() {
|
|
this.currentRef.current.wrappedInstance.checkFormInput((values) => {
|
|
// const current = this.state.current + 1;
|
|
this.updateData(values);
|
|
// this.setState({ current });
|
|
this.setState((prev) => ({ current: prev.current + 1 }));
|
|
});
|
|
}
|
|
|
|
init() {
|
|
this.store = {};
|
|
}
|
|
|
|
renderFooterLeft() {
|
|
return null;
|
|
}
|
|
|
|
renderFooter() {
|
|
const { current } = this.state;
|
|
return (
|
|
<div className={styles.footer}>
|
|
<div
|
|
className={classnames(styles['footer-left'], 'step-form-footer-left')}
|
|
>
|
|
{this.renderFooterLeft()}
|
|
</div>
|
|
<div className={classnames(styles.btns, 'step-form-footer-btns')}>
|
|
<Button className={styles.cancel} onClick={this.onClickCancel}>
|
|
{t('Cancel')}
|
|
</Button>
|
|
{this.getPrevBtn()}
|
|
{this.getNextBtn()}
|
|
{current === this.steps.length - 1 && (
|
|
<Button type="primary" onClick={this.onClickSubmit}>
|
|
{t('Confirm')}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
renderForms() {
|
|
const Component = this.currentComponent;
|
|
const { data, extra } = this.state;
|
|
if (this.hasExtraProps && isEmpty(extra)) {
|
|
return null;
|
|
}
|
|
return (
|
|
<Component
|
|
ref={this.currentRef}
|
|
context={data}
|
|
extra={extra}
|
|
updateContext={this.updateData}
|
|
goStep={this.goStep}
|
|
isAdminPage={this.isAdminPage}
|
|
match={this.match}
|
|
location={this.location}
|
|
/>
|
|
);
|
|
}
|
|
|
|
renderSteps() {
|
|
const { current } = this.state;
|
|
const { Step } = Steps;
|
|
return (
|
|
<div>
|
|
<div className={styles.step}>
|
|
<Steps current={current}>
|
|
{this.steps.map((item) => (
|
|
<Step key={item.title} title={item.title} />
|
|
))}
|
|
</Steps>
|
|
</div>
|
|
|
|
<div className={styles.form}>
|
|
{/* {this.steps[current].content} */}
|
|
{this.renderForms()}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
if (this.endpointError) {
|
|
return (
|
|
<NotFound
|
|
title={this.name}
|
|
link={this.listUrl}
|
|
endpointError
|
|
goList
|
|
isAction
|
|
/>
|
|
);
|
|
}
|
|
return (
|
|
<div className={classnames(styles.wrapper, this.className)}>
|
|
<Spin spinning={this.isLoading || this.isSubmitting}>
|
|
{this.renderSteps()}
|
|
{this.renderFooter()}
|
|
</Spin>
|
|
</div>
|
|
);
|
|
}
|
|
}
|