diff --git a/src/course-outline/card-header/CardHeader.jsx b/src/course-outline/card-header/CardHeader.jsx
index 1524b3fb17..4e7cae4e43 100644
--- a/src/course-outline/card-header/CardHeader.jsx
+++ b/src/course-outline/card-header/CardHeader.jsx
@@ -27,6 +27,7 @@ const CardHeader = ({
hasChanges,
onClickPublish,
onClickConfigure,
+ onClickManageTags,
onClickMenuButton,
onClickEdit,
isFormOpen,
@@ -162,6 +163,15 @@ const CardHeader = ({
>
{intl.formatMessage(messages.menuConfigure)}
+ {onClickManageTags && (
+
+ {intl.formatMessage(messages.menuManageTags)}
+
+ )}
+
{isVertical && enableCopyPasteUnits && (
{intl.formatMessage(messages.menuCopy)}
@@ -218,6 +228,7 @@ CardHeader.defaultProps = {
discussionEnabled: false,
discussionsSettings: {},
parentInfo: {},
+ onClickManageTags: null,
};
CardHeader.propTypes = {
@@ -227,6 +238,7 @@ CardHeader.propTypes = {
hasChanges: PropTypes.bool.isRequired,
onClickPublish: PropTypes.func.isRequired,
onClickConfigure: PropTypes.func.isRequired,
+ onClickManageTags: PropTypes.func,
onClickMenuButton: PropTypes.func.isRequired,
onClickEdit: PropTypes.func.isRequired,
isFormOpen: PropTypes.bool.isRequired,
diff --git a/src/course-outline/card-header/CardHeader.test.jsx b/src/course-outline/card-header/CardHeader.test.jsx
index 1a666b6614..35ce66d599 100644
--- a/src/course-outline/card-header/CardHeader.test.jsx
+++ b/src/course-outline/card-header/CardHeader.test.jsx
@@ -1,6 +1,6 @@
import { MemoryRouter } from 'react-router-dom';
import {
- act, render, fireEvent, waitFor,
+ act, render, fireEvent, waitFor, screen,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
@@ -18,6 +18,7 @@ const onClickDuplicateMock = jest.fn();
const onClickConfigureMock = jest.fn();
const onClickMoveUpMock = jest.fn();
const onClickMoveDownMock = jest.fn();
+const onClickManageTagsMock = jest.fn();
const closeFormMock = jest.fn();
const cardHeaderProps = {
@@ -28,6 +29,7 @@ const cardHeaderProps = {
onClickMenuButton: onClickMenuButtonMock,
onClickPublish: onClickPublishMock,
onClickEdit: onClickEditMock,
+ onClickManageTags: onClickManageTagsMock,
isFormOpen: false,
onEditSubmit: jest.fn(),
closeForm: closeFormMock,
@@ -168,6 +170,16 @@ describe('', () => {
expect(onClickPublishMock).toHaveBeenCalled();
});
+ it('calls onClickManageTags when the menu is clicked', async () => {
+ renderComponent();
+ const menuButton = await screen.findByTestId('subsection-card-header__menu-button');
+ fireEvent.click(menuButton);
+
+ const manageTagsMenuItem = await screen.findByText(messages.menuManageTags.defaultMessage);
+ await act(async () => fireEvent.click(manageTagsMenuItem));
+ expect(onClickManageTagsMock).toHaveBeenCalled();
+ });
+
it('calls onClickEdit when the button is clicked', async () => {
const { findByTestId } = renderComponent();
diff --git a/src/course-outline/card-header/messages.js b/src/course-outline/card-header/messages.js
index d9f250970d..410443d695 100644
--- a/src/course-outline/card-header/messages.js
+++ b/src/course-outline/card-header/messages.js
@@ -73,6 +73,10 @@ const messages = defineMessages({
id: 'course-authoring.course-outline.card.badge.discussionEnabled',
defaultMessage: 'Discussions enabled',
},
+ menuManageTags: {
+ id: 'course-authoring.course-outline.card.menu.manageTags',
+ defaultMessage: 'Manage tags',
+ },
});
export default messages;
diff --git a/src/course-outline/unit-card/UnitCard.jsx b/src/course-outline/unit-card/UnitCard.jsx
index f2cb4ac3e9..1ab5a97a5c 100644
--- a/src/course-outline/unit-card/UnitCard.jsx
+++ b/src/course-outline/unit-card/UnitCard.jsx
@@ -1,7 +1,7 @@
-import { useEffect, useRef } from 'react';
+import { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
-import { useToggle } from '@openedx/paragon';
+import { useToggle, Sheet } from '@openedx/paragon';
import { setCurrentItem, setCurrentSection, setCurrentSubsection } from '../data/slice';
import { RequestStatus } from '../../data/constants';
@@ -10,6 +10,7 @@ import ConditionalSortableElement from '../drag-helper/ConditionalSortableElemen
import TitleLink from '../card-header/TitleLink';
import XBlockStatus from '../xblock-status/XBlockStatus';
import { getItemStatus, getItemStatusBorder, scrollToElement } from '../utils';
+import { ContentTagsDrawer } from '../../content-tags-drawer';
const UnitCard = ({
unit,
@@ -34,6 +35,7 @@ const UnitCard = ({
const dispatch = useDispatch();
const [isFormOpen, openForm, closeForm] = useToggle(false);
const namePrefix = 'unit';
+ const [showManageTags, setShowManageTags] = useState(false);
const {
id,
@@ -122,55 +124,68 @@ const UnitCard = ({
const isDraggable = actions.draggable && (actions.allowMoveUp || actions.allowMoveDown);
return (
-
-
+
-
-
-
+ setShowManageTags(true)}
+ onClickEdit={openForm}
+ onClickDelete={onOpenDeleteModal}
+ onClickMoveUp={handleUnitMoveUp}
+ onClickMoveDown={handleUnitMoveDown}
+ isFormOpen={isFormOpen}
+ closeForm={closeForm}
+ onEditSubmit={handleEditSubmit}
+ isDisabledEditField={savingStatus === RequestStatus.IN_PROGRESS}
+ onClickDuplicate={onDuplicateSubmit}
+ titleComponent={titleComponent}
+ namePrefix={namePrefix}
+ actions={actions}
+ isVertical
+ enableCopyPasteUnits={enableCopyPasteUnits}
+ onClickCopy={handleCopyClick}
+ discussionEnabled={discussionEnabled}
+ discussionsSettings={discussionsSettings}
+ parentInfo={parentInfo}
/>
+
+
+
-
-
+
+ setShowManageTags(false)}
+ >
+ setShowManageTags(false)}
+ />
+
+ >
);
};