From 55276c852ec81e54a8471bcc262021c1607dc5e3 Mon Sep 17 00:00:00 2001 From: Christofer Chavez Date: Wed, 17 Jan 2024 18:31:18 +0000 Subject: [PATCH 1/6] feat: Send message after update tags on content --- src/content-tags-drawer/data/apiHooks.jsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index 44151727a5..cafed4ca01 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -1,5 +1,6 @@ // @ts-check import { useMemo } from 'react'; +import { getConfig } from '@edx/frontend-platform'; import { useQuery, useQueries, @@ -142,5 +143,16 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { onSettled: () => { queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] }); }, + onSuccess: () => { + if (window.top != null) { + // Sends content tags to the parent page if is called from a iframe. + getContentTaxonomyTagsData(contentId).then((data) => { + window.top?.postMessage( + `[Manage tags drawer] Tags updated: ${JSON.stringify(data)}`, + getConfig().STUDIO_BASE_URL, + ); + }); + } + }, }); }; From 786a04eaf0987371fabad87969b31fc646443e5f Mon Sep 17 00:00:00 2001 From: Christofer Date: Thu, 18 Jan 2024 13:52:27 +0000 Subject: [PATCH 2/6] feat: Send messages with updated tags count from manage tags drawer --- src/content-tags-drawer/data/api.js | 11 +++++++++++ src/content-tags-drawer/data/api.test.js | 13 +++++++++++++ src/content-tags-drawer/data/apiHooks.jsx | 17 ++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/content-tags-drawer/data/api.js b/src/content-tags-drawer/data/api.js index b5b28514f9..c0fb1cdc56 100644 --- a/src/content-tags-drawer/data/api.js +++ b/src/content-tags-drawer/data/api.js @@ -29,6 +29,7 @@ export const getTaxonomyTagsApiUrl = (taxonomyId, options = {}) => { return url.href; }; export const getContentTaxonomyTagsApiUrl = (contentId) => new URL(`api/content_tagging/v1/object_tags/${contentId}/`, getApiBaseUrl()).href; +export const getContentTaxonomyTagsCountApiUrl = (contentId) => new URL(`api/content_tagging/v1/object_tag_counts/${contentId}/?count_implicit`, getApiBaseUrl()).href; export const getXBlockContentDataApiURL = (contentId) => new URL(`/xblock/outline/${contentId}`, getApiBaseUrl()).href; export const getLibraryContentDataApiUrl = (contentId) => new URL(`/api/libraries/v2/blocks/${contentId}/`, getApiBaseUrl()).href; @@ -54,6 +55,16 @@ export async function getContentTaxonomyTagsData(contentId) { return camelCaseObject(data[contentId]); } +/** + * Get the count of the tags that are applied to the content object + * @param {string} contentId The id of the content object to fetch the applied tags for + * @returns {Promise} + */ +export async function getContentTaxonomyTagsCountData(contentId) { + const { data } = await getAuthenticatedHttpClient().get(getContentTaxonomyTagsCountApiUrl(contentId)); + return camelCaseObject(data[contentId]); +} + /** * Fetch meta data (eg: display_name) about the content object (unit/compoenent) * @param {string} contentId The id of the content object (unit/component) diff --git a/src/content-tags-drawer/data/api.test.js b/src/content-tags-drawer/data/api.test.js index d183f59ea2..62719e920c 100644 --- a/src/content-tags-drawer/data/api.test.js +++ b/src/content-tags-drawer/data/api.test.js @@ -13,10 +13,12 @@ import { import { getTaxonomyTagsApiUrl, getContentTaxonomyTagsApiUrl, + getContentTaxonomyTagsCountApiUrl, getXBlockContentDataApiURL, getLibraryContentDataApiUrl, getTaxonomyTagsData, getContentTaxonomyTagsData, + getContentTaxonomyTagsCountData, getContentData, updateContentTaxonomyTags, } from './api'; @@ -88,6 +90,17 @@ describe('content tags drawer api calls', () => { expect(result).toEqual(contentTaxonomyTagsMock[contentId]); }); + it('should get content taxonomy tags count', async () => { + const contentId = 'block-v1:SampleTaxonomyOrg1+STC1+2023_1+type@vertical+block@aaf8b8eb86b54281aeeab12499d2cb0b'; + const dataMock = {}; + dataMock[contentId] = 1000; + axiosMock.onGet(getContentTaxonomyTagsCountApiUrl(contentId)).reply(200, dataMock); + const result = await getContentTaxonomyTagsCountData(contentId); + + expect(axiosMock.history.get[0].url).toEqual(getContentTaxonomyTagsCountApiUrl(contentId)); + expect(result).toEqual(1000); + }); + it('should get content data for course component', async () => { const contentId = 'block-v1:SampleTaxonomyOrg1+STC1+2023_1+type@vertical+block@aaf8b8eb86b54281aeeab12499d2cb0b'; axiosMock.onGet(getXBlockContentDataApiURL(contentId)).reply(200, contentDataMock); diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index cafed4ca01..328d631bbf 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -10,6 +10,7 @@ import { import { getTaxonomyTagsData, getContentTaxonomyTagsData, + getContentTaxonomyTagsCountData, getContentData, updateContentTaxonomyTags, } from './api'; @@ -147,8 +148,22 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { if (window.top != null) { // Sends content tags to the parent page if is called from a iframe. getContentTaxonomyTagsData(contentId).then((data) => { + const messageJson = { + contentId, + ...data, + }; window.top?.postMessage( - `[Manage tags drawer] Tags updated: ${JSON.stringify(data)}`, + `[Manage tags drawer] Tags updated: ${JSON.stringify(messageJson)}`, + getConfig().STUDIO_BASE_URL, + ); + }); + getContentTaxonomyTagsCountData(contentId).then((data) => { + const messageJson = { + contentId, + count: data, + }; + window.top?.postMessage( + `[Manage tags drawer] Count updated: ${JSON.stringify(messageJson)}`, getConfig().STUDIO_BASE_URL, ); }); From 78db929864f04038023d5f1374a9f8048791f880 Mon Sep 17 00:00:00 2001 From: Christofer Date: Mon, 22 Jan 2024 03:05:13 +0000 Subject: [PATCH 3/6] docs: Comments added --- src/content-tags-drawer/data/apiHooks.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index 328d631bbf..ee829d6420 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -145,8 +145,16 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] }); }, onSuccess: () => { + /* istanbul ignore next */ if (window.top != null) { - // Sends content tags to the parent page if is called from a iframe. + // This send messages to the parent page if the drawer is called from a iframe. + // Is used on Studio to update tags data and counts. + // In the future, when the Course Outline Page and Unit Page are integrated into this MFE, + // they should just use React Query to load the tag counts, and React Query will automatically + // refresh those counts when the mutation invalidates them. So this postMessage is just a temporary + // feature to support the legacy Django template courseware page. + + // Sends content tags. getContentTaxonomyTagsData(contentId).then((data) => { const messageJson = { contentId, @@ -157,6 +165,7 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { getConfig().STUDIO_BASE_URL, ); }); + // Sends tags count. getContentTaxonomyTagsCountData(contentId).then((data) => { const messageJson = { contentId, From 04f5bf9c04cbaa654e5872c0108a4729193f331c Mon Sep 17 00:00:00 2001 From: Christofer Date: Mon, 22 Jan 2024 03:21:26 +0000 Subject: [PATCH 4/6] docs: Comments added --- src/content-tags-drawer/data/apiHooks.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index ee829d6420..4fa557d3a6 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -144,6 +144,7 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { onSettled: () => { queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] }); }, + /* istanbul ignore next */ onSuccess: () => { /* istanbul ignore next */ if (window.top != null) { From e60c559a4578bb5be3d4849b37ff3f3b773572bf Mon Sep 17 00:00:00 2001 From: Christofer Date: Mon, 22 Jan 2024 23:30:06 +0000 Subject: [PATCH 5/6] test: Fix coverage --- src/content-tags-drawer/data/apiHooks.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index 4fa557d3a6..30e5977e11 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -144,9 +144,7 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { onSettled: () => { queryClient.invalidateQueries({ queryKey: ['contentTaxonomyTags', contentId] }); }, - /* istanbul ignore next */ - onSuccess: () => { - /* istanbul ignore next */ + onSuccess: /* istanbul ignore next */ () => { if (window.top != null) { // This send messages to the parent page if the drawer is called from a iframe. // Is used on Studio to update tags data and counts. From 2170664fc1a936cd054cea4d3cf95443d7be6145 Mon Sep 17 00:00:00 2001 From: Christofer Chavez Date: Mon, 12 Feb 2024 21:34:35 +0000 Subject: [PATCH 6/6] refactor: Send Json message on tags drawer update --- src/content-tags-drawer/data/apiHooks.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content-tags-drawer/data/apiHooks.jsx b/src/content-tags-drawer/data/apiHooks.jsx index 8bd08389a4..e7afba6d03 100644 --- a/src/content-tags-drawer/data/apiHooks.jsx +++ b/src/content-tags-drawer/data/apiHooks.jsx @@ -151,23 +151,23 @@ export const useContentTaxonomyTagsUpdater = (contentId, taxonomyId) => { // Sends content tags. getContentTaxonomyTagsData(contentId).then((data) => { - const messageJson = { + const contentData = { contentId, ...data, }; window.top?.postMessage( - `[Manage tags drawer] Tags updated: ${JSON.stringify(messageJson)}`, + { type: 'authoring.events.tags.updated', data: contentData }, getConfig().STUDIO_BASE_URL, ); }); // Sends tags count. getContentTaxonomyTagsCountData(contentId).then((data) => { - const messageJson = { + const contentData = { contentId, count: data, }; window.top?.postMessage( - `[Manage tags drawer] Count updated: ${JSON.stringify(messageJson)}`, + { type: 'authoring.events.tags.count.updated', data: contentData }, getConfig().STUDIO_BASE_URL, ); });