codekingpro/portable-devtools
114k
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9import React, { useContext, useEffect } from 'react';10import ReactDataGrid, { Row } from 'react-data-grid';11import { Box } from '@mui/material';12import { makeStyles } from '@mui/styles';13import clsx from 'clsx';14import PropTypes from 'prop-types';15import CustomPropTypes from '../custom_prop_types';16import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';17import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';18import gettext from 'sources/gettext';19 20const useStyles = makeStyles((theme)=>({21 root: {22 height: '100%',23 color: theme.palette.text.primary,24 backgroundColor: theme.otherVars.qtDatagridBg,25 fontSize: '12px',26 border: 'none',27 '--rdg-selection-color': theme.palette.primary.main,28 '& .rdg-cell': {29 ...theme.mixins.panelBorder.right,30 ...theme.mixins.panelBorder.bottom,31 fontWeight: 'abc',32 whiteSpace: 'pre',33 '&[aria-colindex="1"]': {34 padding: 0,35 },36 '&[aria-selected=true]:not([role="columnheader"])': {37 outlineWidth: '0px',38 outlineOffset: '0px',39 }40 },41 '& .rdg-header-row .rdg-cell': {42 padding: 0,43 },44 '& .rdg-header-row': {45 backgroundColor: theme.palette.background.default,46 },47 '& .rdg-row': {48 backgroundColor: theme.palette.background.default,49 '&[aria-selected=true]': {50 backgroundColor: theme.palette.primary.light,51 color: theme.otherVars.qtDatagridSelectFg,52 },53 }54 },55 cellSelection: {56 '& .rdg-cell': {57 '&[aria-selected=true]:not([role="columnheader"])': {58 outlineWidth: '1px',59 outlineOffset: '-1px',60 backgroundColor: theme.palette.primary.light,61 color: theme.otherVars.qtDatagridSelectFg,62 }63 },64 },65 hasSelectColumn: {66 '& .rdg-cell': {67 '&[aria-selected=true][aria-colindex="1"]': {68 outlineWidth: '2px',69 outlineOffset: '-2px',70 backgroundColor: theme.otherVars.qtDatagridBg,71 color: theme.palette.text.primary,72 }73 },74 '& .rdg-row[aria-selected=true] .rdg-cell:nth-child(1)': {75 backgroundColor: theme.palette.primary.main,76 color: theme.palette.primary.contrastText,77 }78 }79}));80 81export const GridContextUtils = React.createContext();82 83function CutomSortIcon({sortDirection}) {84 if(sortDirection == 'DESC') {85 return <KeyboardArrowDownIcon style={{fontSize: '1.2rem'}} />;86 } else if(sortDirection == 'ASC') {87 return <KeyboardArrowUpIcon style={{fontSize: '1.2rem'}} />;88 }89 return <></>;90}91CutomSortIcon.propTypes = {92 sortDirection: PropTypes.string,93};94 95export function CustomRow({inTest=false, ...props}) {96 const gridUtils = useContext(GridContextUtils);97 const handleKeyDown = (e)=>{98 if(e.code == 'Tab' || e.code == 'ArrowRight' || e.code == 'ArrowLeft') {99 e.stopPropagation();100 }101 if(e.code == 'Enter') {102 gridUtils.onItemEnter?.(props.row);103 }104 };105 const isRowSelected = props.selectedCellIdx >= 0;106 useEffect(()=>{107 if(isRowSelected) {108 gridUtils.onItemSelect?.(props.rowIdx);109 }110 }, [props.selectedCellIdx]);111 if(inTest) {112 return <div data-test='test-div' tabIndex={0} onKeyDown={handleKeyDown}></div>;113 }114 const onRowClick = (...args)=>{115 gridUtils.onItemClick?.(props.rowIdx);116 props.onRowClick?.(...args);117 };118 return (119 <Row {...props} onKeyDown={handleKeyDown} onRowClick={onRowClick} onRowDoubleClick={(row)=>gridUtils.onItemEnter?.(row)}120 selectCell={(row, column)=>props.selectCell(row, column)} aria-selected={isRowSelected}/>121 );122}123CustomRow.propTypes = {124 inTest: PropTypes.bool,125 row: PropTypes.object,126 selectedCellIdx: PropTypes.number,127 onRowClick: PropTypes.func,128 rowIdx: PropTypes.number,129 selectCell: PropTypes.func,130};131 132export default function PgReactDataGrid({gridRef, className, hasSelectColumn=true, onItemEnter, onItemSelect,133 onItemClick, noRowsText, noRowsIcon,...props}) {134 const classes = useStyles();135 let finalClassName = [classes.root];136 hasSelectColumn && finalClassName.push(classes.hasSelectColumn);137 props.enableCellSelect && finalClassName.push(classes.cellSelection);138 finalClassName.push(className);139 return (140 <GridContextUtils.Provider value={{onItemEnter, onItemSelect, onItemClick}}>141 <ReactDataGrid142 ref={gridRef}143 className={clsx(finalClassName)}144 components={{145 sortIcon: CutomSortIcon,146 rowRenderer: CustomRow,147 noRowsFallback: <Box textAlign="center" gridColumn="1/-1" p={1}>{noRowsIcon}{noRowsText || gettext('No rows found.')}</Box>,148 }}149 {...props}150 />151 </GridContextUtils.Provider>152 );153}154 155PgReactDataGrid.propTypes = {156 gridRef: CustomPropTypes.ref,157 className: CustomPropTypes.className,158 hasSelectColumn: PropTypes.bool,159 enableCellSelect: PropTypes.bool,160 onItemEnter: PropTypes.func,161 onItemSelect: PropTypes.func,162 onItemClick: PropTypes.func,163 noRowsText: PropTypes.string,164 noRowsIcon: PropTypes.object165};166 