feat: Added Schedule and Details MFE page (#547)
This commit is contained in:
2
.env
2
.env
@@ -34,7 +34,6 @@ ENABLE_NEW_HOME_PAGE = false
|
||||
ENABLE_NEW_COURSE_OUTLINE_PAGE = false
|
||||
ENABLE_NEW_UPDATES_PAGE = false
|
||||
ENABLE_NEW_VIDEO_UPLOAD_PAGE = false
|
||||
ENABLE_NEW_SCHEDULE_DETAILS_PAGE = false
|
||||
ENABLE_NEW_GRADING_PAGE = false
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = false
|
||||
ENABLE_NEW_IMPORT_PAGE = false
|
||||
@@ -45,3 +44,4 @@ BBB_LEARN_MORE_URL=''
|
||||
HOTJAR_APP_ID=''
|
||||
HOTJAR_VERSION=6
|
||||
HOTJAR_DEBUG=false
|
||||
INVITE_STUDENTS_EMAIL_TO=''
|
||||
|
||||
@@ -36,7 +36,6 @@ ENABLE_NEW_HOME_PAGE = false
|
||||
ENABLE_NEW_COURSE_OUTLINE_PAGE = false
|
||||
ENABLE_NEW_UPDATES_PAGE = false
|
||||
ENABLE_NEW_VIDEO_UPLOAD_PAGE = false
|
||||
ENABLE_NEW_SCHEDULE_DETAILS_PAGE = false
|
||||
ENABLE_NEW_GRADING_PAGE = false
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = false
|
||||
ENABLE_NEW_IMPORT_PAGE = false
|
||||
@@ -47,3 +46,4 @@ BBB_LEARN_MORE_URL=''
|
||||
HOTJAR_APP_ID=''
|
||||
HOTJAR_VERSION=6
|
||||
HOTJAR_DEBUG=true
|
||||
INVITE_STUDENTS_EMAIL_TO="someone@domain.com"
|
||||
|
||||
@@ -32,7 +32,6 @@ ENABLE_NEW_HOME_PAGE = false
|
||||
ENABLE_NEW_COURSE_OUTLINE_PAGE = true
|
||||
ENABLE_NEW_UPDATES_PAGE = true
|
||||
ENABLE_NEW_VIDEO_UPLOAD_PAGE = true
|
||||
ENABLE_NEW_SCHEDULE_DETAILS_PAGE = true
|
||||
ENABLE_NEW_GRADING_PAGE = true
|
||||
ENABLE_NEW_COURSE_TEAM_PAGE = true
|
||||
ENABLE_NEW_IMPORT_PAGE = true
|
||||
@@ -40,3 +39,4 @@ ENABLE_NEW_EXPORT_PAGE = true
|
||||
ENABLE_UNIT_PAGE = true
|
||||
ENABLE_VIDEO_UPLOAD_PAGE_LINK_IN_CONTENT_DROPDOWN = true
|
||||
BBB_LEARN_MORE_URL=''
|
||||
INVITE_STUDENTS_EMAIL_TO="someone@domain.com"
|
||||
|
||||
91
package-lock.json
generated
91
package-lock.json
generated
@@ -12,7 +12,7 @@
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
||||
"@edx/frontend-component-footer": "12.0.0",
|
||||
"@edx/frontend-enterprise-hotjar": "^1.2.1",
|
||||
"@edx/frontend-lib-content-components": "^1.163.1",
|
||||
"@edx/frontend-lib-content-components": "^1.167.0",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/paragon": "^20.45.4",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.28",
|
||||
@@ -30,6 +30,7 @@
|
||||
"moment": "2.29.2",
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.14.0",
|
||||
"react-datepicker": "^4.13.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-redux": "7.1.3",
|
||||
@@ -1884,16 +1885,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-html": {
|
||||
"version": "6.1.0",
|
||||
"license": "MIT",
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.4.tgz",
|
||||
"integrity": "sha512-NbrqEp0GUOSvhZbG6BxVcS4SzM4SvN5vkkD2sEoETHIyHLZDb9pO1z+r1L2heb6LuF4bUeBCXKjHXoSeDJHO1w==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
"@codemirror/lang-javascript": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.2.2",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/html": "^1.0.0"
|
||||
"@lezer/css": "^1.1.0",
|
||||
"@lezer/html": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-javascript": {
|
||||
@@ -1951,14 +1955,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.1.1",
|
||||
"license": "MIT"
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz",
|
||||
"integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw=="
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.2.0",
|
||||
"license": "MIT",
|
||||
"version": "6.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.13.2.tgz",
|
||||
"integrity": "sha512-XA/jUuu1H+eTja49654QkrQwx2CuDMdjciHcdqyasfTVo4HRlvj87rD/Qmm4HfnhwX8234FQSSA8HxEzxihX/Q==",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/state": "^6.1.4",
|
||||
"style-mod": "^4.0.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
@@ -2291,9 +2297,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-lib-content-components": {
|
||||
"version": "1.163.1",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-lib-content-components/-/frontend-lib-content-components-1.163.1.tgz",
|
||||
"integrity": "sha512-GrEsEh+AkO+9slCU+PK0I+w2/7OkJS08rRZpuLxNF2g7lv4IC6YcCuyhCSR99lIcTPmqsceKvuiLy8ehpMobDg==",
|
||||
"version": "1.167.0",
|
||||
"resolved": "https://registry.npmjs.org/@edx/frontend-lib-content-components/-/frontend-lib-content-components-1.167.0.tgz",
|
||||
"integrity": "sha512-fISyyUiZhdAkEhYsz8hJOIt5w3vpBAH5J0pf4UpxyzqzpxU6anTI3VIkF3i78yJMZgIQ6Sl4eW75KXqIXAijPw==",
|
||||
"dependencies": {
|
||||
"@codemirror/lang-html": "^6.0.0",
|
||||
"@codemirror/lang-xml": "^6.0.0",
|
||||
@@ -2331,8 +2337,8 @@
|
||||
"@edx/frontend-platform": "^4.0.0",
|
||||
"@edx/paragon": "^20.27.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0"
|
||||
"react": "^16.14.0 || ^17.0.0",
|
||||
"react-dom": "^16.14.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@edx/frontend-lib-content-components/node_modules/@edx/browserslist-config": {
|
||||
@@ -3797,8 +3803,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.2.tgz",
|
||||
"integrity": "sha512-5TKMAReXukfEmIiZprDlGfZVfOOCyEStFi1YLzxclm9H3G/HHI49/2wzlRT6bQw5r7PoZVEtjTItEkb/UuZQyg==",
|
||||
"dependencies": {
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
@@ -3812,8 +3819,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/html": {
|
||||
"version": "1.0.1",
|
||||
"license": "MIT",
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.4.tgz",
|
||||
"integrity": "sha512-HdJYMVZcT4YsMo7lW3ipL4NoyS2T67kMPuSVS5TgLGqmaCjEU/D6xv7zsa1ktvTK5lwk7zzF1e3eU6gBZIPm5g==",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@@ -7662,6 +7670,21 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"dev": true,
|
||||
@@ -17443,6 +17466,23 @@
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.13.0.tgz",
|
||||
"integrity": "sha512-1S8yAqzcHE+LjCjMrTXJfUkTVijTPogxUYrmQmSpmRJ23fdC2w8cg04jzaEAyesTzyUa06JzayZJKk85QHbvcw==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.24.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-onclickoutside": "^6.12.2",
|
||||
"react-popper": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17 || ^18",
|
||||
"react-dom": "^16.9.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dev-utils": {
|
||||
"version": "12.0.1",
|
||||
"dev": true,
|
||||
@@ -17808,6 +17848,19 @@
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-onclickoutside": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz",
|
||||
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.5.x || ^16.x || ^17.x || ^18.x",
|
||||
"react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
|
||||
}
|
||||
},
|
||||
"node_modules/react-overlays": {
|
||||
"version": "5.2.0",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
||||
"@edx/frontend-component-footer": "12.0.0",
|
||||
"@edx/frontend-enterprise-hotjar": "^1.2.1",
|
||||
"@edx/frontend-lib-content-components": "^1.163.1",
|
||||
"@edx/frontend-lib-content-components": "^1.167.0",
|
||||
"@edx/frontend-platform": "4.2.0",
|
||||
"@edx/paragon": "^20.45.4",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.28",
|
||||
@@ -55,6 +55,7 @@
|
||||
"moment": "2.29.2",
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.14.0",
|
||||
"react-datepicker": "^4.13.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-redux": "7.1.3",
|
||||
|
||||
@@ -11,6 +11,7 @@ import VideoSelectorContainer from './selectors/VideoSelectorContainer';
|
||||
import CustomPages from './custom-pages';
|
||||
import FilesAndUploads from './files-and-uploads';
|
||||
import { AdvancedSettings } from './advanced-settings';
|
||||
import ScheduleAndDetails from './schedule-and-details';
|
||||
|
||||
/**
|
||||
* As of this writing, these routes are mounted at a path prefixed with the following:
|
||||
@@ -86,10 +87,7 @@ const CourseAuthoringRoutes = ({ courseId }) => {
|
||||
)}
|
||||
</PageRoute>
|
||||
<PageRoute path={`${path}/settings/details`}>
|
||||
{process.env.ENABLE_NEW_SCHEDULE_DETAILS_PAGE === 'true'
|
||||
&& (
|
||||
<Placeholder />
|
||||
)}
|
||||
<ScheduleAndDetails courseId={courseId} />
|
||||
</PageRoute>
|
||||
<PageRoute path={`${path}/settings/grading`}>
|
||||
{process.env.ENABLE_NEW_GRADING_PAGE === 'true'
|
||||
|
||||
@@ -14,6 +14,17 @@ const videoSelectorContainerMockText = 'Video Selector Container';
|
||||
const customPagesMockText = 'Custom Pages';
|
||||
let store;
|
||||
const mockComponentFn = jest.fn();
|
||||
|
||||
// Mock the TinyMceWidget from frontend-lib-content-components
|
||||
jest.mock('@edx/frontend-lib-content-components', () => ({
|
||||
TinyMceWidget: () => <div>Widget</div>,
|
||||
Footer: () => <div>Footer</div>,
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'),
|
||||
useRouteMatch: () => ({
|
||||
|
||||
@@ -55,6 +55,10 @@ const AdvancedSettings = ({ intl, courseId }) => {
|
||||
},
|
||||
disabledStates: ['pending'],
|
||||
};
|
||||
const {
|
||||
proctoringErrors,
|
||||
mfeProctoredExamSettingsUrl,
|
||||
} = proctoringExamErrors;
|
||||
|
||||
useEffect(() => {
|
||||
if (savingStatus === RequestStatus.SUCCESSFUL) {
|
||||
@@ -123,10 +127,10 @@ const AdvancedSettings = ({ intl, courseId }) => {
|
||||
<>
|
||||
<Container size="xl" className="px-4">
|
||||
<div className="setting-header mt-5">
|
||||
{(proctoringExamErrors?.length > 0) && (
|
||||
{(proctoringErrors?.length > 0) && (
|
||||
<AlertProctoringError
|
||||
icon={Info}
|
||||
proctoringErrorsData={proctoringExamErrors}
|
||||
proctoringErrorsData={proctoringErrors}
|
||||
aria-hidden="true"
|
||||
aria-labelledby={intl.formatMessage(messages.alertProctoringAriaLabelledby)}
|
||||
aria-describedby={intl.formatMessage(messages.alertProctoringDescribedby)}
|
||||
@@ -215,7 +219,10 @@ const AdvancedSettings = ({ intl, courseId }) => {
|
||||
</article>
|
||||
</Layout.Element>
|
||||
<Layout.Element>
|
||||
<SettingsSidebar courseId={courseId} />
|
||||
<SettingsSidebar
|
||||
courseId={courseId}
|
||||
proctoredExamSettingsUrl={mfeProctoredExamSettingsUrl}
|
||||
/>
|
||||
</Layout.Element>
|
||||
</Layout>
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const getLoadingStatus = (state) => state.advancedSettings.loadingStatus;
|
||||
export const getCourseAppSettings = state => state.advancedSettings.courseAppSettings;
|
||||
export const getSavingStatus = (state) => state.advancedSettings.savingStatus;
|
||||
export const getProctoringExamErrors = (state) => state.advancedSettings.proctoringErrors.proctoringErrors;
|
||||
export const getProctoringExamErrors = (state) => state.advancedSettings.proctoringErrors;
|
||||
export const getSendRequestErrors = (state) => state.advancedSettings.sendRequestErrors.developer_message;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Alert } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const SettingAlert = ({
|
||||
title, description, ...props
|
||||
}) => (
|
||||
<Alert {...props}>
|
||||
<Alert.Heading>{title}</Alert.Heading>
|
||||
<p>{description}</p>
|
||||
</Alert>
|
||||
);
|
||||
|
||||
SettingAlert.propTypes = {
|
||||
title: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
};
|
||||
|
||||
SettingAlert.defaultProps = {
|
||||
title: undefined,
|
||||
description: undefined,
|
||||
};
|
||||
|
||||
export default SettingAlert;
|
||||
@@ -1,36 +0,0 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import SettingAlert from './SettingAlert';
|
||||
|
||||
const alertTitle = 'Test Title';
|
||||
const alertDescription = 'Test Description';
|
||||
const alertClassName = 'custom-class';
|
||||
|
||||
const RootWrapper = () => (
|
||||
<IntlProvider locale="en">
|
||||
<SettingAlert
|
||||
title={alertTitle}
|
||||
description={alertDescription}
|
||||
className={alertClassName}
|
||||
/>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
describe('<SettingAlert />', () => {
|
||||
it('renders the title and description correctly', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
const titleElement = getByText(alertTitle);
|
||||
const descriptionElement = getByText(alertDescription);
|
||||
expect(titleElement).toBeInTheDocument();
|
||||
expect(descriptionElement).toBeInTheDocument();
|
||||
});
|
||||
it('renders the alert with additional props', () => {
|
||||
const { getByRole } = render(<RootWrapper />);
|
||||
const alertElement = getByRole('alert');
|
||||
const classNameExists = alertElement.classList.contains(alertClassName);
|
||||
expect(alertElement).toBeInTheDocument();
|
||||
expect(classNameExists).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -1,87 +1,47 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { AppContext } from '@edx/frontend-platform/react';
|
||||
import React from 'react';
|
||||
import {
|
||||
FormattedMessage,
|
||||
injectIntl,
|
||||
intlShape,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Hyperlink } from '@edx/paragon';
|
||||
|
||||
import { getPagePath } from '../../utils';
|
||||
import HelpSidebar from '../../generic/help-sidebar';
|
||||
import messages from './messages';
|
||||
|
||||
const SettingsSidebar = ({ intl, courseId }) => {
|
||||
const { config } = useContext(AppContext);
|
||||
return (
|
||||
<aside className="setting-sidebar-supplementary">
|
||||
<div className="setting-sidebar-supplementary-about">
|
||||
<h4 className="setting-sidebar-supplementary-about-title">{intl.formatMessage(messages.about)}</h4>
|
||||
<p className="setting-sidebar-supplementary-about-descriptions">
|
||||
{intl.formatMessage(messages.aboutDescription1)}
|
||||
</p>
|
||||
<p className="setting-sidebar-supplementary-about-descriptions">
|
||||
{intl.formatMessage(messages.aboutDescription2)}
|
||||
</p>
|
||||
<p className="setting-sidebar-supplementary-about-descriptions">
|
||||
<FormattedMessage
|
||||
id="course-authoring.advanced-settings.about.description-3"
|
||||
defaultMessage="{notice} When you enter strings as policy values, ensure that you use double quotation marks (“) around the string. Do not use single quotation marks (‘)."
|
||||
values={{ notice: <strong>Note:</strong> }}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<hr />
|
||||
<div className="setting-sidebar-supplementary-other">
|
||||
<h4 className="setting-sidebar-supplementary-other-title">{intl.formatMessage(messages.other)}</h4>
|
||||
<nav className="setting-sidebar-supplementary-other-links" aria-label={intl.formatMessage(messages.other)}>
|
||||
<ul className="p-0 mb-0">
|
||||
<li className="setting-sidebar-supplementary-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={getPagePath(courseId, process.env.ENABLE_NEW_SCHEDULE_DETAILS_PAGE, 'settings/details')}
|
||||
>
|
||||
{intl.formatMessage(messages.otherCourseSettingsLinkToScheduleAndDetails)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
<li className="setting-sidebar-supplementary-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={getPagePath(courseId, process.env.ENABLE_NEW_GRADING_PAGE, 'settings/grading')}
|
||||
>
|
||||
{intl.formatMessage(messages.otherCourseSettingsLinkToGrading)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
<li className="setting-sidebar-supplementary-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={getPagePath(courseId, process.env.ENABLE_NEW_COURSE_TEAM_PAGE, 'course_team')}
|
||||
>
|
||||
{intl.formatMessage(messages.otherCourseSettingsLinkToCourseTeam)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
<li className="setting-sidebar-supplementary-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={`${config.STUDIO_BASE_URL}/group_configurations/${courseId}`}
|
||||
>
|
||||
{intl.formatMessage(messages.otherCourseSettingsLinkToGroupConfigurations)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
<li className="setting-sidebar-supplementary-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={`${config.BASE_URL}/course/${courseId}/proctored-exam-settings`}
|
||||
>
|
||||
{intl.formatMessage(messages.otherCourseSettingsLinkToProctoredExamSettings)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
const SettingsSidebar = ({ intl, courseId, proctoredExamSettingsUrl }) => (
|
||||
<HelpSidebar
|
||||
courseId={courseId}
|
||||
proctoredExamSettingsUrl={proctoredExamSettingsUrl}
|
||||
showOtherSettings
|
||||
>
|
||||
<h4 className="help-sidebar-about-title">
|
||||
{intl.formatMessage(messages.about)}
|
||||
</h4>
|
||||
<p className="help-sidebar-about-descriptions">
|
||||
{intl.formatMessage(messages.aboutDescription1)}
|
||||
</p>
|
||||
<p className="help-sidebar-about-descriptions">
|
||||
{intl.formatMessage(messages.aboutDescription2)}
|
||||
</p>
|
||||
<p className="help-sidebar-about-descriptions">
|
||||
<FormattedMessage
|
||||
id="course-authoring.advanced-settings.about.description-3"
|
||||
defaultMessage="{notice} When you enter strings as policy values, ensure that you use double quotation marks (“) around the string. Do not use single quotation marks (‘)."
|
||||
values={{ notice: <strong>Note:</strong> }}
|
||||
/>
|
||||
</p>
|
||||
</HelpSidebar>
|
||||
);
|
||||
|
||||
SettingsSidebar.defaultProps = {
|
||||
proctoredExamSettingsUrl: '',
|
||||
};
|
||||
|
||||
SettingsSidebar.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
proctoredExamSettingsUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
export default injectIntl(SettingsSidebar);
|
||||
|
||||
81
src/assets/scss/_form.scss
Normal file
81
src/assets/scss/_form.scss
Normal file
@@ -0,0 +1,81 @@
|
||||
.form-group-custom {
|
||||
.pgn__form-label {
|
||||
font: normal $font-weight-bold .75rem/1.25rem $font-family-base;
|
||||
color: $gray-500;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.pgn__form-control-description,
|
||||
.pgn__form-text {
|
||||
font: normal $font-weight-normal .75rem/1.25rem $font-family-base;
|
||||
color: $gray-500;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.form-group-custom_isInvalid {
|
||||
input {
|
||||
border-color: $form-feedback-invalid-color;
|
||||
}
|
||||
}
|
||||
|
||||
.feedback-error {
|
||||
color: $form-feedback-invalid-color;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-custom {
|
||||
margin: 0;
|
||||
|
||||
.datepicker-custom-control {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: $input-font-size;
|
||||
font-weight: $input-font-weight;
|
||||
line-height: $input-line-height;
|
||||
background: $input-bg;
|
||||
border-color: $input-border-color;
|
||||
border-width: $input-border-width;
|
||||
box-shadow: $input-box-shadow;
|
||||
border-radius: $input-border-radius;
|
||||
color: $input-color;
|
||||
padding: $input-padding-y $input-padding-x;
|
||||
height: $input-height;
|
||||
resize: none;
|
||||
|
||||
&:focus,
|
||||
:focus-visible {
|
||||
color: $input-focus-color;
|
||||
background-color: $input-bg;
|
||||
border-color: $input-focus-border-color;
|
||||
box-shadow: $input-focus-box-shadow;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: $input-placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-custom-control_readonly {
|
||||
border-color: transparent;
|
||||
background: $input-disabled-bg;
|
||||
}
|
||||
|
||||
.datepicker-custom-control_isInvalid {
|
||||
border-color: $form-feedback-invalid-color;
|
||||
}
|
||||
|
||||
.datepicker-custom-control-icon {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
right: 1.188rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
3
src/assets/scss/_utilities.scss
Normal file
3
src/assets/scss/_utilities.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.text-black {
|
||||
color: $black;
|
||||
}
|
||||
8
src/constants.js
Normal file
8
src/constants.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export const DATE_FORMAT = 'MM/dd/yyyy';
|
||||
export const TIME_FORMAT = 'HH:mm';
|
||||
export const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm:ss\\Z';
|
||||
export const DEFAULT_EMPTY_WYSIWYG_VALUE = '<p> </p>';
|
||||
export const STATEFUL_BUTTON_STATES = {
|
||||
pending: 'pending',
|
||||
default: 'default',
|
||||
};
|
||||
3
src/generic/ApplyWrapper.jsx
Normal file
3
src/generic/ApplyWrapper.jsx
Normal file
@@ -0,0 +1,3 @@
|
||||
const ApplyWrapper = ({ condition, wrapper, children }) => (condition ? wrapper(children) : children);
|
||||
|
||||
export default ApplyWrapper;
|
||||
94
src/generic/WysiwygEditor.jsx
Normal file
94
src/generic/WysiwygEditor.jsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { createStore } from 'redux';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import {
|
||||
prepareEditorRef,
|
||||
TinyMceWidget,
|
||||
} from '@edx/frontend-lib-content-components';
|
||||
|
||||
import { DEFAULT_EMPTY_WYSIWYG_VALUE } from '../constants';
|
||||
|
||||
const store = createStore(() => ({}));
|
||||
|
||||
export const SUPPORTED_TEXT_EDITORS = {
|
||||
text: 'text',
|
||||
expandable: 'expandable',
|
||||
};
|
||||
|
||||
const mapStateToProps = () => ({
|
||||
assets: {},
|
||||
lmsEndpointUrl: getConfig().LMS_BASE_URL,
|
||||
studioEndpointUrl: getConfig().STUDIO_BASE_URL,
|
||||
isLibrary: true,
|
||||
onEditorChange: () => ({}),
|
||||
});
|
||||
|
||||
const Editor = connect(mapStateToProps)(TinyMceWidget);
|
||||
|
||||
export const WysiwygEditor = ({
|
||||
initialValue, editorType, onChange, minHeight,
|
||||
}) => {
|
||||
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
|
||||
|
||||
const isEquivalentCodeExtraSpaces = (first, second) => {
|
||||
// Utils allows to compare code extra spaces
|
||||
const removeWhitespace = (str) => str.replace(/\s/g, '');
|
||||
return removeWhitespace(first) === removeWhitespace(second);
|
||||
};
|
||||
|
||||
const isEquivalentCodeQuotes = (first, second) => {
|
||||
// Utils allows to compare code with single quotes and double quotes
|
||||
const normalizeQuotes = (section) => section.replace(/'/g, '"');
|
||||
return normalizeQuotes(first) === normalizeQuotes(second);
|
||||
};
|
||||
|
||||
// default initial string returned onEditorChange if empty input
|
||||
const needToChange = (value) => !isEquivalentCodeQuotes(initialValue, value)
|
||||
&& !isEquivalentCodeExtraSpaces(initialValue, value)
|
||||
&& (initialValue !== DEFAULT_EMPTY_WYSIWYG_VALUE || value !== '');
|
||||
|
||||
const handleUpdate = (value, editor) => {
|
||||
// With bookmarks keep the current cursor position at the end of the line
|
||||
// and it inserts new content only at the end of the line.
|
||||
const bm = editor.selection.getBookmark();
|
||||
const existingContent = editor.getContent({ format: 'raw' });
|
||||
if (needToChange(value)) { onChange(value); }
|
||||
editor.setContent(existingContent);
|
||||
editor.selection.moveToBookmark(bm);
|
||||
};
|
||||
|
||||
if (!refReady) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<Editor
|
||||
textValue={initialValue}
|
||||
editorRef={editorRef}
|
||||
editorType={editorType}
|
||||
initialValue={initialValue}
|
||||
minHeight={minHeight}
|
||||
editorContentHtml={initialValue}
|
||||
setEditorRef={setEditorRef}
|
||||
updateContent={handleUpdate}
|
||||
initializeEditor={() => ({})}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
WysiwygEditor.defaultProps = {
|
||||
initialValue: '',
|
||||
editorType: SUPPORTED_TEXT_EDITORS.text,
|
||||
minHeight: 200,
|
||||
};
|
||||
|
||||
WysiwygEditor.propTypes = {
|
||||
initialValue: PropTypes.string,
|
||||
editorType: PropTypes.oneOf(Object.values(SUPPORTED_TEXT_EDITORS)),
|
||||
onChange: PropTypes.func.isRequired,
|
||||
minHeight: PropTypes.number,
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import SettingAlert from '.';
|
||||
import AlertMessage from '.';
|
||||
|
||||
const alertTitle = 'Test Title';
|
||||
const alertDescription = 'Test Description';
|
||||
@@ -10,7 +10,7 @@ const alertClassName = 'custom-class';
|
||||
|
||||
const RootWrapper = () => (
|
||||
<IntlProvider locale="en">
|
||||
<SettingAlert
|
||||
<AlertMessage
|
||||
title={alertTitle}
|
||||
description={alertDescription}
|
||||
className={alertClassName}
|
||||
@@ -18,7 +18,7 @@ const RootWrapper = () => (
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
describe('<SettingAlert />', () => {
|
||||
describe('<AlertMessage />', () => {
|
||||
it('renders the title and description correctly', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
const titleElement = getByText(alertTitle);
|
||||
|
||||
26
src/generic/course-upload-image/CourseUploadImage.scss
Normal file
26
src/generic/course-upload-image/CourseUploadImage.scss
Normal file
@@ -0,0 +1,26 @@
|
||||
.image-preview {
|
||||
@include pgn-box-shadow(1, "down");
|
||||
|
||||
display: block;
|
||||
width: 23.4375rem;
|
||||
height: 12.5rem;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border: .0625rem solid $gray-300;
|
||||
padding: .625rem;
|
||||
background: $white;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.image-body {
|
||||
text-align: center;
|
||||
|
||||
.pgn__dropzone {
|
||||
background: $white;
|
||||
}
|
||||
}
|
||||
83
src/generic/course-upload-image/CourseUploadImage.test.jsx
Normal file
83
src/generic/course-upload-image/CourseUploadImage.test.jsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { fireEvent, render, act } from '@testing-library/react';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import initializeStore from '../../store';
|
||||
import messages from './messages';
|
||||
import CourseUploadImage from '.';
|
||||
|
||||
let store;
|
||||
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<AppProvider store={store}>
|
||||
<CourseUploadImage {...props} />
|
||||
</AppProvider>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
label: 'foo-label-field',
|
||||
customHelpText: 'custom-help-text',
|
||||
assetImagePath: '/asset-v1:edX+M12+2T2023+type@asset+block@image_1.png',
|
||||
imageNameField: 'cardImageName',
|
||||
assetImageField: 'cardImageAssetPath',
|
||||
identifierFieldText: 'some identified field',
|
||||
showImageBodyText: true,
|
||||
customInputPlaceholder: 'custom-input-placeholder',
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<CourseUploadImage />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
});
|
||||
|
||||
it('renders successfully', () => {
|
||||
const { getByText, getByPlaceholderText } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
expect(getByText(props.label)).toBeInTheDocument();
|
||||
expect(getByText(props.customHelpText)).toBeInTheDocument();
|
||||
expect(getByPlaceholderText(props.customInputPlaceholder)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', async () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(props.customInputPlaceholder);
|
||||
await act(() => {
|
||||
fireEvent.change(input, { target: { value: '/assets' } });
|
||||
});
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
'/assets',
|
||||
props.assetImageField,
|
||||
);
|
||||
});
|
||||
|
||||
it('should change body text if input cleared', () => {
|
||||
const initialProps = { ...props, assetImagePath: '' };
|
||||
const { getByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(
|
||||
getByText(messages.uploadImageEmpty.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide body text if showImageBodyText disabled', () => {
|
||||
const initialProps = { ...props, showImageBodyText: false };
|
||||
const { queryAllByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(queryAllByText(messages.uploadImageEmpty.defaultMessage).length).toBe(0);
|
||||
expect(queryAllByText(messages.uploadImageBodyFilled.defaultMessage).length).toBe(0);
|
||||
});
|
||||
});
|
||||
21
src/generic/course-upload-image/data/api.js
Normal file
21
src/generic/course-upload-image/data/api.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
export const getUploadAssetsUrl = (courseId) => new URL(
|
||||
`/assets/${courseId}/`,
|
||||
getConfig().STUDIO_BASE_URL,
|
||||
);
|
||||
|
||||
/**
|
||||
* Upload assets.
|
||||
* @param {string} courseId
|
||||
* @param {binary} formData
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function uploadAssets(courseId, fileData) {
|
||||
const { data } = await getAuthenticatedHttpClient().post(
|
||||
`${getUploadAssetsUrl(courseId).href}`,
|
||||
fileData,
|
||||
);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
167
src/generic/course-upload-image/index.jsx
Normal file
167
src/generic/course-upload-image/index.jsx
Normal file
@@ -0,0 +1,167 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import _ from 'lodash';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { FileUpload as FileUploadIcon } from '@edx/paragon/icons';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import {
|
||||
Form,
|
||||
Dropzone,
|
||||
Image,
|
||||
Hyperlink,
|
||||
Card,
|
||||
Icon,
|
||||
IconButton,
|
||||
} from '@edx/paragon';
|
||||
|
||||
import { uploadAssets } from './data/api';
|
||||
import messages from './messages';
|
||||
|
||||
const CourseUploadImage = ({
|
||||
label,
|
||||
customHelpText,
|
||||
assetImagePath,
|
||||
imageNameField,
|
||||
assetImageField,
|
||||
identifierFieldText,
|
||||
showImageBodyText,
|
||||
customInputPlaceholder,
|
||||
onChange,
|
||||
}) => {
|
||||
const { courseId } = useParams();
|
||||
const intl = useIntl();
|
||||
const imageAbsolutePath = new URL(assetImagePath, getConfig().LMS_BASE_URL);
|
||||
const assetsUrl = new URL(`/assets/${courseId}`, getConfig().STUDIO_BASE_URL);
|
||||
|
||||
const handleChangeImageAsset = (path) => {
|
||||
const assetPath = _.last(path.split('/'));
|
||||
// If image path is entered directly, we need to strip the asset prefix
|
||||
const imageName = _.last(assetPath.split('block@'));
|
||||
onChange(path, assetImageField);
|
||||
if (imageNameField) {
|
||||
onChange(imageName, imageNameField);
|
||||
}
|
||||
};
|
||||
|
||||
const handleProcessUpload = async ({ fileData, handleError }) => {
|
||||
try {
|
||||
const response = await uploadAssets(courseId, fileData);
|
||||
const url = response?.asset?.url;
|
||||
if (url) {
|
||||
handleChangeImageAsset(url);
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
}
|
||||
};
|
||||
|
||||
const inputComponent = assetImagePath ? (
|
||||
<div className="image-preview">
|
||||
<Image
|
||||
src={imageAbsolutePath.href}
|
||||
alt={intl.formatMessage(messages.uploadImageDropzoneAlt)}
|
||||
fluid
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<IconButton
|
||||
isActive
|
||||
src={FileUploadIcon}
|
||||
iconAs={Icon}
|
||||
variant="secondary"
|
||||
alt={intl.formatMessage(messages.uploadImageDropzoneAlt)}
|
||||
/>
|
||||
<p>
|
||||
{intl.formatMessage(messages.uploadImageDropzoneText, {
|
||||
identifierFieldText,
|
||||
})}
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
|
||||
const cardImageTextBody = assetImagePath ? (
|
||||
<span className="x-small text-gray-700">
|
||||
<FormattedMessage
|
||||
{...messages.uploadImageBodyFilled}
|
||||
values={{
|
||||
hyperlink: (
|
||||
<Hyperlink
|
||||
destination={assetsUrl.href}
|
||||
target="_blank"
|
||||
showLaunchIcon={false}
|
||||
>
|
||||
{intl.formatMessage(messages.uploadImageFilesAndUploads)}
|
||||
</Hyperlink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
) : (
|
||||
<span className="x-small text-gray-700">
|
||||
{intl.formatMessage(messages.uploadImageEmpty)}
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<Form.Group className="form-group-custom w-100">
|
||||
<Form.Label>{label}</Form.Label>
|
||||
<Card>
|
||||
<Card.Body className="image-body">
|
||||
<Dropzone
|
||||
onProcessUpload={handleProcessUpload}
|
||||
inputComponent={inputComponent}
|
||||
accept={{
|
||||
'image/*': ['.png', '.jpeg'],
|
||||
}}
|
||||
/>
|
||||
{showImageBodyText && cardImageTextBody}
|
||||
</Card.Body>
|
||||
<Card.Divider />
|
||||
<Card.Footer className="p-2.5">
|
||||
<Form.Control
|
||||
value={assetImagePath}
|
||||
onChange={(e) => handleChangeImageAsset(e.target.value)}
|
||||
placeholder={
|
||||
customInputPlaceholder
|
||||
|| intl.formatMessage(messages.uploadImageInputPlaceholder, {
|
||||
identifierFieldText,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
<Form.Control.Feedback>
|
||||
{customHelpText
|
||||
|| intl.formatMessage(messages.uploadImageHelpText, {
|
||||
identifierFieldText,
|
||||
})}
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
);
|
||||
};
|
||||
|
||||
CourseUploadImage.defaultProps = {
|
||||
assetImagePath: '',
|
||||
customHelpText: '',
|
||||
imageNameField: '',
|
||||
assetImageField: '',
|
||||
showImageBodyText: false,
|
||||
identifierFieldText: '',
|
||||
customInputPlaceholder: '',
|
||||
};
|
||||
|
||||
CourseUploadImage.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
assetImagePath: PropTypes.string,
|
||||
customHelpText: PropTypes.string,
|
||||
imageNameField: PropTypes.string,
|
||||
assetImageField: PropTypes.string,
|
||||
showImageBodyText: PropTypes.bool,
|
||||
identifierFieldText: PropTypes.string,
|
||||
customInputPlaceholder: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default CourseUploadImage;
|
||||
38
src/generic/course-upload-image/messages.js
Normal file
38
src/generic/course-upload-image/messages.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
uploadImageHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.help-text',
|
||||
defaultMessage: 'Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)',
|
||||
},
|
||||
uploadImageFilesAndUploads: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.file-and-uploads',
|
||||
defaultMessage: 'files and uploads',
|
||||
},
|
||||
uploadImageDropzoneText: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.dropzone-text',
|
||||
defaultMessage: 'Drag and drop your {identifierFieldText} here or click to upload.',
|
||||
},
|
||||
uploadImageDropzoneAlt: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.dropzone-alt',
|
||||
defaultMessage: 'Uploaded image for course',
|
||||
},
|
||||
uploadImageEmpty: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.empty',
|
||||
defaultMessage: 'Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)',
|
||||
},
|
||||
uploadImageIconAlt: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.icon-alt',
|
||||
defaultMessage: 'File upload icon',
|
||||
},
|
||||
uploadImageBodyFilled: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.manage',
|
||||
defaultMessage: 'You can manage this image along with all of your other {hyperlink}',
|
||||
},
|
||||
uploadImageInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.introducing.upload-image.input.placeholder',
|
||||
defaultMessage: 'Your {identifierFieldText} URL',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
102
src/generic/datepicker-control/DatepickerControl.jsx
Normal file
102
src/generic/datepicker-control/DatepickerControl.jsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React from 'react';
|
||||
import DatePicker from 'react-datepicker/dist';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { Form, Icon } from '@edx/paragon';
|
||||
import { Calendar } from '@edx/paragon/icons';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { convertToDateFromString, convertToStringFromDate, isValidDate } from '../../utils';
|
||||
import { DATE_FORMAT, TIME_FORMAT } from '../../constants';
|
||||
import messages from './messages';
|
||||
|
||||
export const DATEPICKER_TYPES = {
|
||||
date: 'date',
|
||||
time: 'time',
|
||||
};
|
||||
|
||||
const DatepickerControl = ({
|
||||
type,
|
||||
label,
|
||||
value,
|
||||
showUTC,
|
||||
readonly,
|
||||
helpText,
|
||||
isInvalid,
|
||||
controlName,
|
||||
onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const formattedDate = convertToDateFromString(value);
|
||||
const inputFormat = {
|
||||
[DATEPICKER_TYPES.date]: DATE_FORMAT,
|
||||
[DATEPICKER_TYPES.time]: TIME_FORMAT,
|
||||
};
|
||||
|
||||
return (
|
||||
<Form.Group className="form-group-custom datepicker-custom">
|
||||
<Form.Label className="d-flex justify-content-between">
|
||||
{label}
|
||||
{showUTC && (
|
||||
<span className="h6 font-weight-normal text-gray-500 mb-0">
|
||||
({intl.formatMessage(messages.datepickerUTC)})
|
||||
</span>
|
||||
)}
|
||||
</Form.Label>
|
||||
<div className="position-relative">
|
||||
{type === DATEPICKER_TYPES.date && !readonly && (
|
||||
<Icon
|
||||
src={Calendar}
|
||||
className="datepicker-custom-control-icon"
|
||||
alt={intl.formatMessage(messages.calendarAltText)}
|
||||
/>
|
||||
)}
|
||||
<DatePicker
|
||||
name={controlName}
|
||||
selected={formattedDate}
|
||||
disabled={readonly}
|
||||
dateFormat={inputFormat[type]}
|
||||
timeFormat={inputFormat[type]}
|
||||
className={classNames('datepicker-custom-control', {
|
||||
'datepicker-custom-control_readonly': readonly,
|
||||
'datepicker-custom-control_isInvalid': isInvalid,
|
||||
})}
|
||||
autoComplete="off"
|
||||
selectsStart
|
||||
showTimeSelect={type === DATEPICKER_TYPES.time}
|
||||
showTimeSelectOnly={type === DATEPICKER_TYPES.time}
|
||||
placeholderText={inputFormat[type].toLocaleUpperCase()}
|
||||
showPopperArrow={false}
|
||||
onChange={(date) => {
|
||||
if (isValidDate(date)) {
|
||||
onChange(convertToStringFromDate(date));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{helpText && <Form.Control.Feedback>{helpText}</Form.Control.Feedback>}
|
||||
</Form.Group>
|
||||
);
|
||||
};
|
||||
|
||||
DatepickerControl.defaultProps = {
|
||||
helpText: '',
|
||||
showUTC: false,
|
||||
value: '',
|
||||
readonly: false,
|
||||
isInvalid: false,
|
||||
};
|
||||
|
||||
DatepickerControl.propTypes = {
|
||||
type: PropTypes.oneOf(Object.values(DATEPICKER_TYPES)).isRequired,
|
||||
value: PropTypes.string,
|
||||
label: PropTypes.string.isRequired,
|
||||
showUTC: PropTypes.bool,
|
||||
helpText: PropTypes.string,
|
||||
readonly: PropTypes.bool,
|
||||
isInvalid: PropTypes.bool,
|
||||
controlName: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default DatepickerControl;
|
||||
51
src/generic/datepicker-control/DatepickerControl.test.jsx
Normal file
51
src/generic/datepicker-control/DatepickerControl.test.jsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { convertToStringFromDate } from '../../utils';
|
||||
import { DatepickerControl, DATEPICKER_TYPES } from '.';
|
||||
import messages from './messages';
|
||||
import { DATE_FORMAT } from '../../constants';
|
||||
|
||||
describe('<DatepickerControl />', () => {
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<DatepickerControl {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
intl: {},
|
||||
type: DATEPICKER_TYPES.date,
|
||||
label: 'fooLabel',
|
||||
value: '',
|
||||
showUTC: false,
|
||||
readonly: false,
|
||||
helpText: 'barHelpText',
|
||||
isInvalid: false,
|
||||
controlName: 'fooControlName',
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const { getByText, queryAllByText, getByPlaceholderText } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
expect(getByText(props.label)).toBeInTheDocument();
|
||||
expect(getByText(props.helpText)).toBeInTheDocument();
|
||||
expect(queryAllByText(messages.datepickerUTC.defaultMessage).length).toBe(0);
|
||||
expect(
|
||||
getByPlaceholderText(DATE_FORMAT.toLocaleUpperCase()),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onChange on datepicker input change', () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(DATE_FORMAT.toLocaleUpperCase());
|
||||
fireEvent.change(input, { target: { value: '06/16/2023' } });
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
convertToStringFromDate('06/16/2023'),
|
||||
);
|
||||
});
|
||||
});
|
||||
2
src/generic/datepicker-control/index.js
Normal file
2
src/generic/datepicker-control/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as DatepickerControl } from './DatepickerControl';
|
||||
export { DATEPICKER_TYPES } from './DatepickerControl';
|
||||
14
src/generic/datepicker-control/messages.js
Normal file
14
src/generic/datepicker-control/messages.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
calendarAltText: {
|
||||
id: 'course-authoring.schedule.schedule-section.alt-text',
|
||||
defaultMessage: 'Calendar for datepicker input',
|
||||
},
|
||||
datepickerUTC: {
|
||||
id: 'course-authoring.schedule.schedule-section.datepicker.utc',
|
||||
defaultMessage: 'UTC',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -11,17 +11,14 @@
|
||||
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
|
||||
color: $text-color-base;
|
||||
}
|
||||
|
||||
.help-sidebar-about-link {
|
||||
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
|
||||
}
|
||||
}
|
||||
|
||||
.help-sidebar-other-links ul {
|
||||
list-style: none;
|
||||
|
||||
.help-sidebar-other-link {
|
||||
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
|
||||
line-height: 1.5rem;
|
||||
color: $info-500;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.help-sidebar-other-title {
|
||||
@@ -29,4 +26,11 @@
|
||||
color: $black;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.sidebar-link {
|
||||
font: normal $font-weight-normal .875rem/1.5rem $font-family-base;
|
||||
line-height: 1.5rem;
|
||||
color: $info-500;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,31 +14,51 @@ jest.mock('react-router-dom', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const RootWrapper = () => (
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<HelpSidebar
|
||||
courseId="course123"
|
||||
showOtherSettings
|
||||
proctoredExamSettingsUrl=""
|
||||
>
|
||||
<HelpSidebar {...props}>
|
||||
<p>Test children</p>
|
||||
</HelpSidebar>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
courseId: 'course123',
|
||||
showOtherSettings: true,
|
||||
proctoredExamSettingsUrl: '',
|
||||
};
|
||||
|
||||
describe('HelpSidebar', () => {
|
||||
it('renders children correctly', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
const { getByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText('Test children')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render all sidebar links with correct text', () => {
|
||||
const { getByText } = render(<RootWrapper />);
|
||||
const { getByText, queryByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.sidebarTitleOther.defaultMessage)).toBeTruthy();
|
||||
expect(getByText(messages.sidebarLinkToScheduleAndDetails.defaultMessage)).toBeTruthy();
|
||||
expect(getByText(messages.sidebarLinkToGrading.defaultMessage)).toBeTruthy();
|
||||
expect(getByText(messages.sidebarLinkToCourseTeam.defaultMessage)).toBeTruthy();
|
||||
expect(getByText(messages.sidebarLinkToGroupConfigurations.defaultMessage)).toBeTruthy();
|
||||
expect(getByText(messages.sidebarLinkToAdvancedSettings.defaultMessage)).toBeTruthy();
|
||||
expect(queryByText(messages.sidebarLinkToProctoredExamSettings.defaultMessage)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should hide other settings url if showOtherSettings disabled', () => {
|
||||
const initialProps = { ...props, showOtherSettings: false };
|
||||
const { queryByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(queryByText(messages.sidebarTitleOther.defaultMessage)).toBeFalsy();
|
||||
expect(queryByText(messages.sidebarLinkToScheduleAndDetails.defaultMessage)).toBeFalsy();
|
||||
expect(queryByText(messages.sidebarLinkToGrading.defaultMessage)).toBeFalsy();
|
||||
expect(queryByText(messages.sidebarLinkToCourseTeam.defaultMessage)).toBeFalsy();
|
||||
expect(queryByText(messages.sidebarLinkToGroupConfigurations.defaultMessage)).toBeFalsy();
|
||||
expect(queryByText(messages.sidebarLinkToAdvancedSettings.defaultMessage)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should render proctored mfe url only if passed not empty value', () => {
|
||||
const initialProps = { ...props, proctoredExamSettingsUrl: 'http:/link-to' };
|
||||
const { getByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(getByText(messages.sidebarLinkToProctoredExamSettings.defaultMessage)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
26
src/generic/help-sidebar/HelpSidebarLink.jsx
Normal file
26
src/generic/help-sidebar/HelpSidebarLink.jsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Hyperlink } from '@edx/paragon';
|
||||
|
||||
const HelpSidebarLink = ({ as, pathToPage, title }) => {
|
||||
const TagElement = as;
|
||||
return (
|
||||
<TagElement className="sidebar-link">
|
||||
<Hyperlink destination={pathToPage}>
|
||||
{title}
|
||||
</Hyperlink>
|
||||
</TagElement>
|
||||
);
|
||||
};
|
||||
|
||||
HelpSidebarLink.propTypes = {
|
||||
pathToPage: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
as: PropTypes.string,
|
||||
};
|
||||
|
||||
HelpSidebarLink.defaultProps = {
|
||||
as: 'li',
|
||||
};
|
||||
|
||||
export default HelpSidebarLink;
|
||||
9
src/generic/help-sidebar/constants.js
Normal file
9
src/generic/help-sidebar/constants.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const otherLinkURLParams = {
|
||||
scheduleAndDetails: 'settings/details',
|
||||
grading: 'settings/grading',
|
||||
courseTeam: 'course_team',
|
||||
advancedSettings: 'settings/advanced',
|
||||
groupConfigurations: 'group_configurations',
|
||||
proctoredExamSettings: 'proctored-exam-settings',
|
||||
};
|
||||
@@ -4,9 +4,9 @@ import { useLocation } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { Hyperlink } from '@edx/paragon';
|
||||
|
||||
import { getPagePath } from '../../utils';
|
||||
import HelpSidebarLink from './HelpSidebarLink';
|
||||
import { otherLinkURLParams } from './constants';
|
||||
import messages from './messages';
|
||||
|
||||
const HelpSidebar = ({
|
||||
@@ -18,34 +18,25 @@ const HelpSidebar = ({
|
||||
className,
|
||||
}) => {
|
||||
const { pathname } = useLocation();
|
||||
const scheduleAndDetailsDestination = getPagePath(
|
||||
courseId,
|
||||
process.env.ENABLE_NEW_SCHEDULE_DETAILS_PAGE,
|
||||
'settings/details',
|
||||
);
|
||||
const gradingDestination = getPagePath(
|
||||
courseId,
|
||||
process.env.ENABLE_NEW_GRADING_PAGE,
|
||||
'settings/grading',
|
||||
);
|
||||
const courseTeamDestination = getPagePath(
|
||||
courseId,
|
||||
process.env.ENABLE_NEW_COURSE_TEAM_PAGE,
|
||||
'course_team',
|
||||
);
|
||||
const advancedSettingsDestination = getPagePath(
|
||||
courseId,
|
||||
process.env.ENABLE_NEW_ADVANCED_SETTINGS_PAGE,
|
||||
'settings/advanced',
|
||||
);
|
||||
const groupConfigurationsDestination = new URL(
|
||||
`/group_configurations/${courseId}`,
|
||||
getConfig().STUDIO_BASE_URL,
|
||||
);
|
||||
const proctoredExamSettingsDestination = new URL(
|
||||
`/course/${courseId}/proctored-exam-settings`,
|
||||
getConfig().BASE_URL,
|
||||
);
|
||||
const {
|
||||
grading,
|
||||
courseTeam,
|
||||
advancedSettings,
|
||||
scheduleAndDetails,
|
||||
groupConfigurations,
|
||||
} = otherLinkURLParams;
|
||||
|
||||
const showOtherLink = (params) => !pathname.includes(params);
|
||||
const generateLegacyURL = (urlParameter) => {
|
||||
const referObj = new URL(`${urlParameter}/${courseId}`, getConfig().STUDIO_BASE_URL);
|
||||
return referObj.href;
|
||||
};
|
||||
|
||||
const scheduleAndDetailsDestination = generateLegacyURL(scheduleAndDetails);
|
||||
const gradingDestination = generateLegacyURL(grading);
|
||||
const courseTeamDestination = generateLegacyURL(courseTeam);
|
||||
const advancedSettingsDestination = generateLegacyURL(advancedSettings);
|
||||
const groupConfigurationsDestination = generateLegacyURL(groupConfigurations);
|
||||
|
||||
return (
|
||||
<aside className={classNames('help-sidebar', className)}>
|
||||
@@ -61,73 +52,47 @@ const HelpSidebar = ({
|
||||
aria-label={intl.formatMessage(messages.sidebarTitleOther)}
|
||||
>
|
||||
<ul className="p-0 mb-0">
|
||||
{!scheduleAndDetailsDestination.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink destination={scheduleAndDetailsDestination}>
|
||||
{intl.formatMessage(
|
||||
messages.sidebarLinkToScheduleAndDetails,
|
||||
)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{showOtherLink(scheduleAndDetails) && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={scheduleAndDetailsDestination}
|
||||
title={intl.formatMessage(
|
||||
messages.sidebarLinkToScheduleAndDetails,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{!gradingDestination.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink rel="noopener" destination={gradingDestination}>
|
||||
{intl.formatMessage(messages.sidebarLinkToGrading)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{showOtherLink(grading) && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={gradingDestination}
|
||||
title={intl.formatMessage(messages.sidebarLinkToGrading)}
|
||||
/>
|
||||
)}
|
||||
{!courseTeamDestination.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink rel="noopener" destination={courseTeamDestination}>
|
||||
{intl.formatMessage(messages.sidebarLinkToCourseTeam)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{showOtherLink(courseTeam) && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={courseTeamDestination}
|
||||
title={intl.formatMessage(messages.sidebarLinkToCourseTeam)}
|
||||
/>
|
||||
)}
|
||||
{proctoredExamSettingsUrl
|
||||
&& !proctoredExamSettingsUrl.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={proctoredExamSettingsUrl}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
messages.sidebarLinkToProctoredExamSettings,
|
||||
)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{showOtherLink(groupConfigurations) && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={groupConfigurationsDestination}
|
||||
title={intl.formatMessage(
|
||||
messages.sidebarLinkToGroupConfigurations,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{!groupConfigurationsDestination.href.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={groupConfigurationsDestination.href}
|
||||
>
|
||||
{intl.formatMessage(
|
||||
messages.sidebarLinkToGroupConfigurations,
|
||||
)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{showOtherLink(advancedSettings) && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={advancedSettingsDestination}
|
||||
title={intl.formatMessage(messages.sidebarLinkToAdvancedSettings)}
|
||||
/>
|
||||
)}
|
||||
{!advancedSettingsDestination.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={advancedSettingsDestination}
|
||||
>
|
||||
{intl.formatMessage(messages.sidebarLinkToAdvancedSettings)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
)}
|
||||
{!proctoredExamSettingsDestination.href.includes(pathname) && !gradingDestination.includes(pathname) && (
|
||||
<li className="help-sidebar-other-link">
|
||||
<Hyperlink
|
||||
rel="noopener"
|
||||
destination={proctoredExamSettingsDestination}
|
||||
>
|
||||
{intl.formatMessage(messages.sidebarLinkToProctoredExamSettings)}
|
||||
</Hyperlink>
|
||||
</li>
|
||||
{proctoredExamSettingsUrl && (
|
||||
<HelpSidebarLink
|
||||
pathToPage={proctoredExamSettingsUrl}
|
||||
title={intl.formatMessage(
|
||||
messages.sidebarLinkToProctoredExamSettings,
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
@import "./help-sidebar/HelpSidebar";
|
||||
@import "./course-upload-image/CourseUploadImage";
|
||||
@import "./sub-header/SubHeader";
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -376,11 +376,6 @@
|
||||
"course-authoring.advanced-settings.sidebar.about.title": "What do advanced settings do?",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-1": "Advanced settings control specific course functionality. On this page, you can edit manual policies, which are JSON-based key and value pairs that control specific course settings.",
|
||||
"course-authoring.advanced-settings.sidebar.about.description-2": "Any policies you modify here override all other information you’ve defined elsewhere in Studio. Do not edit policies unless you are familiar with both their purpose and syntax.",
|
||||
"course-authoring.advanced-settings.sidebar.other.title": "Other course settings",
|
||||
"course-authoring.advanced-settings.sidebar.links.schedule-and-details": "Details & schedule",
|
||||
"course-authoring.advanced-settings.sidebar.links.grading": "Grading",
|
||||
"course-authoring.advanced-settings.sidebar.links.course-team": "Course team",
|
||||
"course-authoring.advanced-settings.sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.advanced-settings.button.deprecated": "Deprecated",
|
||||
"course-authoring.advanced-settings.modal.error.title": "Validation error while saving",
|
||||
"course-authoring.advanced-settings.modal.error.btn.change-manually": "Change manually",
|
||||
@@ -389,5 +384,206 @@
|
||||
"course-authoring.advanced-settings.policies.description": "{notice} Do not modify these policies unless you are familiar with their purpose.",
|
||||
"course-authoring.advanced-settings.deprecated.button.text": "{visibility} Deprecated Settings",
|
||||
"course-authoring.advanced-settings.button.help": "Show help text",
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving"
|
||||
"course-authoring.advanced-settings.alert.button.saving": "Saving",
|
||||
"course-authoring.schedule.basic.title": "Basic information",
|
||||
"course-authoring.schedule.basic.description": "The nuts and bolts of this course",
|
||||
"course-authoring.schedule.basic.email-icon": "Invite your students email icon",
|
||||
"course-authoring.schedule.basic.organization": "Organization",
|
||||
"course-authoring.schedule.basic.course-number": "Course number",
|
||||
"course-authoring.schedule.basic.course-run": "Course run",
|
||||
"course-authoring.schedule.basic.banner.title": "Promoting your course with edX",
|
||||
"course-authoring.schedule.basic.banner.text": "Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.",
|
||||
"course-authoring.schedule.basic.promotion.button": "Invite your students",
|
||||
"course-authoring.schedule.credit.title": "Course credit requirements",
|
||||
"course-authoring.schedule.credit.description": "Steps required to earn course credit",
|
||||
"course-authoring.schedule.credit.help": "A requirement appears in this list when you publish the unit that contains the requirement.",
|
||||
"course-authoring.schedule.credit.minimum-grade": "Minimum grade",
|
||||
"course-authoring.schedule.credit.proctored-exam": "Successful proctored exam",
|
||||
"course-authoring.schedule.credit.verification": "ID Verification",
|
||||
"course-authoring.schedule.credit.not-found": "No credit requirements found.",
|
||||
"course-authoring.schedule.pacing.title": "Course pacing",
|
||||
"course-authoring.schedule.pacing.description": "Set the pacing for this course",
|
||||
"course-authoring.schedule.pacing.restriction": "Course pacing cannot be changed once a course has started",
|
||||
"course-authoring.schedule.pacing.radio.instructor.label": "Instructor-paced",
|
||||
"course-authoring.schedule.pacing.radio.instructor.description": "Instructor-paced courses progress at the pace that the course author sets. You can configure release dates for course content and due dates for assignments.",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.label": "Self-paced",
|
||||
"course-authoring.schedule.pacing.radio.self-paced.description": "Self-paced courses offer suggested due dates for assignments or exams based on the learner’s enrollment date and the expected course duration. These courses offer learners flexibility to modify the assignment dates as needed.",
|
||||
"course-authoring.schedule.sidebar.about.title": "How are these settings used?",
|
||||
"course-authoring.schedule.sidebar.about.text": "Your course's schedule determines when students can enroll in and begin a course. Other information from this page appears on the About page for your course. This information includes the course overview, course image, introduction video, and estimated time requirements. Students use About pages to choose new courses to take.",
|
||||
"course-authoring.schedule.heading.title": "Schedule & details",
|
||||
"course-authoring.schedule.heading.subtitle": "Settings",
|
||||
"course-authoring.schedule.alert.button.save": "Save changes",
|
||||
"course-authoring.schedule.alert.button.cancel": "Cancel",
|
||||
"course-authoring.schedule.alert.warning.aria.labelledby": "notification-warning-title",
|
||||
"course-authoring.schedule.alert.warning.aria.describedby": "notification-warning-description",
|
||||
"course-authoring.schedule.alert.warning": "You`ve made some changes",
|
||||
"course-authoring.schedule.alert.warning.descriptions": "Your changes will not take effect until you save your progress.",
|
||||
"course-authoring.schedule.alert.success.aria.labelledby": "alert-confirmation-title",
|
||||
"course-authoring.schedule.alert.success.aria.describedby": "alert-confirmation-description",
|
||||
"course-authoring.schedule.alert.success": "Your changes have been saved.",
|
||||
"course-authoring.help-sidebar.other.title": "Other course settings",
|
||||
"course-authoring.help-sidebar.links.schedule-and-details": "Schedule & Details",
|
||||
"course-authoring.help-sidebar.links.grading": "Grading",
|
||||
"course-authoring.help-sidebar.links.course-team": "Course team",
|
||||
"course-authoring.help-sidebar.links.group-configurations": "Group configurations",
|
||||
"course-authoring.help-sidebar.links.proctored-exam-settings": "Proctored exam settings",
|
||||
"course-authoring.help-sidebar.links.advanced-settings": "Advanced settings",
|
||||
"course-authoring.schedule.basic.email.subject": "Enroll in {courseDisplayName}.",
|
||||
"course-authoring.schedule.basic.email.body": "The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.",
|
||||
"course-authoring.schedule.basic.promotion.title": "Course summary page {smallText}",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.label": "Certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.help-text": "Certificates are awarded at the end of a course run",
|
||||
"course-authoring.schedule.schedule-section.certificate-available-date.label": "Certificate available date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.title": "Read more about this setting",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph": "In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-1": "Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-2": "On course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-2": "Learners with passing grades can access their certificate once the end date of the course has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.heading-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.toggle.paragraph-3": "Learners with passing grades can access their certificate after the date that you set has elapsed.",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-1": "Immediately upon passing",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-2": "End date of course",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.option-3": "A date after the course end date",
|
||||
"course-authoring.schedule.schedule-section.certificate-behavior.dropdown.empty": "Select certificate display behavior",
|
||||
"course-authoring.schedule.schedule-section.alt-text": "Calendar for datepicker input",
|
||||
"course-authoring.schedule.schedule-section.datepicker.utc": "UTC",
|
||||
"course-authoring.schedule.schedule-section.title": "Course schedule",
|
||||
"course-authoring.schedule.schedule-section.description": "Dates that control when your course can be viewed",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.label": "Course start date",
|
||||
"course-authoring.schedule.schedule-section.course-start.date.help-text": "First day the course begins",
|
||||
"course-authoring.schedule.schedule-section.course-start.time.label": "Course start time",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.label": "Course end date",
|
||||
"course-authoring.schedule.schedule-section.course-end.date.help-text": "Last day your course is active",
|
||||
"course-authoring.schedule.schedule-section.course-end.time.label": "Course end time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.date.label": "Enrollment start date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.help-text": "First day students can enroll",
|
||||
"course-authoring.schedule.schedule-section.enrollment-start.time.label": "Enrollment start time",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.label": "Enrollment end date",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.help-text": "Last day students can enroll.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.date.restricted.help-text": "Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.enrollment-end.time.label": "Enrollment end time",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.label": "Upgrade deadline date",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.date.help-text": "Last day students can upgrade to a verified enrollment. Contact your {platformName} partner manager to update these settings.",
|
||||
"course-authoring.schedule.schedule-section.upgrade-deadline.time.label": "Upgrade deadline time",
|
||||
"course-authoring.schedule.alert.warning.save.error": "You've made some changes, but there are some errors",
|
||||
"course-authoring.schedule.alert.warning.save.descriptions.error": "Please address the errors on this page first, and then save your progress.",
|
||||
"course-authoring.schedule.schedule-section.error-message-1": "The certificates display behavior must be 'A date after the course end date' if certificate available date is set.",
|
||||
"course-authoring.schedule.schedule-section.error-message-2": "The enrollment end date cannot be after the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-3": "The enrollment start date cannot be after the enrollment end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-4": "The course start date must be later than the enrollment start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-5": "The course end date must be later than the course start date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-6": "The certificate available date must be later than the course end date.",
|
||||
"course-authoring.schedule.schedule-section.error-message-7": "The course must have an assigned start date.",
|
||||
"course-authoring.schedule-section.details.title": "Course details",
|
||||
"course-authoring.schedule-section.details.description": "Provide useful information about your course",
|
||||
"course-authoring.schedule-section.details.dropdown.label": "Course language",
|
||||
"course-authoring.schedule-section.details.dropdown.help-text": "Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the 'From:' field in bulk emails.",
|
||||
"course-authoring.schedule-section.details.dropdown.empty": "Select language",
|
||||
"course-authoring.schedule-section.introducing.title": "Introducing your course",
|
||||
"course-authoring.schedule-section.introducing.description": "Information for prospective students",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.label": "Course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.aria-label": "Show course short description",
|
||||
"course-authoring.schedule-section.introducing.course-short-description.help-text": "Appears on the course catalog page when students roll over the course name. Limit to ~150 characters",
|
||||
"course-authoring.schedule-section.introducing.course-overview.label": "Course overview",
|
||||
"course-authoring.schedule-section.introducing.course-about.hyperlink": "your course summary page",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.label": "Course about sidebar HTML",
|
||||
"course-authoring.schedule-section.introducing.course-about-sidebar.help-text": "Custom sidebar content for your course summary page (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.label": "Course introduction video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.delete": "Delete current video",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.help-text": "Enter your YouTube video's ID (along with any restriction parameters)",
|
||||
"course-authoring.schedule-section.introducing.introduction-video.placeholder": "your YouTube video's ID",
|
||||
"course-authoring.schedule-section.introducing.course-overview.help-text": "Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.about-sidebar.help-text": "Custom sidebar content for {hyperlink} (formatted in HTML)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.help-text": "Please provide a valid path and name to your {identifierFieldText} (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.file-and-uploads": "files and uploads",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-text": "Drag and drop your {identifierFieldText} here or click to upload.",
|
||||
"course-authoring.schedule-section.introducing.upload-image.dropzone-alt": "Uploaded image for course",
|
||||
"course-authoring.schedule-section.introducing.upload-image.empty": "Your course currently does not have an image. Please upload one (JPEG or PNG format, and minimum suggested dimensions are 375px wide by 200px tall)",
|
||||
"course-authoring.schedule-section.introducing.upload-image.icon-alt": "File upload icon",
|
||||
"course-authoring.schedule-section.introducing.upload-image.manage": "You can manage this image along with all of your other {hyperlink}",
|
||||
"course-authoring.schedule-section.introducing.upload-image.input.placeholder": "Your {identifierFieldText} URL",
|
||||
"course-authoring.schedule-section.instructors.title": "Instructors",
|
||||
"course-authoring.schedule-section.instructors.description": "Add details about the instructors for this course",
|
||||
"course-authoring.schedule-section.instructors.add-instructor": "Add Instructor",
|
||||
"course-authoring.schedule-section.instructor.name.label": "Name",
|
||||
"course-authoring.schedule-section.instructor.name.help-text": "Please add the instructor's name",
|
||||
"course-authoring.schedule-section.instructor.name.input.placeholder": "Instructor name",
|
||||
"course-authoring.schedule-section.instructor.title.label": "Title",
|
||||
"course-authoring.schedule-section.instructor.title.help-text": "Please add the instructor's title",
|
||||
"course-authoring.schedule-section.instructor.title.input.placeholder": "Instructor title",
|
||||
"course-authoring.schedule-section.instructor.organization.label": "Organization",
|
||||
"course-authoring.schedule-section.instructor.organization.help-text": "Please add the institute where the instructor is associated",
|
||||
"course-authoring.schedule-section.instructor.organization.input.placeholder": "Instructor organization",
|
||||
"course-authoring.schedule-section.instructor.bio.label": "Biography",
|
||||
"course-authoring.schedule-section.instructor.bio.help-text": "Please add the instructor's biography",
|
||||
"course-authoring.schedule-section.instructor.bio.input.placeholder": "Instructor biography",
|
||||
"course-authoring.schedule-section.instructor.photo.label": "Photo",
|
||||
"course-authoring.schedule-section.instructor.photo.help-text": "Please add a photo of the instructor (Note: only JPEG or PNG format supported)",
|
||||
"course-authoring.schedule-section.instructor.photo.input.placeholder": "Instructor photo URL",
|
||||
"course-authoring.schedule-section.instructor.delete": "Delete",
|
||||
"course-authoring.schedule-section.introducing.title.label": "Course title",
|
||||
"course-authoring.schedule-section.introducing.title.help-text": "Displayed as title on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.title.aria-label": "Show course title",
|
||||
"course-authoring.schedule-section.introducing.subtitle.label": "Course subtitle",
|
||||
"course-authoring.schedule-section.introducing.subtitle.help-text": "Displayed as subtitle on the course details page. Limit to 150 characters.",
|
||||
"course-authoring.schedule-section.introducing.subtitle.aria-label": "Show course subtitle",
|
||||
"course-authoring.schedule-section.introducing.duration.label": "Course duration",
|
||||
"course-authoring.schedule-section.introducing.duration.help-text": "Displayed on the course details page. Limit to 50 characters.",
|
||||
"course-authoring.schedule-section.introducing.duration.aria-label": "Show course duration",
|
||||
"course-authoring.schedule-section.introducing.description.label": "Course description",
|
||||
"course-authoring.schedule-section.introducing.description.help-text": "Displayed on the course details page. Limit to 1000 characters.",
|
||||
"course-authoring.schedule-section.introducing.description.aria-label": "Show course description",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.label": "Course card image",
|
||||
"course-authoring.schedule-section.introducing.course-card-image.identifier-text": "course image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.label": "Course banner image",
|
||||
"course-authoring.schedule-section.introducing.course-banner-image.insert-banner": "banner image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.label": "Course video thumbnail image",
|
||||
"course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card": "video thumbnail image",
|
||||
"course-authoring.schedule.learning-outcomes-section.title": "Learning outcomes",
|
||||
"course-authoring.schedule.learning-outcomes-section.description": "Add the learning outcomes for this course",
|
||||
"course-authoring.schedule.learning-outcomes-section.delete": "Delete",
|
||||
"course-authoring.schedule.learning-outcomes-section.add": "Add learning outcome",
|
||||
"course-authoring.schedule.learning-outcomes-section.input.placeholder": "Add a learning outcome here",
|
||||
"course-authoring.schedule.learning-outcomes-section.label-increment": "Learning outcome",
|
||||
"course-authoring.generic.alert.warning.offline.title": "Studio's having trouble saving your work",
|
||||
"course-authoring.generic.alert.warning.offline.description": "This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.",
|
||||
"course-authoring.generic.alert.warning.offline.title.aria.labelled-by": "alert-internet-error-title",
|
||||
"course-authoring.generic.alert.warning.offline.subtitle.aria.described-by": "alert-internet-error-description",
|
||||
"course-authoring.schedule-section.requirements.entrance.label": "Entrance exam",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.title": "Require students to pass an exam before beginning the course.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.paragraph": "You can now view and author your course entrance exam from the {hyperlink}.",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.hyperlink": "course outline",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.label": "Grade requirements",
|
||||
"course-authoring.schedule-section.requirements.entrance.collapse.help-text": "The score student must meet in order to successfully complete the entrance exam.",
|
||||
"course-authoring.schedule-section.requirements.title": "Requirements",
|
||||
"course-authoring.schedule-section.requirements.description": "Expectations of the students taking this course",
|
||||
"course-authoring.schedule-section.requirements.timepicker.label": "Hours of effort per week",
|
||||
"course-authoring.schedule-section.requirements.timepicker.help-text": "Time spent on all course work",
|
||||
"course-authoring.schedule-section.requirements.dropdown.label": "Prerequisite course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.help-text": "Course that students must complete before beginning this course",
|
||||
"course-authoring.schedule-section.requirements.dropdown.empty-text": "None",
|
||||
"course-authoring.schedule-section.license.title": "Course content license",
|
||||
"course-authoring.schedule-section.license.description": "Select the default license for course content",
|
||||
"course-authoring.schedule-section.license.type": "License type",
|
||||
"course-authoring.schedule-section.license.choice-1": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.choice-2": "Creative commons",
|
||||
"course-authoring.schedule-section.license.tooltip-1": "You reserve all rights for your work",
|
||||
"course-authoring.schedule-section.license.tooltip-2": "You waive some rights for your work, such that others can use it too",
|
||||
"course-authoring.schedule-section.license.creative-commons.url": "Learn more about creative commons",
|
||||
"course-authoring.schedule-section.license.all-right-reserved.label": "All rights reserved",
|
||||
"course-authoring.schedule-section.license.creative-commons.label": "Some rights reserved",
|
||||
"course-authoring.schedule-section.license.license-display.label": "License display",
|
||||
"course-authoring.schedule-section.license.license-display.paragraph": "The following message will be displayed at the bottom of the courseware pages within your course:",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.label": "Options for creative commons",
|
||||
"course-authoring.schedule-section.license.creative-commons.options.help-text": "The following options are available for the creative commons license.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.label": "Attribution",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.BY.description": "Allow others to copy, distribute, display and perform your copyrighted work but only if they give credit the way you request. Currently, this option is required.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.label": "Noncommercial",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.NC.description": "Allow others to copy, distribute, display and perform your work - and derivative works based upon it - but for noncommercial purposes only.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.label": "No derivatives",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.ND.description": "Allow others to copy, distribute, display and perform only verbatim copies of your work, not derivative works based upon it. This option is incompatible with 'Share Alike'.",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.label": "Share alike",
|
||||
"course-authoring.schedule-section.license.creative-commons.option.SA.description": "Allow others to distribute derivative works only under a license identical to the license that governs your work. This option is incompatible with 'No Derivatives'.",
|
||||
"course-authoring.schedule.alert.button.saving": "Saving"
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import initializeStore from './store';
|
||||
import CourseAuthoringRoutes from './CourseAuthoringRoutes';
|
||||
import Head from './head/Head';
|
||||
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import './index.scss';
|
||||
|
||||
const App = () => {
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
@import "~@edx/brand/paragon/overrides";
|
||||
@import "studio-header/header";
|
||||
@import "~@edx/frontend-component-footer/dist/footer";
|
||||
@import "assets/scss/variables";
|
||||
@import "assets/scss/form";
|
||||
@import "assets/scss/utilities";
|
||||
@import "proctored-exam-settings/proctoredExamSettings";
|
||||
@import "pages-and-resources/discussions/app-list/AppList";
|
||||
@import "advanced-settings/scss/AdvancedSettings";
|
||||
@import "generic/styles";
|
||||
@import "schedule-and-details/ScheduleAndDetails";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// legend styling should match label styling
|
||||
legend {
|
||||
font-size: 1rem;
|
||||
font-size: $spacer;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
|
||||
30
src/schedule-and-details/ScheduleAndDetails.scss
Normal file
30
src/schedule-and-details/ScheduleAndDetails.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
@import "./basic-section/BasicSection";
|
||||
@import "./credit-section/CreditSection";
|
||||
@import "./pacing-section/PacingSection";
|
||||
@import "./details-section/DetailsSection";
|
||||
@import "./introducing-section/IntroducingSection";
|
||||
@import "./schedule-section/ScheduleSection";
|
||||
@import "./schedule-section/certificate-display-row/CertificateDisplayRow";
|
||||
@import "./learning-outcomes-section/LearningOutcomes";
|
||||
@import "./instructors-section/InstructorsSection";
|
||||
@import "./requirements-section/RequirementsSection";
|
||||
@import "./license-section/LicenseSection";
|
||||
|
||||
.section-container {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 1.75rem;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: .75rem;
|
||||
border-bottom: $border-width solid $light-400;
|
||||
|
||||
h2 {
|
||||
color: $black;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
147
src/schedule-and-details/ScheduleAndDetails.test.jsx
Normal file
147
src/schedule-and-details/ScheduleAndDetails.test.jsx
Normal file
@@ -0,0 +1,147 @@
|
||||
import React from 'react';
|
||||
import { 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 {
|
||||
act, render, waitFor, fireEvent,
|
||||
} from '@testing-library/react';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
|
||||
import initializeStore from '../store';
|
||||
import { courseDetailsMock, courseSettingsMock } from './__mocks__';
|
||||
import { getCourseDetailsApiUrl, getCourseSettingsApiUrl } from './data/api';
|
||||
import { DATE_FORMAT } from '../constants';
|
||||
import creditMessages from './credit-section/messages';
|
||||
import pacingMessages from './pacing-section/messages';
|
||||
import basicMessages from './basic-section/messages';
|
||||
import scheduleMessages from './schedule-section/messages';
|
||||
import genericMessages from '../generic/help-sidebar/messages';
|
||||
import messages from './messages';
|
||||
import ScheduleAndDetails from '.';
|
||||
|
||||
let axiosMock;
|
||||
let store;
|
||||
const mockPathname = '/foo-bar';
|
||||
const courseId = '123';
|
||||
|
||||
// Mock the tinymce lib
|
||||
jest.mock('@tinymce/tinymce-react', () => {
|
||||
const originalModule = jest.requireActual('@tinymce/tinymce-react');
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
Editor: () => 'foo bar',
|
||||
};
|
||||
});
|
||||
|
||||
// Mock the TinyMceWidget from frontend-lib-content-components
|
||||
jest.mock('@edx/frontend-lib-content-components', () => ({
|
||||
TinyMceWidget: () => <div>Widget</div>,
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
// Mock the TextareaAutosize component
|
||||
jest.mock('react-textarea-autosize', () => jest.fn((props) => (
|
||||
<textarea {...props} onFocus={() => {}} onBlur={() => {}} />
|
||||
)));
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: () => ({
|
||||
pathname: mockPathname,
|
||||
}),
|
||||
}));
|
||||
|
||||
const RootWrapper = () => (
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en" messages={{}}>
|
||||
<ScheduleAndDetails intl={injectIntl} courseId={courseId} />
|
||||
</IntlProvider>
|
||||
</AppProvider>
|
||||
);
|
||||
|
||||
describe('<ScheduleAndDetails />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
axiosMock
|
||||
.onGet(getCourseDetailsApiUrl(courseId))
|
||||
.reply(200, courseDetailsMock);
|
||||
axiosMock
|
||||
.onGet(getCourseSettingsApiUrl(courseId))
|
||||
.reply(200, courseSettingsMock);
|
||||
});
|
||||
|
||||
it('should render without errors', async () => {
|
||||
const { getByText, getByRole } = render(<RootWrapper />);
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
getByText(pacingMessages.pacingTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.headingTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(basicMessages.basicTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(creditMessages.creditTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(scheduleMessages.scheduleTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByRole('navigation', {
|
||||
name: genericMessages.sidebarTitleOther.defaultMessage,
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should hide credit section with condition', async () => {
|
||||
const updatedResponse = {
|
||||
...courseSettingsMock,
|
||||
creditEligibilityEnabled: false,
|
||||
isCreditCourse: false,
|
||||
};
|
||||
axiosMock
|
||||
.onGet(getCourseSettingsApiUrl(courseId))
|
||||
.reply(200, updatedResponse);
|
||||
|
||||
const { queryAllByText } = render(<RootWrapper />);
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
queryAllByText(creditMessages.creditTitle.defaultMessage).length,
|
||||
).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show save alert onChange ', async () => {
|
||||
const { getAllByPlaceholderText, getByText } = render(
|
||||
<RootWrapper />,
|
||||
);
|
||||
await waitFor(() => {
|
||||
const inputs = getAllByPlaceholderText(DATE_FORMAT.toLocaleUpperCase());
|
||||
act(() => {
|
||||
fireEvent.change(inputs[0], { target: { value: '06/16/2023' } });
|
||||
});
|
||||
|
||||
expect(
|
||||
getByText(messages.alertWarning.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
48
src/schedule-and-details/__mocks__/courseDetails.js
Normal file
48
src/schedule-and-details/__mocks__/courseDetails.js
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = {
|
||||
aboutSidebarHtml: '',
|
||||
bannerImageName: 'images_course_image.jpg',
|
||||
bannerImageAssetPath:
|
||||
'/asset-v1:edX+M12+2T2023+type@asset+block@images_courseasdd_image.jpg',
|
||||
certificateAvailableDate: null,
|
||||
certificatesDisplayBehavior: 'end',
|
||||
courseId: 'M12',
|
||||
courseImageAssetPath: '/static/studio/images/pencils.jpg',
|
||||
courseImageName: '',
|
||||
description: 'description',
|
||||
duration: '10h',
|
||||
effort: '10h',
|
||||
endDate: null,
|
||||
enrollmentEnd: null,
|
||||
enrollmentStart: null,
|
||||
entranceExamEnabled: 'true',
|
||||
entranceExamId: '',
|
||||
entranceExamMinimumScorePct: '50',
|
||||
instructorInfo: {
|
||||
instructors: [
|
||||
{
|
||||
name: 'foo bar',
|
||||
title: 'title',
|
||||
organization: 'org',
|
||||
image: 'image',
|
||||
bio: 'biography',
|
||||
},
|
||||
],
|
||||
},
|
||||
introVideo: null,
|
||||
language: 'creative-commons: ver=4.0 BY NC ND',
|
||||
learningInfo: ['foo'],
|
||||
license: 'creative-commons: ver=4.0 BY NC ND',
|
||||
org: 'edX',
|
||||
overview: "<section class='about'></section>",
|
||||
preRequisiteCourses: [],
|
||||
run: '2T2023',
|
||||
selfPaced: false,
|
||||
shortDescription: '',
|
||||
startDate: '2023-06-14T00:00:00Z',
|
||||
subtitle: 'subtitle',
|
||||
syllabus: null,
|
||||
title: 'title',
|
||||
videoThumbnailImageAssetPath:
|
||||
'/asset-v1:edX+M12+2T2023+type@asset+block@images_course_image.jpg',
|
||||
videoThumbnailImageName: 'images_course_image.jpg',
|
||||
};
|
||||
61
src/schedule-and-details/__mocks__/courseSettings.js
Normal file
61
src/schedule-and-details/__mocks__/courseSettings.js
Normal file
@@ -0,0 +1,61 @@
|
||||
module.exports = {
|
||||
aboutPageEditable: true,
|
||||
canShowCertificateAvailableDateField: false,
|
||||
courseDisplayName: 'Differential Equations',
|
||||
courseDisplayNameWithDefault: 'Differential Equations',
|
||||
creditEligibilityEnabled: true,
|
||||
creditRequirements: {
|
||||
grade: [
|
||||
{
|
||||
name: 'grade',
|
||||
displayName: 'Minimum Grade',
|
||||
criteria: {
|
||||
minGrade: 0.8,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
enableExtendedCourseDetails: true,
|
||||
enrollmentEndEditable: true,
|
||||
isCreditCourse: true,
|
||||
isEntranceExamsEnabled: true,
|
||||
isPrerequisiteCoursesEnabled: true,
|
||||
languageOptions: [
|
||||
['en', 'English'],
|
||||
['uk', 'Ukrainian'],
|
||||
],
|
||||
lmsLinkForAboutPage:
|
||||
'http://localhost:18000/courses/course-v1:edX+M12+2T2023/about',
|
||||
marketingEnabled: true,
|
||||
mfeProctoredExamSettingsUrl: '',
|
||||
possiblePreRequisiteCourses: [
|
||||
{
|
||||
courseKey: 'course-v1:edX+P315+2T2023',
|
||||
displayName: 'Quantum Entanglement',
|
||||
lmsLink:
|
||||
'//localhost:18000/courses/course-v1:edX+P315+2T2023/jump_to/block-v1:edX+P315+2T2023+type@course+block@course',
|
||||
number: 'P315',
|
||||
org: 'edX',
|
||||
rerunLink: '/course_rerun/course-v1:edX+P315+2T2023',
|
||||
run: '2T2023',
|
||||
url: '/course/course-v1:edX+P315+2T2023',
|
||||
},
|
||||
{
|
||||
courseKey: 'course-v1:edX+DemoX+Demo_Course',
|
||||
displayName: 'Demonstration Course',
|
||||
lmsLink:
|
||||
'//localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@course+block@course',
|
||||
number: 'DemoX',
|
||||
org: 'edX',
|
||||
rerunLink: '/course_rerun/course-v1:edX+DemoX+Demo_Course',
|
||||
run: 'Demo_Course',
|
||||
url: '/course/course-v1:edX+DemoX+Demo_Course',
|
||||
},
|
||||
],
|
||||
shortDescriptionEditable: true,
|
||||
showMinGradeWarning: false,
|
||||
sidebarHtmlEnabled: true,
|
||||
upgradeDeadline: '2023-07-02T23:59:59+00:00',
|
||||
useV2CertDisplaySettings: false,
|
||||
platformName: 'edX',
|
||||
};
|
||||
2
src/schedule-and-details/__mocks__/index.js
Normal file
2
src/schedule-and-details/__mocks__/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as courseDetailsMock } from './courseDetails';
|
||||
export { default as courseSettingsMock } from './courseSettings';
|
||||
31
src/schedule-and-details/basic-section/BasicSection.scss
Normal file
31
src/schedule-and-details/basic-section/BasicSection.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
.basic-section {
|
||||
.basic-info-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.75rem;
|
||||
padding-inline-start: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.pgn__pageBanner-component {
|
||||
@include pgn-box-shadow(1, "down");
|
||||
|
||||
background-color: $white;
|
||||
border-radius: .375rem;
|
||||
}
|
||||
|
||||
.pgn__pageBanner-content {
|
||||
align-items: flex-start;
|
||||
padding: 1.5rem;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pgn__pageBanner-dismissButtonContainer {
|
||||
margin: 1.5rem 1.5rem 0 0;
|
||||
align-self: baseline;
|
||||
}
|
||||
|
||||
.pgn__card-header-content {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
}
|
||||
80
src/schedule-and-details/basic-section/BasicSection.test.jsx
Normal file
80
src/schedule-and-details/basic-section/BasicSection.test.jsx
Normal file
@@ -0,0 +1,80 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { INVITE_STUDENTS_LINK_ID } from './constants';
|
||||
import messages from './messages';
|
||||
import BasicSection from '.';
|
||||
|
||||
describe('<BasicSection />', () => {
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<BasicSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
intl: {},
|
||||
org: 'foo org',
|
||||
courseNumber: 'bar number',
|
||||
run: 'foo run',
|
||||
lmsLinkForAboutPage: 'link://to',
|
||||
marketingEnabled: true,
|
||||
courseDisplayName: 'foo course',
|
||||
platformName: 'Your platform name here',
|
||||
};
|
||||
|
||||
it('renders basic section successfully', () => {
|
||||
const { getByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.basicTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.basicDescription.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.courseOrganization.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(getByText(props.org)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseNumber.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(props.courseNumber)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseRun.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(props.run)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows the page banner if the marketingEnabled is true', () => {
|
||||
const { getByText, queryAllByText } = render(<RootWrapper {...props} />);
|
||||
expect(
|
||||
getByText(messages.basicBannerTitle.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.basicBannerText.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(queryAllByText('Course summary page').length).toBe(0);
|
||||
});
|
||||
|
||||
it('shows the course promotion if the marketingEnabled is false', () => {
|
||||
const initialProps = { ...props, marketingEnabled: false };
|
||||
const { getByText, getByRole, queryAllByText } = render(
|
||||
<RootWrapper {...initialProps} />,
|
||||
);
|
||||
const inviteButton = getByRole('button', {
|
||||
name: messages.basicPromotionButton.defaultMessage,
|
||||
});
|
||||
|
||||
expect(getByText(/Course Summary Page/i)).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(/(for student enrollment and access)/i),
|
||||
).toBeInTheDocument();
|
||||
expect(getByText(props.lmsLinkForAboutPage)).toBeInTheDocument();
|
||||
expect(inviteButton).toBeInTheDocument();
|
||||
expect(queryAllByText(messages.basicBannerTitle.defaultMessage).length).toBe(0);
|
||||
});
|
||||
|
||||
it('checks link link to invite', () => {
|
||||
const initialProps = { ...props, marketingEnabled: false };
|
||||
const { getByTestId } = render(<RootWrapper {...initialProps} />);
|
||||
const inviteLink = getByTestId(INVITE_STUDENTS_LINK_ID);
|
||||
expect(decodeURIComponent(inviteLink.href)).toEqual(
|
||||
`mailto:${process.env.INVITE_STUDENTS_EMAIL_TO}?body=The course ${props.courseDisplayName}, provided by ${props.platformName}, is open for enrollment. Please navigate to this course at ${props.lmsLinkForAboutPage} to enroll.&subject=Enroll in ${props.courseDisplayName}.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
2
src/schedule-and-details/basic-section/constants.js
Normal file
2
src/schedule-and-details/basic-section/constants.js
Normal file
@@ -0,0 +1,2 @@
|
||||
/* eslint-disable-next-line import/prefer-default-export */
|
||||
export const INVITE_STUDENTS_LINK_ID = 'invite-students-link';
|
||||
151
src/schedule-and-details/basic-section/index.jsx
Normal file
151
src/schedule-and-details/basic-section/index.jsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl, FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
PageBanner, Button, Card, MailtoLink, Hyperlink,
|
||||
} from '@edx/paragon';
|
||||
import { Email as EmailIcon } from '@edx/paragon/icons';
|
||||
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import { INVITE_STUDENTS_LINK_ID } from './constants';
|
||||
import messages from './messages';
|
||||
|
||||
const BasicSection = ({
|
||||
org,
|
||||
courseNumber,
|
||||
run,
|
||||
lmsLinkForAboutPage,
|
||||
marketingEnabled,
|
||||
courseDisplayName,
|
||||
platformName,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [showPageBanner, setShowPageBanner] = useState(true);
|
||||
const emailSubject = intl.formatMessage(
|
||||
{
|
||||
id: 'course-authoring.schedule.basic.email.subject',
|
||||
defaultMessage: 'Enroll in {courseDisplayName}.',
|
||||
},
|
||||
{ courseDisplayName },
|
||||
);
|
||||
|
||||
const emailBody = intl.formatMessage(
|
||||
{
|
||||
id: 'course-authoring.schedule.basic.email.body',
|
||||
defaultMessage:
|
||||
'The course {courseDisplayName}, provided by {platformName}, is open for enrollment. Please navigate to this course at {lmsLinkForAboutPage} to enroll.',
|
||||
},
|
||||
{
|
||||
courseDisplayName,
|
||||
platformName,
|
||||
lmsLinkForAboutPage,
|
||||
},
|
||||
);
|
||||
|
||||
const promotionTitle = (
|
||||
<FormattedMessage
|
||||
id="course-authoring.schedule.basic.promotion.title"
|
||||
defaultMessage="Course summary page {smallText}"
|
||||
values={{
|
||||
smallText: <small>(for student enrollment and access)</small>,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const courseBasicInfo = [
|
||||
{
|
||||
label: `${intl.formatMessage(messages.courseOrganization)}`,
|
||||
prefix: 'basic-organization',
|
||||
value: org,
|
||||
},
|
||||
{
|
||||
label: `${intl.formatMessage(messages.courseNumber)}`,
|
||||
prefix: 'basic-course-number',
|
||||
value: courseNumber,
|
||||
},
|
||||
{
|
||||
label: `${intl.formatMessage(messages.courseRun)}`,
|
||||
prefix: 'basic-course-run',
|
||||
value: run,
|
||||
},
|
||||
];
|
||||
|
||||
const renderBasicInfo = (info) => (
|
||||
<li key={info.prefix}>
|
||||
<h4 className="mb-0 text-black">{info.label}</h4>
|
||||
<span className="small text-black">{info.value}</span>
|
||||
</li>
|
||||
);
|
||||
|
||||
const renderPageBanner = () => (
|
||||
<PageBanner
|
||||
show={showPageBanner}
|
||||
dismissible
|
||||
onDismiss={() => setShowPageBanner(false)}
|
||||
className="align-items-start"
|
||||
>
|
||||
<h4 className="text-black">{intl.formatMessage(messages.basicBannerTitle)}</h4>
|
||||
<span className="text text-gray-700 text-left">
|
||||
{intl.formatMessage(messages.basicBannerText)}
|
||||
</span>
|
||||
</PageBanner>
|
||||
);
|
||||
|
||||
const renderCoursePromotion = () => (
|
||||
<Card>
|
||||
<Card.Header
|
||||
className="h4 px-3 text-gray-500"
|
||||
title={promotionTitle}
|
||||
size="sm"
|
||||
/>
|
||||
<Card.Section className="px-3 py-1">
|
||||
<Hyperlink
|
||||
destination={lmsLinkForAboutPage}
|
||||
className="lead info-500 text-decoration-none"
|
||||
target="_blank"
|
||||
showLaunchIcon={false}
|
||||
>
|
||||
{lmsLinkForAboutPage}
|
||||
</Hyperlink>
|
||||
</Card.Section>
|
||||
<Card.Divider />
|
||||
<Card.Footer className="p-3 justify-content-start">
|
||||
<MailtoLink
|
||||
to={process.env.INVITE_STUDENTS_EMAIL_TO}
|
||||
subject={emailSubject}
|
||||
body={emailBody}
|
||||
data-testid={INVITE_STUDENTS_LINK_ID}
|
||||
>
|
||||
<Button variant="outline-primary" iconBefore={EmailIcon}>
|
||||
{intl.formatMessage(messages.basicPromotionButton)}
|
||||
</Button>
|
||||
</MailtoLink>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="section-container basic-section">
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.basicTitle)}
|
||||
description={intl.formatMessage(messages.basicDescription)}
|
||||
/>
|
||||
<ul className="basic-info-list">
|
||||
{courseBasicInfo.map(renderBasicInfo)}
|
||||
</ul>
|
||||
{marketingEnabled ? renderPageBanner() : renderCoursePromotion()}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
BasicSection.propTypes = {
|
||||
org: PropTypes.string.isRequired,
|
||||
courseNumber: PropTypes.string.isRequired,
|
||||
run: PropTypes.string.isRequired,
|
||||
lmsLinkForAboutPage: PropTypes.string.isRequired,
|
||||
marketingEnabled: PropTypes.bool.isRequired,
|
||||
courseDisplayName: PropTypes.string.isRequired,
|
||||
platformName: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default BasicSection;
|
||||
42
src/schedule-and-details/basic-section/messages.js
Normal file
42
src/schedule-and-details/basic-section/messages.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
basicTitle: {
|
||||
id: 'course-authoring.schedule.basic.title',
|
||||
defaultMessage: 'Basic information',
|
||||
},
|
||||
basicDescription: {
|
||||
id: 'course-authoring.schedule.basic.description',
|
||||
defaultMessage: 'The nuts and bolts of this course',
|
||||
},
|
||||
basicEmailIcon: {
|
||||
id: 'course-authoring.schedule.basic.email-icon',
|
||||
defaultMessage: 'Invite your students email icon',
|
||||
},
|
||||
courseOrganization: {
|
||||
id: 'course-authoring.schedule.basic.organization',
|
||||
defaultMessage: 'Organization',
|
||||
},
|
||||
courseNumber: {
|
||||
id: 'course-authoring.schedule.basic.course-number',
|
||||
defaultMessage: 'Course number',
|
||||
},
|
||||
courseRun: {
|
||||
id: 'course-authoring.schedule.basic.course-run',
|
||||
defaultMessage: 'Course run',
|
||||
},
|
||||
basicBannerTitle: {
|
||||
id: 'course-authoring.schedule.basic.banner.title',
|
||||
defaultMessage: 'Promoting your course with edX',
|
||||
},
|
||||
basicBannerText: {
|
||||
id: 'course-authoring.schedule.basic.banner.text',
|
||||
defaultMessage: 'Your course summary page will not be viewable until your course has been announced. To provide content for the page and preview it, follow the instructions provided by your Program Manager. Please note that changes here may take up to a business day to appear on your course summary page.',
|
||||
},
|
||||
basicPromotionButton: {
|
||||
id: 'course-authoring.schedule.basic.promotion.button',
|
||||
defaultMessage: 'Invite your students',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
2
src/schedule-and-details/constants.js
Normal file
2
src/schedule-and-details/constants.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const defaultEntranceExamMinimumScorePct = '50';
|
||||
15
src/schedule-and-details/credit-section/CreditSection.scss
Normal file
15
src/schedule-and-details/credit-section/CreditSection.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.credit-section {
|
||||
.credit-help-text {
|
||||
padding-top: $spacer;
|
||||
margin-bottom: .5rem;
|
||||
font: normal .875rem/1.5rem $font-family-base;
|
||||
}
|
||||
|
||||
.credit-info-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 1.25rem 0 1.75rem;
|
||||
padding-inline-start: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
import CreditSection from '.';
|
||||
|
||||
describe('<CreditSection />', () => {
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<CreditSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
creditRequirements: {
|
||||
grade: [
|
||||
{
|
||||
name: 'grade',
|
||||
displayName: 'Minimum Grade',
|
||||
criteria: {
|
||||
minGrade: 0.8,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
it('renders credit section successfully', () => {
|
||||
const { getByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.creditTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.creditDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.creditHelp.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders empty requirements', () => {
|
||||
const initialProps = { ...props, creditRequirements: {} };
|
||||
const { getByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(getByText(messages.creditNotFound.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders requirements successfully', () => {
|
||||
const { getByText, queryAllByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.creditMinimumGrade.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText('80%')).toBeInTheDocument();
|
||||
expect(queryAllByText(messages.creditProctoredExam.defaultMessage).length).toBe(0);
|
||||
expect(queryAllByText(messages.creditVerification.defaultMessage).length).toBe(0);
|
||||
});
|
||||
});
|
||||
84
src/schedule-and-details/credit-section/index.jsx
Normal file
84
src/schedule-and-details/credit-section/index.jsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import messages from './messages';
|
||||
|
||||
const CreditSection = ({ creditRequirements }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const CREDIT_REQUIREMENTS_TYPES = {
|
||||
grade: intl.formatMessage(messages.creditMinimumGrade),
|
||||
proctoredExam: intl.formatMessage(messages.creditProctoredExam),
|
||||
reverification: intl.formatMessage(messages.creditVerification),
|
||||
};
|
||||
|
||||
const renderRequirementValue = (requirementValue, key) => {
|
||||
const displayValue = key === 'grade'
|
||||
? `${(parseFloat(requirementValue.criteria.minGrade) || 0) * 100}%`
|
||||
: requirementValue.displayName;
|
||||
return (
|
||||
<span className="small text-black" key={requirementValue.name}>
|
||||
{displayValue}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const renderCreditRequirements = (requirements) => {
|
||||
const creditRequirementsKeys = Object.keys(requirements);
|
||||
|
||||
if (creditRequirementsKeys.length) {
|
||||
return (
|
||||
<ul className="credit-info-list">
|
||||
{creditRequirementsKeys.map((key) => (
|
||||
<li key={key}>
|
||||
<h4 className="mb-0 text-black">
|
||||
{CREDIT_REQUIREMENTS_TYPES[key]}
|
||||
</h4>
|
||||
<div className="d-flex flex-column">
|
||||
{creditRequirements[key].map((value) => renderRequirementValue(value, key))}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
return <p>{intl.formatMessage(messages.creditNotFound)}</p>;
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-container credit-section">
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.creditTitle)}
|
||||
description={intl.formatMessage(messages.creditDescription)}
|
||||
/>
|
||||
<p className="credit-help-text">{intl.formatMessage(messages.creditHelp)}</p>
|
||||
{renderCreditRequirements(creditRequirements)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
const creditRequirementsNamespace = PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
display_name: PropTypes.string,
|
||||
criteria: PropTypes.shape({
|
||||
min_grade: PropTypes.number,
|
||||
}),
|
||||
});
|
||||
|
||||
const creditRequirementsPropTypes = PropTypes.shape({
|
||||
proctoredExam: PropTypes.arrayOf(creditRequirementsNamespace),
|
||||
grade: PropTypes.arrayOf(creditRequirementsNamespace),
|
||||
reverification: PropTypes.arrayOf(creditRequirementsNamespace),
|
||||
});
|
||||
|
||||
CreditSection.defaultProps = {
|
||||
creditRequirements: undefined,
|
||||
};
|
||||
|
||||
CreditSection.propTypes = {
|
||||
creditRequirements: creditRequirementsPropTypes,
|
||||
};
|
||||
|
||||
export default CreditSection;
|
||||
35
src/schedule-and-details/credit-section/messages.js
Normal file
35
src/schedule-and-details/credit-section/messages.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
creditTitle: {
|
||||
id: 'course-authoring.schedule.credit.title',
|
||||
defaultMessage: 'Course credit requirements',
|
||||
},
|
||||
creditDescription: {
|
||||
id: 'course-authoring.schedule.credit.description',
|
||||
defaultMessage: 'Steps required to earn course credit',
|
||||
},
|
||||
creditHelp: {
|
||||
id: 'course-authoring.schedule.credit.help',
|
||||
defaultMessage:
|
||||
'A requirement appears in this list when you publish the unit that contains the requirement.',
|
||||
},
|
||||
creditMinimumGrade: {
|
||||
id: 'course-authoring.schedule.credit.minimum-grade',
|
||||
defaultMessage: 'Minimum grade',
|
||||
},
|
||||
creditProctoredExam: {
|
||||
id: 'course-authoring.schedule.credit.proctored-exam',
|
||||
defaultMessage: 'Successful proctored exam',
|
||||
},
|
||||
creditVerification: {
|
||||
id: 'course-authoring.schedule.credit.verification',
|
||||
defaultMessage: 'ID Verification',
|
||||
},
|
||||
creditNotFound: {
|
||||
id: 'course-authoring.schedule.credit.not-found',
|
||||
defaultMessage: 'No credit requirements found.',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
47
src/schedule-and-details/data/api.js
Normal file
47
src/schedule-and-details/data/api.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import { camelCaseObject, getConfig } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { convertObjectToSnakeCase } from '../../utils';
|
||||
|
||||
const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
|
||||
export const getCourseDetailsApiUrl = (courseId) => `${getApiBaseUrl()}/api/contentstore/v1/course_details/${courseId}`;
|
||||
export const getCourseSettingsApiUrl = (courseId) => `${getApiBaseUrl()}/api/contentstore/v1/course_settings/${courseId}`;
|
||||
export const getUploadAssetsUrl = (courseId) => `${getApiBaseUrl()}/assets/${courseId}/`;
|
||||
|
||||
/**
|
||||
* Get course details.
|
||||
* @param {string} courseId
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function getCourseDetails(courseId) {
|
||||
const { data } = await getAuthenticatedHttpClient().get(
|
||||
`${getCourseDetailsApiUrl(courseId)}`,
|
||||
);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update course details.
|
||||
* @param {string} courseId
|
||||
* @param {object} details
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function updateCourseDetails(courseId, details) {
|
||||
const { data } = await getAuthenticatedHttpClient().put(
|
||||
`${getCourseDetailsApiUrl(courseId)}`,
|
||||
convertObjectToSnakeCase(details, true),
|
||||
);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get course settings.
|
||||
* @param {string} courseId
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function getCourseSettings(courseId) {
|
||||
const { data } = await getAuthenticatedHttpClient().get(
|
||||
`${getCourseSettingsApiUrl(courseId)}`,
|
||||
);
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
5
src/schedule-and-details/data/selectors.js
Normal file
5
src/schedule-and-details/data/selectors.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const getLoadingDetailsStatus = (state) => state.scheduleAndDetails.loadingDetailsStatus;
|
||||
export const getLoadingSettingsStatus = (state) => state.scheduleAndDetails.loadingSettingsStatus;
|
||||
export const getSavingStatus = (state) => state.scheduleAndDetails.savingStatus;
|
||||
export const getCourseDetails = state => state.scheduleAndDetails.courseDetails;
|
||||
export const getCourseSettings = (state) => state.scheduleAndDetails.courseSettings;
|
||||
48
src/schedule-and-details/data/slice.js
Normal file
48
src/schedule-and-details/data/slice.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { RequestStatus } from '../../data/constants';
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'scheduleAndDetails',
|
||||
initialState: {
|
||||
loadingDetailsStatus: RequestStatus.IN_PROGRESS,
|
||||
loadingSettingsStatus: RequestStatus.IN_PROGRESS,
|
||||
savingStatus: '',
|
||||
courseDetails: {},
|
||||
courseSettings: {},
|
||||
},
|
||||
reducers: {
|
||||
updateLoadingDetailsStatus: (state, { payload }) => {
|
||||
state.loadingDetailsStatus = payload.status;
|
||||
},
|
||||
updateLoadingSettingsStatus: (state, { payload }) => {
|
||||
state.loadingSettingsStatus = payload.status;
|
||||
},
|
||||
updateSavingStatus: (state, { payload }) => {
|
||||
state.savingStatus = payload.status;
|
||||
},
|
||||
updateCourseDetailsSuccess: (state, { payload }) => {
|
||||
Object.assign(state.courseDetails, payload);
|
||||
},
|
||||
fetchCourseDetailsSuccess: (state, { payload }) => {
|
||||
Object.assign(state.courseDetails, payload);
|
||||
},
|
||||
fetchCourseSettingsSuccess: (state, { payload }) => {
|
||||
Object.assign(state.courseSettings, payload);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const {
|
||||
updateSavingStatus,
|
||||
updateLoadingDetailsStatus,
|
||||
updateLoadingSettingsStatus,
|
||||
updateCourseDetailsSuccess,
|
||||
fetchCourseDetailsSuccess,
|
||||
fetchCourseSettingsSuccess,
|
||||
} = slice.actions;
|
||||
|
||||
export const {
|
||||
reducer,
|
||||
} = slice;
|
||||
68
src/schedule-and-details/data/thunks.js
Normal file
68
src/schedule-and-details/data/thunks.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import { RequestStatus } from '../../data/constants';
|
||||
import {
|
||||
getCourseDetails,
|
||||
updateCourseDetails,
|
||||
getCourseSettings,
|
||||
} from './api';
|
||||
import {
|
||||
updateSavingStatus,
|
||||
updateLoadingDetailsStatus,
|
||||
updateLoadingSettingsStatus,
|
||||
fetchCourseDetailsSuccess,
|
||||
updateCourseDetailsSuccess,
|
||||
fetchCourseSettingsSuccess,
|
||||
} from './slice';
|
||||
|
||||
export function fetchCourseDetailsQuery(courseId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateLoadingDetailsStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
|
||||
try {
|
||||
const detailsValues = await getCourseDetails(courseId);
|
||||
dispatch(fetchCourseDetailsSuccess(detailsValues));
|
||||
dispatch(updateLoadingDetailsStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 403) {
|
||||
dispatch(updateLoadingDetailsStatus({ courseId, status: RequestStatus.DENIED }));
|
||||
} else {
|
||||
dispatch(updateLoadingDetailsStatus({ status: RequestStatus.FAILED }));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function updateCourseDetailsQuery(courseId, details) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
|
||||
try {
|
||||
const detailsValues = await updateCourseDetails(courseId, details);
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
dispatch(updateCourseDetailsSuccess(detailsValues));
|
||||
return true;
|
||||
} catch (error) {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchCourseSettingsQuery(courseId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateLoadingSettingsStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
|
||||
try {
|
||||
const settingsValues = await getCourseSettings(courseId);
|
||||
dispatch(fetchCourseSettingsSuccess(settingsValues));
|
||||
dispatch(updateLoadingSettingsStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 403) {
|
||||
dispatch(updateLoadingSettingsStatus({ courseId, status: RequestStatus.DENIED }));
|
||||
} else {
|
||||
dispatch(updateLoadingSettingsStatus({ status: RequestStatus.FAILED }));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
.dropdown-language {
|
||||
.dropdown-menu {
|
||||
overflow: auto;
|
||||
height: 20rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseSettingsMock } from '../__mocks__';
|
||||
import messages from './messages';
|
||||
import DetailsSection from '.';
|
||||
|
||||
describe('<DetailsSection />', () => {
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<DetailsSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
language: courseSettingsMock.languageOptions[1][0],
|
||||
languageOptions: courseSettingsMock.languageOptions,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
it('renders details section successfully', () => {
|
||||
const { getByText, getByRole } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
expect(getByText(messages.detailsTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.detailsDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.dropdownHelpText.defaultMessage)).toBeInTheDocument();
|
||||
expect(
|
||||
getByRole('button', { name: courseSettingsMock.languageOptions[1][1] }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if dropdown value changed', () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const option = getByRole('button', {
|
||||
name: courseSettingsMock.languageOptions[1][1],
|
||||
});
|
||||
fireEvent.click(option);
|
||||
const anotherOption = getByRole('button', {
|
||||
name: courseSettingsMock.languageOptions[0][1],
|
||||
});
|
||||
|
||||
waitFor(() => expect(anotherOption));
|
||||
fireEvent.click(anotherOption);
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
courseSettingsMock.languageOptions[0][0],
|
||||
'language',
|
||||
);
|
||||
});
|
||||
|
||||
it('should render an empty option if no option is selected', () => {
|
||||
const initialProps = { ...props, language: '' };
|
||||
const { getByRole } = render(<RootWrapper {...initialProps} />);
|
||||
expect(
|
||||
getByRole('button', { name: messages.dropdownEmpty.defaultMessage }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
61
src/schedule-and-details/details-section/index.jsx
Normal file
61
src/schedule-and-details/details-section/index.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Form, Dropdown } from '@edx/paragon';
|
||||
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import messages from './messages';
|
||||
|
||||
const DetailsSection = ({
|
||||
language, languageOptions, onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const formattedLanguage = () => {
|
||||
const result = languageOptions.find((arr) => arr[0] === language);
|
||||
return result ? result[1] : intl.formatMessage(messages.dropdownEmpty);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-container details-section">
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.detailsTitle)}
|
||||
description={intl.formatMessage(messages.detailsDescription)}
|
||||
/>
|
||||
<Form.Group className="form-group-custom dropdown-language">
|
||||
<Form.Label>{intl.formatMessage(messages.dropdownLabel)}</Form.Label>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle variant="outline-primary" id="languageDropdown">
|
||||
{formattedLanguage()}
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{languageOptions.map((option) => (
|
||||
<Dropdown.Item
|
||||
key={option[0]}
|
||||
onClick={() => onChange(option[0], 'language')}
|
||||
>
|
||||
{option[1]}
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<Form.Control.Feedback>
|
||||
{intl.formatMessage(messages.dropdownHelpText)}
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
DetailsSection.defaultProps = {
|
||||
language: '',
|
||||
};
|
||||
|
||||
DetailsSection.propTypes = {
|
||||
language: PropTypes.string,
|
||||
languageOptions: PropTypes.arrayOf(
|
||||
PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
|
||||
).isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default DetailsSection;
|
||||
26
src/schedule-and-details/details-section/messages.js
Normal file
26
src/schedule-and-details/details-section/messages.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
detailsTitle: {
|
||||
id: 'course-authoring.schedule-section.details.title',
|
||||
defaultMessage: 'Course details',
|
||||
},
|
||||
detailsDescription: {
|
||||
id: 'course-authoring.schedule-section.details.description',
|
||||
defaultMessage: 'Provide useful information about your course',
|
||||
},
|
||||
dropdownLabel: {
|
||||
id: 'course-authoring.schedule-section.details.dropdown.label',
|
||||
defaultMessage: 'Course language',
|
||||
},
|
||||
dropdownHelpText: {
|
||||
id: 'course-authoring.schedule-section.details.dropdown.help-text',
|
||||
defaultMessage: 'Identify the course language here. This is used to assist users find courses that are taught in a specific language. It is also used to localize the \'From:\' field in bulk emails.',
|
||||
},
|
||||
dropdownEmpty: {
|
||||
id: 'course-authoring.schedule-section.details.dropdown.empty',
|
||||
defaultMessage: 'Select language',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
106
src/schedule-and-details/hooks.jsx
Normal file
106
src/schedule-and-details/hooks.jsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import { getSavingStatus } from './data/selectors';
|
||||
import { validateScheduleAndDetails, updateWithDefaultValues } from './utils';
|
||||
|
||||
const useSaveValuesPrompt = (
|
||||
courseId,
|
||||
updateDataQuery,
|
||||
initialEditedData = {},
|
||||
) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const savingStatus = useSelector(getSavingStatus);
|
||||
const [editedValues, setEditedValues] = useState(initialEditedData);
|
||||
const [showSuccessfulAlert, setShowSuccessfulAlert] = useState(false);
|
||||
const [showModifiedAlert, setShowModifiedAlert] = useState(false);
|
||||
const [isQueryPending, setIsQueryPending] = useState(false);
|
||||
const [isEditableState, setIsEditableState] = useState(false);
|
||||
const [errorFields, setErrorFields] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isQueryPending && !isEditableState) {
|
||||
setEditedValues(initialEditedData);
|
||||
}
|
||||
}, [initialEditedData]);
|
||||
|
||||
useEffect(() => {
|
||||
const errors = validateScheduleAndDetails(editedValues, intl);
|
||||
setErrorFields(errors);
|
||||
}, [editedValues]);
|
||||
|
||||
const handleValuesChange = (value, fieldName) => {
|
||||
setIsEditableState(true);
|
||||
setShowSuccessfulAlert(false);
|
||||
|
||||
if (editedValues[fieldName] !== value) {
|
||||
setEditedValues((prevEditedValues) => ({
|
||||
...prevEditedValues,
|
||||
[fieldName]: value || '',
|
||||
}));
|
||||
|
||||
if (!showModifiedAlert) {
|
||||
setShowModifiedAlert(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleResetValues = () => {
|
||||
setIsEditableState(false);
|
||||
setEditedValues(initialEditedData || {});
|
||||
setShowModifiedAlert(false);
|
||||
setShowSuccessfulAlert(false);
|
||||
};
|
||||
|
||||
const handleUpdateValues = () => {
|
||||
setIsQueryPending(true);
|
||||
setIsEditableState(false);
|
||||
};
|
||||
|
||||
const handleInternetConnectionFailed = () => {
|
||||
setShowModifiedAlert(false);
|
||||
setShowSuccessfulAlert(false);
|
||||
setIsQueryPending(false);
|
||||
};
|
||||
|
||||
const handleQueryProcessing = () => {
|
||||
setShowSuccessfulAlert(false);
|
||||
dispatch(updateDataQuery(courseId, updateWithDefaultValues(editedValues)));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (savingStatus === RequestStatus.SUCCESSFUL) {
|
||||
setIsQueryPending(false);
|
||||
setShowSuccessfulAlert(true);
|
||||
setTimeout(() => setShowSuccessfulAlert(false), 15000);
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
|
||||
if (!isEditableState) {
|
||||
setShowModifiedAlert(false);
|
||||
}
|
||||
}
|
||||
}, [savingStatus]);
|
||||
|
||||
return {
|
||||
errorFields,
|
||||
savingStatus,
|
||||
editedValues,
|
||||
isQueryPending,
|
||||
isEditableState,
|
||||
showModifiedAlert,
|
||||
showSuccessfulAlert,
|
||||
dispatch,
|
||||
setErrorFields,
|
||||
handleResetValues,
|
||||
handleValuesChange,
|
||||
handleUpdateValues,
|
||||
handleQueryProcessing,
|
||||
handleInternetConnectionFailed,
|
||||
};
|
||||
};
|
||||
|
||||
/* eslint-disable-next-line import/prefer-default-export */
|
||||
export { useSaveValuesPrompt };
|
||||
355
src/schedule-and-details/index.jsx
Normal file
355
src/schedule-and-details/index.jsx
Normal file
@@ -0,0 +1,355 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
Container, Button, Layout, StatefulButton,
|
||||
} from '@edx/paragon';
|
||||
import {
|
||||
CheckCircle as CheckCircleIcon,
|
||||
Warning as WarningIcon,
|
||||
} from '@edx/paragon/icons';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import Placeholder from '@edx/frontend-lib-content-components';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import AlertMessage from '../generic/alert-message';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import { STATEFUL_BUTTON_STATES } from '../constants';
|
||||
import {
|
||||
fetchCourseSettingsQuery,
|
||||
fetchCourseDetailsQuery,
|
||||
updateCourseDetailsQuery,
|
||||
} from './data/thunks';
|
||||
import {
|
||||
getCourseSettings,
|
||||
getCourseDetails,
|
||||
getLoadingDetailsStatus,
|
||||
getLoadingSettingsStatus,
|
||||
} from './data/selectors';
|
||||
import BasicSection from './basic-section';
|
||||
import CreditSection from './credit-section';
|
||||
import DetailsSection from './details-section';
|
||||
import IntroducingSection from './introducing-section';
|
||||
import PacingSection from './pacing-section';
|
||||
import ScheduleSection from './schedule-section';
|
||||
import LearningOutcomesSection from './learning-outcomes-section';
|
||||
import InstructorsSection from './instructors-section';
|
||||
import RequirementsSection from './requirements-section';
|
||||
import LicenseSection from './license-section';
|
||||
import ScheduleSidebar from './schedule-sidebar';
|
||||
import messages from './messages';
|
||||
import { useSaveValuesPrompt } from './hooks';
|
||||
|
||||
const ScheduleAndDetails = ({ intl, courseId }) => {
|
||||
const courseSettings = useSelector(getCourseSettings);
|
||||
const courseDetails = useSelector(getCourseDetails);
|
||||
const loadingDetailsStatus = useSelector(getLoadingDetailsStatus);
|
||||
const loadingSettingsStatus = useSelector(getLoadingSettingsStatus);
|
||||
const isLoading = loadingDetailsStatus === RequestStatus.IN_PROGRESS
|
||||
|| loadingSettingsStatus === RequestStatus.IN_PROGRESS;
|
||||
|
||||
const {
|
||||
errorFields,
|
||||
savingStatus,
|
||||
editedValues,
|
||||
isQueryPending,
|
||||
isEditableState,
|
||||
showModifiedAlert,
|
||||
showSuccessfulAlert,
|
||||
dispatch,
|
||||
handleResetValues,
|
||||
handleValuesChange,
|
||||
handleUpdateValues,
|
||||
handleQueryProcessing,
|
||||
handleInternetConnectionFailed,
|
||||
} = useSaveValuesPrompt(courseId, updateCourseDetailsQuery, courseDetails);
|
||||
|
||||
const {
|
||||
platformName,
|
||||
isCreditCourse,
|
||||
upgradeDeadline,
|
||||
languageOptions,
|
||||
marketingEnabled,
|
||||
licensingEnabled,
|
||||
aboutPageEditable,
|
||||
courseDisplayName,
|
||||
sidebarHtmlEnabled,
|
||||
lmsLinkForAboutPage,
|
||||
enrollmentEndEditable,
|
||||
isEntranceExamsEnabled,
|
||||
creditEligibilityEnabled,
|
||||
shortDescriptionEditable,
|
||||
enableExtendedCourseDetails,
|
||||
isPrerequisiteCoursesEnabled,
|
||||
mfeProctoredExamSettingsUrl,
|
||||
possiblePreRequisiteCourses,
|
||||
canShowCertificateAvailableDateField,
|
||||
} = courseSettings;
|
||||
|
||||
const {
|
||||
org,
|
||||
courseId: courseNumber,
|
||||
run,
|
||||
title,
|
||||
effort,
|
||||
endDate,
|
||||
license,
|
||||
language,
|
||||
subtitle,
|
||||
overview,
|
||||
duration,
|
||||
selfPaced,
|
||||
startDate,
|
||||
introVideo,
|
||||
description,
|
||||
learningInfo,
|
||||
enrollmentEnd,
|
||||
instructorInfo,
|
||||
enrollmentStart,
|
||||
shortDescription,
|
||||
aboutSidebarHtml,
|
||||
preRequisiteCourses,
|
||||
entranceExamEnabled,
|
||||
courseImageAssetPath,
|
||||
bannerImageAssetPath,
|
||||
certificateAvailableDate,
|
||||
entranceExamMinimumScorePct,
|
||||
certificatesDisplayBehavior,
|
||||
videoThumbnailImageAssetPath,
|
||||
} = editedValues;
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchCourseSettingsQuery(courseId));
|
||||
dispatch(fetchCourseDetailsQuery(courseId));
|
||||
}, [courseId]);
|
||||
|
||||
if (isLoading) {
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (loadingDetailsStatus === RequestStatus.DENIED || loadingSettingsStatus === RequestStatus.DENIED) {
|
||||
return (
|
||||
<div className="row justify-content-center m-6">
|
||||
<Placeholder />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const showCreditSection = creditEligibilityEnabled && isCreditCourse;
|
||||
const showRequirementsSection = aboutPageEditable || isPrerequisiteCoursesEnabled || isEntranceExamsEnabled;
|
||||
const hasErrors = !!Object.keys(errorFields).length;
|
||||
const updateValuesButtonState = {
|
||||
labels: {
|
||||
default: intl.formatMessage(messages.buttonSaveText),
|
||||
pending: intl.formatMessage(messages.buttonSavingText),
|
||||
},
|
||||
disabledStates: [STATEFUL_BUTTON_STATES.pending],
|
||||
};
|
||||
const alertWhileSavingTitle = hasErrors
|
||||
? intl.formatMessage(messages.alertWarningOnSaveWithError)
|
||||
: intl.formatMessage(messages.alertWarning);
|
||||
|
||||
const alertWhileSavingDescription = hasErrors
|
||||
? intl.formatMessage(messages.alertWarningDescriptionsOnSaveWithError)
|
||||
: intl.formatMessage(messages.alertWarningDescriptions);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container size="xl" className="m-4">
|
||||
<div className="mt-5">
|
||||
<AlertMessage
|
||||
show={showSuccessfulAlert}
|
||||
variant="success"
|
||||
icon={CheckCircleIcon}
|
||||
title={intl.formatMessage(messages.alertSuccess)}
|
||||
aria-hidden="true"
|
||||
aria-labelledby={intl.formatMessage(
|
||||
messages.alertSuccessAriaLabelledby,
|
||||
)}
|
||||
aria-describedby={intl.formatMessage(
|
||||
messages.alertSuccessAriaDescribedby,
|
||||
)}
|
||||
/>
|
||||
<header>
|
||||
<span className="small text-gray-700">
|
||||
{intl.formatMessage(messages.headingSubtitle)}
|
||||
</span>
|
||||
<h2 className="mb-4 pb-1">
|
||||
{intl.formatMessage(messages.headingTitle)}
|
||||
</h2>
|
||||
</header>
|
||||
</div>
|
||||
<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>
|
||||
<div>
|
||||
<BasicSection
|
||||
org={org}
|
||||
courseNumber={courseNumber}
|
||||
run={run}
|
||||
lmsLinkForAboutPage={lmsLinkForAboutPage}
|
||||
marketingEnabled={marketingEnabled}
|
||||
courseDisplayName={courseDisplayName}
|
||||
platformName={platformName}
|
||||
/>
|
||||
{showCreditSection && (
|
||||
<CreditSection
|
||||
creditRequirements={courseSettings?.creditRequirements}
|
||||
/>
|
||||
)}
|
||||
<PacingSection
|
||||
selfPaced={selfPaced}
|
||||
startDate={startDate}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
<ScheduleSection
|
||||
endDate={endDate}
|
||||
startDate={startDate}
|
||||
errorFields={errorFields}
|
||||
platformName={platformName}
|
||||
enrollmentEnd={enrollmentEnd}
|
||||
enrollmentStart={enrollmentStart}
|
||||
upgradeDeadline={upgradeDeadline}
|
||||
enrollmentEndEditable={enrollmentEndEditable}
|
||||
certificateAvailableDate={certificateAvailableDate}
|
||||
certificatesDisplayBehavior={certificatesDisplayBehavior}
|
||||
canShowCertificateAvailableDateField={canShowCertificateAvailableDateField}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
{aboutPageEditable && (
|
||||
<DetailsSection
|
||||
language={language}
|
||||
languageOptions={languageOptions}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
)}
|
||||
<IntroducingSection
|
||||
title={title}
|
||||
overview={overview}
|
||||
duration={duration}
|
||||
subtitle={subtitle}
|
||||
introVideo={introVideo}
|
||||
description={description}
|
||||
aboutSidebarHtml={aboutSidebarHtml}
|
||||
shortDescription={shortDescription}
|
||||
aboutPageEditable={aboutPageEditable}
|
||||
sidebarHtmlEnabled={sidebarHtmlEnabled}
|
||||
lmsLinkForAboutPage={lmsLinkForAboutPage}
|
||||
courseImageAssetPath={courseImageAssetPath}
|
||||
bannerImageAssetPath={bannerImageAssetPath}
|
||||
shortDescriptionEditable={shortDescriptionEditable}
|
||||
enableExtendedCourseDetails={enableExtendedCourseDetails}
|
||||
videoThumbnailImageAssetPath={videoThumbnailImageAssetPath}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
{enableExtendedCourseDetails && (
|
||||
<>
|
||||
<LearningOutcomesSection
|
||||
learningInfo={learningInfo}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
<InstructorsSection
|
||||
instructors={instructorInfo?.instructors}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{showRequirementsSection && (
|
||||
<RequirementsSection
|
||||
effort={effort}
|
||||
errorFields={errorFields}
|
||||
aboutPageEditable={aboutPageEditable}
|
||||
entranceExamEnabled={entranceExamEnabled}
|
||||
preRequisiteCourses={preRequisiteCourses}
|
||||
isEntranceExamsEnabled={isEntranceExamsEnabled}
|
||||
possiblePreRequisiteCourses={possiblePreRequisiteCourses}
|
||||
entranceExamMinimumScorePct={entranceExamMinimumScorePct}
|
||||
isPrerequisiteCoursesEnabled={
|
||||
isPrerequisiteCoursesEnabled
|
||||
}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
)}
|
||||
{licensingEnabled && (
|
||||
<LicenseSection
|
||||
license={license}
|
||||
onChange={handleValuesChange}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
</Layout.Element>
|
||||
<Layout.Element>
|
||||
<ScheduleSidebar
|
||||
courseId={courseId}
|
||||
proctoredExamSettingsUrl={mfeProctoredExamSettingsUrl}
|
||||
/>
|
||||
</Layout.Element>
|
||||
</Layout>
|
||||
</section>
|
||||
</Container>
|
||||
<div className="alert-toast">
|
||||
{!isEditableState && (
|
||||
<InternetConnectionAlert
|
||||
isFailed={savingStatus === RequestStatus.FAILED}
|
||||
isQueryPending={isQueryPending}
|
||||
onQueryProcessing={handleQueryProcessing}
|
||||
onInternetConnectionFailed={handleInternetConnectionFailed}
|
||||
/>
|
||||
)}
|
||||
<AlertMessage
|
||||
show={showModifiedAlert}
|
||||
aria-hidden={showModifiedAlert}
|
||||
aria-labelledby={intl.formatMessage(
|
||||
messages.alertWarningAriaLabelledby,
|
||||
)}
|
||||
aria-describedby={intl.formatMessage(
|
||||
messages.alertWarningAriaDescribedby,
|
||||
)}
|
||||
role="dialog"
|
||||
actions={[
|
||||
!isQueryPending && (
|
||||
<Button
|
||||
key="cancel-button"
|
||||
variant="tertiary"
|
||||
onClick={handleResetValues}
|
||||
>
|
||||
{intl.formatMessage(messages.buttonCancelText)}
|
||||
</Button>
|
||||
),
|
||||
<StatefulButton
|
||||
key="save-button"
|
||||
onClick={handleUpdateValues}
|
||||
disabled={hasErrors}
|
||||
state={
|
||||
isQueryPending
|
||||
? STATEFUL_BUTTON_STATES.pending
|
||||
: STATEFUL_BUTTON_STATES.default
|
||||
}
|
||||
{...updateValuesButtonState}
|
||||
/>,
|
||||
].filter(Boolean)}
|
||||
variant="warning"
|
||||
icon={WarningIcon}
|
||||
title={alertWhileSavingTitle}
|
||||
description={alertWhileSavingDescription}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ScheduleAndDetails.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
courseId: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(ScheduleAndDetails);
|
||||
@@ -0,0 +1,11 @@
|
||||
.instructors-section {
|
||||
.instructors-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 1.875rem;
|
||||
padding-inline-start: 0;
|
||||
list-style-type: none;
|
||||
padding-top: $spacer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act, fireEvent, render, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../__mocks__';
|
||||
import messages from './messages';
|
||||
import instructorMessages from './instructor-container/messages';
|
||||
import InstructorsSection from '.';
|
||||
|
||||
const onChangeMock = jest.fn();
|
||||
const courseIdMock = 'course-id-bar';
|
||||
|
||||
// Mock the TextareaAutosize component
|
||||
jest.mock('react-textarea-autosize', () => jest.fn((props) => (
|
||||
<textarea
|
||||
{...props}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
/>
|
||||
)));
|
||||
|
||||
jest.mock('react-redux', () => ({
|
||||
useSelector: jest.fn(),
|
||||
useDispatch: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'),
|
||||
useParams: () => ({
|
||||
courseId: courseIdMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<InstructorsSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
instructors: courseDetailsMock.instructorInfo.instructors,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<InstructorsSection />', () => {
|
||||
it('renders section successfully', () => {
|
||||
const { getByText, getByRole } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.instructorsTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.instructorsDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.instructorAdd.defaultMessage })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should create another instructor form on click Add new instructor', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const addButton = getByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(addButton);
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete instructor form on click Delete', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteButton = getByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(deleteButton);
|
||||
});
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith({ instructors: [] }, 'instructorInfo');
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: instructorMessages.instructorDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const inputName = getByPlaceholderText(instructorMessages.instructorNameInputPlaceholder.defaultMessage);
|
||||
act(() => {
|
||||
fireEvent.change(inputName, { target: { value: 'abc' } });
|
||||
});
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith({
|
||||
instructors: [{
|
||||
bio: props.instructors[0].bio,
|
||||
image: props.instructors[0].image,
|
||||
name: 'abc',
|
||||
organization: props.instructors[0].organization,
|
||||
title: props.instructors[0].title,
|
||||
}],
|
||||
}, 'instructorInfo');
|
||||
});
|
||||
});
|
||||
96
src/schedule-and-details/instructors-section/index.jsx
Normal file
96
src/schedule-and-details/instructors-section/index.jsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Button } from '@edx/paragon';
|
||||
import { Add as AddIcon } from '@edx/paragon/icons';
|
||||
|
||||
import InstructorContainer from './instructor-container';
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import messages from './messages';
|
||||
|
||||
const InstructorsSection = ({ instructors, onChange }) => {
|
||||
const intl = useIntl();
|
||||
const newInstructor = {
|
||||
bio: '',
|
||||
image: '',
|
||||
name: '',
|
||||
organization: '',
|
||||
title: '',
|
||||
};
|
||||
|
||||
const handleChange = (value, idx, field) => {
|
||||
const updatedInstructors = instructors.map((instructor, index) => {
|
||||
if (index === idx) {
|
||||
return {
|
||||
...instructor,
|
||||
[field]: value,
|
||||
};
|
||||
}
|
||||
return instructor;
|
||||
});
|
||||
|
||||
const updatedInstructorInfo = {
|
||||
instructors: updatedInstructors,
|
||||
};
|
||||
onChange(updatedInstructorInfo, 'instructorInfo');
|
||||
};
|
||||
|
||||
const handleDelete = (idx) => {
|
||||
const updatedInstructorInfo = {
|
||||
instructors: [...instructors],
|
||||
};
|
||||
updatedInstructorInfo.instructors.splice(idx, 1);
|
||||
onChange(updatedInstructorInfo, 'instructorInfo');
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
const updatedInstructorInfo = {
|
||||
instructors: [...instructors, newInstructor],
|
||||
};
|
||||
|
||||
onChange(updatedInstructorInfo, 'instructorInfo');
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-container instructors-section">
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.instructorsTitle)}
|
||||
description={intl.formatMessage(messages.instructorsDescription)}
|
||||
/>
|
||||
<ul className="instructors-list">
|
||||
{instructors.map((instructor, idx) => (
|
||||
<InstructorContainer
|
||||
instructor={instructor}
|
||||
key={uuid}
|
||||
idx={idx}
|
||||
onDelete={handleDelete}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
<Button iconBefore={AddIcon} variant="primary" onClick={handleAdd}>
|
||||
{intl.formatMessage(messages.instructorAdd)}
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
InstructorsSection.defaultProps = {
|
||||
instructors: [],
|
||||
};
|
||||
|
||||
InstructorsSection.propTypes = {
|
||||
instructors: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
bio: PropTypes.string,
|
||||
image: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
organization: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
}),
|
||||
),
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default InstructorsSection;
|
||||
@@ -0,0 +1,129 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, render, act } from '@testing-library/react';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
|
||||
import initializeStore from '../../../store';
|
||||
|
||||
import { courseDetailsMock } from '../../__mocks__';
|
||||
import messages from './messages';
|
||||
import InstructorContainer from '.';
|
||||
|
||||
let store;
|
||||
|
||||
const onDeleteMock = jest.fn();
|
||||
const onChangeMock = jest.fn();
|
||||
const courseIdMock = 'course-id-bar';
|
||||
jest.mock('react-router', () => ({
|
||||
...jest.requireActual('react-router'),
|
||||
useParams: () => ({
|
||||
courseId: courseIdMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock the TextareaAutosize component
|
||||
jest.mock('react-textarea-autosize', () => jest.fn((props) => (
|
||||
<textarea
|
||||
{...props}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
/>
|
||||
)));
|
||||
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<AppProvider store={store}>
|
||||
<InstructorContainer {...props} />
|
||||
</AppProvider>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
instructor: courseDetailsMock.instructorInfo.instructors[0],
|
||||
idx: 0,
|
||||
onChange: onChangeMock,
|
||||
onDelete: onDeleteMock,
|
||||
};
|
||||
|
||||
describe('<InstructorContainer />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
});
|
||||
|
||||
it('renders successfully', () => {
|
||||
const { getByText, getByPlaceholderText } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
expect(
|
||||
getByText(messages.instructorNameLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.instructorTitleLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.instructorOrganizationLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.instructorBioLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.instructorPhotoLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
getByPlaceholderText(messages.instructorNameInputPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByPlaceholderText(messages.instructorTitleInputPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByPlaceholderText(messages.instructorOrganizationInputPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByPlaceholderText(messages.instructorBioInputPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByPlaceholderText(messages.instructorPhotoInputPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display input values', () => {
|
||||
const { getByDisplayValue } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
|
||||
expect(getByDisplayValue(props.instructor.name)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.instructor.title)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.instructor.organization)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.instructor.bio)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.instructor.image)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', async () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const nameInput = getByPlaceholderText(messages.instructorNameInputPlaceholder.defaultMessage);
|
||||
await act(() => {
|
||||
fireEvent.change(nameInput, { target: { value: 'abc' } });
|
||||
});
|
||||
expect(onChangeMock).toHaveBeenCalledWith('abc', props.idx, 'name');
|
||||
});
|
||||
|
||||
it('should call onDelete if button delete clicked', async () => {
|
||||
const { getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteBtn = getByRole('button', { name: messages.instructorDelete.defaultMessage });
|
||||
await act(() => {
|
||||
fireEvent.click(deleteBtn);
|
||||
});
|
||||
expect(onDeleteMock).toHaveBeenCalledWith(props.idx);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import {
|
||||
Card, Form, Col, Button,
|
||||
} from '@edx/paragon';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import CourseUploadImage from '../../../generic/course-upload-image';
|
||||
import messages from './messages';
|
||||
|
||||
const InstructorContainer = ({
|
||||
instructor, idx, onDelete, onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Card className="p-3.5" key={idx}>
|
||||
<Card.Body>
|
||||
<Form>
|
||||
<Form.Row>
|
||||
<Form.Group as={Col} className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.instructorNameLabel)}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
value={instructor?.name}
|
||||
placeholder={intl.formatMessage(messages.instructorNameInputPlaceholder)}
|
||||
onChange={(e) => onChange(e.target.value, idx, 'name')}
|
||||
/>
|
||||
<Form.Text>
|
||||
{intl.formatMessage(messages.instructorNameHelpText)}
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group as={Col} className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.instructorTitleLabel)}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
value={instructor?.title}
|
||||
placeholder={intl.formatMessage(messages.instructorTitleInputPlaceholder)}
|
||||
onChange={(e) => onChange(e.target.value, idx, 'title')}
|
||||
/>
|
||||
<Form.Text>
|
||||
{intl.formatMessage(messages.instructorTitleHelpText)}
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group as={Col} className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.instructorOrganizationLabel)}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
value={instructor?.organization}
|
||||
placeholder={intl.formatMessage(messages.instructorOrganizationInputPlaceholder)}
|
||||
onChange={(e) => onChange(e.target.value, idx, 'organization')}
|
||||
/>
|
||||
<Form.Text>
|
||||
{intl.formatMessage(messages.instructorOrganizationHelpText)}
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
</Form.Row>
|
||||
<Form.Row>
|
||||
<Form.Group as={Col} className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.instructorBioLabel)}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as={TextareaAutosize}
|
||||
value={instructor?.bio}
|
||||
placeholder={intl.formatMessage(messages.instructorBioInputPlaceholder)}
|
||||
onChange={(e) => onChange(e.target.value, idx, 'bio')}
|
||||
/>
|
||||
<Form.Text>
|
||||
{intl.formatMessage(messages.instructorBioHelpText)}
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
</Form.Row>
|
||||
<Form.Row className="pl-1 pr-2.5">
|
||||
<CourseUploadImage
|
||||
label={intl.formatMessage(messages.instructorPhotoLabel)}
|
||||
assetImagePath={instructor?.image}
|
||||
assetImageField="image"
|
||||
customInputPlaceholder={intl.formatMessage(
|
||||
messages.instructorPhotoInputPlaceholder,
|
||||
)}
|
||||
customHelpText={intl.formatMessage(messages.instructorPhotoHelpText)}
|
||||
onChange={(value, field) => onChange(value, idx, field)}
|
||||
/>
|
||||
</Form.Row>
|
||||
</Form>
|
||||
</Card.Body>
|
||||
<Card.Divider />
|
||||
<Card.Footer className="p-0 mt-2.5">
|
||||
<Button variant="outline-primary" onClick={() => onDelete(idx)}>
|
||||
{intl.formatMessage(messages.instructorDelete)}
|
||||
</Button>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
InstructorContainer.defaultProps = {
|
||||
instructor: {},
|
||||
};
|
||||
|
||||
InstructorContainer.propTypes = {
|
||||
instructor: PropTypes.shape({
|
||||
bio: PropTypes.string,
|
||||
image: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
organization: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
}),
|
||||
idx: PropTypes.number.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default InstructorContainer;
|
||||
@@ -0,0 +1,70 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
instructorNameLabel: {
|
||||
id: 'course-authoring.schedule-section.instructor.name.label',
|
||||
defaultMessage: 'Name',
|
||||
},
|
||||
instructorNameHelpText: {
|
||||
id: 'course-authoring.schedule-section.instructor.name.help-text',
|
||||
defaultMessage: 'Please add the instructor\'s name',
|
||||
},
|
||||
instructorNameInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.instructor.name.input.placeholder',
|
||||
defaultMessage: 'Instructor name',
|
||||
},
|
||||
instructorTitleLabel: {
|
||||
id: 'course-authoring.schedule-section.instructor.title.label',
|
||||
defaultMessage: 'Title',
|
||||
},
|
||||
instructorTitleHelpText: {
|
||||
id: 'course-authoring.schedule-section.instructor.title.help-text',
|
||||
defaultMessage: 'Please add the instructor\'s title',
|
||||
},
|
||||
instructorTitleInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.instructor.title.input.placeholder',
|
||||
defaultMessage: 'Instructor title',
|
||||
},
|
||||
instructorOrganizationLabel: {
|
||||
id: 'course-authoring.schedule-section.instructor.organization.label',
|
||||
defaultMessage: 'Organization',
|
||||
},
|
||||
instructorOrganizationHelpText: {
|
||||
id: 'course-authoring.schedule-section.instructor.organization.help-text',
|
||||
defaultMessage: 'Please add the institute where the instructor is associated',
|
||||
},
|
||||
instructorOrganizationInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.instructor.organization.input.placeholder',
|
||||
defaultMessage: 'Instructor organization',
|
||||
},
|
||||
instructorBioLabel: {
|
||||
id: 'course-authoring.schedule-section.instructor.bio.label',
|
||||
defaultMessage: 'Biography',
|
||||
},
|
||||
instructorBioHelpText: {
|
||||
id: 'course-authoring.schedule-section.instructor.bio.help-text',
|
||||
defaultMessage: 'Please add the instructor\'s biography',
|
||||
},
|
||||
instructorBioInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.instructor.bio.input.placeholder',
|
||||
defaultMessage: 'Instructor biography',
|
||||
},
|
||||
instructorPhotoLabel: {
|
||||
id: 'course-authoring.schedule-section.instructor.photo.label',
|
||||
defaultMessage: 'Photo',
|
||||
},
|
||||
instructorPhotoHelpText: {
|
||||
id: 'course-authoring.schedule-section.instructor.photo.help-text',
|
||||
defaultMessage: 'Please add a photo of the instructor (Note: only JPEG or PNG format supported)',
|
||||
},
|
||||
instructorPhotoInputPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.instructor.photo.input.placeholder',
|
||||
defaultMessage: 'Instructor photo URL',
|
||||
},
|
||||
instructorDelete: {
|
||||
id: 'course-authoring.schedule-section.instructor.delete',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
18
src/schedule-and-details/instructors-section/messages.js
Normal file
18
src/schedule-and-details/instructors-section/messages.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
instructorsTitle: {
|
||||
id: 'course-authoring.schedule-section.instructors.title',
|
||||
defaultMessage: 'Instructors',
|
||||
},
|
||||
instructorsDescription: {
|
||||
id: 'course-authoring.schedule-section.instructors.description',
|
||||
defaultMessage: 'Add details about the instructors for this course',
|
||||
},
|
||||
instructorAdd: {
|
||||
id: 'course-authoring.schedule-section.instructors.add-instructor',
|
||||
defaultMessage: 'Add Instructor',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -0,0 +1,7 @@
|
||||
@import "./introduction-video/IntroductionVideo";
|
||||
|
||||
.introducing-section {
|
||||
.form-group-custom:not(:last-child) {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import React from 'react';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
|
||||
import initializeStore from '../../store';
|
||||
import { courseSettingsMock, courseDetailsMock } from '../__mocks__';
|
||||
import messages from './messages';
|
||||
import IntroducingSection from '.';
|
||||
|
||||
// Mock the tinymce lib
|
||||
jest.mock('@tinymce/tinymce-react', () => {
|
||||
const originalModule = jest.requireActual('@tinymce/tinymce-react');
|
||||
return {
|
||||
__esModule: true,
|
||||
...originalModule,
|
||||
Editor: () => 'foo bar',
|
||||
};
|
||||
});
|
||||
|
||||
// Mock the TinyMceWidget from frontend-lib-content-components
|
||||
jest.mock('@edx/frontend-lib-content-components', () => ({
|
||||
TinyMceWidget: () => <div>Widget</div>,
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
let store;
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<AppProvider store={store}>
|
||||
<IntroducingSection {...props} />
|
||||
</AppProvider>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const {
|
||||
overview,
|
||||
introVideo,
|
||||
aboutSidebarHtml,
|
||||
shortDescription,
|
||||
courseImageAssetPath,
|
||||
} = courseDetailsMock;
|
||||
|
||||
const {
|
||||
aboutPageEditable, sidebarHtmlEnabled, shortDescriptionEditable, lmsLinkForAboutPage,
|
||||
} = courseSettingsMock;
|
||||
|
||||
const props = {
|
||||
intl: {},
|
||||
courseId: 'foo-course-id',
|
||||
overview,
|
||||
introVideo,
|
||||
aboutSidebarHtml,
|
||||
shortDescription,
|
||||
aboutPageEditable,
|
||||
sidebarHtmlEnabled,
|
||||
lmsLinkForAboutPage,
|
||||
courseImageAssetPath,
|
||||
shortDescriptionEditable,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<IntroducingSection />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
|
||||
store = initializeStore();
|
||||
});
|
||||
|
||||
it('renders successfully', () => {
|
||||
const { getByText, getByLabelText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.introducingTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.introducingDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseShortDescriptionLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseShortDescriptionHelpText.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.courseShortDescriptionLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseOverviewLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.courseAboutSidebarLabel.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should hide components if aboutPageEditable is false', () => {
|
||||
const initialProps = { ...props, aboutPageEditable: false };
|
||||
const { queryAllByText } = render(<RootWrapper {...initialProps} />);
|
||||
expect(queryAllByText(messages.introducingTitle.defaultMessage).length).toBe(0);
|
||||
expect(queryAllByText(messages.introducingDescription.defaultMessage).length).toBe(0);
|
||||
expect(queryAllByText(messages.courseOverviewLabel.defaultMessage).length).toBe(0);
|
||||
expect(queryAllByText(messages.courseAboutSidebarLabel.defaultMessage).length).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import { fireEvent, render, act } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../../__mocks__';
|
||||
import messages from './messages';
|
||||
import ExtendedCourseDetails from '.';
|
||||
|
||||
// Mock the TextareaAutosize component
|
||||
jest.mock('react-textarea-autosize', () => jest.fn((props) => (
|
||||
<textarea
|
||||
{...props}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
/>
|
||||
)));
|
||||
|
||||
const onChangeMock = jest.fn();
|
||||
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<ExtendedCourseDetails {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
title: courseDetailsMock.title,
|
||||
subtitle: courseDetailsMock.subtitle,
|
||||
duration: courseDetailsMock.duration,
|
||||
description: courseDetailsMock.description,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<ExtendedCourseDetails />', () => {
|
||||
it('renders successfully', () => {
|
||||
const { getByText, getByLabelText } = render(<RootWrapper {...props} />);
|
||||
expect(getByLabelText(messages.extendedTitleLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.extendedSubtitleLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.extendedDurationLabel.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.extendedDescriptionLabel.defaultMessage)).toBeInTheDocument();
|
||||
|
||||
expect(getByText(messages.extendedTitleHelpText.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.extendedSubtitleHelpText.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.extendedDurationHelpText.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.extendedDescriptionHelpText.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display input values', () => {
|
||||
const { getByDisplayValue } = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
|
||||
expect(getByDisplayValue(props.title)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.subtitle)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.duration)).toBeInTheDocument();
|
||||
expect(getByDisplayValue(props.description)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', async () => {
|
||||
const { getByLabelText } = render(<RootWrapper {...props} />);
|
||||
const input = getByLabelText(messages.extendedTitleAriaLabel.defaultMessage);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { value: 'abc' } });
|
||||
});
|
||||
expect(onChangeMock).toHaveBeenCalledWith('abc', 'title');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Form } from '@edx/paragon';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const ExtendedCourseDetails = ({
|
||||
title,
|
||||
subtitle,
|
||||
duration,
|
||||
description,
|
||||
onChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const paramsForExtendedFields = [
|
||||
{
|
||||
value: title,
|
||||
label: intl.formatMessage(messages.extendedTitleLabel),
|
||||
helpText: intl.formatMessage(messages.extendedTitleHelpText),
|
||||
ariaLabel: intl.formatMessage(messages.extendedTitleAriaLabel),
|
||||
controlName: 'title',
|
||||
maxLength: 50,
|
||||
},
|
||||
{
|
||||
value: subtitle,
|
||||
label: intl.formatMessage(messages.extendedSubtitleLabel),
|
||||
helpText: intl.formatMessage(messages.extendedSubtitleHelpText),
|
||||
ariaLabel: intl.formatMessage(messages.extendedSubtitleAriaLabel),
|
||||
controlName: 'subtitle',
|
||||
maxLength: 150,
|
||||
},
|
||||
{
|
||||
value: duration,
|
||||
label: intl.formatMessage(messages.extendedDurationLabel),
|
||||
helpText: intl.formatMessage(messages.extendedDurationHelpText),
|
||||
ariaLabel: intl.formatMessage(messages.extendedDurationAriaLabel),
|
||||
controlName: 'duration',
|
||||
maxLength: 50,
|
||||
},
|
||||
{
|
||||
value: description,
|
||||
label: intl.formatMessage(messages.extendedDescriptionLabel),
|
||||
helpText: intl.formatMessage(messages.extendedDescriptionHelpText),
|
||||
ariaLabel: intl.formatMessage(messages.extendedDescriptionAriaLabel),
|
||||
controlName: 'description',
|
||||
maxLength: 1000,
|
||||
asTextarea: true,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<>
|
||||
{paramsForExtendedFields.map((param) => (
|
||||
<Form.Group className="form-group-custom" key={param.label}>
|
||||
<Form.Label>{param.label}</Form.Label>
|
||||
<Form.Control
|
||||
as={param.asTextarea ? TextareaAutosize : 'input'}
|
||||
value={param.value}
|
||||
name={param.controlName}
|
||||
maxLength={param.maxLength}
|
||||
onChange={(e) => onChange(e.target.value, param.controlName)}
|
||||
aria-label={param.ariaLabel}
|
||||
/>
|
||||
<Form.Control.Feedback>{param.helpText}</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
ExtendedCourseDetails.defaultProps = {
|
||||
title: '',
|
||||
subtitle: '',
|
||||
duration: '',
|
||||
description: '',
|
||||
};
|
||||
|
||||
ExtendedCourseDetails.propTypes = {
|
||||
title: PropTypes.string,
|
||||
subtitle: PropTypes.string,
|
||||
duration: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ExtendedCourseDetails;
|
||||
@@ -0,0 +1,54 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
extendedTitleLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.title.label',
|
||||
defaultMessage: 'Course title',
|
||||
},
|
||||
extendedTitleHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.title.help-text',
|
||||
defaultMessage: 'Displayed as title on the course details page. Limit to 50 characters.',
|
||||
},
|
||||
extendedTitleAriaLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.title.aria-label',
|
||||
defaultMessage: 'Show course title',
|
||||
},
|
||||
extendedSubtitleLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.subtitle.label',
|
||||
defaultMessage: 'Course subtitle',
|
||||
},
|
||||
extendedSubtitleHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.subtitle.help-text',
|
||||
defaultMessage: 'Displayed as subtitle on the course details page. Limit to 150 characters.',
|
||||
},
|
||||
extendedSubtitleAriaLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.subtitle.aria-label',
|
||||
defaultMessage: 'Show course subtitle',
|
||||
},
|
||||
extendedDurationLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.duration.label',
|
||||
defaultMessage: 'Course duration',
|
||||
},
|
||||
extendedDurationHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.duration.help-text',
|
||||
defaultMessage: 'Displayed on the course details page. Limit to 50 characters.',
|
||||
},
|
||||
extendedDurationAriaLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.duration.aria-label',
|
||||
defaultMessage: 'Show course duration',
|
||||
},
|
||||
extendedDescriptionLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.description.label',
|
||||
defaultMessage: 'Course description',
|
||||
},
|
||||
extendedDescriptionHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.description.help-text',
|
||||
defaultMessage: 'Displayed on the course details page. Limit to 1000 characters.',
|
||||
},
|
||||
extendedDescriptionAriaLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.description.aria-label',
|
||||
defaultMessage: 'Show course description',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
205
src/schedule-and-details/introducing-section/index.jsx
Normal file
205
src/schedule-and-details/introducing-section/index.jsx
Normal file
@@ -0,0 +1,205 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
injectIntl,
|
||||
intlShape,
|
||||
FormattedMessage,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
import { Form, Hyperlink } from '@edx/paragon';
|
||||
|
||||
import CourseUploadImage from '../../generic/course-upload-image';
|
||||
import { WysiwygEditor } from '../../generic/WysiwygEditor';
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import IntroductionVideo from './introduction-video';
|
||||
import ExtendedCourseDetails from './extended-course-details';
|
||||
import messages from './messages';
|
||||
|
||||
const IntroducingSection = ({
|
||||
intl,
|
||||
title,
|
||||
subtitle,
|
||||
duration,
|
||||
overview,
|
||||
introVideo,
|
||||
description,
|
||||
aboutSidebarHtml,
|
||||
shortDescription,
|
||||
aboutPageEditable,
|
||||
sidebarHtmlEnabled,
|
||||
lmsLinkForAboutPage,
|
||||
courseImageAssetPath,
|
||||
bannerImageAssetPath,
|
||||
shortDescriptionEditable,
|
||||
enableExtendedCourseDetails,
|
||||
videoThumbnailImageAssetPath,
|
||||
onChange,
|
||||
}) => {
|
||||
const overviewHelpText = (
|
||||
<FormattedMessage
|
||||
id="course-authoring.schedule-section.introducing.course-overview.help-text"
|
||||
defaultMessage="Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)"
|
||||
values={{
|
||||
hyperlink: (
|
||||
<Hyperlink
|
||||
destination={lmsLinkForAboutPage}
|
||||
target="_blank"
|
||||
showLaunchIcon={false}
|
||||
>
|
||||
{intl.formatMessage(messages.courseAboutHyperlink)}
|
||||
</Hyperlink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const aboutSidebarHelpText = (
|
||||
<FormattedMessage
|
||||
id="course-authoring.schedule-section.introducing.about-sidebar.help-text"
|
||||
defaultMessage="Custom sidebar content for {hyperlink} (formatted in HTML)"
|
||||
values={{
|
||||
hyperlink: (
|
||||
<Hyperlink
|
||||
destination={lmsLinkForAboutPage}
|
||||
target="_blank"
|
||||
showLaunchIcon={false}
|
||||
>
|
||||
{intl.formatMessage(messages.courseAboutHyperlink)}
|
||||
</Hyperlink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="section-container introducing-section">
|
||||
{aboutPageEditable && (
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.introducingTitle)}
|
||||
description={intl.formatMessage(messages.introducingDescription)}
|
||||
/>
|
||||
)}
|
||||
{enableExtendedCourseDetails && (
|
||||
<ExtendedCourseDetails
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
duration={duration}
|
||||
description={description}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
{shortDescriptionEditable && (
|
||||
<Form.Group className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.courseShortDescriptionLabel)}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
as="textarea"
|
||||
value={shortDescription}
|
||||
name="shortDescription"
|
||||
onChange={(e) => onChange(e.target.value, 'shortDescription')}
|
||||
aria-label={intl.formatMessage(
|
||||
messages.courseShortDescriptionAriaLabel,
|
||||
)}
|
||||
maxLength={150}
|
||||
/>
|
||||
<Form.Control.Feedback>
|
||||
{intl.formatMessage(messages.courseShortDescriptionHelpText)}
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
)}
|
||||
{aboutPageEditable && (
|
||||
<>
|
||||
<Form.Group className="form-group-custom">
|
||||
<Form.Label>{intl.formatMessage(messages.courseOverviewLabel)}</Form.Label>
|
||||
<WysiwygEditor
|
||||
initialValue={overview}
|
||||
onChange={(value) => onChange(value, 'overview')}
|
||||
/>
|
||||
<Form.Control.Feedback>{overviewHelpText}</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
{sidebarHtmlEnabled && (
|
||||
<Form.Group className="form-group-custom">
|
||||
<Form.Label>{intl.formatMessage(messages.courseAboutSidebarLabel)}</Form.Label>
|
||||
<WysiwygEditor
|
||||
initialValue={aboutSidebarHtml}
|
||||
onChange={(value) => onChange(value, 'aboutSidebarHtml')}
|
||||
/>
|
||||
<Form.Control.Feedback>{aboutSidebarHelpText}</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
)}
|
||||
<CourseUploadImage
|
||||
label={intl.formatMessage(messages.courseCardImageLabel)}
|
||||
identifierFieldText={intl.formatMessage(messages.courseCardImageIdentifierText)}
|
||||
assetImagePath={courseImageAssetPath}
|
||||
assetImageField="courseImageAssetPath"
|
||||
imageNameField="courseImageName"
|
||||
showImageBodyText
|
||||
onChange={onChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{enableExtendedCourseDetails && (
|
||||
<>
|
||||
<CourseUploadImage
|
||||
label={intl.formatMessage(messages.courseBannerImageLabel)}
|
||||
identifierFieldText={intl.formatMessage(messages.courseBannerImageInsertText)}
|
||||
assetImagePath={bannerImageAssetPath}
|
||||
assetImageField="bannerImageAssetPath"
|
||||
imageNameField="bannerImageName"
|
||||
showImageBodyText
|
||||
onChange={onChange}
|
||||
/>
|
||||
<CourseUploadImage
|
||||
label={intl.formatMessage(messages.courseVideoThumbnailLabel)}
|
||||
identifierFieldText={intl.formatMessage(messages.courseVideoThumbnailInsertText)}
|
||||
assetImagePath={videoThumbnailImageAssetPath}
|
||||
assetImageField="videoThumbnailImageAssetPath"
|
||||
imageNameField="videoThumbnailImageName"
|
||||
showImageBodyText
|
||||
onChange={onChange}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{aboutPageEditable && (
|
||||
<IntroductionVideo introVideo={introVideo} onChange={onChange} />
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
IntroducingSection.defaultProps = {
|
||||
title: '',
|
||||
subtitle: '',
|
||||
duration: '',
|
||||
description: '',
|
||||
introVideo: '',
|
||||
shortDescription: '',
|
||||
aboutSidebarHtml: '',
|
||||
courseImageAssetPath: '',
|
||||
bannerImageAssetPath: '',
|
||||
videoThumbnailImageAssetPath: '',
|
||||
overview: '',
|
||||
};
|
||||
|
||||
IntroducingSection.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
title: PropTypes.string,
|
||||
subtitle: PropTypes.string,
|
||||
duration: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
overview: PropTypes.string,
|
||||
introVideo: PropTypes.string,
|
||||
aboutSidebarHtml: PropTypes.string,
|
||||
shortDescription: PropTypes.string,
|
||||
aboutPageEditable: PropTypes.bool.isRequired,
|
||||
sidebarHtmlEnabled: PropTypes.bool.isRequired,
|
||||
lmsLinkForAboutPage: PropTypes.string.isRequired,
|
||||
courseImageAssetPath: PropTypes.string,
|
||||
bannerImageAssetPath: PropTypes.string,
|
||||
shortDescriptionEditable: PropTypes.bool.isRequired,
|
||||
enableExtendedCourseDetails: PropTypes.bool.isRequired,
|
||||
videoThumbnailImageAssetPath: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(IntroducingSection);
|
||||
@@ -0,0 +1,10 @@
|
||||
.embed-video-container {
|
||||
@include pgn-box-shadow(1, "down");
|
||||
|
||||
border-radius: .1875rem;
|
||||
|
||||
.introduction-video {
|
||||
padding: .75rem;
|
||||
height: 23.375rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import { act, render, fireEvent } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../../__mocks__';
|
||||
import messages from './messages';
|
||||
import IntroductionVideo from '.';
|
||||
|
||||
describe('<IntroductionVideo />', () => {
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<IntroductionVideo {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
intl: {},
|
||||
introVideo: courseDetailsMock.introVideo,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
it('renders successfully', () => {
|
||||
const {
|
||||
getByText, getByPlaceholderText, getByRole, getByTitle,
|
||||
} = render(
|
||||
<RootWrapper {...props} />,
|
||||
);
|
||||
expect(
|
||||
getByText(messages.courseIntroductionVideoLabel.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByText(messages.courseIntroductionVideoHelpText.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByPlaceholderText(messages.courseIntroductionVideoPlaceholder.defaultMessage),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByRole('button', { name: messages.courseIntroductionVideoDelete.defaultMessage }),
|
||||
).toBeInTheDocument();
|
||||
expect(getByTitle(messages.courseIntroductionVideoLabel.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onChange if video input id changed', async () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(
|
||||
messages.courseIntroductionVideoPlaceholder.defaultMessage,
|
||||
);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { value: '/assets' } });
|
||||
});
|
||||
expect(onChangeMock).toHaveBeenCalledWith(
|
||||
'/assets',
|
||||
'introVideo',
|
||||
);
|
||||
});
|
||||
|
||||
it('should clear video input if button delete clicked', () => {
|
||||
const initialProps = { ...props, introVideo: 'BvgNgTPTkSo' };
|
||||
const { getByRole } = render(<RootWrapper {...initialProps} />);
|
||||
const button = getByRole('button', { name: messages.courseIntroductionVideoDelete.defaultMessage });
|
||||
fireEvent.click(button);
|
||||
expect(onChangeMock).toHaveBeenCalledWith('', 'introVideo');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Form, Button, Card } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
const IntroductionVideo = ({ intl, introVideo, onChange }) => {
|
||||
const embedVideoUrl = introVideo
|
||||
? `//www.youtube.com/embed/${introVideo}`
|
||||
: '';
|
||||
|
||||
return (
|
||||
<Form.Group className="form-group-custom">
|
||||
<Form.Label>
|
||||
{intl.formatMessage(messages.courseIntroductionVideoLabel)}
|
||||
</Form.Label>
|
||||
<Card>
|
||||
<Card.Body className="embed-video-container">
|
||||
<div className="introduction-video">
|
||||
<iframe
|
||||
title={intl.formatMessage(messages.courseIntroductionVideoLabel)}
|
||||
width="618"
|
||||
height="350"
|
||||
src={embedVideoUrl}
|
||||
frameBorder="0"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
</Card.Body>
|
||||
<Card.Divider />
|
||||
<Card.Footer className="p-2.5">
|
||||
<Form.Control
|
||||
value={introVideo || ''}
|
||||
placeholder={intl.formatMessage(messages.courseIntroductionVideoPlaceholder)}
|
||||
onChange={(e) => onChange(e.target.value, 'introVideo')}
|
||||
/>
|
||||
<Button
|
||||
variant="outline-primary"
|
||||
onClick={() => onChange('', 'introVideo')}
|
||||
disabled={!introVideo}
|
||||
>
|
||||
{intl.formatMessage(messages.courseIntroductionVideoDelete)}
|
||||
</Button>
|
||||
</Card.Footer>
|
||||
</Card>
|
||||
<Form.Control.Feedback>
|
||||
{intl.formatMessage(messages.courseIntroductionVideoHelpText)}
|
||||
</Form.Control.Feedback>
|
||||
</Form.Group>
|
||||
);
|
||||
};
|
||||
|
||||
IntroductionVideo.defaultProps = {
|
||||
introVideo: '',
|
||||
};
|
||||
|
||||
IntroductionVideo.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
introVideo: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(IntroductionVideo);
|
||||
@@ -0,0 +1,22 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
courseIntroductionVideoLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.introduction-video.label',
|
||||
defaultMessage: 'Course introduction video',
|
||||
},
|
||||
courseIntroductionVideoDelete: {
|
||||
id: 'course-authoring.schedule-section.introducing.introduction-video.delete',
|
||||
defaultMessage: 'Delete current video',
|
||||
},
|
||||
courseIntroductionVideoHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.introduction-video.help-text',
|
||||
defaultMessage: 'Enter your YouTube video\'s ID (along with any restriction parameters)',
|
||||
},
|
||||
courseIntroductionVideoPlaceholder: {
|
||||
id: 'course-authoring.schedule-section.introducing.introduction-video.placeholder',
|
||||
defaultMessage: 'your YouTube video\'s ID',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
70
src/schedule-and-details/introducing-section/messages.js
Normal file
70
src/schedule-and-details/introducing-section/messages.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
introducingTitle: {
|
||||
id: 'course-authoring.schedule-section.introducing.title',
|
||||
defaultMessage: 'Introducing your course',
|
||||
},
|
||||
introducingDescription: {
|
||||
id: 'course-authoring.schedule-section.introducing.description',
|
||||
defaultMessage: 'Information for prospective students',
|
||||
},
|
||||
courseShortDescriptionLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-short-description.label',
|
||||
defaultMessage: 'Course short description',
|
||||
},
|
||||
courseShortDescriptionAriaLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-short-description.aria-label',
|
||||
defaultMessage: 'Show course short description',
|
||||
},
|
||||
courseShortDescriptionHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-short-description.help-text',
|
||||
defaultMessage: 'Appears on the course catalog page when students roll over the course name. Limit to ~150 characters',
|
||||
},
|
||||
courseOverviewLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-overview.label',
|
||||
defaultMessage: 'Course overview',
|
||||
},
|
||||
courseOverviewHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-overview.help-text',
|
||||
defaultMessage: 'Introductions, prerequisites, FAQs that are used on {hyperlink} (formatted in HTML)',
|
||||
},
|
||||
courseAboutHyperlink: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-about.hyperlink',
|
||||
defaultMessage: 'your course summary page',
|
||||
},
|
||||
courseAboutSidebarLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-about-sidebar.label',
|
||||
defaultMessage: 'Course about sidebar HTML',
|
||||
},
|
||||
courseAboutSidebarHelpText: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-about-sidebar.help-text',
|
||||
defaultMessage: 'Custom sidebar content for {hyperlink} (formatted in HTML)',
|
||||
},
|
||||
courseCardImageLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-card-image.label',
|
||||
defaultMessage: 'Course card image',
|
||||
},
|
||||
courseCardImageIdentifierText: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-card-image.identifier-text',
|
||||
defaultMessage: 'course image',
|
||||
},
|
||||
courseBannerImageLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-banner-image.label',
|
||||
defaultMessage: 'Course banner image',
|
||||
},
|
||||
courseBannerImageInsertText: {
|
||||
id: 'course-authoring.schedule-section.introducing.course-banner-image.insert-banner',
|
||||
defaultMessage: 'banner image',
|
||||
},
|
||||
courseVideoThumbnailLabel: {
|
||||
id: 'course-authoring.schedule-section.introducing.video-thumbnail-image.label',
|
||||
defaultMessage: 'Course video thumbnail image',
|
||||
},
|
||||
courseVideoThumbnailInsertText: {
|
||||
id: 'course-authoring.schedule-section.introducing.video-thumbnail-image.insert-card',
|
||||
defaultMessage: 'video thumbnail image',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
act, fireEvent, render, waitFor,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../__mocks__';
|
||||
import messages from './messages';
|
||||
import LearningOutcomesSection from '.';
|
||||
|
||||
const onChangeMock = jest.fn();
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<LearningOutcomesSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
learningInfo: courseDetailsMock.learningInfo,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<LearningOutcomesSection />', () => {
|
||||
it('renders section successfully', () => {
|
||||
const { getByText, getByRole } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.outcomesTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.outcomesDescription.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.outcomesAdd.defaultMessage })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should create another learning outcome form on click Add learning outcome', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const addButton = getByRole('button', { name: messages.outcomesAdd.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(addButton);
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete learning outcome form on click Delete', () => {
|
||||
const { getAllByRole, getByRole } = render(<RootWrapper {...props} />);
|
||||
const deleteButton = getByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
act(() => {
|
||||
fireEvent.click(deleteButton);
|
||||
});
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith([], 'learningInfo');
|
||||
waitFor(() => {
|
||||
const deleteButtons = getAllByRole('button', { name: messages.outcomesDelete.defaultMessage });
|
||||
expect(deleteButtons.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onChange if input value changed', () => {
|
||||
const { getByPlaceholderText } = render(<RootWrapper {...props} />);
|
||||
const input = getByPlaceholderText(messages.outcomesInputPlaceholder.defaultMessage);
|
||||
act(() => {
|
||||
fireEvent.change(input, { target: { value: 'abc' } });
|
||||
});
|
||||
|
||||
expect(onChangeMock).toHaveBeenCalledWith(['abc'], 'learningInfo');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
.learning-outcomes-section {
|
||||
.learning-outcomes-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-inline-start: 0;
|
||||
list-style-type: none;
|
||||
padding-top: $spacer;
|
||||
}
|
||||
}
|
||||
77
src/schedule-and-details/learning-outcomes-section/index.jsx
Normal file
77
src/schedule-and-details/learning-outcomes-section/index.jsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Form, Button } from '@edx/paragon';
|
||||
import { Add as AddIcon } from '@edx/paragon/icons';
|
||||
|
||||
import ScheduleSubHeader from '../schedule-sub-header';
|
||||
import messages from './messages';
|
||||
|
||||
const LearningOutcomesSection = ({ learningInfo, onChange }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const handleInputChange = (value, index) => {
|
||||
const updatedInfo = [...learningInfo];
|
||||
updatedInfo[index] = value;
|
||||
onChange(updatedInfo, 'learningInfo');
|
||||
};
|
||||
|
||||
const handleDelete = (index) => {
|
||||
const updatedInfo = [...learningInfo];
|
||||
updatedInfo.splice(index, 1);
|
||||
onChange(updatedInfo, 'learningInfo');
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
const updatedInfo = [...learningInfo, ''];
|
||||
onChange(updatedInfo, 'learningInfo');
|
||||
};
|
||||
|
||||
const renderLearningOutcomeItem = (text, idx) => (
|
||||
<Form.Group
|
||||
className="form-group-custom align-items-center d-flex"
|
||||
key={idx}
|
||||
>
|
||||
<Form.Label isInline>
|
||||
{intl.formatMessage(messages.outcomesLabelIncrement)} {idx + 1}
|
||||
</Form.Label>
|
||||
<Form.Control
|
||||
value={text}
|
||||
placeholder={intl.formatMessage(messages.outcomesInputPlaceholder)}
|
||||
onChange={(e) => handleInputChange(e.target.value, idx)}
|
||||
/>
|
||||
<Button
|
||||
variant="outline-primary"
|
||||
onClick={() => handleDelete(idx)}
|
||||
>
|
||||
{intl.formatMessage(messages.outcomesDelete)}
|
||||
</Button>
|
||||
</Form.Group>
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="section-container learning-outcomes-section">
|
||||
<ScheduleSubHeader
|
||||
title={intl.formatMessage(messages.outcomesTitle)}
|
||||
description={intl.formatMessage(messages.outcomesDescription)}
|
||||
/>
|
||||
<ul className="learning-outcomes-list">
|
||||
{learningInfo.map(renderLearningOutcomeItem)}
|
||||
</ul>
|
||||
<Button iconBefore={AddIcon} variant="primary" onClick={handleAdd}>
|
||||
{intl.formatMessage(messages.outcomesAdd)}
|
||||
</Button>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
LearningOutcomesSection.defaultProps = {
|
||||
learningInfo: [],
|
||||
};
|
||||
|
||||
LearningOutcomesSection.propTypes = {
|
||||
learningInfo: PropTypes.arrayOf(PropTypes.string),
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default LearningOutcomesSection;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
outcomesTitle: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.title',
|
||||
defaultMessage: 'Learning outcomes',
|
||||
},
|
||||
outcomesDescription: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.description',
|
||||
defaultMessage: 'Add the learning outcomes for this course',
|
||||
},
|
||||
outcomesDelete: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.delete',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
outcomesAdd: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.add',
|
||||
defaultMessage: 'Add learning outcome',
|
||||
},
|
||||
outcomesInputPlaceholder: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.input.placeholder',
|
||||
defaultMessage: 'Add a learning outcome here',
|
||||
},
|
||||
outcomesLabelIncrement: {
|
||||
id: 'course-authoring.schedule.learning-outcomes-section.label-increment',
|
||||
defaultMessage: 'Learning outcome',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -0,0 +1,9 @@
|
||||
.license-section {
|
||||
.license-option {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.license-option_clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { courseDetailsMock } from '../__mocks__';
|
||||
import messages from './messages';
|
||||
import LicenseSection from '.';
|
||||
|
||||
const onChangeMock = jest.fn();
|
||||
|
||||
const RootWrapper = (props) => (
|
||||
<IntlProvider locale="en">
|
||||
<LicenseSection {...props} />
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
const props = {
|
||||
license: courseDetailsMock.license,
|
||||
onChange: onChangeMock,
|
||||
};
|
||||
|
||||
describe('<LicenseSection />', () => {
|
||||
it('renders successfully', () => {
|
||||
const { getByText } = render(<RootWrapper {...props} />);
|
||||
expect(getByText(messages.licenseTitle.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByText(messages.licenseDescription.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
18
src/schedule-and-details/license-section/constants.js
Normal file
18
src/schedule-and-details/license-section/constants.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const creativeCommonsLicensesURL = 'https://creativecommons.org/licenses';
|
||||
const creativeCommonsVersion = '4.0';
|
||||
|
||||
const LICENSE_TYPE = {
|
||||
allRightsReserved: 'all-rights-reserved',
|
||||
creativeCommons: 'creative-commons',
|
||||
};
|
||||
|
||||
const LICENSE_COMMONS_OPTIONS = {
|
||||
attribution: 'BY',
|
||||
nonCommercial: 'NC',
|
||||
noDerivatives: 'ND',
|
||||
shareAlike: 'SA',
|
||||
};
|
||||
|
||||
export {
|
||||
LICENSE_TYPE, LICENSE_COMMONS_OPTIONS, creativeCommonsLicensesURL, creativeCommonsVersion,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user