Fix SonarQube bugs

This commit is contained in:
Aditya Toshniwal
2024-01-29 18:39:30 +05:30
parent e23ef5d9df
commit 028b70203c
7 changed files with 72 additions and 56 deletions

View File

@@ -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>
);

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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}>

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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}