Skip to content

Commit

Permalink
Merge pull request #39036 from tienifr/fix/37508
Browse files Browse the repository at this point in the history
fix: categorize all expense switch is not disabled
  • Loading branch information
luacmartins authored Apr 3, 2024
2 parents aaddfed + a45c9a9 commit 838206f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ function getSearchValueForPhoneOrEmail(searchTerm: string) {
* Verifies that there is at least one enabled option
*/
function hasEnabledOptions(options: PolicyCategories | PolicyTag[]): boolean {
return Object.values(options).some((option) => option.enabled);
return Object.values(options).some((option) => option.enabled && option.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
}

/**
Expand Down
109 changes: 90 additions & 19 deletions src/libs/actions/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import getIsNarrowLayout from '@libs/getIsNarrowLayout';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import * as NumberUtils from '@libs/NumberUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PhoneNumber from '@libs/PhoneNumber';
import * as PolicyUtils from '@libs/PolicyUtils';
Expand Down Expand Up @@ -2872,27 +2873,29 @@ function createWorkspaceFromIOUPayment(iouReport: Report | EmptyObject): string

function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Record<string, {name: string; enabled: boolean}>) {
const policyCategories = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {};
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
const optimisticPolicyCategoriesData = {
...Object.keys(categoriesToUpdate).reduce<PolicyCategories>((acc, key) => {
acc[key] = {
...policyCategories[key],
...categoriesToUpdate[key],
errors: null,
pendingFields: {
enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
};

return acc;
}, {}),
};
const shouldDisableRequiresCategory = !OptionsListUtils.hasEnabledOptions({...policyCategories, ...optimisticPolicyCategoriesData});
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
...Object.keys(categoriesToUpdate).reduce<PolicyCategories>((acc, key) => {
acc[key] = {
...policyCategories[key],
...categoriesToUpdate[key],
errors: null,
pendingFields: {
enabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
};

return acc;
}, {}),
},
value: optimisticPolicyCategoriesData,
},
],
successData: [
Expand Down Expand Up @@ -2938,6 +2941,37 @@ function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Recor
},
],
};
if (shouldDisableRequiresCategory) {
onyxData.optimisticData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: false,
pendingFields: {
requiresCategory: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
});
onyxData.successData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingFields: {
requiresCategory: null,
},
},
});
onyxData.failureData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: policy?.requiresCategory,
pendingFields: {
requiresCategory: null,
},
},
});
}

const parameters = {
policyID,
Expand Down Expand Up @@ -3437,15 +3471,21 @@ function clearCategoryErrors(policyID: string, categoryName: string) {
}

function deleteWorkspaceCategories(policyID: string, categoryNamesToDelete: string[]) {
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
const policyCategories = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`] ?? {};
const optimisticPolicyCategoriesData = categoryNamesToDelete.reduce<Record<string, Partial<PolicyCategory>>>((acc, categoryName) => {
acc[categoryName] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE};
return acc;
}, {});
const shouldDisableRequiresCategory = !OptionsListUtils.hasEnabledOptions(
Object.values(policyCategories).filter((category) => !categoryNamesToDelete.includes(category.name) && category.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE),
);
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: categoryNamesToDelete.reduce<Record<string, Partial<PolicyCategory>>>((acc, categoryName) => {
acc[categoryName] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE};
return acc;
}, {}),
value: optimisticPolicyCategoriesData,
},
],
successData: [
Expand All @@ -3472,6 +3512,37 @@ function deleteWorkspaceCategories(policyID: string, categoryNamesToDelete: stri
},
],
};
if (shouldDisableRequiresCategory) {
onyxData.optimisticData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: false,
pendingFields: {
requiresCategory: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
});
onyxData.successData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingFields: {
requiresCategory: null,
},
},
});
onyxData.failureData?.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
requiresCategory: policy?.requiresCategory,
pendingFields: {
requiresCategory: null,
},
},
});
}

const parameters = {
policyID,
Expand Down
23 changes: 19 additions & 4 deletions src/pages/workspace/categories/WorkspaceCategoriesSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ScreenWrapper from '@components/ScreenWrapper';
Expand All @@ -9,23 +11,32 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import {setWorkspaceRequiresCategory} from '@libs/actions/Policy';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper';
import FeatureEnabledAccessOrNotFoundWrapper from '@pages/workspace/FeatureEnabledAccessOrNotFoundWrapper';
import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';

type WorkspaceCategoriesSettingsPageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORIES_SETTINGS>;
type WorkspaceCategoriesSettingsPageOnyxProps = {
/** Collection of categories attached to a policy */
policyCategories: OnyxEntry<OnyxTypes.PolicyCategories>;
};

function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPageProps) {
type WorkspaceCategoriesSettingsPageProps = WorkspaceCategoriesSettingsPageOnyxProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CATEGORIES_SETTINGS>;

function WorkspaceCategoriesSettingsPage({route, policyCategories}: WorkspaceCategoriesSettingsPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

const updateWorkspaceRequiresCategory = (value: boolean) => {
setWorkspaceRequiresCategory(route.params.policyID, value);
};

const hasEnabledOptions = OptionsListUtils.hasEnabledOptions(policyCategories ?? {});
return (
<AdminPolicyAccessOrNotFoundWrapper policyID={route.params.policyID}>
<PaidPolicyAccessOrNotFoundWrapper policyID={route.params.policyID}>
Expand Down Expand Up @@ -53,7 +64,7 @@ function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPag
isOn={policy?.requiresCategory ?? false}
accessibilityLabel={translate('workspace.categories.requiresCategory')}
onToggle={updateWorkspaceRequiresCategory}
disabled={!policy?.areCategoriesEnabled}
disabled={!policy?.areCategoriesEnabled || !hasEnabledOptions}
/>
</View>
</View>
Expand All @@ -69,4 +80,8 @@ function WorkspaceCategoriesSettingsPage({route}: WorkspaceCategoriesSettingsPag

WorkspaceCategoriesSettingsPage.displayName = 'WorkspaceCategoriesSettingsPage';

export default WorkspaceCategoriesSettingsPage;
export default withOnyx<WorkspaceCategoriesSettingsPageProps, WorkspaceCategoriesSettingsPageOnyxProps>({
policyCategories: {
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${route.params.policyID}`,
},
})(WorkspaceCategoriesSettingsPage);
6 changes: 3 additions & 3 deletions src/types/onyx/PolicyTag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as OnyxCommon from './OnyxCommon';

type PolicyTag = {
type PolicyTag = OnyxCommon.OnyxValueWithOfflineFeedback<{
/** Name of a Tag */
name: string;

Expand All @@ -13,9 +13,9 @@ type PolicyTag = {

/** A list of errors keyed by microtime */
errors?: OnyxCommon.Errors | null;
};
}>;

type PolicyTags = Record<string, OnyxCommon.OnyxValueWithOfflineFeedback<PolicyTag>>;
type PolicyTags = Record<string, PolicyTag>;

type PolicyTagList<T extends string = string> = Record<
T,
Expand Down

0 comments on commit 838206f

Please sign in to comment.