Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/39463
Browse files Browse the repository at this point in the history
  • Loading branch information
dominictb committed Jun 13, 2024
2 parents c44cbc3 + e9799d9 commit 970bf98
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 12 deletions.
7 changes: 7 additions & 0 deletions src/libs/API/parameters/SetPolicyTagsRequired.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type SetPolicyTagsRequired = {
policyID: string;
tagListIndex: number;
requireTagList: boolean;
};

export default SetPolicyTagsRequired;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export type {default as SetWorkspaceApprovalModeParams} from './SetWorkspaceAppr
export type {default as SetWorkspacePayerParams} from './SetWorkspacePayerParams';
export type {default as SetWorkspaceReimbursementParams} from './SetWorkspaceReimbursementParams';
export type {default as SetPolicyRequiresTag} from './SetPolicyRequiresTag';
export type {default as SetPolicyTagsRequired} from './SetPolicyTagsRequired';
export type {default as RenamePolicyTaglistParams} from './RenamePolicyTaglistParams';
export type {default as SwitchToOldDotParams} from './SwitchToOldDotParams';
export type {default as TrackExpenseParams} from './TrackExpenseParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ const WRITE_COMMANDS = {
RENAME_POLICY_TAG: 'RenamePolicyTag',
SET_WORKSPACE_REQUIRES_CATEGORY: 'SetWorkspaceRequiresCategory',
DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories',
SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired',
SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag',
RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist',
DELETE_POLICY_TAGS: 'DeletePolicyTags',
Expand Down Expand Up @@ -345,6 +346,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams;
[WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams;
[WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag;
[WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired;
[WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglistParams;
[WRITE_COMMANDS.CREATE_POLICY_TAG]: Parameters.CreatePolicyTagsParams;
[WRITE_COMMANDS.RENAME_POLICY_TAG]: Parameters.RenamePolicyTagsParams;
Expand Down
88 changes: 82 additions & 6 deletions src/libs/actions/Policy/Tag.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {NullishDeep, OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, RenamePolicyTaglistParams, RenamePolicyTagsParams, SetPolicyTagsEnabled} from '@libs/API/parameters';
import type {EnablePolicyTagsParams, OpenPolicyTagsPageParams, RenamePolicyTaglistParams, RenamePolicyTagsParams, SetPolicyTagsEnabled, SetPolicyTagsRequired} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as ErrorUtils from '@libs/ErrorUtils';
import getIsNarrowLayout from '@libs/getIsNarrowLayout';
Expand Down Expand Up @@ -161,6 +161,7 @@ function createPolicyTag(policyID: string, tagName: string) {
tags: {
[newTagName]: {
errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'),
pendingAction: null,
},
},
},
Expand Down Expand Up @@ -329,8 +330,8 @@ function deletePolicyTags(policyID: string, tagsToDelete: string[]) {
API.write(WRITE_COMMANDS.DELETE_POLICY_TAGS, parameters, onyxData);
}

function clearPolicyTagErrors(policyID: string, tagName: string) {
const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[0];
function clearPolicyTagErrors(policyID: string, tagName: string, tagListIndex: number) {
const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[tagListIndex];
const tag = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`]?.[tagListName].tags?.[tagName];
if (!tag) {
return;
Expand Down Expand Up @@ -359,10 +360,25 @@ function clearPolicyTagErrors(policyID: string, tagName: string) {
});
}

function clearPolicyTagListError(policyID: string, tagListIndex: number, errorField: string) {
const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {};

if (!policyTag.name) {
return;
}

Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {
[policyTag.name]: {
errorFields: {
[errorField]: null,
},
},
});
}

function renamePolicyTag(policyID: string, policyTag: {oldName: string; newName: string}, tagListIndex: number) {
const tagList = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {};
const tag = tagList.tags?.[policyTag.oldName];

const oldTagName = policyTag.oldName;
const newTagName = PolicyUtils.escapeTagName(policyTag.newName);
const onyxData: OnyxData = {
Expand Down Expand Up @@ -639,16 +655,76 @@ function setPolicyRequiresTag(policyID: string, requiresTag: boolean) {
API.write(WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG, parameters, onyxData);
}

function setPolicyTagsRequired(policyID: string, requiresTag: boolean, tagListIndex: number) {
const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[tagListIndex] ?? {};

if (!policyTag.name) {
return;
}

const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`,
value: {
[policyTag.name]: {
required: requiresTag,
pendingFields: {required: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
errorFields: {required: null},
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`,
value: {
[policyTag.name]: {
pendingFields: {required: null},
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`,
value: {
[policyTag.name]: {
required: policyTag.required,
pendingFields: {required: null},
errorFields: {
required: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'),
},
},
},
},
],
};

const parameters: SetPolicyTagsRequired = {
policyID,
tagListIndex,
requireTagList: requiresTag,
};

API.write(WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED, parameters, onyxData);
}

export {
buildOptimisticPolicyRecentlyUsedTags,
clearPolicyTagErrors,
setPolicyRequiresTag,
setPolicyTagsRequired,
createPolicyTag,
clearPolicyTagErrors,
clearPolicyTagListError,
deletePolicyTags,
enablePolicyTags,
openPolicyTagsPage,
renamePolicyTag,
renamePolicyTaglist,
setPolicyRequiresTag,
setWorkspaceTagEnabled,
};

Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/tags/TagSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function TagSettingsPage({route, policyTags, navigation}: TagSettingsPageProps)
errors={ErrorUtils.getLatestErrorMessageField(currentPolicyTag)}
pendingAction={currentPolicyTag.pendingFields?.enabled}
errorRowStyles={styles.mh5}
onClose={() => Tag.clearPolicyTagErrors(route.params.policyID, route.params.tagName)}
onClose={() => Tag.clearPolicyTagErrors(route.params.policyID, route.params.tagName, route.params.orderWeight)}
>
<View style={[styles.mt2, styles.mh5]}>
<View style={[styles.flexRow, styles.mb5, styles.mr2, styles.alignItemsCenter, styles.justifyContentBetween]}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/tags/WorkspaceTagsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) {
customListHeader={getCustomListHeader()}
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]}
onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value)}
onDismissError={(item) => !isMultiLevelTags && Tag.clearPolicyTagErrors(policyID, item.value, 0)}
listHeaderContent={isSmallScreenWidth ? getHeaderText() : null}
showScrollIndicator={false}
/>
Expand Down
22 changes: 18 additions & 4 deletions src/pages/workspace/tags/WorkspaceViewTagsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import * as PolicyUtils from '@libs/PolicyUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
import * as Tag from '@userActions/Policy/Tag';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -65,10 +66,9 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) {
setSelectedTags({});
}, [isFocused]);

const policyTagList = useMemo(() => PolicyUtils.getTagLists(policyTags).find((policyTag) => policyTag.name === currentTagListName), [currentTagListName, policyTags]);
const tagList = useMemo<TagListItem[]>(
() =>
Object.values(policyTagList?.tags ?? {})
Object.values(currentPolicyTag?.tags ?? {})
.sort((tagA, tagB) => localeCompare(tagA.name, tagB.name))
.map((tag) => ({
value: tag.name,
Expand All @@ -81,7 +81,7 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) {
isDisabled: tag.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
rightElement: <ListItemRightCaretWithLabel labelText={tag.enabled ? translate('workspace.common.enabled') : translate('workspace.common.disabled')} />,
})),
[policyTagList, selectedTags, translate],
[currentPolicyTag, selectedTags, translate],
);

const tagListKeyedByName = useMemo(
Expand Down Expand Up @@ -234,6 +234,18 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) {
cancelText={translate('common.cancel')}
danger
/>
<View style={[styles.pv4, styles.ph5]}>
<ToggleSettingOptionRow
title={translate('common.required')}
switchAccessibilityLabel={translate('common.required')}
isActive={!!currentPolicyTag?.required}
onToggle={(on) => Tag.setPolicyTagsRequired(policyID, on, route.params.orderWeight)}
pendingAction={currentPolicyTag.pendingFields?.required}
errors={currentPolicyTag?.errorFields?.required ?? undefined}
onCloseError={() => Tag.clearPolicyTagListError(policyID, route.params.orderWeight, 'required')}
disabled={!currentPolicyTag?.required && !Object.values(currentPolicyTag?.tags ?? {}).some((tag) => tag.enabled)}
/>
</View>
<OfflineWithFeedback
errors={currentPolicyTag.errors}
pendingAction={currentPolicyTag.pendingAction}
Expand Down Expand Up @@ -264,7 +276,9 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) {
customListHeader={getCustomListHeader()}
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]}
onDismissError={(item) => Tag.clearPolicyTagErrors(policyID, item.value)}
onDismissError={(item) => {
Tag.clearPolicyTagErrors(policyID, item.value, route.params.orderWeight);
}}
/>
)}
</ScreenWrapper>
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/PolicyTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ type PolicyTagList<T extends string = string> = Record<

/** A list of errors keyed by microtime */
errors?: OnyxCommon.Errors;

/** Error objects keyed by field name containing errors keyed by microtime */
errorFields?: OnyxCommon.ErrorFields;
}>
>;

Expand Down

0 comments on commit 970bf98

Please sign in to comment.