diff --git a/src/course-outline/subsection-card/SubsectionCard.test.tsx b/src/course-outline/subsection-card/SubsectionCard.test.tsx
index 159f8bd5aa..ff01a59b86 100644
--- a/src/course-outline/subsection-card/SubsectionCard.test.tsx
+++ b/src/course-outline/subsection-card/SubsectionCard.test.tsx
@@ -5,6 +5,7 @@ import {
import { XBlock } from '@src/data/types';
import cardHeaderMessages from '../card-header/messages';
import SubsectionCard from './SubsectionCard';
+import { SidebarProvider } from '../common/context/SidebarContext';
let store;
const containerKey = 'lct:org:lib:unit:1';
@@ -105,29 +106,31 @@ const section: XBlock = {
const onEditSubectionSubmit = jest.fn();
const renderComponent = (props?: object, entry = '/course/:courseId') => render(
-
- children
- ,
+
+
+ children
+
+ ,
{
path: '/course/:courseId',
params: { courseId: '5' },
@@ -147,6 +150,28 @@ describe('
', () => {
renderComponent();
expect(screen.getByTestId('subsection-card-header')).toBeInTheDocument();
+
+ // The card is not selected
+ const card = screen.getByTestId('subsection-card');
+ expect(card).not.toHaveClass('outline-card-selected');
+ });
+
+ it('render SubsectionCard component in selected state', () => {
+ const { container } = renderComponent();
+
+ expect(screen.getByTestId('subsection-card-header')).toBeInTheDocument();
+
+ // The card is not selected
+ const card = screen.getByTestId('subsection-card');
+ expect(card).not.toHaveClass('outline-card-selected');
+
+ // Get the
that contains the card and click it to select the card
+ const el = container.querySelector('div.row.mx-0') as HTMLInputElement;
+ expect(el).not.toBeNull();
+ fireEvent.click(el!);
+
+ // The card is selected
+ expect(card).toHaveClass('outline-card-selected');
});
it('expands/collapses the card when the subsection button is clicked', async () => {
diff --git a/src/course-outline/subsection-card/SubsectionCard.tsx b/src/course-outline/subsection-card/SubsectionCard.tsx
index 389338519c..a07a1b7e29 100644
--- a/src/course-outline/subsection-card/SubsectionCard.tsx
+++ b/src/course-outline/subsection-card/SubsectionCard.tsx
@@ -30,6 +30,7 @@ import { PreviewLibraryXBlockChanges } from '@src/course-unit/preview-changes';
import type { XBlock } from '@src/data/types';
import { invalidateLinksQuery } from '@src/course-libraries/data/apiHooks';
import messages from './messages';
+import { useSidebarContext } from '../common/context/SidebarContext';
interface SubsectionCardProps {
section: XBlock,
@@ -88,6 +89,7 @@ const SubsectionCard = ({
const intl = useIntl();
const dispatch = useDispatch();
const { activeId, overId } = useContext(DragContext);
+ const { selectedContainerId, openContainerInfoSidebar } = useSidebarContext();
const [searchParams] = useSearchParams();
const locatorId = searchParams.get('show');
const isScrolledToElement = locatorId === subsection.id;
@@ -263,6 +265,12 @@ const SubsectionCard = ({
closeAddLibraryUnitModal();
}, [id, onAddUnitFromLibrary, closeAddLibraryUnitModal]);
+ const onClickCard = useCallback((e: React.MouseEvent) => {
+ if (e.target === e.currentTarget) {
+ openContainerInfoSidebar(subsection.id);
+ }
+ }, [openContainerInfoSidebar]);
+
return (
<>
diff --git a/src/course-outline/unit-card/UnitCard.test.tsx b/src/course-outline/unit-card/UnitCard.test.tsx
index c8282a2735..034d878849 100644
--- a/src/course-outline/unit-card/UnitCard.test.tsx
+++ b/src/course-outline/unit-card/UnitCard.test.tsx
@@ -5,6 +5,7 @@ import {
import { XBlock } from '@src/data/types';
import UnitCard from './UnitCard';
import cardMessages from '../card-header/messages';
+import { SidebarProvider } from '../common/context/SidebarContext';
const mockUseAcceptLibraryBlockChanges = jest.fn();
const mockUseIgnoreLibraryBlockChanges = jest.fn();
@@ -73,28 +74,30 @@ const unit = {
} satisfies Partial
as XBlock;
const renderComponent = (props?: object) => render(
- `/some/${id}`}
- isSelfPaced={false}
- isCustomRelativeDatesActive={false}
- discussionsSettings={{
- providerType: '',
- enableGradedUnits: false,
- }}
- {...props}
- />,
+
+ `/some/${id}`}
+ isSelfPaced={false}
+ isCustomRelativeDatesActive={false}
+ discussionsSettings={{
+ providerType: '',
+ enableGradedUnits: false,
+ }}
+ {...props}
+ />
+ ,
{
path: '/course/:courseId',
params: { courseId: '5' },
@@ -114,6 +117,28 @@ describe('', () => {
'href',
'/some/block-v1:UNIX+UX1+2025_T3+type@unit+block@0',
);
+
+ // The card is not selected
+ const card = screen.getByTestId('unit-card');
+ expect(card).not.toHaveClass('outline-card-selected');
+ });
+
+ it('render UnitCard component in selected state', () => {
+ const { container } = renderComponent();
+
+ expect(screen.getByTestId('unit-card-header')).toBeInTheDocument();
+
+ // The card is not selected
+ const card = screen.getByTestId('unit-card');
+ expect(card).not.toHaveClass('outline-card-selected');
+
+ // Get the that contains the card and click it to select the card
+ const el = container.querySelector('div.row.mx-0') as HTMLInputElement;
+ expect(el).not.toBeNull();
+ fireEvent.click(el!);
+
+ // The card is selected
+ expect(card).toHaveClass('outline-card-selected');
});
it('hides header based on isHeaderVisible flag', async () => {
diff --git a/src/course-outline/unit-card/UnitCard.tsx b/src/course-outline/unit-card/UnitCard.tsx
index 8029f603cc..6ce23aa8fc 100644
--- a/src/course-outline/unit-card/UnitCard.tsx
+++ b/src/course-outline/unit-card/UnitCard.tsx
@@ -4,6 +4,7 @@ import {
useMemo,
useRef,
} from 'react';
+import classNames from 'classnames';
import { useDispatch } from 'react-redux';
import { useToggle } from '@openedx/paragon';
import { isEmpty } from 'lodash';
@@ -24,6 +25,7 @@ import { UpstreamInfoIcon } from '@src/generic/upstream-info-icon';
import { PreviewLibraryXBlockChanges } from '@src/course-unit/preview-changes';
import { invalidateLinksQuery } from '@src/course-libraries/data/apiHooks';
import type { XBlock } from '@src/data/types';
+import { useSidebarContext } from '../common/context/SidebarContext';
interface UnitCardProps {
unit: XBlock;
@@ -70,6 +72,7 @@ const UnitCard = ({
const currentRef = useRef(null);
const dispatch = useDispatch();
const [searchParams] = useSearchParams();
+ const { selectedContainerId, openContainerInfoSidebar } = useSidebarContext();
const locatorId = searchParams.get('show');
const isScrolledToElement = locatorId === unit.id;
const [isFormOpen, openForm, closeForm] = useToggle(false);
@@ -165,6 +168,12 @@ const UnitCard = ({
}
}, [dispatch, section, queryClient, courseId]);
+ const onClickCard = useCallback((e: React.MouseEvent) => {
+ if (e.target === e.currentTarget) {
+ openContainerInfoSidebar(unit.id);
+ }
+ }, [openContainerInfoSidebar]);
+
const titleComponent = (
diff --git a/src/index.scss b/src/index.scss
index 57cad42c85..431cb9cf10 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -39,6 +39,11 @@ div.row:has(> div > div.highlight) {
animation-timing-function: cubic-bezier(1, 0, .72, .04);
}
+// To apply selection style to selected Section/Subsecion/Units, in the Course Outline
+div.row:has(> div > div.outline-card-selected) {
+ box-shadow: 0 0 3px 3px var(--pgn-color-primary-500) !important;
+}
+
// To apply the glow effect to the selected xblock, in the Unit Outline
div.xblock-highlight {
animation: 5s glow;