From 422a5db6f9f8a86a962a74e03de1426a47a7970c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Ch=C3=A1vez?= Date: Wed, 17 Apr 2024 22:45:33 -0500 Subject: [PATCH] [FC-0036] feat: Sort taxonomies (#949) Taxonomies are now sorted by tag count for those with applied tags, and by name for the rest. --- src/content-tags-drawer/ContentTagsDrawer.jsx | 32 ++++++- .../ContentTagsDrawer.test.jsx | 95 +++++++++++++++++-- 2 files changed, 120 insertions(+), 7 deletions(-) diff --git a/src/content-tags-drawer/ContentTagsDrawer.jsx b/src/content-tags-drawer/ContentTagsDrawer.jsx index a20e78bc5..a629a1679 100644 --- a/src/content-tags-drawer/ContentTagsDrawer.jsx +++ b/src/content-tags-drawer/ContentTagsDrawer.jsx @@ -108,6 +108,36 @@ const ContentTagsDrawer = ({ id, onClose }) => { }, []); const taxonomies = useMemo(() => { + const sortTaxonomies = (taxonomiesList) => { + const taxonomiesWithData = taxonomiesList.filter( + (t) => t.contentTags.length !== 0, + ); + + // Count implicit tags per taxonomy. + // TODO This count is also calculated individually + // in ContentTagsCollapsible. It should only be calculated once. + const tagsCountBytaxonomy = {}; + taxonomiesWithData.forEach((tax) => { + tagsCountBytaxonomy[tax.id] = new Set( + tax.contentTags.flatMap(item => item.lineage), + ).size; + }); + + // Sort taxonomies with data by implicit count + const sortedTaxonomiesWithData = taxonomiesWithData.sort( + (a, b) => tagsCountBytaxonomy[b.id] - tagsCountBytaxonomy[a.id], + ); + + // Empty taxonomies sorted by name. + // Since the query returns sorted by name, + // it is not necessary to do another sorting here. + const emptyTaxonomies = taxonomiesList.filter( + (t) => t.contentTags.length === 0, + ); + + return [...sortedTaxonomiesWithData, ...emptyTaxonomies]; + }; + if (taxonomyListData && contentTaxonomyTagsData) { // Initialize list of content tags in taxonomies to populate const taxonomiesList = taxonomyListData.results.map((taxonomy) => ({ @@ -125,7 +155,7 @@ const ContentTagsDrawer = ({ id, onClose }) => { } }); - return taxonomiesList; + return sortTaxonomies(taxonomiesList); } return []; }, [taxonomyListData, contentTaxonomyTagsData]); diff --git a/src/content-tags-drawer/ContentTagsDrawer.test.jsx b/src/content-tags-drawer/ContentTagsDrawer.test.jsx index 91392689e..a87f5f3e4 100644 --- a/src/content-tags-drawer/ContentTagsDrawer.test.jsx +++ b/src/content-tags-drawer/ContentTagsDrawer.test.jsx @@ -96,16 +96,78 @@ describe('', () => { }, ], }, + { + name: 'Taxonomy 2', + taxonomyId: 124, + canTagObject: true, + tags: [ + { + value: 'Tag 1', + lineage: ['Tag 1'], + canDeleteObjecttag: true, + }, + ], + }, + { + name: 'Taxonomy 3', + taxonomyId: 125, + canTagObject: true, + tags: [ + { + value: 'Tag 1.1.1', + lineage: ['Tag 1', 'Tag 1.1', 'Tag 1.1.1'], + canDeleteObjecttag: true, + }, + ], + }, + { + name: '(B) Taxonomy 4', + taxonomyId: 126, + canTagObject: true, + tags: [], + }, + { + name: '(A) Taxonomy 5', + taxonomyId: 127, + canTagObject: true, + tags: [], + }, ], }, }); getTaxonomyListData.mockResolvedValue({ - results: [{ - id: 123, - name: 'Taxonomy 1', - description: 'This is a description 1', - canTagObject: true, - }], + results: [ + { + id: 123, + name: 'Taxonomy 1', + description: 'This is a description 1', + canTagObject: true, + }, + { + id: 124, + name: 'Taxonomy 2', + description: 'This is a description 2', + canTagObject: true, + }, + { + id: 125, + name: 'Taxonomy 3', + description: 'This is a description 3', + canTagObject: true, + }, + { + id: 127, + name: '(A) Taxonomy 5', + description: 'This is a description 5', + canTagObject: true, + }, + { + id: 126, + name: '(B) Taxonomy 4', + description: 'This is a description 4', + canTagObject: true, + }, + ], }); useTaxonomyTagsData.mockReturnValue({ @@ -388,4 +450,25 @@ describe('', () => { postMessageSpy.mockRestore(); }); + + it('should taxonomies must be ordered', async () => { + setupMockDataForStagedTagsTesting(); + render(); + expect(await screen.findByText('Taxonomy 1')).toBeInTheDocument(); + + // First, taxonomies with content sorted by count implicit + // Later, empty taxonomies sorted by name + const expectedOrder = [ + 'Taxonomy 3', // 3 tags + 'Taxonomy 1', // 2 tags + 'Taxonomy 2', // 1 tag + '(A) Taxonomy 5', + '(B) Taxonomy 4', + ]; + + const taxonomies = screen.getAllByText(/.*Taxonomy.*/); + for (let i = 0; i !== taxonomies.length; i++) { + expect(taxonomies[i].textContent).toBe(expectedOrder[i]); + } + }); });