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:
Rômulo Penido
2024-09-27 23:24:12 -03:00
committed by GitHub
parent c80483c053
commit 4d67e8bda9
29 changed files with 1155 additions and 139 deletions

View File

@@ -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);
};

View File

@@ -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,
});

View File

@@ -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);
});
});

View File

@@ -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
*/