From 94ea9835a9fd87e433758f80fe382344df03a890 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 8 May 2023 10:58:53 +0200 Subject: [PATCH] Enable multi-selection on table views (#112) * Enable multi-selection on table views * Enable multi-selection --- front/src/components/form/Checkbox.tsx | 16 ++++++++++- .../components/table/SelectAllCheckbox.tsx | 18 ++++++++++++ front/src/components/table/Table.tsx | 14 ++++++++++ front/src/pages/companies/Companies.tsx | 3 ++ front/src/pages/companies/companies-table.tsx | 22 ++++++++++----- front/src/pages/people/People.tsx | 3 ++ front/src/pages/people/people-table.tsx | 28 ++++++++++++------- 7 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 front/src/components/table/SelectAllCheckbox.tsx diff --git a/front/src/components/form/Checkbox.tsx b/front/src/components/form/Checkbox.tsx index c9bd10266..51671dfca 100644 --- a/front/src/components/form/Checkbox.tsx +++ b/front/src/components/form/Checkbox.tsx @@ -4,6 +4,9 @@ import styled from '@emotion/styled'; type OwnProps = { name: string; id: string; + checked?: boolean; + indeterminate?: boolean; + onChange?: (event: React.ChangeEvent) => void; }; const StyledContainer = styled.span` @@ -28,14 +31,25 @@ const StyledContainer = styled.span` } `; -function Checkbox({ name, id }: OwnProps) { +function Checkbox({ name, id, checked, onChange, indeterminate }: OwnProps) { + const ref = React.useRef(null); + React.useEffect(() => { + if (ref.current === null) return; + if (typeof indeterminate === 'boolean') { + ref.current.indeterminate = !checked && indeterminate; + } + }, [ref, indeterminate, checked]); + return ( ); diff --git a/front/src/components/table/SelectAllCheckbox.tsx b/front/src/components/table/SelectAllCheckbox.tsx new file mode 100644 index 000000000..bc88856e8 --- /dev/null +++ b/front/src/components/table/SelectAllCheckbox.tsx @@ -0,0 +1,18 @@ +import Checkbox from '../form/Checkbox'; + +export const SelectAllCheckbox = ({ + indeterminate, + onChange, +}: { + indeterminate?: boolean; + onChange?: any; +} & React.HTMLProps) => { + return ( + + ); +}; diff --git a/front/src/components/table/Table.tsx b/front/src/components/table/Table.tsx index 04e95b097..a9a02c752 100644 --- a/front/src/components/table/Table.tsx +++ b/front/src/components/table/Table.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ColumnDef, + RowSelectionState, flexRender, getCoreRowModel, useReactTable, @@ -34,6 +35,7 @@ type OwnProps = { filter: FilterType | null, searchValue: string, ) => void; + onRowSelectionChange?: (rowSelection: RowSelectionState) => void; }; const StyledTable = styled.table` @@ -98,11 +100,23 @@ function Table({ onSortsUpdate, onFiltersUpdate, onFilterSearch, + onRowSelectionChange, }: OwnProps) { + const [rowSelection, setRowSelection] = React.useState({}); + + React.useEffect(() => { + onRowSelectionChange && onRowSelectionChange(rowSelection); + }, [rowSelection, onRowSelectionChange]); + const table = useReactTable({ data, columns, + state: { + rowSelection, + }, getCoreRowModel: getCoreRowModel(), + enableRowSelection: true, //enable row selection for all rows + onRowSelectionChange: setRowSelection, }); return ( diff --git a/front/src/pages/companies/Companies.tsx b/front/src/pages/companies/Companies.tsx index 23bb01d88..fff2275b5 100644 --- a/front/src/pages/companies/Companies.tsx +++ b/front/src/pages/companies/Companies.tsx @@ -99,6 +99,9 @@ function Companies() { setSearhInput(searchValue); setFilterSearch(filter); }} + onRowSelectionChange={(selectedRows) => { + console.log(selectedRows); + }} /> diff --git a/front/src/pages/companies/companies-table.tsx b/front/src/pages/companies/companies-table.tsx index dc454f2c3..4718ebe59 100644 --- a/front/src/pages/companies/companies-table.tsx +++ b/front/src/pages/companies/companies-table.tsx @@ -1,11 +1,10 @@ -import { createColumnHelper } from '@tanstack/react-table'; +import { CellContext, createColumnHelper } from '@tanstack/react-table'; import { Company, GraphqlQueryCompany, } from '../../interfaces/company.interface'; import { updateCompany } from '../../services/companies'; import ColumnHead from '../../components/table/ColumnHead'; -import Checkbox from '../../components/form/Checkbox'; import CompanyChip from '../../components/chips/CompanyChip'; import EditableText from '../../components/table/editable-cell/EditableText'; import { @@ -39,6 +38,8 @@ import EditableDate from '../../components/table/editable-cell/EditableDate'; import EditableRelation from '../../components/table/editable-cell/EditableRelation'; import { GraphqlQueryUser, PartialUser } from '../../interfaces/user.interface'; import { useMemo } from 'react'; +import { SelectAllCheckbox } from '../../components/table/SelectAllCheckbox'; +import Checkbox from '../../components/form/Checkbox'; export const availableSorts = [ { @@ -141,17 +142,24 @@ const columnHelper = createColumnHelper(); export const useCompaniesColumns = () => { return useMemo(() => { return [ - columnHelper.accessor('id', { - header: () => ( - + { + id: 'select', + header: ({ table }: any) => ( + ), - cell: (props) => ( + cell: (props: CellContext) => ( ), - }), + }, columnHelper.accessor('name', { header: () => ( } /> diff --git a/front/src/pages/people/People.tsx b/front/src/pages/people/People.tsx index 72096340c..e9375ac13 100644 --- a/front/src/pages/people/People.tsx +++ b/front/src/pages/people/People.tsx @@ -98,6 +98,9 @@ function People() { setSearchInput(searchValue); setFilterSearch(filter); }} + onRowSelectionChange={(selectedRows) => { + console.log(selectedRows); + }} /> } diff --git a/front/src/pages/people/people-table.tsx b/front/src/pages/people/people-table.tsx index 9ec0bff23..ebaf03286 100644 --- a/front/src/pages/people/people-table.tsx +++ b/front/src/pages/people/people-table.tsx @@ -8,7 +8,7 @@ import { FaUser, FaBuilding, } from 'react-icons/fa'; -import { createColumnHelper } from '@tanstack/react-table'; +import { CellContext, createColumnHelper } from '@tanstack/react-table'; import ColumnHead from '../../components/table/ColumnHead'; import Checkbox from '../../components/form/Checkbox'; import CompanyChip, { @@ -39,6 +39,7 @@ import EditableDate from '../../components/table/editable-cell/EditableDate'; import EditableRelation from '../../components/table/editable-cell/EditableRelation'; import { updatePerson } from '../../services/people'; import { useMemo } from 'react'; +import { SelectAllCheckbox } from '../../components/table/SelectAllCheckbox'; export const availableSorts = [ { @@ -247,17 +248,24 @@ const columnHelper = createColumnHelper(); export const usePeopleColumns = () => { return useMemo(() => { return [ - columnHelper.accessor('id', { - header: () => ( - - ), - cell: (props) => ( - ( + ), - }), + cell: (props: CellContext) => ( + + ), + }, columnHelper.accessor('firstname', { header: () => } />, cell: (props) => (