fix: Support cancel upload && show progress
1. Support cancel upload file 3. Show upload progress when upload image 4. Fix delete file after select file Change-Id: I021fee23980e203be68252246d5eb1b5418774fc
This commit is contained in:
parent
4a8970a134
commit
1b122869f7
@ -15,13 +15,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { isFunction, has, isObject, isEmpty } from 'lodash';
|
import { isFunction, has, isObject, isEmpty } from 'lodash';
|
||||||
import Notify from 'components/Notify';
|
import Notify from 'components/Notify';
|
||||||
import { Row, Col, Form, Button, Spin } from 'antd';
|
import { Row, Col, Form, Button, Spin, Progress } from 'antd';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||||
import { isAdminPage, firstUpperCase, unescapeHtml } from 'utils/index';
|
import { isAdminPage, firstUpperCase, unescapeHtml } from 'utils/index';
|
||||||
|
|
||||||
import { parse } from 'qs';
|
import { parse } from 'qs';
|
||||||
import FormItem from 'components/FormItem';
|
import FormItem from 'components/FormItem';
|
||||||
|
import { CancelToken } from 'axios';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
export default class BaseForm extends React.Component {
|
export default class BaseForm extends React.Component {
|
||||||
@ -36,6 +36,7 @@ export default class BaseForm extends React.Component {
|
|||||||
// eslint-disable-next-line react/no-unused-state
|
// eslint-disable-next-line react/no-unused-state
|
||||||
formData: {},
|
formData: {},
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
|
percent: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.values = {};
|
this.values = {};
|
||||||
@ -45,6 +46,12 @@ export default class BaseForm extends React.Component {
|
|||||||
this.tipRef = React.createRef();
|
this.tipRef = React.createRef();
|
||||||
this.codeError = false;
|
this.codeError = false;
|
||||||
this.currentFormValue = {};
|
this.currentFormValue = {};
|
||||||
|
this.cancel = null;
|
||||||
|
this.cancelToken = this.hasRequestCancelCallback
|
||||||
|
? new CancelToken((c) => {
|
||||||
|
this.cancel = c;
|
||||||
|
})
|
||||||
|
: null;
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +238,10 @@ export default class BaseForm extends React.Component {
|
|||||||
.map((it) => it.name);
|
.map((it) => it.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasRequestCancelCallback() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
updateContext = (allFields) => {
|
updateContext = (allFields) => {
|
||||||
const { updateContext } = this.props;
|
const { updateContext } = this.props;
|
||||||
updateContext && updateContext(allFields);
|
updateContext && updateContext(allFields);
|
||||||
@ -314,7 +325,12 @@ export default class BaseForm extends React.Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onCancel = () => {};
|
onCancel = () => {
|
||||||
|
if (this.isSubmitting && this.cancel) {
|
||||||
|
this.cancel();
|
||||||
|
Notify.success(t('Cancel upload successfully.'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
getChangedFieldsValue = (changedFields, name) => {
|
getChangedFieldsValue = (changedFields, name) => {
|
||||||
const value = changedFields[name];
|
const value = changedFields[name];
|
||||||
@ -379,7 +395,10 @@ export default class BaseForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onClickCancel = () => {
|
onClickCancel = () => {
|
||||||
this.routing.push(this.listUrl);
|
this.onCancel();
|
||||||
|
if (this.listUrl) {
|
||||||
|
this.routing.push(this.listUrl);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updateDefaultValue = () => {
|
updateDefaultValue = () => {
|
||||||
@ -396,6 +415,31 @@ export default class BaseForm extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onUploadProgress = (progressEvent) => {
|
||||||
|
const { loaded, total } = progressEvent;
|
||||||
|
const percent = Math.floor((loaded / total) * 100);
|
||||||
|
this.setState({
|
||||||
|
percent,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
getUploadRequestConf = () => {
|
||||||
|
return {
|
||||||
|
onUploadProgress: this.onUploadProgress,
|
||||||
|
canToken: this.cancelToken,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
checkContextValue() {
|
||||||
|
const { context } = this.props;
|
||||||
|
const names = this.nameForStateUpdate;
|
||||||
|
if (isEmpty(context)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const item = names.find((name) => has(context, name));
|
||||||
|
return !!item;
|
||||||
|
}
|
||||||
|
|
||||||
updateState() {
|
updateState() {
|
||||||
// save linkage data to state
|
// save linkage data to state
|
||||||
const { context } = this.props;
|
const { context } = this.props;
|
||||||
@ -418,16 +462,6 @@ export default class BaseForm extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkContextValue() {
|
|
||||||
const { context } = this.props;
|
|
||||||
const names = this.nameForStateUpdate;
|
|
||||||
if (isEmpty(context)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const item = names.find((name) => has(context, name));
|
|
||||||
return !!item;
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.store = {};
|
this.store = {};
|
||||||
}
|
}
|
||||||
@ -544,6 +578,21 @@ export default class BaseForm extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSubmittingTip() {
|
||||||
|
if (!this.hasRequestCancelCallback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { percent } = this.state;
|
||||||
|
return (
|
||||||
|
<div className={styles['submit-tip']}>
|
||||||
|
{t('Upload progress')}
|
||||||
|
<div className={styles['progress-wrapper']}>
|
||||||
|
<Progress percent={percent} size="small" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const wrapperPadding =
|
const wrapperPadding =
|
||||||
this.listUrl || this.isStep || (this.isModal && this.tips)
|
this.listUrl || this.isStep || (this.isModal && this.tips)
|
||||||
@ -564,7 +613,7 @@ export default class BaseForm extends React.Component {
|
|||||||
<div
|
<div
|
||||||
className={classnames(styles.wrapper, wrapperPadding, this.className)}
|
className={classnames(styles.wrapper, wrapperPadding, this.className)}
|
||||||
>
|
>
|
||||||
<Spin spinning={this.isSubmitting}>
|
<Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}>
|
||||||
{tips}
|
{tips}
|
||||||
<div className={classnames(styles.form, 'sl-form')} style={formStyle}>
|
<div className={classnames(styles.form, 'sl-form')} style={formStyle}>
|
||||||
{this.renderForms()}
|
{this.renderForms()}
|
||||||
|
@ -109,4 +109,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-tip {
|
||||||
|
font-size: 16px;
|
||||||
|
// margin-top: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.progress-wrapper {
|
||||||
|
width: 170px;
|
||||||
}
|
}
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Upload, Button, message } from 'antd';
|
import { Upload, Button } from 'antd';
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
import { isArray } from 'lodash';
|
import { isArray } from 'lodash';
|
||||||
|
|
||||||
@ -36,19 +36,7 @@ export default class index extends Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = (info) => {
|
onChange = (file) => {
|
||||||
if (info.file.status !== 'uploading') {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(info.file, info.fileList);
|
|
||||||
}
|
|
||||||
if (info.file.status === 'done') {
|
|
||||||
message.success(`${info.file.name} file uploaded successfully`);
|
|
||||||
} else if (info.file.status === 'error') {
|
|
||||||
message.error(`${info.file.name} file upload failed.`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeUpload = (file) => {
|
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
file,
|
file,
|
||||||
@ -60,6 +48,24 @@ export default class index extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChange = (info) => {
|
||||||
|
const { file, fileList = [] } = info;
|
||||||
|
const { status } = file || {};
|
||||||
|
if (status === 'removed' && fileList.length === 0) {
|
||||||
|
this.onChange(null);
|
||||||
|
}
|
||||||
|
if (!status) {
|
||||||
|
this.onChange(file);
|
||||||
|
}
|
||||||
|
if (info.file.status !== 'uploading') {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(file, fileList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeUpload = () => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +85,7 @@ export default class index extends Component {
|
|||||||
headers: {
|
headers: {
|
||||||
authorization: 'authorization-text',
|
authorization: 'authorization-text',
|
||||||
},
|
},
|
||||||
onChange: this.onChange,
|
onChange: this.handleChange,
|
||||||
progress: this.progress,
|
progress: this.progress,
|
||||||
beforeUpload: this.beforeUpload,
|
beforeUpload: this.beforeUpload,
|
||||||
fileList,
|
fileList,
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { inject, observer } from 'mobx-react';
|
import { inject, observer } from 'mobx-react';
|
||||||
import { Modal, Button, Tooltip } from 'antd';
|
import { Modal, Button, Tooltip } from 'antd';
|
||||||
import { isArray, isFunction } from 'lodash';
|
import { isArray, isFunction, isBoolean } from 'lodash';
|
||||||
import Confirm from 'components/Confirm';
|
import Confirm from 'components/Confirm';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Notify from 'components/Notify';
|
import Notify from 'components/Notify';
|
||||||
@ -381,7 +381,7 @@ class ActionButton extends Component {
|
|||||||
return this.formRef.current.wrappedInstance.onClickSubmit(
|
return this.formRef.current.wrappedInstance.onClickSubmit(
|
||||||
(success, fail) => {
|
(success, fail) => {
|
||||||
this.handleSubmitLoading();
|
this.handleSubmitLoading();
|
||||||
this.onClickModalActionCancel();
|
this.onClickModalActionCancel(true);
|
||||||
this.onCallback(success, fail);
|
this.onCallback(success, fail);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
@ -391,7 +391,10 @@ class ActionButton extends Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onClickModalActionCancel = () => {
|
onClickModalActionCancel = (finish) => {
|
||||||
|
if (!isBoolean(finish)) {
|
||||||
|
this.formRef.current.wrappedInstance.onClickCancel();
|
||||||
|
}
|
||||||
const { onCancelAction } = this.props;
|
const { onCancelAction } = this.props;
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
|
@ -161,7 +161,7 @@ export default class BaseTable extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get itemActions() {
|
get itemActions() {
|
||||||
const { itemActions } = this.props;
|
const { itemActions = {} } = this.props;
|
||||||
return itemActions;
|
return itemActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +214,7 @@
|
|||||||
"Cancel Download": "Cancel Download",
|
"Cancel Download": "Cancel Download",
|
||||||
"Cancel Select": "Cancel Select",
|
"Cancel Select": "Cancel Select",
|
||||||
"Cancel Transfer": "Cancel Transfer",
|
"Cancel Transfer": "Cancel Transfer",
|
||||||
|
"Cancel upload successfully.": "Cancel upload successfully.",
|
||||||
"Capacity (GB)": "Capacity (GB)",
|
"Capacity (GB)": "Capacity (GB)",
|
||||||
"Category": "Category",
|
"Category": "Category",
|
||||||
"CentOS": "CentOS",
|
"CentOS": "CentOS",
|
||||||
@ -1655,6 +1656,7 @@
|
|||||||
"Updated At": "Updated At",
|
"Updated At": "Updated At",
|
||||||
"Updating": "Updating",
|
"Updating": "Updating",
|
||||||
"Updating Password": "Updating Password",
|
"Updating Password": "Updating Password",
|
||||||
|
"Upload progress": "Upload progress",
|
||||||
"Uploading": "Uploading",
|
"Uploading": "Uploading",
|
||||||
"Usage Type": "Usage Type",
|
"Usage Type": "Usage Type",
|
||||||
"Usb Controller": "Usb Controller",
|
"Usb Controller": "Usb Controller",
|
||||||
|
@ -214,6 +214,7 @@
|
|||||||
"Cancel Download": "取消下载",
|
"Cancel Download": "取消下载",
|
||||||
"Cancel Select": "取消选择",
|
"Cancel Select": "取消选择",
|
||||||
"Cancel Transfer": "取消云硬盘转让",
|
"Cancel Transfer": "取消云硬盘转让",
|
||||||
|
"Cancel upload successfully.": "取消上传成功。",
|
||||||
"Capacity (GB)": "容量(GB)",
|
"Capacity (GB)": "容量(GB)",
|
||||||
"Category": "类别",
|
"Category": "类别",
|
||||||
"CentOS": "",
|
"CentOS": "",
|
||||||
@ -1655,6 +1656,7 @@
|
|||||||
"Updated At": "更新于",
|
"Updated At": "更新于",
|
||||||
"Updating": "更新中",
|
"Updating": "更新中",
|
||||||
"Updating Password": "更新密码中",
|
"Updating Password": "更新密码中",
|
||||||
|
"Upload progress": "上传进度",
|
||||||
"Uploading": "上传中",
|
"Uploading": "上传中",
|
||||||
"Usage Type": "使用类型",
|
"Usage Type": "使用类型",
|
||||||
"Usb Controller": "USB控制器",
|
"Usb Controller": "USB控制器",
|
||||||
|
@ -61,6 +61,10 @@ class CreateForm extends FormAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasRequestCancelCallback() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static policy = ['add_image', 'upload_image'];
|
static policy = ['add_image', 'upload_image'];
|
||||||
|
|
||||||
static allowed() {
|
static allowed() {
|
||||||
@ -294,7 +298,8 @@ class CreateForm extends FormAction {
|
|||||||
body.owner = owner.selectedRowKeys[0];
|
body.owner = owner.selectedRowKeys[0];
|
||||||
}
|
}
|
||||||
const mems = visibility === 'shared' ? members.selectedRowKeys : [];
|
const mems = visibility === 'shared' ? members.selectedRowKeys : [];
|
||||||
return this.store.create(body, file, mems);
|
const config = this.getUploadRequestConf();
|
||||||
|
return this.store.create(body, file, mems, config);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user