From abdcd983f68d016babc015a1835e7e21197bcf16 Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Wed, 29 Oct 2025 14:57:20 +0530 Subject: [PATCH] Add support for setting image download resolution in the ERD tool. #6698 --- web/pgadmin/tools/erd/__init__.py | 13 ++++ .../static/js/erd_tool/components/ERDTool.jsx | 27 +++++-- .../static/js/erd_tool/nodes/TableNode.jsx | 71 ++++++++++--------- 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/web/pgadmin/tools/erd/__init__.py b/web/pgadmin/tools/erd/__init__.py index 099925c8c..36504bebd 100644 --- a/web/pgadmin/tools/erd/__init__.py +++ b/web/pgadmin/tools/erd/__init__.py @@ -431,6 +431,19 @@ class ERDModule(PgAdminModule): ) ) + self.preference.register( + 'options', 'image_pixel_ratio', + gettext('Image Download Resolution'), 'radioModern', '1', + category_label=PREF_LABEL_OPTIONS, options=[ + {'label': gettext('Good'), 'value': '1'}, + {'label': gettext('High'), 'value': '3'}, + {'label': gettext('Very High'), 'value': '5'}, + ], + help_str=gettext( + 'Higher values will use higher memory and slower rendering.' + ), + ) + self.preference.register( 'options', 'sql_with_drop', 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 828c50283..8c7f48687 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 @@ -103,6 +103,16 @@ const StyledBox = styled(Box)(({theme})=>({ '& .ERDTool-html2canvasReset': { backgroundImage: 'none !important', overflow: 'auto !important', + textRendering: 'geometricPrecision', + + '& .TableNode-tableToolbar': { + visibility: 'hidden', + }, + + '& .TableNode-tableContent': { + borderTopLeftRadius: theme.shape.borderRadius, + borderTopRightRadius: theme.shape.borderRadius, + }, } })); @@ -163,7 +173,6 @@ export default class ERDTool extends React.Component { this.keyboardActionObj = null; this.erdDialogs = new ERDDialogs(this.context); this.apiObj = getApiInstance(); - this.preferencesStore = usePreferences.getState(); this.fmUtilsObj = new FileManagerUtils(this.apiObj, {modal: this.context}); this.restore = props.params.restore == 'true'; this.eventBus = new EventBus(); @@ -328,17 +337,25 @@ export default class ERDTool extends React.Component { this.setLoading(gettext('Preparing...')); this.registerEvents(); this.diagramContainerRef.current?.focus(); - const erdPref = this.preferencesStore.getPreferencesForModule('erd'); + const erdPref = usePreferences.getState().getPreferencesForModule('erd'); this.setState({ preferences: erdPref, - is_new_tab: (this.preferencesStore.getPreferencesForModule('browser').new_browser_tab_open || '') + is_new_tab: (usePreferences.getState().getPreferencesForModule('browser').new_browser_tab_open || '') .includes('erd_tool'), - is_close_tab_warning: this.preferencesStore.getPreferencesForModule('browser').confirm_on_refresh_close, + is_close_tab_warning: usePreferences.getState().getPreferencesForModule('browser').confirm_on_refresh_close, cardinality_notation: erdPref.cardinality_notation, }, ()=>{ this.registerKeyboardShortcuts(); if(this.state.current_file)this.setTitle(this.state.current_file); }); + + usePreferences.subscribe((state)=>{ + this.setState({ + preferences: state.getPreferencesForModule('erd'), + is_close_tab_warning: state.getPreferencesForModule('browser').confirm_on_refresh_close, + }); + }); + this.registerModelEvents(); this.realignGrid({ backgroundSize: '45px 45px', @@ -808,7 +825,7 @@ export default class ERDTool extends React.Component { height = 32766; isCut = true; } - toPng(this.canvasEle, {width, height}) + toPng(this.canvasEle, {width, height, pixelRatio: this.state.preferences.image_pixel_ratio || 1}) .then((dataUrl)=>{ DownloadUtils.downloadBase64UrlData(dataUrl, `${this.getCurrentProjectName()}.png`); }).catch((err)=>{ diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx index 38668010d..ce95701e5 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx @@ -27,7 +27,7 @@ import { Box } from '@mui/material'; import { styled } from '@mui/material/styles'; const TYPE = 'table'; -const TABLE_WIDTH = 175; +const TABLE_WIDTH = 180; export class TableNodeModel extends DefaultNodeModel { constructor({otherInfo, ...options}) { @@ -214,16 +214,31 @@ RowIcon.propTypes = { const StyledDiv = styled('div')(({theme})=>({ '&.TableNode-tableNode': { - backgroundColor: theme.palette.background.default, color: theme.palette.text.primary, - ...theme.mixins.panelBorder.all, - borderRadius: theme.shape.borderRadius, position: 'relative', width: `${TABLE_WIDTH}px`, fontSize: '0.8em', - '& div:last-child': { - borderBottomLeftRadius: 'inherit', - borderBottomRightRadius: 'inherit', + + '& .TableNode-tableContent': { + backgroundColor: theme.palette.background.default, + ...theme.mixins.panelBorder.all, + borderBottomLeftRadius: theme.shape.borderRadius, + borderBottomRightRadius: theme.shape.borderRadius, + }, + '& .TableNode-tableToolbar': { + background: theme.otherVars.editorToolbarBg, + ...theme.mixins.panelBorder.all, + borderBottom: 'none', + borderTopLeftRadius: theme.shape.borderRadius, + borderTopRightRadius: theme.shape.borderRadius, + padding: '0.125rem 0.25rem', + display: 'flex', + + '& .TableNode-noteBtn': { + marginLeft: 'auto', + backgroundColor: theme.palette.warning.main, + color: theme.palette.warning.contrastText, + }, }, '& .TableNode-tableSection': { ...theme.mixins.panelBorder.bottom, @@ -237,16 +252,6 @@ const StyledDiv = styled('div')(({theme})=>({ color: theme.palette.error.main, }, }, - '&.TableNode-tableToolbar': { - background: theme.otherVars.editorToolbarBg, - borderTopLeftRadius: 'inherit', - borderTopRightRadius: 'inherit', - }, - '& .TableNode-noteBtn': { - marginLeft: 'auto', - backgroundColor: theme.palette.warning.main, - color: theme.palette.warning.contrastText, - }, }, '& .TableNode-columnSection': { display:'flex', @@ -370,7 +375,7 @@ export class TableNodeWidget extends React.Component { return ( {this.props.node.fireEvent({}, 'editTable');}} style={styles}> -
+
: } onClick={this.toggleShowDetails} onDoubleClick={(e)=>{e.stopPropagation();}} /> {this.props.node.getNote() && @@ -381,24 +386,26 @@ export class TableNodeWidget extends React.Component { }} />}
- {tableMetaData.is_promise && +
+ {tableMetaData.is_promise &&
{!tableMetaData.data_failed &&
{gettext('Fetching...')}
} {tableMetaData.data_failed &&
{gettext('Failed to get data. Please delete this table.')}
}
} - {!tableMetaData.is_promise && <> -
- -
{tableData.schema}
-
-
- -
{tableData.name}
-
- {tableData.columns.length > 0 &&
- {_.map(tableData.columns, (col)=>this.generateColumn(col, localFkCols, localUkCols))} -
} - } + {!tableMetaData.is_promise && <> +
+ +
{tableData.schema}
+
+
+ +
{tableData.name}
+
+ {tableData.columns.length > 0 &&
+ {_.map(tableData.columns, (col)=>this.generateColumn(col, localFkCols, localUkCols))} +
} + } +
); }