{title}
{showReadOnlyBadge && (
diff --git a/src/library-authoring/__mocks__/library-search.json b/src/library-authoring/__mocks__/library-search.json
index 9eee97031..ba27af218 100644
--- a/src/library-authoring/__mocks__/library-search.json
+++ b/src/library-authoring/__mocks__/library-search.json
@@ -494,7 +494,7 @@
],
"created": 1742221203.895054,
"modified": 1742221203.895054,
- "usage_key": "lct:Axim:TEST:unit:test-unit-9284e2",
+ "usage_key": "lct:org:lib:unit:test-unit-9a207",
"block_type": "unit",
"context_key": "lib:Axim:TEST",
"org": "Axim",
@@ -512,12 +512,18 @@
],
"created": "1742221203.895054",
"modified": "1742221203.895054",
- "usage_key": "lct:Axim:TEST:unit:test-unit-9284e2",
+ "usage_key": "lct:org:lib:unit:test-unit-9a207",
"block_type": "unit",
"context_key": "lib:Axim:TEST",
"org": "Axim",
"access_id": "15",
- "num_children": "0"
+ "num_children": "0",
+ "published": {
+ "display_name": "Published Test Unit"
+ }
+ },
+ "published": {
+ "display_name": "Published Test Unit"
}
}
],
diff --git a/src/library-authoring/component-picker/ComponentPicker.test.tsx b/src/library-authoring/component-picker/ComponentPicker.test.tsx
index 2d492adf6..cd7f497a3 100644
--- a/src/library-authoring/component-picker/ComponentPicker.test.tsx
+++ b/src/library-authoring/component-picker/ComponentPicker.test.tsx
@@ -14,6 +14,7 @@ import {
mockGetCollectionMetadata,
mockGetContentLibraryV2List,
mockLibraryBlockMetadata,
+ mockGetContainerMetadata,
} from '../data/api.mocks';
import { ComponentPicker } from './ComponentPicker';
@@ -40,6 +41,7 @@ mockContentSearchConfig.applyMock();
mockGetCollectionMetadata.applyMock();
mockGetContentLibraryV2List.applyMock();
mockLibraryBlockMetadata.applyMock();
+mockGetContainerMetadata.applyMock();
let postMessageSpy: jest.SpyInstance;
@@ -99,6 +101,24 @@ describe('', () => {
}, '*');
});
+ it('should open the unit sidebar', async () => {
+ render();
+
+ expect(await screen.findByText('Test Library 1')).toBeInTheDocument();
+ fireEvent.click(screen.getByDisplayValue(/lib:sampletaxonomyorg1:tl1/i));
+
+ // Wait for the content library to load
+ await screen.findByText(/Change Library/i);
+ expect(await screen.findByText('Test Library 1')).toBeInTheDocument();
+
+ // Click on the unit card to open the sidebar
+ fireEvent.click((await screen.findByText('Published Test Unit')));
+
+ const sidebar = await screen.findByTestId('library-sidebar');
+ expect(sidebar).toBeInTheDocument();
+ await waitFor(() => expect(within(sidebar).getByText('Published Test Unit')).toBeInTheDocument());
+ });
+
it('should pick component inside a collection using the card', async () => {
render();
diff --git a/src/library-authoring/containers/ContainerEditableTitle.tsx b/src/library-authoring/containers/ContainerEditableTitle.tsx
new file mode 100644
index 000000000..5a1ea0f6d
--- /dev/null
+++ b/src/library-authoring/containers/ContainerEditableTitle.tsx
@@ -0,0 +1,48 @@
+import { useIntl } from '@edx/frontend-platform/i18n';
+import { useContext } from 'react';
+import { InplaceTextEditor } from '../../generic/inplace-text-editor';
+import { ToastContext } from '../../generic/toast-context';
+import { useLibraryContext } from '../common/context/LibraryContext';
+import { useContainer, useUpdateContainer } from '../data/apiHooks';
+import messages from './messages';
+
+interface EditableTitleProps {
+ containerId: string;
+ textClassName?: string;
+}
+
+export const ContainerEditableTitle = ({ containerId, textClassName }: EditableTitleProps) => {
+ const intl = useIntl();
+
+ const { readOnly, showOnlyPublished } = useLibraryContext();
+
+ const { data: container } = useContainer(containerId);
+
+ const updateMutation = useUpdateContainer(containerId);
+ const { showToast } = useContext(ToastContext);
+
+ const handleSaveDisplayName = async (newDisplayName: string) => {
+ try {
+ await updateMutation.mutateAsync({
+ displayName: newDisplayName,
+ });
+ showToast(intl.formatMessage(messages.updateContainerSuccessMsg));
+ } catch (err) {
+ showToast(intl.formatMessage(messages.updateContainerErrorMsg));
+ }
+ };
+
+ // istanbul ignore if: this should never happen
+ if (!container) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/src/library-authoring/containers/ContainerInfoHeader.tsx b/src/library-authoring/containers/ContainerInfoHeader.tsx
index 65357c0f1..c47a4ee6b 100644
--- a/src/library-authoring/containers/ContainerInfoHeader.tsx
+++ b/src/library-authoring/containers/ContainerInfoHeader.tsx
@@ -1,17 +1,7 @@
-import { useContext } from 'react';
-import { useIntl } from '@edx/frontend-platform/i18n';
-
-import { InplaceTextEditor } from '../../generic/inplace-text-editor';
-import { ToastContext } from '../../generic/toast-context';
-import { useLibraryContext } from '../common/context/LibraryContext';
import { useSidebarContext } from '../common/context/SidebarContext';
-import { useContainer, useUpdateContainer } from '../data/apiHooks';
-import messages from './messages';
+import { ContainerEditableTitle } from './ContainerEditableTitle';
const ContainerInfoHeader = () => {
- const intl = useIntl();
-
- const { readOnly } = useLibraryContext();
const { sidebarComponentInfo } = useSidebarContext();
const containerId = sidebarComponentInfo?.id;
@@ -20,32 +10,9 @@ const ContainerInfoHeader = () => {
throw new Error('containerId is required');
}
- const { data: container } = useContainer(containerId);
-
- const updateMutation = useUpdateContainer(containerId);
- const { showToast } = useContext(ToastContext);
-
- const handleSaveDisplayName = async (newDisplayName: string) => {
- try {
- await updateMutation.mutateAsync({
- displayName: newDisplayName,
- });
- showToast(intl.formatMessage(messages.updateContainerSuccessMsg));
- } catch (err) {
- showToast(intl.formatMessage(messages.updateContainerErrorMsg));
- throw err;
- }
- };
-
- if (!container) {
- return null;
- }
-
return (
-
);
diff --git a/src/library-authoring/data/api.mocks.ts b/src/library-authoring/data/api.mocks.ts
index 3ff35e624..92220b140 100644
--- a/src/library-authoring/data/api.mocks.ts
+++ b/src/library-authoring/data/api.mocks.ts
@@ -495,6 +495,7 @@ mockGetContainerMetadata.containerData = {
id: 'lct:org:lib:unit:test-unit-9a2072',
containerType: 'unit',
displayName: 'Test Unit',
+ publishedDisplayName: 'Published Test Unit',
created: '2024-09-19T10:00:00Z',
createdBy: 'test_author',
lastPublished: '2024-09-20T10:00:00Z',
diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts
index 92f5d3f40..dd8a8f743 100644
--- a/src/library-authoring/data/api.ts
+++ b/src/library-authoring/data/api.ts
@@ -600,6 +600,7 @@ export interface Container {
id: string;
containerType: 'unit';
displayName: string;
+ publishedDisplayName: string;
lastPublished: string | null;
publishedBy: string | null;
createdBy: string | null;
diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts
index 65b9445ad..3fd1f0633 100644
--- a/src/library-authoring/data/apiHooks.ts
+++ b/src/library-authoring/data/apiHooks.ts
@@ -615,7 +615,7 @@ export const useUpdateContainer = (containerId: string) => {
return useMutation({
mutationFn: (data: api.UpdateContainerDataRequest) => api.updateContainerMetadata(containerId, data),
onMutate: (data) => {
- const previousData = queryClient.getQueryData(containerQueryKey) as api.CollectionMetadata;
+ const previousData = queryClient.getQueryData(containerQueryKey) as api.Container;
queryClient.setQueryData(containerQueryKey, {
...previousData,
...data,