feat: improve collection sidebar (#1320)
* feat: improve collection sidebar * feat: add comments to splice blockTypesArray code Co-authored-by: Jillian <jill@opencraft.com> --------- Co-authored-by: Jillian <jill@opencraft.com> Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
This commit is contained in:
@@ -274,3 +274,32 @@ mockLibraryBlockMetadata.dataPublished = {
|
||||
mockLibraryBlockMetadata.usageKeyForTags = mockContentTaxonomyTagsData.largeTagsId;
|
||||
/** Apply this mock. Returns a spy object that can tell you if it's been called. */
|
||||
mockLibraryBlockMetadata.applyMock = () => jest.spyOn(api, 'getLibraryBlockMetadata').mockImplementation(mockLibraryBlockMetadata);
|
||||
|
||||
/**
|
||||
* Mock for `getCollectionMetadata()`
|
||||
*
|
||||
* This mock returns a fixed response for the collection ID *collection_1*.
|
||||
*/
|
||||
export async function mockGetCollectionMetadata(libraryId: string, collectionId: string): Promise<api.Collection> {
|
||||
if (collectionId === mockGetCollectionMetadata.collectionIdError) {
|
||||
throw createAxiosError({ code: 400, message: 'Not found.', path: api.getLibraryCollectionApiUrl(libraryId, collectionId) });
|
||||
}
|
||||
return Promise.resolve(mockGetCollectionMetadata.collectionData);
|
||||
}
|
||||
mockGetCollectionMetadata.collectionId = 'collection_1';
|
||||
mockGetCollectionMetadata.collectionIdError = 'collection_error';
|
||||
mockGetCollectionMetadata.collectionData = {
|
||||
id: 1,
|
||||
key: 'collection_1',
|
||||
title: 'Test Collection',
|
||||
description: 'A collection for testing',
|
||||
created: '2024-09-19T10:00:00Z',
|
||||
createdBy: 'test_author',
|
||||
modified: '2024-09-20T11:00:00Z',
|
||||
learningPackage: 11,
|
||||
enabled: true,
|
||||
} satisfies api.Collection;
|
||||
/** Apply this mock. Returns a spy object that can tell you if it's been called. */
|
||||
mockGetCollectionMetadata.applyMock = () => {
|
||||
jest.spyOn(api, 'getCollectionMetadata').mockImplementation(mockGetCollectionMetadata);
|
||||
};
|
||||
|
||||
@@ -180,6 +180,8 @@ export interface CreateLibraryCollectionDataRequest {
|
||||
description: string | null;
|
||||
}
|
||||
|
||||
export type UpdateCollectionComponentsRequest = Partial<CreateLibraryCollectionDataRequest>;
|
||||
|
||||
/**
|
||||
* Fetch the list of XBlock types that can be added to this library
|
||||
*/
|
||||
@@ -316,10 +318,30 @@ export async function getXBlockOLX(usageKey: string): Promise<string> {
|
||||
return data.olx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collection metadata.
|
||||
*/
|
||||
export async function getCollectionMetadata(libraryId: string, collectionId: string): Promise<Collection> {
|
||||
const { data } = await getAuthenticatedHttpClient().get(getLibraryCollectionApiUrl(libraryId, collectionId));
|
||||
return camelCaseObject(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update collection metadata.
|
||||
*/
|
||||
export async function updateCollectionMetadata(
|
||||
libraryId: string,
|
||||
collectionId: string,
|
||||
collectionData: UpdateCollectionComponentsRequest,
|
||||
) {
|
||||
const client = getAuthenticatedHttpClient();
|
||||
await client.patch(getLibraryCollectionApiUrl(libraryId, collectionId), collectionData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update collection components.
|
||||
*/
|
||||
export async function updateCollectionComponents(libraryId:string, collectionId: string, usageKeys: string[]) {
|
||||
export async function updateCollectionComponents(libraryId: string, collectionId: string, usageKeys: string[]) {
|
||||
await getAuthenticatedHttpClient().patch(getLibraryCollectionComponentApiUrl(libraryId, collectionId), {
|
||||
usage_keys: usageKeys,
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
|
||||
import { initializeMockApp } from '@edx/frontend-platform';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
getCreateLibraryBlockUrl,
|
||||
getLibraryCollectionComponentApiUrl,
|
||||
getLibraryCollectionsApiUrl,
|
||||
getLibraryCollectionApiUrl,
|
||||
} from './api';
|
||||
import {
|
||||
useCommitLibraryChanges,
|
||||
@@ -17,6 +19,7 @@ import {
|
||||
useCreateLibraryCollection,
|
||||
useRevertLibraryChanges,
|
||||
useUpdateCollectionComponents,
|
||||
useCollection,
|
||||
} from './apiHooks';
|
||||
|
||||
let axiosMock;
|
||||
@@ -106,4 +109,18 @@ describe('library api hooks', () => {
|
||||
|
||||
expect(axiosMock.history.patch[0].url).toEqual(url);
|
||||
});
|
||||
|
||||
it('should get collection metadata', async () => {
|
||||
const libraryId = 'lib:org:1';
|
||||
const collectionId = 'my-first-collection';
|
||||
const url = getLibraryCollectionApiUrl(libraryId, collectionId);
|
||||
|
||||
axiosMock.onGet(url).reply(200, { 'test-data': 'test-value' });
|
||||
const { result } = renderHook(() => useCollection(libraryId, collectionId), { wrapper });
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBeFalsy();
|
||||
});
|
||||
expect(result.current.data).toEqual({ testData: 'test-value' });
|
||||
expect(axiosMock.history.get[0].url).toEqual(url);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,8 +26,11 @@ import {
|
||||
updateXBlockFields,
|
||||
createCollection,
|
||||
getXBlockOLX,
|
||||
updateCollectionMetadata,
|
||||
type UpdateCollectionComponentsRequest,
|
||||
updateCollectionComponents,
|
||||
type CreateLibraryCollectionDataRequest,
|
||||
getCollectionMetadata,
|
||||
} from './api';
|
||||
|
||||
export const libraryQueryPredicate = (query: Query, libraryId: string): boolean => {
|
||||
@@ -278,6 +281,33 @@ export const useXBlockOLX = (usageKey: string) => (
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the metadata for a collection in a library
|
||||
*/
|
||||
export const useCollection = (libraryId: string, collectionId: string) => (
|
||||
useQuery({
|
||||
enabled: !!libraryId && !!collectionId,
|
||||
queryKey: libraryAuthoringQueryKeys.collection(libraryId, collectionId),
|
||||
queryFn: () => getCollectionMetadata(libraryId!, collectionId!),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* Use this mutation to update the fields of a collection in a library
|
||||
*/
|
||||
export const useUpdateCollection = (libraryId: string, collectionId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: UpdateCollectionComponentsRequest) => updateCollectionMetadata(libraryId, collectionId, data),
|
||||
onSettled: () => {
|
||||
// NOTE: We invalidate the library query here because we need to update the library's
|
||||
// collection list.
|
||||
queryClient.invalidateQueries({ predicate: (query) => libraryQueryPredicate(query, libraryId) });
|
||||
queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.collection(libraryId, collectionId) });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this mutation to add components to a collection in a library
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user