From f8095e667083c895ff13989fe31a562cef7afe91 Mon Sep 17 00:00:00 2001 From: Ihor Romaniuk Date: Tue, 23 Jan 2024 14:17:15 +0100 Subject: [PATCH] feat: [FC-0044] Unit page - display xblock components --- src/course-outline/CourseOutline.jsx | 8 +- src/course-unit/CourseUnit.jsx | 17 ++- src/course-unit/CourseUnit.scss | 1 + src/course-unit/CourseUnit.test.jsx | 87 +++++++++++++- .../__mocks__/courseVerticalChildren.js | 15 +++ src/course-unit/__mocks__/index.js | 1 + .../course-xblock/CourseXBlock.jsx | 104 +++++++++++++++++ .../course-xblock/CourseXBlock.test.jsx | 108 ++++++++++++++++++ .../course-xblock/CourseXblock.scss | 15 +++ src/course-unit/course-xblock/messages.js | 34 ++++++ src/course-unit/data/api.js | 41 +++++++ src/course-unit/data/selectors.js | 1 + src/course-unit/data/slice.js | 28 +++++ src/course-unit/data/thunk.js | 64 ++++++++++- src/course-unit/hooks.jsx | 21 +++- .../delete-modal/DeleteModal.jsx | 11 +- .../delete-modal/DeleteModal.test.jsx | 7 +- .../delete-modal/messages.js | 0 src/i18n/messages/ar.json | 35 +++++- src/i18n/messages/de.json | 35 +++++- src/i18n/messages/de_DE.json | 35 +++++- src/i18n/messages/es_419.json | 35 +++++- src/i18n/messages/fa_IR.json | 35 +++++- src/i18n/messages/fr.json | 35 +++++- src/i18n/messages/fr_CA.json | 35 +++++- src/i18n/messages/hi.json | 35 +++++- src/i18n/messages/it.json | 35 +++++- src/i18n/messages/it_IT.json | 35 +++++- src/i18n/messages/pt.json | 35 +++++- src/i18n/messages/pt_PT.json | 35 +++++- src/i18n/messages/ru.json | 35 +++++- src/i18n/messages/uk.json | 35 +++++- src/i18n/messages/zh_CN.json | 35 +++++- 33 files changed, 1050 insertions(+), 38 deletions(-) create mode 100644 src/course-unit/__mocks__/courseVerticalChildren.js create mode 100644 src/course-unit/course-xblock/CourseXBlock.jsx create mode 100644 src/course-unit/course-xblock/CourseXBlock.test.jsx create mode 100644 src/course-unit/course-xblock/CourseXblock.scss create mode 100644 src/course-unit/course-xblock/messages.js rename src/{course-outline => generic}/delete-modal/DeleteModal.jsx (76%) rename src/{course-outline => generic}/delete-modal/DeleteModal.test.jsx (94%) rename src/{course-outline => generic}/delete-modal/messages.js (100%) diff --git a/src/course-outline/CourseOutline.jsx b/src/course-outline/CourseOutline.jsx index 986969ee5..5710fd01c 100644 --- a/src/course-outline/CourseOutline.jsx +++ b/src/course-outline/CourseOutline.jsx @@ -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} /> { 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 }]} > + + {courseVerticalChildren.children.map(({ name, blockId: id, shouldScroll }) => ( + + ))} + ', () => { .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('', () => { 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('', () => { 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('', () => { 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('', () => { 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(); + + 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(); + + 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(); + }); + }); }); diff --git a/src/course-unit/__mocks__/courseVerticalChildren.js b/src/course-unit/__mocks__/courseVerticalChildren.js new file mode 100644 index 000000000..8c3651ba6 --- /dev/null +++ b/src/course-unit/__mocks__/courseVerticalChildren.js @@ -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, +}; diff --git a/src/course-unit/__mocks__/index.js b/src/course-unit/__mocks__/index.js index cd5c4ffdf..d8c220b7a 100644 --- a/src/course-unit/__mocks__/index.js +++ b/src/course-unit/__mocks__/index.js @@ -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'; diff --git a/src/course-unit/course-xblock/CourseXBlock.jsx b/src/course-unit/course-xblock/CourseXBlock.jsx new file mode 100644 index 000000000..bd8a11ebf --- /dev/null +++ b/src/course-unit/course-xblock/CourseXBlock.jsx @@ -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 ( +
+ + + {}} + /> + + + + + {intl.formatMessage(messages.blockLabelButtonCopy)} + + unitXBlockActions.handleDuplicate(id)}> + {intl.formatMessage(messages.blockLabelButtonDuplicate)} + + + {intl.formatMessage(messages.blockLabelButtonMove)} + + + {intl.formatMessage(messages.blockLabelButtonManageAccess)} + + + {intl.formatMessage(messages.blockLabelButtonDelete)} + + + + + + )} + size="md" + /> + +
+ + +
+ ); +}; + +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; diff --git a/src/course-unit/course-xblock/CourseXBlock.test.jsx b/src/course-unit/course-xblock/CourseXBlock.test.jsx new file mode 100644 index 000000000..2c6defc76 --- /dev/null +++ b/src/course-unit/course-xblock/CourseXBlock.test.jsx @@ -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( + + + + + , +); + +describe('', () => { + 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); + }); + }); +}); diff --git a/src/course-unit/course-xblock/CourseXblock.scss b/src/course-unit/course-xblock/CourseXblock.scss new file mode 100644 index 000000000..52c8e0bef --- /dev/null +++ b/src/course-unit/course-xblock/CourseXblock.scss @@ -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; + } + } +} diff --git a/src/course-unit/course-xblock/messages.js b/src/course-unit/course-xblock/messages.js new file mode 100644 index 000000000..80e25dac1 --- /dev/null +++ b/src/course-unit/course-xblock/messages.js @@ -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; diff --git a/src/course-unit/data/api.js b/src/course-unit/data/api.js index 5e1e5158a..43992f576 100644 --- a/src/course-unit/data/api.js +++ b/src/course-unit/data/api.js @@ -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} + */ +export async function getCourseVerticalChildren(itemId) { + const { data } = await getAuthenticatedHttpClient() + .get(getCourseVerticalChildrenApiUrl(itemId)); + + return camelCaseObject(data); +} + +/** + * Delete a unit item. + * @param {string} itemId + * @returns {Promise} + */ +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} + */ +export async function duplicateUnitItem(itemId, XBlockId) { + const { data } = await getAuthenticatedHttpClient() + .post(postXBlockBaseApiUrl(), { + parent_locator: itemId, + duplicate_source_locator: XBlockId, + }); + + return data; +} diff --git a/src/course-unit/data/selectors.js b/src/course-unit/data/selectors.js index a5a1eb95b..5fa52ac1b 100644 --- a/src/course-unit/data/selectors.js +++ b/src/course-unit/data/selectors.js @@ -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) => { diff --git a/src/course-unit/data/slice.js b/src/course-unit/data/slice.js index 7f243c511..bd4066afc 100644 --- a/src/course-unit/data/slice.js +++ b/src/course-unit/data/slice.js @@ -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 { diff --git a/src/course-unit/data/thunk.js b/src/course-unit/data/thunk.js index defb940cd..b6e247784 100644 --- a/src/course-unit/data/thunk.js +++ b/src/course-unit/data/thunk.js @@ -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 })); + } + }; +} diff --git a/src/course-unit/hooks.jsx b/src/course-unit/hooks.jsx index 7c7a01fc9..b99bfaed1 100644 --- a/src/course-unit/hooks.jsx +++ b/src/course-unit/hooks.jsx @@ -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, }; }; diff --git a/src/course-outline/delete-modal/DeleteModal.jsx b/src/generic/delete-modal/DeleteModal.jsx similarity index 76% rename from src/course-outline/delete-modal/DeleteModal.jsx rename to src/generic/delete-modal/DeleteModal.jsx index eff6cb317..1f9ebc286 100644 --- a/src/course-outline/delete-modal/DeleteModal.jsx +++ b/src/generic/delete-modal/DeleteModal.jsx @@ -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 ( { DeleteModal.propTypes = { isOpen: PropTypes.bool.isRequired, close: PropTypes.func.isRequired, + category: PropTypes.string.isRequired, onDeleteSubmit: PropTypes.func.isRequired, }; diff --git a/src/course-outline/delete-modal/DeleteModal.test.jsx b/src/generic/delete-modal/DeleteModal.test.jsx similarity index 94% rename from src/course-outline/delete-modal/DeleteModal.test.jsx rename to src/generic/delete-modal/DeleteModal.test.jsx index e03e4a4b8..5edf101f8 100644 --- a/src/course-outline/delete-modal/DeleteModal.test.jsx +++ b/src/generic/delete-modal/DeleteModal.test.jsx @@ -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( @@ -60,7 +56,6 @@ describe('', () => { store = initializeStore(); axiosMock = new MockAdapter(getAuthenticatedHttpClient()); - useSelector.mockReturnValue(currentItemMock); }); it('render DeleteModal component correctly', () => { diff --git a/src/course-outline/delete-modal/messages.js b/src/generic/delete-modal/messages.js similarity index 100% rename from src/course-outline/delete-modal/messages.js rename to src/generic/delete-modal/messages.js diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index b7f55cd56..57a247dbf 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -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" } diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -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" } diff --git a/src/i18n/messages/de_DE.json b/src/i18n/messages/de_DE.json index 5b567106a..5ad4d1441 100644 --- a/src/i18n/messages/de_DE.json +++ b/src/i18n/messages/de_DE.json @@ -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" } diff --git a/src/i18n/messages/es_419.json b/src/i18n/messages/es_419.json index 29a33d631..979df0d74 100644 --- a/src/i18n/messages/es_419.json +++ b/src/i18n/messages/es_419.json @@ -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" } diff --git a/src/i18n/messages/fa_IR.json b/src/i18n/messages/fa_IR.json index 423f64688..1252d8c29 100644 --- a/src/i18n/messages/fa_IR.json +++ b/src/i18n/messages/fa_IR.json @@ -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" } diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index 8a8181249..003397d4d 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -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" } diff --git a/src/i18n/messages/fr_CA.json b/src/i18n/messages/fr_CA.json index dc8f5d57f..0b0f31624 100644 --- a/src/i18n/messages/fr_CA.json +++ b/src/i18n/messages/fr_CA.json @@ -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" } diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -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" } diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -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" } diff --git a/src/i18n/messages/it_IT.json b/src/i18n/messages/it_IT.json index a17d786ee..de45f7f48 100644 --- a/src/i18n/messages/it_IT.json +++ b/src/i18n/messages/it_IT.json @@ -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" } diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -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" } diff --git a/src/i18n/messages/pt_PT.json b/src/i18n/messages/pt_PT.json index b345c4711..c804de275 100644 --- a/src/i18n/messages/pt_PT.json +++ b/src/i18n/messages/pt_PT.json @@ -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" } diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -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" } diff --git a/src/i18n/messages/uk.json b/src/i18n/messages/uk.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/uk.json +++ b/src/i18n/messages/uk.json @@ -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" } diff --git a/src/i18n/messages/zh_CN.json b/src/i18n/messages/zh_CN.json index e3311ad17..e06d421e3 100644 --- a/src/i18n/messages/zh_CN.json +++ b/src/i18n/messages/zh_CN.json @@ -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" }