Skip to content

Commit

Permalink
fix: Show published OLX in Library Content Picker [FC-0062] (#1534)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisChV authored Dec 5, 2024
1 parent e75ce15 commit a0f6f43
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -25,6 +26,7 @@ const setOLXspy = mockSetXBlockOLX.applyMock();
const render = (
usageKey: string = mockLibraryBlockMetadata.usageKeyPublished,
libraryId: string = mockContentLibrary.libraryId,
showOnlyPublished: boolean = false,
) => baseRender(
<ComponentAdvancedInfo />,
{
Expand All @@ -35,6 +37,7 @@ const render = (
id: usageKey,
type: SidebarBodyComponentId.ComponentInfo,
}}
showOnlyPublished={showOnlyPublished}
>
{children}
</LibraryProvider>
Expand Down Expand Up @@ -124,13 +127,31 @@ describe('<ComponentAdvancedInfo />', () => {
});

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 () => {
Expand Down
11 changes: 9 additions & 2 deletions src/library-authoring/component-info/ComponentAdvancedInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,22 @@ import { ComponentAdvancedAssets } from './ComponentAdvancedAssets';

const ComponentAdvancedInfoInner: React.FC<Record<never, never>> = () => {
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
if (!usageKey) {
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<EditorAccessor | undefined>(undefined);
const [isEditingOLX, setEditingOLX] = React.useState(false);
const olxUpdater = useUpdateXBlockOLX(usageKey);
Expand Down
11 changes: 7 additions & 4 deletions src/library-authoring/data/api.ts
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -391,7 +394,7 @@ export async function getLibraryBlockMetadata(usageKey: string): Promise<Library
/**
* Fetch xblock fields.
*/
export async function getXBlockFields(usageKey: string, version: string = 'draft'): Promise<XBlockFields> {
export async function getXBlockFields(usageKey: string, version: VersionSpec = 'draft'): Promise<XBlockFields> {
const { data } = await getAuthenticatedHttpClient().get(getXBlockFieldsVersionApiUrl(usageKey, version));
return camelCaseObject(data);
}
Expand All @@ -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<string> {
const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXApiUrl(usageKey));
export async function getXBlockOLX(usageKey: string, version: VersionSpec = 'draft'): Promise<string> {
const { data } = await getAuthenticatedHttpClient().get(getXBlockOLXVersionApiUrl(usageKey, version));
return data.olx;
}

Expand Down
9 changes: 5 additions & 4 deletions src/library-authoring/data/apiHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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) */
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,
})
);
Expand Down

0 comments on commit a0f6f43

Please sign in to comment.