uploads: captures error states more accurately

This commit is contained in:
jimmylee 2020-08-15 18:32:38 -07:00
parent 4007910627
commit 91f52e7ada
5 changed files with 58 additions and 29 deletions

View File

@ -5,7 +5,6 @@ import * as State from "~/common/state";
import * as Credentials from "~/common/credentials";
import * as Validations from "~/common/validations";
import * as System from "~/components/system";
import * as Window from "~/common/window";
// NOTE(jim):
// Scenes each have an ID and can be navigated to with _handleAction
@ -133,7 +132,13 @@ export default class ApplicationPage extends React.Component {
};
XHR.onloadend = (event) => {
console.log("FILE UPLOAD END", event);
resolve(JSON.parse(event.target.response));
try {
return resolve(JSON.parse(event.target.response));
} catch (e) {
return resolve({
error: "SERVER_UPLOAD_ERROR",
});
}
};
XHR.send(formData);
});
@ -141,19 +146,20 @@ export default class ApplicationPage extends React.Component {
const json = await upload(`/api/data/${file.name}`);
console.log(json);
if (!json) {
return { error: "NO_RESPONSE" };
if (!json || json.error || !json.data) {
this.setState({
fileLoading: {
...this.state.fileLoading,
[`${file.lastModified}-${file.name}`]: {
name: file.name,
failed: true,
},
},
});
return !json ? { error: "NO_RESPONSE" } : json;
}
if (json.error) {
return json;
}
if (!json.data) {
return json;
}
if (json && slate) {
if (slate) {
const addResponse = await fetch(`/api/slates/add-url`, {
method: "POST",
headers: {

View File

@ -69,6 +69,7 @@ const STYLES_TITLE = css`
font-size: 14px;
display: block;
margin-bottom: 4px;
overflow-wrap: break-word;
`;
export const DataMeterBar = (props) => {
@ -76,17 +77,21 @@ export const DataMeterBar = (props) => {
return (
<React.Fragment>
<div css={STYLES_STATS_ROW}>
<div css={STYLES_LEFT}>{Strings.bytesToSize(props.bytes)}</div>
<div css={STYLES_RIGHT}>{Strings.bytesToSize(props.maximumBytes)}</div>
</div>
{!props.inaccurate ? (
<div css={STYLES_STATS_ROW}>
<div css={STYLES_LEFT}>{Strings.bytesToSize(props.bytes)}</div>
<div css={STYLES_RIGHT}>{Strings.bytesToSize(props.maximumBytes)}</div>
</div>
) : null}
<div css={STYLES_ROW}>
<div css={STYLES_LEFT}>Used</div>
<div css={STYLES_RIGHT}>Total</div>
<div css={STYLES_LEFT} style={{ color: props.failed ? Constants.system.red : null }}>
{props.leftLabel}
</div>
<div css={STYLES_RIGHT}>{props.rightLabel}</div>
</div>
<div css={STYLES_DATA} style={{ marginTop: 4 }}>
<div css={STYLES_DATA} style={{ marginTop: 4, backgroundColor: props.failed ? Constants.system.red : null }}>
<div css={STYLES_DATA_METER} style={{ width: `${percentage * 100}%` }} />
</div>
</React.Fragment>
@ -104,7 +109,12 @@ export default (props) => {
<br />
</System.P>
<DataMeterBar bytes={props.stats.bytes} maximumBytes={props.stats.maximumBytes} />
<DataMeterBar
leftLabel="used"
rightLabel="total"
bytes={props.stats.bytes}
maximumBytes={props.stats.maximumBytes}
/>
</div>
);
};

View File

@ -135,13 +135,21 @@ export default class SidebarAddFileToBucket extends React.Component {
</System.ButtonSecondary>
) : null}
<br />
{this.props.fileLoading
? Object.keys(this.props.fileLoading).map((timestamp) => {
const p = this.props.fileLoading[timestamp];
return (
<React.Fragment key={timestamp}>
<strong css={STYLES_STRONG}>{p.name}</strong>
<DataMeterBar bytes={p.loaded} maximumBytes={p.total} />
<DataMeterBar
failed={p.failed}
inaccurate
leftLabel={p.failed ? "failed" : "progress"}
bytes={p.loaded}
maximumBytes={p.total}
/>
</React.Fragment>
);
})

View File

@ -19,13 +19,13 @@ export const createBucket = ({ id, name }) => {
// Every root level user gets a bucket.
export const init = ({ bucketName, readableName }) => [createBucket({ id: bucketName, name: readableName })];
export const createLocalDataIncomplete = ({ type, size, name }) => {
export const createLocalDataIncomplete = ({ type, size, name }, id = null) => {
return {
id: `data-${uuid()}`,
id: !id ? `data-${uuid()}` : id,
name: name,
decorator: "FILE",
icon: type,
size: size,
name: `data-${uuid()}`,
file: name,
type: type,
date: new Date(),

View File

@ -6,11 +6,13 @@ import FORM from "formidable";
import { PassThrough } from "stream";
export const formMultipart = (req, res, { user }) =>
new Promise((resolve, reject) => {
new Promise(async (resolve, reject) => {
const f = new FORM.IncomingForm();
const p = new PassThrough();
const p = new PassThrough({ highWaterMark: 1024 * 1024 * 3 });
const file = {};
const { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
f.keepExtensions = true;
f.onPart = (part) => {
@ -31,9 +33,11 @@ export const formMultipart = (req, res, { user }) =>
});
};
f.parse(req, async (e) => {
const { buckets, bucketKey } = await Utilities.getBucketAPIFromUserToken(user.data.tokens.api);
f.on("progress", (bytesReceived, bytesExpected) => {
// console.log({ bytesReceived, bytesExpected });
});
f.parse(req, async (e) => {
if (e) {
return reject({
decorator: "SERVER_UPLOAD_PARSE_FAILURE",
@ -50,6 +54,7 @@ export const formMultipart = (req, res, { user }) =>
});
}
// NOTE(jim): Creates a Slate compatable Data object.
const data = LibraryManager.createLocalDataIncomplete(file);
let push;