From a0f6f4357efec543031692a6b18e49d3d4f74f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ch=C3=A1vez?= Date: Thu, 5 Dec 2024 14:13:04 -0500 Subject: [PATCH] fix: Show published OLX in Library Content Picker [FC-0062] (#1534) --- .../ComponentAdvancedInfo.test.tsx | 23 ++++++++++++++++++- .../component-info/ComponentAdvancedInfo.tsx | 11 +++++++-- src/library-authoring/data/api.ts | 11 +++++---- src/library-authoring/data/apiHooks.ts | 9 ++++---- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx index 238be40d39..862ccfe339 100644 --- a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx +++ b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx @@ -12,6 +12,7 @@ import { mockXBlockAssets, mockXBlockOLX, } from '../data/api.mocks'; +import * as apiHooks from '../data/apiHooks'; import { LibraryProvider, SidebarBodyComponentId } from '../common/context'; import { ComponentAdvancedInfo } from './ComponentAdvancedInfo'; import { getXBlockAssetsApiUrl } from '../data/api'; @@ -25,6 +26,7 @@ const setOLXspy = mockSetXBlockOLX.applyMock(); const render = ( usageKey: string = mockLibraryBlockMetadata.usageKeyPublished, libraryId: string = mockContentLibrary.libraryId, + showOnlyPublished: boolean = false, ) => baseRender( , { @@ -35,6 +37,7 @@ const render = ( id: usageKey, type: SidebarBodyComponentId.ComponentInfo, }} + showOnlyPublished={showOnlyPublished} > {children} @@ -124,13 +127,31 @@ describe('', () => { }); it('should display the OLX source of the block (when expanded)', async () => { + const usageKey = mockXBlockOLX.usageKeyHtml; + const spy = jest.spyOn(apiHooks, 'useXBlockOLX'); + render(mockXBlockOLX.usageKeyHtml); const expandButton = await screen.findByRole('button', { name: /Advanced details/ }); fireEvent.click(expandButton); - // Because of syntax highlighting, the OLX will be borken up by many different tags so we need to search for + // Because of syntax highlighting, the OLX will be broken up by many different tags so we need to search for + // just a substring: + const olxPart = /This is a text component which uses/; + await waitFor(() => expect(screen.getByText(olxPart)).toBeInTheDocument()); + expect(spy).toHaveBeenCalledWith(usageKey, 'draft'); + }); + + it('should display the published OLX source of the block (when expanded)', async () => { + const usageKey = mockXBlockOLX.usageKeyHtml; + const spy = jest.spyOn(apiHooks, 'useXBlockOLX'); + + render(usageKey, undefined, true); + const expandButton = await screen.findByRole('button', { name: /Advanced details/ }); + fireEvent.click(expandButton); + // Because of syntax highlighting, the OLX will be broken up by many different tags so we need to search for // just a substring: const olxPart = /This is a text component which uses/; await waitFor(() => expect(screen.getByText(olxPart)).toBeInTheDocument()); + expect(spy).toHaveBeenCalledWith(usageKey, 'published'); }); it('does not display "Edit OLX" button and assets dropzone when the library is read-only', async () => { diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx index a558ef6902..f3396e941f 100644 --- a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx +++ b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx @@ -21,7 +21,11 @@ import { ComponentAdvancedAssets } from './ComponentAdvancedAssets'; const ComponentAdvancedInfoInner: React.FC> = () => { const intl = useIntl(); - const { readOnly, sidebarComponentInfo } = useLibraryContext(); + const { + readOnly, + sidebarComponentInfo, + showOnlyPublished, + } = useLibraryContext(); const usageKey = sidebarComponentInfo?.id; // istanbul ignore if: this should never happen in production @@ -29,7 +33,10 @@ const ComponentAdvancedInfoInner: React.FC> = () => { throw new Error('sidebarComponentUsageKey is required to render ComponentAdvancedInfo'); } - const { data: olx, isLoading: isOLXLoading } = useXBlockOLX(usageKey); + const { data: olx, isLoading: isOLXLoading } = useXBlockOLX( + usageKey, + showOnlyPublished ? 'published' : 'draft', + ); const editorRef = React.useRef(undefined); const [isEditingOLX, setEditingOLX] = React.useState(false); const olxUpdater = useUpdateXBlockOLX(usageKey); diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts index 2efdf9175b..35615df1c6 100644 --- a/src/library-authoring/data/api.ts +++ b/src/library-authoring/data/api.ts @@ -1,5 +1,6 @@ import { camelCaseObject, getConfig, snakeCaseObject } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; +import { VersionSpec } from '../LibraryBlock'; const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL; @@ -52,12 +53,14 @@ export const getLibraryPasteClipboardUrl = (libraryId: string) => `${getApiBaseU * Get the URL for the xblock fields/metadata API. */ export const getXBlockFieldsApiUrl = (usageKey: string) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}/fields/`; -export const getXBlockFieldsVersionApiUrl = (usageKey: string, version: string) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/fields/`; +export const getXBlockFieldsVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/fields/`; /** * Get the URL for the xblock OLX API */ export const getXBlockOLXApiUrl = (usageKey: string) => `${getLibraryBlockMetadataUrl(usageKey)}olx/`; +export const getXBlockOLXVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/olx/`; + /** * Get the URL for the xblock Publish API */ @@ -391,7 +394,7 @@ export async function getLibraryBlockMetadata(usageKey: string): Promise { +export async function getXBlockFields(usageKey: string, version: VersionSpec = 'draft'): Promise { const { data } = await getAuthenticatedHttpClient().get(getXBlockFieldsVersionApiUrl(usageKey, version)); return camelCaseObject(data); } @@ -418,8 +421,8 @@ export async function createCollection(libraryId: string, collectionData: Create * Fetch the OLX for the given XBlock. */ // istanbul ignore next -export async function getXBlockOLX(usageKey: string): Promise { - const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXApiUrl(usageKey)); +export async function getXBlockOLX(usageKey: string, version: VersionSpec = 'draft'): Promise { + const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXVersionApiUrl(usageKey, version)); return data.olx; } diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts index 09151a4602..549e211b8f 100644 --- a/src/library-authoring/data/apiHooks.ts +++ b/src/library-authoring/data/apiHooks.ts @@ -45,6 +45,7 @@ import { publishXBlock, deleteXBlockAsset, } from './api'; +import { VersionSpec } from '../LibraryBlock'; export const libraryQueryPredicate = (query: Query, libraryId: string): boolean => { // Invalidate all content queries related to this library. @@ -91,7 +92,7 @@ export const xblockQueryKeys = { */ xblock: (usageKey?: string) => [...xblockQueryKeys.all, usageKey], /** Fields (i.e. the content, display name, etc.) of an XBlock */ - xblockFields: (usageKey: string, version: string = 'draft') => [...xblockQueryKeys.xblock(usageKey), 'fields', version], + xblockFields: (usageKey: string, version: VersionSpec = 'draft') => [...xblockQueryKeys.xblock(usageKey), 'fields', version], /** OLX (XML representation of the fields/content) */ xblockOLX: (usageKey: string) => [...xblockQueryKeys.xblock(usageKey), 'OLX'], /** assets (static files) */ @@ -293,7 +294,7 @@ export const useLibraryBlockMetadata = (usageId: string | undefined) => ( }) ); -export const useXBlockFields = (usageKey: string, version: string = 'draft') => ( +export const useXBlockFields = (usageKey: string, version: VersionSpec = 'draft') => ( useQuery({ queryKey: xblockQueryKeys.xblockFields(usageKey, version), queryFn: () => getXBlockFields(usageKey, version), @@ -350,10 +351,10 @@ export const useCreateLibraryCollection = (libraryId: string) => { }; /** Get the OLX source of a library component */ -export const useXBlockOLX = (usageKey: string) => ( +export const useXBlockOLX = (usageKey: string, version: VersionSpec) => ( useQuery({ queryKey: xblockQueryKeys.xblockOLX(usageKey), - queryFn: () => getXBlockOLX(usageKey), + queryFn: () => getXBlockOLX(usageKey, version), enabled: !!usageKey, }) );