Skip to content

Commit f9efda9

Browse files
committed
feat: add container collections support
1 parent 04faf54 commit f9efda9

31 files changed

Lines changed: 496 additions & 245 deletions

src/course-unit/add-component/AddComponent.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ const AddComponent = ({
195195
>
196196
<ComponentPicker
197197
showOnlyPublished
198+
extraFilter={['NOT block_type = "unit"']}
198199
componentPickerMode={isAddLibraryContentModalOpen ? 'single' : 'multiple'}
199200
onComponentSelected={handleLibraryV2Selection}
200201
onChangeComponentSelection={setSelectedComponents}

src/index.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,14 @@ const App = () => {
6666
<Route path="/libraries-v1" element={<StudioHome />} />
6767
<Route path="/library/create" element={<CreateLibrary />} />
6868
<Route path="/library/:libraryId/*" element={<LibraryLayout />} />
69-
<Route path="/component-picker" element={<ComponentPicker />} />
70-
<Route path="/component-picker/multiple" element={<ComponentPicker componentPickerMode="multiple" />} />
69+
<Route
70+
path="/component-picker"
71+
element={<ComponentPicker extraFilter={['NOT block_type = "unit"']} />}
72+
/>
73+
<Route
74+
path="/component-picker/multiple"
75+
element={<ComponentPicker componentPickerMode="multiple" extraFilter={['NOT block_type = "unit"']} />}
76+
/>
7177
<Route path="/legacy/preview-changes/:usageKey" element={<PreviewChangesEmbed />} />
7278
<Route path="/course/:courseId/*" element={<CourseAuthoringRoutes />} />
7379
<Route path="/course_rerun/:courseId" element={<CourseRerun />} />

src/library-authoring/LibraryAuthoringPage.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
141141
libraryData,
142142
isLoadingLibraryData,
143143
showOnlyPublished,
144+
extraFilter: contextExtraFilter,
144145
componentId,
145146
collectionId,
146147
unitId,
@@ -223,6 +224,10 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
223224
extraFilter.push('last_published IS NOT NULL');
224225
}
225226

227+
if (contextExtraFilter) {
228+
extraFilter.push(...contextExtraFilter);
229+
}
230+
226231
const activeTypeFilters = {
227232
components: 'type = "library_block"',
228233
collections: 'type = "collection"',

src/library-authoring/add-content/AddContentContainer.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
mockXBlockFields,
1313
} from '../data/api.mocks';
1414
import {
15-
getContentLibraryApiUrl, getCreateLibraryBlockUrl, getLibraryCollectionComponentApiUrl, getLibraryPasteClipboardUrl,
15+
getContentLibraryApiUrl, getCreateLibraryBlockUrl, getLibraryCollectionItemsApiUrl, getLibraryPasteClipboardUrl,
1616
getXBlockFieldsApiUrl,
1717
} from '../data/api';
1818
import { mockBroadcastChannel, mockClipboardEmpty, mockClipboardHtml } from '../../generic/data/api.mock';
@@ -137,7 +137,7 @@ describe('<AddContentContainer />', () => {
137137
const url = getCreateLibraryBlockUrl(libraryId);
138138
const usageKey = mockXBlockFields.usageKeyNewHtml;
139139
const updateBlockUrl = getXBlockFieldsApiUrl(usageKey);
140-
const collectionComponentUrl = getLibraryCollectionComponentApiUrl(
140+
const collectionComponentUrl = getLibraryCollectionItemsApiUrl(
141141
libraryId,
142142
collectionId,
143143
);
@@ -195,7 +195,7 @@ describe('<AddContentContainer />', () => {
195195

196196
const pasteUrl = getLibraryPasteClipboardUrl(libraryId);
197197
const collectionId = 'some-collection-id';
198-
const collectionComponentUrl = getLibraryCollectionComponentApiUrl(
198+
const collectionComponentUrl = getLibraryCollectionItemsApiUrl(
199199
libraryId,
200200
collectionId,
201201
);
@@ -220,7 +220,7 @@ describe('<AddContentContainer />', () => {
220220

221221
const pasteUrl = getLibraryPasteClipboardUrl(libraryId);
222222
const collectionId = 'some-collection-id';
223-
const collectionComponentUrl = getLibraryCollectionComponentApiUrl(
223+
const collectionComponentUrl = getLibraryCollectionItemsApiUrl(
224224
libraryId,
225225
collectionId,
226226
);

src/library-authoring/add-content/AddContentContainer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { getCanEdit } from '../../course-unit/data/selectors';
2121
import {
2222
useCreateLibraryBlock,
2323
useLibraryPasteClipboard,
24-
useAddComponentsToCollection,
24+
useAddItemsToCollection,
2525
useBlockTypesMetadata,
2626
} from '../data/apiHooks';
2727
import { useLibraryContext } from '../common/context/LibraryContext';
@@ -195,7 +195,7 @@ const AddContentContainer = () => {
195195
openCreateUnitModal,
196196
openComponentEditor,
197197
} = useLibraryContext();
198-
const updateComponentsMutation = useAddComponentsToCollection(libraryId, collectionId);
198+
const updateItemsMutation = useAddItemsToCollection(libraryId, collectionId);
199199
const createBlockMutation = useCreateLibraryBlock();
200200
const pasteClipboardMutation = useLibraryPasteClipboard();
201201
const { showToast } = useContext(ToastContext);
@@ -273,8 +273,8 @@ const AddContentContainer = () => {
273273
contentTypes.push(pasteButton);
274274
}
275275

276-
const linkComponent = (usageKey: string) => {
277-
updateComponentsMutation.mutateAsync([usageKey]).catch(() => {
276+
const linkComponent = (opaque_key: string) => {
277+
updateItemsMutation.mutateAsync([opaque_key]).catch(() => {
278278
showToast(intl.formatMessage(messages.errorAssociateComponentMessage));
279279
});
280280
};

src/library-authoring/add-content/PickLibraryContentModal.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ describe('<PickLibraryContentModal />', () => {
4949
});
5050

5151
it('can pick components from the modal', async () => {
52-
const mockAddComponentsToCollection = jest.fn();
53-
jest.spyOn(api, 'addComponentsToCollection').mockImplementation(mockAddComponentsToCollection);
52+
const mockAddItemsToCollection = jest.fn();
53+
jest.spyOn(api, 'addItemsToCollection').mockImplementation(mockAddItemsToCollection);
5454

5555
render();
5656

@@ -67,7 +67,7 @@ describe('<PickLibraryContentModal />', () => {
6767
fireEvent.click(screen.queryAllByRole('button', { name: 'Add to Collection' })[0]);
6868

6969
await waitFor(() => {
70-
expect(mockAddComponentsToCollection).toHaveBeenCalledWith(
70+
expect(mockAddItemsToCollection).toHaveBeenCalledWith(
7171
libraryId,
7272
'collectionId',
7373
['lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd'],
@@ -78,8 +78,8 @@ describe('<PickLibraryContentModal />', () => {
7878
});
7979

8080
it('show error when api call fails', async () => {
81-
const mockAddComponentsToCollection = jest.fn().mockRejectedValue(new Error('Failed to add components'));
82-
jest.spyOn(api, 'addComponentsToCollection').mockImplementation(mockAddComponentsToCollection);
81+
const mockAddItemsToCollection = jest.fn().mockRejectedValue(new Error('Failed to add components'));
82+
jest.spyOn(api, 'addItemsToCollection').mockImplementation(mockAddItemsToCollection);
8383
render();
8484

8585
// Wait for the content library to load
@@ -95,7 +95,7 @@ describe('<PickLibraryContentModal />', () => {
9595
fireEvent.click(screen.queryAllByRole('button', { name: 'Add to Collection' })[0]);
9696

9797
await waitFor(() => {
98-
expect(mockAddComponentsToCollection).toHaveBeenCalledWith(
98+
expect(mockAddItemsToCollection).toHaveBeenCalledWith(
9999
libraryId,
100100
'collectionId',
101101
['lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd'],

src/library-authoring/add-content/PickLibraryContentModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ActionRow, Button, StandardModal } from '@openedx/paragon';
55
import { ToastContext } from '../../generic/toast-context';
66
import { useLibraryContext } from '../common/context/LibraryContext';
77
import type { SelectedComponent } from '../common/context/ComponentPickerContext';
8-
import { useAddComponentsToCollection } from '../data/apiHooks';
8+
import { useAddItemsToCollection } from '../data/apiHooks';
99
import messages from './messages';
1010

1111
interface PickLibraryContentModalFooterProps {
@@ -51,7 +51,7 @@ export const PickLibraryContentModal: React.FC<PickLibraryContentModalProps> = (
5151
throw new Error('libraryId and componentPicker are required');
5252
}
5353

54-
const updateComponentsMutation = useAddComponentsToCollection(libraryId, collectionId);
54+
const updateComponentsMutation = useAddItemsToCollection(libraryId, collectionId);
5555

5656
const { showToast } = useContext(ToastContext);
5757

src/library-authoring/collections/LibraryCollectionPage.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { mockContentSearchConfig, mockGetBlockTypes } from '../../search-manager
2020
import { mockBroadcastChannel, mockClipboardEmpty } from '../../generic/data/api.mock';
2121
import { LibraryLayout } from '..';
2222
import { ContentTagsDrawer } from '../../content-tags-drawer';
23-
import { getLibraryCollectionComponentApiUrl } from '../data/api';
23+
import { getLibraryCollectionItemsApiUrl } from '../data/api';
2424

2525
let axiosMock: MockAdapter;
2626
let mockShowToast;
@@ -351,7 +351,7 @@ describe('<LibraryCollectionPage />', () => {
351351
});
352352

353353
it('should remove component from collection and hides sidebar', async () => {
354-
const url = getLibraryCollectionComponentApiUrl(
354+
const url = getLibraryCollectionItemsApiUrl(
355355
mockContentLibrary.libraryId,
356356
mockCollection.collectionId,
357357
);

src/library-authoring/collections/LibraryCollectionPage.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ const LibraryCollectionPage = () => {
109109
}
110110

111111
const { componentPickerMode } = useComponentPickerContext();
112-
const { showOnlyPublished, setCollectionId, componentId } = useLibraryContext();
112+
const {
113+
showOnlyPublished, extraFilter: contextExtraFilter, setCollectionId, componentId,
114+
} = useLibraryContext();
113115
const { sidebarComponentInfo, openInfoSidebar } = useSidebarContext();
114116

115117
const {
@@ -182,6 +184,10 @@ const LibraryCollectionPage = () => {
182184
extraFilter.push('last_published IS NOT NULL');
183185
}
184186

187+
if (contextExtraFilter) {
188+
extraFilter.push(...contextExtraFilter);
189+
}
190+
185191
return (
186192
<div className="d-flex">
187193
<div className="flex-grow-1">

src/library-authoring/common/context/ComponentPickerContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88

99
export interface SelectedComponent {
1010
usageKey: string;
11-
blockType: string;
11+
blockType?: string;
1212
}
1313

1414
export type ComponentSelectedEvent = (selectedComponent: SelectedComponent) => void;

0 commit comments

Comments
 (0)