mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Implement shift + click selection
This commit is contained in:
parent
22ce5094d4
commit
c1fc52821b
|
@ -100,6 +100,7 @@ function DataTable<TData extends RowData>({
|
||||||
...restProps
|
...restProps
|
||||||
}: DataTableProps<TData>) {
|
}: DataTableProps<TData>) {
|
||||||
const [sorting, setSorting] = useState<SortingState>(initialSorting ? [initialSorting] : []);
|
const [sorting, setSorting] = useState<SortingState>(initialSorting ? [initialSorting] : []);
|
||||||
|
const [lastSelected, setLastSelected] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
const [pagination, setPagination] = useState<PaginationState>({
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
|
@ -147,6 +148,7 @@ function DataTable<TData extends RowData>({
|
||||||
enableRowSelection={enableRowSelection}
|
enableRowSelection={enableRowSelection}
|
||||||
enableSorting={enableSorting}
|
enableSorting={enableSorting}
|
||||||
headPosition={headPosition}
|
headPosition={headPosition}
|
||||||
|
setLastSelected={setLastSelected}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
@ -155,6 +157,8 @@ function DataTable<TData extends RowData>({
|
||||||
dense={dense}
|
dense={dense}
|
||||||
conditionalRowStyles={conditionalRowStyles}
|
conditionalRowStyles={conditionalRowStyles}
|
||||||
enableRowSelection={enableRowSelection}
|
enableRowSelection={enableRowSelection}
|
||||||
|
lastSelected={lastSelected}
|
||||||
|
setLastSelected={setLastSelected}
|
||||||
onRowClicked={onRowClicked}
|
onRowClicked={onRowClicked}
|
||||||
onRowDoubleClicked={onRowDoubleClicked}
|
onRowDoubleClicked={onRowDoubleClicked}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -4,9 +4,15 @@ import CheckboxTristate from '@/components/ui/CheckboxTristate';
|
||||||
|
|
||||||
interface SelectAllProps<TData> {
|
interface SelectAllProps<TData> {
|
||||||
table: Table<TData>;
|
table: Table<TData>;
|
||||||
|
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectAll<TData>({ table }: SelectAllProps<TData>) {
|
function SelectAll<TData>({ table, setLastSelected }: SelectAllProps<TData>) {
|
||||||
|
function handleChange(value: boolean | null) {
|
||||||
|
setLastSelected(undefined);
|
||||||
|
table.toggleAllPageRowsSelected(value !== false);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxTristate
|
<CheckboxTristate
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
@ -14,7 +20,7 @@ function SelectAll<TData>({ table }: SelectAllProps<TData>) {
|
||||||
value={
|
value={
|
||||||
!table.getIsAllPageRowsSelected() && table.getIsSomePageRowsSelected() ? null : table.getIsAllPageRowsSelected()
|
!table.getIsAllPageRowsSelected() && table.getIsSomePageRowsSelected() ? null : table.getIsAllPageRowsSelected()
|
||||||
}
|
}
|
||||||
setValue={value => table.toggleAllPageRowsSelected(value !== false)}
|
setValue={handleChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,16 @@ import Checkbox from '@/components/ui/Checkbox';
|
||||||
|
|
||||||
interface SelectRowProps<TData> {
|
interface SelectRowProps<TData> {
|
||||||
row: Row<TData>;
|
row: Row<TData>;
|
||||||
|
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectRow<TData>({ row }: SelectRowProps<TData>) {
|
function SelectRow<TData>({ row, setLastSelected }: SelectRowProps<TData>) {
|
||||||
return <Checkbox tabIndex={-1} value={row.getIsSelected()} setValue={row.getToggleSelectedHandler()} />;
|
function handleChange(value: boolean) {
|
||||||
|
setLastSelected(row.id);
|
||||||
|
row.toggleSelected(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Checkbox tabIndex={-1} value={row.getIsSelected()} setValue={handleChange} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SelectRow;
|
export default SelectRow;
|
||||||
|
|
|
@ -8,6 +8,10 @@ interface TableBodyProps<TData> {
|
||||||
dense?: boolean;
|
dense?: boolean;
|
||||||
enableRowSelection?: boolean;
|
enableRowSelection?: boolean;
|
||||||
conditionalRowStyles?: IConditionalStyle<TData>[];
|
conditionalRowStyles?: IConditionalStyle<TData>[];
|
||||||
|
|
||||||
|
lastSelected: string | undefined;
|
||||||
|
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
|
|
||||||
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
||||||
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
onRowDoubleClicked?: (rowData: TData, event: React.MouseEvent<Element, MouseEvent>) => void;
|
||||||
}
|
}
|
||||||
|
@ -17,15 +21,34 @@ function TableBody<TData>({
|
||||||
dense,
|
dense,
|
||||||
enableRowSelection,
|
enableRowSelection,
|
||||||
conditionalRowStyles,
|
conditionalRowStyles,
|
||||||
|
lastSelected,
|
||||||
|
setLastSelected,
|
||||||
onRowClicked,
|
onRowClicked,
|
||||||
onRowDoubleClicked
|
onRowDoubleClicked
|
||||||
}: TableBodyProps<TData>) {
|
}: TableBodyProps<TData>) {
|
||||||
function handleRowClicked(row: Row<TData>, event: React.MouseEvent<Element, MouseEvent>) {
|
function handleRowClicked(target: Row<TData>, event: React.MouseEvent<Element, MouseEvent>) {
|
||||||
if (onRowClicked) {
|
if (onRowClicked) {
|
||||||
onRowClicked(row.original, event);
|
onRowClicked(target.original, event);
|
||||||
}
|
}
|
||||||
if (enableRowSelection && row.getCanSelect()) {
|
if (enableRowSelection && target.getCanSelect()) {
|
||||||
row.getToggleSelectedHandler()(!row.getIsSelected());
|
if (event.shiftKey && !!lastSelected && lastSelected !== target.id) {
|
||||||
|
const { rows, rowsById } = table.getRowModel();
|
||||||
|
const lastIndex = rowsById[lastSelected].index;
|
||||||
|
const currentIndex = target.index;
|
||||||
|
const toggleRows = rows.slice(
|
||||||
|
lastIndex > currentIndex ? currentIndex : lastIndex + 1,
|
||||||
|
lastIndex > currentIndex ? lastIndex : currentIndex + 1
|
||||||
|
);
|
||||||
|
const newSelection: { [key: string]: boolean } = {};
|
||||||
|
toggleRows.forEach(row => {
|
||||||
|
newSelection[row.id] = !target.getIsSelected();
|
||||||
|
});
|
||||||
|
table.setRowSelection(prev => ({ ...prev, ...newSelection }));
|
||||||
|
setLastSelected(undefined);
|
||||||
|
} else {
|
||||||
|
setLastSelected(target.id);
|
||||||
|
target.toggleSelected(!target.getIsSelected());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +76,7 @@ function TableBody<TData>({
|
||||||
>
|
>
|
||||||
{enableRowSelection ? (
|
{enableRowSelection ? (
|
||||||
<td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'>
|
<td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'>
|
||||||
<SelectRow row={row} />
|
<SelectRow row={row} setLastSelected={setLastSelected} />
|
||||||
</td>
|
</td>
|
||||||
) : null}
|
) : null}
|
||||||
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
|
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
|
||||||
|
|
|
@ -8,9 +8,16 @@ interface TableHeaderProps<TData> {
|
||||||
headPosition?: string;
|
headPosition?: string;
|
||||||
enableRowSelection?: boolean;
|
enableRowSelection?: boolean;
|
||||||
enableSorting?: boolean;
|
enableSorting?: boolean;
|
||||||
|
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableHeader<TData>({ table, headPosition, enableRowSelection, enableSorting }: TableHeaderProps<TData>) {
|
function TableHeader<TData>({
|
||||||
|
table,
|
||||||
|
headPosition,
|
||||||
|
enableRowSelection,
|
||||||
|
enableSorting,
|
||||||
|
setLastSelected
|
||||||
|
}: TableHeaderProps<TData>) {
|
||||||
return (
|
return (
|
||||||
<thead
|
<thead
|
||||||
className='clr-app shadow-border'
|
className='clr-app shadow-border'
|
||||||
|
@ -23,7 +30,7 @@ function TableHeader<TData>({ table, headPosition, enableRowSelection, enableSor
|
||||||
<tr key={headerGroup.id}>
|
<tr key={headerGroup.id}>
|
||||||
{enableRowSelection ? (
|
{enableRowSelection ? (
|
||||||
<th className='pl-3 pr-1 align-middle'>
|
<th className='pl-3 pr-1 align-middle'>
|
||||||
<SelectAll table={table} />
|
<SelectAll table={table} setLastSelected={setLastSelected} />
|
||||||
</th>
|
</th>
|
||||||
) : null}
|
) : null}
|
||||||
{headerGroup.headers.map((header: Header<TData, unknown>) => (
|
{headerGroup.headers.map((header: Header<TData, unknown>) => (
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useLayoutEffect, useMemo, useState } from 'react';
|
import { useLayoutEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { type RowSelectionState } from '@/components/ui/DataTable';
|
|
||||||
import SelectedCounter from '@/components/info/SelectedCounter';
|
import SelectedCounter from '@/components/info/SelectedCounter';
|
||||||
|
import { type RowSelectionState } from '@/components/ui/DataTable';
|
||||||
import { useConceptTheme } from '@/context/ThemeContext';
|
import { useConceptTheme } from '@/context/ThemeContext';
|
||||||
import { ConstituentaID, CstType } from '@/models/rsform';
|
import { ConstituentaID, CstType } from '@/models/rsform';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user