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:
zhangjingwei 2021-07-30 09:34:00 +08:00 committed by Jingwei.Zhang
parent 4a8970a134
commit 1b122869f7
8 changed files with 111 additions and 35 deletions

View File

@ -15,13 +15,13 @@
import React from 'react';
import { isFunction, has, isObject, isEmpty } from 'lodash';
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 { InfoCircleOutlined } from '@ant-design/icons';
import { isAdminPage, firstUpperCase, unescapeHtml } from 'utils/index';
import { parse } from 'qs';
import FormItem from 'components/FormItem';
import { CancelToken } from 'axios';
import styles from './index.less';
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
formData: {},
isSubmitting: false,
percent: '',
};
this.values = {};
@ -45,6 +46,12 @@ export default class BaseForm extends React.Component {
this.tipRef = React.createRef();
this.codeError = false;
this.currentFormValue = {};
this.cancel = null;
this.cancelToken = this.hasRequestCancelCallback
? new CancelToken((c) => {
this.cancel = c;
})
: null;
this.init();
}
@ -231,6 +238,10 @@ export default class BaseForm extends React.Component {
.map((it) => it.name);
}
get hasRequestCancelCallback() {
return false;
}
updateContext = (allFields) => {
const { updateContext } = this.props;
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) => {
const value = changedFields[name];
@ -379,7 +395,10 @@ export default class BaseForm extends React.Component {
};
onClickCancel = () => {
this.onCancel();
if (this.listUrl) {
this.routing.push(this.listUrl);
}
};
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() {
// save linkage data to state
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() {
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() {
const wrapperPadding =
this.listUrl || this.isStep || (this.isModal && this.tips)
@ -564,7 +613,7 @@ export default class BaseForm extends React.Component {
<div
className={classnames(styles.wrapper, wrapperPadding, this.className)}
>
<Spin spinning={this.isSubmitting}>
<Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}>
{tips}
<div className={classnames(styles.form, 'sl-form')} style={formStyle}>
{this.renderForms()}

View File

@ -110,3 +110,12 @@
align-items: center;
justify-content: left;
}
.submit-tip {
font-size: 16px;
// margin-top: 16px;
display: inline-block;
}
.progress-wrapper {
width: 170px;
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import React, { Component } from 'react';
import { Upload, Button, message } from 'antd';
import { Upload, Button } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { isArray } from 'lodash';
@ -36,19 +36,7 @@ export default class index extends Component {
};
}
onChange = (info) => {
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) => {
onChange = (file) => {
this.setState(
{
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;
};
@ -79,7 +85,7 @@ export default class index extends Component {
headers: {
authorization: 'authorization-text',
},
onChange: this.onChange,
onChange: this.handleChange,
progress: this.progress,
beforeUpload: this.beforeUpload,
fileList,

View File

@ -15,7 +15,7 @@
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import { Modal, Button, Tooltip } from 'antd';
import { isArray, isFunction } from 'lodash';
import { isArray, isFunction, isBoolean } from 'lodash';
import Confirm from 'components/Confirm';
import PropTypes from 'prop-types';
import Notify from 'components/Notify';
@ -381,7 +381,7 @@ class ActionButton extends Component {
return this.formRef.current.wrappedInstance.onClickSubmit(
(success, fail) => {
this.handleSubmitLoading();
this.onClickModalActionCancel();
this.onClickModalActionCancel(true);
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;
this.setState(
{

View File

@ -161,7 +161,7 @@ export default class BaseTable extends React.Component {
}
get itemActions() {
const { itemActions } = this.props;
const { itemActions = {} } = this.props;
return itemActions;
}

View File

@ -214,6 +214,7 @@
"Cancel Download": "Cancel Download",
"Cancel Select": "Cancel Select",
"Cancel Transfer": "Cancel Transfer",
"Cancel upload successfully.": "Cancel upload successfully.",
"Capacity (GB)": "Capacity (GB)",
"Category": "Category",
"CentOS": "CentOS",
@ -1655,6 +1656,7 @@
"Updated At": "Updated At",
"Updating": "Updating",
"Updating Password": "Updating Password",
"Upload progress": "Upload progress",
"Uploading": "Uploading",
"Usage Type": "Usage Type",
"Usb Controller": "Usb Controller",

View File

@ -214,6 +214,7 @@
"Cancel Download": "取消下载",
"Cancel Select": "取消选择",
"Cancel Transfer": "取消云硬盘转让",
"Cancel upload successfully.": "取消上传成功。",
"Capacity (GB)": "容量(GB)",
"Category": "类别",
"CentOS": "",
@ -1655,6 +1656,7 @@
"Updated At": "更新于",
"Updating": "更新中",
"Updating Password": "更新密码中",
"Upload progress": "上传进度",
"Uploading": "上传中",
"Usage Type": "使用类型",
"Usb Controller": "USB控制器",

View File

@ -61,6 +61,10 @@ class CreateForm extends FormAction {
};
}
get hasRequestCancelCallback() {
return true;
}
static policy = ['add_image', 'upload_image'];
static allowed() {
@ -294,7 +298,8 @@ class CreateForm extends FormAction {
body.owner = owner.selectedRowKeys[0];
}
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);
};
}