From 8795b7e636203a348ae518f4afa2f00ff331bc51 Mon Sep 17 00:00:00 2001 From: pravesh-sharma Date: Fri, 6 Feb 2026 08:41:15 +0530 Subject: [PATCH 1/3] Fixed an issue where internal settings for the separate tools tab were not being restored during application relaunch. #8988 --- .../static/js/erd_tool/components/ERDTool.jsx | 5 +- .../js/erd_tool/components/MainToolBar.jsx | 59 ++++++++++++++++--- .../components/SchemaDiffButtonComponent.jsx | 9 ++- .../js/components/SchemaDiffCompare.jsx | 15 +++-- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx index d93ddf8de30..a487819fd97 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx @@ -177,6 +177,7 @@ export default class ERDTool extends React.Component { this.fmUtilsObj = new FileManagerUtils(this.apiObj, {modal: this.context}); this.restore = props.params.restore == 'true'; this.eventBus = new EventBus(); + this.toolbarPrefs = null; _.bindAll(this, ['onLoadDiagram', 'onSaveDiagram', 'onSQLClick', 'onImageClick', 'onSearchNode', 'onAddNewNode', 'onEditTable', 'onCloneNode', 'onDeleteNode', 'onNoteClick', @@ -408,6 +409,7 @@ export default class ERDTool extends React.Component { restoreToolContent = async (toolContent) => { if(toolContent){ + this.toolbarPrefs = toolContent.connectionInfo?.preferences || {}; if(toolContent?.modifiedExternally){ toolContent = await this.fmUtilsObj.warnFileReload(toolContent?.fileName, toolContent?.data, ''); } @@ -420,7 +422,7 @@ export default class ERDTool extends React.Component { this.registerModelEvents(); if(toolContent.fileName)this.setState({current_file: toolContent.fileName}); this.setState({dirty: true}); - this.eventBus.fireEvent(ERD_EVENTS.DIRTY, true, toolContent.data); + this.eventBus.fireEvent(ERD_EVENTS.DIRTY, true, toolContent.data, null, this.toolbarPrefs); } } }; @@ -1086,6 +1088,7 @@ export default class ERDTool extends React.Component { diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx index 124583f95e5..33a4527600e 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx @@ -51,7 +51,7 @@ const StyledBox = styled(Box)(({theme}) => ({ ...theme.mixins.panelBorder.bottom, })); -export function MainToolBar({preferences, eventBus, fillColor, textColor, notation, onNotationChange, connectionInfo}) { +export function MainToolBar({preferences, eventBus, fillColor, textColor, notation, onNotationChange, connectionInfo, toolbarPrefs}) { const theme = useTheme(); const [buttonsDisabled, setButtonsDisabled] = useState({ 'save': true, @@ -72,6 +72,7 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati const notationMenuRef = React.useRef(null); const isDirtyRef = React.useRef(null); const [checkedMenuItems, setCheckedMenuItems] = React.useState({}); + const notationRef = React.useRef(notation); const modal = useModal(); const setDisableButton = useCallback((name, disable=true)=>{ @@ -86,6 +87,15 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati [e.value]: newVal, }; }); + setSaveERDData((prev)=>{ + return { + ...prev, + toolbarPrefs: { + ...prev?.toolbarPrefs, + [e.value]: !prev?.toolbarPrefs?.[e.value], + }, + }; + }); }, []); const onHelpClick=()=>{ @@ -111,15 +121,31 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati }; useEffect(()=>{ - if(preferences) { + if(!_.isUndefined(toolbarPrefs) && !_.isNull(toolbarPrefs) && Object.keys(toolbarPrefs).length > 0) { + /* Apply toolbar prefs */ + if(!_.isUndefined(toolbarPrefs.sql_with_drop)) { + setCheckedMenuItems((prev)=>({ + ...prev, + sql_with_drop: toolbarPrefs.sql_with_drop, + })); + } + if(!_.isUndefined(toolbarPrefs.cardinality)) { + notationRef.current = toolbarPrefs.cardinality; + onNotationChange({'value': toolbarPrefs.cardinality}); + } else { + notationRef.current = notation; + } + } + else if(preferences) { /* Get the prefs first time */ if(_.isUndefined(checkedMenuItems.sql_with_drop)) { setCheckedMenuItems({ sql_with_drop: preferences.sql_with_drop, }); } + notationRef.current = notation; } - }, [preferences]); + }, [preferences, toolbarPrefs]); useEffect(()=>{ const events = [ @@ -134,11 +160,11 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati [ERD_EVENTS.ANY_ITEM_SELECTED, (selected)=>{ setDisableButton('drop-table', !selected); }], - [ERD_EVENTS.DIRTY, (isDirty, data, fileName)=>{ + [ERD_EVENTS.DIRTY, (isDirty, data, fileName, toolbarPrefs)=>{ isDirtyRef.current = isDirty; setDisableButton('save', !isDirty); if((isDirty || fileName) && isSaveToolDataEnabled('ERD')){ - setSaveERDData({data, fileName, isDirty}); + setSaveERDData({data, fileName, isDirty, toolbarPrefs}); } }], ]; @@ -153,8 +179,8 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati }, []); const [saveERDData, setSaveERDData] = useState(null); - useDelayDebounce(({data, fileName, isDirty})=>{ - saveToolData('ERD', {...connectionInfo,'open_file_name':fileName, 'is_editor_dirty': isDirty}, connectionInfo.trans_id, data); + useDelayDebounce(({data, fileName, isDirty, toolbarPrefs})=>{ + saveToolData('ERD', {...connectionInfo,'open_file_name':fileName, 'is_editor_dirty': isDirty, 'preferences': toolbarPrefs}, connectionInfo.trans_id, data); }, saveERDData, 500); useEffect(()=>{ @@ -167,6 +193,20 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati }; }, [checkedMenuItems['sql_with_drop']]); + const onCardinalityNotationChange = useCallback((e)=>{ + setSaveERDData((prev)=>{ + return { + ...prev, + toolbarPrefs: { + ...prev?.toolbarPrefs, + cardinality: e.value, + }, + }; + }); + notationRef.current = e.value; + onNotationChange(e); + }, [onNotationChange]); + return ( (<> @@ -336,8 +376,8 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati label={gettext('Cardinality Notation')} > - {gettext('Crow\'s Foot Notation')} - {gettext('Chen Notation')} + {gettext('Crow\'s Foot Notation')} + {gettext('Chen Notation')} ) ); @@ -351,6 +391,7 @@ MainToolBar.propTypes = { notation: PropTypes.string, onNotationChange: PropTypes.func, connectionInfo: PropTypes.object, + toolbarPrefs: PropTypes.object, }; const ColorButton = withColorPicker(PgIconButton); diff --git a/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffButtonComponent.jsx b/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffButtonComponent.jsx index cbcc1750e7a..3cf0675e473 100644 --- a/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffButtonComponent.jsx +++ b/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffButtonComponent.jsx @@ -64,7 +64,7 @@ const Root = styled('div')(({theme}) => ({ }, })); -export function SchemaDiffButtonComponent({ sourceData, targetData, selectedRowIds, onServerSchemaChange, rows, compareParams, filterParams = [FILTER_NAME.DIFFERENT, FILTER_NAME.SOURCE_ONLY, FILTER_NAME.TARGET_ONLY] }) { +export function SchemaDiffButtonComponent({ sourceData, targetData, selectedRowIds, onServerSchemaChange, rows, compareParams, filterParams, filters }) { const filterRef = useRef(null); const compareRef = useRef(null); @@ -103,8 +103,13 @@ export function SchemaDiffButtonComponent({ sourceData, targetData, selectedRowI schemaDiffCtx?.preferences_schema_diff?.ignore_grants && prefCompareOptions.push(MENUS_COMPARE_CONSTANT.COMPARE_IGNORE_GRANTS); setSelectedCompare(prefCompareOptions); } - }, [schemaDiffCtx.preferences_schema_diff]); + }, [schemaDiffCtx.preferences_schema_diff, compareParams]); + useEffect(() => { + if (!_.isUndefined(filters) && !_.isEmpty(filters)) { + setSelectedFilters(filters); + } + }, [filters]); const selectFilterOption = (option) => { let newOptions = []; diff --git a/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffCompare.jsx b/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffCompare.jsx index 6924b76f4ed..c6c0388936c 100644 --- a/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffCompare.jsx +++ b/web/pgadmin/tools/schema_diff/static/js/components/SchemaDiffCompare.jsx @@ -143,7 +143,11 @@ export function SchemaDiffCompare({ params }) { if(params.params?.restore == 'true'){ async function fetchData() { const response = await getToolContent(params.transId); - oldSchemaDiffData.current = response?.data; + oldSchemaDiffData.current = response; + if(response?.connectionInfo?.preferences){ + setCompareOptions(response?.connectionInfo?.preferences?.compareParams); + setFilterOptions(response?.connectionInfo?.preferences?.filterParams); + } } fetchData(); } @@ -152,7 +156,7 @@ export function SchemaDiffCompare({ params }) { useEffect(()=>{ if(oldSchemaDiffData.current){ - _.each(oldSchemaDiffData.current,(d)=>{ + _.each(oldSchemaDiffData.current.data,(d)=>{ if(d.diff_type == TYPE.SOURCE){ setSelectedSourceSid(d.selectedSourceSid); }else{ @@ -294,7 +298,7 @@ export function SchemaDiffCompare({ params }) { { diff_type: TYPE.SOURCE, selectedSourceSid: sourceData.sid, selectedSourceDid:sourceData.did, selectedSourceScid: sourceData.scid}, { diff_type: TYPE.TARGET, selectedTargetSid:targetData.sid, selectedTargetDid:targetData.did, selectedTargetScid:targetData.scid }, ]; - saveToolData('schema_diff', null, params.transId, toolData); + saveToolData('schema_diff', {preferences:{compareParams, filterParams}}, params.transId, toolData); } setLoaderText('Comparing objects... (this may take a few minutes)...'); @@ -678,7 +682,7 @@ export function SchemaDiffCompare({ params }) { useEffect(()=>{ if(oldSchemaDiffData.current){ - _.each(oldSchemaDiffData.current,(d)=>{ + _.each(oldSchemaDiffData.current?.data,(d)=>{ if(d.diff_type == TYPE.SOURCE){ setSelectedSourceDid(d.selectedSourceDid); }else{ @@ -702,7 +706,7 @@ export function SchemaDiffCompare({ params }) { useEffect(()=>{ if(oldSchemaDiffData.current){ - _.each(oldSchemaDiffData.current,(d)=>{ + _.each(oldSchemaDiffData.current?.data,(d)=>{ if(d.diff_type == TYPE.SOURCE){ setSelectedSourceScid(d.selectedSourceScid); }else{ @@ -802,6 +806,7 @@ export function SchemaDiffCompare({ params }) { }} filterParams={getFilterParams()} compareParams={compareOptions} + filters={filterOptions} > From 3df14ae18878c824d9350a28bcc39791f7674cb2 Mon Sep 17 00:00:00 2001 From: pravesh-sharma Date: Fri, 6 Feb 2026 13:50:01 +0530 Subject: [PATCH 2/3] Implemented review comments. --- .../static/js/erd_tool/components/MainToolBar.jsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx index 33a4527600e..bb60c2a7e79 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx @@ -7,6 +7,7 @@ // ////////////////////////////////////////////////////////////// import React, {useCallback, useEffect, useState} from 'react'; +import _ from 'lodash'; import { styled } from '@mui/material/styles'; import { Box, useTheme } from '@mui/material'; import { PgButtonGroup, PgIconButton } from '../../../../../../static/js/components/Buttons'; @@ -164,7 +165,13 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati isDirtyRef.current = isDirty; setDisableButton('save', !isDirty); if((isDirty || fileName) && isSaveToolDataEnabled('ERD')){ - setSaveERDData({data, fileName, isDirty, toolbarPrefs}); + setSaveERDData((prev) => ({ + ...prev, + data, + fileName, + isDirty, + ...(toolbarPrefs !== undefined && { toolbarPrefs }), + })); } }], ]; @@ -179,8 +186,10 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati }, []); const [saveERDData, setSaveERDData] = useState(null); - useDelayDebounce(({data, fileName, isDirty, toolbarPrefs})=>{ - saveToolData('ERD', {...connectionInfo,'open_file_name':fileName, 'is_editor_dirty': isDirty, 'preferences': toolbarPrefs}, connectionInfo.trans_id, data); + useDelayDebounce((saveData)=>{ + if(saveData?.data !== undefined){ + saveToolData('ERD', {...connectionInfo, 'open_file_name': saveData.fileName, 'is_editor_dirty': saveData.isDirty, 'preferences': saveData.toolbarPrefs}, connectionInfo.trans_id, saveData.data); + } }, saveERDData, 500); useEffect(()=>{ From 506d061df15c5fba55d7e562412c3df99ed77264 Mon Sep 17 00:00:00 2001 From: pravesh-sharma Date: Fri, 6 Feb 2026 14:15:49 +0530 Subject: [PATCH 3/3] Fixed some more review comments. --- .../tools/erd/static/js/erd_tool/components/MainToolBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx index bb60c2a7e79..457e9a7ebca 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/MainToolBar.jsx @@ -146,7 +146,7 @@ export function MainToolBar({preferences, eventBus, fillColor, textColor, notati } notationRef.current = notation; } - }, [preferences, toolbarPrefs]); + }, [preferences, toolbarPrefs, notation, onNotationChange]); useEffect(()=>{ const events = [