diff --git a/src/library-authoring/common/context.tsx b/src/library-authoring/common/context.tsx
index fcc45d00e..8b3b2a5ab 100644
--- a/src/library-authoring/common/context.tsx
+++ b/src/library-authoring/common/context.tsx
@@ -26,6 +26,7 @@ export interface LibraryContextData {
setCollectionId: (collectionId?: string) => void;
// Whether we're in "component picker" mode
componentPickerMode: boolean;
+ parentLocator?: string;
// Sidebar stuff - only one sidebar is active at any given time:
sidebarBodyComponent: SidebarBodyComponentId | null;
closeLibrarySidebar: () => void;
@@ -62,6 +63,7 @@ interface LibraryProviderProps {
libraryId: string;
collectionId?: string;
componentPickerMode?: boolean;
+ parentLocator?: string;
sidebarCollectionId?: string;
sidebarComponentUsageKey?: string;
}
@@ -74,6 +76,7 @@ export const LibraryProvider = ({
libraryId,
collectionId: collectionIdProp,
componentPickerMode = false,
+ parentLocator,
sidebarCollectionId: sideBarCollectionIdProp,
sidebarComponentUsageKey: sidebarComponentUsageKeyProp,
}: LibraryProviderProps) => {
@@ -131,6 +134,7 @@ export const LibraryProvider = ({
readOnly,
isLoadingLibraryData,
componentPickerMode,
+ parentLocator,
sidebarBodyComponent,
closeLibrarySidebar,
openAddContentSidebar,
diff --git a/src/library-authoring/component-picker/ComponentPicker.tsx b/src/library-authoring/component-picker/ComponentPicker.tsx
index 909d30e44..3ab849710 100644
--- a/src/library-authoring/component-picker/ComponentPicker.tsx
+++ b/src/library-authoring/component-picker/ComponentPicker.tsx
@@ -1,6 +1,7 @@
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button, Stepper } from '@openedx/paragon';
import { useState } from 'react';
+import { useSearchParams } from 'react-router-dom';
import { LibraryProvider, useLibraryContext } from '../common/context';
import LibraryAuthoringPage from '../LibraryAuthoringPage';
@@ -9,9 +10,7 @@ import SelectLibrary from './SelectLibrary';
import messages from './messages';
const InnerComponentPicker = () => {
- const {
- collectionId,
- } = useLibraryContext();
+ const { collectionId } = useLibraryContext();
if (collectionId) {
return ;
@@ -22,6 +21,15 @@ const InnerComponentPicker = () => {
// eslint-disable-next-line import/prefer-default-export
export const ComponentPicker = () => {
const intl = useIntl();
+ const [searchParams] = useSearchParams();
+ let parentLocator = searchParams.get('parentLocator');
+
+ // istanbul ignore if: this should never happen
+ if (!parentLocator) {
+ throw new Error('parentLocator is required');
+ }
+
+ parentLocator = parentLocator.replaceAll(' ', '+');
const [currentStep, setCurrentStep] = useState('select-library');
const [selectedLibrary, setSelectedLibrary] = useState('');
@@ -35,7 +43,7 @@ export const ComponentPicker = () => {
-
+
diff --git a/src/library-authoring/components/ComponentCard.tsx b/src/library-authoring/components/ComponentCard.tsx
index 44e0e5922..619af4dd0 100644
--- a/src/library-authoring/components/ComponentCard.tsx
+++ b/src/library-authoring/components/ComponentCard.tsx
@@ -1,4 +1,4 @@
-import { useContext, useState } from 'react';
+import { useContext, useEffect, useState } from 'react';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow,
@@ -71,6 +71,7 @@ const ComponentCard = ({ contentHit }: ComponentCardProps) => {
const {
openComponentInfoSidebar,
componentPickerMode,
+ parentLocator,
} = useLibraryContext();
const { showToast } = useContext(ToastContext);
@@ -91,15 +92,19 @@ const ComponentCard = ({ contentHit }: ComponentCardProps) => {
mutate: addComponentToCourse,
isSuccess: addComponentToCourseSuccess,
isError: addComponentToCourseError,
- } = useAddComponentToCourse();
+ reset,
+ } = useAddComponentToCourse(parentLocator, contentHit.usageKey);
if (addComponentToCourseSuccess) {
window.parent.postMessage('closeComponentPicker', '*');
}
- if (addComponentToCourseError) {
- showToast(intl.formatMessage(messages.addComponentToCourseError));
- }
+ useEffect(() => {
+ if (addComponentToCourseError) {
+ showToast(intl.formatMessage(messages.addComponentToCourseError));
+ reset();
+ }
+ }, [addComponentToCourseError, showToast, intl]);
const handleAddComponentToCourse = () => {
addComponentToCourse();
diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts
index d565881c7..b8b2954f9 100644
--- a/src/library-authoring/data/api.ts
+++ b/src/library-authoring/data/api.ts
@@ -61,6 +61,10 @@ export const getLibraryCollectionComponentApiUrl = (libraryId: string, collectio
* Get the API URL for restoring deleted collection.
*/
export const getLibraryCollectionRestoreApiUrl = (libraryId: string, collectionId: string) => `${getLibraryCollectionApiUrl(libraryId, collectionId)}restore/`;
+/**
+ * Get the URL for the xblock api.
+ */
+export const getXBlockBaseApiUrl = () => `${getApiBaseUrl()}/xblock/`;
export interface ContentLibrary {
id: string;
@@ -383,7 +387,10 @@ export async function restoreCollection(libraryId: string, collectionId: string)
* Add a component to a course.
*/
// istanbul ignore next
-export async function addComponentToCourse() {
- // TODO: Call endpoint to add component to course
- return Promise.resolve();
+export async function addComponentToCourse(parentLocator: string, componentUsageKey: string) {
+ const client = getAuthenticatedHttpClient();
+ await client.post(getXBlockBaseApiUrl(), {
+ parent_locator: parentLocator,
+ library_content_key: componentUsageKey,
+ });
}
diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts
index 082bc4f6f..7a79a318f 100644
--- a/src/library-authoring/data/apiHooks.ts
+++ b/src/library-authoring/data/apiHooks.ts
@@ -377,8 +377,14 @@ export const useRestoreCollection = (libraryId: string, collectionId: string) =>
/**
* Use this mutation to add a component to a course
*/
-export const useAddComponentToCourse = () => (
+export const useAddComponentToCourse = (parentLocator: string | undefined, componentUsageKey: string) => (
useMutation({
- mutationFn: addComponentToCourse,
+ mutationFn: () => {
+ // istanbul ignore if: this should never happen
+ if (!parentLocator) {
+ throw new Error('parentLocator is required');
+ }
+ return addComponentToCourse(parentLocator, componentUsageKey);
+ },
})
);