mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Fix SonarQube bugs
This commit is contained in:
@@ -28,9 +28,6 @@ const useStyles = makeStyles((theme)=>({
|
||||
margin: '4px',
|
||||
textAlign: 'center',
|
||||
position: 'relative',
|
||||
},
|
||||
gridItemContent: {
|
||||
padding: '4px',
|
||||
border: '1px solid transparent',
|
||||
cursor: 'pointer',
|
||||
'&[aria-selected=true]': {
|
||||
@@ -39,6 +36,9 @@ const useStyles = makeStyles((theme)=>({
|
||||
borderColor: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
gridItemContent: {
|
||||
padding: '4px',
|
||||
},
|
||||
gridFilename: {
|
||||
overflowWrap: 'break-word',
|
||||
},
|
||||
@@ -67,11 +67,18 @@ export function ItemView({idx, row, selected, onItemSelect, onItemEnter, onEditC
|
||||
}
|
||||
}, [editMode]);
|
||||
|
||||
const handleKeyDown = (e)=>{
|
||||
const handleItemKeyDown = (e)=>{
|
||||
if(e.code == 'Enter') {
|
||||
onItemEnter(row);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditKeyDown = (e)=>{
|
||||
if(e.code == 'Tab') {
|
||||
e.stopPropagation();
|
||||
}
|
||||
if(e.code == 'Enter') {
|
||||
e.stopPropagation();
|
||||
onEditComplete({...row, Filename: fileNameRef.current.textContent?.trim()});
|
||||
}
|
||||
if(e.code == 'Escape') {
|
||||
@@ -90,17 +97,17 @@ export function ItemView({idx, row, selected, onItemSelect, onItemEnter, onEditC
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={classes.gridItem} aria-rowindex={idx} aria-selected={selected}>
|
||||
<div className={classes.gridItemContent} aria-selected={selected} onClick={()=>onItemSelect(idx)} onDoubleClick={()=>onItemEnter(row)}>
|
||||
<div tabIndex="-1" className={classes.gridItem} aria-selected={selected} onClick={()=>onItemSelect(idx)} onDoubleClick={()=>onItemEnter(row)} onKeyDown={handleItemKeyDown} role="gridcell">
|
||||
<div className={classes.gridItemContent}>
|
||||
<div>
|
||||
{icon}
|
||||
{Boolean(row.Protected) && <LockRoundedIcon className={classes.protected}/>}
|
||||
</div>
|
||||
<div ref={fileNameRef} onKeyDown={handleKeyDown} onBlur={()=>onEditComplete(row)}
|
||||
<div tabIndex="-1" ref={fileNameRef} onKeyDown={handleEditKeyDown} onBlur={()=>onEditComplete?.(row)}
|
||||
className={editMode ? classes.gridItemEdit : classes.gridFilename} suppressContentEditableWarning={true}
|
||||
contentEditable={editMode} data-test="filename-div">{row['Filename']}</div>
|
||||
contentEditable={editMode} data-test="filename-div" role={editMode ? 'textbox' : 'none'}>{row['Filename']}</div>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
ItemView.propTypes = {
|
||||
@@ -131,12 +138,12 @@ export default function GridView({items, operation, onItemSelect, onItemEnter})
|
||||
|
||||
return (
|
||||
<Box flexGrow={1} overflow="hidden auto" id="grid">
|
||||
<ul ref={gridRef} className={classes.grid}>
|
||||
<div ref={gridRef} className={classes.grid}>
|
||||
{items.map((item, i)=>(
|
||||
<ItemView key={item.Filename} idx={i} row={item} selected={selectedIdx==i} onItemSelect={setSelectedIdx}
|
||||
onItemEnter={onItemEnter} onEditComplete={operation.idx==i ? onEditComplete : null} />)
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
{items.length == 0 && <Box textAlign="center" p={1}>{gettext('No files/folders found')}</Box>}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -44,7 +44,7 @@ export default function PgTreeView({ data = [], hasCheckbox = false, selectionCh
|
||||
let treeData = data;
|
||||
const treeObj = useRef();
|
||||
const treeContainerRef = useRef();
|
||||
const [selectedCheckBoxNodes, setSelectedCheckBoxNodes] = React.useState();
|
||||
const [selectedCheckBoxNodes, setSelectedCheckBoxNodes] = React.useState([]);
|
||||
|
||||
const onSelectionChange = () => {
|
||||
let selectedChNodes = treeObj.current.selectedNodes;
|
||||
@@ -70,7 +70,7 @@ export default function PgTreeView({ data = [], hasCheckbox = false, selectionCh
|
||||
|
||||
return (<>
|
||||
{ treeData.length > 0 ?
|
||||
<PgTreeSelectionContext.Provider value={_.isUndefined(selectedCheckBoxNodes) ? []: selectedCheckBoxNodes}>
|
||||
<PgTreeSelectionContext.Provider value={selectedCheckBoxNodes}>
|
||||
<div ref={(containerRef) => treeContainerRef.current = containerRef} className={clsx(classes.tree)}>
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
@@ -109,8 +109,8 @@ PgTreeView.propTypes = {
|
||||
function Node({ node, style, tree, hasCheckbox, onNodeSelectionChange}) {
|
||||
const classes = useStyles();
|
||||
const pgTreeSelCtx = React.useContext(PgTreeSelectionContext);
|
||||
const [isSelected, setIsSelected] = React.useState(pgTreeSelCtx.includes(node.id) || node.data?.isSelected ? true : false);
|
||||
const [isIndeterminate, setIsIndeterminate] = React.useState(node?.parent.level==0? true: false);
|
||||
const [isSelected, setIsSelected] = React.useState(pgTreeSelCtx.includes(node.id) || node.data?.isSelected);
|
||||
const [isIndeterminate, setIsIndeterminate] = React.useState(node?.parent.level==0);
|
||||
|
||||
useEffect(()=>{
|
||||
setIsIndeterminate(node.data.isIndeterminate);
|
||||
@@ -136,10 +136,8 @@ function Node({ node, style, tree, hasCheckbox, onNodeSelectionChange}) {
|
||||
if (!node.isLeaf) {
|
||||
node.data.isIndeterminate = false;
|
||||
selectAllChild(node, tree, 'checkbox', pgTreeSelCtx);
|
||||
} else {
|
||||
if (node?.parent) {
|
||||
checkAndSelectParent(node);
|
||||
}
|
||||
} else if (node?.parent) {
|
||||
checkAndSelectParent(node);
|
||||
}
|
||||
|
||||
if(node?.level == 0) {
|
||||
@@ -162,15 +160,23 @@ function Node({ node, style, tree, hasCheckbox, onNodeSelectionChange}) {
|
||||
onNodeSelectionChange();
|
||||
};
|
||||
|
||||
const onSelect = (e) => {
|
||||
node.focus();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const onKeyDown = (e) => {
|
||||
if(e.code == 'Enter') {
|
||||
onSelect(e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={style} className={clsx(node.isFocused ? classes.focusedNode : '')} onClick={(e) => {
|
||||
node.focus();
|
||||
e.stopPropagation();
|
||||
}}>
|
||||
<div style={style} className={clsx(node.isFocused ? classes.focusedNode : '')} onClick={onSelect} onKeyDown={onKeyDown}>
|
||||
<CollectionArrow node={node} tree={tree} selectedNodeIds={pgTreeSelCtx} />
|
||||
{
|
||||
hasCheckbox ? <Checkbox style={{ padding: 0 }} color="primary" className={clsx(!node.isInternal ? classes.leafNode: null)}
|
||||
checked={isSelected ? true: false}
|
||||
checked={isSelected}
|
||||
checkedIcon={isIndeterminate ? <IndeterminateCheckBoxIcon style={{height: '1.4rem'}} />: <CheckBoxIcon style={{height: '1.4rem'}} />}
|
||||
onChange={onCheckboxSelection}/> :
|
||||
<span className={clsx(node.data.icon)}></span>
|
||||
@@ -197,7 +203,7 @@ function CollectionArrow({ node, tree, selectedNodeIds }) {
|
||||
}
|
||||
};
|
||||
return (
|
||||
<span onClick={toggleNode} >
|
||||
<span onClick={toggleNode} onKeyDown={()=>{/* handled by parent */}}>
|
||||
{node.isInternal && node?.children.length > 0 ? <ToggleArrowIcon node={node} /> : null}
|
||||
</span>
|
||||
);
|
||||
@@ -275,10 +281,7 @@ function selectAllChild(chNode, tree, source, selectedNodeIds){
|
||||
if(!child.isLeaf) {
|
||||
child.data.isIndeterminate = false;
|
||||
}
|
||||
if(source == 'expand' && selectedNodeIds.includes(child.id)) {
|
||||
child.data.isSelected = true;
|
||||
selectedChild += 1;
|
||||
} else if(source == 'checkbox'){
|
||||
if((source == 'expand' && selectedNodeIds.includes(child.id)) || source == 'checkbox') {
|
||||
child.data.isSelected = true;
|
||||
selectedChild += 1;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ function HelpArticleContents({isHelpLoading, isMenuLoading, helpSearchResult}) {
|
||||
}
|
||||
</div>
|
||||
<SearchLoader loading={true} />
|
||||
</div>) : '';
|
||||
</div>) : <></>;
|
||||
}
|
||||
|
||||
HelpArticleContents.propTypes = {
|
||||
@@ -265,7 +265,7 @@ export default function QuickSearch({closeModal}) {
|
||||
useOutsideAlerter(wrapperRef);
|
||||
|
||||
return (
|
||||
<div id='quick-search-container' onClick={setSearchTerm}></div>,
|
||||
<div id='quick-search-container' onClick={setSearchTerm} onKeyDown={()=>{/* no need */}}></div>,
|
||||
<div id='quick-search-container' ref={wrapperRef} className={clsx('test', modalClasses.setTop)} role="menu">
|
||||
<div>
|
||||
<div>
|
||||
|
||||
@@ -27,7 +27,7 @@ interface IItemRendererXProps {
|
||||
// DO NOT EXTEND FROM PureComponent!!! You might miss critical changes made deep within `item` prop
|
||||
// as far as efficiency is concerned, `react-aspen` works hard to ensure unnecessary updates are ignored
|
||||
export class FileTreeItem extends React.Component<IItemRendererXProps & IItemRendererProps> {
|
||||
public static getBoundingClientRectForItem(item: FileEntry | Directory): ClientRect {
|
||||
public static getBoundingClientRectForItem(item: FileEntry | Directory): DOMRect {
|
||||
const divRef = FileTreeItem.itemIdToRefMap.get(item.id);
|
||||
if (divRef) {
|
||||
return divRef.getBoundingClientRect();
|
||||
@@ -86,6 +86,7 @@ export class FileTreeItem extends React.Component<IItemRendererXProps & IItemRen
|
||||
onDragStart={this.handleDragStartItem}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
onKeyDown={()=>{/* taken care by parent */}}
|
||||
// required for rendering context menus when opened through context menu button on keyboard
|
||||
ref={this.handleDivRef}
|
||||
draggable={true}>
|
||||
|
||||
@@ -425,7 +425,7 @@ export class Tree {
|
||||
}
|
||||
|
||||
findNode(path) {
|
||||
if (path === null || path === undefined || path.length === 0) {
|
||||
if (path === null || path === undefined || path.length === 0 || path == '/browser') {
|
||||
return this.rootNode;
|
||||
}
|
||||
return findInTree(this.rootNode, path);
|
||||
|
||||
@@ -89,9 +89,9 @@ function ObjectNameFormatter({row}) {
|
||||
<Box className={row.show_node ? '' : classes.cellMuted}>
|
||||
<span className={clsx(classes.gridCell, row.icon)}></span>
|
||||
{row.name}
|
||||
{row.other_info != null && row.other_info != '' && <>
|
||||
<span className={classes.funcArgs}onClick={()=>{row.showArgs = true;}}> {row?.showArgs ? `(${row.other_info})` : '(...)'}</span>
|
||||
</>}
|
||||
{row.other_info != null && row.other_info != '' && (
|
||||
<span tabIndex="-1" className={classes.funcArgs} onClick={()=>{row.showArgs = true;}} onKeyDown={()=>{/* no need */}}> {row?.showArgs ? `(${row.other_info})` : '(...)'}</span>
|
||||
)}
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
@@ -372,7 +372,7 @@ export default function SearchObjects({nodeData}) {
|
||||
}))
|
||||
.then(res=>{
|
||||
let typeOpt = [{label:gettext('All types'), value:'all'}];
|
||||
let typesRes = Object.entries(res.data.data).sort();
|
||||
let typesRes = Object.entries(res.data.data).sort((a,b)=>a?.localeCompare?.(b));
|
||||
typesRes.forEach((element) => {
|
||||
typeOpt.push({label:gettext(element[1]), value:element[0]});
|
||||
});
|
||||
@@ -400,7 +400,7 @@ export default function SearchObjects({nodeData}) {
|
||||
<InputSelect value={type} controlProps={{allowClear: false}} options={typeOptions} onChange={(v)=>setType(v)}/>
|
||||
</Box>
|
||||
<PrimaryButton style={{width: '120px'}} data-test="search" className={modalClasses.margin} startIcon={<SearchRoundedIcon />}
|
||||
onClick={onSearch} disabled={search.length >= 3 ? false : true}>{gettext('Search')}</PrimaryButton>
|
||||
onClick={onSearch} disabled={search.length < 3}>{gettext('Search')}</PrimaryButton>
|
||||
</Box>
|
||||
<Box flexGrow="1" display="flex" flexDirection="column" position="relative" overflow="hidden">
|
||||
<PgReactDataGrid
|
||||
@@ -437,6 +437,5 @@ export default function SearchObjects({nodeData}) {
|
||||
}
|
||||
|
||||
SearchObjects.propTypes = {
|
||||
onClose: PropTypes.func,
|
||||
nodeData: PropTypes.object,
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
import { Box, makeStyles } from '@material-ui/core';
|
||||
import _ from 'lodash';
|
||||
import React, {useState, useEffect, useContext, useRef, useLayoutEffect} from 'react';
|
||||
import React, {useState, useEffect, useContext, useRef, useLayoutEffect, useMemo} from 'react';
|
||||
import {Row, useRowSelection} from 'react-data-grid';
|
||||
import LockIcon from '@material-ui/icons/Lock';
|
||||
import EditIcon from '@material-ui/icons/Edit';
|
||||
@@ -72,12 +72,14 @@ export const DataGridExtrasContext = React.createContext();
|
||||
function CustomRow(props) {
|
||||
const rowRef = useRef();
|
||||
const dataGridExtras = useContext(DataGridExtrasContext);
|
||||
const rowInfoValue = {
|
||||
|
||||
const rowInfoValue = useMemo({
|
||||
rowIdx: props.rowIdx,
|
||||
getCellElement: (colIdx)=>{
|
||||
return rowRef.current?.querySelector(`.rdg-cell[aria-colindex="${colIdx+1}"]`);
|
||||
}
|
||||
};
|
||||
}, [props.rowIdx]);
|
||||
|
||||
if(!props.isRowSelected && props.selectedCellIdx > 0) {
|
||||
dataGridExtras.onSelectedCellChange?.([props.row, props.viewportColumns?.find(columns => columns.idx === props.selectedCellIdx)]);
|
||||
} else if(props.selectedCellIdx == 0) {
|
||||
@@ -291,7 +293,7 @@ function RowNumColFormatter({row, rowKeyGetter, dataChangeStore, onSelectedColum
|
||||
return (<div className={classes.rowNumCell} onClick={()=>{
|
||||
onSelectedColumnsChange(new Set());
|
||||
onRowSelectionChange({ row: row, checked: !isRowSelected, isShiftClick: false});
|
||||
}}>
|
||||
}} onKeyDown={()=>{/* already taken care by parent */}}>
|
||||
{rownum}
|
||||
</div>);
|
||||
}
|
||||
@@ -361,30 +363,34 @@ function getTextWidth(column, rows, canvas, columnWidthBy) {
|
||||
export default function QueryToolDataGrid({columns, rows, totalRowCount, dataChangeStore,
|
||||
onSelectedCellChange, selectedColumns, onSelectedColumnsChange, columnWidthBy, ...props}) {
|
||||
const classes = useStyles();
|
||||
const [readyColumns, setColumns] = useState([]);
|
||||
const [readyColumns, setReadyColumns] = useState([]);
|
||||
const eventBus = useContext(QueryToolEventsContext);
|
||||
const onSelectedColumnsChangeWrapped = (arg)=>{
|
||||
props.onSelectedRowsChange(new Set());
|
||||
onSelectedColumnsChange(arg);
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
let initCols = initialiseColumns(columns, rows, totalRowCount, columnWidthBy);
|
||||
setColumns(formatColumns(initCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter, classes));
|
||||
}, [columns]);
|
||||
|
||||
useEffect(()=>{
|
||||
setColumns((prevCols)=>{
|
||||
return formatColumns(prevCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter, classes);
|
||||
});
|
||||
}, [dataChangeStore, selectedColumns]);
|
||||
|
||||
function handleCopy() {
|
||||
eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_COPY_DATA);
|
||||
}
|
||||
|
||||
const dataGridExtras = useMemo(()=>({
|
||||
onSelectedCellChange, handleCopy
|
||||
}), []);
|
||||
|
||||
useEffect(()=>{
|
||||
let initCols = initialiseColumns(columns, rows, totalRowCount, columnWidthBy);
|
||||
setReadyColumns(formatColumns(initCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter, classes));
|
||||
}, [columns]);
|
||||
|
||||
useEffect(()=>{
|
||||
setReadyColumns((prevCols)=>{
|
||||
return formatColumns(prevCols, dataChangeStore, selectedColumns, onSelectedColumnsChangeWrapped, props.rowKeyGetter, classes);
|
||||
});
|
||||
}, [dataChangeStore, selectedColumns]);
|
||||
|
||||
return (
|
||||
<DataGridExtrasContext.Provider value={{onSelectedCellChange, handleCopy}}>
|
||||
<DataGridExtrasContext.Provider value={dataGridExtras}>
|
||||
<PgReactDataGrid
|
||||
id="datagrid"
|
||||
columns={readyColumns}
|
||||
|
||||
Reference in New Issue
Block a user