diff --git a/web/package.json b/web/package.json index 8f625ab77..ff59c9251 100644 --- a/web/package.json +++ b/web/package.json @@ -151,7 +151,7 @@ "react": "^17.0.1", "react-aspen": "^1.1.0", "react-checkbox-tree": "^1.7.2", - "react-data-grid": "^7.0.0-beta.11", + "react-data-grid": "^7.0.0-beta.12", "react-dom": "^17.0.1", "react-draggable": "^4.4.4", "react-leaflet": "^3.2.2", diff --git a/web/pgadmin/static/js/Explain/Analysis.jsx b/web/pgadmin/static/js/Explain/Analysis.jsx index bf4553dd2..17ed8479f 100644 --- a/web/pgadmin/static/js/Explain/Analysis.jsx +++ b/web/pgadmin/static/js/Explain/Analysis.jsx @@ -15,6 +15,7 @@ import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'; import HTMLReactParse from 'html-react-parser'; import { commonTableStyles } from '../Theme'; import PropTypes from 'prop-types'; +import gettext from 'sources/gettext'; const useStyles = makeStyles((theme)=>({ collapsible: { @@ -172,26 +173,26 @@ export default function Analysis({explainTable}) { - + - - + - + - + - + - - - + + + diff --git a/web/pgadmin/static/js/Explain/ExplainStatistics.jsx b/web/pgadmin/static/js/Explain/ExplainStatistics.jsx index c9d1ce670..7a114a42b 100644 --- a/web/pgadmin/static/js/Explain/ExplainStatistics.jsx +++ b/web/pgadmin/static/js/Explain/ExplainStatistics.jsx @@ -92,7 +92,7 @@ export default function ExplainStatistics({explainTable}) { {_.sortBy(Object.keys(explainTable.statistics.tables)).map((key, i)=>{ let table = explainTable.statistics.tables[key]; - table.sum_of_times = _.sumBy(table.nodes, 'sum_of_times'); + table.sum_of_times = _.sumBy(Object.values(table.nodes), 'sum_of_times'); return {table.name} diff --git a/web/pgadmin/static/js/Explain/Graphical.jsx b/web/pgadmin/static/js/Explain/Graphical.jsx index be722f4b6..0ce0c6068 100644 --- a/web/pgadmin/static/js/Explain/Graphical.jsx +++ b/web/pgadmin/static/js/Explain/Graphical.jsx @@ -419,7 +419,7 @@ export default function Graphical({planData, ctx}) { } /> - +
diff --git a/web/pgadmin/static/js/Explain/index.jsx b/web/pgadmin/static/js/Explain/index.jsx index c5ff0bbe5..9f6854080 100644 --- a/web/pgadmin/static/js/Explain/index.jsx +++ b/web/pgadmin/static/js/Explain/index.jsx @@ -237,6 +237,14 @@ function nodeExplainTableData(_planData, _ctx) { info.statistics.nodes[node_info] = node; } +function parseExplainTableData(plan, ctx) { + nodeExplainTableData(plan, ctx); + + plan['Plans']?.map((p)=>{ + parseExplainTableData(p, ctx); + }); +} + function parsePlan(data, ctx) { var idx = 1, lvl = data.level = data.level || [idx], @@ -408,7 +416,6 @@ function parsePlan(data, ctx) { // Final Width and Height of current node data['width'] += maxChildWidth; data['Plans'] = plans; - nodeExplainTableData(data, ctx); return data; } @@ -456,6 +463,8 @@ function parsePlanData(data, ctx) { if (data && 'Settings' in data) { retPlan['Statistics']['Settings'] = data['Settings']; } + + parseExplainTableData(retPlan['Plan'], ctx); } return retPlan; } diff --git a/web/pgadmin/static/js/Theme/index.jsx b/web/pgadmin/static/js/Theme/index.jsx index 402e82439..2dbcadbe3 100644 --- a/web/pgadmin/static/js/Theme/index.jsx +++ b/web/pgadmin/static/js/Theme/index.jsx @@ -27,6 +27,18 @@ basicSettings = createMuiTheme(basicSettings, { typography: { fontSize: 14, htmlFontSize: 14, + fontFamily: [ + 'Roboto', + '"Helvetica Neue"', + '-apple-system', + 'BlinkMacSystemFont', + '"Segoe UI"', + 'Arial', + 'sans-serif', + '"Apple Color Emoji"', + '"Segoe UI Emoji"', + '"Segoe UI Symbol"', + ].join(','), }, shape: { borderRadius: 4, @@ -281,6 +293,9 @@ function getFinalTheme(baseTheme) { overrides: { MuiCssBaseline: { '@global': { + body: { + fontFamily: baseTheme.typography.fontFamily, + }, ul: { margin: 0, padding: 0, @@ -618,6 +633,11 @@ export const commonTableStyles = makeStyles((theme)=>({ borderBottom: '1px solid '+theme.otherVars.borderColor, }, }, + wrapTd: { + '& tbody td': { + whiteSpace: 'pre-wrap', + } + }, noHover: { '& tbody > tr': { '&:hover': { diff --git a/web/pgadmin/static/js/components/CodeMirror.jsx b/web/pgadmin/static/js/components/CodeMirror.jsx index 218efc8a3..c220ccb88 100644 --- a/web/pgadmin/static/js/components/CodeMirror.jsx +++ b/web/pgadmin/static/js/components/CodeMirror.jsx @@ -462,16 +462,12 @@ export default function CodeMirror({currEditor, name, value, options, events, re useEffect(()=>{ if(editor.current) { - if(disabled) { - editor.current.setOption('readOnly', true); - cmWrapper.current.classList.add(classes.hideCursor); - } else if(readonly) { + if(readonly || disabled) { editor.current.setOption('readOnly', true); editor.current.addKeyMap({'Tab': false}); editor.current.addKeyMap({'Shift-Tab': false}); cmWrapper.current.classList.add(classes.hideCursor); } else { - cmWrapper.current.classList.remove('cm_disabled'); editor.current.setOption('readOnly', false); editor.current.removeKeyMap('Tab'); editor.current.removeKeyMap('Shift-Tab'); diff --git a/web/pgadmin/static/js/components/EmptyPanelMessage.jsx b/web/pgadmin/static/js/components/EmptyPanelMessage.jsx index 8b96374f5..d8fc8d4f3 100644 --- a/web/pgadmin/static/js/components/EmptyPanelMessage.jsx +++ b/web/pgadmin/static/js/components/EmptyPanelMessage.jsx @@ -9,7 +9,9 @@ const useStyles = makeStyles((theme)=>({ color: theme.palette.text.primary, margin: 'auto', marginTop: '24px', - fontSize: '0.9em', + fontSize: '0.8rem', + display: 'flex', + alignItems: 'center', }, })); @@ -17,8 +19,8 @@ export default function EmptyPanelMessage({text}) { const classes = useStyles(); return ( - - {text} + + {text} ); } diff --git a/web/pgadmin/static/js/helpers/Layout.jsx b/web/pgadmin/static/js/helpers/Layout.jsx index 5074024cc..c9f8054e3 100644 --- a/web/pgadmin/static/js/helpers/Layout.jsx +++ b/web/pgadmin/static/js/helpers/Layout.jsx @@ -81,6 +81,9 @@ const useStyles = makeStyles((theme)=>({ }, '& > div': { padding: '4px 10px', + '&:focus': { + outline: '2px solid '+theme.otherVars.activeBorder, + } }, '& .drag-initiator': { display: 'flex', @@ -190,6 +193,11 @@ export class LayoutHelper { return Boolean(docker.find(panelId)); } + static isTabVisible(docker, panelId) { + let panelData = docker.find(panelId); + return panelData?.parent?.activeId == panelData.id; + } + static openTab(docker, panelData, refTabId, direction, forceRerender=false) { let panel = docker.find(panelData.id); if(panel) { @@ -203,6 +211,43 @@ export class LayoutHelper { docker.dockMove(LayoutHelper.getPanel(panelData), tgtPanel, direction); } } + + static moveTo(direction) { + let dockBar = document.activeElement.closest('.dock')?.querySelector('.dock-bar.drag-initiator'); + if(dockBar) { + let key = { + key: 'ArrowRight', keyCode: 39, which: 39, code: 'ArrowRight', + metaKey: false, ctrlKey: false, shiftKey: false, altKey: false, + bubbles: true, + }; + if(direction == 'right') { + key = { + ...key, + key: 'ArrowRight', keyCode: 39, which: 39, code: 'ArrowRight' + }; + } else if(direction == 'left') { + key = { + ...key, + key: 'ArrowLeft', keyCode: 37, which: 37, code: 'ArrowLeft', + }; + } + dockBar.dispatchEvent(new KeyboardEvent('keydown', key)); + } + } + + static switchPanel() { + let currDockPanel = document.activeElement.closest('.dock-panel.dock-style-default'); + let dockLayoutPanels = currDockPanel?.closest('.dock-layout').querySelectorAll('.dock-panel.dock-style-default'); + if(dockLayoutPanels?.length > 1) { + for(let i=0; i