feat: tag sections, subsections, and the whole course (FC-0053) (#879)

* feat: tag sections, subsections, and the whole course
* docs: add comments to useContentTagsCount
This commit is contained in:
Rômulo Penido
2024-03-28 09:14:29 -03:00
committed by GitHub
parent 80bf86992d
commit f57d40ea34
32 changed files with 671 additions and 560 deletions

View File

@@ -8,6 +8,7 @@ export const getApiBaseUrl = () => getConfig().STUDIO_BASE_URL;
export const getCreateOrRerunCourseUrl = () => new URL('course/', getApiBaseUrl()).href;
export const getCourseRerunUrl = (courseId) => new URL(`/api/contentstore/v1/course_rerun/${courseId}`, getApiBaseUrl()).href;
export const getOrganizationsUrl = () => new URL('organizations', getApiBaseUrl()).href;
export const getTagsCountApiUrl = (contentPattern) => new URL(`api/content_tagging/v1/object_tag_counts/${contentPattern}/?count_implicit`, getApiBaseUrl()).href;
/**
* Get's organizations data. Returns list of organization names.
@@ -43,3 +44,18 @@ export async function createOrRerunCourse(courseData) {
);
return camelCaseObject(data);
}
/**
* Gets the tags count of multiple content by id separated by commas or a pattern using a '*' wildcard.
* @param {string} contentPattern
* @returns {Promise<Object>}
*/
export async function getTagsCount(contentPattern) {
if (contentPattern) {
const { data } = await getAuthenticatedHttpClient()
.get(getTagsCountApiUrl(contentPattern));
return data;
}
return null;
}

View File

@@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import { initializeMockApp } from '@edx/frontend-platform';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { contentTagsCountMock } from '../__mocks__';
import {
createOrRerunCourse,
getApiBaseUrl,
@@ -9,6 +10,8 @@ import {
getCreateOrRerunCourseUrl,
getCourseRerunUrl,
getCourseRerun,
getTagsCount,
getTagsCountApiUrl,
} from './api';
let axiosMock;
@@ -72,4 +75,19 @@ describe('generic api calls', () => {
expect(axiosMock.history.post[0].url).toEqual(getCreateOrRerunCourseUrl());
expect(result).toEqual(courseRerunData);
});
it('should get tags count', async () => {
const pattern = 'this,is,a,pattern';
const contentId = 'block-v1:SampleTaxonomyOrg1+STC1+2023_1+type@vertical+block@aaf8b8eb86b54281aeeab12499d2cb06';
axiosMock.onGet().reply(200, contentTagsCountMock);
const result = await getTagsCount(pattern);
expect(axiosMock.history.get[0].url).toEqual(getTagsCountApiUrl(pattern));
expect(result).toEqual(contentTagsCountMock);
expect(contentTagsCountMock[contentId]).toEqual(15);
});
it('should get null on empty pattern', async () => {
const result = await getTagsCount('');
expect(result).toEqual(null);
});
});

View File

@@ -1,6 +1,6 @@
// @ts-check
import { useQuery } from '@tanstack/react-query';
import { getOrganizations } from './api';
import { getOrganizations, getTagsCount } from './api';
/**
* Builds the query to get a list of available organizations
@@ -12,4 +12,23 @@ export const useOrganizationListData = () => (
})
);
export default useOrganizationListData;
/**
* Builds the query to get tags count of the whole contentId course and
* returns the tags count of the specific contentId.
* @param {string} contentId
*/
export const useContentTagsCount = (contentId) => {
let contentPattern;
if (contentId.includes('course-v1')) {
// If the contentId is a course, we want to get the tags count only for the course
contentPattern = contentId;
} else {
// If the contentId is not a course, we want to get the tags count for all the content of the course
contentPattern = contentId.replace(/\+type@.*$/, '*');
}
return useQuery({
queryKey: ['contentTagsCount', contentPattern],
queryFn: /* istanbul ignore next */ () => getTagsCount(contentPattern),
select: (data) => data[contentId] || 0, // Return the tags count of the specific contentId
});
};

View File

@@ -0,0 +1,28 @@
import { useQuery } from '@tanstack/react-query';
import { useContentTagsCount } from './apiHooks';
jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(),
}));
jest.mock('./api', () => ({
getTagsCount: jest.fn(),
}));
describe('useContentTagsCount', () => {
it('should return success response', () => {
useQuery.mockReturnValueOnce({ isSuccess: true, data: 'data' });
const pattern = '123';
const result = useContentTagsCount(pattern);
expect(result).toEqual({ isSuccess: true, data: 'data' });
});
it('should return failure response', () => {
useQuery.mockReturnValueOnce({ isSuccess: false });
const pattern = '123';
const result = useContentTagsCount(pattern);
expect(result).toEqual({ isSuccess: false });
});
});