Skip to content

Commit

Permalink
ENH Gracefully handle AJAX failures
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Jan 10, 2024
1 parent 39112dc commit 9d3a6f0
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 10 deletions.
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions client/lang/en.js
Expand Up @@ -14,6 +14,13 @@ if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
"LinkField.ADD_LINK": "Add Link",
"LinkField.ARCHIVE": "Archive",
"LinkField.DELETE": "Delete",
"LinkField.LINK_DRAFT_TITLE": "Link has draft changes",
"LinkField.LINK_DRAFT_LABEL": "Draft",
"LinkField.LINK_MODIFIED_TITLE": "Link has unpublished changes",
"LinkField.LINK_MODIFIED_LABEL": "Modified",
"LinkField.CANNOT_CREATE_LINK": "Cannot create link",
"LinkField.FAILED_TO_LOAD_LINKS": "Failed to load links",
"LinkField.FAILED_TO_SAVE_LINK": "Failed to save link",
"LinkField.SAVE_RECORD_FIRST": "Cannot add links until the record has been saved"
});
}
2 changes: 2 additions & 0 deletions client/lang/src/en.json
Expand Up @@ -12,5 +12,7 @@
"LinkField.LINK_MODIFIED_TITLE": "Link has unpublished changes",
"LinkField.LINK_MODIFIED_LABEL": "Modified",
"LinkField.CANNOT_CREATE_LINK": "Cannot create link",
"LinkField.FAILED_TO_LOAD_LINKS": "Failed to load links",
"LinkField.FAILED_TO_SAVE_LINK": "Failed to save link",
"LinkField.SAVE_RECORD_FIRST": "Cannot add links until the record has been saved"
}
12 changes: 5 additions & 7 deletions client/src/components/LinkField/LinkField.js
Expand Up @@ -70,6 +70,9 @@ const LinkField = ({
.then(response => response.json())
.then(responseJson => {
setData(responseJson);
})
.catch(() => {
actions.toasts.error(i18n._t('LinkField.FAILED_TO_LOAD_LINKS', 'Failed to load links'))
});
}
}, [editingID, value && value.length]);
Expand Down Expand Up @@ -99,12 +102,7 @@ const LinkField = ({
onChange(isMulti ? ids : ids[0]);

// success toast
actions.toasts.success(
i18n._t(
'LinkField.SAVE_SUCCESS',
'Saved link',
)
);
actions.toasts.success(i18n._t('LinkField.SAVE_SUCCESS', 'Saved link'));
}

/**
Expand Down Expand Up @@ -174,7 +172,7 @@ const LinkField = ({
const renderModal = !saveRecordFirst && Boolean(editingID);
const saveRecordFirstText = i18n._t('LinkField.SAVE_RECORD_FIRST', 'Cannot add links until the record has been saved');

return <LinkFieldContext.Provider value={{ ownerID, ownerClass, ownerRelation }}>
return <LinkFieldContext.Provider value={{ ownerID, ownerClass, ownerRelation, actions }}>
{ saveRecordFirst && <div className="link-field__save-record-first">{saveRecordFirstText}</div>}
{ renderPicker && <LinkPicker
onModalSuccess={onModalSuccess}
Expand Down
12 changes: 11 additions & 1 deletion client/src/components/LinkModal/LinkModal.js
Expand Up @@ -23,6 +23,8 @@ const buildSchemaUrl = (typeKey, linkID) => {
}

const LinkModal = ({ typeTitle, typeKey, linkID = 0, isOpen, onSuccess, onClosed }) => {
const { actions } = useContext(LinkFieldContext);

if (!typeKey) {
return false;
}
Expand All @@ -31,7 +33,15 @@ const LinkModal = ({ typeTitle, typeKey, linkID = 0, isOpen, onSuccess, onClosed
* Call back used by LinkModal after the form has been submitted and the response has been received
*/
const onSubmit = async (modalData, action, submitFn) => {
const formSchema = await submitFn();
let formSchema = null;
try {
formSchema = await submitFn();
} catch (error) {
actions.toasts.error(i18n._t('LinkField.FAILED_TO_SAVE_LINK', 'Failed to save link'))
// Intentionally using Promise.resolve() instead of Promise.reject() as existing code in FormBuilder.js
// will raise console warnings if we use Promise.reject(). From a UX point of view it makes no difference.
return Promise.resolve();
}

// slightly annoyingly, on validation error formSchema at this point will not have an errors node
// instead it will have the original formSchema id used for the GET request to get the formSchema i.e.
Expand Down
2 changes: 1 addition & 1 deletion client/src/containers/LinkModalContainer.js
Expand Up @@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
/**
* Contains the LinkModal and determines which modal component to render based on the link type.
*/
const LinkModalContainer = ({ types, typeKey, linkID = 0, isOpen, onSuccess, onClosed}) => {
const LinkModalContainer = ({ types, typeKey, linkID = 0, isOpen, onSuccess, onClosed }) => {
if (!typeKey) {
return false;
}
Expand Down

0 comments on commit 9d3a6f0

Please sign in to comment.