mirror of
https://github.com/filecoin-project/slate.git
synced 2024-09-11 22:07:08 +03:00
cancel file upload button
This commit is contained in:
parent
f1c929e200
commit
9082a97baf
@ -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
9
common/store.js
Normal file
@ -0,0 +1,9 @@
|
||||
const cancelledUploads = {};
|
||||
|
||||
export const checkCancelled = (val) => {
|
||||
return cancelledUploads[val];
|
||||
};
|
||||
|
||||
export const setCancelled = (val) => {
|
||||
cancelledUploads[val] = true;
|
||||
};
|
@ -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;
|
||||
|
@ -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));
|
||||
};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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 ? (
|
||||
|
Loading…
Reference in New Issue
Block a user