twentyhq / twenty

Building a modern alternative to Salesforce, powered by the community.
https://twenty.com
GNU Affero General Public License v3.0
14.96k stars 1.46k forks source link

Add deletion confirmation modals to tasks, notes and single objects #6075

Closed JarWarren closed 1 day ago

JarWarren commented 3 days ago

Scope & Context

In many cases, deletion is an irreversible single-click procedure.

Current behavior

Tasks and notes can be deleted by (mis)clicking a trash button. No confirmation is needed.

Objects (Person, Company, etc) can be deleted through the menu option, which requires a second click, but still no confirmation is needed. This risks substantial data loss for large objects.

Expected behavior

A confirmation modal, similar to batch deletion or API key deletion.

Example: See #4016 for an example modal.

greptile-apps[bot] commented 3 days ago

Implementation Steps

  1. Create Confirmation Modal Component

    • Create a new component DeleteConfirmationModal.tsx in a shared components directory.
      
      import React from 'react';
      import { Modal, Button } from 'twenty-ui';

    type DeleteConfirmationModalProps = { isOpen: boolean; onConfirm: () => void; onCancel: () => void; };

    export const DeleteConfirmationModal = ({ isOpen, onConfirm, onCancel }: DeleteConfirmationModalProps) => (

    Confirm Deletion

    Are you sure you want to delete this item? This action cannot be undone.

    );

  2. Integrate Modal in Task Deletion

    • Update ActivityTitle.tsx to include the modal and handle its state.
      
      import { useState } from 'react';
      import { DeleteConfirmationModal } from '@/components/DeleteConfirmationModal';

    export const ActivityTitle = ({ activityId }: ActivityTitleProps) => { const [isModalOpen, setModalOpen] = useState(false); const { deleteOneRecord } = useDeleteOneRecord({ objectNameSingular: 'Task' });

    const handleDelete = () => setModalOpen(true); const confirmDelete = () => { deleteOneRecord(activityId); setModalOpen(false); };

    return ( <>

     <DeleteConfirmationModal isOpen={isModalOpen} onConfirm={confirmDelete} onCancel={() => setModalOpen(false)} />

    </> ); };

  3. Integrate Modal in Note Deletion

    • Update the relevant note component similarly to ActivityTitle.tsx.
  4. Integrate Modal in Single Object Deletion

    • Update useDeleteOneRecord.ts to include modal logic.
      
      import { useState } from 'react';
      import { DeleteConfirmationModal } from '@/components/DeleteConfirmationModal';

    export const useDeleteOneRecord = ({ objectNameSingular }: useDeleteOneRecordProps) => { const [isModalOpen, setModalOpen] = useState(false); const apolloClient = useApolloClient();

    const deleteOneRecord = useCallback(async (idToDelete: string) => { setModalOpen(true); const confirmDelete = async () => { const deletedRecord = await apolloClient.mutate({ mutation: deleteOneRecordMutation, variables: { idToDelete }, optimisticResponse: { [mutationResponseField]: { __typename: capitalize(objectNameSingular), id: idToDelete } }, update: (cache, { data }) => { const record = data?.[mutationResponseField]; if (!record) return; const cachedRecord = getRecordFromCache(record.id, cache); if (!cachedRecord) return; triggerDeleteRecordsOptimisticEffect({ cache, objectMetadataItem, recordsToDelete: [cachedRecord], objectMetadataItems }); }, }); setModalOpen(false); return deletedRecord.data?.[mutationResponseField] ?? null; }; return ( <DeleteConfirmationModal isOpen={isModalOpen} onConfirm={confirmDelete} onCancel={() => setModalOpen(false)} /> ); }, [apolloClient, deleteOneRecordMutation, getRecordFromCache, mutationResponseField, objectMetadataItem, objectNameSingular, objectMetadataItems]);

    return { deleteOneRecord }; };

Update the components and hooks as shown to include the deletion confirmation modal.

References

/packages/twenty-front/src/modules/object-record/hooks/useDeleteOneRecord.ts /packages/twenty-front/src/modules/activities/comment/Comment.tsx /packages/twenty-front/src/modules/activities/components/ActivityTitle.tsx /packages/twenty-front/src/modules/activities/calendar/components/CalendarEventDetails.tsx /packages/twenty-front/src/modules/activities /packages/twenty-front/src/modules/object-record

#### About Greptile This response provides a starting point for your research, not a precise solution. Help us improve! Please leave a ๐Ÿ‘ if this is helpful and ๐Ÿ‘Ž if it is irrelevant. [Ask Greptile](https://app.greptile.com/chat/github/twentyhq/twenty/main) ยท [Edit Issue Bot Settings](https://app.greptile.com/apps/github)
Us3r-gitHub commented 1 day ago

6027

Bonapara commented 1 day ago

Hi @JarWarren, thanks for the feedback! We will address your issue soon by implementing the Soft Delete feature (https://github.com/twentyhq/twenty/issues/6075), which will allow you to retrieve a deleted issue.

In this context, resolving this issue