Skip to content

Commit

Permalink
refactored state sharing + real dnd for test
Browse files Browse the repository at this point in the history
  • Loading branch information
Zasa-san committed Jul 18, 2024
1 parent 07b849a commit b363cfe
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 160 deletions.
4 changes: 0 additions & 4 deletions app/react/App/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1704,10 +1704,6 @@ input[type="range"]::-ms-fill-lower {
grid-column: span 2 / span 2;
}

.float-start {
float: inline-start;
}

.float-right {
float: right;
}
Expand Down
10 changes: 5 additions & 5 deletions app/react/V2/Components/UI/TableV2/DnDComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { CSSProperties } from 'react';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { flexRender, Row } from '@tanstack/react-table';
import { t, Translate } from 'app/I18N';
import { Translate } from 'app/I18N';
import { RowWithId } from './Table';

const RowDragHandleCell = <T extends RowWithId<T>>({ row }: { row: Row<T> }) => {
Expand All @@ -14,21 +14,21 @@ const RowDragHandleCell = <T extends RowWithId<T>>({ row }: { row: Row<T> }) =>

const canExpand = row.originalSubRows;
const expanded = row.getIsExpanded();
const parentRow = row.getParentRow();

if (canExpand && expanded && isDragging) {
row.toggleExpanded();
}

return (
<button {...attributes} {...listeners} type="button" className="w-2 h-6 bg-primary-700">
<span className="sr-only">{`${t('System', 'Drag row', null, false)} ${parentRow ? `${parentRow.index + 1}-${row.index + 1}` : `${row.index + 1}`}`}</span>
<span className="sr-only">
<Translate>Drag row</Translate>
</span>
</button>
);
};

const DraggableRow = <T extends RowWithId<T>>({ row }: { row: Row<T> }) => {
const isParent = row.getCanExpand() || row.originalSubRows;
const expanded = row.getIsExpanded();
const isEmpty = row.originalSubRows?.length === 0;

Expand Down Expand Up @@ -84,7 +84,7 @@ const DraggableRow = <T extends RowWithId<T>>({ row }: { row: Row<T> }) => {
})}
</tr>

{isParent && isEmpty && expanded && (
{isEmpty && expanded && (
<tr ref={dropNoderef} className={`border-b ${isOverDropzone ? 'border-b-indigo-700' : ''}`}>
<td className="px-4 py-2">dropzone</td>
</tr>
Expand Down
2 changes: 1 addition & 1 deletion app/react/V2/Components/UI/TableV2/GroupComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const GroupCell = <T extends RowWithId<T>>({ row }: { row: Row<T> }) => {
color="indigo"
className="bg-indigo-100 rounded-md border-none drop-shadow-none"
>
<span className="sr-only">{`${t('System', 'Open group', null, false)} ${`${row.index + 1}`}`}</span>
<Translate>Group</Translate>
<Translate className="sr-only">Open group</Translate>
</EmbededButton>
) : null;
};
Expand Down
89 changes: 43 additions & 46 deletions app/react/V2/Components/UI/TableV2/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import {
useReactTable,
getCoreRowModel,
Expand All @@ -7,6 +7,7 @@ import {
getExpandedRowModel,
SortingState,
getSortedRowModel,
RowSelectionState,
} from '@tanstack/react-table';
import {
DragEndEvent,
Expand All @@ -17,14 +18,12 @@ import {
useSensors,
DndContext,
closestCenter,
UniqueIdentifier,
} from '@dnd-kit/core';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { cloneDeep } from 'lodash';
import { DraggableRow, RowDragHandleCell, DnDHeader } from './DnDComponents';
import { IndeterminateCheckboxHeader, IndeterminateCheckboxRow } from './RowSelectComponents';
import { dndSortHandler, getRowIds, sortHandler } from './helpers';
import { dndSortHandler, getRowIds } from './helpers';
import { SortingChevrons } from './SortingChevrons';
import { GroupCell, GroupHeader } from './GroupComponents';

Expand All @@ -36,10 +35,19 @@ type RowWithId<T extends { rowId: string }> = {
type TableProps<T extends RowWithId<T>> = {
columns: ColumnDef<T, any>[];
data: T[];
setData?: React.Dispatch<React.SetStateAction<T[]>>;
selectionState?: [state: {}, setter: React.Dispatch<React.SetStateAction<{}>>];
onChange?: ({
rows,
selectedRows,
sortingState,
}: {
rows: T[];
selectedRows: RowSelectionState;
sortingState: SortingState;
}) => void;
enableDnd?: boolean;
enableSelections?: boolean;
defaultSorting?: SortingState;
manualSorting?: boolean;
header?: React.ReactNode;
footer?: React.ReactNode;
className?: string;
Expand All @@ -48,24 +56,20 @@ type TableProps<T extends RowWithId<T>> = {
const Table = <T extends RowWithId<T>>({
columns,
data,
setData,
selectionState,
onChange,
enableDnd,
enableSelections,
defaultSorting,
manualSorting,
header,
footer,
className,
}: TableProps<T>) => {
const rowIds = useMemo(() => getRowIds(data), [data]);
const [rowSelection, setRowSelection] = selectionState || [null, null];
const [dataState, setDataState] = useState(data);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [sortingState, setSortingState] = useState<SortingState>(defaultSorting || []);
const originalState = useRef<T[]>([]);
const originalRowIds = useRef<{ id: UniqueIdentifier; parentId?: string }[]>([]);
const disableSortingEffect = useRef(false);

if (!originalState.current) originalState.current = cloneDeep(data);
if (!originalRowIds.current) originalRowIds.current = [...rowIds];

const rowIds = useMemo(() => getRowIds(dataState), [dataState]);
const memoizedColumns = useMemo<ColumnDef<T, any>[]>(() => {
const tableColumns = [...columns];
const hasGroups = data.find(item => item.subRows);
Expand All @@ -79,7 +83,7 @@ const Table = <T extends RowWithId<T>>({
});
}

if (rowSelection) {
if (enableSelections) {
tableColumns.unshift({
id: 'select',
header: IndeterminateCheckboxHeader,
Expand All @@ -98,10 +102,10 @@ const Table = <T extends RowWithId<T>>({
}

return tableColumns;
}, [columns, rowSelection, enableDnd]);
}, [columns, data, enableSelections, enableDnd]);

const table = useReactTable({
data,
data: dataState,
columns: memoizedColumns,
state: {
sorting: sortingState,
Expand All @@ -111,49 +115,45 @@ const Table = <T extends RowWithId<T>>({
getSortedRowModel: getSortedRowModel(),
getExpandedRowModel: getExpandedRowModel(),
onSortingChange: setSortingState,
manualSorting,
getRowId: row => row.rowId,
getSubRows: row => row.subRows || undefined,
...(setRowSelection && { enableRowSelection: true, onRowSelectionChange: setRowSelection }),
});

useEffect(() => {
originalState.current = cloneDeep(data);
originalRowIds.current = [...rowIds];
if (setRowSelection) {
setRowSelection({});
}
setDataState(data);
}, [data]);

useEffect(() => {
setRowSelection({});
}, [rowIds.length]);

useEffect(() => {
if (disableSortingEffect.current) {
disableSortingEffect.current = false;
} else if (setData) {
if (onChange) {
let updatedData = dataState;
if (sortingState.length) {
const { rows } = table.getSortedRowModel();
setData(sortHandler(rows));
} else {
setData(originalState.current);
updatedData = table.getSortedRowModel().rows.map(row => row.original);
}
onChange({ rows: updatedData, selectedRows: rowSelection, sortingState });
}
}, [sortingState]);
}, [dataState, onChange, rowSelection, sortingState, table]);

const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;

if (active && over && active.id !== over.id) {
if (setData) {
setData(() => {
let tableRows = data;
if (sortingState.length) {
table.resetSorting();
tableRows = table.getSortedRowModel().rows.map(row => row.original);
return dndSortHandler(tableRows, rowIds, active.id, over.id);
}
return dndSortHandler(tableRows, rowIds, active.id, over.id);
});
}
setDataState(() => {
let tableRows = dataState;
if (sortingState.length) {
table.resetSorting();
tableRows = table.getSortedRowModel().rows.map(row => row.original);
}
return dndSortHandler(tableRows, rowIds, active.id, over.id);
});
}
};

const sensors = useSensors(
useSensor(MouseSensor, {}),
useSensor(TouchSensor, {}),
Expand All @@ -166,9 +166,6 @@ const Table = <T extends RowWithId<T>>({
modifiers={[restrictToVerticalAxis]}
onDragEnd={handleDragEnd}
sensors={sensors}
onDragStart={() => {
disableSortingEffect.current = true;
}}
>
<div className="rounded-md shadow">
<table className={`w-full ${className || ''}`}>
Expand Down
12 changes: 1 addition & 11 deletions app/react/V2/Components/UI/TableV2/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { UniqueIdentifier } from '@dnd-kit/core';
import { cloneDeep } from 'lodash';
import { Row } from '@tanstack/react-table';
import { RowWithId, TableProps } from './Table';

const getRowIds = <T extends RowWithId<T>>(data: TableProps<T>['data']) => {
Expand Down Expand Up @@ -75,13 +74,4 @@ const dndSortHandler = <T extends RowWithId<T>>(
return state;
};

const sortHandler = <T extends RowWithId<T>>(rows: Row<T>[]) =>
rows.map(row => {
const { original, subRows } = row;
if (subRows.length) {
original.subRows = subRows.map(subRow => subRow.original);
}
return original;
});

export { getRowIds, dndSortHandler, sortHandler };
export { getRowIds, dndSortHandler };
Loading

0 comments on commit b363cfe

Please sign in to comment.