cancel file upload button

This commit is contained in:
Martina 2020-10-01 21:24:10 -07:00
parent f1c929e200
commit 9082a97baf
7 changed files with 144 additions and 31 deletions

View File

@ -1,5 +1,7 @@
import { dispatchCustomEvent } from "~/common/custom-events";
import * as Actions from "~/common/actions";
import * as Store from "~/common/store";
import { dispatchCustomEvent } from "~/common/custom-events";
const STAGING_DEAL_BUCKET = "stage-deal";
@ -18,16 +20,26 @@ export const upload = async ({ file, context, bucketName }) => {
blob: file,
toType: "image/png",
quality: 1,
});
}); //TODO(martina): figure out how to cancel an await if upload has been cancelled
formData.append("data", converted);
} else {
formData.append("data", file);
}
const _privateUploadMethod = (path) =>
if (Store.checkCancelled(`${file.lastModified}-${file.name}`)) {
return;
}
const _privateUploadMethod = (path, file) =>
new Promise((resolve, reject) => {
const XHR = new XMLHttpRequest();
window.addEventListener(
`cancel-${file.lastModified}-${file.name}`,
() => {
XHR.abort();
}
);
XHR.open("post", path, true);
XHR.onerror = (event) => {
console.log(event);
@ -58,6 +70,11 @@ export const upload = async ({ file, context, bucketName }) => {
false
);
window.removeEventListener(
`cancel-${file.lastModified}-${file.name}`,
() => XHR.abort()
);
XHR.onloadend = (event) => {
console.log("FILE UPLOAD END", event);
try {
@ -74,9 +91,9 @@ export const upload = async ({ file, context, bucketName }) => {
let json;
// TODO(jim): Make this smarter.
if (bucketName && bucketName === STAGING_DEAL_BUCKET) {
json = await _privateUploadMethod(`/api/data/deal/${file.name}`);
json = await _privateUploadMethod(`/api/data/deal/${file.name}`, file);
} else {
json = await _privateUploadMethod(`/api/data/${file.name}`);
json = await _privateUploadMethod(`/api/data/${file.name}`, file);
}
if (!json || json.error || !json.data) {

9
common/store.js Normal file
View File

@ -0,0 +1,9 @@
const cancelledUploads = {};
export const checkCancelled = (val) => {
return cancelledUploads[val];
};
export const setCancelled = (val) => {
cancelledUploads[val] = true;
};

View File

@ -158,7 +158,9 @@ export class Alert extends React.Component {
</div>
);
}
let total = Object.keys(this.props.fileLoading).length;
let total = Object.values(this.props.fileLoading).filter((upload) => {
return !upload.cancelled;
}).length;
let uploaded =
Object.values(this.props.fileLoading).filter((upload) => {
return upload.loaded === upload.total;

View File

@ -8,6 +8,7 @@ import * as Validations from "~/common/validations";
import * as FileUtilities from "~/common/file-utilities";
import * as System from "~/components/system";
import * as Window from "~/common/window";
import * as Store from "~/common/store";
// NOTE(jim):
// Scenes each have an ID and can be navigated to with _handleAction
@ -271,12 +272,17 @@ export default class ApplicationPage extends React.Component {
// to allow parallel downloads again.
const resolvedFiles = [];
for (let i = 0; i < files.length; i++) {
if (Store.checkCancelled(`${files[i].lastModified}-${files[i].name}`)) {
continue;
}
const response = await FileUtilities.upload({
file: files[i],
context: this,
});
resolvedFiles.push(response);
if (response) {
resolvedFiles.push(response);
}
}
let responses = await Promise.allSettled(resolvedFiles);
@ -373,6 +379,12 @@ export default class ApplicationPage extends React.Component {
});
};
_handleRegisterFileCancelled = ({ key }) => {
let fileLoading = this.state.fileLoading;
fileLoading[key].cancelled = true;
this.setState({ fileLoading });
};
_handleRegisterLoadingFinished = ({ keys }) => {
let fileLoading = this.state.fileLoading;
for (let key of keys) {
@ -611,6 +623,10 @@ export default class ApplicationPage extends React.Component {
});
}
if (options.type === "REGISTER_FILE_CANCELLED") {
return this._handleRegisterFileCancelled({ key: options.value });
}
return alert(JSON.stringify(options));
};

View File

@ -135,14 +135,11 @@ export default class GlobalViewerCIDSidebar extends React.Component {
const elements = [];
if (this.props.onClose) {
console.log("dismiss added");
elements.push(
<div key="s-1" css={STYLES_DISMISS_BOX} onClick={this.props.onClose}>
<SVG.Dismiss height="24px" />
</div>
);
} else {
console.log("dismiss not added");
}
if (this.props.renderDataControls) {

View File

@ -3,6 +3,7 @@ import * as Constants from "~/common/constants";
import * as Strings from "~/common/strings";
import * as System from "~/components/system";
import * as Validations from "~/common/validations";
import * as Store from "~/common/store";
import * as SVG from "~/common/svg";
import { css } from "@emotion/react";
@ -40,6 +41,19 @@ const STYLES_FILE_NAME = css`
font-family: ${Constants.font.medium};
`;
const STYLES_LEFT = css`
width: 100%;
min-width: 10%;
display: flex;
align-items: center;
`;
const STYLES_RIGHT = css`
flex-shrink: 0;
display: flex;
align-items: center;
`;
const STYLES_FILE_STATUS = css`
flex-shrink: 0;
margin-right: 16px;
@ -80,6 +94,14 @@ export default class SidebarAddFileToBucket extends React.Component {
this.props.onCancel();
};
_handleCancel = (e, key) => {
e.preventDefault();
e.stopPropagation();
dispatchCustomEvent({ name: `cancel-${key}` }); //NOTE(martina): so that will cancel if is in the middle of uploading
Store.setCancelled(key); //NOTE(martina): so that will cancel if hasn't started uploading yet
this.props.onAction({ type: "REGISTER_FILE_CANCELLED", value: key }); //NOTE(martina): so that fileLoading registers it
};
render() {
let loaded = 0;
let total = 0;
@ -157,30 +179,81 @@ export default class SidebarAddFileToBucket extends React.Component {
) : null}
<div style={{ marginTop: 24 }}>
{this.props.fileLoading
? Object.values(this.props.fileLoading).map((file) => (
<div css={STYLES_FILE_LINE} key={file.name}>
<div css={STYLES_FILE_STATUS}>
{file.failed ? (
<SVG.Alert
height="24px"
style={{ color: Constants.system.red }}
? Object.entries(this.props.fileLoading).map((entry) => {
let file = entry[1];
return (
<div css={STYLES_FILE_LINE} key={file.name}>
<span css={STYLES_LEFT}>
<div css={STYLES_FILE_STATUS}>
{file.failed ? (
<SVG.Alert
height="24px"
style={{
color: Constants.system.red,
pointerEvents: "none",
}}
/>
) : file.cancelled ? (
<SVG.Dismiss
height="24px"
style={{
color: Constants.system.gray,
pointerEvents: "none",
}}
/>
) : file.loaded === file.total ? (
<SVG.CheckBox height="24px" />
) : (
<System.LoaderSpinner
style={{
width: "20px",
height: "20px",
margin: "2px",
}}
/>
)}
</div>
<div
css={STYLES_FILE_NAME}
style={
file.failed
? { color: Constants.system.red }
: file.cancelled
? { color: Constants.system.gray }
: null
}
>
{file.name}
</div>
</span>
{file.loaded === file.total ||
file.failed ||
file.cancelled ? (
<div
css={STYLES_RIGHT}
style={{ height: 24, width: 24 }}
/>
) : file.loaded === file.total ? (
<SVG.CheckBox height="24px" />
) : (
<System.LoaderSpinner
style={{ width: "20px", height: "20px", margin: "2px" }}
/>
<span
css={STYLES_RIGHT}
style={{
cursor: "pointer",
}}
onClick={(e) => this._handleCancel(e, entry[0])}
>
<SVG.Dismiss
height="24px"
className="boundary-ignore"
style={{
color: Constants.system.gray,
pointerEvents: "none",
}}
/>
</span>
)}
</div>
<div
css={STYLES_FILE_NAME}
style={file.failed ? { color: Constants.system.red } : null}
>
{file.name}
</div>
</div>
))
);
})
: null}
</div>
</React.Fragment>

View File

@ -152,7 +152,6 @@ export default class SceneProfile extends React.Component {
};
render() {
console.log(this.props.data);
let buttons = (
<div css={STYLES_BUTTONS}>
{this.state.followStatus ? (