From fa5f4088b5c32f2308219981f27eb746482f5310 Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 13:10:14 +0700 Subject: [PATCH 1/7] fix The tag and category lists lack consistent alphabetical order --- src/libs/OptionsListUtils.ts | 3 +- .../categories/WorkspaceCategoriesPage.tsx | 29 +++++++++---------- .../workspace/tags/WorkspaceTagsPage.tsx | 25 ++++++++-------- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 330d9d6ef61d..5be1e278416d 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -987,8 +987,9 @@ function hasEnabledOptions(options: PolicyCategories | PolicyTag[]): boolean { * Via the hierarchy we avoid duplicating and sort categories one by one. Subcategories are being sorted alphabetically. */ function sortCategories(categories: Record): Category[] { + const categoriesList = Object.values(categories); // Sorts categories alphabetically by name. - const sortedCategories = Object.values(categories).sort((a, b) => a.name.localeCompare(b.name)); + const sortedCategories = lodashSortBy(categoriesList, 'name', localeCompare); // An object that respects nesting of categories. Also, can contain only uniq categories. const hierarchy: Hierarchy = {}; diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index 633d1833e43f..65a28ecdaad7 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -1,5 +1,6 @@ import {useFocusEffect, useIsFocused} from '@react-navigation/native'; import type {StackScreenProps} from '@react-navigation/stack'; +import lodashSortBy from 'lodash/sortBy'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -79,23 +80,21 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { } setSelectedCategories({}); }, [isFocused]); - + const a = lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare) const categoryList = useMemo( () => - Object.values(policyCategories ?? {}) - .sort((a, b) => localeCompare(a.name, b.name)) - .map((value) => { - const isDisabled = value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; - return { - text: value.name, - keyForList: value.name, - isSelected: !!selectedCategories[value.name], - isDisabled, - pendingAction: value.pendingAction, - errors: value.errors ?? undefined, - rightElement: , - }; - }), + lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare).map((value) => { + const isDisabled = value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + return { + text: value.name, + keyForList: value.name, + isSelected: !!selectedCategories[value.name], + isDisabled, + pendingAction: value.pendingAction, + errors: value.errors ?? undefined, + rightElement: , + }; + }), [policyCategories, selectedCategories, translate], ); diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index 92b016766742..bef1904a78b2 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -1,5 +1,6 @@ import {useFocusEffect, useIsFocused} from '@react-navigation/native'; import type {StackScreenProps} from '@react-navigation/stack'; +import lodashSortBy from 'lodash/sortBy'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; @@ -100,19 +101,17 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { ), })); } - return Object.values(policyTagLists[0]?.tags ?? {}) - .sort((tagA, tagB) => localeCompare(tagA.name, tagB.name)) - .map((tag) => ({ - value: tag.name, - text: PolicyUtils.getCleanedTagName(tag.name), - keyForList: tag.name, - isSelected: selectedTags[tag.name], - pendingAction: tag.pendingAction, - errors: tag.errors ?? undefined, - enabled: tag.enabled, - isDisabled: tag.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - rightElement: , - })); + return lodashSortBy(Object.values(policyTagLists[0]?.tags ?? {}), 'name', localeCompare).map((tag) => ({ + value: tag.name, + text: PolicyUtils.getCleanedTagName(tag.name), + keyForList: tag.name, + isSelected: selectedTags[tag.name], + pendingAction: tag.pendingAction, + errors: tag.errors ?? undefined, + enabled: tag.enabled, + isDisabled: tag.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + rightElement: , + })); }, [isMultiLevelTags, policyTagLists, selectedTags, translate]); const tagListKeyedByName = useMemo( From 80278615cae9594f0102c7936ebad872c946243f Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 16:35:58 +0700 Subject: [PATCH 2/7] fix lint --- src/libs/OptionsListUtils.ts | 2 +- .../workspace/categories/WorkspaceCategoriesPage.tsx | 8 +++++--- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index da562de23d9b..d20bae69a034 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -992,7 +992,7 @@ function hasEnabledOptions(options: PolicyCategories | PolicyTag[]): boolean { function sortCategories(categories: Record): Category[] { const categoriesList = Object.values(categories); // Sorts categories alphabetically by name. - const sortedCategories = lodashSortBy(categoriesList, 'name', localeCompare); + const sortedCategories = lodashSortBy(categoriesList, 'name', localeCompare) as Category[]; // An object that respects nesting of categories. Also, can contain only uniq categories. const hierarchy: Hierarchy = {}; diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index f77b431357ed..13c29955cf0e 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -38,6 +38,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; +import {PolicyCategory} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; type PolicyOption = ListItem & { @@ -60,6 +61,7 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { const backTo = route.params?.backTo; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyId}`); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyId}`); + const sortedPolicyCategories = lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare) as PolicyCategory[]; const isConnectedToAccounting = Object.keys(policy?.connections ?? {}).length > 0; const currentConnectionName = PolicyUtils.getCurrentConnectionName(policy); @@ -81,10 +83,10 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { } setSelectedCategories({}); }, [isFocused]); - const a = lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare) + const categoryList = useMemo( () => - lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare).map((value) => { + sortedPolicyCategories.map((value) => { const isDisabled = value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; return { text: value.name, @@ -96,7 +98,7 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { rightElement: , }; }), - [policyCategories, selectedCategories, translate], + [sortedPolicyCategories, selectedCategories, translate], ); const toggleCategory = (category: PolicyOption) => { diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index bdc2ec546238..08ca59441a3e 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -102,7 +102,8 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { ), })); } - return lodashSortBy(Object.values(policyTagLists[0]?.tags ?? {}), 'name', localeCompare).map((tag) => ({ + const sortedTags = lodashSortBy(Object.values(policyTagLists[0]?.tags ?? {}), 'name', localeCompare) as PolicyTag[]; + return sortedTags.map((tag) => ({ value: tag.name, text: PolicyUtils.getCleanedTagName(tag.name), keyForList: tag.name, From b16268ef7f34eeecfceb9aa4f75f8fef42e18a50 Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 16:47:50 +0700 Subject: [PATCH 3/7] fix lint --- src/pages/workspace/categories/WorkspaceCategoriesPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index 13c29955cf0e..748b3e0b5dd7 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -38,7 +38,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import {PolicyCategory} from '@src/types/onyx'; +import type {PolicyCategory} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; type PolicyOption = ListItem & { From 932b6b872341b7709608232d284e99bd92a2563f Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 17:39:00 +0700 Subject: [PATCH 4/7] fix sorted category issue --- src/libs/OptionsListUtils.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index d20bae69a034..17934f1f30a1 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -990,9 +990,8 @@ function hasEnabledOptions(options: PolicyCategories | PolicyTag[]): boolean { * Via the hierarchy we avoid duplicating and sort categories one by one. Subcategories are being sorted alphabetically. */ function sortCategories(categories: Record): Category[] { - const categoriesList = Object.values(categories); // Sorts categories alphabetically by name. - const sortedCategories = lodashSortBy(categoriesList, 'name', localeCompare) as Category[]; + const sortedCategories = Object.values(categories).sort((a, b) => a.name.localeCompare(b.name)); // An object that respects nesting of categories. Also, can contain only uniq categories. const hierarchy: Hierarchy = {}; @@ -1048,7 +1047,7 @@ function sortCategories(categories: Record): Category[] { return acc; }, []); - return flatHierarchy(hierarchy); + return lodashSortBy(flatHierarchy(hierarchy), 'name', localeCompare) as Category[]; } /** From fa582329c6ec01f3ccffeb4ce801f82139fea8fc Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 16 Jul 2024 16:47:56 +0700 Subject: [PATCH 5/7] add comment --- src/libs/OptionsListUtils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index ad259587c5bd..4c8136beccc1 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1062,6 +1062,8 @@ function sortCategories(categories: Record): Category[] { return acc; }, []); + // Use lodash's sortBy to ensure consistency with oldDot. + // See: https://github.com/Expensify/App/issues/33650#issuecomment-1919599578 return lodashSortBy(flatHierarchy(hierarchy), 'name', localeCompare) as Category[]; } From deb54bc43b0fca1fc7e69eac0ecbfce40f1af87d Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 17 Jul 2024 18:16:10 +0700 Subject: [PATCH 6/7] revert change in sortCategories --- src/libs/OptionsListUtils.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 48f63faf4dae..c552c5521219 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1064,9 +1064,7 @@ function sortCategories(categories: Record): Category[] { return acc; }, []); - // Use lodash's sortBy to ensure consistency with oldDot. - // See: https://github.com/Expensify/App/issues/33650#issuecomment-1919599578 - return lodashSortBy(flatHierarchy(hierarchy), 'name', localeCompare) as Category[]; + return flatHierarchy(hierarchy); } /** From 4d0676196cf07e9da7e7b673a3cc5d8fbe23bfd0 Mon Sep 17 00:00:00 2001 From: dominictb Date: Mon, 22 Jul 2024 17:27:32 +0700 Subject: [PATCH 7/7] remove sortedPolicyCategories --- src/pages/workspace/categories/WorkspaceCategoriesPage.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index 748b3e0b5dd7..f8b539ca61db 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -61,7 +61,6 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { const backTo = route.params?.backTo; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyId}`); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyId}`); - const sortedPolicyCategories = lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare) as PolicyCategory[]; const isConnectedToAccounting = Object.keys(policy?.connections ?? {}).length > 0; const currentConnectionName = PolicyUtils.getCurrentConnectionName(policy); @@ -86,7 +85,7 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { const categoryList = useMemo( () => - sortedPolicyCategories.map((value) => { + (lodashSortBy(Object.values(policyCategories ?? {}), 'name', localeCompare) as PolicyCategory[]).map((value) => { const isDisabled = value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; return { text: value.name, @@ -98,7 +97,7 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { rightElement: , }; }), - [sortedPolicyCategories, selectedCategories, translate], + [policyCategories, selectedCategories, translate], ); const toggleCategory = (category: PolicyOption) => {