|
|
|
|
@@ -1,9 +1,20 @@
|
|
|
|
|
import React from 'react';
|
|
|
|
|
import ReactDataGrid from 'react-data-grid';
|
|
|
|
|
import { makeStyles } from '@material-ui/core';
|
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// pgAdmin 4 - PostgreSQL Tools
|
|
|
|
|
//
|
|
|
|
|
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
|
|
|
|
// This software is released under the PostgreSQL Licence
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
import React, { useContext, useEffect } from 'react';
|
|
|
|
|
import ReactDataGrid, { Row } from 'react-data-grid';
|
|
|
|
|
import { Box, makeStyles } from '@material-ui/core';
|
|
|
|
|
import clsx from 'clsx';
|
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
import CustomPropTypes from '../custom_prop_types';
|
|
|
|
|
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
|
|
|
|
|
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
|
|
|
|
import gettext from 'sources/gettext';
|
|
|
|
|
|
|
|
|
|
const useStyles = makeStyles((theme)=>({
|
|
|
|
|
root: {
|
|
|
|
|
@@ -30,7 +41,6 @@ const useStyles = makeStyles((theme)=>({
|
|
|
|
|
},
|
|
|
|
|
'& .rdg-header-row': {
|
|
|
|
|
backgroundColor: theme.palette.background.default,
|
|
|
|
|
fontWeight: 'normal',
|
|
|
|
|
},
|
|
|
|
|
'& .rdg-row': {
|
|
|
|
|
backgroundColor: theme.palette.background.default,
|
|
|
|
|
@@ -66,18 +76,78 @@ const useStyles = makeStyles((theme)=>({
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
export const GridContextUtils = React.createContext();
|
|
|
|
|
|
|
|
|
|
export default function PgReactDataGrid({gridRef, className, hasSelectColumn=true, ...props}) {
|
|
|
|
|
function CutomSortIcon({sortDirection}) {
|
|
|
|
|
if(sortDirection == 'DESC') {
|
|
|
|
|
return <KeyboardArrowDownIcon style={{fontSize: '1.2rem'}} />;
|
|
|
|
|
} else if(sortDirection == 'ASC') {
|
|
|
|
|
return <KeyboardArrowUpIcon style={{fontSize: '1.2rem'}} />;
|
|
|
|
|
}
|
|
|
|
|
return <></>;
|
|
|
|
|
}
|
|
|
|
|
CutomSortIcon.propTypes = {
|
|
|
|
|
sortDirection: PropTypes.string,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function CustomRow({inTest=false, ...props}) {
|
|
|
|
|
const gridUtils = useContext(GridContextUtils);
|
|
|
|
|
const handleKeyDown = (e)=>{
|
|
|
|
|
if(e.code == 'Tab' || e.code == 'ArrowRight' || e.code == 'ArrowLeft') {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
if(e.code == 'Enter') {
|
|
|
|
|
gridUtils.onItemEnter?.(props.row);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const isRowSelected = props.selectedCellIdx >= 0;
|
|
|
|
|
useEffect(()=>{
|
|
|
|
|
if(isRowSelected) {
|
|
|
|
|
gridUtils.onItemSelect?.(props.rowIdx);
|
|
|
|
|
}
|
|
|
|
|
}, [props.selectedCellIdx]);
|
|
|
|
|
if(inTest) {
|
|
|
|
|
return <div data-test='test-div' tabIndex={0} onKeyDown={handleKeyDown}></div>;
|
|
|
|
|
}
|
|
|
|
|
const onRowClick = (...args)=>{
|
|
|
|
|
gridUtils.onItemClick?.(props.rowIdx);
|
|
|
|
|
props.onRowClick?.(...args);
|
|
|
|
|
};
|
|
|
|
|
return (
|
|
|
|
|
<Row {...props} onKeyDown={handleKeyDown} onRowClick={onRowClick} onRowDoubleClick={(row)=>gridUtils.onItemEnter?.(row)}
|
|
|
|
|
selectCell={(row, column)=>props.selectCell(row, column)} aria-selected={isRowSelected}/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
CustomRow.propTypes = {
|
|
|
|
|
inTest: PropTypes.bool,
|
|
|
|
|
row: PropTypes.object,
|
|
|
|
|
selectedCellIdx: PropTypes.number,
|
|
|
|
|
onRowClick: PropTypes.func,
|
|
|
|
|
rowIdx: PropTypes.number,
|
|
|
|
|
selectCell: PropTypes.func,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default function PgReactDataGrid({gridRef, className, hasSelectColumn=true, onItemEnter, onItemSelect,
|
|
|
|
|
onItemClick, noRowsText, ...props}) {
|
|
|
|
|
const classes = useStyles();
|
|
|
|
|
let finalClassName = [classes.root];
|
|
|
|
|
hasSelectColumn && finalClassName.push(classes.hasSelectColumn);
|
|
|
|
|
props.enableCellSelect && finalClassName.push(classes.cellSelection);
|
|
|
|
|
finalClassName.push(className);
|
|
|
|
|
return <ReactDataGrid
|
|
|
|
|
ref={gridRef}
|
|
|
|
|
className={clsx(finalClassName)}
|
|
|
|
|
{...props}
|
|
|
|
|
/>;
|
|
|
|
|
return (
|
|
|
|
|
<GridContextUtils.Provider value={{onItemEnter, onItemSelect, onItemClick}}>
|
|
|
|
|
<ReactDataGrid
|
|
|
|
|
ref={gridRef}
|
|
|
|
|
className={clsx(finalClassName)}
|
|
|
|
|
components={{
|
|
|
|
|
sortIcon: CutomSortIcon,
|
|
|
|
|
rowRenderer: CustomRow,
|
|
|
|
|
noRowsFallback: <Box textAlign="center" gridColumn="1/-1" p={1}>{noRowsText || gettext('No rows found.')}</Box>,
|
|
|
|
|
}}
|
|
|
|
|
{...props}
|
|
|
|
|
/>
|
|
|
|
|
</GridContextUtils.Provider>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PgReactDataGrid.propTypes = {
|
|
|
|
|
@@ -85,4 +155,8 @@ PgReactDataGrid.propTypes = {
|
|
|
|
|
className: CustomPropTypes.className,
|
|
|
|
|
hasSelectColumn: PropTypes.bool,
|
|
|
|
|
enableCellSelect: PropTypes.bool,
|
|
|
|
|
onItemEnter: PropTypes.func,
|
|
|
|
|
onItemSelect: PropTypes.func,
|
|
|
|
|
onItemClick: PropTypes.func,
|
|
|
|
|
noRowsText: PropTypes.string
|
|
|
|
|
};
|
|
|
|
|
|