From e4c83e9f484fbde53e3cf64bd33426c49016f44d Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Wed, 27 Nov 2024 13:44:37 -0500 Subject: [PATCH 1/4] fix: Show published OLX in Library Content Picker --- .../ComponentAdvancedInfo.test.tsx | 21 +++++++++++++++++++ .../component-info/ComponentAdvancedInfo.tsx | 11 ++++++++-- src/library-authoring/data/api.ts | 4 ++-- src/library-authoring/data/apiHooks.ts | 4 ++-- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx index 238be40d39..11eb0e3911 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,6 +127,9 @@ 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); @@ -131,6 +137,21 @@ describe('', () => { // just a substring: const olxPart = /This is a text component which uses/; await waitFor(() => expect(screen.getByText(olxPart)).toBeInTheDocument()); + expect(spy).toHaveBeenCalledWith(usageKey, undefined); + }); + + 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 borken 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..82d655ca18 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' : undefined, + ); 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..75fdbd9862 100644 --- a/src/library-authoring/data/api.ts +++ b/src/library-authoring/data/api.ts @@ -418,8 +418,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?: string): Promise { + const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXApiUrl(usageKey), { params: { version } }); return data.olx; } diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts index 09151a4602..2190208768 100644 --- a/src/library-authoring/data/apiHooks.ts +++ b/src/library-authoring/data/apiHooks.ts @@ -350,10 +350,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?: string) => ( useQuery({ queryKey: xblockQueryKeys.xblockOLX(usageKey), - queryFn: () => getXBlockOLX(usageKey), + queryFn: () => getXBlockOLX(usageKey, version), enabled: !!usageKey, }) ); From 73ed8461ee4ad76faee9f1e106f156ac00ef3bd9 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Thu, 28 Nov 2024 22:05:32 -0500 Subject: [PATCH 2/4] refactor: Use VersionSpecin new code --- .../component-info/ComponentAdvancedInfo.test.tsx | 4 ++-- src/library-authoring/data/api.ts | 3 ++- src/library-authoring/data/apiHooks.ts | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx index 11eb0e3911..b00b86e87c 100644 --- a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx +++ b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx @@ -133,7 +133,7 @@ describe('', () => { 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()); @@ -147,7 +147,7 @@ describe('', () => { render(usageKey, undefined, true); 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()); diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts index 75fdbd9862..ebeb6c6d59 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; @@ -418,7 +419,7 @@ export async function createCollection(libraryId: string, collectionData: Create * Fetch the OLX for the given XBlock. */ // istanbul ignore next -export async function getXBlockOLX(usageKey: string, version?: string): Promise { +export async function getXBlockOLX(usageKey: string, version?: VersionSpec): Promise { const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXApiUrl(usageKey), { params: { version } }); return data.olx; } diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts index 2190208768..8e145ce2b5 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. @@ -350,7 +351,7 @@ export const useCreateLibraryCollection = (libraryId: string) => { }; /** Get the OLX source of a library component */ -export const useXBlockOLX = (usageKey: string, version?: string) => ( +export const useXBlockOLX = (usageKey: string, version?: VersionSpec) => ( useQuery({ queryKey: xblockQueryKeys.xblockOLX(usageKey), queryFn: () => getXBlockOLX(usageKey, version), From dc7c9818fc4c06c268ceedde7e0ad74b68f26065 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 29 Nov 2024 07:32:59 -0500 Subject: [PATCH 3/4] refactor: Use new get xblock view --- .../component-info/ComponentAdvancedInfo.test.tsx | 2 +- .../component-info/ComponentAdvancedInfo.tsx | 2 +- src/library-authoring/data/api.ts | 10 ++++++---- src/library-authoring/data/apiHooks.ts | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx index b00b86e87c..862ccfe339 100644 --- a/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx +++ b/src/library-authoring/component-info/ComponentAdvancedInfo.test.tsx @@ -137,7 +137,7 @@ describe('', () => { // just a substring: const olxPart = /This is a text component which uses/; await waitFor(() => expect(screen.getByText(olxPart)).toBeInTheDocument()); - expect(spy).toHaveBeenCalledWith(usageKey, undefined); + expect(spy).toHaveBeenCalledWith(usageKey, 'draft'); }); it('should display the published OLX source of the block (when expanded)', async () => { diff --git a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx index 82d655ca18..f3396e941f 100644 --- a/src/library-authoring/component-info/ComponentAdvancedInfo.tsx +++ b/src/library-authoring/component-info/ComponentAdvancedInfo.tsx @@ -35,7 +35,7 @@ const ComponentAdvancedInfoInner: React.FC> = () => { const { data: olx, isLoading: isOLXLoading } = useXBlockOLX( usageKey, - showOnlyPublished ? 'published' : undefined, + showOnlyPublished ? 'published' : 'draft', ); const editorRef = React.useRef(undefined); const [isEditingOLX, setEditingOLX] = React.useState(false); diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts index ebeb6c6d59..0d3172179b 100644 --- a/src/library-authoring/data/api.ts +++ b/src/library-authoring/data/api.ts @@ -53,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) => `${getXBlockFieldsVersionApiUrl(usageKey, version)}olx/`; + /** * Get the URL for the xblock Publish API */ @@ -392,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); } @@ -419,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, version?: VersionSpec): Promise { - const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXApiUrl(usageKey), { params: { version } }); +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 8e145ce2b5..549e211b8f 100644 --- a/src/library-authoring/data/apiHooks.ts +++ b/src/library-authoring/data/apiHooks.ts @@ -92,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) */ @@ -294,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), @@ -351,7 +351,7 @@ export const useCreateLibraryCollection = (libraryId: string) => { }; /** Get the OLX source of a library component */ -export const useXBlockOLX = (usageKey: string, version?: VersionSpec) => ( +export const useXBlockOLX = (usageKey: string, version: VersionSpec) => ( useQuery({ queryKey: xblockQueryKeys.xblockOLX(usageKey), queryFn: () => getXBlockOLX(usageKey, version), From 34f8fda111efb17bb5f39b3447dd16c15c4b2602 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Mon, 2 Dec 2024 08:58:41 -0500 Subject: [PATCH 4/4] refactor: Update get olx url with new endpoint --- src/library-authoring/data/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library-authoring/data/api.ts b/src/library-authoring/data/api.ts index 0d3172179b..35615df1c6 100644 --- a/src/library-authoring/data/api.ts +++ b/src/library-authoring/data/api.ts @@ -59,7 +59,7 @@ export const getXBlockFieldsVersionApiUrl = (usageKey: string, version: VersionS * Get the URL for the xblock OLX API */ export const getXBlockOLXApiUrl = (usageKey: string) => `${getLibraryBlockMetadataUrl(usageKey)}olx/`; -export const getXBlockOLXVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getXBlockFieldsVersionApiUrl(usageKey, version)}olx/`; +export const getXBlockOLXVersionApiUrl = (usageKey: string, version: VersionSpec) => `${getApiBaseUrl()}/api/xblock/v2/xblocks/${usageKey}@${version}/olx/`; /** * Get the URL for the xblock Publish API