From 82e62526aa398f061bd80dd6222dd10d537cc2eb Mon Sep 17 00:00:00 2001 From: "Dusan Mijatovic (PC2020)" Date: Fri, 22 Nov 2024 18:01:44 +0100 Subject: [PATCH] feat: order organisation and community categories alphabetically fix: software organisation categories select/decelet/save --- frontend/components/category/useCategories.ts | 7 +++++++ .../components/category/useCategoryTree.tsx | 19 ++++++++++++++++++- .../components/projects/ProjectCategories.tsx | 5 +++++ .../organisations/useProjectCategories.tsx | 3 +++ .../communities/useCommunityCategories.tsx | 8 +++++--- .../organisations/useSoftwareCategories.tsx | 7 +++++-- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/frontend/components/category/useCategories.ts b/frontend/components/category/useCategories.ts index eb8fbd345..c94f845f4 100644 --- a/frontend/components/category/useCategories.ts +++ b/frontend/components/category/useCategories.ts @@ -10,6 +10,7 @@ import logger from '~/utils/logger' import {TreeNode} from '~/types/TreeNode' import {CategoryEntry} from '~/types/Category' import {loadCategoryRoots} from '~/components/category/apiCategories' +import {sortCategoriesByName} from './useCategoryTree' type UseCategoriesProps={ community?:string|null, @@ -27,6 +28,9 @@ export default function useCategories({community,organisation}:UseCategoriesProp loadCategoryRoots({community,organisation}) .then(roots => { if (abort) return + // sort categories + sortCategoriesByName(roots) + // set state setRoots(roots) setError(null) }) @@ -46,6 +50,9 @@ export default function useCategories({community,organisation}:UseCategoriesProp function onMutation() { if (roots !== null) { + // sort categories + sortCategoriesByName(roots) + // update state setRoots([...roots]) } } diff --git a/frontend/components/category/useCategoryTree.tsx b/frontend/components/category/useCategoryTree.tsx index dbab5d6d3..1a0d73f82 100644 --- a/frontend/components/category/useCategoryTree.tsx +++ b/frontend/components/category/useCategoryTree.tsx @@ -18,6 +18,22 @@ export const categoryTreeNodesSort = (trees: TreeNode[]) => { } } +/** + * Sort (ascending) the complete category tree, at all levels, on name property . + * @param trees TreeNode[] + */ +export function sortCategoriesByName(trees: TreeNode[]){ + trees.sort(compareCategoryTreeNode) + for (const root of trees) { + // sort children first + if (root.childrenCount()>0){ + sortCategoriesByName(root.children()) + } + // sort roots + root.sortRecursively(compareCategoryEntry) + } +} + export const genCategoryTreeNodes = (categories: CategoryPath[]=[]) : TreeNode[] => { const allEntries: CategoryEntry[] = [] @@ -29,7 +45,7 @@ export const genCategoryTreeNodes = (categories: CategoryPath[]=[]) : TreeNode[]{ return useMemo(() => genCategoryTreeNodes(categories), [categories]) } + diff --git a/frontend/components/projects/ProjectCategories.tsx b/frontend/components/projects/ProjectCategories.tsx index 25ca62069..6e40d4e09 100644 --- a/frontend/components/projects/ProjectCategories.tsx +++ b/frontend/components/projects/ProjectCategories.tsx @@ -12,6 +12,11 @@ import {CategoryChipFilter} from '../category/CategoryChipFilter' export default function ProjectCategories({categories}:{categories:CategoryPath[]}) { const tree = useCategoryTree(categories) + // console.group('ProjectCategories') + // console.log('categories...', categories) + // console.log('tree...', tree) + // console.groupEnd() + // each root category is separate sidebar section return tree.map(node => { const category = node.getValue() diff --git a/frontend/components/projects/edit/organisations/useProjectCategories.tsx b/frontend/components/projects/edit/organisations/useProjectCategories.tsx index 45c6c128d..81b08039d 100644 --- a/frontend/components/projects/edit/organisations/useProjectCategories.tsx +++ b/frontend/components/projects/edit/organisations/useProjectCategories.tsx @@ -9,6 +9,7 @@ import {createJsonHeaders, getBaseUrl} from '~/utils/fetchHelpers' import {CategoryEntry} from '~/types/Category' import {TreeNode} from '~/types/TreeNode' import {loadCategoryRoots} from '~/components/category/apiCategories' +import {sortCategoriesByName} from '~/components/category/useCategoryTree' import {getCategoryListForProject, removeOrganisationCategoriesFromProject} from './apiProjectOrganisations' type UseProjectOrganisationCategoriesProps={ @@ -46,6 +47,8 @@ export default function useProjectCategories({ .then(([roots,selected]) => { // filter top level categories for projects (only top level items have this flag) const categories = roots.filter(item=>item.getValue().allow_projects) + // sort categories + sortCategoriesByName(categories) // collect tree leaves ids (end nodes) const availableIds = new Set() categories.forEach(root=>{ diff --git a/frontend/components/software/edit/communities/useCommunityCategories.tsx b/frontend/components/software/edit/communities/useCommunityCategories.tsx index 8663d2903..c4be37211 100644 --- a/frontend/components/software/edit/communities/useCommunityCategories.tsx +++ b/frontend/components/software/edit/communities/useCommunityCategories.tsx @@ -5,10 +5,11 @@ import {useEffect, useState} from 'react' import {useSession} from '~/auth' -import {loadCategoryRoots} from '~/components/category/apiCategories' import {CategoryEntry} from '~/types/Category' import {TreeNode} from '~/types/TreeNode' import {getCategoryForSoftwareIds} from '~/utils/getSoftware' +import {loadCategoryRoots} from '~/components/category/apiCategories' +import {sortCategoriesByName} from '~/components/category/useCategoryTree' import {saveSoftwareCategories, SoftwareCategories} from '../organisations/apiSoftwareOrganisations' import {removeCommunityCategoriesFromSoftware} from './apiSoftwareCommunities' @@ -40,8 +41,9 @@ export default function useCommunityCategories({ getCategoryForSoftwareIds(softwareId, token) ]) .then(([roots,selected]) => { - // filter top level categories for software (only top level items have this flag) - // collect tree leaves ids (end nodes) + // sort categories + sortCategoriesByName(roots) + // collect ids const availableIds = new Set() roots.forEach(root=>{ root.forEach(node=>{ diff --git a/frontend/components/software/edit/organisations/useSoftwareCategories.tsx b/frontend/components/software/edit/organisations/useSoftwareCategories.tsx index 827d59089..6cc9f99f6 100644 --- a/frontend/components/software/edit/organisations/useSoftwareCategories.tsx +++ b/frontend/components/software/edit/organisations/useSoftwareCategories.tsx @@ -10,6 +10,7 @@ import {CategoryEntry} from '~/types/Category' import {TreeNode} from '~/types/TreeNode' import {getCategoryForSoftwareIds} from '~/utils/getSoftware' import {loadCategoryRoots} from '~/components/category/apiCategories' +import {sortCategoriesByName} from '~/components/category/useCategoryTree' import { removeOrganisationCategoriesFromSoftware, saveSoftwareCategories, @@ -46,7 +47,9 @@ export default function useSoftwareCategories({ .then(([roots,selected]) => { // filter top level categories for software (only top level items have this flag) const categories = roots.filter(item=>item.getValue().allow_software) - // collect tree leaves ids (end nodes) + // sort categories + sortCategoriesByName(categories) + // collect ids const availableIds = new Set() categories.forEach(root=>{ root.forEach(node=>{ @@ -85,7 +88,7 @@ export default function useSoftwareCategories({ } } - if (selectedCategoryIds.size === 0) { + if (selected.size === 0) { onComplete() return }