Add support for showing the column data type beside column name in the object explorer. #8968

pull/9355/head
Anil Sahoo 2025-11-12 19:50:28 +05:30 committed by GitHub
parent 5e472ec42a
commit 14dec7e5ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 42 additions and 3 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -60,6 +60,9 @@ Use the fields on the *Display* panel to specify general display preferences:
all the shared servers from the object explorer. **Note:** This option is visible only when
pgAdmin is running in server mode.
* When the *Show column data type?* switch is turned off, then the data types
of the columns will not be displayed alongside their column names.
* When the *Show empty object collections?* switch is turned off, then all object
collections which are empty will be hidden from browser tree.

View File

@ -33,6 +33,16 @@ def register_browser_preferences(self):
)
)
self.show_column_datatype = self.preference.register(
'display', 'show_column_datatype',
gettext("Show column data type?"), 'boolean', True,
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'If turned off, then the data types of the columns '
'will not be displayed alongside their column names.'
)
)
self.show_user_defined_templates = self.preference.register(
'display', 'show_user_defined_templates',
gettext("Show template databases?"), 'boolean', False,

View File

@ -305,7 +305,8 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
row['name'],
icon="icon-column",
datatype=row['datatype'], # We need datatype somewhere in,
description=row['description']
description=row['description'],
displaytypname=row['displaytypname'],
),
status=200
)
@ -318,7 +319,8 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
row['name'],
icon="icon-column",
datatype=row['datatype'], # We need datatype somewhere in
description=row['description']
description=row['description'],
displaytypname=row['displaytypname'],
)) # exclusion constraint.
return make_json_response(

View File

@ -9,6 +9,7 @@
import { getNodeColumnSchema } from './column.ui';
import _ from 'lodash';
import usePreferences from '../../../../../../../../../preferences/static/js/store';
define('pgadmin.node.column', [
'sources/gettext', 'sources/url_for', 'pgadmin.browser',
@ -41,6 +42,14 @@ define('pgadmin.node.column', [
sqlAlterHelp: 'sql-altertable.html',
sqlCreateHelp: 'sql-altertable.html',
dialogHelp: url_for('help.static', {'filename': 'column_dialog.html'}),
// Overriding getNodeInfoLabel to add datatype alongside column name
getNodeInfoLabel: function(data) {
let show_column_datatype = usePreferences.getState().getPreferences('browser', 'show_column_datatype');
if (show_column_datatype?.value && data.datatype && data.displaytypname) {
return data.displaytypname;
}
return null;
},
canDrop: function(itemData, item){
let node = pgBrowser.tree.findNodeByDomElement(item);

View File

@ -1,4 +1,5 @@
SELECT DISTINCT att.attname as name, att.attnum as OID, pg_catalog.format_type(ty.oid,NULL) AS datatype,
pg_catalog.format_type(ty.oid,att.atttypmod) AS displaytypname,
att.attnotnull as not_null,
CASE WHEN att.atthasdef OR att.attidentity != '' OR ty.typdefault IS NOT NULL THEN True
ELSE False END as has_default_val, des.description, seq.seqtypid

View File

@ -99,6 +99,14 @@ define('pgadmin.browser.node', [
// during the copying process of any node.
return d;
},
getNodeInfoLabel: function(data) {
// Adds an extra informational label appended to the node label.
// Override this function to return a string to display, or null for no extra label.
if(data.info_label)
return data.info_label;
else
return null;
},
hasId: true,
///////
// Initialization function

View File

@ -267,7 +267,7 @@ export default function PreferencesComponent({panelId}) {
});
} else {
const requiresTreeRefresh = _data.some((s) =>
['show_system_objects', 'show_empty_coll_nodes', 'hide_shared_server', 'show_user_defined_templates'].includes(s.name) || s.name.startsWith('show_node_')
['show_system_objects', 'show_empty_coll_nodes', 'hide_shared_server', 'show_user_defined_templates', 'show_column_datatype'].includes(s.name) || s.name.startsWith('show_node_')
);
let requiresFullPageRefresh = false;

View File

@ -112,6 +112,9 @@ export class FileTreeItem extends React.Component<IItemRendererXProps & IItemRen
<span className='file-name'>
{ _.unescape(this.props.item.getMetadata('data')._label)}
</span>
<span className="text-muted" style={{fontSize: '0.9em', whiteSpace: 'nowrap'}}>
{_.unescape(this.props.item.getMetadata('data').info_label)}
</span>
<span className='children-count'>{itemChildren}</span>
{tags.map((tag)=>(
<div key={tag.text} className='file-tag' style={{'--tag-color': tag.color} as React.CSSProperties}>

View File

@ -60,6 +60,9 @@ export class ManageTreeNodes {
public addNode = (_parent: string, _path: string, _data: []) => new Promise((res) => {
_data.type = _data.inode ? FileType.Directory : FileType.File;
_data._label = _data.label;
_data.info_label = pgAdmin.Browser.Nodes[_data._type]?.getNodeInfoLabel(_data);
_data.label = _.escape(_data.label);
_data.is_collection = isCollectionNode(_data._type);