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

This commit is contained in:
Aditya Toshniwal
2023-10-27 15:51:45 +05:30
parent 1bfd8d7f3c
commit b11b2a2f50
26 changed files with 171 additions and 111 deletions

View File

@@ -207,8 +207,7 @@ Front End
pgAdmin uses javascript extensively for the front-end implementation. It uses pgAdmin uses javascript extensively for the front-end implementation. It uses
require.js to allow the lazy loading (or, say load only when required), require.js to allow the lazy loading (or, say load only when required),
bootstrap and MaterialUI for UI look and feel, React for generating ReactJS with CSS and MaterialUI for UI look and feel. We have
properties/create dialog for selected node. We have
divided each module in small chunks as much as possible. Not all javascript divided each module in small chunks as much as possible. Not all javascript
modules are required to be loaded (i.e. loading a javascript module for modules are required to be loaded (i.e. loading a javascript module for
database will make sense only when a server node is loaded completely.) Please database will make sense only when a server node is loaded completely.) Please

View File

@@ -22,14 +22,12 @@ purpose or how it works if not obvious from a quick review of the code itself.
CSS 3 CSS 3
***** *****
CSS3 is used for styling and layout throughout the application. Extensive use is CSS3 is used for styling and layout throughout the application.
made of the Bootstrap Framework to aid in that process, however additional
styles must still be created from time to time.
Most custom styling comes from individual modules which may advertise static Most custom styling comes from individual modules which may advertise static
stylesheets to be included in the module that is loading them via hooks. stylesheets to be included in the module that is loading them via hooks.
Styling overrides (for example, to alter the Bootstrap look and feel) will Styling overrides (for example, to alter the look and feel) will
typically be found in the **overrides.css** file in the main static file typically be found in the **overrides.css** file in the main static file
directory for the application. directory for the application.

View File

@@ -5,3 +5,5 @@ logFilters:
level: discard level: discard
nodeLinker: node-modules nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.6.4.cjs

View File

@@ -230,8 +230,8 @@ PROXY_X_PREFIX_COUNT = 0
# COMPRESSION # COMPRESSION
COMPRESS_MIMETYPES = [ COMPRESS_MIMETYPES = [
'text/html', 'text/css', 'text/xml', 'application/json', 'text/html', 'text/css', 'text/xml', 'text/javascript',
'application/javascript' 'application/json', 'application/javascript'
] ]
COMPRESS_LEVEL = 9 COMPRESS_LEVEL = 9
COMPRESS_MIN_SIZE = 500 COMPRESS_MIN_SIZE = 500

View File

@@ -314,7 +314,6 @@ define('pgadmin.browser', [
'pgadmin:server:disconnect', stop_heartbeat.bind(obj) 'pgadmin:server:disconnect', stop_heartbeat.bind(obj)
); );
obj.set_master_password('');
obj.check_corrupted_db_file(); obj.check_corrupted_db_file();
obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode.bind(obj)); obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode.bind(obj));
obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode.bind(obj)); obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode.bind(obj));
@@ -328,6 +327,7 @@ define('pgadmin.browser', [
obj.start_inactivity_timeout_daemon(); obj.start_inactivity_timeout_daemon();
}, },
uiloaded: function() { uiloaded: function() {
this.set_master_password('');
this.check_version_update(); this.check_version_update();
}, },
check_corrupted_db_file: function() { check_corrupted_db_file: function() {

View File

@@ -13,7 +13,7 @@ import gettext from 'sources/gettext';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import { BgProcessManagerEvents, BgProcessManagerProcessState } from './BgProcessConstants'; import { BgProcessManagerEvents, BgProcessManagerProcessState } from './BgProcessConstants';
import { PgIconButton } from '../../../../static/js/components/Buttons'; import { PgButtonGroup, PgIconButton } from '../../../../static/js/components/Buttons';
import CancelIcon from '@material-ui/icons/Cancel'; import CancelIcon from '@material-ui/icons/Cancel';
import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined'; import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';
import DeleteIcon from '@material-ui/icons/Delete'; import DeleteIcon from '@material-ui/icons/Delete';
@@ -282,9 +282,9 @@ export default function Processes() {
CustomHeader={()=>{ CustomHeader={()=>{
return ( return (
<Box> <Box>
<PgButtonGroup>
<PgIconButton <PgIconButton
className={classes.dropButton} icon={<DeleteIcon style={{height: '1.4rem'}}/>}
icon={<DeleteIcon/>}
aria-label="Acknowledge and Remove" aria-label="Acknowledge and Remove"
title={gettext('Acknowledge and Remove')} title={gettext('Acknowledge and Remove')}
onClick={() => { onClick={() => {
@@ -295,14 +295,14 @@ export default function Processes() {
disabled={selectedRows.length <= 0} disabled={selectedRows.length <= 0}
></PgIconButton> ></PgIconButton>
<PgIconButton <PgIconButton
icon={<HelpIcon/>} icon={<HelpIcon style={{height: '1.4rem'}}/>}
aria-label="Help" aria-label="Help"
title={gettext('Help')} title={gettext('Help')}
style={{marginLeft: '8px'}}
onClick={() => { onClick={() => {
window.open(url_for('help.static', {'filename': 'processes.html'})); window.open(url_for('help.static', {'filename': 'processes.html'}));
}} }}
></PgIconButton> ></PgIconButton>
</PgButtonGroup>
</Box> </Box>
); );
}} }}

View File

@@ -154,6 +154,7 @@ function Dependencies({ nodeData, nodeItem, node, treeNodeInfo, isActive, isStal
if (message != '') { if (message != '') {
setMsg(message); setMsg(message);
setLoaderText(''); setLoaderText('');
setTableData([]);
} }
setIsStale(false); setIsStale(false);
}, [isActive, isStale]); }, [isActive, isStale]);

View File

@@ -152,6 +152,7 @@ function Dependents({ nodeData, nodeItem, node, treeNodeInfo, isActive, isStale,
} }
if (message != '') { if (message != '') {
setLoaderText(''); setLoaderText('');
setTableData([]);
setMsg(message); setMsg(message);
} }

View File

@@ -15,7 +15,7 @@ import gettext from 'sources/gettext';
import PgTable from 'sources/components/PgTable'; import PgTable from 'sources/components/PgTable';
import Theme from 'sources/Theme'; import Theme from 'sources/Theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { PgIconButton } from '../../static/js/components/Buttons'; import { PgButtonGroup, PgIconButton } from '../../static/js/components/Buttons';
import DeleteIcon from '@material-ui/icons/Delete'; import DeleteIcon from '@material-ui/icons/Delete';
import DeleteSweepIcon from '@material-ui/icons/DeleteSweep'; import DeleteSweepIcon from '@material-ui/icons/DeleteSweep';
import DeleteForeverIcon from '@material-ui/icons/DeleteForever'; import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
@@ -64,9 +64,6 @@ const useStyles = makeStyles((theme) => ({
overflow: 'hidden !important', overflow: 'hidden !important',
overflowX: 'auto !important' overflowX: 'auto !important'
}, },
dropButton: {
marginRight: '8px !important'
},
readOnlySwitch: { readOnlySwitch: {
opacity: 0.75, opacity: 0.75,
'& .MuiSwitch-track': { '& .MuiSwitch-track': {
@@ -291,9 +288,9 @@ export default function CollectionNodeProperties({
const canDropForce = evalFunc(node, node.canDropForce, nodeData, nodeItem, treeNodeInfo); const canDropForce = evalFunc(node, node.canDropForce, nodeData, nodeItem, treeNodeInfo);
return ( return (
<Box > <Box >
<PgButtonGroup size="small">
<PgIconButton <PgIconButton
className={classes.dropButton} icon={<DeleteIcon style={{height: '1.35rem'}}/>}
icon={<DeleteIcon/>}
aria-label="Delete" aria-label="Delete"
title={gettext('Delete')} title={gettext('Delete')}
onClick={() => { onClick={() => {
@@ -306,8 +303,7 @@ export default function CollectionNodeProperties({
} }
></PgIconButton> ></PgIconButton>
{node.type !== 'coll-database' ? <PgIconButton {node.type !== 'coll-database' ? <PgIconButton
className={classes.dropButton} icon={<DeleteSweepIcon style={{height: '1.5rem'}} />}
icon={<DeleteSweepIcon />}
aria-label="Delete Cascade" aria-label="Delete Cascade"
title={gettext('Delete (Cascade)')} title={gettext('Delete (Cascade)')}
onClick={() => { onClick={() => {
@@ -320,8 +316,7 @@ export default function CollectionNodeProperties({
} }
></PgIconButton> : ></PgIconButton> :
<PgIconButton <PgIconButton
className={classes.dropButton} icon={<DeleteForeverIcon style={{height: '1.4rem'}} />}
icon={<DeleteForeverIcon />}
aria-label="Delete Force" aria-label="Delete Force"
title={gettext('Delete (Force)')} title={gettext('Delete (Force)')}
onClick={() => { onClick={() => {
@@ -333,6 +328,7 @@ export default function CollectionNodeProperties({
: true : true
} }
></PgIconButton>} ></PgIconButton>}
</PgButtonGroup>
</Box>); </Box>);
}; };
@@ -356,9 +352,7 @@ export default function CollectionNodeProperties({
: :
( (
<div className={classes.emptyPanel}> <div className={classes.emptyPanel}>
{loaderText ? (<Loader message={loaderText}/>) :
<EmptyPanelMessage text={gettext(infoMsg)}/> <EmptyPanelMessage text={gettext(infoMsg)}/>
}
</div> </div>
) )
} }

View File

@@ -90,7 +90,7 @@ function SQL({nodeData, node, treeNodeInfo, isActive, isStale, setIsStale}) {
setNodeSQL(sql); setNodeSQL(sql);
} }
setIsStale(false); setIsStale(false);
}, [isStale, isActive]); }, [isStale, isActive, nodeData?.id]);
return ( return (
<> <>

View File

@@ -237,10 +237,11 @@ function Statistics({ nodeData, nodeItem, node, treeNodeInfo, isActive, isStale,
} }
} }
if (message != '') { if (message != '') {
setTableData([]);
setMsg(message); setMsg(message);
} }
setIsStale(false); setIsStale(false);
}, [isStale, isActive]); }, [isStale, isActive, nodeData?.id]);
return ( return (
<> <>

View File

@@ -1,4 +1,4 @@
import React, {useLayoutEffect, useMemo } from 'react'; import React, {useEffect, useMemo, useState } from 'react';
import AppMenuBar from './AppMenuBar'; import AppMenuBar from './AppMenuBar';
import ObjectBreadcrumbs from './components/ObjectBreadcrumbs'; import ObjectBreadcrumbs from './components/ObjectBreadcrumbs';
import Layout, { LayoutDocker, getDefaultGroup } from './helpers/Layout'; import Layout, { LayoutDocker, getDefaultGroup } from './helpers/Layout';
@@ -35,27 +35,27 @@ const mainPanelGroup = {
}; };
export const processesPanelData = { export const processesPanelData = {
id: BROWSER_PANELS.PROCESSES, title: gettext('Processes'), content: <Processes />, closable: true, group: 'main' id: BROWSER_PANELS.PROCESSES, title: gettext('Processes'), content: <Processes />, closable: true, group: 'playground'
}; };
export const defaultTabsData = [ export const defaultTabsData = [
{ {
id: BROWSER_PANELS.DASHBOARD, title: gettext('Dashboard'), content: <Dashboard />, closable: true, group: 'main' id: BROWSER_PANELS.DASHBOARD, title: gettext('Dashboard'), content: <Dashboard />, closable: true, group: 'playground'
}, },
{ {
id: BROWSER_PANELS.PROPERTIES, title: gettext('Properties'), content: <Properties />, closable: true, group: 'main' id: BROWSER_PANELS.PROPERTIES, title: gettext('Properties'), content: <Properties />, closable: true, group: 'playground'
}, },
{ {
id: BROWSER_PANELS.SQL, title: gettext('SQL'), content: <SQL />, closable: true, group: 'main' id: BROWSER_PANELS.SQL, title: gettext('SQL'), content: <SQL />, closable: true, group: 'playground'
}, },
{ {
id: BROWSER_PANELS.STATISTICS, title: gettext('Statistics'), content: <Statistics />, closable: true, group: 'main' id: BROWSER_PANELS.STATISTICS, title: gettext('Statistics'), content: <Statistics />, closable: true, group: 'playground'
}, },
{ {
id: BROWSER_PANELS.DEPENDENCIES, title: gettext('Dependencies'), content: <Dependencies />, closable: true, group: 'main' id: BROWSER_PANELS.DEPENDENCIES, title: gettext('Dependencies'), content: <Dependencies />, closable: true, group: 'playground'
}, },
{ {
id: BROWSER_PANELS.DEPENDENTS, title: gettext('Dependents'), content: <Dependents />, closable: true, group: 'main' id: BROWSER_PANELS.DEPENDENTS, title: gettext('Dependents'), content: <Dependents />, closable: true, group: 'playground'
}, },
processesPanelData, processesPanelData,
]; ];
@@ -81,9 +81,9 @@ export default function BrowserComponent({pgAdmin}) {
{ {
size: 80, size: 80,
id: BROWSER_PANELS.MAIN, id: BROWSER_PANELS.MAIN,
group: 'main', group: 'playground',
tabs: defaultTabsData.map((t)=>LayoutDocker.getPanel(t)), tabs: defaultTabsData.map((t)=>LayoutDocker.getPanel(t)),
panelLock: {panelStyle: 'main'}, panelLock: {panelStyle: 'playground'},
} }
] ]
}, },
@@ -92,10 +92,13 @@ export default function BrowserComponent({pgAdmin}) {
}; };
const {isLoading, failed} = usePreferences(); const {isLoading, failed} = usePreferences();
let { name: browser } = useMemo(()=>getBrowser(), []); let { name: browser } = useMemo(()=>getBrowser(), []);
const [uiReady, setUiReady] = useState(false);
useLayoutEffect(()=>{ useEffect(()=>{
if(uiReady) {
pgAdmin?.Browser?.uiloaded?.(); pgAdmin?.Browser?.uiloaded?.();
}, []); }
}, [uiReady]);
if(isLoading) { if(isLoading) {
return <></>; return <></>;
@@ -107,9 +110,9 @@ export default function BrowserComponent({pgAdmin}) {
return ( return (
<PgAdminContext.Provider value={pgAdmin}> <PgAdminContext.Provider value={pgAdmin}>
<ModalProvider> <ModalProvider>
<NotifierProvider pgAdmin={pgAdmin} /> <NotifierProvider pgAdmin={pgAdmin} onReady={()=>setUiReady(true)}/>
{browser != 'Nwjs' && <AppMenuBar />} {browser != 'Nwjs' && <AppMenuBar />}
<div style={{height: 'calc(100% - 32px)'}}> <div style={{height: 'calc(100% - 30px)'}}>
<Layout <Layout
getLayoutInstance={(obj)=>{ getLayoutInstance={(obj)=>{
pgAdmin.Browser.docker = obj; pgAdmin.Browser.docker = obj;
@@ -119,7 +122,7 @@ export default function BrowserComponent({pgAdmin}) {
savedLayout={pgAdmin.Browser.utils.layout} savedLayout={pgAdmin.Browser.utils.layout}
groups={{ groups={{
'object-explorer': objectExplorerGroup, 'object-explorer': objectExplorerGroup,
'main': mainPanelGroup, 'playground': mainPanelGroup,
}} }}
noContextGroups={['object-explorer']} noContextGroups={['object-explorer']}
resetToTabPanel={BROWSER_PANELS.MAIN} resetToTabPanel={BROWSER_PANELS.MAIN}

View File

@@ -39,6 +39,7 @@ import DataGridView from './DataGridView';
import { useIsMounted } from '../custom_hooks'; import { useIsMounted } from '../custom_hooks';
import ErrorBoundary from '../helpers/ErrorBoundary'; import ErrorBoundary from '../helpers/ErrorBoundary';
import { usePgAdmin } from '../BrowserComponent'; import { usePgAdmin } from '../BrowserComponent';
import { PgButtonGroup } from '../components/Buttons';
const useDialogStyles = makeStyles((theme)=>({ const useDialogStyles = makeStyles((theme)=>({
root: { root: {
@@ -866,7 +867,7 @@ const usePropsStyles = makeStyles((theme)=>({
flexGrow: 1, flexGrow: 1,
}, },
toolbar: { toolbar: {
padding: theme.spacing(0.5, 1), padding: theme.spacing(1),
background: theme.palette.background.default, background: theme.palette.background.default,
...theme.mixins.panelBorder.bottom, ...theme.mixins.panelBorder.bottom,
}, },
@@ -1000,11 +1001,13 @@ function SchemaPropertiesView({
<Box className={classes.root}> <Box className={classes.root}>
<Loader message={loaderText}/> <Loader message={loaderText}/>
<Box className={classes.toolbar}> <Box className={classes.toolbar}>
<PgButtonGroup size="small">
<PgIconButton <PgIconButton
data-test="help" onClick={()=>props.onHelp(true, false)} icon={<InfoIcon />} disabled={props.disableSqlHelp} data-test="help" onClick={()=>props.onHelp(true, false)} icon={<InfoIcon />} disabled={props.disableSqlHelp}
title="SQL help for this object type." className={classes.buttonMargin} /> title="SQL help for this object type." />
<PgIconButton data-test="edit" <PgIconButton data-test="edit"
onClick={props.onEdit} icon={<EditIcon />} title={gettext('Edit object...')} /> onClick={props.onEdit} icon={<EditIcon />} title={gettext('Edit object...')} />
</PgButtonGroup>
</Box> </Box>
<Box className={clsx(classes.form, classes.formProperties)}> <Box className={clsx(classes.form, classes.formProperties)}>
<Box> <Box>

View File

@@ -413,6 +413,9 @@ function getFinalTheme(baseTheme) {
MuiAccordion: { MuiAccordion: {
root: { root: {
...mixins.panelBorder, ...mixins.panelBorder,
'&.Mui-expanded': {
marginBottom: '8px',
},
} }
}, },
MuiAccordionSummary: { MuiAccordionSummary: {

View File

@@ -41,10 +41,14 @@ export default function rcdockOverride(theme) {
}, },
'& .dock-tab-active': { '& .dock-tab-active': {
color: theme.palette.text.primary, color: theme.palette.text.primary,
cursor: 'move',
'&::hover': { '&::hover': {
color: theme.palette.text.primary, color: theme.palette.text.primary,
} }
}, },
'& .dock-tab-btn': {
pointerEvents: 'none',
}
}, },
'&.dock-style-dialogs': { '&.dock-style-dialogs': {
borderRadius: theme.shape.borderRadius, borderRadius: theme.shape.borderRadius,
@@ -159,7 +163,30 @@ export default function rcdockOverride(theme) {
}, },
'& .drag-accept-reject::after': { '& .drag-accept-reject::after': {
content: '', content: '',
},
'& .dock-nav-more': {
color: theme.custom.icon.contrastText
}
},
'.dock-dropdown': {
zIndex: 1004,
'& .dock-dropdown-menu': {
padding: '4px 0px',
backgroundColor: theme.palette.background.default,
color: theme.palette.text.primary,
border: `1px solid ${theme.otherVars.borderColor}`,
},
'& .dock-dropdown-menu-item': {
display: 'flex',
padding: '3px 12px',
color: theme.palette.text.primary,
transition: 'none',
'&.dock-dropdown-menu-item-active, &:hover': {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
} }
} }
},
}; };
} }

View File

@@ -69,7 +69,7 @@ export default function ToolView() {
manualClose: true, manualClose: true,
...tabParams, ...tabParams,
cache: false, cache: false,
group: 'main' group: 'playground'
}, BROWSER_PANELS.MAIN, 'middle', true); }, BROWSER_PANELS.MAIN, 'middle', true);
} }
}); });

View File

@@ -81,11 +81,11 @@ const useStyles = makeStyles((theme)=>({
}, },
noBorder: { noBorder: {
border: 0, border: 0,
color: 'inherit',
backgroundColor: 'transparent', backgroundColor: 'transparent',
color: theme.custom.icon.contrastText,
'&:hover': { '&:hover': {
border: 0, border: 0,
color: 'inherit', color: theme.custom.icon.contrastText,
backgroundColor: 'inherit', backgroundColor: 'inherit',
filter: 'brightness(85%)', filter: 'brightness(85%)',
}, },

View File

@@ -92,7 +92,7 @@ const useStyles = makeStyles((theme) => ({
pgTableHeader: { pgTableHeader: {
display: 'flex', display: 'flex',
background: theme.palette.background.default, background: theme.palette.background.default,
padding: '4px 8px', padding: '8px 8px 4px',
}, },
tableRowContent:{ tableRowContent:{
display: 'flex', display: 'flex',

View File

@@ -118,7 +118,6 @@ export class FileTreeX extends React.Component<IFileTreeXProps> {
setPseudoActiveFile: this.setPseudoActiveFile, setPseudoActiveFile: this.setPseudoActiveFile,
toggleDirectory: this.toggleDirectory, toggleDirectory: this.toggleDirectory,
closeDir: this.closeDir, closeDir: this.closeDir,
remove: this.removeDir,
newFile: async (dirOrPath: Directory | string) => this.supervisePrompt(await handle.promptNewFile(dirOrPath as string)), newFile: async (dirOrPath: Directory | string) => this.supervisePrompt(await handle.promptNewFile(dirOrPath as string)),
newFolder: async (dirOrPath: Directory | string) => this.supervisePrompt(await handle.promptNewDirectory(dirOrPath as string)), newFolder: async (dirOrPath: Directory | string) => this.supervisePrompt(await handle.promptNewDirectory(dirOrPath as string)),
onBlur: (callback) => this.events.add(FileTreeXEvent.OnBlur, callback), onBlur: (callback) => this.events.add(FileTreeXEvent.OnBlur, callback),

View File

@@ -335,7 +335,7 @@ export function getDefaultGroup() {
closable: false, closable: false,
maximizable: false, maximizable: false,
floatable: false, floatable: false,
moreIcon: <ExpandMoreIcon style={{height: '0.9em'}} />, moreIcon: <ExpandMoreIcon style={{height: '0.9em', marginTop: '4px'}} />,
panelExtra: (panelData, context) => { panelExtra: (panelData, context) => {
let icon = <ExpandDialogIcon style={{width: '0.7em'}}/>; let icon = <ExpandDialogIcon style={{width: '0.7em'}}/>;
let title = gettext('Maximise'); let title = gettext('Maximise');

View File

@@ -183,13 +183,14 @@ class Notifier {
} }
} }
export function NotifierProvider({ pgAdmin, pgWindow, getInstance, children }) { export function NotifierProvider({ pgAdmin, pgWindow, getInstance, children, onReady }) {
const modal = useModal(); const modal = useModal();
useEffect(()=>{ useEffect(()=>{
// if open in an iframe then use top pgAdmin // if open in an iframe then use top pgAdmin
if(window.self != window.top) { if(window.self != window.top) {
pgAdmin.Browser.notifier = new Notifier(modal, pgWindow.pgAdmin.Browser.notifier.snackbar); pgAdmin.Browser.notifier = new Notifier(modal, pgWindow.pgAdmin.Browser.notifier.snackbar);
onReady?.();
getInstance?.(pgAdmin.Browser.notifier); getInstance?.(pgAdmin.Browser.notifier);
} }
}, []); }, []);
@@ -203,6 +204,7 @@ export function NotifierProvider({ pgAdmin, pgWindow, getInstance, children }) {
ref={(obj)=>{ ref={(obj)=>{
pgAdmin.Browser.notifier = new Notifier(modal, new SnackbarNotifier(obj)); pgAdmin.Browser.notifier = new Notifier(modal, new SnackbarNotifier(obj));
getInstance?.(pgAdmin.Browser.notifier); getInstance?.(pgAdmin.Browser.notifier);
onReady?.();
}} }}
> >
{children} {children}
@@ -221,6 +223,7 @@ NotifierProvider.propTypes = {
pgWindow: PropTypes.object, pgWindow: PropTypes.object,
getInstance: PropTypes.func, getInstance: PropTypes.func,
children: CustomPropTypes.children, children: CustomPropTypes.children,
onReady: PropTypes.func,
}; };
export default Notifier; export default Notifier;

View File

@@ -960,6 +960,7 @@ table.table-empty-rows{
.dialog-node-icon { .dialog-node-icon {
margin-right: 2px !important; margin-right: 2px !important;
padding: 0px 10px; padding: 0px 10px;
background-position: 50%;
} }
textarea { textarea {

View File

@@ -75,10 +75,10 @@
}); });
</script> </script>
<script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.main.js') }}" ></script> <script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.react.js') }}" ></script>
<!-- View specified scripts -->
<script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.main.js') }}" ></script> <script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.main.js') }}" ></script>
<script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.others.js') }}" ></script> <script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.others.js') }}" ></script>
<script type="application/javascript" src="{{ url_for('static', filename='js/generated/vendor.sqleditor.js') }}"></script>
<script type="application/javascript" src="{{ url_for('static', filename='js/generated/pgadmin_commons.js') }}" ></script> <script type="application/javascript" src="{{ url_for('static', filename='js/generated/pgadmin_commons.js') }}" ></script>
</head> </head>

View File

@@ -824,6 +824,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
schema={debuggerArgsSchema.current} schema={debuggerArgsSchema.current}
showFooter={false} showFooter={false}
isTabView={false} isTabView={false}
Notifier={pgAdmin.Browser.notifier}
onDataChange={(isChanged, changedData) => { onDataChange={(isChanged, changedData) => {
let isValid = false; let isValid = false;
let skipStep = false; let skipStep = false;

View File

@@ -393,19 +393,19 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros}) {
{ {
shortcut: queryToolPref.execute_query, shortcut: queryToolPref.execute_query,
options: { options: {
callback: ()=>{!buttonsDisabled['execute']?executeQuery():null;} callback: ()=>{!buttonsDisabled['execute']&&executeQuery();}
} }
}, },
{ {
shortcut: queryToolPref.explain_query, shortcut: queryToolPref.explain_query,
options: { options: {
callback: (e)=>{e.preventDefault(); !buttonsDisabled['explain']?explain():null;} callback: (e)=>{e.preventDefault(); !buttonsDisabled['explain']&&explain();}
} }
}, },
{ {
shortcut: queryToolPref.explain_analyze_query, shortcut: queryToolPref.explain_analyze_query,
options: { options: {
callback: ()=>{!buttonsDisabled['explain_analyse']?explainAnalyse():null;} callback: ()=>{!buttonsDisabled['explain_analyse']&&explainAnalyse();}
} }
}, },
{ {

View File

@@ -580,6 +580,30 @@ module.exports = [{
] : [], ] : [],
splitChunks: { splitChunks: {
cacheGroups: { cacheGroups: {
vendor_sqleditor: {
name: 'vendor_sqleditor',
filename: 'vendor.sqleditor.js',
chunks: 'all',
reuseExistingChunk: true,
priority: 9,
minChunks: 2,
enforce: true,
test(module) {
return webpackShimConfig.matchModules(module, ['jsoneditor', 'leaflet']);
},
},
vendor_react: {
name: 'vendor_react',
filename: 'vendor.react.js',
chunks: 'all',
reuseExistingChunk: true,
priority: 8,
minChunks: 2,
enforce: true,
test(module) {
return webpackShimConfig.matchModules(module, ['react', 'react-dom']);
},
},
vendor_main: { vendor_main: {
name: 'vendor_main', name: 'vendor_main',
filename: 'vendor.main.js', filename: 'vendor.main.js',
@@ -589,7 +613,7 @@ module.exports = [{
minChunks: 2, minChunks: 2,
enforce: true, enforce: true,
test(module) { test(module) {
return webpackShimConfig.matchModules(module, ['react', 'react-dom', 'bootstrap', 'popper']); return webpackShimConfig.matchModules(module, ['codemirror', 'rc-', '@material-ui']);
}, },
}, },
vendor_others: { vendor_others: {