feat: [FC-0044] Unit page - display xblock components
This commit is contained in:
committed by
Adolfo R. Brandes
parent
e4c3997d17
commit
f8095e6670
@@ -24,8 +24,11 @@ import { RequestStatus } from '../data/constants';
|
||||
import SubHeader from '../generic/sub-header/SubHeader';
|
||||
import ProcessingNotification from '../generic/processing-notification';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import DeleteModal from '../generic/delete-modal/DeleteModal';
|
||||
import AlertMessage from '../generic/alert-message';
|
||||
import getPageHeadTitle from '../generic/utils';
|
||||
import { getCurrentItem } from './data/selectors';
|
||||
import { COURSE_BLOCK_NAMES } from './constants';
|
||||
import HeaderNavigations from './header-navigations/HeaderNavigations';
|
||||
import OutlineSideBar from './outline-sidebar/OutlineSidebar';
|
||||
import StatusBar from './status-bar/StatusBar';
|
||||
@@ -37,7 +40,6 @@ import HighlightsModal from './highlights-modal/HighlightsModal';
|
||||
import EmptyPlaceholder from './empty-placeholder/EmptyPlaceholder';
|
||||
import PublishModal from './publish-modal/PublishModal';
|
||||
import ConfigureModal from './configure-modal/ConfigureModal';
|
||||
import DeleteModal from './delete-modal/DeleteModal';
|
||||
import PageAlerts from './page-alerts/PageAlerts';
|
||||
import { useCourseOutline } from './hooks';
|
||||
import messages from './messages';
|
||||
@@ -115,6 +117,9 @@ const CourseOutline = ({ courseId }) => {
|
||||
title: processingNotificationTitle,
|
||||
} = useSelector(getProcessingNotification);
|
||||
|
||||
const { category } = useSelector(getCurrentItem);
|
||||
const deleteCategory = COURSE_BLOCK_NAMES[category]?.name.toLowerCase();
|
||||
|
||||
const finalizeSectionOrder = () => (newSections) => {
|
||||
initialSections = [...sectionsList];
|
||||
handleSectionDragAndDrop(newSections.map(section => section.id), () => {
|
||||
@@ -459,6 +464,7 @@ const CourseOutline = ({ courseId }) => {
|
||||
onConfigureSubmit={handleConfigureItemSubmit}
|
||||
/>
|
||||
<DeleteModal
|
||||
category={deleteCategory}
|
||||
isOpen={isDeleteModalOpen}
|
||||
close={closeDeleteModal}
|
||||
onDeleteSubmit={handleDeleteItemSubmit}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Container, Layout } from '@openedx/paragon';
|
||||
import { Container, Layout, Stack } from '@openedx/paragon';
|
||||
import { useIntl, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import { ErrorAlert } from '@edx/frontend-lib-content-components';
|
||||
|
||||
@@ -13,6 +13,7 @@ import ProcessingNotification from '../generic/processing-notification';
|
||||
import InternetConnectionAlert from '../generic/internet-connection-alert';
|
||||
import Loading from '../generic/Loading';
|
||||
import AddComponent from './add-component/AddComponent';
|
||||
import CourseXBlock from './course-xblock/CourseXBlock';
|
||||
import HeaderTitle from './header-title/HeaderTitle';
|
||||
import Breadcrumbs from './breadcrumbs/Breadcrumbs';
|
||||
import HeaderNavigations from './header-navigations/HeaderNavigations';
|
||||
@@ -32,11 +33,13 @@ const CourseUnit = ({ courseId }) => {
|
||||
isTitleEditFormOpen,
|
||||
isErrorAlert,
|
||||
isInternetConnectionAlertFailed,
|
||||
unitXBlockActions,
|
||||
handleTitleEditSubmit,
|
||||
headerNavigationsActions,
|
||||
handleTitleEdit,
|
||||
handleInternetConnectionFailed,
|
||||
handleCreateNewCourseXBlock,
|
||||
courseVerticalChildren,
|
||||
} = useCourseUnit({ courseId, blockId });
|
||||
|
||||
document.title = getPageHeadTitle('', unitTitle);
|
||||
@@ -90,6 +93,18 @@ const CourseUnit = ({ courseId }) => {
|
||||
xl={[{ span: 9 }, { span: 3 }]}
|
||||
>
|
||||
<Layout.Element>
|
||||
<Stack gap={4} className="mb-4">
|
||||
{courseVerticalChildren.children.map(({ name, blockId: id, shouldScroll }) => (
|
||||
<CourseXBlock
|
||||
id={id}
|
||||
key={id}
|
||||
title={name}
|
||||
shouldScroll={shouldScroll}
|
||||
unitXBlockActions={unitXBlockActions}
|
||||
data-testid="course-xblock"
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
<AddComponent
|
||||
blockId={blockId}
|
||||
handleCreateNewCourseXBlock={handleCreateNewCourseXBlock}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "./breadcrumbs/Breadcrumbs";
|
||||
@import "./course-sequence/CourseSequence";
|
||||
@import "./add-component/AddComponent";
|
||||
@import "./course-xblock/CourseXblock";
|
||||
|
||||
@@ -12,12 +12,14 @@ import { cloneDeep, set } from 'lodash';
|
||||
import {
|
||||
getCourseSectionVerticalApiUrl,
|
||||
getCourseUnitApiUrl,
|
||||
getCourseVerticalChildrenApiUrl,
|
||||
getXBlockBaseApiUrl,
|
||||
postXBlockBaseApiUrl,
|
||||
} from './data/api';
|
||||
import {
|
||||
fetchCourseSectionVerticalData,
|
||||
fetchCourseUnitQuery,
|
||||
fetchCourseVerticalChildrenData,
|
||||
} from './data/thunk';
|
||||
import initializeStore from '../store';
|
||||
import {
|
||||
@@ -25,13 +27,17 @@ import {
|
||||
courseSectionVerticalMock,
|
||||
courseUnitIndexMock,
|
||||
courseUnitMock,
|
||||
courseVerticalChildrenMock,
|
||||
} from './__mocks__';
|
||||
import { executeThunk } from '../utils';
|
||||
import CourseUnit from './CourseUnit';
|
||||
import headerNavigationsMessages from './header-navigations/messages';
|
||||
import headerTitleMessages from './header-title/messages';
|
||||
import courseSequenceMessages from './course-sequence/messages';
|
||||
import messages from './add-component/messages';
|
||||
|
||||
import deleteModalMessages from '../generic/delete-modal/messages';
|
||||
import courseXBlockMessages from './course-xblock/messages';
|
||||
import addComponentMessages from './add-component/messages';
|
||||
|
||||
let axiosMock;
|
||||
let store;
|
||||
@@ -75,6 +81,10 @@ describe('<CourseUnit />', () => {
|
||||
.onGet(getCourseSectionVerticalApiUrl(blockId))
|
||||
.reply(200, courseSectionVerticalMock);
|
||||
await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch);
|
||||
axiosMock
|
||||
.onGet(getCourseVerticalChildrenApiUrl(blockId))
|
||||
.reply(200, courseVerticalChildrenMock);
|
||||
await executeThunk(fetchCourseVerticalChildrenData(blockId), store.dispatch);
|
||||
});
|
||||
|
||||
it('render CourseUnit component correctly', async () => {
|
||||
@@ -169,7 +179,7 @@ describe('<CourseUnit />', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const videoButton = getByRole('button', {
|
||||
name: new RegExp(`${messages.buttonText.defaultMessage} Video`, 'i'),
|
||||
name: new RegExp(`${addComponentMessages.buttonText.defaultMessage} Video`, 'i'),
|
||||
});
|
||||
|
||||
userEvent.click(videoButton);
|
||||
@@ -186,7 +196,7 @@ describe('<CourseUnit />', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const problemButton = getByRole('button', {
|
||||
name: new RegExp(`${messages.buttonText.defaultMessage} Problem`, 'i'),
|
||||
name: new RegExp(`${addComponentMessages.buttonText.defaultMessage} Problem`, 'i'),
|
||||
});
|
||||
|
||||
userEvent.click(problemButton);
|
||||
@@ -291,7 +301,7 @@ describe('<CourseUnit />', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const videoButton = getByRole('button', {
|
||||
name: new RegExp(`${messages.buttonText.defaultMessage} Video`, 'i'),
|
||||
name: new RegExp(`${addComponentMessages.buttonText.defaultMessage} Video`, 'i'),
|
||||
});
|
||||
|
||||
userEvent.click(videoButton);
|
||||
@@ -299,4 +309,73 @@ describe('<CourseUnit />', () => {
|
||||
expect(mockedUsedNavigate).toHaveBeenCalledWith(`/course/${courseKey}/editor/video/${locator}`);
|
||||
});
|
||||
});
|
||||
|
||||
it('checks whether xblock is deleted when corresponding delete button is clicked', async () => {
|
||||
axiosMock
|
||||
.onDelete(getXBlockBaseApiUrl(courseVerticalChildrenMock.children[0].block_id))
|
||||
.replyOnce(200, { dummy: 'value' });
|
||||
|
||||
const {
|
||||
getByText,
|
||||
getAllByLabelText,
|
||||
getByRole,
|
||||
getAllByTestId,
|
||||
} = render(<RootWrapper />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText(unitDisplayName)).toBeInTheDocument();
|
||||
const [xblockActionBtn] = getAllByLabelText(courseXBlockMessages.blockActionsDropdownAlt.defaultMessage);
|
||||
userEvent.click(xblockActionBtn);
|
||||
|
||||
const deleteBtn = getByRole('button', { name: courseXBlockMessages.blockLabelButtonDelete.defaultMessage });
|
||||
userEvent.click(deleteBtn);
|
||||
expect(getByText(/Delete this component?/)).toBeInTheDocument();
|
||||
|
||||
const deleteConfirmBtn = getByRole('button', { name: deleteModalMessages.deleteButton.defaultMessage });
|
||||
userEvent.click(deleteConfirmBtn);
|
||||
|
||||
expect(getAllByTestId('course-xblock')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('checks whether xblock is duplicate when corresponding delete button is clicked', async () => {
|
||||
axiosMock
|
||||
.onPost(postXBlockBaseApiUrl({
|
||||
parent_locator: blockId,
|
||||
duplicate_source_locator: courseVerticalChildrenMock.children[0].block_id,
|
||||
}))
|
||||
.replyOnce(200, { locator: '1234567890' });
|
||||
|
||||
axiosMock
|
||||
.onGet(getCourseVerticalChildrenApiUrl(blockId))
|
||||
.reply(200, {
|
||||
...courseVerticalChildrenMock,
|
||||
children: [
|
||||
...courseVerticalChildrenMock.children,
|
||||
{
|
||||
name: 'New Cloned XBlock',
|
||||
block_id: '1234567890',
|
||||
block_type: 'drag-and-drop-v2',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const {
|
||||
getByText,
|
||||
getAllByLabelText,
|
||||
getAllByTestId,
|
||||
} = render(<RootWrapper />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText(unitDisplayName)).toBeInTheDocument();
|
||||
const [xblockActionBtn] = getAllByLabelText(courseXBlockMessages.blockActionsDropdownAlt.defaultMessage);
|
||||
userEvent.click(xblockActionBtn);
|
||||
|
||||
const duplicateBtn = getByText(courseXBlockMessages.blockLabelButtonDuplicate.defaultMessage);
|
||||
userEvent.click(duplicateBtn);
|
||||
|
||||
expect(getAllByTestId('course-xblock')).toHaveLength(3);
|
||||
expect(getByText('New Cloned XBlock')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
15
src/course-unit/__mocks__/courseVerticalChildren.js
Normal file
15
src/course-unit/__mocks__/courseVerticalChildren.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
children: [
|
||||
{
|
||||
name: 'Discussion',
|
||||
block_id: 'block-v1:edX+L153+3T2023+type@discussion+block@fecd20842dd24f50bdc06643e791b013',
|
||||
block_type: 'discussion',
|
||||
},
|
||||
{
|
||||
name: 'Drag and Drop',
|
||||
block_id: 'block-v1:edX+L153+3T2023+type@drag-and-drop-v2+block@b33cf1f6df4c41639659bc91132eeb02',
|
||||
block_type: 'drag-and-drop-v2',
|
||||
},
|
||||
],
|
||||
is_published: false,
|
||||
};
|
||||
@@ -2,3 +2,4 @@ export { default as courseUnitIndexMock } from './courseUnitIndex';
|
||||
export { default as courseSectionVerticalMock } from './courseSectionVertical';
|
||||
export { default as courseUnitMock } from './courseUnit';
|
||||
export { default as courseCreateXblockMock } from './courseCreateXblock';
|
||||
export { default as courseVerticalChildrenMock } from './courseVerticalChildren';
|
||||
|
||||
104
src/course-unit/course-xblock/CourseXBlock.jsx
Normal file
104
src/course-unit/course-xblock/CourseXBlock.jsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
ActionRow, Card, Dropdown, Icon, IconButton, useToggle,
|
||||
} from '@openedx/paragon';
|
||||
import { EditOutline as EditIcon, MoreVert as MoveVertIcon } from '@openedx/paragon/icons';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import DeleteModal from '../../generic/delete-modal/DeleteModal';
|
||||
import { scrollToElement } from '../../course-outline/utils';
|
||||
import messages from './messages';
|
||||
|
||||
const CourseXBlock = ({
|
||||
id, title, unitXBlockActions, shouldScroll, ...props
|
||||
}) => {
|
||||
const courseXBlockElementRef = useRef(null);
|
||||
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
|
||||
const intl = useIntl();
|
||||
|
||||
const onXBlockDelete = () => {
|
||||
unitXBlockActions.handleDelete(id);
|
||||
closeDeleteModal();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// if this item has been newly added, scroll to it.
|
||||
if (courseXBlockElementRef.current && shouldScroll) {
|
||||
scrollToElement(courseXBlockElementRef.current);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div ref={courseXBlockElementRef} {...props}>
|
||||
<Card className="mb-1">
|
||||
<Card.Header
|
||||
title={title}
|
||||
actions={(
|
||||
<ActionRow>
|
||||
<IconButton
|
||||
alt={intl.formatMessage(messages.blockAltButtonEdit)}
|
||||
iconAs={EditIcon}
|
||||
size="md"
|
||||
onClick={() => {}}
|
||||
/>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
id={id}
|
||||
as={IconButton}
|
||||
src={MoveVertIcon}
|
||||
alt={intl.formatMessage(messages.blockActionsDropdownAlt)}
|
||||
size="sm"
|
||||
iconAs={Icon}
|
||||
/>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item>
|
||||
{intl.formatMessage(messages.blockLabelButtonCopy)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item onClick={() => unitXBlockActions.handleDuplicate(id)}>
|
||||
{intl.formatMessage(messages.blockLabelButtonDuplicate)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item>
|
||||
{intl.formatMessage(messages.blockLabelButtonMove)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item>
|
||||
{intl.formatMessage(messages.blockLabelButtonManageAccess)}
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item onClick={openDeleteModal}>
|
||||
{intl.formatMessage(messages.blockLabelButtonDelete)}
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<DeleteModal
|
||||
category="component"
|
||||
isOpen={isDeleteModalOpen}
|
||||
close={closeDeleteModal}
|
||||
onDeleteSubmit={onXBlockDelete}
|
||||
/>
|
||||
</ActionRow>
|
||||
)}
|
||||
size="md"
|
||||
/>
|
||||
<Card.Section>
|
||||
<div className="w-100 bg-gray-100" style={{ height: 200 }} data-block-id={id} />
|
||||
</Card.Section>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CourseXBlock.defaultProps = {
|
||||
shouldScroll: false,
|
||||
};
|
||||
|
||||
CourseXBlock.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
shouldScroll: PropTypes.bool,
|
||||
unitXBlockActions: PropTypes.shape({
|
||||
handleDelete: PropTypes.func,
|
||||
handleDuplicate: PropTypes.func,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default CourseXBlock;
|
||||
108
src/course-unit/course-xblock/CourseXBlock.test.jsx
Normal file
108
src/course-unit/course-xblock/CourseXBlock.test.jsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { AppProvider } from '@edx/frontend-platform/react';
|
||||
|
||||
import { courseVerticalChildrenMock } from '../__mocks__';
|
||||
import CourseXBlock from './CourseXBlock';
|
||||
|
||||
import deleteModalMessages from '../../generic/delete-modal/messages';
|
||||
import messages from './messages';
|
||||
|
||||
let store;
|
||||
const handleDeleteMock = jest.fn();
|
||||
const handleDuplicateMock = jest.fn();
|
||||
const xblockData = courseVerticalChildrenMock.children[0];
|
||||
const unitXBlockActionsMock = {
|
||||
handleDelete: handleDeleteMock,
|
||||
handleDuplicate: handleDuplicateMock,
|
||||
};
|
||||
|
||||
const renderComponent = () => render(
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en">
|
||||
<CourseXBlock
|
||||
id={xblockData.block_id}
|
||||
title={xblockData.block_id}
|
||||
unitXBlockActions={unitXBlockActionsMock}
|
||||
shouldScroll={false}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</AppProvider>,
|
||||
);
|
||||
|
||||
describe('<CourseXBlock />', () => {
|
||||
beforeEach(async () => {
|
||||
initializeMockApp({
|
||||
authenticatedUser: {
|
||||
userId: 3,
|
||||
username: 'abc123',
|
||||
administrator: true,
|
||||
roles: [],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('render CourseXBlock component correctly', async () => {
|
||||
const { getByText, getByLabelText } = renderComponent();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText(xblockData.block_id)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.blockAltButtonEdit.defaultMessage)).toBeInTheDocument();
|
||||
expect(getByLabelText(messages.blockActionsDropdownAlt.defaultMessage)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('render CourseXBlock component action dropdown correctly', async () => {
|
||||
const { getByRole, getByLabelText } = renderComponent();
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(getByLabelText(messages.blockActionsDropdownAlt.defaultMessage));
|
||||
expect(getByRole('button', { name: messages.blockLabelButtonCopy.defaultMessage })).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.blockLabelButtonDuplicate.defaultMessage })).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.blockLabelButtonMove.defaultMessage })).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.blockLabelButtonManageAccess.defaultMessage })).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: messages.blockLabelButtonDelete.defaultMessage })).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('calls handleDuplicate when item is clicked', async () => {
|
||||
const { getByText, getByLabelText } = renderComponent();
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(getByLabelText(messages.blockActionsDropdownAlt.defaultMessage));
|
||||
const duplicateBtn = getByText(messages.blockLabelButtonDuplicate.defaultMessage);
|
||||
|
||||
userEvent.click(duplicateBtn);
|
||||
expect(handleDuplicateMock).toHaveBeenCalledTimes(1);
|
||||
expect(handleDuplicateMock).toHaveBeenCalledWith(xblockData.block_id);
|
||||
});
|
||||
});
|
||||
|
||||
it('opens confirm delete modal and calls handleDelete when deleting was confirmed', async () => {
|
||||
const { getByText, getByLabelText, getByRole } = renderComponent();
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(getByLabelText(messages.blockActionsDropdownAlt.defaultMessage));
|
||||
const deleteBtn = getByText(messages.blockLabelButtonDelete.defaultMessage);
|
||||
|
||||
userEvent.click(deleteBtn);
|
||||
expect(getByText(/Delete this component?/)).toBeInTheDocument();
|
||||
expect(getByText(/Deleting this component is permanent and cannot be undone./)).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: deleteModalMessages.cancelButton.defaultMessage })).toBeInTheDocument();
|
||||
expect(getByRole('button', { name: deleteModalMessages.deleteButton.defaultMessage })).toBeInTheDocument();
|
||||
|
||||
userEvent.click(getByRole('button', { name: deleteModalMessages.cancelButton.defaultMessage }));
|
||||
expect(handleDeleteMock).not.toHaveBeenCalled();
|
||||
|
||||
userEvent.click(getByText(messages.blockLabelButtonDelete.defaultMessage));
|
||||
expect(getByText(/Delete this component?/)).toBeInTheDocument();
|
||||
|
||||
userEvent.click(deleteBtn);
|
||||
userEvent.click(getByRole('button', { name: deleteModalMessages.deleteButton.defaultMessage }));
|
||||
expect(handleDeleteMock).toHaveBeenCalled();
|
||||
expect(handleDeleteMock).toHaveBeenCalledWith(xblockData.block_id);
|
||||
});
|
||||
});
|
||||
});
|
||||
15
src/course-unit/course-xblock/CourseXblock.scss
Normal file
15
src/course-unit/course-xblock/CourseXblock.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.course-unit {
|
||||
.pgn__card .pgn__card-header {
|
||||
border-bottom: 1px solid $light-400;
|
||||
padding-bottom: map-get($spacers, 2);
|
||||
|
||||
.pgn__card-header-content {
|
||||
margin-top: map-get($spacers, 3\.5);
|
||||
}
|
||||
|
||||
.btn-icon .btn-icon__icon {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
src/course-unit/course-xblock/messages.js
Normal file
34
src/course-unit/course-xblock/messages.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
blockAltButtonEdit: {
|
||||
id: 'course-authoring.course-unit.xblock.button.edit.alt',
|
||||
defaultMessage: 'Edit Item',
|
||||
},
|
||||
blockActionsDropdownAlt: {
|
||||
id: 'course-authoring.course-unit.xblock.button.actions.alt',
|
||||
defaultMessage: 'Actions',
|
||||
},
|
||||
blockLabelButtonCopy: {
|
||||
id: 'course-authoring.course-unit.xblock.button.copy.label',
|
||||
defaultMessage: 'Copy',
|
||||
},
|
||||
blockLabelButtonDuplicate: {
|
||||
id: 'course-authoring.course-unit.xblock.button.duplicate.label',
|
||||
defaultMessage: 'Duplicate',
|
||||
},
|
||||
blockLabelButtonMove: {
|
||||
id: 'course-authoring.course-unit.xblock.button.move.label',
|
||||
defaultMessage: 'Move',
|
||||
},
|
||||
blockLabelButtonManageAccess: {
|
||||
id: 'course-authoring.course-unit.xblock.button.manageAccess.label',
|
||||
defaultMessage: 'Manage access',
|
||||
},
|
||||
blockLabelButtonDelete: {
|
||||
id: 'course-authoring.course-unit.xblock.button.delete.label',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -19,6 +19,7 @@ export const getCourseSectionVerticalApiUrl = (itemId) => `${getStudioBaseUrl()}
|
||||
export const getLearningSequencesOutlineApiUrl = (courseId) => `${getLmsBaseUrl()}/api/learning_sequences/v1/course_outline/${courseId}`;
|
||||
export const getCourseMetadataApiUrl = (courseId) => `${getLmsBaseUrl()}/api/courseware/course/${courseId}`;
|
||||
export const getCourseHomeCourseMetadataApiUrl = (courseId) => `${getLmsBaseUrl()}/api/course_home/course_metadata/${courseId}`;
|
||||
export const getCourseVerticalChildrenApiUrl = (itemId) => `${getStudioBaseUrl()}/api/contentstore/v1/container/vertical/${itemId}/children`;
|
||||
|
||||
export const postXBlockBaseApiUrl = () => `${getStudioBaseUrl()}/xblock/`;
|
||||
|
||||
@@ -128,3 +129,43 @@ export async function createCourseXblock({
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object containing course section vertical children data.
|
||||
* @param {string} itemId
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function getCourseVerticalChildren(itemId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.get(getCourseVerticalChildrenApiUrl(itemId));
|
||||
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a unit item.
|
||||
* @param {string} itemId
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function deleteUnitItem(itemId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.delete(getXBlockBaseApiUrl(itemId));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a unit item.
|
||||
* @param {string} itemId
|
||||
* @param {string} XBlockId
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export async function duplicateUnitItem(itemId, XBlockId) {
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.post(postXBlockBaseApiUrl(), {
|
||||
parent_locator: itemId,
|
||||
duplicate_source_locator: XBlockId,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export const getCoursewareMeta = state => state.models.coursewareMeta;
|
||||
export const getSections = state => state.models.sections;
|
||||
export const getCourseId = state => state.courseDetail.courseId;
|
||||
export const getSequenceId = state => state.courseUnit.sequenceId;
|
||||
export const getCourseVerticalChildren = state => state.courseUnit.courseVerticalChildren;
|
||||
export const sequenceIdsSelector = createSelector(
|
||||
[getCourseStatus, getCoursewareMeta, getSections, getCourseId],
|
||||
(courseStatus, coursewareMeta, sections, courseId) => {
|
||||
|
||||
@@ -12,9 +12,11 @@ const slice = createSlice({
|
||||
loadingStatus: {
|
||||
fetchUnitLoadingStatus: RequestStatus.IN_PROGRESS,
|
||||
courseSectionVerticalLoadingStatus: RequestStatus.IN_PROGRESS,
|
||||
courseVerticalChildrenLoadingStatus: RequestStatus.IN_PROGRESS,
|
||||
},
|
||||
unit: {},
|
||||
courseSectionVertical: {},
|
||||
courseVerticalChildren: [],
|
||||
},
|
||||
reducers: {
|
||||
fetchCourseItemSuccess: (state, { payload }) => {
|
||||
@@ -87,6 +89,28 @@ const slice = createSlice({
|
||||
fetchUnitLoadingStatus: payload.status,
|
||||
};
|
||||
},
|
||||
updateCourseVerticalChildren: (state, { payload }) => {
|
||||
state.courseVerticalChildren = payload;
|
||||
},
|
||||
updateCourseVerticalChildrenLoadingStatus: (state, { payload }) => {
|
||||
state.loadingStatus.courseVerticalChildrenLoadingStatus = payload.status;
|
||||
},
|
||||
deleteXBlock: (state, { payload }) => {
|
||||
state.courseVerticalChildren.children = state.courseVerticalChildren.children.filter(
|
||||
(component) => component.blockId !== payload,
|
||||
);
|
||||
},
|
||||
duplicateXBlock: (state, { payload }) => {
|
||||
state.courseVerticalChildren = {
|
||||
...payload.newCourseVerticalChildren,
|
||||
children: payload.newCourseVerticalChildren.children.map((component) => {
|
||||
if (component.blockId === payload.newId) {
|
||||
component.shouldScroll = true;
|
||||
}
|
||||
return component;
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -107,6 +131,10 @@ export const {
|
||||
changeEditTitleFormOpen,
|
||||
updateQueryPendingStatus,
|
||||
updateLoadingCourseXblockStatus,
|
||||
updateCourseVerticalChildren,
|
||||
updateCourseVerticalChildrenLoadingStatus,
|
||||
deleteXBlock,
|
||||
duplicateXBlock,
|
||||
} = slice.actions;
|
||||
|
||||
export const {
|
||||
|
||||
@@ -17,6 +17,9 @@ import {
|
||||
getCourseHomeCourseMetadata,
|
||||
getCourseSectionVerticalData,
|
||||
createCourseXblock,
|
||||
getCourseVerticalChildren,
|
||||
deleteUnitItem,
|
||||
duplicateUnitItem,
|
||||
} from './api';
|
||||
import {
|
||||
updateLoadingCourseUnitStatus,
|
||||
@@ -32,6 +35,10 @@ import {
|
||||
fetchCourseSectionVerticalDataSuccess,
|
||||
updateLoadingCourseSectionVerticalDataStatus,
|
||||
updateLoadingCourseXblockStatus,
|
||||
updateCourseVerticalChildren,
|
||||
updateCourseVerticalChildrenLoadingStatus,
|
||||
deleteXBlock,
|
||||
duplicateXBlock,
|
||||
} from './slice';
|
||||
|
||||
export function fetchCourseUnitQuery(courseId) {
|
||||
@@ -192,7 +199,7 @@ export function fetchCourse(courseId) {
|
||||
};
|
||||
}
|
||||
|
||||
export function createNewCourseXblock(body, callback) {
|
||||
export function createNewCourseXBlock(body, callback, blockId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateLoadingCourseXblockStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.adding));
|
||||
@@ -205,7 +212,8 @@ export function createNewCourseXblock(body, callback) {
|
||||
const courseSectionVerticalData = await getCourseSectionVerticalData(result.locator);
|
||||
dispatch(fetchCourseSectionVerticalDataSuccess(courseSectionVerticalData));
|
||||
}
|
||||
// ToDo: implement fetching (update) xblocks after success creating
|
||||
const courseVerticalChildrenData = await getCourseVerticalChildren(blockId);
|
||||
dispatch(updateCourseVerticalChildren(courseVerticalChildrenData));
|
||||
dispatch(hideProcessingNotification());
|
||||
dispatch(updateLoadingCourseXblockStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
@@ -221,3 +229,55 @@ export function createNewCourseXblock(body, callback) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchCourseVerticalChildrenData(itemId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateCourseVerticalChildrenLoadingStatus({ status: RequestStatus.IN_PROGRESS }));
|
||||
|
||||
try {
|
||||
const courseVerticalChildrenData = await getCourseVerticalChildren(itemId);
|
||||
dispatch(updateCourseVerticalChildren(courseVerticalChildrenData));
|
||||
dispatch(updateCourseVerticalChildrenLoadingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
} catch (error) {
|
||||
dispatch(updateCourseVerticalChildrenLoadingStatus({ status: RequestStatus.FAILED }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteUnitItemQuery(itemId, xblockId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
|
||||
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.deleting));
|
||||
|
||||
try {
|
||||
await deleteUnitItem(xblockId);
|
||||
dispatch(deleteXBlock(xblockId));
|
||||
dispatch(hideProcessingNotification());
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
} catch (error) {
|
||||
dispatch(hideProcessingNotification());
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function duplicateUnitItemQuery(itemId, xblockId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.PENDING }));
|
||||
dispatch(showProcessingNotification(NOTIFICATION_MESSAGES.duplicating));
|
||||
|
||||
try {
|
||||
const { locator } = await duplicateUnitItem(itemId, xblockId);
|
||||
const newCourseVerticalChildren = await getCourseVerticalChildren(itemId);
|
||||
dispatch(duplicateXBlock({
|
||||
newId: locator,
|
||||
newCourseVerticalChildren,
|
||||
}));
|
||||
dispatch(hideProcessingNotification());
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.SUCCESSFUL }));
|
||||
} catch (error) {
|
||||
dispatch(hideProcessingNotification());
|
||||
dispatch(updateSavingStatus({ status: RequestStatus.FAILED }));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import {
|
||||
createNewCourseXblock,
|
||||
createNewCourseXBlock,
|
||||
fetchCourseUnitQuery,
|
||||
editCourseItemQuery,
|
||||
fetchCourse,
|
||||
fetchCourseSectionVerticalData,
|
||||
fetchCourseVerticalChildrenData,
|
||||
deleteUnitItemQuery,
|
||||
duplicateUnitItemQuery,
|
||||
} from './data/thunk';
|
||||
import {
|
||||
getCourseSectionVertical,
|
||||
getCourseVerticalChildren,
|
||||
getCourseUnitData,
|
||||
getLoadingStatus,
|
||||
getSavingStatus,
|
||||
@@ -28,6 +32,7 @@ export const useCourseUnit = ({ courseId, blockId }) => {
|
||||
const savingStatus = useSelector(getSavingStatus);
|
||||
const loadingStatus = useSelector(getLoadingStatus);
|
||||
const { draftPreviewLink, publishedPreviewLink } = useSelector(getCourseSectionVertical);
|
||||
const courseVerticalChildren = useSelector(getCourseVerticalChildren);
|
||||
const navigate = useNavigate();
|
||||
const isTitleEditFormOpen = useSelector(state => state.courseUnit.isTitleEditFormOpen);
|
||||
const isQueryPending = useSelector(state => state.courseUnit.isQueryPending);
|
||||
@@ -67,9 +72,18 @@ export const useCourseUnit = ({ courseId, blockId }) => {
|
||||
};
|
||||
|
||||
const handleCreateNewCourseXBlock = (body, callback) => (
|
||||
dispatch(createNewCourseXblock(body, callback))
|
||||
dispatch(createNewCourseXBlock(body, callback, blockId))
|
||||
);
|
||||
|
||||
const unitXBlockActions = {
|
||||
handleDelete: (XBlockId) => {
|
||||
dispatch(deleteUnitItemQuery(blockId, XBlockId));
|
||||
},
|
||||
handleDuplicate: (XBlockId) => {
|
||||
dispatch(duplicateUnitItemQuery(blockId, XBlockId));
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (savingStatus === RequestStatus.SUCCESSFUL) {
|
||||
dispatch(updateQueryPendingStatus(false));
|
||||
@@ -81,6 +95,7 @@ export const useCourseUnit = ({ courseId, blockId }) => {
|
||||
useEffect(() => {
|
||||
dispatch(fetchCourseUnitQuery(blockId));
|
||||
dispatch(fetchCourseSectionVerticalData(blockId, sequenceId));
|
||||
dispatch(fetchCourseVerticalChildrenData(blockId));
|
||||
dispatch(fetchCourse(courseId));
|
||||
|
||||
handleNavigate(sequenceId);
|
||||
@@ -98,9 +113,11 @@ export const useCourseUnit = ({ courseId, blockId }) => {
|
||||
isTitleEditFormOpen,
|
||||
isInternetConnectionAlertFailed: savingStatus === RequestStatus.FAILED,
|
||||
handleInternetConnectionFailed,
|
||||
unitXBlockActions,
|
||||
headerNavigationsActions,
|
||||
handleTitleEdit,
|
||||
handleTitleEditSubmit,
|
||||
handleCreateNewCourseXBlock,
|
||||
courseVerticalChildren,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
ActionRow,
|
||||
Button,
|
||||
AlertModal,
|
||||
} from '@openedx/paragon';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { COURSE_BLOCK_NAMES } from '../constants';
|
||||
import { getCurrentItem } from '../data/selectors';
|
||||
import messages from './messages';
|
||||
|
||||
const DeleteModal = ({ isOpen, close, onDeleteSubmit }) => {
|
||||
const DeleteModal = ({
|
||||
category, isOpen, close, onDeleteSubmit,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
let { category } = useSelector(getCurrentItem);
|
||||
category = COURSE_BLOCK_NAMES[category]?.name.toLowerCase();
|
||||
|
||||
return (
|
||||
<AlertModal
|
||||
@@ -47,6 +43,7 @@ const DeleteModal = ({ isOpen, close, onDeleteSubmit }) => {
|
||||
DeleteModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
close: PropTypes.func.isRequired,
|
||||
category: PropTypes.string.isRequired,
|
||||
onDeleteSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { render, fireEvent } from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
@@ -30,16 +29,13 @@ jest.mock('@edx/frontend-platform/i18n', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const currentItemMock = {
|
||||
displayName: 'Delete',
|
||||
};
|
||||
|
||||
const renderComponent = (props) => render(
|
||||
<AppProvider store={store}>
|
||||
<IntlProvider locale="en">
|
||||
<DeleteModal
|
||||
isOpen
|
||||
close={closeMock}
|
||||
category="Section"
|
||||
onDeleteSubmit={onDeleteSubmitMock}
|
||||
{...props}
|
||||
/>
|
||||
@@ -60,7 +56,6 @@ describe('<DeleteModal />', () => {
|
||||
|
||||
store = initializeStore();
|
||||
axiosMock = new MockAdapter(getAuthenticatedHttpClient());
|
||||
useSelector.mockReturnValue(currentItemMock);
|
||||
});
|
||||
|
||||
it('render DeleteModal component correctly', () => {
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.course-unit.add.component.button.text": "Add Component:",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -36,5 +36,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
@@ -1013,5 +1013,38 @@
|
||||
"course-authoring.certificates.sidebar.learnmore.button": "Learn more about certificates",
|
||||
"course-authoring.course-unit.modal.button.text": "Select",
|
||||
"course-authoring.course-unit.modal.container.title": "Add {componentTitle} component",
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel"
|
||||
"course-authoring.course-unit.modal.container.cancel.button.text": "Cancel",
|
||||
"course-authoring.course-unit.sidebar.title.draft.never-published": "Draft (never published)",
|
||||
"course-authoring.course-unit.sidebar.title.visible.to-staff-only": "Visible to staff only",
|
||||
"course-authoring.course-unit.sidebar.title.published.live": "Published and live",
|
||||
"course-authoring.course-unit.sidebar.title.draft.unpublished": "Draft (unpublished changes)",
|
||||
"course-authoring.course-unit.sidebar.title.published.not-yet-released": "Published (not yet released)",
|
||||
"course-authoring.course-unit.sidebar.header.unit-location.title": "Unit location",
|
||||
"course-authoring.course-unit.sidebar.body.note": "Note: Do not hide graded assignments after they have been released.",
|
||||
"course-authoring.course-unit.publish.info.previously-published": "Previously published",
|
||||
"course-authoring.course-unit.publish.info.draft.saved": "Draft saved on {editedOn} by {editedBy}",
|
||||
"course-authoring.course-unit.publish.info.last.published": "Last published {publishedOn} by {publishedBy}",
|
||||
"course-authoring.course-unit.release.info.unscheduled": "Unscheduled",
|
||||
"course-authoring.course-unit.release.info.with-unit": "with {sectionName}",
|
||||
"course-authoring.course-unit.visibility.is-visible-to.title": "IS VISIBLE TO",
|
||||
"course-authoring.course-unit.visibility.will-be-visible-to.title": "WILL BE VISIBLE TO",
|
||||
"course-authoring.course-unit.unit-location.title": "LOCATION ID",
|
||||
"course-authoring.course-unit.unit-location.description": "To create a link to this unit from an HTML component in this course, enter /jump_to_id/{id} as the URL value",
|
||||
"course-authoring.course-unit.visibility.checkbox.title": "Hide from learners",
|
||||
"course-authoring.course-unit.visibility.staff-only.title": "Staff only",
|
||||
"course-authoring.course-unit.visibility.staff-and-learners.title": "Staff and learners",
|
||||
"course-authoring.course-unit.visibility.has-explicit-staff-lock.text": "with {date} {sectionName}",
|
||||
"course-authoring.course-unit.action-buttons.publish.title": "Publish",
|
||||
"course-authoring.course-unit.action-button.discard-changes.title": "Discard changes",
|
||||
"course-authoring.course-unit.action-button.copy-unit.title": "Copy unit",
|
||||
"course-authoring.course-unit.status.release.title": "RELEASE",
|
||||
"course-authoring.course-unit.status.released.title": "RELEASED",
|
||||
"course-authoring.course-unit.status.scheduled.title": "SCHEDULED",
|
||||
"course-authoring.course-unit.xblock.button.edit.alt": "Edit Item",
|
||||
"course-authoring.course-unit.xblock.button.copy.label": "Copy",
|
||||
"course-authoring.course-unit.xblock.button.duplicate.label": "Duplicate",
|
||||
"course-authoring.course-unit.xblock.button.move.label": "Move",
|
||||
"course-authoring.course-unit.xblock.button.manageAccess.label": "Manage access",
|
||||
"course-authoring.course-unit.xblock.button.delete.label": "Delete",
|
||||
"course-authoring.course-unit.xblock.button.actions.alt": "Actions"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user