Skip to content

Conversation

jmthibault79
Copy link
Collaborator

@jmthibault79 jmthibault79 commented Oct 20, 2022

Add a new fetchWithErrorModal() function which wraps API calls, and use this function for all workspace-about API calls.

By default, it pops up an error modal when the API returns an error (like 404). It takes an optional options object with the following parameters:

  • onSuccess - a function to execute on the successful result
  • expectedResponseMatcher - whether to silence specific errors when appropriate (such as 404 for runtime polling)
  • customErrorResponseFormatter - custom error modal text and an optional onDismiss handler

The error modal behavior is powered by the existing notificationStore / NotificationModal

An example of the default handler
default

A custom handler which is only applied for 404 (otherwise the default is used)

          customErrorResponseFormatter: (er: ErrorResponse) =>
            er.statusCode === 404 && {
              title: 'Foobar not found',
              message:
                'The Foobar may not have been created yet - please try again in a few minutes',
            },

custom


PR checklist

  • This PR meets the Acceptance Criteria in the JIRA story
  • The JIRA story has been moved to Dev Review
  • This PR includes appropriate unit tests
  • I have added explanatory comments where the logic is not obvious
  • I have run and tested this change locally, and my testing process is described here
  • If this includes a new feature flag, I have created and linked new JIRA tickets to (a) turn on the feature flag and (b) remove it later
  • If this includes an API change, I have run the E2E tests on this change against my local server with yarn test-local because this PR won't be covered by the CircleCI tests
  • If this includes a UI change, I have taken screen recordings or screenshots of the new behavior and notified the PO and UX designer in Slack
  • If this change impacts deployment safety (e.g. removing/altering APIs which are in use) I have documented these in the description
  • If this includes an API change, I have updated the appropriate Swagger definitions and updated the appropriate API consumers

.catch((error) => {
console.error(error);
});
fetchWithErrorModal(() =>
Copy link
Collaborator Author

@jmthibault79 jmthibault79 Oct 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the simplest way to use the new fetchWithErrorModal: a default popup will appear with info if there's an error. See errors and errors.spec for more examples

() => ''
);

return `An API error${errorCodeStr} occurred${detailsStr}${messageStr}`;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See errors.spec for examples of how the final result looks

@jmthibault79 jmthibault79 marked this pull request as ready for review October 21, 2022 14:39
@jmthibault79 jmthibault79 changed the title [risk=no][RW-8242] Error handling POC [risk=no][RW-8242] Use fetchWithErrorModal() for workspace-about API calls Oct 21, 2022
errorCode && errorCode !== ErrorCode.PARSEERROR
? ` of type ${errorCode.toString()}`
: '';
const messageStr = message ? `: ${message}` : '.';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encode message to remove HTML escaping?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of where this would be necessary?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I create a corhort/dataset/something else with ‘<’, ‘>’, ‘alert’. inside.
Would that lead to XSS attack if we want to prin balbla not found

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text in React components is escaped under all but the most unusual circumstances.

Comment on lines +204 to +203
fetchWithErrorModal(() =>
profileApi().updatePageVisits({ page: pageId })
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably return the promises for these so the caller can make the decision about whether it makes sense to await them.

Suggested change
fetchWithErrorModal(() =>
profileApi().updatePageVisits({ page: pageId })
);
return fetchWithErrorModal(() =>
profileApi().updatePageVisits({ page: pageId })
);

errorCode && errorCode !== ErrorCode.PARSEERROR
? ` of type ${errorCode.toString()}`
: '';
const messageStr = message ? `: ${message}` : '.';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text in React components is escaped under all but the most unusual circumstances.

* await responseP.then(resp =>
* errorHandlerWithFallback(
* resp,
* (er) => er.statusCode === 404,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: err is more idiomatic for an error variable name.

Comment on lines 209 to 211
return apiCall()
.then(onSuccess)
.catch(async (apiError) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return apiCall()
.then(onSuccess)
.catch(async (apiError) => {
return apiCall()
.catch(async (apiError) => {

expectedResponseMatcher?: (ErrorResponse) => boolean,
customErrorResponseFormatter?: (ErrorResponse) => NotificationStore
): Promise<NotificationStore> =>
convertAPIError(anyApiErrorResponse).then((errorResponse) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function (convertAPIError) perhaps should be avoided. It takes an ErrorResponse, calls .json() on it, and then throws it away if that method fails.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a new version of this is toApiErrorResponse() which retains all fields in the original and the json()

this.loadUserRoles(workspace);
}

async loadInitialCreditsUsage(workspace: WorkspaceData) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to await these, so they don't need to be async

@jmthibault79 jmthibault79 merged commit 9e8fcb1 into main Oct 25, 2022
@jmthibault79 jmthibault79 deleted the joel/RW-8242 branch October 25, 2022 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants