Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
mmarkauskas committed Mar 14, 2024
1 parent 1e8b5e2 commit a984bca
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 163 deletions.
210 changes: 210 additions & 0 deletions src/view/app/Components/Layout/Query/QueryFormTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { CSSProperties, Fragment, UIEvent } from 'react';
import DataGrid, {
CopyEvent,
DataGridHandle,
SortColumn,
} from 'react-data-grid';
import { Box } from '@mui/material';
import { IFilters } from '@app/common/types';

const filterCSS: CSSProperties = {

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

No reason for this to be global for the file

inlineSize: '100%',
padding: '4px',
fontSize: '14px',
};

interface QueryFormTableProps {

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

This is basically a wrapper for the <DataGrid> component, so you should not limit the user. Extend this interface:
interface QueryFormTableProps extends DataGridProps

then you can use the rest operator and spread operator.

queryGridRef: React.RefObject<DataGridHandle>;
selected: any[];

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

What else needs to be done here, is a lot of logic left in the query.tsx file, which perhaps can/should be moved here. For example, here you're passing a lot of props, with the state that is probably not needed in the parent.

Just to be clear: this component is about a table, so it should accept related data, e.g. columns, rows, maybe event handlers etc.

Example: there are 3 props passed here: isFormatted, formattedRows, rawRows. Why should this component care about those? It should accept only rows and on line 182 be this rows={rows}. The parent should be responsible for what kind of rows are passed: <QueryFormTable rows={isFormatted ? formattedRows : rawRows} />

isFormatted: boolean;
formattedRows: any[];
rawRows: any[];
sortColumns: SortColumn[];
handleScroll: (event: UIEvent<HTMLDivElement>) => void;
onSortClick: (inputSortColumns: SortColumn[]) => void;
filters: IFilters;
selectedRows: Set<string>;
setSelectedRows: React.Dispatch<React.SetStateAction<Set<string>>>;
rowKeyGetter: (row: any) => string;
readRecord: (row: any) => void;
handleCopy: (event: CopyEvent<any>) => void;
calculateHeight: () => number;
windowHeight: number;
setRowHeight: () => number;
reloadData: (loaded: number) => void;
configuration: any;
setFilters: (data: IFilters) => void;
}

const headerRenderer = ({

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

use a different name, maybe getColumnHeaderRenderer or something.

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

This should explicitly be React.FC

column,
sortDirection,
priority,
onSort,
isCellSelected,
reloadData,
configuration,
filters,
setFilters,
}) => {
function handleKeyDown(event) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
onSort(event.ctrlKey || event.metaKey);
}
}

function handleClick(event) {
onSort(event.ctrlKey || event.metaKey);
}

let timer;
function handleKeyInputTimeout() {
clearTimeout(timer);
timer = setTimeout(() => {
reloadData(configuration.initialBatchSizeLoad);
}, 500);
}

function testKeyDown(event) {
if (event.key === 'Enter') {
event.preventDefault();
reloadData(configuration.initialBatchSizeLoad);
}
}

function handleInputKeyDown(event) {
const tempFilters = filters;
tempFilters.columns[column.key] = event.target.value;
setFilters(tempFilters);
if (configuration.filterAsYouType === true) {
handleKeyInputTimeout();
}
}
return (
<Fragment>

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

You don't need this html stuff. Take a look at this Pull Request

Notice that you can use the HeaderRenderer component from react-data-grid to get the default behavior, as this is just a copy of that.

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

Then you wouldn't need the half the functions described above. Just the ones for the "filter as you type" functionality

<div className={filters.enabled ? 'filter-cell' : undefined}>
<span
tabIndex={-1}
style={{
cursor: 'pointer',
display: 'flex',
}}
className='rdg-header-sort-cell'
onClick={handleClick}
onKeyDown={handleKeyDown}
>
<span
className='rdg-header-sort-name'
style={{
flexGrow: '1',
overflow: 'clip',
textOverflow: 'ellipsis',
}}
>
{column.name}
</span>
<span>
<svg
viewBox='0 0 12 8'
width='12'
height='8'
className='rdg-sort-arrow'
style={{
fill: 'currentcolor',
}}
>
{sortDirection === 'ASC' && (
<path d='M0 8 6 0 12 8'></path>
)}
{sortDirection === 'DESC' && (
<path d='M0 0 6 8 12 0'></path>
)}
</svg>
{priority}
</span>
</span>
</div>
{filters.enabled && (
<div className={'filter-cell'}>
<input
className='textInput'
autoFocus={isCellSelected}
style={filterCSS}
defaultValue={filters.columns[column.key]}
onChange={handleInputKeyDown}
onKeyDown={testKeyDown}
/>
</div>
)}
</Fragment>
);
};

const QueryFormTable: React.FC<QueryFormTableProps> = ({
queryGridRef,
selected,
isFormatted,
formattedRows,
rawRows,
sortColumns,
handleScroll,
onSortClick,
filters,
selectedRows,
setSelectedRows,
rowKeyGetter,
readRecord,
handleCopy,
calculateHeight,
windowHeight,
setRowHeight,
reloadData,
configuration,
setFilters,
}) => {
const adjustedColumns = selected.map((col) => ({

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

This will get rerendered everytime a prop is changed. So each time a row is changed, this will get recalculated. Use React.useMemo here.

...col,
headerRenderer: (props) =>
headerRenderer({
...props,
reloadData,
configuration,
filters,
setFilters,
}),
}));
return (
<Box>
<DataGrid
ref={queryGridRef}
columns={adjustedColumns}
rows={isFormatted ? formattedRows : rawRows}
defaultColumnOptions={{
sortable: true,
resizable: true,
}}
sortColumns={sortColumns}
onScroll={handleScroll}
onSortColumnsChange={onSortClick}
className={filters.enabled ? 'filter-cell' : ''}
headerRowHeight={filters.enabled ? 70 : undefined}
style={{
height: calculateHeight(),

This comment has been minimized.

Copy link
@abelzis

abelzis Mar 14, 2024

Collaborator

this function should be in this component then.

overflow: 'auto',
minHeight: 105,
maxHeight: windowHeight - 120,
whiteSpace: 'pre',
}}
selectedRows={selectedRows}
onSelectedRowsChange={setSelectedRows}
rowKeyGetter={rowKeyGetter}
onRowDoubleClick={readRecord}
onCopy={handleCopy}
rowHeight={setRowHeight}
></DataGrid>
</Box>
);
};

export default QueryFormTable;
Loading

0 comments on commit a984bca

Please sign in to comment.