4410-feat(front): Implement Confirmation Prompt for Multiple Record Deletion (#4514)
* 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 <felix.malfait@gmail.com>
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ import {
|
|||||||
IconPuzzle,
|
IconPuzzle,
|
||||||
IconTrash,
|
IconTrash,
|
||||||
} from '@/ui/display/icon';
|
} from '@/ui/display/icon';
|
||||||
|
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||||
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
|
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
|
||||||
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
|
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
|
||||||
import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry';
|
import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry';
|
||||||
@ -36,6 +37,8 @@ export const useRecordActionBar = ({
|
|||||||
}: useRecordActionBarProps) => {
|
}: useRecordActionBarProps) => {
|
||||||
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
|
const setContextMenuEntries = useSetRecoilState(contextMenuEntriesState);
|
||||||
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
|
const setActionBarEntriesState = useSetRecoilState(actionBarEntriesState);
|
||||||
|
const [isDeleteRecordsModalOpen, setIsDeleteRecordsModalOpen] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
const { createFavorite, favorites, deleteFavorite } = useFavorites();
|
const { createFavorite, favorites, deleteFavorite } = useFavorites();
|
||||||
|
|
||||||
@ -106,10 +109,26 @@ export const useRecordActionBar = ({
|
|||||||
const baseActions: ContextMenuEntry[] = useMemo(
|
const baseActions: ContextMenuEntry[] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
label: `Delete (${selectedRecordIds.length})`,
|
label: 'Delete',
|
||||||
Icon: IconTrash,
|
Icon: IconTrash,
|
||||||
accent: 'danger',
|
accent: 'danger',
|
||||||
onClick: () => handleDeleteClick(),
|
onClick: () => setIsDeleteRecordsModalOpen(true),
|
||||||
|
ConfirmationModal: (
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={isDeleteRecordsModalOpen}
|
||||||
|
setIsOpen={setIsDeleteRecordsModalOpen}
|
||||||
|
title={`Delete ${selectedRecordIds.length} ${
|
||||||
|
selectedRecordIds.length === 1 ? `record` : 'records'
|
||||||
|
}`}
|
||||||
|
subtitle={`This action cannot be undone. This will permanently delete ${
|
||||||
|
selectedRecordIds.length === 1 ? 'this record' : 'these records'
|
||||||
|
}`}
|
||||||
|
onConfirmClick={() => handleDeleteClick()}
|
||||||
|
deleteButtonText={`Delete ${
|
||||||
|
selectedRecordIds.length > 1 ? 'Records' : 'Record'
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`,
|
label: `${progress === undefined ? `Export` : `Export (${progress}%)`}`,
|
||||||
@ -118,7 +137,14 @@ export const useRecordActionBar = ({
|
|||||||
onClick: () => download(),
|
onClick: () => download(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[handleDeleteClick, download, progress, selectedRecordIds],
|
[
|
||||||
|
handleDeleteClick,
|
||||||
|
download,
|
||||||
|
progress,
|
||||||
|
selectedRecordIds,
|
||||||
|
isDeleteRecordsModalOpen,
|
||||||
|
setIsDeleteRecordsModalOpen,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled(
|
const dataExecuteQuickActionOnmentEnabled = useIsFeatureEnabled(
|
||||||
|
|||||||
@ -18,5 +18,5 @@ export const RecordBoardActionBar = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ActionBar />;
|
return <ActionBar selectedIds={selectedRecordIds} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,5 +16,5 @@ export const RecordTableActionBar = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ActionBar />;
|
return <ActionBar selectedIds={selectedRowIds} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
@ -7,6 +7,10 @@ import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/cont
|
|||||||
|
|
||||||
import { ActionBarItem } from './ActionBarItem';
|
import { ActionBarItem } from './ActionBarItem';
|
||||||
|
|
||||||
|
type ActionBarProps = {
|
||||||
|
selectedIds?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
const StyledContainerActionBar = styled.div`
|
const StyledContainerActionBar = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.secondary};
|
background: ${({ theme }) => theme.background.secondary};
|
||||||
@ -27,7 +31,15 @@ const StyledContainerActionBar = styled.div`
|
|||||||
z-index: 1;
|
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 contextMenuIsOpen = useRecoilValue(contextMenuIsOpenState);
|
||||||
const actionBarEntries = useRecoilValue(actionBarEntriesState);
|
const actionBarEntries = useRecoilValue(actionBarEntriesState);
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
@ -37,14 +49,22 @@ export const ActionBar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainerActionBar
|
<>
|
||||||
data-select-disable
|
<StyledContainerActionBar
|
||||||
className="action-bar"
|
data-select-disable
|
||||||
ref={wrapperRef}
|
className="action-bar"
|
||||||
>
|
ref={wrapperRef}
|
||||||
{actionBarEntries.map((item, index) => (
|
>
|
||||||
<ActionBarItem key={index} item={item} />
|
{selectedIds && (
|
||||||
))}
|
<StyledLabel>{selectedIds.length} selected:</StyledLabel>
|
||||||
</StyledContainerActionBar>
|
)}
|
||||||
|
{actionBarEntries.map((item, index) => (
|
||||||
|
<ActionBarItem key={index} item={item} />
|
||||||
|
))}
|
||||||
|
</StyledContainerActionBar>
|
||||||
|
<div data-select-disable className="action-bar">
|
||||||
|
{actionBarEntries[0]?.ConfirmationModal}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,4 +7,5 @@ export type ActionBarEntry = {
|
|||||||
accent?: MenuItemAccent;
|
accent?: MenuItemAccent;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
subActions?: ActionBarEntry[];
|
subActions?: ActionBarEntry[];
|
||||||
|
ConfirmationModal?: JSX.Element;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user