Add quota error handling to RCS sidebar

closes CORE-1239

Test Plan:
  - Set a course's usage quota to 10mb (or anything low)
  - Attempt to upload a file bigger than that through
    the RCS sidebar
  - Notice an error shows up
  - Upload a file less than the quota
  - Notice the error goes away

Change-Id: I2b8cab2fb76d3ec3520fff5eee337892d34d56d1
Reviewed-on: https://gerrit.instructure.com/150085
Tested-by: Jenkins
Reviewed-by: Ryan Shaw <ryan@instructure.com>
QA-Review: Rohan Cheeniyil <rcheeniyil@instructure.com>
Product-Review: Clay Diffrient <cdiffrient@instructure.com>
This commit is contained in:
Clay Diffrient 2018-05-11 17:06:58 -06:00
parent ebbfde74ef
commit 0a9226051e
5 changed files with 104 additions and 5 deletions

View File

@ -28,6 +28,7 @@ export const FAIL_FILE_UPLOAD = "FAIL_FILE_UPLOAD";
export const COMPLETE_FILE_UPLOAD = "COMPLETE_FILE_UPLOAD";
export const TOGGLE_UPLOAD_FORM = "TOGGLE_UPLOAD_FORM";
export const PROCESSED_FOLDER_BATCH = "PROCESSED_FOLDER_BATCH";
export const QUOTA_EXCEEDED_UPLOAD = "QUOTA_EXCEEDED_UPLOAD";
export function receiveFolder({ id, name, parentId }) {
return { type: RECEIVE_FOLDER, id, name, parentId };
@ -45,6 +46,10 @@ export function failUpload(error) {
return { type: FAIL_FILE_UPLOAD, error };
}
export function quotaExceeded(error) {
return { type: QUOTA_EXCEEDED_UPLOAD, error };
}
export function completeUpload(results) {
return { type: COMPLETE_FILE_UPLOAD, results };
}
@ -174,6 +179,19 @@ export function setAltText(altText, results) {
return results;
}
export function handleFailures(error, dispatch) {
return error.response
.json()
.then(resp => {
if (resp.message === "file size exceeds quota") {
dispatch(quotaExceeded(error));
} else {
dispatch(failUpload(error));
}
})
.catch(error => dispatch(failUpload(error)))
}
export function uploadPreflight(tabContext, fileMetaProps) {
return (dispatch, getState) => {
const { source, jwt, host, contextId, contextType } = getState();
@ -202,6 +220,6 @@ export function uploadPreflight(tabContext, fileMetaProps) {
.then(results => {
dispatch(allUploadCompleteActions(results, fileMetaProps));
})
.catch(error => dispatch(failUpload(error)));
.catch(err => handleFailures(err, dispatch));
};
}

View File

@ -24,6 +24,7 @@ import formatMessage from "../../format-message";
import ScreenReaderContent from "@instructure/ui-core/lib/components/ScreenReaderContent";
import Select from "@instructure/ui-core/lib/components/Select";
import Button from "@instructure/ui-core/lib/components/Button";
import Alert from "@instructure/ui-alerts/lib/components/Alert";
import IconAddSolid from "instructure-icons/lib/Solid/IconAddSolid";
import IconMinimizeSolid from "instructure-icons/lib/Solid/IconMinimizeSolid";
import Loading from "../../common/components/Loading";
@ -234,6 +235,13 @@ class UploadForm extends Component {
renderForm() {
if (this.props.upload.formExpanded) {
let screenreaderMessage = formatMessage("Select a file");
let errorMessage =
this.props.upload.error &&
this.props.upload.error.type === "QUOTA_EXCEEDED_UPLOAD"
? formatMessage(
"This upload exceeds the file storage quota. Please speak to your system administrator."
)
: null;
return (
<form
onSubmit={this.handleUpload.bind(this)}
@ -245,6 +253,7 @@ class UploadForm extends Component {
<label htmlFor="upload-form-file-input">
<ScreenReaderContent>{screenreaderMessage}</ScreenReaderContent>
</label>
{errorMessage && <Alert variant="error">{errorMessage}</Alert>}
<input
className={css(styles.uploadedData)}
type="file"
@ -308,7 +317,10 @@ UploadForm.propTypes = {
uploading: PropTypes.bool.isRequired,
formExpanded: PropTypes.bool.isRequired,
rootFolderId: PropTypes.number,
folderTree: PropTypes.object.isRequired
folderTree: PropTypes.object.isRequired,
error: PropTypes.shape({
type: PropTypes.string
})
}).isRequired,
toggleUploadForm: PropTypes.func.isRequired,
fetchFolders: PropTypes.func.isRequired,

View File

@ -23,7 +23,8 @@ import {
COMPLETE_FILE_UPLOAD,
RECEIVE_FOLDER,
FAIL_FOLDERS_LOAD,
PROCESSED_FOLDER_BATCH
PROCESSED_FOLDER_BATCH,
QUOTA_EXCEEDED_UPLOAD
} from "../actions/upload";
import { combineReducers } from "redux";
@ -33,12 +34,27 @@ function uploading(state = false, action) {
return true;
case FAIL_FILE_UPLOAD:
case COMPLETE_FILE_UPLOAD:
case QUOTA_EXCEEDED_UPLOAD:
return false;
default:
return state;
}
}
function error(state = {}, action) {
switch (action.type) {
case COMPLETE_FILE_UPLOAD:
return {};
case QUOTA_EXCEEDED_UPLOAD:
return {
...state,
type: action.type
};
default:
return state;
}
}
function formExpanded(state = false, action) {
switch (action.type) {
case COMPLETE_FILE_UPLOAD:
@ -116,5 +132,6 @@ export default combineReducers({
formExpanded,
folders,
rootFolderId,
folderTree
folderTree,
error
});

View File

@ -499,4 +499,36 @@ describe("Upload data actions", () => {
});
});
});
describe('handleFailures', () => {
it('calls quota exceeded when the file size exceeds the quota', () => {
const fakeDispatch = sinon.spy();
const error = {
response: new Response('{ "message": "file size exceeds quota" }', { status: 400})
}
return actions.handleFailures(error, fakeDispatch).then(() => {
sinon.assert.calledWith(fakeDispatch,
sinon.match({
type: 'QUOTA_EXCEEDED_UPLOAD',
error
})
);
})
});
it('calls failUpload for other errors', () => {
const fakeDispatch = sinon.spy();
const error = {
response: new Response('{ "message": "we don\'t like you " }', { status: 400})
}
return actions.handleFailures(error, fakeDispatch).then(() => {
sinon.assert.calledWith(fakeDispatch,
sinon.match({
type: 'FAIL_FILE_UPLOAD',
error
})
);
})
})
})
});

View File

@ -30,7 +30,8 @@ describe("Upload reducer", () => {
formExpanded: false,
folders: {},
rootFolderId: null,
folderTree: {}
folderTree: {},
error: {}
};
});
@ -67,6 +68,11 @@ describe("Upload reducer", () => {
state.formExpanded = true;
assert.equal(false, upload(state, action).formExpanded);
});
it('resets the error state', () => {
state.error = { type: 'SOME_ERROR'}
assert.deepEqual({}, upload(state, action).error);
})
});
describe("FAIL_FILE_UPLOAD", () => {
@ -83,6 +89,20 @@ describe("Upload reducer", () => {
});
});
describe('QUOTA_EXCEEDED_UPLOAD', () => {
beforeEach(() => {
action = { type: actions.QUOTA_EXCEEDED_UPLOAD };
});
it('sets the error state type to QUOTA_EXCEEDED_UPLOAD', () => {
assert.equal(upload(state, action).error.type, 'QUOTA_EXCEEDED_UPLOAD');
});
it('sets the uploading state the false', () => {
assert.equal(false, upload(state, action).uploading);
})
});
describe("RECEIVE_FOLDER", () => {
beforeEach(() => {
action = {