feat: Add sidebar and library dropdown filter [FC-0114] (#2778)

* Add flow in course outline sidebar. Allows author to add new section/subsection/unit or any container from existing libraries via sidebar.
* Adds library dropdown filter and collections dropdown filter in add sidebar. Allows authors to filter containers by selected libraries and collections.
This commit is contained in:
Navin Karkera
2026-01-09 22:44:48 +05:30
committed by GitHub
parent a7cbfead75
commit 3c22e4bbe1
107 changed files with 2218 additions and 659 deletions

View File

@@ -25,9 +25,9 @@ const blockId = '123';
const handleCreateNewCourseXBlockMock = jest.fn();
const usageKey = 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fddest-usage-key';
// Mock ComponentPicker to call onComponentSelected on click
// Mock LibraryAndComponentPicker to call onComponentSelected on click
jest.mock('../../library-authoring/component-picker', () => ({
ComponentPicker: (props) => {
LibraryAndComponentPicker: (props) => {
const onClick = () => {
if (props.componentPickerMode === 'single') {
props.onComponentSelected({

View File

@@ -8,7 +8,7 @@ import {
import { useWaffleFlags } from '@src/data/apiHooks';
import { COMPONENT_TYPES } from '@src/generic/block-type-utils/constants';
import { ComponentPicker } from '@src/library-authoring/component-picker';
import { LibraryAndComponentPicker } from '@src/library-authoring/component-picker';
import { ContentType } from '@src/library-authoring/routes';
import { useIframe } from '@src/generic/hooks/context/hooks';
import { useEventListener } from '@src/generic/hooks';
@@ -276,7 +276,7 @@ const AddComponent = ({
)
}
>
<ComponentPicker
<LibraryAndComponentPicker
showOnlyPublished
extraFilter={['NOT block_type = "unit"', 'NOT block_type = "section"', 'NOT block_type = "subsection"']}
visibleTabs={[ContentType.home, ContentType.components, ContentType.collections]}

View File

@@ -41,42 +41,6 @@ export async function getVerticalData(unitId: string): Promise<object> {
return courseSectionVerticalData;
}
/**
* Creates a new course XBlock.
*/
export async function createCourseXblock({
type,
category,
parentLocator,
displayName,
boilerplate,
stagedContent,
libraryContentKey,
}: {
type: string,
category?: string, // The category of the XBlock. Defaults to the type if not provided.
parentLocator: string,
displayName?: string,
boilerplate?: string,
stagedContent?: string,
libraryContentKey?: string, // component key from library if being imported.
}) {
const body = {
type,
boilerplate,
category: category || type,
parent_locator: parentLocator,
display_name: displayName,
staged_content: stagedContent,
library_content_key: libraryContentKey,
};
const { data } = await getAuthenticatedHttpClient()
.post(postXBlockBaseApiUrl(), body);
return data;
}
/**
* Handles the visibility and data of a course unit, such as publishing, resetting to default values,
* and toggling visibility to students.

View File

@@ -8,11 +8,11 @@ import { handleResponseErrors } from '@src/generic/saving-error-alert';
import { RequestStatus } from '@src/data/constants';
import { NOTIFICATION_MESSAGES } from '@src/constants';
import { updateModel, updateModels } from '@src/generic/model-store';
import { createCourseXblock } from '@src/course-outline/data/api';
import { messageTypes } from '../constants';
import {
editUnitDisplayName,
getVerticalData,
createCourseXblock,
getCourseContainerChildren,
handleCourseUnitVisibilityAndData,
deleteUnitItem,