From 6ae67224fdb9595b3b03b7d5d6ffd7e467f2c299 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Mon, 23 Feb 2026 15:50:09 -0500 Subject: [PATCH 01/10] fix: Open info sidebar when creating containers --- src/course-outline/OutlineAddChildButtons.tsx | 12 +++++++++++- .../outline-sidebar/AddSidebar.tsx | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/course-outline/OutlineAddChildButtons.tsx b/src/course-outline/OutlineAddChildButtons.tsx index 562c489cba..94063a8d1c 100644 --- a/src/course-outline/OutlineAddChildButtons.tsx +++ b/src/course-outline/OutlineAddChildButtons.tsx @@ -111,7 +111,7 @@ const NewOutlineAddChildButtons = ({ handleAddBlock, handleAddAndOpenUnit, } = useCourseAuthoringContext(); - const { startCurrentFlow } = useOutlineSidebarContext(); + const { startCurrentFlow, openContainerInfoSidebar } = useOutlineSidebarContext(); let messageMap = { newButton: messages.newUnitButton, importButton: messages.useUnitFromLibraryButton, @@ -130,6 +130,11 @@ const NewOutlineAddChildButtons = ({ type: ContainerType.Chapter, parentLocator: courseUsageKey, displayName: COURSE_BLOCK_NAMES.chapter.name, + }, { + onSuccess: (data: { locator: string; }) => { + // istanbul ignore next + openContainerInfoSidebar(data.locator, undefined, data.locator); + }, }); flowType = ContainerType.Section; break; @@ -143,6 +148,11 @@ const NewOutlineAddChildButtons = ({ parentLocator, displayName: COURSE_BLOCK_NAMES.sequential.name, sectionId: parentLocator, + }, { + onSuccess: (data: { locator: string; }) => { + // istanbul ignore next + openContainerInfoSidebar(data.locator, data.locator, parentLocator); + }, }); flowType = ContainerType.Subsection; break; diff --git a/src/course-outline/outline-sidebar/AddSidebar.tsx b/src/course-outline/outline-sidebar/AddSidebar.tsx index 8915d5da98..49edff6c29 100644 --- a/src/course-outline/outline-sidebar/AddSidebar.tsx +++ b/src/course-outline/outline-sidebar/AddSidebar.tsx @@ -222,6 +222,7 @@ const ShowLibraryContent = () => { lastEditableSubsection, selectedContainerState, currentItemData, + openContainerInfoSidebar, } = useOutlineSidebarContext(); let sectionParentId = lastEditableSection?.id; @@ -235,6 +236,11 @@ const ShowLibraryContent = () => { category: ContainerType.Chapter, parentLocator: courseUsageKey, libraryContentKey: usageKey, + }, { + onSuccess: (data: { locator: string; }) => { + // istanbul ignore next + openContainerInfoSidebar(data.locator, undefined, data.locator); + }, }); break; case 'subsection': @@ -246,6 +252,11 @@ const ShowLibraryContent = () => { parentLocator: sectionParentId, libraryContentKey: usageKey, sectionId: sectionParentId, + }, { + onSuccess: (data: { locator: string; }) => { + // istanbul ignore next + openContainerInfoSidebar(data.locator, data.locator, sectionParentId); + }, }); } break; @@ -261,6 +272,11 @@ const ShowLibraryContent = () => { parentLocator: subsectionParentId, libraryContentKey: usageKey, sectionId: sectionParentId, + }, { + onSuccess: (data: { locator: string; }) => { + // istanbul ignore next + openContainerInfoSidebar(data.locator, subsectionParentId, sectionParentId); + }, }); } break; From a2c13f6fb011de9ce3b61a5ba95826869fb3c360 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Mon, 23 Feb 2026 21:01:21 -0500 Subject: [PATCH 02/10] fix: Disable view live button in unit header when is never published --- src/course-unit/CourseUnit.tsx | 1 + .../HeaderNavigations.test.tsx | 12 +++++ .../header-navigations/HeaderNavigations.tsx | 10 +++- .../CourseUnitHeaderActionsSlot/index.jsx | 44 ----------------- .../index.test.tsx | 3 ++ .../CourseUnitHeaderActionsSlot/index.tsx | 49 +++++++++++++++++++ 6 files changed, 73 insertions(+), 46 deletions(-) delete mode 100644 src/plugin-slots/CourseUnitHeaderActionsSlot/index.jsx create mode 100644 src/plugin-slots/CourseUnitHeaderActionsSlot/index.tsx diff --git a/src/course-unit/CourseUnit.tsx b/src/course-unit/CourseUnit.tsx index 14fa7f9e54..e07cb204b1 100644 --- a/src/course-unit/CourseUnit.tsx +++ b/src/course-unit/CourseUnit.tsx @@ -312,6 +312,7 @@ const CourseUnit = () => { headerNavigationsActions={headerNavigationsActions} unitTitle={unitTitle} verticalBlocks={courseVerticalChildren.children} + isPublished={courseUnit.published} /> )} /> diff --git a/src/course-unit/header-navigations/HeaderNavigations.test.tsx b/src/course-unit/header-navigations/HeaderNavigations.test.tsx index a650677232..7cbff05f4d 100644 --- a/src/course-unit/header-navigations/HeaderNavigations.test.tsx +++ b/src/course-unit/header-navigations/HeaderNavigations.test.tsx @@ -78,6 +78,18 @@ describe('', () => { }); }); + it('should enable the "View Live" button when isPublished is true', () => { + renderComponent({ unitCategory: COURSE_BLOCK_NAMES.vertical.id, isPublished: true }); + + expect(screen.getByRole('button', { name: messages.viewLiveButton.defaultMessage })).not.toBeDisabled(); + }); + + it('should disable the "View Live" button when isPublished is false', () => { + renderComponent({ unitCategory: COURSE_BLOCK_NAMES.vertical.id, isPublished: false }); + + expect(screen.getByRole('button', { name: messages.viewLiveButton.defaultMessage })).toBeDisabled(); + }); + it('click Info button should open info sidebar', async () => { setConfig({ ...getConfig(), diff --git a/src/course-unit/header-navigations/HeaderNavigations.tsx b/src/course-unit/header-navigations/HeaderNavigations.tsx index 093dd0cb54..5bf83aa7bc 100644 --- a/src/course-unit/header-navigations/HeaderNavigations.tsx +++ b/src/course-unit/header-navigations/HeaderNavigations.tsx @@ -11,7 +11,7 @@ import messages from './messages'; import { isUnitPageNewDesignEnabled } from '../utils'; import { useUnitSidebarContext } from '../unit-sidebar/UnitSidebarContext'; -type HeaderNavigationActions = { +export type HeaderNavigationActions = { handleViewLive: () => void; handlePreview: () => void; handleEdit: () => void; @@ -20,6 +20,7 @@ type HeaderNavigationActions = { type HeaderNavigationsProps = { headerNavigationsActions: HeaderNavigationActions; category: string; + isPublished?: boolean; }; /** @@ -28,7 +29,11 @@ type HeaderNavigationsProps = { * - Legacy library content page * - Split test page */ -const HeaderNavigations = ({ headerNavigationsActions, category }: HeaderNavigationsProps) => { +const HeaderNavigations = ({ + headerNavigationsActions, + category, + isPublished = true, +}: HeaderNavigationsProps) => { const intl = useIntl(); const { handleViewLive, @@ -78,6 +83,7 @@ const HeaderNavigations = ({ headerNavigationsActions, category }: HeaderNavigat diff --git a/src/plugin-slots/CourseUnitHeaderActionsSlot/index.jsx b/src/plugin-slots/CourseUnitHeaderActionsSlot/index.jsx deleted file mode 100644 index ff4446ba05..0000000000 --- a/src/plugin-slots/CourseUnitHeaderActionsSlot/index.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { PluginSlot } from '@openedx/frontend-plugin-framework'; - -import HeaderNavigations from 'CourseAuthoring/course-unit/header-navigations/HeaderNavigations'; -import { COURSE_BLOCK_NAMES } from 'CourseAuthoring/constants'; - -const CourseUnitHeaderActionsSlot = ({ - headerNavigationsActions, category, unitTitle, verticalBlocks, -}) => { - const isUnitVerticalType = category === COURSE_BLOCK_NAMES.vertical.id; - return ( - - - - ); -}; - -CourseUnitHeaderActionsSlot.propTypes = { - headerNavigationsActions: PropTypes.shape({ - handleViewLive: PropTypes.func.isRequired, - handlePreview: PropTypes.func.isRequired, - handleEdit: PropTypes.func.isRequired, - }).isRequired, - category: PropTypes.string.isRequired, - unitTitle: PropTypes.string.isRequired, - verticalBlocks: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - blockId: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - blockType: PropTypes.string.isRequired, - }), - ).isRequired, -}; - -export default CourseUnitHeaderActionsSlot; diff --git a/src/plugin-slots/CourseUnitHeaderActionsSlot/index.test.tsx b/src/plugin-slots/CourseUnitHeaderActionsSlot/index.test.tsx index c55fe17da1..82f12fa1fa 100644 --- a/src/plugin-slots/CourseUnitHeaderActionsSlot/index.test.tsx +++ b/src/plugin-slots/CourseUnitHeaderActionsSlot/index.test.tsx @@ -21,6 +21,7 @@ const headerNavProps = { unitTitle: 'Mock Unit', isUnitVerticalType: false, verticalBlocks: [], + isPublished: true, }; describe('CourseUnitHeaderActionsSlot', () => { @@ -40,6 +41,7 @@ describe('CourseUnitHeaderActionsSlot', () => { verticalBlocks={[]} category="library" headerNavigationsActions={headerNavProps.headerNavigationsActions} + isPublished />, ); expect(component.toJSON().props.pluginProps.isUnitVerticalType).toEqual(false); @@ -50,6 +52,7 @@ describe('CourseUnitHeaderActionsSlot', () => { verticalBlocks={[]} category={COURSE_BLOCK_NAMES.vertical.id} headerNavigationsActions={headerNavProps.headerNavigationsActions} + isPublished />, ); expect(component.toJSON().props.pluginProps.isUnitVerticalType).toEqual(true); diff --git a/src/plugin-slots/CourseUnitHeaderActionsSlot/index.tsx b/src/plugin-slots/CourseUnitHeaderActionsSlot/index.tsx new file mode 100644 index 0000000000..db8a26cd2d --- /dev/null +++ b/src/plugin-slots/CourseUnitHeaderActionsSlot/index.tsx @@ -0,0 +1,49 @@ +import { PluginSlot } from '@openedx/frontend-plugin-framework'; + +import HeaderNavigations, { HeaderNavigationActions } from 'CourseAuthoring/course-unit/header-navigations/HeaderNavigations'; +import { COURSE_BLOCK_NAMES } from 'CourseAuthoring/constants'; + +export interface CourseUnitHeaderActionsSlotProps { + headerNavigationsActions: HeaderNavigationActions; + category: string; + unitTitle: string; + verticalBlocks: { + id: string; + blockId: string; + name: string; + blockType: string; + }[]; + isPublished: boolean; +} + +const CourseUnitHeaderActionsSlot = ({ + headerNavigationsActions, + category, + unitTitle, + verticalBlocks, + isPublished, +}: CourseUnitHeaderActionsSlotProps) => { + const isUnitVerticalType = category === COURSE_BLOCK_NAMES.vertical.id; + return ( + + + + ); +}; + +export default CourseUnitHeaderActionsSlot; From 8ffa53d920030da3e648214ec4f58d5d3638ea44 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 7 Apr 2026 17:13:14 -0500 Subject: [PATCH 03/10] fix: Update icon size in course outline container cards --- src/course-outline/card-header/CardHeader.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/course-outline/card-header/CardHeader.scss b/src/course-outline/card-header/CardHeader.scss index ffa8712a7c..cf4a0c6875 100644 --- a/src/course-outline/card-header/CardHeader.scss +++ b/src/course-outline/card-header/CardHeader.scss @@ -6,7 +6,7 @@ justify-content: flex-start; padding: 0; flex: 1 1 0; - height: 1.5rem; + height: 1.75rem; margin-right: .25rem; background: transparent; color: var(--pgn-color-black); From 92f72006499f03ed6321806e1fb5c7f292d16120 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 7 Apr 2026 17:35:54 -0500 Subject: [PATCH 04/10] fix: Add margin to the toggle button --- src/generic/sidebar/Sidebar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generic/sidebar/Sidebar.tsx b/src/generic/sidebar/Sidebar.tsx index ebfd06aee4..bbb3c89a30 100644 --- a/src/generic/sidebar/Sidebar.tsx +++ b/src/generic/sidebar/Sidebar.tsx @@ -137,6 +137,7 @@ export function Sidebar({ alt={intl.formatMessage(messages.toggle)} onClick={toggle} variant="primary" + className="mb-2" /> Date: Tue, 7 Apr 2026 17:47:05 -0500 Subject: [PATCH 05/10] fix: Add negative margin to add cards --- src/generic/sidebar/BlockCardButton.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generic/sidebar/BlockCardButton.tsx b/src/generic/sidebar/BlockCardButton.tsx index 569fdf0ac9..600e466167 100644 --- a/src/generic/sidebar/BlockCardButton.tsx +++ b/src/generic/sidebar/BlockCardButton.tsx @@ -47,7 +47,7 @@ export const BlockCardButton = ({
@@ -65,7 +65,7 @@ export const BlockCardButton = ({ return ( + {/* TODO: convert to