☑️ Refacto "Select All/Unselect all" on indexes (#5320)

### Description

- Refacto "Select All/Unselect all" on indexes
- Add sequential mass deletion from front end (limited to 10k records)
- Fixed coverage with new unit tests on new useFetchAllRecordIds hook
and other utils

### Refs

Closes #4397 
Closes #5169

### Demo


https://github.com/twentyhq/twenty/assets/26528466/2658ad2c-827e-4670-b42b-3092e268ff32

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
gitstart-twenty
2024-07-15 06:26:10 -04:00
committed by GitHub
parent e5d76a33ed
commit d560d25736
40 changed files with 1349 additions and 433 deletions

View File

@ -1,15 +1,17 @@
import { useEffect, useRef } from 'react';
import styled from '@emotion/styled';
import { useEffect, useRef } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/contextMenuIsOpenState';
import SharedNavigationModal from '@/ui/navigation/shared/components/NavigationModal';
import { isDefined } from '~/utils/isDefined';
import { ActionBarItem } from './ActionBarItem';
type ActionBarProps = {
selectedIds?: string[];
totalNumberOfSelectedRecords?: number;
};
const StyledContainerActionBar = styled.div`
@ -40,7 +42,10 @@ const StyledLabel = styled.div`
padding-right: ${({ theme }) => theme.spacing(2)};
`;
export const ActionBar = ({ selectedIds = [] }: ActionBarProps) => {
export const ActionBar = ({
selectedIds = [],
totalNumberOfSelectedRecords,
}: ActionBarProps) => {
const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState);
useEffect(() => {
@ -57,6 +62,12 @@ export const ActionBar = ({ selectedIds = [] }: ActionBarProps) => {
return null;
}
const selectedNumberLabel =
totalNumberOfSelectedRecords ?? selectedIds?.length;
const showSelectedNumberLabel =
isDefined(totalNumberOfSelectedRecords) || Array.isArray(selectedIds);
return (
<>
<StyledContainerActionBar
@ -64,8 +75,8 @@ export const ActionBar = ({ selectedIds = [] }: ActionBarProps) => {
className="action-bar"
ref={wrapperRef}
>
{selectedIds && (
<StyledLabel>{selectedIds.length} selected:</StyledLabel>
{showSelectedNumberLabel && (
<StyledLabel>{selectedNumberLabel} selected:</StyledLabel>
)}
{actionBarEntries.map((item, index) => (
<ActionBarItem key={index} item={item} />

View File

@ -1,12 +1,5 @@
import { IconComponent } from 'twenty-ui';
import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry';
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
export type ActionBarEntry = {
label: string;
Icon: IconComponent;
accent?: MenuItemAccent;
onClick?: () => void;
export type ActionBarEntry = ContextMenuEntry & {
subActions?: ActionBarEntry[];
ConfirmationModal?: JSX.Element;
};

View File

@ -1,3 +1,4 @@
import { MouseEvent, ReactNode } from 'react';
import { IconComponent } from 'twenty-ui';
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
@ -6,5 +7,6 @@ export type ContextMenuEntry = {
label: string;
Icon: IconComponent;
accent?: MenuItemAccent;
onClick: () => void;
onClick?: (event?: MouseEvent<HTMLElement>) => void;
ConfirmationModal?: ReactNode;
};