[ Feature ] :: Reorder Table columns using drag and drop (#4327)

* column reordering using dnd

* fix :: drag handler area made as whole header

* setting drag item close to cursor

* removing padding

* style fix :: sort and dragger

* removing width :: making draggable element width same as th row width

* temperory fix :: table drag attachment to cursor
This commit is contained in:
Kiran Ashok 2022-10-13 17:09:45 +05:30 committed by GitHub
parent e99fff4508
commit a7f925d52e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 97 additions and 25 deletions

View file

@ -11,6 +11,7 @@ import {
useBlockLayout,
useResizeColumns,
useRowSelect,
useColumnOrder,
} from 'react-table';
import cx from 'classnames';
import { resolveReferences, validateWidget } from '@/_helpers/utils';
@ -28,6 +29,7 @@ import generateActionsData from './columns/actions';
import autogenerateColumns from './columns/autogenerateColumns';
import IndeterminateCheckbox from './IndeterminateCheckbox';
import { useTranslation } from 'react-i18next';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
// eslint-disable-next-line import/no-unresolved
import { IconEyeOff } from '@tabler/icons';
import * as XLSX from 'xlsx/xlsx.mjs';
@ -86,6 +88,22 @@ export function Table({
disabledSort,
} = loadPropertiesAndStyles(properties, styles, darkMode, component);
const getItemStyle = ({ isDragging, isDropAnimating }, draggableStyle) => ({
...draggableStyle,
userSelect: 'none',
background: isDragging ? 'rgba(77, 114, 250, 0.2)' : '',
top: 'auto',
borderRadius: '4px',
...(isDragging && {
marginLeft: '-120px',
display: 'flex',
alignItems: 'center',
paddingLeft: '10px',
height: '30px',
}),
...(!isDragging && { transform: 'translate(0,0)', width: '100%' }),
...(isDropAnimating && { transitionDuration: '0.001s' }),
});
const { t } = useTranslation();
const [tableDetails, dispatch] = useReducer(reducer, initialState());
@ -340,12 +358,13 @@ export function Table({
setAllFilters,
preGlobalFilteredRows,
setGlobalFilter,
allColumns,
setColumnOrder,
state: { pageIndex, globalFilter },
exportData,
selectedFlatRows,
globalFilteredRows,
getToggleHideAllColumnsProps,
allColumns,
} = useTable(
{
autoResetPage: false,
@ -363,6 +382,7 @@ export function Table({
disableSortBy: disabledSort,
manualSortBy: serverSideSort,
},
useColumnOrder,
useFilters,
useGlobalFilter,
useSortBy,
@ -393,6 +413,7 @@ export function Table({
]);
}
);
const currentColOrder = React.useRef();
const sortOptions = useMemo(() => {
if (state?.sortBy?.length === 0) {
@ -609,27 +630,75 @@ export function Table({
<table {...getTableProps()} className={`table table-vcenter table-nowrap ${tableType}`} style={computedStyles}>
<thead>
{headerGroups.map((headerGroup, index) => (
<tr key={index} {...headerGroup.getHeaderGroupProps()} tabIndex="0" className="tr">
{headerGroup.headers.map((column, index) => (
<th className="th" key={index} {...column.getHeaderProps()}>
<div
className={column.isSorted ? (column.isSortedDesc ? 'sort-desc' : 'sort-asc') : ''}
{...column.getSortByToggleProps()}
<DragDropContext
key={index}
onDragStart={() => {
currentColOrder.current = allColumns?.map((o) => o.id);
}}
onDragUpdate={(dragUpdateObj) => {
const colOrder = [...currentColOrder.current];
const sIndex = dragUpdateObj.source.index;
const dIndex = dragUpdateObj.destination && dragUpdateObj.destination.index;
if (typeof sIndex === 'number' && typeof dIndex === 'number') {
colOrder.splice(sIndex, 1);
colOrder.splice(dIndex, 0, dragUpdateObj.draggableId);
setColumnOrder(colOrder);
}
}}
>
<Droppable droppableId="droppable" direction="horizontal">
{(droppableProvided, snapshot) => (
<tr
ref={droppableProvided.innerRef}
key={index}
{...headerGroup.getHeaderGroupProps()}
tabIndex="0"
className="tr"
>
{column.render('Header')}
</div>
<div
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
draggable="true"
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
/>
</th>
))}
</tr>
{headerGroup.headers.map((column, index) => (
<Draggable
key={column.id}
draggableId={column.id}
index={index}
isDragDisabled={!column.accessor}
>
{(provided, snapshot) => {
return (
<th
key={index}
{...column.getHeaderProps(column.getSortByToggleProps())}
className={
column.isSorted ? (column.isSortedDesc ? 'sort-desc th' : 'sort-asc th') : 'th'
}
>
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
// {...extraProps}
ref={provided.innerRef}
style={{ ...getItemStyle(snapshot, provided.draggableProps.style) }}
>
{column.render('Header')}
</div>
<div
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
draggable="true"
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
/>
</th>
);
}}
</Draggable>
))}
</tr>
)}
</Droppable>
</DragDropContext>
))}
</thead>

View file

@ -1902,8 +1902,8 @@ button {
border-right: 5px solid transparent;
border-top: 5px solid #767676;
border-bottom: 5px solid transparent;
left: 6px;
top: 8px;
left: 0px;
top: 7px;
}
.sort-asc:after {
@ -1911,8 +1911,8 @@ button {
border-right: 5px solid transparent;
border-top: 0px solid transparent;
border-bottom: 5px solid #767676;
left: 6px;
bottom: 8px;
left: 0px;
top: 7px;
}
}
@ -3441,6 +3441,9 @@ input:focus-visible {
.gui-select-wrappper .select-search__input {
height: 30px;
}
.table thead th {
display: flex !important;
}
.theme-dark .input-group-text,
.theme-dark .markdown>table thead th,