From faddd9b24a444362264b686d958849aac96be3fa Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Mon, 18 Mar 2024 01:34:23 +0500 Subject: [PATCH] add delete functionality --- src/languages/en.ts | 3 + src/languages/es.ts | 3 + .../API/parameters/DeletePolicyTagsParams.ts | 10 +++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + src/libs/actions/Policy.ts | 74 +++++++++++++++++-- src/pages/workspace/tags/TagSettingsPage.tsx | 39 +++++++++- 7 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/libs/API/parameters/DeletePolicyTagsParams.ts diff --git a/src/languages/en.ts b/src/languages/en.ts index a80889ef7857..df37e55afad8 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1847,6 +1847,9 @@ export default { title: "You haven't created any tags", subtitle: 'Add a tag to track projects, locations, departments, and more.', }, + deleteTag: 'Delete tag', + deleteTagConfirmation: 'Are you sure that you want to delete this tag?', + deleteFailureMessage: 'An error occurred while deleting the tag, please try again.', tagRequiredError: 'Tag name is required.', existingTagError: 'A tag with this name already exists.', genericFailureMessage: 'An error occurred while updating the tag, please try again.', diff --git a/src/languages/es.ts b/src/languages/es.ts index 4660b57c9265..c89431985b1d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1871,6 +1871,9 @@ export default { title: 'No has creado ninguna etiqueta', subtitle: 'Añade una etiqueta para realizar el seguimiento de proyectos, ubicaciones, departamentos y otros.', }, + deleteTag: 'Eliminar etiqueta', + deleteTagConfirmation: '¿Estás seguro de que quieres eliminar esta etiqueta?', + deleteFailureMessage: 'Se ha producido un error al intentar eliminar la etiqueta. Por favor, inténtalo más tarde.', tagRequiredError: 'Lo nombre de la etiqueta es obligatorio.', existingTagError: 'Ya existe una etiqueta con este nombre.', genericFailureMessage: 'Se produjo un error al actualizar la etiqueta, inténtelo nuevamente.', diff --git a/src/libs/API/parameters/DeletePolicyTagsParams.ts b/src/libs/API/parameters/DeletePolicyTagsParams.ts new file mode 100644 index 000000000000..0094ce318390 --- /dev/null +++ b/src/libs/API/parameters/DeletePolicyTagsParams.ts @@ -0,0 +1,10 @@ +type DeletePolicyTagsParams = { + policyID: string; + /** + * Stringified JSON object with type of following structure: + * Array + */ + tags: string; +}; + +export default DeletePolicyTagsParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 5213bc4cd984..2932fc6be95a 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -181,3 +181,4 @@ export type {default as EnablePolicyTaxesParams} from './EnablePolicyTaxesParams export type {default as OpenPolicyMoreFeaturesPageParams} from './OpenPolicyMoreFeaturesPageParams'; export type {default as CreatePolicyDistanceRateParams} from './CreatePolicyDistanceRateParams'; export type {default as CreatePolicyTagsParams} from './CreatePolicyTagsParams'; +export type {default as DeletePolicyTagsParams} from './DeletePolicyTagsParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 14d963b5fa44..bfc57c2730dd 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -126,6 +126,7 @@ const WRITE_COMMANDS = { DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories', SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag', RENAME_POLICY_TAG_LIST: 'RenamePolicyTaglist', + DELETE_POLICY_TAGS: 'Policy_IndependentTaglist_Tags_Remove', CREATE_TASK: 'CreateTask', CANCEL_TASK: 'CancelTask', EDIT_TASK_ASSIGNEE: 'EditTaskAssignee', @@ -294,6 +295,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.RENAME_POLICY_TAG_LIST]: Parameters.RenamePolicyTaglist; [WRITE_COMMANDS.CREATE_POLICY_TAG]: Parameters.CreatePolicyTagsParams; [WRITE_COMMANDS.SET_POLICY_TAGS_ENABLED]: Parameters.SetPolicyTagsEnabled; + [WRITE_COMMANDS.DELETE_POLICY_TAGS]: Parameters.DeletePolicyTagsParams; [WRITE_COMMANDS.CREATE_TASK]: Parameters.CreateTaskParams; [WRITE_COMMANDS.CANCEL_TASK]: Parameters.CancelTaskParams; [WRITE_COMMANDS.EDIT_TASK_ASSIGNEE]: Parameters.EditTaskAssigneeParams; diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index b304a85cc27a..bf162a59ec2f 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -70,6 +70,7 @@ import type { PolicyCategories, PolicyCategory, PolicyMember, + PolicyTag, PolicyTagList, PolicyTags, RecentlyUsedCategories, @@ -79,7 +80,7 @@ import type { ReportAction, Transaction, } from '@src/types/onyx'; -import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; +import type {Errors, OnyxValueWithOfflineFeedback, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {OriginalMessageJoinPolicyChangeLog} from '@src/types/onyx/OriginalMessage'; import type {Attributes, CustomUnit, Rate, Unit} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; @@ -2841,7 +2842,7 @@ function renamePolicyCategory(policyID: string, policyCategory: {oldName: string } function createPolicyTag(policyID: string, tagName: string) { - const tagListName = Object.keys(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})[0]; + const policyTag = PolicyUtils.getTagLists(allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {})?.[0] ?? {}; const onyxData: OnyxData = { optimisticData: [ @@ -2849,7 +2850,7 @@ function createPolicyTag(policyID: string, tagName: string) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - [tagListName]: { + [policyTag.name]: { tags: { [tagName]: { name: tagName, @@ -2867,7 +2868,7 @@ function createPolicyTag(policyID: string, tagName: string) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - [tagListName]: { + [policyTag.name]: { tags: { [tagName]: { errors: null, @@ -2883,7 +2884,7 @@ function createPolicyTag(policyID: string, tagName: string) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, value: { - [tagListName]: { + [policyTag.name]: { tags: { [tagName]: { errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.genericFailureMessage'), @@ -2989,6 +2990,68 @@ function setWorkspaceTagEnabled(policyID: string, tagsToUpdate: Record>>>((acc, tagName) => { + acc[tagName] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}; + return acc; + }, {}), + }, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + value: { + [policyTag.name]: { + tags: { + ...tagsToDelete.reduce>>>((acc, tagName) => { + acc[tagName] = null; + return acc; + }, {}), + }, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + value: { + [policyTag.name]: { + tags: { + ...tagsToDelete.reduce>>>((acc, tagName) => { + acc[tagName] = {pendingAction: null, errors: ErrorUtils.getMicroSecondOnyxError('workspace.tags.deleteFailureMessage')}; + return acc; + }, {}), + }, + }, + }, + }, + ], + }; + + const parameters = { + policyID, + tags: JSON.stringify(tagsToDelete), + }; + + 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]; const tag = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`]?.[tagListName].tags?.[tagName]; @@ -3908,5 +3971,6 @@ export { clearPolicyTagErrors, clearWorkspaceReimbursementErrors, deleteWorkspaceCategories, + deletePolicyTags, setWorkspaceTagEnabled, }; diff --git a/src/pages/workspace/tags/TagSettingsPage.tsx b/src/pages/workspace/tags/TagSettingsPage.tsx index 14ba54e09f7e..6e6694d1dc39 100644 --- a/src/pages/workspace/tags/TagSettingsPage.tsx +++ b/src/pages/workspace/tags/TagSettingsPage.tsx @@ -3,7 +3,9 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import {Trashcan} from '@components/Icon/Expensicons'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -11,8 +13,10 @@ import Switch from '@components/Switch'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; import {setWorkspaceTagEnabled} from '@libs/actions/Policy'; import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {SettingsNavigatorParamList} from '@navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; @@ -35,12 +39,22 @@ function TagSettingsPage({route, policyTags}: TagSettingsPageProps) { const {translate} = useLocalize(); const policyTag = useMemo(() => PolicyUtils.getTagList(policyTags, 0), [policyTags]); + const {windowWidth} = useWindowDimensions(); + + const [isDeleteTagModalOpen, setIsDeleteTagModalOpen] = React.useState(false); + const currentPolicyTag = policyTag.tags[decodeURIComponent(route.params.tagName)]; if (!currentPolicyTag) { return ; } + const deleteTagAndHideModal = () => { + Policy.deletePolicyTags(route.params.policyID, [currentPolicyTag.name]); + setIsDeleteTagModalOpen(false); + Navigation.goBack(); + }; + const updateWorkspaceTagEnabled = (value: boolean) => { setWorkspaceTagEnabled(route.params.policyID, {[currentPolicyTag.name]: {name: currentPolicyTag.name, enabled: value}}); }; @@ -53,7 +67,30 @@ function TagSettingsPage({route, policyTags}: TagSettingsPageProps) { style={[styles.defaultModalContainer]} testID={TagSettingsPage.displayName} > - + setIsDeleteTagModalOpen(true), + }, + ]} + /> + setIsDeleteTagModalOpen(false)} + shouldSetModalVisibility={false} + prompt={translate('workspace.tags.deleteTagConfirmation')} + confirmText={translate('common.delete')} + cancelText={translate('common.cancel')} + danger + />