Continue fixing multiple UI and SonarQube issues found when testing wcDocker changes. #6479

This commit is contained in:
Aditya Toshniwal 2023-10-30 16:57:01 +05:30
parent 4bc6dcca67
commit e30d2eca90
10 changed files with 65 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -33,6 +33,7 @@ Bug fixes
********* *********
| `Issue #2986 <https://github.com/pgadmin-org/pgadmin4/issues/2986>`_ - Fix an issue where the scroll position of panels was not remembered on Firefox. | `Issue #2986 <https://github.com/pgadmin-org/pgadmin4/issues/2986>`_ - Fix an issue where the scroll position of panels was not remembered on Firefox.
| `Issue #6459 <https://github.com/pgadmin-org/pgadmin4/issues/6459>`_ - Fix the sorting of size on the statistics panel.
| `Issue #6602 <https://github.com/pgadmin-org/pgadmin4/issues/6602>`_ - Fix an issue where the default server-group is being deleted if the load-server json file contains no servers. | `Issue #6602 <https://github.com/pgadmin-org/pgadmin4/issues/6602>`_ - Fix an issue where the default server-group is being deleted if the load-server json file contains no servers.
| `Issue #6720 <https://github.com/pgadmin-org/pgadmin4/issues/6720>`_ - Fix an issue of the incorrect format (no indent) of SQL stored functions/procedures. | `Issue #6720 <https://github.com/pgadmin-org/pgadmin4/issues/6720>`_ - Fix an issue of the incorrect format (no indent) of SQL stored functions/procedures.
| `Issue #6784 <https://github.com/pgadmin-org/pgadmin4/issues/6784>`_ - Fixed an issue where Schema Diff does not work when the user language is set to any language other than English in Preferences. | `Issue #6784 <https://github.com/pgadmin-org/pgadmin4/issues/6784>`_ - Fixed an issue where Schema Diff does not work when the user language is set to any language other than English in Preferences.

View File

@ -5,9 +5,9 @@
**************** ****************
The pgAdmin toolbar provides shortcut buttons for frequently used features like The pgAdmin toolbar provides shortcut buttons for frequently used features like
View Data and the Query Tool which are most frequently used in pgAdmin. This the Query Tool, View/Edit Data, Search Object and the PSQL Tool. This
toolbar is visible on the Browser panel. Buttons get enabled/disabled based on toolbar is visible on the Object explorer panel. Buttons get enabled/disabled based on
the selected browser node. the selected object node.
.. image:: /images/toolbar.png .. image:: /images/toolbar.png
:alt: pgAdmin Toolbar :alt: pgAdmin Toolbar

View File

@ -4,8 +4,8 @@
`Tree Control`:index: `Tree Control`:index:
********************* *********************
The left pane of the main window displays a tree control (the *pgAdmin* tree The left pane of the main window displays a tree control (Object explorer)
control) that provides access to the objects that reside on a server. that provides access to the objects that reside on a server.
.. image:: /images/main_left_pane.png .. image:: /images/main_left_pane.png
:alt: object explorer panel :alt: object explorer panel

View File

@ -55,29 +55,17 @@ const useStyles = makeStyles((theme) => ({
})); }));
function getColumn(data, singleLineStatistics, prettifyFields=[]) { function getColumn(data, singleLineStatistics, prettifyFields=[]) {
let columns = [], column; let columns = [];
if (!singleLineStatistics) { if (!singleLineStatistics) {
if (!_.isUndefined(data)) { if (!_.isUndefined(data)) {
data.forEach((row) => { data.forEach((row) => {
if (row.name == gettext('Total Size')) { columns.push({
column = {
Header: row.name, Header: row.name,
accessor: row.name, accessor: row.name,
sortable: true, sortable: true,
resizable: true, resizable: true,
disableGlobalFilter: false, disableGlobalFilter: false,
}; });
}else{
column = {
Header: row.name,
accessor: row.name,
sortable: true,
resizable: true,
disableGlobalFilter: false,
};
}
columns.push(column);
}); });
} }
} else { } else {

View File

@ -77,6 +77,9 @@ const useStyles = makeStyles((theme)=>({
minWidth: '24px', minWidth: '24px',
'& .MuiSvgIcon-root': { '& .MuiSvgIcon-root': {
height: '0.8em', height: '0.8em',
},
'.MuiButtonGroup-root &': {
minWidth: '30px',
} }
}, },
noBorder: { noBorder: {

View File

@ -1,4 +1,4 @@
import React, { useRef, useMemo, useEffect, useCallback } from 'react'; import React, { useRef, useMemo, useEffect, useCallback, useState } from 'react';
import DockLayout from 'rc-dock'; import DockLayout from 'rc-dock';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import EventBus from '../EventBus'; import EventBus from '../EventBus';
@ -17,8 +17,12 @@ import usePreferences from '../../../../preferences/static/js/store';
import _ from 'lodash'; import _ from 'lodash';
function TabTitle({id, icon, title, closable, tooltip}) { function TabTitle({id, icon, title, closable, tooltip}) {
const [attrs, setAttrs] = useState({
icon: icon,
title: title,
tooltip: tooltip??title,
});
const layoutDocker = React.useContext(LayoutDockerContext); const layoutDocker = React.useContext(LayoutDockerContext);
const onContextMenu = useCallback((e)=>{ const onContextMenu = useCallback((e)=>{
const g = layoutDocker.find(id)?.group??''; const g = layoutDocker.find(id)?.group??'';
if((layoutDocker.noContextGroups??[]).includes(g)) return; if((layoutDocker.noContextGroups??[]).includes(g)) return;
@ -27,10 +31,24 @@ function TabTitle({id, icon, title, closable, tooltip}) {
layoutDocker.eventBus.fireEvent(LAYOUT_EVENTS.CONTEXT, e, id); layoutDocker.eventBus.fireEvent(LAYOUT_EVENTS.CONTEXT, e, id);
}, []); }, []);
useEffect(()=>{
const deregister = layoutDocker.eventBus.registerListener(LAYOUT_EVENTS.REFRESH_TITLE, _.debounce((panelId)=>{
if(panelId == id) {
const p = layoutDocker.find(id)?.internal??{};
setAttrs({
icon: p.icon,
title: p.title,
tooltip: p.tooltip??p.title
});
}
}, 100));
return deregister;
}, []);
return ( return (
<Box display="flex" alignItems="center" title={tooltip??title} onContextMenu={onContextMenu} width="100%"> <Box display="flex" alignItems="center" title={attrs.tooltip} onContextMenu={onContextMenu} width="100%">
{icon && <span style={{fontSize: '1rem', marginRight: '4px'}} className={icon}></span>} {attrs.icon && <span style={{fontSize: '1rem', marginRight: '4px'}} className={attrs.icon}></span>}
<span style={{textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap'}} data-visible={layoutDocker.isTabVisible(id)}>{title}</span> <span style={{textOverflow: 'ellipsis', overflow: 'hidden', whiteSpace: 'nowrap'}} data-visible={layoutDocker.isTabVisible(id)}>{attrs.title}</span>
{closable && <PgIconButton title={gettext('Close')} icon={<CloseIcon style={{height: '0.7em'}} />} size="xs" noBorder onClick={()=>{ {closable && <PgIconButton title={gettext('Close')} icon={<CloseIcon style={{height: '0.7em'}} />} size="xs" noBorder onClick={()=>{
layoutDocker.close(id); layoutDocker.close(id);
}} style={{margin: '-1px -10px -1px 0'}} />} }} style={{margin: '-1px -10px -1px 0'}} />}
@ -99,7 +117,7 @@ export class LayoutDocker {
} }
find(...args) { find(...args) {
return this.layoutObj.find(...args); return this.layoutObj?.find(...args);
} }
setTitle(panelId, title, icon, tooltip) { setTitle(panelId, title, icon, tooltip) {
@ -116,22 +134,17 @@ export class LayoutDocker {
if(tooltip) { if(tooltip) {
internal.tooltip = tooltip; internal.tooltip = tooltip;
} }
this.layoutObj.updateTab(panelId, { panelData.internal = internal;
...panelData, this.eventBus.fireEvent(LAYOUT_EVENTS.REFRESH_TITLE, panelId);
internal: internal,
title: <TabTitle id={panelData.id} icon={internal.icon} title={internal.title} closable={internal.closable} tooltip={internal.tooltip} />
}, false);
} }
setInternalAttrs(panelId, attrs) { setInternalAttrs(panelId, attrs) {
const panelData = this.find(panelId); const panelData = this.find(panelId);
this.layoutObj.updateTab(panelId, { panelData.internal = {
...panelData,
internal: {
...panelData.internal, ...panelData.internal,
...attrs, ...attrs,
}, };
}, false); this.eventBus.fireEvent(LAYOUT_EVENTS.REFRESH_TITLE, panelId);
} }
getInternalAttrs(panelId) { getInternalAttrs(panelId) {
@ -449,12 +462,12 @@ export default function Layout({groups, noContextGroups, getLayoutInstance, layo
}} }}
groups={defaultGroups} groups={defaultGroups}
onLayoutChange={(l, currentTabId, direction)=>{ onLayoutChange={(l, currentTabId, direction)=>{
layoutDockerObj.saveLayout(l);
direction = direction == 'update' ? 'active' : direction;
if(Object.values(LAYOUT_EVENTS).indexOf(direction) > -1) { if(Object.values(LAYOUT_EVENTS).indexOf(direction) > -1) {
layoutDockerObj.eventBus.fireEvent(LAYOUT_EVENTS[direction.toUpperCase()], currentTabId); layoutDockerObj.eventBus.fireEvent(LAYOUT_EVENTS[direction.toUpperCase()], currentTabId);
} else if(direction) { layoutDockerObj.saveLayout(l);
} else if(direction && direction != 'update') {
layoutDockerObj.eventBus.fireEvent(LAYOUT_EVENTS.CHANGE, currentTabId); layoutDockerObj.eventBus.fireEvent(LAYOUT_EVENTS.CHANGE, currentTabId);
layoutDockerObj.saveLayout(l);
} }
}} }}
{...props} {...props}
@ -486,5 +499,6 @@ export const LAYOUT_EVENTS = {
MOVE: 'move', MOVE: 'move',
CLOSING: 'closing', CLOSING: 'closing',
CONTEXT: 'context', CONTEXT: 'context',
CHANGE: 'change' CHANGE: 'change',
REFRESH_TITLE: 'refresh-title'
}; };

View File

@ -3,15 +3,15 @@ import { usePgAdmin } from '../BrowserComponent';
import { Box } from '@material-ui/core'; import { Box } from '@material-ui/core';
import { QueryToolIcon, RowFilterIcon, TerminalIcon, ViewDataIcon } from '../components/ExternalIcon'; import { QueryToolIcon, RowFilterIcon, TerminalIcon, ViewDataIcon } from '../components/ExternalIcon';
import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined'; import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined';
import { PgIconButton } from '../components/Buttons'; import { PgButtonGroup, PgIconButton } from '../components/Buttons';
import _ from 'lodash'; import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import CustomPropTypes from '../custom_prop_types'; import CustomPropTypes from '../custom_prop_types';
function ToolbarButton({menuItem, icon}) { function ToolbarButton({menuItem, icon, ...props}) {
return ( return (
<PgIconButton title={menuItem?.label??''} icon={icon} size="xs" <PgIconButton title={menuItem?.label??''} icon={icon} {...props} size="xs"
disabled={menuItem?.isDisabled??true} onClick={()=>menuItem?.callback()} /> disabled={menuItem?.isDisabled??true} onClick={()=>menuItem?.callback()} />
); );
} }
@ -60,11 +60,13 @@ export default function ObjectExplorerToolbar() {
return ( return (
<Box display="flex" alignItems="center" gridGap={'2px'}> <Box display="flex" alignItems="center" gridGap={'2px'}>
<PgButtonGroup size="small">
<ToolbarButton icon={<QueryToolIcon />} menuItem={menus['query_tool']} /> <ToolbarButton icon={<QueryToolIcon />} menuItem={menus['query_tool']} />
<ToolbarButton icon={<ViewDataIcon />} menuItem={menus['view_all_rows_context_table']} /> <ToolbarButton icon={<ViewDataIcon />} menuItem={menus['view_all_rows_context_table']} />
<ToolbarButton icon={<RowFilterIcon />} menuItem={menus['view_filtered_rows_context_table']} /> <ToolbarButton icon={<RowFilterIcon />} menuItem={menus['view_filtered_rows_context_table']} />
<ToolbarButton icon={<SearchOutlinedIcon style={{height: '1.4rem'}} />} menuItem={menus['search_objects']} /> <ToolbarButton icon={<SearchOutlinedIcon style={{height: '1.4rem'}} />} menuItem={menus['search_objects']} />
<ToolbarButton icon={<TerminalIcon />} menuItem={menus['psql']} /> <ToolbarButton icon={<TerminalIcon />} menuItem={menus['psql']} />
</PgButtonGroup>
</Box> </Box>
); );
} }

View File

@ -498,11 +498,11 @@ export default function Query() {
const isDirty = ()=>(queryToolCtx.params.is_query_tool && lastSavedText.current !== editor.current.getValue()); const isDirty = ()=>(queryToolCtx.params.is_query_tool && lastSavedText.current !== editor.current.getValue());
const cursorActivity = useCallback((cmObj)=>{ const cursorActivity = useCallback(_.debounce((cmObj)=>{
const c = cmObj.getCursor(); const c = cmObj.getCursor();
lastCursorPos.current = c; lastCursorPos.current = c;
eventBus.fireEvent(QUERY_TOOL_EVENTS.CURSOR_ACTIVITY, [c.line+1, c.ch+1]); eventBus.fireEvent(QUERY_TOOL_EVENTS.CURSOR_ACTIVITY, [c.line+1, c.ch+1]);
}, []); }, 100), []);
const change = useCallback(()=>{ const change = useCallback(()=>{
eventBus.fireEvent(QUERY_TOOL_EVENTS.QUERY_CHANGED, isDirty()); eventBus.fireEvent(QUERY_TOOL_EVENTS.QUERY_CHANGED, isDirty());