Enable the start debugging button once execution is completed. Fixes #7517

This commit is contained in:
Nikhil Mohite
2022-07-01 12:41:06 +05:30
committed by Akshay Joshi
parent 7d0ed90796
commit 9c745db413
7 changed files with 89 additions and 68 deletions

View File

@@ -18,3 +18,5 @@ Housekeeping
Bug fixes
*********
| `Issue #7517 <https://redmine.postgresql.org/issues/7517>`_ - Enable the start debugging button once execution is completed.

View File

@@ -985,7 +985,7 @@ def start_debugger_listener(trans_id):
# If user again start the same debug function with different arguments
# then we need to save that values to session variable and database.
if request.method == 'POST':
data = json.loads(request.values['data'], encoding='utf-8')
data = json.loads(request.data, encoding='utf-8')
if data:
de_inst.function_data['args_value'] = data
de_inst.update_session()

View File

@@ -47,8 +47,8 @@ export const MENUS = {
STEPINTO: 'step-into',
STEPOVER: 'step-over',
STOP: 'stop',
CONTINUE: 'continue',
CLEAR_ALL_BREAKPOINT: 'clear-al-breakpoint',
START: 'start',
CLEAR_ALL_BREAKPOINT: 'clear-all-breakpoint',
TOGGLE_BREAKPOINT: 'toggle-breakpoint'
};

View File

@@ -69,7 +69,7 @@ const useStyles = makeStyles((theme) =>
);
export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug, isEdbProc, transId, ...props }) {
export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug, isEdbProc, transId, pgTreeInfo, pgData, ...props }) {
const classes = useStyles();
const debuggerArgsSchema = useRef(new DebuggerArgumentSchema());
const api = getApiInstance();
@@ -85,16 +85,13 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
var _Url = null;
if (restartDebug == 0) {
var t = pgAdmin.Browser.tree,
i = t.selected(),
d = i ? t.itemData(i) : undefined;
if (!d)
if (!pgData)
return;
var treeInfo = t.getTreeNodeHierarchy(i);
var treeInfo = pgTreeInfo;
if (d._type == 'function') {
if (pgData._type == 'function') {
// Get the existing function parameters available from sqlite database
_Url = url_for('debugger.get_arguments', {
'sid': treeInfo.server._id,
@@ -102,7 +99,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
'scid': treeInfo.schema._id,
'func_id': treeInfo.function._id,
});
} else if (d._type == 'procedure') {
} else if (pgData._type == 'procedure') {
// Get the existing function parameters available from sqlite database
_Url = url_for('debugger.get_arguments', {
'sid': treeInfo.server._id,
@@ -110,7 +107,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
'scid': treeInfo.schema._id,
'func_id': treeInfo.procedure._id,
});
} else if (d._type == 'edbfunc') {
} else if (pgData._type == 'edbfunc') {
// Get the existing function parameters available from sqlite database
_Url = url_for('debugger.get_arguments', {
'sid': treeInfo.server._id,
@@ -118,7 +115,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
'scid': treeInfo.schema._id,
'func_id': treeInfo.edbfunc._id,
});
} else if (d._type == 'edbproc') {
} else if (pgData._type == 'edbproc') {
// Get the existing function parameters available from sqlite database
_Url = url_for('debugger.get_arguments', {
'sid': treeInfo.server._id,
@@ -452,18 +449,16 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
let base_url = null;
if (restartDebug == 0) {
let selectedItem = pgAdmin.Browser.tree.selected();
let itemData = pgAdmin.Browser.tree.itemData(selectedItem);
if (!itemData)
if (!pgData)
return;
let treeInfo = pgAdmin.Browser.tree.getTreeNodeHierarchy(selectedItem);
let treeInfo = pgTreeInfo;
base_url = url_for('debugger.clear_arguments', {
'sid': treeInfo.server._id,
'did': treeInfo.database._id,
'scid': treeInfo.schema._id,
'func_id': itemData._id,
'func_id': pgData._id,
});
} else {
base_url = url_for('debugger.clear_arguments', {
@@ -587,7 +582,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
'is_null': arg.is_null ? 1 : 0,
'is_expression': arg.expr ? 1 : 0,
'use_default': arg.use_default ? 1 : 0,
'value': debuggerInfo.value,
'value': arg.value,
'is_array_value': arg?.isArrayType,
});
}
@@ -675,43 +670,27 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
return baseUrl;
}
function getSelectedNodeData() {
var treeInfo, d;
if (restartDebug == 0) {
var t = pgAdmin.Browser.tree,
i = t.selected();
d = i ? t.itemData(i) : undefined;
if (!d)
return;
treeInfo = t.getTreeNodeHierarchy(i);
}
return [treeInfo, d];
}
function startDebugging() {
var self = this;
setLoaderText('Starting debugger.');
try {
/* Initialize the target once the debug button is clicked and create asynchronous connection
and unique transaction ID If the debugging is started again then treeInfo is already stored. */
var [treeInfo, d] = getSelectedNodeData();
if (!d) return;
var treeInfo = pgTreeInfo;
if (!pgData) return;
var argsValueList = [];
var sqliteFuncArgsList = [];
var intCount = 0;
let argsList = []; //debuggerFinalArgs.current?.changed ? [] : debuggerArgsData.current.aregsCollection;
let argsList = [];
let argSet = [];
setDebuggingArgs(argsList, argSet);
argsList.forEach(arg => {
checkArgsVal(arg, argsValueList);
setSqliteFuncArgs(d, treeInfo, arg, intCount, sqliteFuncArgsList);
setSqliteFuncArgs(pgData, treeInfo, arg, intCount, sqliteFuncArgsList);
intCount = intCount + 1;
});
@@ -719,7 +698,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
/* If debugging is not started again then we should initialize the target otherwise not */
if (restartDebug == 0) {
baseUrl = checkTypeAndGetUrl(d, treeInfo);
baseUrl = checkTypeAndGetUrl(pgData, treeInfo);
api({
url: baseUrl,
@@ -791,7 +770,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
});
}
var _url = getSetArgsUrl(d, treeInfo);
var _url = getSetArgsUrl(pgData, treeInfo);
api({
url: _url,
@@ -831,8 +810,12 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
method: 'POST',
data: JSON.stringify(argsValueList),
})
.then(function () {/*This is intentional (SonarQube)*/ })
.then(function () {
/* Close the debugger modal dialog */
props.closeModal();
})
.catch(function (error) {
props.closeModal();
Notify.alert(
gettext('Debugger Listener Startup Error'),
gettext(error.response.data)
@@ -851,7 +834,9 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
method: 'POST',
data: JSON.stringify(sqliteFuncArgsList),
})
.then(function () {/*This is intentional (SonarQube)*/ })
.then(function () {
/*This is intentional (SonarQube)*/
})
.catch(function (error) {
setLoaderText('');
Notify.alert(
@@ -942,5 +927,7 @@ DebuggerArgumentComponent.propTypes = {
isEdbProc: PropTypes.bool,
transId: PropTypes.string,
closeModal: PropTypes.func,
pgTreeInfo: PropTypes.object,
pgData: PropTypes.object,
};

View File

@@ -31,6 +31,7 @@ import { ToolBar } from './ToolBar';
import { Stack } from './Stack';
import { Results } from './Results';
import { LocalVariablesAndParams } from './LocalVariablesAndParams';
import DebuggerArgumentComponent from './DebuggerArgumentComponent';
export const DebuggerContext = React.createContext();
export const DebuggerEventsContext = React.createContext();
@@ -524,7 +525,7 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
// Restarting debugging in the same transaction do not work
// We will give same behaviour as pgAdmin3 and disable all buttons
enableToolbarButtons(MENUS.CONTINUE);
disableToolbarButtons();
// Set the Alertify message to inform the user that execution
// is completed.
@@ -571,7 +572,26 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
listener.
*/
if (res.data.data.result.require_input) {
params.funcArgsInstance.show(res.data.data.result, restart_dbg);
let t = pgAdmin.Browser.tree,
i = t.selected(),
d = i ? t.itemData(i) : undefined;
let treeInfo = t.getTreeNodeHierarchy(i);
if (d) {
let isEdbProc = d._type == 'edbproc';
modal.showModal(gettext('Debugger'), (closeModal) => {
return <DebuggerArgumentComponent
closeModal={closeModal}
debuggerInfo={res.data.data.result}
restartDebug={restart_dbg}
isEdbProc={isEdbProc}
transId={params.transId.toString()}
pgData={d}
pgTreeInfo={treeInfo}
></DebuggerArgumentComponent>;
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md });
}
} else {
// Debugging of void function is started again so we need to start
// the listener again
@@ -612,7 +632,7 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
// If debugging is stopped by user then do not enable
// continue/restart button
if (!params.directDebugger.is_user_aborted_debugging) {
enableToolbarButtons(MENUS.CONTINUE);
enableToolbarButtons();
params.directDebugger.is_user_aborted_debugging = false;
}
@@ -620,7 +640,7 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
params.directDebugger.is_polling_required = false;
};
const updateResultAnsMessages = (res) => {
const updateResultAndMessages = (res) => {
if (res.data.data.result != null) {
setActiveLine(-1);
// Call function to update results information and set result panel focus
@@ -640,6 +660,7 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
// "Continue/Start" button because user can still
// start the same execution again.
disableToolbarButtons();
enableToolbarButtons(MENUS.START);
// Stop further pooling
params.directDebugger.is_polling_required = false;
@@ -706,11 +727,12 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panel, ev
// "Continue/Start" button because user can still
// start the same execution again.
disableToolbarButtons();
enableToolbarButtons(MENUS.START);
// Stop further polling
params.directDebugger.is_polling_required = false;
} else {
updateResultAnsMessages(res);
updateResultAndMessages(res);
}
} else if (res.data.data.status === 'Busy') {
// If status is Busy then poll the result by recursive call to

View File

@@ -25,7 +25,7 @@ import url_for from 'sources/url_for';
import { PgButtonGroup, PgIconButton } from '../../../../../static/js/components/Buttons';
import { DebuggerContext, DebuggerEventsContext } from './DebuggerComponent';
import { DEBUGGER_EVENTS } from '../DebuggerConstants';
import { DEBUGGER_EVENTS, MENUS } from '../DebuggerConstants';
const useStyles = makeStyles((theme) => ({
root: {
@@ -45,6 +45,8 @@ export function ToolBar() {
const eventBus = useContext(DebuggerEventsContext);
let preferences = debuggerCtx.preferences.debugger;
// JS not allowing to use constants as key hence unable to use MENUS constants,
// If required any changes in key update MENUS constans as well form DebuggerConstans file.
const [buttonsDisabled, setButtonsDisabled] = useState({
'stop': true,
'clear-all-breakpoints': true,
@@ -94,21 +96,21 @@ export function ToolBar() {
useEffect(() => {
eventBus.registerListener(DEBUGGER_EVENTS.DISABLE_MENU, () => {
setDisableButton('start', true);
setDisableButton('step-into', true);
setDisableButton('step-over', true);
setDisableButton('clear-all-breakpoints', true);
setDisableButton('toggle-breakpoint', true);
setDisableButton('stop', true);
setDisableButton(MENUS.START, true);
setDisableButton(MENUS.STEPINTO, true);
setDisableButton(MENUS.STEPOVER, true);
setDisableButton(MENUS.CLEAR_ALL_BREAKPOINT, true);
setDisableButton(MENUS.TOGGLE_BREAKPOINT, true);
setDisableButton(MENUS.STOP, true);
});
eventBus.registerListener(DEBUGGER_EVENTS.ENABLE_MENU, () => {
setDisableButton('start', false);
setDisableButton('step-into', false);
setDisableButton('step-over', false);
setDisableButton('clear-all-breakpoints', false);
setDisableButton('toggle-breakpoint', false);
setDisableButton('stop', false);
setDisableButton(MENUS.START, false);
setDisableButton(MENUS.STEPINTO, false);
setDisableButton(MENUS.STEPOVER, false);
setDisableButton(MENUS.CLEAR_ALL_BREAKPOINT, false);
setDisableButton(MENUS.TOGGLE_BREAKPOINT, false);
setDisableButton(MENUS.STOP, false);
});
eventBus.registerListener(DEBUGGER_EVENTS.ENABLE_SPECIFIC_MENU, (key) => {
@@ -120,21 +122,21 @@ export function ToolBar() {
return (
<Box className={classes.root}>
<PgButtonGroup size="small">
<PgIconButton data-test='step-in' title={gettext('Step into')} disabled={buttonsDisabled['step-into']} icon={<FormatIndentIncreaseIcon />} onClick={() => { stepInTODebugger(); }}
<PgIconButton data-test='step-in' title={gettext('Step into')} disabled={buttonsDisabled[MENUS.STEPINTO]} icon={<FormatIndentIncreaseIcon />} onClick={() => { stepInTODebugger(); }}
accesskey={shortcut_key(preferences?.btn_step_into)} />
<PgIconButton data-test='step-over' title={gettext('Step over')} disabled={buttonsDisabled['step-over']} icon={<FormatIndentDecreaseIcon />} onClick={() => { stepOverDebugger(); }}
<PgIconButton data-test='step-over' title={gettext('Step over')} disabled={buttonsDisabled[MENUS.STEPOVER]} icon={<FormatIndentDecreaseIcon />} onClick={() => { stepOverDebugger(); }}
accesskey={shortcut_key(preferences?.btn_step_over)} />
<PgIconButton data-test='debugger-contiue' title={gettext('Continue/Start')} disabled={buttonsDisabled['start']} icon={<PlayCircleFilledWhiteIcon />} onClick={() => { continueDebugger(); }}
<PgIconButton data-test='debugger-contiue' title={gettext('Continue/Start')} disabled={buttonsDisabled[MENUS.START]} icon={<PlayCircleFilledWhiteIcon />} onClick={() => { continueDebugger(); }}
accesskey={shortcut_key(preferences?.btn_start)} />
</PgButtonGroup>
<PgButtonGroup size="small">
<PgIconButton data-test='toggle-breakpoint' title={gettext('Toggle breakpoint')} disabled={buttonsDisabled['toggle-breakpoint']} icon={<FiberManualRecordIcon style={{height: '2rem'}} />}
<PgIconButton data-test='toggle-breakpoint' title={gettext('Toggle breakpoint')} disabled={buttonsDisabled[MENUS.TOGGLE_BREAKPOINT]} icon={<FiberManualRecordIcon style={{height: '2rem'}} />}
accesskey={shortcut_key(preferences?.btn_toggle_breakpoint)} onClick={() => { toggleBreakpoint(); }} />
<PgIconButton data-test='clear-breakpoint' title={gettext('Clear all breakpoints')} disabled={buttonsDisabled['clear-all-breakpoints']} icon={<NotInterestedIcon />}
<PgIconButton data-test='clear-breakpoint' title={gettext('Clear all breakpoints')} disabled={buttonsDisabled[MENUS.CLEAR_ALL_BREAKPOINT]} icon={<NotInterestedIcon />}
accesskey={shortcut_key(preferences?.btn_clear_breakpoints)} onClick={() => { clearAllBreakpoint(); }} />
</PgButtonGroup>
<PgButtonGroup size="small">
<PgIconButton data-test='stop-debugger' title={gettext('Stop')} icon={<StopIcon style={{height: '2rem'}} />} disabled={buttonsDisabled['stop']} onClick={() => { stop(); }}
<PgIconButton data-test='stop-debugger' title={gettext('Stop')} icon={<StopIcon style={{height: '2rem'}} />} disabled={buttonsDisabled[MENUS.STOP]} onClick={() => { stop(); }}
accesskey={shortcut_key(preferences?.btn_stop)} />
</PgButtonGroup>
<PgButtonGroup size="small">

View File

@@ -18,9 +18,17 @@ import DebuggerArgumentComponent from './components/DebuggerArgumentComponent';
export default class FunctionArguments {
show(debugInfo, restartDebug, isEdbProc, transId) {
var t = pgAdmin.Browser.tree,
i = t.selected(),
d = i ? t.itemData(i) : undefined;
if (!d)
return;
let treeInfo = t.getTreeNodeHierarchy(i);
// Render Debugger argument component
Notify.showModal(gettext('Debugger'), (closeModal) => {
return <DebuggerArgumentComponent closeModal={closeModal} debuggerInfo={debugInfo} restartDebug={restartDebug} isEdbProc={isEdbProc} transId={transId}></DebuggerArgumentComponent>;
return <DebuggerArgumentComponent closeModal={closeModal} debuggerInfo={debugInfo} restartDebug={restartDebug} isEdbProc={isEdbProc} transId={transId} pgTreeInfo={treeInfo} pgData={d}></DebuggerArgumentComponent>;
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md });
}
}