diff --git a/src/course-outline/page-alerts/PageAlerts.jsx b/src/course-outline/page-alerts/PageAlerts.jsx index 4b12996395..2dc9842025 100644 --- a/src/course-outline/page-alerts/PageAlerts.jsx +++ b/src/course-outline/page-alerts/PageAlerts.jsx @@ -343,13 +343,34 @@ const PageAlerts = ({ const renderApiErrors = () => { let errorList = Object.entries(errors).filter(obj => obj[1] !== null).map(([k, v]) => { switch (v.type) { - case API_ERROR_TYPES.serverError: + case API_ERROR_TYPES.serverError: { + let description = ( + + {v.data || intl.formatMessage(messages.serverErrorAlertBody)} + + ); + let alertTitle = intl.formatMessage(messages.serverErrorAlert); + if (v.status === 403) { + description = intl.formatMessage(messages.forbiddenAlertBody, { + LMS: ( + + {intl.formatMessage(messages.forbiddenAlertLmsUrl)} + + ), + }); + alertTitle = intl.formatMessage(messages.forbiddenAlert); + } return { key: k, - desc: v.data || intl.formatMessage(messages.serverErrorAlertBody), - title: intl.formatMessage(messages.serverErrorAlert), + desc: description, + title: alertTitle, dismissible: v.dismissible, }; + } case API_ERROR_TYPES.networkError: return { key: k, @@ -378,7 +399,7 @@ const PageAlerts = ({ dismissError={() => dispatch(dismissError(msgObj.key))} > {msgObj.title} - {msgObj.desc && {msgObj.desc}} + {msgObj.desc} ) : ( {msgObj.title} - {msgObj.desc && {msgObj.desc}} + {msgObj.desc} ) )) diff --git a/src/course-outline/page-alerts/PageAlerts.test.jsx b/src/course-outline/page-alerts/PageAlerts.test.jsx index 6d646f7cb4..28e39945ef 100644 --- a/src/course-outline/page-alerts/PageAlerts.test.jsx +++ b/src/course-outline/page-alerts/PageAlerts.test.jsx @@ -218,4 +218,29 @@ describe('', () => { expect(queryByText('some error')).toBeInTheDocument(); expect(queryByText('some unknown error')).toBeInTheDocument(); }); + + it('renders forbidden api error alerts', async () => { + const { queryByText } = renderComponent({ + ...pageAlertsData, + errors: { + outlineIndexApi: { + data: 'some error', status: 403, type: API_ERROR_TYPES.serverError, dismissable: true, + }, + }, + }); + expect(queryByText(messages.forbiddenAlert.defaultMessage)).toBeInTheDocument(); + expect(queryByText(messages.forbiddenAlertBody.defaultMessage)).toBeInTheDocument(); + }); + + it('renders api error alerts when status is not 403', async () => { + const { queryByText } = renderComponent({ + ...pageAlertsData, + errors: { + outlineIndexApi: { + data: 'some error', status: 500, type: API_ERROR_TYPES.serverError, dismissable: true, + }, + }, + }); + expect(queryByText('some error')).toBeInTheDocument(); + }); }); diff --git a/src/course-outline/page-alerts/messages.js b/src/course-outline/page-alerts/messages.js index f9638398d8..9aa6756a78 100644 --- a/src/course-outline/page-alerts/messages.js +++ b/src/course-outline/page-alerts/messages.js @@ -121,6 +121,21 @@ const messages = defineMessages({ defaultMessage: 'Network error', description: 'Generic network error alert.', }, + forbiddenAlert: { + id: 'course-authoring.course-outline.page-alert.forbidden.title', + defaultMessage: 'Access Restricted', + description: 'Forbidden(403) alert title', + }, + forbiddenAlertBody: { + id: 'course-authoring.course-outline.page-alert.forbidden.body', + defaultMessage: 'It looks like you’re trying to access a page you don’t have permission to view. Contact your admin if you think this is a mistake, or head back to the {LMS}.', + description: 'Forbidden(403) alert body', + }, + forbiddenAlertLmsUrl: { + id: 'course-authoring.course-outline.page-alert.lms', + defaultMessage: 'LMS', + description: 'LMS base redirection url', + }, }); export default messages;