From 183fd877c45a1970c036889717b0df4c29d52ef4 Mon Sep 17 00:00:00 2001 From: khuddite <62555977+khuddite@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:23:27 -0500 Subject: [PATCH] Add a confirmation modal for relation object deletion (#8818) Fixes #8698 1. Summary We decided to add a confirmation modal for the relation object deletion. It's gonna a bit of safety to the user interactions because this action can be disruptive even though it can be restored. 2. Solution Used `createPortal` function to address the issue where the vertical scrollbar shows over the modal. Added a logic that displays a confirmation modal for deletion in [this file](https://github.com/twentyhq/twenty/blob/d284419d66cf52e418d6622b9635334486b51040/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx). I can update the text(title, description, and CTA) as necessary based on the feedback. _**However, I observed an issue that the deleted object still shows up under the list until hard-refresh. I figured that can be addressed as a separate issue.**_ 3. Recording https://github.com/user-attachments/assets/1a64b702-a915-49f3-a226-2c2d5af8a1d7 --- .../RecordDetailRelationRecordsListItem.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx index 6c9c2ed81d..cba3ca9c1c 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx @@ -1,7 +1,7 @@ import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; -import { useCallback, useContext } from 'react'; +import { useCallback, useContext, useState } from 'react'; import { AnimatedEaseInOut, IconChevronDown, @@ -17,6 +17,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; +import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename'; import { RecordChip } from '@/object-record/components/RecordChip'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; @@ -39,6 +40,8 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; +import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; +import { createPortal } from 'react-dom'; import { RelationDefinitionType } from '~/generated-metadata/graphql'; const StyledListItem = styled(RecordDetailRecordsListItem)<{ @@ -94,6 +97,9 @@ export const RecordDetailRelationRecordsListItem = ({ }: RecordDetailRelationRecordsListItemProps) => { const { fieldDefinition } = useContext(FieldContext); + const [isDeleteRelationModalOpen, setIsDeleteRelationModalOpen] = + useState(false); + const { relationFieldMetadataId, relationObjectMetadataNameSingular, @@ -106,6 +112,10 @@ export const RecordDetailRelationRecordsListItem = ({ objectNameSingular: relationObjectMetadataNameSingular, }); + const relationObjectTypeName = getObjectTypename( + relationObjectMetadataNameSingular, + ); + const { objectMetadataItems } = useObjectMetadataItems(); const persistField = usePersistField(); @@ -158,8 +168,13 @@ export const RecordDetailRelationRecordsListItem = ({ }; const handleDelete = async () => { + setIsDeleteRelationModalOpen(true); closeDropdown(); + }; + + const handleConfirmDelete = async () => { await deleteOneRelationRecord(relationRecord.id); + setIsDeleteRelationModalOpen(false); }; const useUpdateOneObjectRecordMutation: RecordUpdateHook = () => { @@ -268,6 +283,24 @@ export const RecordDetailRelationRecordsListItem = ({ )} + {createPortal( + + Are you sure you want to delete this related{' '} + {relationObjectMetadataNameSingular}? +
+ This action will break all its relationships with other objects. + + } + onConfirmClick={handleConfirmDelete} + deleteButtonText={`Delete ${relationObjectTypeName}`} + />, + document.body, + )} ); };