diff --git a/front/package.json b/front/package.json index 594e22913..9b8bf5f9a 100644 --- a/front/package.json +++ b/front/package.json @@ -13,7 +13,6 @@ "@hello-pangea/dnd": "^16.2.0", "@hookform/resolvers": "^3.1.1", "@tabler/icons-react": "^2.20.0", - "@tanstack/react-table": "^8.8.5", "@types/node": "^16.18.4", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", diff --git a/front/src/modules/comments/hooks/useOpenCreateCommentDrawerForSelectedRowIds.ts b/front/src/modules/comments/hooks/useOpenCreateCommentDrawerForSelectedRowIds.ts index 7a5fe26c2..7596dec0e 100644 --- a/front/src/modules/comments/hooks/useOpenCreateCommentDrawerForSelectedRowIds.ts +++ b/front/src/modules/comments/hooks/useOpenCreateCommentDrawerForSelectedRowIds.ts @@ -8,7 +8,7 @@ import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope'; import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; import { GET_PEOPLE } from '@/people/services'; import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; -import { selectedRowIdsState } from '@/ui/tables/states/selectedRowIdsState'; +import { selectedRowIdsSelector } from '@/ui/tables/states/selectedRowIdsSelector'; import { CommentableType, useCreateCommentThreadMutation, @@ -36,7 +36,7 @@ export function useOpenCreateCommentThreadDrawerForSelectedRowIds() { commentableEntityArrayState, ); - const selectedEntityIds = useRecoilValue(selectedRowIdsState); + const selectedEntityIds = useRecoilValue(selectedRowIdsSelector); return function openCreateCommentDrawerForSelectedRowIds( entityType: CommentableType, diff --git a/front/src/modules/companies/table/components/CompanyEntityTableDataMocked.tsx b/front/src/modules/companies/table/components/CompanyEntityTableDataMocked.tsx new file mode 100644 index 000000000..33e702ee0 --- /dev/null +++ b/front/src/modules/companies/table/components/CompanyEntityTableDataMocked.tsx @@ -0,0 +1,36 @@ +import { useEffect } from 'react'; +import { useRecoilState } from 'recoil'; + +import { isFetchingEntityTableDataState } from '@/ui/tables/states/isFetchingEntityTableDataState'; +import { tableRowIdsState } from '@/ui/tables/states/tableRowIdsState'; +import { mockedCompaniesData } from '~/testing/mock-data/companies'; + +import { useSetCompanyEntityTable } from '../hooks/useSetCompanyEntityTable'; + +export function CompanyEntityTableDataMocked() { + const [, setTableRowIds] = useRecoilState(tableRowIdsState); + + const [, setIsFetchingEntityTableData] = useRecoilState( + isFetchingEntityTableDataState, + ); + + const setCompanyEntityTable = useSetCompanyEntityTable(); + + useEffect(() => { + const companyIds = mockedCompaniesData.map((company) => company.id); + + setTableRowIds((currentRowIds) => { + if (JSON.stringify(currentRowIds) !== JSON.stringify(companyIds)) { + return companyIds; + } + + return currentRowIds; + }); + + setCompanyEntityTable(mockedCompaniesData); + + setIsFetchingEntityTableData(false); + }, [setCompanyEntityTable, setIsFetchingEntityTableData, setTableRowIds]); + + return <>; +} diff --git a/front/src/modules/ui/components/editable-cell/types/EditableCellDateEditMode.tsx b/front/src/modules/ui/components/editable-cell/types/EditableCellDateEditMode.tsx index a258e2ae7..64fadd77e 100644 --- a/front/src/modules/ui/components/editable-cell/types/EditableCellDateEditMode.tsx +++ b/front/src/modules/ui/components/editable-cell/types/EditableCellDateEditMode.tsx @@ -1,3 +1,7 @@ +import { Key } from 'ts-key-enum'; + +import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys'; +import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; import { InplaceInputDateEditMode } from '@/ui/inplace-inputs/components/InplaceInputDateEditMode'; import { useEditableCell } from '../hooks/useEditableCell'; @@ -18,5 +22,14 @@ export function EditableCellDateEditMode({ closeEditableCell(); } + useScopedHotkeys( + Key.Escape, + () => { + closeEditableCell(); + }, + InternalHotkeysScope.CellDateEditMode, + [closeEditableCell], + ); + return ; } diff --git a/front/src/modules/ui/components/editable-cell/types/EditableCellDoubleText.tsx b/front/src/modules/ui/components/editable-cell/types/EditableCellDoubleText.tsx index 4378f36a8..ac85dabe8 100644 --- a/front/src/modules/ui/components/editable-cell/types/EditableCellDoubleText.tsx +++ b/front/src/modules/ui/components/editable-cell/types/EditableCellDoubleText.tsx @@ -1,4 +1,4 @@ -import { ReactElement, useState } from 'react'; +import { ReactElement, useEffect, useState } from 'react'; import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope'; @@ -29,6 +29,11 @@ export function EditableCellDoubleText({ const [firstInternalValue, setFirstInternalValue] = useState(firstValue); const [secondInternalValue, setSecondInternalValue] = useState(secondValue); + useEffect(() => { + setFirstInternalValue(firstValue); + setSecondInternalValue(secondValue); + }, [firstValue, secondValue]); + function handleOnChange(firstValue: string, secondValue: string): void { setFirstInternalValue(firstValue); setSecondInternalValue(secondValue); diff --git a/front/src/modules/ui/components/table/EntityTableBody.tsx b/front/src/modules/ui/components/table/EntityTableBody.tsx index b23ad8cd7..2f749007b 100644 --- a/front/src/modules/ui/components/table/EntityTableBody.tsx +++ b/front/src/modules/ui/components/table/EntityTableBody.tsx @@ -17,17 +17,13 @@ export function EntityTableBody({ columns }: { columns: Array }) { return ( - {!isFetchingEntityTableData ? ( - rowIds.map((rowId, index) => ( - - - - )) - ) : ( - - loading... - - )} + {!isFetchingEntityTableData + ? rowIds.map((rowId, index) => ( + + + + )) + : null} ); } diff --git a/front/src/modules/ui/components/table/EntityTableCell.tsx b/front/src/modules/ui/components/table/EntityTableCell.tsx index 08067932d..94ef72a89 100644 --- a/front/src/modules/ui/components/table/EntityTableCell.tsx +++ b/front/src/modules/ui/components/table/EntityTableCell.tsx @@ -1,11 +1,11 @@ import { useEffect } from 'react'; -import { useRecoilState, useSetRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState'; +import { useCurrentRowSelected } from '@/ui/tables/hooks/useCurrentRowSelected'; import { CellContext } from '@/ui/tables/states/CellContext'; import { contextMenuPositionState } from '@/ui/tables/states/contextMenuPositionState'; import { currentColumnNumberScopedState } from '@/ui/tables/states/currentColumnNumberScopedState'; -import { currentRowSelectionState } from '@/ui/tables/states/rowSelectionState'; export function EntityTableCell({ rowId, @@ -18,8 +18,6 @@ export function EntityTableCell({ cellIndex: number; children: React.ReactNode; }) { - const [, setCurrentRowSelection] = useRecoilState(currentRowSelectionState); - const [, setCurrentColumnNumber] = useRecoilScopedState( currentColumnNumberScopedState, CellContext, @@ -31,9 +29,12 @@ export function EntityTableCell({ const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); - function handleContextMenu(event: React.MouseEvent, id: string) { + const { setCurrentRowSelected } = useCurrentRowSelected(); + + function handleContextMenu(event: React.MouseEvent) { event.preventDefault(); - setCurrentRowSelection((prev) => ({ ...prev, [id]: true })); + + setCurrentRowSelected(true); setContextMenuPosition({ x: event.clientX, @@ -43,7 +44,7 @@ export function EntityTableCell({ return ( handleContextMenu(event, rowId)} + onContextMenu={(event) => handleContextMenu(event)} style={{ width: size, minWidth: size, diff --git a/front/src/modules/ui/components/table/EntityTableRow.tsx b/front/src/modules/ui/components/table/EntityTableRow.tsx index a2648605c..85d809e96 100644 --- a/front/src/modules/ui/components/table/EntityTableRow.tsx +++ b/front/src/modules/ui/components/table/EntityTableRow.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; +import { useRecoilValue } from 'recoil'; import { TableColumn } from '@/people/table/components/peopleColumns'; import { RecoilScope } from '@/recoil-scope/components/RecoilScope'; @@ -8,8 +8,8 @@ import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState' import { CellContext } from '@/ui/tables/states/CellContext'; import { currentRowEntityIdScopedState } from '@/ui/tables/states/currentRowEntityIdScopedState'; import { currentRowNumberScopedState } from '@/ui/tables/states/currentRowNumberScopedState'; +import { isRowSelectedFamilyState } from '@/ui/tables/states/isRowSelectedFamilyState'; import { RowContext } from '@/ui/tables/states/RowContext'; -import { currentRowSelectionState } from '@/ui/tables/states/rowSelectionState'; import { CheckboxCell } from './CheckboxCell'; import { EntityTableCell } from './EntityTableCell'; @@ -28,12 +28,13 @@ export function EntityTableRow({ rowId: string; index: number; }) { - const [currentRowSelection] = useRecoilState(currentRowSelectionState); const [currentRowEntityId, setCurrentRowEntityId] = useRecoilScopedState( currentRowEntityIdScopedState, RowContext, ); + const isCurrentRowSelected = useRecoilValue(isRowSelectedFamilyState(rowId)); + const [, setCurrentRowNumber] = useRecoilScopedState( currentRowNumberScopedState, RowContext, @@ -53,7 +54,7 @@ export function EntityTableRow({ diff --git a/front/src/modules/ui/components/table/action-bar/EntityTableActionBar.tsx b/front/src/modules/ui/components/table/action-bar/EntityTableActionBar.tsx index 9d8f97729..8e44ee820 100644 --- a/front/src/modules/ui/components/table/action-bar/EntityTableActionBar.tsx +++ b/front/src/modules/ui/components/table/action-bar/EntityTableActionBar.tsx @@ -2,14 +2,14 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; import { ActionBar } from '@/ui/components/action-bar/ActionBar'; -import { selectedRowIdsState } from '@/ui/tables/states/selectedRowIdsState'; +import { selectedRowIdsSelector } from '@/ui/tables/states/selectedRowIdsSelector'; type OwnProps = { children: React.ReactNode | React.ReactNode[]; }; export function EntityTableActionBar({ children }: OwnProps) { - const selectedRowIds = useRecoilValue(selectedRowIdsState); + const selectedRowIds = useRecoilValue(selectedRowIdsSelector); return {children}; } diff --git a/front/src/modules/ui/tables/hooks/useCurrentRowSelected.ts b/front/src/modules/ui/tables/hooks/useCurrentRowSelected.ts index cc46df59f..46ec08fbd 100644 --- a/front/src/modules/ui/tables/hooks/useCurrentRowSelected.ts +++ b/front/src/modules/ui/tables/hooks/useCurrentRowSelected.ts @@ -1,7 +1,6 @@ import { useRecoilCallback, useRecoilState } from 'recoil'; import { isRowSelectedFamilyState } from '../states/isRowSelectedFamilyState'; -import { numberOfSelectedRowState } from '../states/numberOfSelectedRowState'; import { useCurrentRowEntityId } from './useCurrentEntityId'; @@ -21,15 +20,9 @@ export function useCurrentRowSelected() { .getLoadable(isRowSelectedFamilyState(currentRowId)) .valueOrThrow(); - const numberOfSelectedRow = snapshot - .getLoadable(numberOfSelectedRowState) - .valueOrThrow(); - if (newSelectedState && !isRowSelected) { - set(numberOfSelectedRowState, numberOfSelectedRow + 1); set(isRowSelectedFamilyState(currentRowId), true); } else if (!newSelectedState && isRowSelected) { - set(numberOfSelectedRowState, numberOfSelectedRow - 1); set(isRowSelectedFamilyState(currentRowId), false); } }, diff --git a/front/src/modules/ui/tables/hooks/useResetTableRowSelection.ts b/front/src/modules/ui/tables/hooks/useResetTableRowSelection.ts index d3065651a..543704117 100644 --- a/front/src/modules/ui/tables/hooks/useResetTableRowSelection.ts +++ b/front/src/modules/ui/tables/hooks/useResetTableRowSelection.ts @@ -1,17 +1,20 @@ -import { useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useRecoilCallback } from 'recoil'; -import { currentRowSelectionState } from '../states/rowSelectionState'; +import { isRowSelectedFamilyState } from '../states/isRowSelectedFamilyState'; +import { tableRowIdsState } from '../states/tableRowIdsState'; export function useResetTableRowSelection() { - const setCurrentRowSelectionState = useSetRecoilState( - currentRowSelectionState, - ); + return useRecoilCallback( + ({ snapshot, set }) => + () => { + const tableRowIds = snapshot + .getLoadable(tableRowIdsState) + .valueOrThrow(); - return useCallback( - function resetCurrentRowSelection() { - setCurrentRowSelectionState({}); - }, - [setCurrentRowSelectionState], + for (const rowId of tableRowIds) { + set(isRowSelectedFamilyState(rowId), false); + } + }, + [], ); } diff --git a/front/src/modules/ui/tables/hooks/useSelectAllRows.ts b/front/src/modules/ui/tables/hooks/useSelectAllRows.ts index e644ed5ce..4868236d6 100644 --- a/front/src/modules/ui/tables/hooks/useSelectAllRows.ts +++ b/front/src/modules/ui/tables/hooks/useSelectAllRows.ts @@ -2,8 +2,6 @@ import { useRecoilCallback, useRecoilValue } from 'recoil'; import { allRowsSelectedStatusSelector } from '../states/allRowsSelectedStatusSelector'; import { isRowSelectedFamilyState } from '../states/isRowSelectedFamilyState'; -import { numberOfSelectedRowState } from '../states/numberOfSelectedRowState'; -import { numberOfTableRowsSelectorState } from '../states/numberOfTableRowsSelectorState'; import { tableRowIdsState } from '../states/tableRowIdsState'; export function useSelectAllRows() { @@ -16,23 +14,15 @@ export function useSelectAllRows() { .getLoadable(allRowsSelectedStatusSelector) .valueOrThrow(); - const numberOfRows = snapshot - .getLoadable(numberOfTableRowsSelectorState) - .valueOrThrow(); - const tableRowIds = snapshot .getLoadable(tableRowIdsState) .valueOrThrow(); if (allRowsSelectedStatus === 'none') { - set(numberOfSelectedRowState, numberOfRows); - for (const rowId of tableRowIds) { set(isRowSelectedFamilyState(rowId), true); } } else { - set(numberOfSelectedRowState, 0); - for (const rowId of tableRowIds) { set(isRowSelectedFamilyState(rowId), false); } diff --git a/front/src/modules/ui/tables/states/allRowsSelectedStatusSelector.ts b/front/src/modules/ui/tables/states/allRowsSelectedStatusSelector.ts index 09ebde969..b1c551952 100644 --- a/front/src/modules/ui/tables/states/allRowsSelectedStatusSelector.ts +++ b/front/src/modules/ui/tables/states/allRowsSelectedStatusSelector.ts @@ -2,15 +2,17 @@ import { selector } from 'recoil'; import { AllRowsSelectedStatus } from '../types/AllRowSelectedStatus'; -import { numberOfSelectedRowState } from './numberOfSelectedRowState'; import { numberOfTableRowsSelectorState } from './numberOfTableRowsSelectorState'; +import { selectedRowIdsSelector } from './selectedRowIdsSelector'; export const allRowsSelectedStatusSelector = selector({ key: 'allRowsSelectedStatusSelector', get: ({ get }) => { const numberOfRows = get(numberOfTableRowsSelectorState); - const numberOfSelectedRows = get(numberOfSelectedRowState); + const selectedRowIds = get(selectedRowIdsSelector); + + const numberOfSelectedRows = selectedRowIds.length; const allRowsSelectedStatus = numberOfSelectedRows === 0 diff --git a/front/src/modules/ui/tables/states/numberOfSelectedRowState.ts b/front/src/modules/ui/tables/states/numberOfSelectedRowState.ts deleted file mode 100644 index 2169e9fbb..000000000 --- a/front/src/modules/ui/tables/states/numberOfSelectedRowState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { atom } from 'recoil'; - -export const numberOfSelectedRowState = atom({ - key: 'numberOfSelectedRowState', - default: 0, -}); diff --git a/front/src/modules/ui/tables/states/rowSelectionState.ts b/front/src/modules/ui/tables/states/rowSelectionState.ts deleted file mode 100644 index acf8943f6..000000000 --- a/front/src/modules/ui/tables/states/rowSelectionState.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { RowSelectionState } from '@tanstack/react-table'; -import { atom } from 'recoil'; - -export const currentRowSelectionState = atom({ - key: 'currentRowSelectionState', - default: {}, -}); diff --git a/front/src/modules/ui/tables/states/selectedRowIdsSelector.ts b/front/src/modules/ui/tables/states/selectedRowIdsSelector.ts new file mode 100644 index 000000000..8cd0027c8 --- /dev/null +++ b/front/src/modules/ui/tables/states/selectedRowIdsSelector.ts @@ -0,0 +1,15 @@ +import { selector } from 'recoil'; + +import { isRowSelectedFamilyState } from './isRowSelectedFamilyState'; +import { tableRowIdsState } from './tableRowIdsState'; + +export const selectedRowIdsSelector = selector({ + key: 'selectedRowIdsSelector', + get: ({ get }) => { + const rowIds = get(tableRowIdsState); + + return rowIds.filter( + (rowId) => get(isRowSelectedFamilyState(rowId)) === true, + ); + }, +}); diff --git a/front/src/modules/ui/tables/states/selectedRowIdsState.ts b/front/src/modules/ui/tables/states/selectedRowIdsState.ts deleted file mode 100644 index ce69c8ef8..000000000 --- a/front/src/modules/ui/tables/states/selectedRowIdsState.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { selector } from 'recoil'; - -import { currentRowSelectionState } from './rowSelectionState'; - -export const selectedRowIdsState = selector({ - key: 'selectedRowIdsState', - get: ({ get }) => { - const currentRowSelection = get(currentRowSelectionState); - - return Object.keys(currentRowSelection).filter( - (key) => currentRowSelection[key] === true, - ); - }, -}); diff --git a/front/src/pages/companies/CompanyTableMockMode.tsx b/front/src/pages/companies/CompanyTableMockMode.tsx index 5a596d575..5fe478b0f 100644 --- a/front/src/pages/companies/CompanyTableMockMode.tsx +++ b/front/src/pages/companies/CompanyTableMockMode.tsx @@ -1,6 +1,7 @@ import { IconList } from '@tabler/icons-react'; import { companyColumns } from '@/companies/table/components/companyColumns'; +import { CompanyEntityTableDataMocked } from '@/companies/table/components/CompanyEntityTableDataMocked'; import { EntityTable } from '@/ui/components/table/EntityTable'; import { HooksEntityTable } from '@/ui/components/table/HooksEntityTable'; @@ -10,6 +11,7 @@ import { availableSorts } from './companies-sorts'; export function CompanyTableMockMode() { return ( <> +