From 7f3623239aaa481339fa337c03fa07349bb0d8b4 Mon Sep 17 00:00:00 2001 From: Anchit Sinha Date: Fri, 29 Mar 2024 22:48:21 +0530 Subject: [PATCH] 4410-feat(front): Implement Confirmation Prompt for Multiple Record Deletion (#4514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: implement confirmation prompt * feat: remove prop drilling and introduce recoil state * chore: fix eslint issues * feat: set record text according to length of records * chore: fix eslint issues * refactor: made changes according to code review * fix: show delete according to singular and plural records. * fix: eslint issues * feat: show number of selected records * style: fix positioning of actionbar * feat: display ConfirmationModal seperately * chore: remove recoil state and use usestate instead * chore: minor change --------- Co-authored-by: Félix Malfait --- .../hooks/useRecordActionBar.tsx | 34 +++++++++++++-- .../components/RecordBoardActionBar.tsx | 2 +- .../components/RecordTableActionBar.tsx | 2 +- .../action-bar/components/ActionBar.tsx | 42 ++++++++++++++----- .../action-bar/types/ActionBarEntry.ts | 1 + 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx index 090647575..26addcc3e 100644 --- a/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-action-bar/hooks/useRecordActionBar.tsx @@ -1,4 +1,4 @@ -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import { isNonEmptyString } from '@sniptt/guards'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; @@ -17,6 +17,7 @@ import { IconPuzzle, IconTrash, } from '@/ui/display/icon'; +import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState'; import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState'; import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry'; @@ -36,6 +37,8 @@ export const useRecordActionBar = ({ }: useRecordActionBarProps) => { const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState); const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState); + const [isDeleteRecordsModalOpen, setIsDeleteRecordsModalOpen] = + useState(false); const { createFavorite, favorites, deleteFavorite } = useFavorites(); @@ -106,10 +109,26 @@ export const useRecordActionBar = ({ const baseActions: ContextMenuEntry[] = useMemo( () => [ { - label: `Delete (${selectedRecordIds.length})`, + label: 'Delete', Icon: IconTrash, accent: 'danger', - onClick: () => handleDeleteClick(), + onClick: () => setIsDeleteRecordsModalOpen(true), + ConfirmationModal: ( + handleDeleteClick()} + deleteButtonText={`Delete ${ + selectedRecordIds.length > 1 ? 'Records' : 'Record' + }`} + /> + ), }, { label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`, @@ -118,7 +137,14 @@ export const useRecordActionBar = ({ onClick: () => download(), }, ], - [handleDeleteClick, download, progress, selectedRecordIds], + [ + handleDeleteClick, + download, + progress, + selectedRecordIds, + isDeleteRecordsModalOpen, + setIsDeleteRecordsModalOpen, + ], ); const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled( diff --git a/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx index 2bb43e96c..584cbeab3 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/action-bar/components/RecordBoardActionBar.tsx @@ -18,5 +18,5 @@ export const RecordBoardActionBar = ({ return null; } - return ; + return ; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx index 14b3768d0..f7241a5e2 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/action-bar/components/RecordTableActionBar.tsx @@ -16,5 +16,5 @@ export const RecordTableActionBar = ({ return null; } - return ; + return ; }; diff --git a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx index bf5c2586a..f0e2a9d2f 100644 --- a/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/action-bar/components/ActionBar.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import { useRef } from 'react'; import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; @@ -7,6 +7,10 @@ import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/cont import { ActionBarItem } from './ActionBarItem'; +type ActionBarProps = { + selectedIds?: string[]; +}; + const StyledContainerActionBar = styled.div` align-items: center; background: ${({ theme }) => theme.background.secondary}; @@ -27,7 +31,15 @@ const StyledContainerActionBar = styled.div` z-index: 1; `; -export const ActionBar = () => { +const StyledLabel = styled.div` + color: ${({ theme }) => theme.font.color.tertiary}; + font-size: ${({ theme }) => theme.font.size.md}; + font-weight: ${({ theme }) => theme.font.weight.medium}; + padding-left: ${({ theme }) => theme.spacing(2)}; + padding-right: ${({ theme }) => theme.spacing(2)}; +`; + +export const ActionBar = ({ selectedIds }: ActionBarProps) => { const contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState); const actionBarEntries = useRecoilValue(actionBarEntriesState); const wrapperRef = useRef(null); @@ -37,14 +49,22 @@ export const ActionBar = () => { } return ( - - {actionBarEntries.map((item, index) => ( - - ))} - + <> + + {selectedIds && ( + {selectedIds.length} selected: + )} + {actionBarEntries.map((item, index) => ( + + ))} + +
+ {actionBarEntries[0]?.ConfirmationModal} +
+ ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/action-bar/types/ActionBarEntry.ts b/packages/twenty-front/src/modules/ui/navigation/action-bar/types/ActionBarEntry.ts index ddd947a16..1ef345e3c 100644 --- a/packages/twenty-front/src/modules/ui/navigation/action-bar/types/ActionBarEntry.ts +++ b/packages/twenty-front/src/modules/ui/navigation/action-bar/types/ActionBarEntry.ts @@ -7,4 +7,5 @@ export type ActionBarEntry = { accent?: MenuItemAccent; onClick?: () => void; subActions?: ActionBarEntry[]; + ConfirmationModal?: JSX.Element; };