diff --git a/src/course-unit/data/api.js b/src/course-unit/data/api.js
index 7a4697406..58aa28426 100644
--- a/src/course-unit/data/api.js
+++ b/src/course-unit/data/api.js
@@ -3,7 +3,7 @@ import { camelCaseObject, getConfig } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { PUBLISH_TYPES } from '../constants';
-import { normalizeCourseSectionVerticalData, updateXBlockBlockIdToId } from './utils';
+import { isUnitReadOnly, normalizeCourseSectionVerticalData, updateXBlockBlockIdToId } from './utils';
const getStudioBaseUrl = () => getConfig().STUDIO_BASE_URL;
@@ -24,7 +24,9 @@ export async function getCourseUnitData(unitId) {
const { data } = await getAuthenticatedHttpClient()
.get(getCourseUnitApiUrl(unitId));
- return camelCaseObject(data);
+ const result = camelCaseObject(data);
+ result.readOnly = isUnitReadOnly(result);
+ return result;
}
/**
diff --git a/src/course-unit/data/thunk.js b/src/course-unit/data/thunk.js
index ee2c4da65..481b9c6ca 100644
--- a/src/course-unit/data/thunk.js
+++ b/src/course-unit/data/thunk.js
@@ -38,7 +38,7 @@ import {
updateCourseOutlineInfoLoadingStatus,
updateMovedXBlockParams,
} from './slice';
-import { getNotificationMessage, isUnitReadOnly } from './utils';
+import { getNotificationMessage } from './utils';
export function fetchCourseUnitQuery(courseId) {
return async (dispatch) => {
@@ -46,7 +46,6 @@ export function fetchCourseUnitQuery(courseId) {
try {
const courseUnit = await getCourseUnitData(courseId);
- courseUnit.readOnly = isUnitReadOnly(courseUnit);
dispatch(fetchCourseItemSuccess(courseUnit));
dispatch(updateLoadingCourseUnitStatus({ status: RequestStatus.SUCCESSFUL }));
diff --git a/src/library-authoring/components/ContainerCard.tsx b/src/library-authoring/components/ContainerCard.tsx
index 1617c9d1f..a6442b1b5 100644
--- a/src/library-authoring/components/ContainerCard.tsx
+++ b/src/library-authoring/components/ContainerCard.tsx
@@ -208,7 +208,9 @@ const ContainerCard = ({ hit } : ContainerCardProps) => {
if (itemType === 'unit') {
openUnitInfoSidebar(unitId);
setUnitId(unitId);
- navigateTo({ unitId });
+ if (!componentPickerMode) {
+ navigateTo({ unitId });
+ }
}
}, [unitId, itemType, openUnitInfoSidebar, navigateTo]);
diff --git a/src/library-authoring/containers/UnitInfo.test.tsx b/src/library-authoring/containers/UnitInfo.test.tsx
index 677063f85..9b154d13c 100644
--- a/src/library-authoring/containers/UnitInfo.test.tsx
+++ b/src/library-authoring/containers/UnitInfo.test.tsx
@@ -5,7 +5,7 @@ import {
initializeMocks, render as baseRender, screen, waitFor,
fireEvent,
} from '../../testUtils';
-import { mockContentLibrary, mockGetContainerMetadata } from '../data/api.mocks';
+import { mockContentLibrary, mockGetContainerChildren, mockGetContainerMetadata } from '../data/api.mocks';
import { LibraryProvider } from '../common/context/LibraryContext';
import UnitInfo from './UnitInfo';
import { getLibraryContainerApiUrl, getLibraryContainerPublishApiUrl } from '../data/api';
@@ -14,14 +14,16 @@ import { SidebarBodyComponentId, SidebarProvider } from '../common/context/Sideb
mockGetContainerMetadata.applyMock();
mockContentLibrary.applyMock();
mockGetContainerMetadata.applyMock();
+mockGetContainerChildren.applyMock();
const { libraryId } = mockContentLibrary;
const { containerId } = mockGetContainerMetadata;
-const render = () => baseRender(, {
+const render = (showOnlyPublished: boolean = false) => baseRender(, {
extraWrapper: ({ children }) => (
', () => {
});
expect(mockShowToast).toHaveBeenCalledWith('Failed to publish changes');
});
+
+ it('show only published content', async () => {
+ render(true);
+ expect(await screen.findByTestId('unit-info-menu-toggle')).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: /text block published 1/i })).toBeInTheDocument();
+ });
});
diff --git a/src/library-authoring/data/api.mocks.ts b/src/library-authoring/data/api.mocks.ts
index eb5f60188..6be3d681e 100644
--- a/src/library-authoring/data/api.mocks.ts
+++ b/src/library-authoring/data/api.mocks.ts
@@ -188,6 +188,7 @@ mockCreateLibraryBlock.newHtmlData = {
id: 'lb:Axim:TEST:html:123',
blockType: 'html',
displayName: 'New Text Component',
+ publishedDisplayName: null,
hasUnpublishedChanges: true,
lastPublished: null, // or e.g. '2024-08-30T16:37:42Z',
publishedBy: null, // or e.g. 'test_author',
@@ -202,6 +203,7 @@ mockCreateLibraryBlock.newProblemData = {
id: 'lb:Axim:TEST:problem:prob1',
blockType: 'problem',
displayName: 'New Problem',
+ publishedDisplayName: null,
hasUnpublishedChanges: true,
lastPublished: null, // or e.g. '2024-08-30T16:37:42Z',
publishedBy: null, // or e.g. 'test_author',
@@ -216,6 +218,7 @@ mockCreateLibraryBlock.newVideoData = {
id: 'lb:Axim:TEST:video:vid1',
blockType: 'video',
displayName: 'New Video',
+ publishedDisplayName: null,
hasUnpublishedChanges: true,
lastPublished: null, // or e.g. '2024-08-30T16:37:42Z',
publishedBy: null, // or e.g. 'test_author',
@@ -348,6 +351,7 @@ mockLibraryBlockMetadata.dataNeverPublished = {
id: 'lb:Axim:TEST1:html:571fe018-f3ce-45c9-8f53-5dafcb422fd1',
blockType: 'html',
displayName: 'Introduction to Testing 1',
+ publishedDisplayName: null,
lastPublished: null,
publishedBy: null,
lastDraftCreated: null,
@@ -363,6 +367,7 @@ mockLibraryBlockMetadata.dataPublished = {
id: 'lb:Axim:TEST2:html:571fe018-f3ce-45c9-8f53-5dafcb422fd2',
blockType: 'html',
displayName: 'Introduction to Testing 2',
+ publishedDisplayName: 'Introduction to Testing 2',
lastPublished: '2024-06-22T00:00:00',
publishedBy: 'Luke',
lastDraftCreated: null,
@@ -391,6 +396,7 @@ mockLibraryBlockMetadata.dataWithCollections = {
id: 'lb:Axim:TEST:html:571fe018-f3ce-45c9-8f53-5dafcb422fdd',
blockType: 'html',
displayName: 'Introduction to Testing 2',
+ publishedDisplayName: null,
lastPublished: '2024-06-21T00:00:00',
publishedBy: 'Luke',
lastDraftCreated: null,
@@ -407,6 +413,7 @@ mockLibraryBlockMetadata.dataPublishedWithChanges = {
id: 'lb:Axim:TEST2:html:571fe018-f3ce-45c9-8f53-5dafcb422fvv',
blockType: 'html',
displayName: 'Introduction to Testing 2',
+ publishedDisplayName: 'Introduction to Testing 3',
lastPublished: '2024-06-22T00:00:00',
publishedBy: 'Luke',
lastDraftCreated: null,
@@ -536,6 +543,7 @@ export async function mockGetContainerChildren(containerId: string): Promise `${getL
/**
* Get the URL for a single container children api.
*/
-export const getLibraryContainerChildrenApiUrl = (containerId: string) => `${getLibraryContainerApiUrl(containerId)}children/`;
+export const getLibraryContainerChildrenApiUrl = (containerId: string, published: boolean = false) => `${getLibraryContainerApiUrl(containerId)}children/?published=${published}`;
/**
* Get the URL for library container collections.
*/
@@ -250,6 +250,7 @@ export interface LibraryBlockMetadata {
id: string;
blockType: string;
displayName: string;
+ publishedDisplayName: string | null;
lastPublished: string | null;
publishedBy: string | null;
lastDraftCreated: string | null;
@@ -652,8 +653,13 @@ export async function restoreContainer(containerId: string) {
/**
* Fetch a library container's children's metadata.
*/
-export async function getLibraryContainerChildren(containerId: string): Promise {
- const { data } = await getAuthenticatedHttpClient().get(getLibraryContainerChildrenApiUrl(containerId));
+export async function getLibraryContainerChildren(
+ containerId: string,
+ published: boolean = false,
+): Promise {
+ const { data } = await getAuthenticatedHttpClient().get(
+ getLibraryContainerChildrenApiUrl(containerId, published),
+ );
return camelCaseObject(data);
}
diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts
index a74fc5097..01dd97c3e 100644
--- a/src/library-authoring/data/apiHooks.ts
+++ b/src/library-authoring/data/apiHooks.ts
@@ -641,11 +641,11 @@ export const useRestoreContainer = (containerId: string) => {
/**
* Get the metadata and children for a container in a library
*/
-export const useContainerChildren = (containerId?: string) => (
+export const useContainerChildren = (containerId?: string, published: boolean = false) => (
useQuery({
enabled: !!containerId,
queryKey: libraryAuthoringQueryKeys.containerChildren(containerId!),
- queryFn: () => api.getLibraryContainerChildren(containerId!),
+ queryFn: () => api.getLibraryContainerChildren(containerId!, published),
structuralSharing: (oldData: api.LibraryBlockMetadata[], newData: api.LibraryBlockMetadata[]) => {
// This just sets `isNew` flag to new children components
if (oldData) {
diff --git a/src/library-authoring/units/LibraryUnitBlocks.tsx b/src/library-authoring/units/LibraryUnitBlocks.tsx
index f518e976d..4d42bf2a4 100644
--- a/src/library-authoring/units/LibraryUnitBlocks.tsx
+++ b/src/library-authoring/units/LibraryUnitBlocks.tsx
@@ -56,6 +56,7 @@ interface ComponentBlockProps {
/** Component header */
const BlockHeader = ({ block }: ComponentBlockProps) => {
const intl = useIntl();
+ const { showOnlyPublished } = useLibraryContext();
const { showToast } = useContext(ToastContext);
const { navigateTo } = useLibraryRoutes();
const { openComponentInfoSidebar, setSidebarAction } = useSidebarContext();
@@ -101,7 +102,7 @@ const BlockHeader = ({ block }: ComponentBlockProps) => {
@@ -112,7 +113,7 @@ const BlockHeader = ({ block }: ComponentBlockProps) => {
/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
onClick={(e) => e.stopPropagation()}
>
- {block.hasUnpublishedChanges && (
+ {!showOnlyPublished && block.hasUnpublishedChanges && (
{
const [hidePreviewFor, setHidePreviewFor] = useState(null);
const { showToast } = useContext(ToastContext);
- const { unitId, readOnly } = useLibraryContext();
+ const { readOnly, showOnlyPublished } = useLibraryContext();
+ const { sidebarComponentInfo } = useSidebarContext();
+ const unitId = sidebarComponentInfo?.id;
const { openAddContentSidebar } = useSidebarContext();
@@ -247,7 +250,7 @@ export const LibraryUnitBlocks = ({ preview }: LibraryUnitBlocksProps) => {
isLoading,
isError,
error,
- } = useContainerChildren(unitId);
+ } = useContainerChildren(unitId, showOnlyPublished);
const handleReorder = useCallback(() => async (newOrder?: LibraryBlockMetadataWithUniqueId[]) => {
if (!newOrder) {