Files
frontend-app-authoring/src/export-page/CourseExportPage.jsx
Peter Kulko 0706a09acb fix: error handling (#1079)
Added alert message if 403 error occurs.
2024-11-18 11:27:36 -03:00

138 lines
5.3 KiB
JavaScript

import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
Container, Layout, Button, Card,
} from '@openedx/paragon';
import { ArrowCircleDown as ArrowCircleDownIcon } from '@openedx/paragon/icons';
import Cookies from 'universal-cookie';
import { getConfig } from '@edx/frontend-platform';
import { Helmet } from 'react-helmet';
import InternetConnectionAlert from '../generic/internet-connection-alert';
import ConnectionErrorAlert from '../generic/ConnectionErrorAlert';
import SubHeader from '../generic/sub-header/SubHeader';
import { RequestStatus } from '../data/constants';
import { useModel } from '../generic/model-store';
import messages from './messages';
import ExportSidebar from './export-sidebar/ExportSidebar';
import {
getCurrentStage, getError, getExportTriggered, getLoadingStatus, getSavingStatus,
} from './data/selectors';
import { startExportingCourse } from './data/thunks';
import { EXPORT_STAGES, LAST_EXPORT_COOKIE_NAME } from './data/constants';
import { updateExportTriggered, updateSavingStatus, updateSuccessDate } from './data/slice';
import ExportModalError from './export-modal-error/ExportModalError';
import ExportFooter from './export-footer/ExportFooter';
import ExportStepper from './export-stepper/ExportStepper';
const CourseExportPage = ({ intl, courseId }) => {
const dispatch = useDispatch();
const exportTriggered = useSelector(getExportTriggered);
const courseDetails = useModel('courseDetails', courseId);
const currentStage = useSelector(getCurrentStage);
const { msg: errorMessage } = useSelector(getError);
const loadingStatus = useSelector(getLoadingStatus);
const savingStatus = useSelector(getSavingStatus);
const cookies = new Cookies();
const isShowExportButton = !exportTriggered || errorMessage || currentStage === EXPORT_STAGES.SUCCESS;
const anyRequestFailed = savingStatus === RequestStatus.FAILED || loadingStatus === RequestStatus.FAILED;
const isLoadingDenied = loadingStatus === RequestStatus.DENIED;
const anyRequestInProgress = savingStatus === RequestStatus.PENDING || loadingStatus === RequestStatus.IN_PROGRESS;
useEffect(() => {
const cookieData = cookies.get(LAST_EXPORT_COOKIE_NAME);
if (cookieData) {
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
dispatch(updateExportTriggered(true));
dispatch(updateSuccessDate(cookieData.date));
}
}, []);
if (isLoadingDenied) {
return (
<Container size="xl" className="course-unit px-4 mt-4">
<ConnectionErrorAlert />
</Container>
);
}
return (
<>
<Helmet>
<title>
{intl.formatMessage(messages.pageTitle, {
headingTitle: intl.formatMessage(messages.headingTitle),
courseName: courseDetails?.name,
siteName: process.env.SITE_NAME,
})}
</title>
</Helmet>
<Container size="xl" className="mt-4 px-4 export">
<section className="setting-items mb-4">
<Layout
lg={[{ span: 9 }, { span: 3 }]}
md={[{ span: 9 }, { span: 3 }]}
sm={[{ span: 9 }, { span: 3 }]}
xs={[{ span: 9 }, { span: 3 }]}
xl={[{ span: 9 }, { span: 3 }]}
>
<Layout.Element>
<article>
<SubHeader
title={intl.formatMessage(messages.headingTitle)}
subtitle={intl.formatMessage(messages.headingSubtitle)}
/>
<p className="small">{intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}</p>
<p className="small">{intl.formatMessage(messages.description2)}</p>
<Card>
<Card.Header
className="h3 px-3 text-black mb-4"
title={intl.formatMessage(messages.titleUnderButton)}
/>
{isShowExportButton && (
<Card.Section className="px-3 py-1">
<Button
size="lg"
block
className="mb-4"
onClick={() => dispatch(startExportingCourse(courseId))}
iconBefore={ArrowCircleDownIcon}
>
{intl.formatMessage(messages.buttonTitle)}
</Button>
</Card.Section>
)}
</Card>
{exportTriggered && <ExportStepper courseId={courseId} />}
<ExportFooter />
</article>
</Layout.Element>
<Layout.Element>
<ExportSidebar courseId={courseId} />
</Layout.Element>
</Layout>
</section>
<ExportModalError courseId={courseId} />
</Container>
<div className="alert-toast">
<InternetConnectionAlert
isFailed={anyRequestFailed}
isQueryPending={anyRequestInProgress}
onInternetConnectionFailed={() => null}
/>
</div>
</>
);
};
CourseExportPage.propTypes = {
intl: intlShape.isRequired,
courseId: PropTypes.string.isRequired,
};
CourseExportPage.defaultProps = {};
export default injectIntl(CourseExportPage);