Skip to content

Commit abdcd98

Browse files
Add support for setting image download resolution in the ERD tool. #6698
1 parent c7a6056 commit abdcd98

File tree

3 files changed

+74
-37
lines changed

3 files changed

+74
-37
lines changed

web/pgadmin/tools/erd/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,19 @@ def register_preferences(self):
431431
)
432432
)
433433

434+
self.preference.register(
435+
'options', 'image_pixel_ratio',
436+
gettext('Image Download Resolution'), 'radioModern', '1',
437+
category_label=PREF_LABEL_OPTIONS, options=[
438+
{'label': gettext('Good'), 'value': '1'},
439+
{'label': gettext('High'), 'value': '3'},
440+
{'label': gettext('Very High'), 'value': '5'},
441+
],
442+
help_str=gettext(
443+
'Higher values will use higher memory and slower rendering.'
444+
),
445+
)
446+
434447
self.preference.register(
435448
'options',
436449
'sql_with_drop',

web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ const StyledBox = styled(Box)(({theme})=>({
103103
'& .ERDTool-html2canvasReset': {
104104
backgroundImage: 'none !important',
105105
overflow: 'auto !important',
106+
textRendering: 'geometricPrecision',
107+
108+
'& .TableNode-tableToolbar': {
109+
visibility: 'hidden',
110+
},
111+
112+
'& .TableNode-tableContent': {
113+
borderTopLeftRadius: theme.shape.borderRadius,
114+
borderTopRightRadius: theme.shape.borderRadius,
115+
},
106116
}
107117
}));
108118

@@ -163,7 +173,6 @@ export default class ERDTool extends React.Component {
163173
this.keyboardActionObj = null;
164174
this.erdDialogs = new ERDDialogs(this.context);
165175
this.apiObj = getApiInstance();
166-
this.preferencesStore = usePreferences.getState();
167176
this.fmUtilsObj = new FileManagerUtils(this.apiObj, {modal: this.context});
168177
this.restore = props.params.restore == 'true';
169178
this.eventBus = new EventBus();
@@ -328,17 +337,25 @@ export default class ERDTool extends React.Component {
328337
this.setLoading(gettext('Preparing...'));
329338
this.registerEvents();
330339
this.diagramContainerRef.current?.focus();
331-
const erdPref = this.preferencesStore.getPreferencesForModule('erd');
340+
const erdPref = usePreferences.getState().getPreferencesForModule('erd');
332341
this.setState({
333342
preferences: erdPref,
334-
is_new_tab: (this.preferencesStore.getPreferencesForModule('browser').new_browser_tab_open || '')
343+
is_new_tab: (usePreferences.getState().getPreferencesForModule('browser').new_browser_tab_open || '')
335344
.includes('erd_tool'),
336-
is_close_tab_warning: this.preferencesStore.getPreferencesForModule('browser').confirm_on_refresh_close,
345+
is_close_tab_warning: usePreferences.getState().getPreferencesForModule('browser').confirm_on_refresh_close,
337346
cardinality_notation: erdPref.cardinality_notation,
338347
}, ()=>{
339348
this.registerKeyboardShortcuts();
340349
if(this.state.current_file)this.setTitle(this.state.current_file);
341350
});
351+
352+
usePreferences.subscribe((state)=>{
353+
this.setState({
354+
preferences: state.getPreferencesForModule('erd'),
355+
is_close_tab_warning: state.getPreferencesForModule('browser').confirm_on_refresh_close,
356+
});
357+
});
358+
342359
this.registerModelEvents();
343360
this.realignGrid({
344361
backgroundSize: '45px 45px',
@@ -808,7 +825,7 @@ export default class ERDTool extends React.Component {
808825
height = 32766;
809826
isCut = true;
810827
}
811-
toPng(this.canvasEle, {width, height})
828+
toPng(this.canvasEle, {width, height, pixelRatio: this.state.preferences.image_pixel_ratio || 1})
812829
.then((dataUrl)=>{
813830
DownloadUtils.downloadBase64UrlData(dataUrl, `${this.getCurrentProjectName()}.png`);
814831
}).catch((err)=>{

web/pgadmin/tools/erd/static/js/erd_tool/nodes/TableNode.jsx

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { Box } from '@mui/material';
2727
import { styled } from '@mui/material/styles';
2828

2929
const TYPE = 'table';
30-
const TABLE_WIDTH = 175;
30+
const TABLE_WIDTH = 180;
3131

3232
export class TableNodeModel extends DefaultNodeModel {
3333
constructor({otherInfo, ...options}) {
@@ -214,16 +214,31 @@ RowIcon.propTypes = {
214214

215215
const StyledDiv = styled('div')(({theme})=>({
216216
'&.TableNode-tableNode': {
217-
backgroundColor: theme.palette.background.default,
218217
color: theme.palette.text.primary,
219-
...theme.mixins.panelBorder.all,
220-
borderRadius: theme.shape.borderRadius,
221218
position: 'relative',
222219
width: `${TABLE_WIDTH}px`,
223220
fontSize: '0.8em',
224-
'& div:last-child': {
225-
borderBottomLeftRadius: 'inherit',
226-
borderBottomRightRadius: 'inherit',
221+
222+
'& .TableNode-tableContent': {
223+
backgroundColor: theme.palette.background.default,
224+
...theme.mixins.panelBorder.all,
225+
borderBottomLeftRadius: theme.shape.borderRadius,
226+
borderBottomRightRadius: theme.shape.borderRadius,
227+
},
228+
'& .TableNode-tableToolbar': {
229+
background: theme.otherVars.editorToolbarBg,
230+
...theme.mixins.panelBorder.all,
231+
borderBottom: 'none',
232+
borderTopLeftRadius: theme.shape.borderRadius,
233+
borderTopRightRadius: theme.shape.borderRadius,
234+
padding: '0.125rem 0.25rem',
235+
display: 'flex',
236+
237+
'& .TableNode-noteBtn': {
238+
marginLeft: 'auto',
239+
backgroundColor: theme.palette.warning.main,
240+
color: theme.palette.warning.contrastText,
241+
},
227242
},
228243
'& .TableNode-tableSection': {
229244
...theme.mixins.panelBorder.bottom,
@@ -237,16 +252,6 @@ const StyledDiv = styled('div')(({theme})=>({
237252
color: theme.palette.error.main,
238253
},
239254
},
240-
'&.TableNode-tableToolbar': {
241-
background: theme.otherVars.editorToolbarBg,
242-
borderTopLeftRadius: 'inherit',
243-
borderTopRightRadius: 'inherit',
244-
},
245-
'& .TableNode-noteBtn': {
246-
marginLeft: 'auto',
247-
backgroundColor: theme.palette.warning.main,
248-
color: theme.palette.warning.contrastText,
249-
},
250255
},
251256
'& .TableNode-columnSection': {
252257
display:'flex',
@@ -370,7 +375,7 @@ export class TableNodeWidget extends React.Component {
370375
return (
371376
<StyledDiv className={['TableNode-tableNode', (this.props.node.isSelected() ? 'TableNode-tableNodeSelected': '')].join(' ')}
372377
onDoubleClick={()=>{this.props.node.fireEvent({}, 'editTable');}} style={styles}>
373-
<div className={'TableNode-tableSection TableNode-tableToolbar'}>
378+
<div className={'TableNode-tableToolbar'}>
374379
<PgIconButton size="xs" title={gettext('Show Details')} icon={this.state.show_details ? <VisibilityRoundedIcon /> : <VisibilityOffRoundedIcon />}
375380
onClick={this.toggleShowDetails} onDoubleClick={(e)=>{e.stopPropagation();}} />
376381
{this.props.node.getNote() &&
@@ -381,24 +386,26 @@ export class TableNodeWidget extends React.Component {
381386
}}
382387
/>}
383388
</div>
384-
{tableMetaData.is_promise &&
389+
<div className='TableNode-tableContent'>
390+
{tableMetaData.is_promise &&
385391
<div className='TableNode-tableSection'>
386392
{!tableMetaData.data_failed && <div className='TableNode-tableNameText'>{gettext('Fetching...')}</div>}
387393
{tableMetaData.data_failed && <div className={'TableNode-tableNameText TableNode-error'}>{gettext('Failed to get data. Please delete this table.')}</div>}
388394
</div>}
389-
{!tableMetaData.is_promise && <>
390-
<div className='TableNode-tableSection'>
391-
<RowIcon icon={SchemaIcon}/>
392-
<div className='TableNode-tableNameText' data-test="schema-name">{tableData.schema}</div>
393-
</div>
394-
<div className='TableNode-tableSection'>
395-
<RowIcon icon={TableIcon} />
396-
<div className='TableNode-tableNameText' data-test="table-name">{tableData.name}</div>
397-
</div>
398-
{tableData.columns.length > 0 && <div>
399-
{_.map(tableData.columns, (col)=>this.generateColumn(col, localFkCols, localUkCols))}
400-
</div>}
401-
</>}
395+
{!tableMetaData.is_promise && <>
396+
<div className='TableNode-tableSection'>
397+
<RowIcon icon={SchemaIcon}/>
398+
<div className='TableNode-tableNameText' data-test="schema-name">{tableData.schema}</div>
399+
</div>
400+
<div className='TableNode-tableSection'>
401+
<RowIcon icon={TableIcon} />
402+
<div className='TableNode-tableNameText' data-test="table-name">{tableData.name}</div>
403+
</div>
404+
{tableData.columns.length > 0 && <div>
405+
{_.map(tableData.columns, (col)=>this.generateColumn(col, localFkCols, localUkCols))}
406+
</div>}
407+
</>}
408+
</div>
402409
</StyledDiv>
403410
);
404411
}

0 commit comments

Comments
 (0)