feat: implement export page (#586)
This commit is contained in:
committed by
GitHub
parent
fb28693854
commit
1888993113
1
.env
1
.env
@@ -36,7 +36,6 @@ ENABLE_NEW_VIDEO_UPLOAD_PAGE = false
|
||||
ENABLE_NEW_GRADING_PAGE = false
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = false
|
||||
ENABLE_NEW_IMPORT_PAGE = false
|
||||
ENABLE_NEW_EXPORT_PAGE = false
|
||||
ENABLE_UNIT_PAGE = false
|
||||
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN = false
|
||||
BBB_LEARN_MORE_URL=''
|
||||
|
||||
@@ -38,7 +38,6 @@ ENABLE_NEW_VIDEO_UPLOAD_PAGE = false
|
||||
ENABLE_NEW_GRADING_PAGE = false
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = false
|
||||
ENABLE_NEW_IMPORT_PAGE = false
|
||||
ENABLE_NEW_EXPORT_PAGE = false
|
||||
ENABLE_UNIT_PAGE = false
|
||||
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN = false
|
||||
BBB_LEARN_MORE_URL=''
|
||||
|
||||
@@ -34,7 +34,6 @@ ENABLE_NEW_VIDEO_UPLOAD_PAGE = true
|
||||
ENABLE_NEW_GRADING_PAGE = true
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = true
|
||||
ENABLE_NEW_IMPORT_PAGE = true
|
||||
ENABLE_NEW_EXPORT_PAGE = true
|
||||
ENABLE_UNIT_PAGE = true
|
||||
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN = true
|
||||
BBB_LEARN_MORE_URL=''
|
||||
|
||||
1
package-lock.json
generated
1
package-lock.json
generated
@@ -42,6 +42,7 @@
|
||||
"react-transition-group": "4.4.1",
|
||||
"redux": "4.0.5",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"uuid": "^3.4.0",
|
||||
"yup": "0.31.1"
|
||||
},
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
"react-transition-group": "4.4.1",
|
||||
"redux": "4.0.5",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"universal-cookie": "^4.0.4",
|
||||
"uuid": "^3.4.0",
|
||||
"yup": "0.31.1"
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ import ScheduleAndDetails from './schedule-and-details';
|
||||
import { GradingSettings } from './grading-settings';
|
||||
import CourseTeam from './course-team/CourseTeam';
|
||||
import { CourseUpdates } from './course-updates';
|
||||
import CourseExportPage from './export-page/CourseExportPage';
|
||||
|
||||
/**
|
||||
* As of this writing, these routes are mounted at a path prefixed with the following:
|
||||
@@ -105,10 +106,7 @@ const CourseAuthoringRoutes = ({ courseId }) => {
|
||||
)}
|
||||
</PageRoute>
|
||||
<PageRoute path={`${path}/export`}>
|
||||
{process.env.ENABLE_NEW_EXPORT_PAGE === 'true'
|
||||
&& (
|
||||
<Placeholder />
|
||||
)}
|
||||
<CourseExportPage courseId={courseId} />
|
||||
</PageRoute>
|
||||
</Switch>
|
||||
</CourseAuthoringPage>
|
||||
|
||||
127
src/export-page/CourseExportPage.jsx
Normal file
127
src/export-page/CourseExportPage.jsx
Normal file
@@ -0,0 +1,127 @@
|
||||
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 '@edx/paragon';
|
||||
import { ArrowCircleDown as ArrowCircleDownIcon } from '@edx/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 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 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));
|
||||
}
|
||||
}, []);
|
||||
|
||||
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="m-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>{intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}</p>
|
||||
<p>{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);
|
||||
9
src/export-page/CourseExportPage.scss
Normal file
9
src/export-page/CourseExportPage.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@import "./export-stepper/ExportStepper";
|
||||
@import "./export-footer/ExportFooter";
|
||||
@import "./export-sidebar/ExportSidebar";
|
||||
|
||||
.export {
|
||||
.help-sidebar {
|
||||
margin-top: 7.188rem;
|
||||
}
|
||||
}
|
||||
127
src/export-page/CourseExportPage.test.jsx
Normal file
127
src/export-page/CourseExportPage.test.jsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import React from 'react';
|
||||
import { getConfig, initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import Cookies from 'universal-cookie';
|
||||
import initializeStore from '../store';
|
||||
import stepperMessages from './export-stepper/messages';
|
||||
import modalErrorMessages from './export-modal-error/messages';
|
||||
import { getExportStatusApiUrl, postExportCourseApiUrl } from './data/api';
|
||||
import { EXPORT_STAGES } from './data/constants';
|
||||
import { exportPageMock } from './__mocks__';
|
||||
import messages from './messages';
|
||||
import CourseExportPage from './CourseExportPage';
|
||||
|
||||
let store;
|
||||
let axiosMock;
|
||||
let cookies;
|
||||
const courseId = '123';
|
||||
const courseName = 'About Node JS';
|
||||
|
||||
jest.mock('../generic/model-store', () => ({
|
||||
useModel: jest.fn().mockReturnValue({
|
||||
name: courseName,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('universal-cookie', () => {
|
||||
const mCookie = {
|
||||
get: jest.fn(),
|
||||
set: jest.fn(),
|
||||
};
|
||||
return jest.fn(() => mCookie);
|
||||
});
|
||||
|
||||
const RootWrapper = () => (
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
<CourseExportPage intl={injectIntl} courseId={courseId} />
|
||||
</IntlProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
|
||||
describe('<CourseExportPage />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
axiosMock
|
||||
.onGet(postExportCourseApiUrl(courseId))
|
||||
.reply(200, exportPageMock);
|
||||
cookies = new Cookies();
|
||||
cookies.get.mockReturnValue(null);
|
||||
});
|
||||
it('should render page title correctly', async () => {
|
||||
render(<RootWrapper />);
|
||||
await waitFor(() => {
|
||||
const helmet = Helmet.peek();
|
||||
expect(helmet.title).toEqual(
|
||||
`${messages.headingTitle.defaultMessage} | ${courseName} | ${process.env.SITE_NAME}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
it('should render without errors', async () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
await waitFor(() => {
|
||||
expect(getByText(messages.headingSubtitle.defaultMessage)).toBeInTheDocument();
|
||||
const exportPageElement = getByText(messages.headingTitle.defaultMessage, {
|
||||
selector: 'h2.sub-header-title',
|
||||
});
|
||||
expect(exportPageElement).toBeInTheDocument();
|
||||
expect(getByText(messages.titleUnderButton.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.description2.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.buttonTitle.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
it('should start exporting on click', async () => {
|
||||
const { getByText, container } = render(<RootWrapper />);
|
||||
const button = container.querySelector('.btn-primary');
|
||||
fireEvent.click(button);
|
||||
expect(getByText(stepperMessages.stepperPreparingDescription.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
it('should show modal error', async () => {
|
||||
axiosMock
|
||||
.onGet(getExportStatusApiUrl(courseId))
|
||||
.reply(200, { exportStatus: EXPORT_STAGES.EXPORTING, exportError: { rawErrorMsg: 'test error', editUnitUrl: 'http://test-url.test' } });
|
||||
const { getByText, queryByText, container } = render(<RootWrapper />);
|
||||
const startExportButton = container.querySelector('.btn-primary');
|
||||
fireEvent.click(startExportButton);
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
await new Promise((r) => setTimeout(r, 3500));
|
||||
expect(getByText(/There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: test error/i));
|
||||
const closeModalWindowButton = getByText('Return to export');
|
||||
fireEvent.click(closeModalWindowButton);
|
||||
expect(queryByText(modalErrorMessages.errorCancelButtonUnit.defaultMessage)).not.toBeInTheDocument();
|
||||
fireEvent.click(closeModalWindowButton);
|
||||
});
|
||||
it('should fetch status without clicking when cookies has', async () => {
|
||||
cookies.get.mockReturnValue({ date: 1679787000 });
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
expect(getByText(stepperMessages.stepperPreparingDescription.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
it('should show download path', async () => {
|
||||
axiosMock
|
||||
.onGet(getExportStatusApiUrl(courseId))
|
||||
.reply(200, { exportStatus: EXPORT_STAGES.SUCCESS, exportOutput: '/test-download-path.test' });
|
||||
const { getByText, container } = render(<RootWrapper />);
|
||||
const startExportButton = container.querySelector('.btn-primary');
|
||||
fireEvent.click(startExportButton);
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
await new Promise((r) => setTimeout(r, 3500));
|
||||
const downloadButton = getByText(stepperMessages.downloadCourseButtonTitle.defaultMessage);
|
||||
expect(downloadButton).toBeInTheDocument();
|
||||
expect(downloadButton.getAttribute('href')).toEqual(`${getConfig().STUDIO_BASE_URL}/test-download-path.test`);
|
||||
});
|
||||
});
|
||||
3
src/export-page/__mocks__/exportPage.js
Normal file
3
src/export-page/__mocks__/exportPage.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
exportStatus: 1,
|
||||
};
|
||||
2
src/export-page/__mocks__/index.js
Normal file
2
src/export-page/__mocks__/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { default as exportPageMock } from './exportPage';
|
||||
19
src/export-page/data/api.js
Normal file
19
src/export-page/data/api.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
|
||||
export const postExportCourseApiUrl = (courseId) => new URL(`export/${courseId}`, getApiBaseUrl()).href;
|
||||
export const getExportStatusApiUrl = (courseId) => new URL(`export_status/${courseId}`, getApiBaseUrl()).href;
|
||||
|
||||
export async function startCourseExporting(courseId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.post(postExportCourseApiUrl(courseId));
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
export async function getExportStatus(courseId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(getExportStatusApiUrl(courseId));
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
47
src/export-page/data/api.test.js
Normal file
47
src/export-page/data/api.test.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { initializeMockApp, getConfig } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
import { getExportStatus, postExportCourseApiUrl, startCourseExporting } from './api';
|
||||
|
||||
let axiosMock;
|
||||
const courseId = 'course-123';
|
||||
|
||||
describe('API Functions', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should fetch status on start exporting', async () => {
|
||||
const data = { exportStatus: 1 };
|
||||
axiosMock.onPost(postExportCourseApiUrl(courseId)).reply(200, data);
|
||||
|
||||
const result = await startCourseExporting(courseId);
|
||||
|
||||
expect(axiosMock.history.post[0].url).toEqual(postExportCourseApiUrl(courseId));
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
|
||||
it('should fetch on get export status', async () => {
|
||||
const data = { exportStatus: 2 };
|
||||
const queryUrl = new URL(`export_status/${courseId}`, getConfig().STUDIO_BASE_URL).href;
|
||||
axiosMock.onGet(queryUrl).reply(200, data);
|
||||
|
||||
const result = await getExportStatus(courseId);
|
||||
|
||||
expect(axiosMock.history.get[0].url).toEqual(queryUrl);
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
});
|
||||
8
src/export-page/data/constants.js
Normal file
8
src/export-page/data/constants.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export const LAST_EXPORT_COOKIE_NAME = 'lastexport';
|
||||
export const EXPORT_STAGES = {
|
||||
PREPARING: 0,
|
||||
EXPORTING: 1,
|
||||
COMPRESSING: 2,
|
||||
SUCCESS: 3,
|
||||
};
|
||||
export const SUCCESS_DATE_FORMAT = 'MM/DD/yyyy';
|
||||
8
src/export-page/data/selectors.js
Normal file
8
src/export-page/data/selectors.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export const getExportTriggered = (state) => state.courseExport.exportTriggered;
|
||||
export const getCurrentStage = (state) => state.courseExport.currentStage;
|
||||
export const getDownloadPath = (state) => state.courseExport.downloadPath;
|
||||
export const getSuccessDate = (state) => state.courseExport.successDate;
|
||||
export const getError = (state) => state.courseExport.error;
|
||||
export const getIsErrorModalOpen = (state) => state.courseExport.isErrorModalOpen;
|
||||
export const getLoadingStatus = (state) => state.courseExport.loadingStatus;
|
||||
export const getSavingStatus = (state) => state.courseExport.savingStatus;
|
||||
63
src/export-page/data/slice.js
Normal file
63
src/export-page/data/slice.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = {
|
||||
exportTriggered: false,
|
||||
currentStage: 0,
|
||||
error: { msg: null, unitUrl: null },
|
||||
downloadPath: null,
|
||||
successDate: null,
|
||||
isErrorModalOpen: false,
|
||||
loadingStatus: '',
|
||||
savingStatus: '',
|
||||
};
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'exportPage',
|
||||
initialState,
|
||||
reducers: {
|
||||
updateExportTriggered: (state, { payload }) => {
|
||||
state.exportTriggered = payload;
|
||||
},
|
||||
updateCurrentStage: (state, { payload }) => {
|
||||
if (payload >= state.currentStage) {
|
||||
state.currentStage = payload;
|
||||
}
|
||||
},
|
||||
updateDownloadPath: (state, { payload }) => {
|
||||
state.downloadPath = payload;
|
||||
},
|
||||
updateSuccessDate: (state, { payload }) => {
|
||||
state.successDate = payload;
|
||||
},
|
||||
updateError: (state, { payload }) => {
|
||||
state.error = payload;
|
||||
},
|
||||
updateIsErrorModalOpen: (state, { payload }) => {
|
||||
state.isErrorModalOpen = payload;
|
||||
},
|
||||
reset: () => initialState,
|
||||
updateLoadingStatus: (state, { payload }) => {
|
||||
state.loadingStatus = payload.status;
|
||||
},
|
||||
updateSavingStatus: (state, { payload }) => {
|
||||
state.savingStatus = payload.status;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
updateExportTriggered,
|
||||
updateCurrentStage,
|
||||
updateDownloadPath,
|
||||
updateSuccessDate,
|
||||
updateError,
|
||||
updateIsErrorModalOpen,
|
||||
reset,
|
||||
updateLoadingStatus,
|
||||
updateSavingStatus,
|
||||
} = slice.actions;
|
||||
|
||||
export const {
|
||||
reducer,
|
||||
} = slice;
|
||||
75
src/export-page/data/thunks.js
Normal file
75
src/export-page/data/thunks.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import Cookies from 'universal-cookie';
|
||||
import moment from 'moment';
|
||||
|
||||
import { RequestStatus } from '../../data/constants';
|
||||
import { setExportCookie } from '../utils';
|
||||
import { EXPORT_STAGES, LAST_EXPORT_COOKIE_NAME } from './constants';
|
||||
|
||||
import {
|
||||
startCourseExporting,
|
||||
getExportStatus,
|
||||
} from './api';
|
||||
import {
|
||||
updateExportTriggered,
|
||||
updateCurrentStage,
|
||||
updateDownloadPath,
|
||||
updateSuccessDate,
|
||||
updateError,
|
||||
updateIsErrorModalOpen,
|
||||
reset,
|
||||
updateLoadingStatus,
|
||||
updateSavingStatus,
|
||||
} from './slice';
|
||||
|
||||
export function startExportingCourse(courseId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
|
||||
try {
|
||||
dispatch(reset());
|
||||
dispatch(updateExportTriggered(true));
|
||||
const exportData = await startCourseExporting(courseId);
|
||||
dispatch(updateCurrentStage(exportData.exportStatus));
|
||||
setExportCookie(moment().valueOf(), exportData.exportStatus === EXPORT_STAGES.SUCCESS);
|
||||
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
return true;
|
||||
} catch (error) {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchExportStatus(courseId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
try {
|
||||
const { exportStatus, exportOutput, exportError } = await getExportStatus(courseId);
|
||||
dispatch(updateCurrentStage(Math.abs(exportStatus)));
|
||||
|
||||
if (exportOutput) {
|
||||
dispatch(updateDownloadPath(exportOutput));
|
||||
dispatch(updateSuccessDate(moment().valueOf()));
|
||||
}
|
||||
|
||||
const cookies = new Cookies();
|
||||
const cookieData = cookies.get(LAST_EXPORT_COOKIE_NAME);
|
||||
if (!cookieData?.completed) {
|
||||
setExportCookie(moment().valueOf(), exportStatus === EXPORT_STAGES.SUCCESS);
|
||||
}
|
||||
|
||||
if (exportError) {
|
||||
const errorMessage = exportError.rawErrorMsg || exportError;
|
||||
const errorUnitUrl = exportError.editUnitUrl || null;
|
||||
dispatch(updateError({ msg: errorMessage, unitUrl: errorUnitUrl }));
|
||||
dispatch(updateIsErrorModalOpen(true));
|
||||
}
|
||||
|
||||
dispatch(updateLoadingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
return true;
|
||||
} catch (error) {
|
||||
dispatch(updateLoadingStatus({ status: RequestStatus.FAILED }));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
48
src/export-page/export-footer/ExportFooter.jsx
Normal file
48
src/export-page/export-footer/ExportFooter.jsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
injectIntl,
|
||||
intlShape,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { Layout } from '@edx/paragon';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const ExportFooter = ({ intl }) => (
|
||||
<footer className="mt-4">
|
||||
<Layout
|
||||
lg={[{ span: 6 }, { span: 6 }]}
|
||||
md={[{ span: 6 }, { span: 6 }]}
|
||||
sm={[{ span: 6 }, { span: 6 }]}
|
||||
xs={[{ span: 6 }, { span: 6 }]}
|
||||
xl={[{ span: 6 }, { span: 6 }]}
|
||||
>
|
||||
<Layout.Element>
|
||||
<h4>{intl.formatMessage(messages.exportedDataTitle)}</h4>
|
||||
<ul className="export-footer-list">
|
||||
<li>{intl.formatMessage(messages.exportedDataItem1)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem2)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem3)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem4)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem5)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem6)}</li>
|
||||
<li>{intl.formatMessage(messages.exportedDataItem7)}</li>
|
||||
</ul>
|
||||
</Layout.Element>
|
||||
<Layout.Element>
|
||||
<h4>{intl.formatMessage(messages.notExportedDataTitle)}</h4>
|
||||
<ul className="export-footer-list">
|
||||
<li>{intl.formatMessage(messages.notExportedDataItem1)}</li>
|
||||
<li>{intl.formatMessage(messages.notExportedDataItem2)}</li>
|
||||
<li>{intl.formatMessage(messages.notExportedDataItem3)}</li>
|
||||
<li>{intl.formatMessage(messages.notExportedDataItem4)}</li>
|
||||
</ul>
|
||||
</Layout.Element>
|
||||
</Layout>
|
||||
</footer>
|
||||
);
|
||||
|
||||
ExportFooter.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ExportFooter);
|
||||
14
src/export-page/export-footer/ExportFooter.scss
Normal file
14
src/export-page/export-footer/ExportFooter.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.export-footer-list {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
padding-bottom: .3125rem;
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
margin-bottom: .3125rem;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
58
src/export-page/export-footer/messages.js
Normal file
58
src/export-page/export-footer/messages.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
exportedDataTitle: {
|
||||
id: 'course-authoring.export.footer.exportedData.title',
|
||||
defaultMessage: 'Data exported with your course:',
|
||||
},
|
||||
exportedDataItem1: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.1',
|
||||
defaultMessage: 'Values from Advanced settings, including MATLAB API keys and LTI passports',
|
||||
},
|
||||
exportedDataItem2: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.2',
|
||||
defaultMessage: 'Course content (all sections, sub-sections, and units)',
|
||||
},
|
||||
exportedDataItem3: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.3',
|
||||
defaultMessage: 'Course structure',
|
||||
},
|
||||
exportedDataItem4: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.4',
|
||||
defaultMessage: 'Individual problems',
|
||||
},
|
||||
exportedDataItem5: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.5',
|
||||
defaultMessage: 'Pages',
|
||||
},
|
||||
exportedDataItem6: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.6',
|
||||
defaultMessage: 'Course assets',
|
||||
},
|
||||
exportedDataItem7: {
|
||||
id: 'course-authoring.export.footer.exportedData.item.7',
|
||||
defaultMessage: 'Course settings',
|
||||
},
|
||||
notExportedDataTitle: {
|
||||
id: 'course-authoring.export.footer.notExportedData.title',
|
||||
defaultMessage: 'Data not exported with your course:',
|
||||
},
|
||||
notExportedDataItem1: {
|
||||
id: 'course-authoring.export.footer.notExportedData.item.1',
|
||||
defaultMessage: 'User data',
|
||||
},
|
||||
notExportedDataItem2: {
|
||||
id: 'course-authoring.export.footer.notExportedData.item.2',
|
||||
defaultMessage: 'Course team data',
|
||||
},
|
||||
notExportedDataItem3: {
|
||||
id: 'course-authoring.export.footer.notExportedData.item.3',
|
||||
defaultMessage: 'Forum/discussion data',
|
||||
},
|
||||
notExportedDataItem4: {
|
||||
id: 'course-authoring.export.footer.notExportedData.item.4',
|
||||
defaultMessage: 'Certificates',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
54
src/export-page/export-modal-error/ExportModalError.jsx
Normal file
54
src/export-page/export-modal-error/ExportModalError.jsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { history } from '@edx/frontend-platform';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import ModalError from '../../generic/modal-error/ModalError';
|
||||
import { getError, getIsErrorModalOpen } from '../data/selectors';
|
||||
import { updateIsErrorModalOpen } from '../data/slice';
|
||||
import messages from './messages';
|
||||
|
||||
const ExportModalError = ({
|
||||
intl,
|
||||
courseId,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
const isErrorModalOpen = useSelector(getIsErrorModalOpen);
|
||||
const { msg: errorMessage, unitUrl: unitErrorUrl } = useSelector(getError);
|
||||
|
||||
const handleUnitRedirect = () => { window.location.href = unitErrorUrl; };
|
||||
const handleRedirectCourseHome = () => history.push(`/course/${courseId}/outline`);
|
||||
|
||||
return (
|
||||
<ModalError
|
||||
isOpen={isErrorModalOpen}
|
||||
title={intl.formatMessage(messages.errorTitle)}
|
||||
message={
|
||||
intl.formatMessage(
|
||||
unitErrorUrl
|
||||
? messages.errorDescriptionUnit
|
||||
: messages.errorDescriptionNotUnit,
|
||||
{ errorMessage },
|
||||
)
|
||||
}
|
||||
cancelButtonText={
|
||||
intl.formatMessage(unitErrorUrl ? messages.errorCancelButtonUnit : messages.errorCancelButtonNotUnit)
|
||||
}
|
||||
actionButtonText={
|
||||
intl.formatMessage(unitErrorUrl ? messages.errorActionButtonUnit : messages.errorActionButtonNotUnit)
|
||||
}
|
||||
handleCancel={() => dispatch(updateIsErrorModalOpen(false))}
|
||||
handleAction={unitErrorUrl ? handleUnitRedirect : handleRedirectCourseHome}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ExportModalError.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
ExportModalError.defaultProps = {};
|
||||
|
||||
export default injectIntl(ExportModalError);
|
||||
34
src/export-page/export-modal-error/messages.js
Normal file
34
src/export-page/export-modal-error/messages.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
errorTitle: {
|
||||
id: 'course-authoring.export.modal.error.title',
|
||||
defaultMessage: 'There has been an error while exporting.',
|
||||
},
|
||||
errorDescriptionNotUnit: {
|
||||
id: 'course-authoring.export.modal.error.description.not.unit',
|
||||
defaultMessage: 'Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}',
|
||||
},
|
||||
errorDescriptionUnit: {
|
||||
id: 'course-authoring.export.modal.error.description.unit',
|
||||
defaultMessage: 'There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}',
|
||||
},
|
||||
errorCancelButtonUnit: {
|
||||
id: 'course-authoring.export.modal.error.button.cancel.unit',
|
||||
defaultMessage: 'Return to export',
|
||||
},
|
||||
errorCancelButtonNotUnit: {
|
||||
id: 'course-authoring.export.modal.error.button.cancel.not.unit',
|
||||
defaultMessage: 'Cancel',
|
||||
},
|
||||
errorActionButtonNotUnit: {
|
||||
id: 'course-authoring.export.modal.error.button.action.not.unit',
|
||||
defaultMessage: 'Take me to the main course page',
|
||||
},
|
||||
errorActionButtonUnit: {
|
||||
id: 'course-authoring.export.modal.error.button.action.unit',
|
||||
defaultMessage: 'Correct failed component',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
49
src/export-page/export-sidebar/ExportSidebar.jsx
Normal file
49
src/export-page/export-sidebar/ExportSidebar.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
injectIntl,
|
||||
intlShape,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from '@edx/paragon';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import HelpSidebar from '../../generic/help-sidebar';
|
||||
import { useHelpUrls } from '../../help-urls/hooks';
|
||||
import messages from './messages';
|
||||
|
||||
const ExportSidebar = ({ intl, courseId }) => {
|
||||
const { exportCourse: exportLearnMoreUrl } = useHelpUrls(['exportCourse']);
|
||||
return (
|
||||
<HelpSidebar courseId={courseId}>
|
||||
<h4 className="help-sidebar-about-title">{intl.formatMessage(messages.title1)}</h4>
|
||||
<p className="help-sidebar-about-descriptions">{intl.formatMessage(messages.description1, { studioShortName: getConfig().STUDIO_SHORT_NAME })}</p>
|
||||
<hr />
|
||||
<h4 className="help-sidebar-about-title">{intl.formatMessage(messages.exportedContent)}</h4>
|
||||
<p className="help-sidebar-about-descriptions">{intl.formatMessage(messages.exportedContentHeading)}</p>
|
||||
<ul className="export-sidebar-list">
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content1)}</li>
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content2)}</li>
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content3)}</li>
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content4)}</li>
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content5)}</li>
|
||||
</ul>
|
||||
<p className="help-sidebar-about-descriptions">{intl.formatMessage(messages.notExportedContent)}</p>
|
||||
<ul className="export-sidebar-list">
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content6)}</li>
|
||||
<li className="help-sidebar-about-descriptions">{intl.formatMessage(messages.content7)}</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h4 className="help-sidebar-about-title">{intl.formatMessage(messages.openDownloadFile)}</h4>
|
||||
<p className="help-sidebar-about-descriptions">{intl.formatMessage(messages.openDownloadFileDescription)}</p>
|
||||
<hr />
|
||||
<Button href={exportLearnMoreUrl} target="_blank" variant="outline-primary">{intl.formatMessage(messages.learnMoreButtonTitle)}</Button>
|
||||
</HelpSidebar>
|
||||
);
|
||||
};
|
||||
|
||||
ExportSidebar.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ExportSidebar);
|
||||
4
src/export-page/export-sidebar/ExportSidebar.scss
Normal file
4
src/export-page/export-sidebar/ExportSidebar.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
.export-sidebar-list {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
39
src/export-page/export-sidebar/ExportSidebar.test.jsx
Normal file
39
src/export-page/export-sidebar/ExportSidebar.test.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import initializeStore from '../../store';
|
||||
import messages from './messages';
|
||||
import ExportSidebar from './ExportSidebar';
|
||||
|
||||
const courseId = 'course-123';
|
||||
let store;
|
||||
|
||||
const RootWrapper = () => (
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
<ExportSidebar intl={{ formatMessage: jest.fn() }} courseId={courseId} />
|
||||
</IntlProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
|
||||
describe('<ExportSidebar />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
store = initializeStore();
|
||||
});
|
||||
it('render sidebar correctly', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
expect(getByText(messages.title1.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.exportedContentHeading.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
66
src/export-page/export-sidebar/messages.js
Normal file
66
src/export-page/export-sidebar/messages.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
title1: {
|
||||
id: 'course-authoring.export.sidebar.title1',
|
||||
defaultMessage: 'Why export a course?',
|
||||
},
|
||||
description1: {
|
||||
id: 'course-authoring.export.sidebar.description1',
|
||||
defaultMessage: 'You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.',
|
||||
},
|
||||
exportedContent: {
|
||||
id: 'course-authoring.export.sidebar.exportedContent',
|
||||
defaultMessage: 'What content is exported?',
|
||||
},
|
||||
exportedContentHeading: {
|
||||
id: 'course-authoring.export.sidebar.exportedContentHeading',
|
||||
defaultMessage: 'The following content is exported.',
|
||||
},
|
||||
content1: {
|
||||
id: 'course-authoring.export.sidebar.content1',
|
||||
defaultMessage: 'Course content and structure',
|
||||
},
|
||||
content2: {
|
||||
id: 'course-authoring.export.sidebar.content2',
|
||||
defaultMessage: 'Course dates',
|
||||
},
|
||||
content3: {
|
||||
id: 'course-authoring.export.sidebar.content3',
|
||||
defaultMessage: 'Grading policy',
|
||||
},
|
||||
content4: {
|
||||
id: 'course-authoring.export.sidebar.content4',
|
||||
defaultMessage: 'Any group configurations',
|
||||
},
|
||||
content5: {
|
||||
id: 'course-authoring.export.sidebar.content5',
|
||||
defaultMessage: 'Settings on the Advanced settings page, including MATLAB API keys and LTI passports',
|
||||
},
|
||||
notExportedContent: {
|
||||
id: 'course-authoring.export.sidebar.notExportedContent',
|
||||
defaultMessage: 'The following content is not exported.',
|
||||
},
|
||||
content6: {
|
||||
id: 'course-authoring.export.sidebar.content6',
|
||||
defaultMessage: 'Learner-specific content, such as learner grades and discussion forum data',
|
||||
},
|
||||
content7: {
|
||||
id: 'course-authoring.export.sidebar.content7',
|
||||
defaultMessage: 'The course team',
|
||||
},
|
||||
openDownloadFile: {
|
||||
id: 'course-authoring.export.sidebar.openDownloadFile',
|
||||
defaultMessage: 'Opening the downloaded file',
|
||||
},
|
||||
openDownloadFileDescription: {
|
||||
id: 'course-authoring.export.sidebar.openDownloadFileDescription',
|
||||
defaultMessage: 'Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.',
|
||||
},
|
||||
learnMoreButtonTitle: {
|
||||
id: 'course-authoring.export.sidebar.learnMoreButtonTitle',
|
||||
defaultMessage: 'Learn more about exporting a course',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
89
src/export-page/export-stepper/ExportStepper.jsx
Normal file
89
src/export-page/export-stepper/ExportStepper.jsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
injectIntl,
|
||||
intlShape,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { Button } from '@edx/paragon';
|
||||
|
||||
import CourseStepper from '../../generic/course-stepper';
|
||||
import {
|
||||
getCurrentStage, getDownloadPath, getError, getLoadingStatus, getSuccessDate,
|
||||
} from '../data/selectors';
|
||||
import { fetchExportStatus } from '../data/thunks';
|
||||
import { EXPORT_STAGES } from '../data/constants';
|
||||
import { getFormattedSuccessDate } from '../utils';
|
||||
import { RequestStatus } from '../../data/constants';
|
||||
import messages from './messages';
|
||||
|
||||
const ExportStepper = ({ intl, courseId }) => {
|
||||
const currentStage = useSelector(getCurrentStage);
|
||||
const downloadPath = useSelector(getDownloadPath);
|
||||
const successDate = useSelector(getSuccessDate);
|
||||
const loadingStatus = useSelector(getLoadingStatus);
|
||||
const { msg: errorMessage } = useSelector(getError);
|
||||
const dispatch = useDispatch();
|
||||
const isStopFetching = currentStage === EXPORT_STAGES.SUCCESS
|
||||
|| loadingStatus === RequestStatus.FAILED
|
||||
|| errorMessage;
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => {
|
||||
if (isStopFetching) {
|
||||
clearInterval(id);
|
||||
} else {
|
||||
dispatch(fetchExportStatus(courseId));
|
||||
}
|
||||
}, 3000);
|
||||
return () => clearInterval(id);
|
||||
});
|
||||
|
||||
let successTitle = intl.formatMessage(messages.stepperSuccessTitle);
|
||||
const formattedSuccessDate = getFormattedSuccessDate(successDate);
|
||||
if (formattedSuccessDate && currentStage === EXPORT_STAGES.SUCCESS) {
|
||||
successTitle += formattedSuccessDate;
|
||||
}
|
||||
const steps = [
|
||||
{
|
||||
title: intl.formatMessage(messages.stepperPreparingTitle),
|
||||
description: intl.formatMessage(messages.stepperPreparingDescription),
|
||||
key: EXPORT_STAGES.PREPARING,
|
||||
}, {
|
||||
title: intl.formatMessage(messages.stepperExportingTitle),
|
||||
description: intl.formatMessage(messages.stepperExportingDescription),
|
||||
key: EXPORT_STAGES.EXPORTING,
|
||||
}, {
|
||||
title: intl.formatMessage(messages.stepperCompressingTitle),
|
||||
description: intl.formatMessage(messages.stepperCompressingDescription),
|
||||
key: EXPORT_STAGES.COMPRESSING,
|
||||
}, {
|
||||
title: successTitle,
|
||||
description: intl.formatMessage(messages.stepperSuccessDescription),
|
||||
key: EXPORT_STAGES.SUCCESS,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mt-4">{intl.formatMessage(messages.stepperHeaderTitle)}</h3>
|
||||
<hr />
|
||||
<CourseStepper
|
||||
courseId={courseId}
|
||||
steps={steps}
|
||||
activeKey={currentStage}
|
||||
errorMessage={errorMessage}
|
||||
hasError={!!errorMessage}
|
||||
/>
|
||||
{downloadPath && currentStage === EXPORT_STAGES.SUCCESS && <Button href={`${getConfig().STUDIO_BASE_URL}${downloadPath}`}>{intl.formatMessage(messages.downloadCourseButtonTitle)}</Button>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ExportStepper.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ExportStepper);
|
||||
3
src/export-page/export-stepper/ExportStepper.scss
Normal file
3
src/export-page/export-stepper/ExportStepper.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.pgn__stepper-header-step-list {
|
||||
flex-direction: column;
|
||||
}
|
||||
38
src/export-page/export-stepper/ExportStepper.test.jsx
Normal file
38
src/export-page/export-stepper/ExportStepper.test.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import initializeStore from '../../store';
|
||||
import messages from './messages';
|
||||
import ExportStepper from './ExportStepper';
|
||||
|
||||
const courseId = 'course-123';
|
||||
let store;
|
||||
|
||||
const RootWrapper = () => (
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
<ExportStepper intl={{ formatMessage: jest.fn() }} courseId={courseId} />
|
||||
</IntlProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
|
||||
describe('<ExportStepper />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
store = initializeStore();
|
||||
});
|
||||
it('render stepper correctly', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
expect(getByText(messages.stepperHeaderTitle.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
46
src/export-page/export-stepper/messages.js
Normal file
46
src/export-page/export-stepper/messages.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
stepperPreparingTitle: {
|
||||
id: 'course-authoring.export.stepper.title.preparing',
|
||||
defaultMessage: 'Preparing',
|
||||
},
|
||||
stepperExportingTitle: {
|
||||
id: 'course-authoring.export.stepper.title.exporting',
|
||||
defaultMessage: 'Exporting',
|
||||
},
|
||||
stepperCompressingTitle: {
|
||||
id: 'course-authoring.export.stepper.title.compressing',
|
||||
defaultMessage: 'Compressing',
|
||||
},
|
||||
stepperSuccessTitle: {
|
||||
id: 'course-authoring.export.stepper.title.success',
|
||||
defaultMessage: 'Success',
|
||||
},
|
||||
stepperPreparingDescription: {
|
||||
id: 'course-authoring.export.stepper.description.preparing',
|
||||
defaultMessage: 'Preparing to start the export',
|
||||
},
|
||||
stepperExportingDescription: {
|
||||
id: 'course-authoring.export.stepper.description.exporting',
|
||||
defaultMessage: 'Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)',
|
||||
},
|
||||
stepperCompressingDescription: {
|
||||
id: 'course-authoring.export.stepper.description.compressing',
|
||||
defaultMessage: 'Compressing the exported data and preparing it for download',
|
||||
},
|
||||
stepperSuccessDescription: {
|
||||
id: 'course-authoring.export.stepper.description.success',
|
||||
defaultMessage: 'Your exported course can now be downloaded',
|
||||
},
|
||||
downloadCourseButtonTitle: {
|
||||
id: 'course-authoring.export.stepper.download.button.title',
|
||||
defaultMessage: 'Download exported course',
|
||||
},
|
||||
stepperHeaderTitle: {
|
||||
id: 'course-authoring.export.stepper.header.title',
|
||||
defaultMessage: 'Course export status',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
34
src/export-page/messages.js
Normal file
34
src/export-page/messages.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
pageTitle: {
|
||||
id: 'course-authoring.export.page.title',
|
||||
defaultMessage: '{headingTitle} | {courseName} | {siteName}',
|
||||
},
|
||||
headingTitle: {
|
||||
id: 'course-authoring.export.heading.title',
|
||||
defaultMessage: 'Course export',
|
||||
},
|
||||
headingSubtitle: {
|
||||
id: 'course-authoring.export.heading.subtitle',
|
||||
defaultMessage: 'Tools',
|
||||
},
|
||||
description1: {
|
||||
id: 'course-authoring.export.description1',
|
||||
defaultMessage: 'You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you\'ve exported.',
|
||||
},
|
||||
description2: {
|
||||
id: 'course-authoring.export.description2',
|
||||
defaultMessage: 'Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.',
|
||||
},
|
||||
titleUnderButton: {
|
||||
id: 'course-authoring.export.title-under-button',
|
||||
defaultMessage: 'Export my course content',
|
||||
},
|
||||
buttonTitle: {
|
||||
id: 'course-authoring.export.button.title',
|
||||
defaultMessage: 'Export course content',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
29
src/export-page/utils.js
Normal file
29
src/export-page/utils.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import Cookies from 'universal-cookie';
|
||||
import moment from 'moment';
|
||||
|
||||
import { TIME_FORMAT } from '../constants';
|
||||
import { LAST_EXPORT_COOKIE_NAME, SUCCESS_DATE_FORMAT } from './data/constants';
|
||||
|
||||
/**
|
||||
* Sets an export-related cookie with the provided information.
|
||||
*
|
||||
* @param {Date} date - Date of export.
|
||||
* @param {boolean} completed - Indicates if export was completed successfully.
|
||||
* @returns {void}
|
||||
*/
|
||||
export const setExportCookie = (date, completed) => {
|
||||
const cookies = new Cookies();
|
||||
cookies.set(LAST_EXPORT_COOKIE_NAME, { date, completed }, { path: window.location.pathname });
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a Unix timestamp as a formatted success date string.
|
||||
*
|
||||
* @param {number} unixDate - Unix timestamp to be formatted.
|
||||
* @returns {string|null} Formatted success date string, including date and time in UTC, or null if the input is falsy.
|
||||
*/
|
||||
export const getFormattedSuccessDate = (unixDate) => {
|
||||
const formattedDate = moment(unixDate).utc().format(SUCCESS_DATE_FORMAT);
|
||||
const formattedTime = moment(unixDate).utc().format(TIME_FORMAT);
|
||||
return unixDate ? ` (${formattedDate} at ${formattedTime} UTC)` : null;
|
||||
};
|
||||
51
src/export-page/utils.test.js
Normal file
51
src/export-page/utils.test.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import Cookies from 'universal-cookie';
|
||||
import moment from 'moment';
|
||||
|
||||
import { LAST_EXPORT_COOKIE_NAME } from './data/constants';
|
||||
import { setExportCookie, getFormattedSuccessDate } from './utils';
|
||||
|
||||
global.window = Object.create(window);
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
pathname: '/some-path',
|
||||
},
|
||||
});
|
||||
|
||||
describe('setExportCookie', () => {
|
||||
it('should set the export cookie with the provided date and completed status', () => {
|
||||
const cookiesSetMock = jest.spyOn(Cookies.prototype, 'set');
|
||||
const date = '2023-07-24';
|
||||
const completed = true;
|
||||
setExportCookie(date, completed);
|
||||
|
||||
expect(cookiesSetMock).toHaveBeenCalledWith(
|
||||
LAST_EXPORT_COOKIE_NAME,
|
||||
{ date, completed },
|
||||
{ path: '/some-path' },
|
||||
);
|
||||
|
||||
cookiesSetMock.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFormattedSuccessDate', () => {
|
||||
it('should return formatted success date with valid input', () => {
|
||||
const mockCurrentUtcDate = moment.utc('2023-07-24T12:34:56');
|
||||
const momentMock = jest.spyOn(moment, 'utc').mockReturnValue(mockCurrentUtcDate);
|
||||
|
||||
const unixDate = 1679787000;
|
||||
|
||||
const expectedFormattedDate = ' (01/20/1970 at 10:36 UTC)';
|
||||
|
||||
const result = getFormattedSuccessDate(unixDate);
|
||||
expect(result).toBe(expectedFormattedDate);
|
||||
|
||||
momentMock.mockRestore();
|
||||
});
|
||||
|
||||
it('should return null with null input', () => {
|
||||
const unixDate = null;
|
||||
const result = getFormattedSuccessDate(unixDate);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
107
src/generic/course-stepper/CourseStepper.test.jsx
Normal file
107
src/generic/course-stepper/CourseStepper.test.jsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import CourseStepper from '.';
|
||||
|
||||
const stepsMock = [
|
||||
{
|
||||
title: 'Preparing',
|
||||
description: 'Preparing to start the export',
|
||||
},
|
||||
{
|
||||
title: 'Exporting',
|
||||
description: 'Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete',
|
||||
},
|
||||
{
|
||||
title: 'Compressing',
|
||||
description: 'Compressing the exported data and preparing it for download',
|
||||
},
|
||||
{
|
||||
title: 'Success',
|
||||
description: 'Your exported course can now be downloaded',
|
||||
},
|
||||
];
|
||||
|
||||
const renderComponent = (props) => render(
|
||||
<IntlProvider locale="en">
|
||||
<CourseStepper steps={stepsMock} {...props} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
describe('<CourseStepper />', () => {
|
||||
it('renders CourseStepper correctly', () => {
|
||||
const {
|
||||
getByText, getByTestId, getAllByTestId, queryByTestId,
|
||||
} = renderComponent({ activeKey: 0 });
|
||||
|
||||
const steps = getAllByTestId('course-stepper__step');
|
||||
expect(steps.length).toBe(stepsMock.length);
|
||||
|
||||
stepsMock.forEach((step) => {
|
||||
expect(getByText(step.title)).toBeInTheDocument();
|
||||
expect(getByText(step.description)).toBeInTheDocument();
|
||||
expect(getByTestId(`${step.title}-icon`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const percentElement = queryByTestId('course-stepper__step-percent');
|
||||
expect(percentElement).toBeNull();
|
||||
});
|
||||
|
||||
it('marks the active and done steps correctly', () => {
|
||||
const activeKey = 1;
|
||||
const { getAllByTestId } = renderComponent({ activeKey });
|
||||
|
||||
const steps = getAllByTestId('course-stepper__step');
|
||||
stepsMock.forEach((_, index) => {
|
||||
const stepElement = steps[index];
|
||||
if (index === activeKey) {
|
||||
expect(stepElement).toHaveClass('active');
|
||||
expect(stepElement).not.toHaveClass('done');
|
||||
}
|
||||
if (index < activeKey) {
|
||||
expect(stepElement).not.toHaveClass('active');
|
||||
expect(stepElement).toHaveClass('done');
|
||||
}
|
||||
if (index > activeKey) {
|
||||
expect(stepElement).not.toHaveClass('active');
|
||||
expect(stepElement).not.toHaveClass('done');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('mark the error step correctly', () => {
|
||||
const { getAllByTestId } = renderComponent({ activeKey: 1, hasError: true });
|
||||
|
||||
const errorStep = getAllByTestId('course-stepper__step')[1];
|
||||
expect(errorStep).toHaveClass('error');
|
||||
});
|
||||
|
||||
it('shows error message for error step', () => {
|
||||
const errorMessage = 'Some error text';
|
||||
const { getAllByTestId } = renderComponent({ activeKey: 1, hasError: true, errorMessage });
|
||||
|
||||
const errorStep = getAllByTestId('course-stepper__step')[1];
|
||||
expect(errorStep).toHaveClass('error');
|
||||
});
|
||||
|
||||
it('shows percentage for active step', () => {
|
||||
const percent = 50;
|
||||
const { getByTestId } = renderComponent({ activeKey: 1, percent });
|
||||
|
||||
const percentElement = getByTestId('course-stepper__step-percent');
|
||||
expect(percentElement).toBeInTheDocument();
|
||||
expect(percentElement).toHaveTextContent(`${percent}%`);
|
||||
});
|
||||
|
||||
it('shows null when steps length equal to zero', () => {
|
||||
const { queryByTestId } = render(
|
||||
<IntlProvider locale="en">
|
||||
<CourseStepper steps={[]} activeKey={0} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
const steps = queryByTestId('[data-testid="course-stepper__step"]');
|
||||
expect(steps).toBe(null);
|
||||
});
|
||||
});
|
||||
68
src/generic/course-stepper/CouseStepper.scss
Normal file
68
src/generic/course-stepper/CouseStepper.scss
Normal file
@@ -0,0 +1,68 @@
|
||||
.course-stepper {
|
||||
.course-stepper__step {
|
||||
display: flex;
|
||||
gap: $spacer;
|
||||
padding: 1.25rem 0;
|
||||
opacity: .5;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
|
||||
.course-stepper__step-icon {
|
||||
position: relative;
|
||||
|
||||
& svg {
|
||||
position: absolute;
|
||||
top: .875rem;
|
||||
left: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.course-stepper__step-info {
|
||||
margin-left: 1.875rem;
|
||||
}
|
||||
|
||||
.course-stepper__step-title {
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
.course-stepper__step-percent {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.course-stepper__step-description {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
color: $gray-400;
|
||||
}
|
||||
}
|
||||
|
||||
.course-stepper__step.active {
|
||||
opacity: 1;
|
||||
|
||||
& svg {
|
||||
animation: rotate 2s infinite linear;
|
||||
}
|
||||
}
|
||||
|
||||
.course-stepper__step.done {
|
||||
opacity: 1;
|
||||
|
||||
& svg,
|
||||
.course-stepper__step-title {
|
||||
color: $success-500;
|
||||
}
|
||||
}
|
||||
|
||||
.course-stepper__step.error {
|
||||
opacity: 1;
|
||||
|
||||
.course-stepper__step-title,
|
||||
.course-stepper__step-description,
|
||||
& svg {
|
||||
color: $danger-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
src/generic/course-stepper/index.jsx
Normal file
114
src/generic/course-stepper/index.jsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import React from 'react';
|
||||
import { injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Settings as SettingsIcon,
|
||||
CheckBoxOutlineBlank as SuccessIcon,
|
||||
LibraryAddCheck as SuccessDoneIcon,
|
||||
Warning as ErrorIcon,
|
||||
} from '@edx/paragon/icons';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const CourseStepper = ({
|
||||
steps,
|
||||
activeKey,
|
||||
percent,
|
||||
hasError,
|
||||
errorMessage,
|
||||
}) => {
|
||||
const getStepperSettings = (index) => {
|
||||
const lastStepIndex = steps.length - 1;
|
||||
const isActiveStep = index === activeKey;
|
||||
const isLastStep = index === lastStepIndex;
|
||||
const isErrorStep = isActiveStep && hasError;
|
||||
const isLastStepDone = isLastStep && isActiveStep;
|
||||
|
||||
const getStepIcon = () => {
|
||||
if (hasError && isActiveStep) {
|
||||
return ErrorIcon;
|
||||
}
|
||||
if (isLastStep && !isActiveStep) {
|
||||
return SuccessIcon;
|
||||
}
|
||||
if (isLastStepDone) {
|
||||
return SuccessDoneIcon;
|
||||
}
|
||||
|
||||
return SettingsIcon;
|
||||
};
|
||||
|
||||
return {
|
||||
stepIcon: getStepIcon(index),
|
||||
isPercentShow: Boolean(percent) && percent !== 100 && isActiveStep && !hasError,
|
||||
isErrorMessageShow: isErrorStep && errorMessage,
|
||||
isActiveClass: isActiveStep && !isLastStep && !hasError,
|
||||
isDoneClass: index < activeKey || isLastStepDone,
|
||||
isErrorClass: isErrorStep,
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="course-stepper">
|
||||
{steps.length ? steps.map(({ title, description }, index) => {
|
||||
const {
|
||||
stepIcon,
|
||||
isPercentShow,
|
||||
isErrorMessageShow,
|
||||
isActiveClass,
|
||||
isDoneClass,
|
||||
isErrorClass,
|
||||
} = getStepperSettings(index);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('course-stepper__step', {
|
||||
active: isActiveClass,
|
||||
done: isDoneClass,
|
||||
error: isErrorClass,
|
||||
})}
|
||||
key={title}
|
||||
data-testid="course-stepper__step"
|
||||
>
|
||||
<div className="course-stepper__step-icon">
|
||||
<Icon src={stepIcon} alt={title} data-testid={`${title}-icon`} />
|
||||
</div>
|
||||
<div className="course-stepper__step-info">
|
||||
<h3 className="h4 title course-stepper__step-title font-weight-600">{title}</h3>
|
||||
{isPercentShow && (
|
||||
<p
|
||||
className="course-stepper__step-percent font-weight-400"
|
||||
data-testid="course-stepper__step-percent"
|
||||
>
|
||||
{percent}%
|
||||
</p>
|
||||
)}
|
||||
<p className="course-stepper__step-description font-weight-400">
|
||||
{isErrorMessageShow ? errorMessage : description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CourseStepper.defaultProps = {
|
||||
percent: false,
|
||||
hasError: false,
|
||||
errorMessage: '',
|
||||
};
|
||||
|
||||
CourseStepper.propTypes = {
|
||||
steps: PropTypes.arrayOf(PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
})).isRequired,
|
||||
activeKey: PropTypes.number.isRequired,
|
||||
percent: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
|
||||
errorMessage: PropTypes.string,
|
||||
hasError: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default injectIntl(CourseStepper);
|
||||
33
src/generic/modal-error/ModalError.jsx
Normal file
33
src/generic/modal-error/ModalError.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ActionRow, AlertModal, Button } from '@edx/paragon';
|
||||
|
||||
const ModalError = ({
|
||||
isOpen, title, message, handleCancel, handleAction, cancelButtonText, actionButtonText,
|
||||
}) => (
|
||||
<AlertModal
|
||||
title={title}
|
||||
isOpen={isOpen}
|
||||
variant="danger"
|
||||
footerNode={(
|
||||
<ActionRow>
|
||||
<Button variant="tertiary" onClick={handleCancel}>{cancelButtonText}</Button>
|
||||
<Button onClick={handleAction}>{actionButtonText}</Button>
|
||||
</ActionRow>
|
||||
)}
|
||||
>
|
||||
<p>{message}</p>
|
||||
</AlertModal>
|
||||
);
|
||||
|
||||
ModalError.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
handleCancel: PropTypes.func.isRequired,
|
||||
handleAction: PropTypes.func.isRequired,
|
||||
cancelButtonText: PropTypes.string.isRequired,
|
||||
actionButtonText: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ModalError;
|
||||
@@ -4,3 +4,4 @@
|
||||
@import "./section-sub-header/SectionSubHeader";
|
||||
@import "./processing-notification/ProccessingNotification";
|
||||
@import "./WysiwygEditor";
|
||||
@import "./course-stepper/CouseStepper";
|
||||
|
||||
@@ -694,5 +694,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -731,5 +731,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -695,5 +695,56 @@
|
||||
"course-authoring.grading-settings.assignment.alert.warning.usage.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.warning.title": "Warning: The number of {type} assignments defined here does not match the current number of {type} assignments in the course:",
|
||||
"course-authoring.grading-settings.assignment.alert.success.title": "The number of {type} assignments in the course matches the number defined here.",
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}"
|
||||
"course-authoring.grading-settings.assignment.type-name.error.message-2": "For grading to work, you must change all {initialAssignmentName} subsections to {value}",
|
||||
"course-authoring.export.footer.exportedData.title": "Data exported with your course:",
|
||||
"course-authoring.export.footer.exportedData.item.1": "Values from Advanced settings, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.footer.exportedData.item.2": "Course content (all sections, sub-sections, and units)",
|
||||
"course-authoring.export.footer.exportedData.item.3": "Course structure",
|
||||
"course-authoring.export.footer.exportedData.item.4": "Individual problems",
|
||||
"course-authoring.export.footer.exportedData.item.5": "Pages",
|
||||
"course-authoring.export.footer.exportedData.item.6": "Course assets",
|
||||
"course-authoring.export.footer.exportedData.item.7": "Course settings",
|
||||
"course-authoring.export.footer.notExportedData.title": "Data not exported with your course:",
|
||||
"course-authoring.export.footer.notExportedData.item.1": "User data",
|
||||
"course-authoring.export.footer.notExportedData.item.2": "Course team data",
|
||||
"course-authoring.export.footer.notExportedData.item.3": "Forum/discussion data",
|
||||
"course-authoring.export.footer.notExportedData.item.4": "Certificates",
|
||||
"course-authoring.export.modal.error.title": "There has been an error while exporting.",
|
||||
"course-authoring.export.modal.error.description.not.unit": "Your course could not be exported to XML. There is not enough information to identify the failed component. Inspect your course to identify any problematic components and try again. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.description.unit": "There has been a failure to export to XML at least one component. It is recommended that you go to the edit page and repair the error before attempting another export. Please check that all components on the page are valid and do not display any error messages. The raw error message is: {errorMessage}",
|
||||
"course-authoring.export.modal.error.button.cancel.unit": "Return to Export",
|
||||
"course-authoring.export.modal.error.button.cancel.not.unit": "Cancel",
|
||||
"course-authoring.export.modal.error.button.action.not.unit": "Take me to the main course page",
|
||||
"course-authoring.export.modal.error.button.action.unit": "Correct failed component",
|
||||
"course-authoring.export.sidebar.title1": "Why export a course?",
|
||||
"course-authoring.export.sidebar.description1": "You may want to edit the XML in your course directly, outside of {studioShortName}. You may want to create a backup copy of your course. Or, you may want to create a copy of your course that you can later import into another course instance and customize.",
|
||||
"course-authoring.export.sidebar.exportedContent": "What content is exported?",
|
||||
"course-authoring.export.sidebar.exportedContentHeading": "The following content is exported.",
|
||||
"course-authoring.export.sidebar.content1": "Course content and structure",
|
||||
"course-authoring.export.sidebar.content2": "Course dates",
|
||||
"course-authoring.export.sidebar.content3": "Grading policy",
|
||||
"course-authoring.export.sidebar.content4": "Any group configurations",
|
||||
"course-authoring.export.sidebar.content5": "Settings on the Advanced settings page, including MATLAB API keys and LTI passports",
|
||||
"course-authoring.export.sidebar.notExportedContent": "The following content is not exported.",
|
||||
"course-authoring.export.sidebar.content6": "Learner-specific content, such as learner grades and discussion forum data",
|
||||
"course-authoring.export.sidebar.content7": "The course team",
|
||||
"course-authoring.export.sidebar.openDownloadFile": "Opening the downloaded file",
|
||||
"course-authoring.export.sidebar.openDownloadFileDescription": "Use an archive program to extract the data from the .tar.gz file. Extracted data includes the course.xml file, as well as subfolders that contain course content.",
|
||||
"course-authoring.export.sidebar.learnMoreButtonTitle": "Learn more about exporting a course",
|
||||
"course-authoring.export.stepper.title.preparing": "Preparing",
|
||||
"course-authoring.export.stepper.title.exporting": "Exporting",
|
||||
"course-authoring.export.stepper.title.compressing": "Compressing",
|
||||
"course-authoring.export.stepper.title.success": "Success",
|
||||
"course-authoring.export.stepper.description.preparing": "Preparing to start the export",
|
||||
"course-authoring.export.stepper.description.exporting": "Creating the export data files (You can now leave this page safely, but avoid making drastic changes to content until this export is complete)",
|
||||
"course-authoring.export.stepper.description.compressing": "Compressing the exported data and preparing it for download",
|
||||
"course-authoring.export.stepper.description.success": "Your exported course can now be downloaded",
|
||||
"course-authoring.export.stepper.download.button.title": "Download exported course",
|
||||
"course-authoring.export.stepper.header.title": "Course import status",
|
||||
"course-authoring.export.heading.title": "Course export",
|
||||
"course-authoring.export.heading.subtitle": "Tools",
|
||||
"course-authoring.export.description1": "You can export courses and edit them outside of {studioShortName}. The exported file is a .tar.gz file (that is, a .tar file compressed with GNU Zip) that contains the course structure and content. You can also re-import courses that you've exported.",
|
||||
"course-authoring.export.description2": "Caution: When you export a course, information such as MATLAB API keys, LTI passports, annotation secret token strings, and annotation storage URLs are included in the exported data. If you share your exported files, you may also be sharing sensitive or license-specific information.",
|
||||
"course-authoring.export.title-under-button": "Export my course content",
|
||||
"course-authoring.export.button.title": "Export course content"
|
||||
}
|
||||
|
||||
@@ -17,3 +17,4 @@
|
||||
@import "pages-and-resources/PagesAndResources";
|
||||
@import "course-team/CourseTeam";
|
||||
@import "course-updates/CourseUpdates";
|
||||
@import "export-page/CourseExportPage";
|
||||
|
||||
@@ -14,6 +14,7 @@ import { reducer as courseTeamReducer } from './course-team/data/slice';
|
||||
import { reducer as CourseUpdatesReducer } from './course-updates/data/slice';
|
||||
import { reducer as processingNotificationReducer } from './generic/processing-notification/data/slice';
|
||||
import { reducer as helpUrlsReducer } from './help-urls/data/slice';
|
||||
import { reducer as courseExportReducer } from './export-page/data/slice';
|
||||
|
||||
export default function initializeStore(preloadedState = undefined) {
|
||||
return configureStore({
|
||||
@@ -32,6 +33,7 @@ export default function initializeStore(preloadedState = undefined) {
|
||||
courseUpdates: CourseUpdatesReducer,
|
||||
processingNotification: processingNotificationReducer,
|
||||
helpUrls: helpUrlsReducer,
|
||||
courseExport: courseExportReducer,
|
||||
},
|
||||
preloadedState,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user