diff --git a/docs/en_US/images/preferences_browser_breadcrumbs.png b/docs/en_US/images/preferences_browser_breadcrumbs.png new file mode 100644 index 000000000..8257207b5 Binary files /dev/null and b/docs/en_US/images/preferences_browser_breadcrumbs.png differ diff --git a/docs/en_US/images/preferences_browser_display.png b/docs/en_US/images/preferences_browser_display.png index 1fe7653c1..de504e510 100644 Binary files a/docs/en_US/images/preferences_browser_display.png and b/docs/en_US/images/preferences_browser_display.png differ diff --git a/docs/en_US/images/preferences_browser_keyboard_shortcuts.png b/docs/en_US/images/preferences_browser_keyboard_shortcuts.png index d732d0a7a..8b7356303 100644 Binary files a/docs/en_US/images/preferences_browser_keyboard_shortcuts.png and b/docs/en_US/images/preferences_browser_keyboard_shortcuts.png differ diff --git a/docs/en_US/images/preferences_browser_nodes.png b/docs/en_US/images/preferences_browser_nodes.png index 9fbcea064..00d06cd04 100644 Binary files a/docs/en_US/images/preferences_browser_nodes.png and b/docs/en_US/images/preferences_browser_nodes.png differ diff --git a/docs/en_US/images/preferences_browser_processes.png b/docs/en_US/images/preferences_browser_processes.png new file mode 100644 index 000000000..6b6ca1712 Binary files /dev/null and b/docs/en_US/images/preferences_browser_processes.png differ diff --git a/docs/en_US/images/preferences_browser_properties.png b/docs/en_US/images/preferences_browser_properties.png index 7cb86261c..a2094b523 100644 Binary files a/docs/en_US/images/preferences_browser_properties.png and b/docs/en_US/images/preferences_browser_properties.png differ diff --git a/docs/en_US/images/preferences_browser_tab_settings.png b/docs/en_US/images/preferences_browser_tab_settings.png index 035c8b017..16f2bd110 100644 Binary files a/docs/en_US/images/preferences_browser_tab_settings.png and b/docs/en_US/images/preferences_browser_tab_settings.png differ diff --git a/docs/en_US/preferences.rst b/docs/en_US/preferences.rst index 91a5ae9d1..1a3406634 100644 --- a/docs/en_US/preferences.rst +++ b/docs/en_US/preferences.rst @@ -88,6 +88,30 @@ displayed in the *Browser* tree control: catalogs, you can reduce the number of object types displayed to increase speed. +Use the fields on the *Object Breadcrumbs* panel to change object breadcrumbs +related settings: + +.. image:: images/preferences_browser_breadcrumbs.png + :alt: Preferences dialog object breadcrumbs section + :align: center + +* Use *Enable object breadcrumbs?* to enable or disable object breadcrumbs + displayed on on object mouse hover. + +* Use *Show comment with object breadcrumbs?* to enable or disable the + comment visibility which comes displayed with object breadcrumbs. + + +Use the fields on the *Processes* panel to change processes tab +related settings: + +.. image:: images/preferences_browser_processes.png + :alt: Preferences dialog processes section + :align: center + +* Change *Process details/logs retention days* to the number of days, + the process info and logs will be automatically cleared. + Use fields on the *Properties* panel to specify browser properties: .. image:: images/preferences_browser_properties.png diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py index e4156aeff..1bdd0ddfe 100644 --- a/web/pgadmin/browser/register_browser_preferences.py +++ b/web/pgadmin/browser/register_browser_preferences.py @@ -10,7 +10,8 @@ import sys from flask_babel import gettext from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\ PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_TABS_SETTINGS, \ - PREF_LABEL_OPTIONS, QT_DEFAULT_PLACEHOLDER, VW_EDT_DEFAULT_PLACEHOLDER + PREF_LABEL_OPTIONS, QT_DEFAULT_PLACEHOLDER, VW_EDT_DEFAULT_PLACEHOLDER, \ + PREF_LABEL_BREADCRUMBS from flask import current_app import config @@ -557,3 +558,25 @@ def register_browser_preferences(self): ' back to the default title with placeholders.' ) ) + + self.preference.register( + 'breadcrumbs', 'breadcrumbs_enable', + gettext("Enable object breadcrumbs?"), + 'boolean', + True, category_label=PREF_LABEL_BREADCRUMBS, + help_str=gettext( + 'Enable breadcrumbs to show the complete path of an object in the ' + 'object explorer. The breadcrumbs are displayed on object mouse ' + 'hover.' + ) + ) + + self.preference.register( + 'breadcrumbs', 'breadcrumbs_show_comment', + gettext("Show comment with object breadcrumbs?"), + 'boolean', + True, category_label=PREF_LABEL_BREADCRUMBS, + help_str=gettext( + 'Show object comment along with breadcrumbs.' + ) + ) diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index b271d42f8..bf4ce74e6 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -271,7 +271,8 @@ class ServerModule(sg.ServerGroupPluginModule): shared=server.shared, is_kerberos_conn=bool(server.kerberos_conn), gss_authenticated=manager.gss_authenticated, - cloud_status=server.cloud_status + cloud_status=server.cloud_status, + description=server.comment ) @property @@ -595,7 +596,8 @@ class ServerNode(PGChildNodeView): username=server.username, shared=server.shared, is_kerberos_conn=bool(server.kerberos_conn), - gss_authenticated=manager.gss_authenticated + gss_authenticated=manager.gss_authenticated, + description=server.comment ) ) @@ -846,7 +848,8 @@ class ServerNode(PGChildNodeView): server_type='pg', # default server type username=server.username, role=server.role, - is_password_saved=bool(server.save_password) + is_password_saved=bool(server.save_password), + description=server.comment ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/__init__.py index 120059bd3..677def01e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/__init__.py @@ -386,7 +386,8 @@ class DatabaseView(PGChildNodeView): canDisconn=can_dis_conn, canDrop=can_drop, isTemplate=row['is_template'], - inode=True if row['datallowconn'] else False + inode=True if row['datallowconn'] else False, + description=row['description'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py index 2bc3e44cc..9d47c6a90 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py @@ -282,7 +282,8 @@ class CastView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], did, row['name'], - icon="icon-cast" + icon="icon-cast", + description=row['description'] )) return make_json_response( @@ -449,12 +450,17 @@ class CastView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( cid, did, name, - "icon-{0}".format(self.node_type) + "icon-{0}".format(self.node_type), + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/casts/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/casts/sql/default/nodes.sql index d1975f5a1..e044e4bd7 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/casts/templates/casts/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/casts/templates/casts/sql/default/nodes.sql @@ -1,6 +1,7 @@ SELECT ca.oid, - pg_catalog.concat(pg_catalog.format_type(st.oid,NULL),'->',pg_catalog.format_type(tt.oid,tt.typtypmod)) as name + pg_catalog.concat(pg_catalog.format_type(st.oid,NULL),'->',pg_catalog.format_type(tt.oid,tt.typtypmod)) as name, + des.description FROM pg_catalog.pg_cast ca JOIN pg_catalog.pg_type st ON st.oid=castsource JOIN pg_catalog.pg_namespace ns ON ns.oid=st.typnamespace diff --git a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py index de49e77ec..32915cb2a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py @@ -264,7 +264,8 @@ class EventTriggerView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], did, row['name'], - self.node_icon + self.node_icon, + description=row['comment'] )) return make_json_response( @@ -481,12 +482,17 @@ class EventTriggerView(PGChildNodeView, SchemaDiffObjectCompare): ) status, etid = self.conn.execute_scalar(sql) + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( etid, did, data['name'], - self.node_icon + self.node_icon, + **other_node_info ) ) else: diff --git a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/templates/event_triggers/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/templates/event_triggers/sql/default/nodes.sql index 5b9de08d5..03c9f2e7e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/templates/event_triggers/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/templates/event_triggers/sql/default/nodes.sql @@ -1,4 +1,5 @@ -SELECT e.oid, e.evtname AS name +SELECT e.oid, e.evtname AS name, + pg_catalog.obj_description(e.oid, 'pg_event_trigger') AS comment FROM pg_catalog.pg_event_trigger e {% if etid %} WHERE e.oid={{etid}}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py index 6f9b11adf..599999638 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py @@ -188,7 +188,8 @@ class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], did, row['name'], - 'icon-extension' + 'icon-extension', + description=row['comment'] )) return make_json_response( @@ -327,12 +328,17 @@ class ExtensionView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( eid, did, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py index 3e518a832..0970f9781 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py @@ -299,7 +299,8 @@ class ForeignDataWrapperView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], did, row['name'], - icon="icon-foreign_data_wrapper" + icon="icon-foreign_data_wrapper", + description=row['description'] )) return make_json_response( @@ -505,12 +506,17 @@ class ForeignDataWrapperView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( fid, did, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py index 9d643e1c7..a3320da2c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py @@ -290,7 +290,8 @@ class ForeignServerView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], fid, row['name'], - icon="icon-foreign_server" + icon="icon-foreign_server", + description=row['description'] )) return make_json_response( @@ -503,12 +504,17 @@ class ForeignServerView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( fsid, fid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py index e001bbc8f..1267b8eb0 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py @@ -296,7 +296,8 @@ class LanguageView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], did, row['name'], - icon="icon-language" + icon="icon-language", + description=row['description'] )) return make_json_response( @@ -434,12 +435,17 @@ class LanguageView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( lid, did, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py index 5b357ea75..dd1626392 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py @@ -540,7 +540,8 @@ class SchemaView(PGChildNodeView): row['name'], icon=self.node_icon, can_create=row['can_create'], - has_usage=row['has_usage'] + has_usage=row['has_usage'], + description=row['description'] ), status=200 ) @@ -553,7 +554,8 @@ class SchemaView(PGChildNodeView): row['name'], icon=self.node_icon, can_create=row['can_create'], - has_usage=row['has_usage'] + has_usage=row['has_usage'], + description=row['description'] ) ) @@ -750,12 +752,17 @@ It may have been removed by another user. if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( scid, did, name, - icon=self.node_icon + icon=self.node_icon, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/__init__.py index b2bfa160f..2ce90fc33 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/__init__.py @@ -231,7 +231,8 @@ class AggregateView(PGChildNodeView): row['oid'], scid, row['name'], - icon="icon-aggregate" + icon="icon-aggregate", + description=row['description'] )) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/templates/aggregates/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/templates/aggregates/sql/default/nodes.sql index 885b65e9a..4546c461a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/templates/aggregates/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/templates/aggregates/sql/default/nodes.sql @@ -1,6 +1,7 @@ SELECT aggfnoid::oid as oid, proname || '(' || COALESCE(pg_catalog.pg_get_function_arguments(aggfnoid::oid), '') || ')' AS name, - pg_catalog.pg_get_userbyid(proowner) AS owner + pg_catalog.pg_get_userbyid(proowner) AS owner, + description FROM pg_aggregate ag LEFT OUTER JOIN pg_catalog.pg_proc pr ON pr.oid = ag.aggfnoid LEFT OUTER JOIN pg_catalog.pg_type tt on tt.oid=aggtranstype diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/__init__.py index 2a92b4060..be78850b2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/__init__.py @@ -235,7 +235,8 @@ class CatalogObjectView(PGChildNodeView): row['oid'], scid, row['name'], - icon="icon-catalog_object" + icon="icon-catalog_object", + description=row['description'] )) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/__init__.py index 8638998b3..5003f33aa 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/__init__.py @@ -246,7 +246,8 @@ class CatalogObjectColumnsView(PGChildNodeView): row['attnum'], coid, row['attname'], - icon="icon-catalog_object_column" + icon="icon-catalog_object_column", + description=row['description'] )) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/templates/catalog_object_column/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/templates/catalog_object_column/sql/default/nodes.sql index 88a16c0a2..b20583eab 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/templates/catalog_object_column/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/templates/catalog_object_column/sql/default/nodes.sql @@ -1,6 +1,7 @@ SELECT - attnum, attname + attnum, attname, des.description FROM pg_catalog.pg_attribute att + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=att.attrelid AND des.objsubid=att.attnum AND des.classoid='pg_class'::regclass) WHERE att.attrelid = {{coid}}::oid AND att.attnum > 0 AND att.attisdropped IS FALSE diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/templates/catalog_object/sql/pg/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/templates/catalog_object/sql/pg/default/nodes.sql index d11d2c2cc..d09bab504 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/templates/catalog_object/sql/pg/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/templates/catalog_object/sql/pg/default/nodes.sql @@ -1,7 +1,9 @@ SELECT - c.oid, c.relname as name + c.oid, c.relname as name, description FROM pg_catalog.pg_class c + LEFT OUTER JOIN pg_catalog.pg_description d + ON d.objoid=c.oid AND d.classoid='pg_class'::regclass {% if scid %} WHERE relnamespace = {{scid}}::oid {% elif coid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py index 1295982fb..4ab0ee131 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py @@ -268,7 +268,8 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-collation" + icon="icon-collation", + description=row['description'] )) return make_json_response( @@ -604,12 +605,17 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare): scid = res['rows'][0]['scid'] + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( coid, scid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/templates/collations/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/templates/collations/sql/default/nodes.sql index 6c561f2cc..933124d44 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/templates/collations/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/templates/collations/sql/default/nodes.sql @@ -1,5 +1,6 @@ -SELECT c.oid, c.collname AS name +SELECT c.oid, c.collname AS name, des.description FROM pg_catalog.pg_collation c + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=c.oid AND des.classoid='pg_collation'::regclass) {% if scid %} WHERE c.collnamespace = {{scid}}::oid {% elif coid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py index f31d94cde..431cd7c88 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py @@ -358,7 +358,8 @@ class DomainView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-domain" + icon="icon-domain", + description=row['description'] )) return make_json_response( @@ -713,12 +714,17 @@ AND relkind != 'c'))""" if not status: return internal_server_error(errormsg=scid) + other_node_info = {} + if 'description' in self.request: + other_node_info['description'] = self.request['description'] + return jsonify( node=self.blueprint.generate_browser_node( doid, scid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/__init__.py index 306339c35..5c907998f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/__init__.py @@ -333,7 +333,8 @@ class DomainConstraintView(PGChildNodeView): row['oid'], doid, row['name'], - icon=icon + icon=icon, + description=row['description'] )) return make_json_response( @@ -559,12 +560,17 @@ class DomainConstraintView(PGChildNodeView): else: icon = '' + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( coid, doid, name, - icon=icon + icon=icon, + **other_node_info ) ) else: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/default/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/default/node.sql index 0ae54e860..3f671c76d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/default/node.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/default/node.sql @@ -1,12 +1,14 @@ SELECT d.oid, d.typname as name, pg_catalog.pg_get_userbyid(d.typowner) as owner, - bn.nspname as basensp + bn.nspname as basensp, des.description FROM pg_catalog.pg_type d JOIN pg_catalog.pg_type b ON b.oid = d.typbasetype JOIN pg_catalog.pg_namespace bn ON bn.oid=d.typnamespace +LEFT OUTER JOIN + pg_catalog.pg_description des ON (des.objoid=d.oid AND des.classoid='pg_type'::regclass) {% if scid is defined %} WHERE d.typnamespace = {{scid}}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py index ac8dd4fcd..641f88a04 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py @@ -447,7 +447,8 @@ class ForeignTableView(PGChildNodeView, DataTypeReader, row['oid'], scid, row['name'], - icon="icon-foreign_table" + icon="icon-foreign_table", + description=row['description'] )) return make_json_response( @@ -835,12 +836,17 @@ class ForeignTableView(PGChildNodeView, DataTypeReader, scid = res['rows'][0]['scid'] + other_node_info = {} + if 'description' in self.request: + other_node_info['description'] = self.request['description'] + return jsonify( node=self.blueprint.generate_browser_node( foid, scid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py index 712505b79..b7d04e16d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py @@ -296,7 +296,8 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-fts_configuration" + icon="icon-fts_configuration", + description=row['description'] )) return make_json_response( @@ -539,12 +540,17 @@ class FtsConfigurationView(PGChildNodeView, SchemaDiffObjectCompare): _("Could not find the FTS Configuration node to update.") ) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( cfgid, data['schema'] if 'schema' in data else scid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/nodes.sql index 143bcb331..739c56d13 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/templates/fts_configurations/sql/default/nodes.sql @@ -1,8 +1,10 @@ {# FETCH FTS CONFIGURATION NAME statement #} SELECT - oid, cfgname as name + cfg.oid, cfgname as name, des.description FROM pg_catalog.pg_ts_config cfg + LEFT OUTER JOIN pg_catalog.pg_description des + ON (des.objoid=cfg.oid AND des.classoid='pg_ts_config'::regclass) WHERE {% if scid %} cfg.cfgnamespace = {{scid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py index e8525793a..c2dab76ea 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py @@ -308,7 +308,8 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-fts_dictionary" + icon="icon-fts_dictionary", + description=row['description'] )) return make_json_response( @@ -530,12 +531,17 @@ class FtsDictionaryView(PGChildNodeView, SchemaDiffObjectCompare): _("Could not find the FTS Dictionary node to update.") ) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( dcid, res['rows'][0]['schema'], name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/templates/fts_dictionaries/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/templates/fts_dictionaries/sql/default/nodes.sql index 636909633..10e9abf4a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/templates/fts_dictionaries/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/templates/fts_dictionaries/sql/default/nodes.sql @@ -1,9 +1,11 @@ {# Fetch FTS DICTIONARY name statement #} SELECT - oid, dictname as name, - dictnamespace as schema + dict.oid, dictname as name, + dictnamespace as schema, + des.description FROM pg_catalog.pg_ts_dict dict + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=dict.oid AND des.classoid='pg_ts_dict'::regclass) WHERE {% if scid %} dict.dictnamespace = {{scid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/__init__.py index 21bbeaa5b..a141c295a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/__init__.py @@ -279,7 +279,8 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-fts_parser" + icon="icon-fts_parser", + description=row['description'] )) return make_json_response( @@ -477,12 +478,17 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare): _("Could not find the FTS Parser node to update.") ) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( pid, data['schema'] if 'schema' in data else scid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/templates/fts_parsers/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/templates/fts_parsers/sql/default/nodes.sql index 996b821cc..d547baeaf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/templates/fts_parsers/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/templates/fts_parsers/sql/default/nodes.sql @@ -1,8 +1,14 @@ {# FETCH FTS PARSER name statement #} SELECT - oid, prsname as name, prs.prsnamespace AS schema + prs.oid, prsname as name, prs.prsnamespace AS schema, des.description FROM pg_catalog.pg_ts_parser prs + LEFT OUTER JOIN pg_catalog.pg_description des +ON + ( + des.objoid=prs.oid + AND des.classoid='pg_ts_parser'::regclass + ) WHERE {% if scid %} prs.prsnamespace = {{scid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py index 64a8eaeea..673bf99fa 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py @@ -257,7 +257,8 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon="icon-fts_template" + icon="icon-fts_template", + description=row['description'] )) return make_json_response( @@ -445,7 +446,8 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare): tid, rset['schema'], rset['name'], - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + description=rset['description'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_templates/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_templates/sql/default/nodes.sql index e07733783..f7b2bf61b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_templates/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_templates/sql/default/nodes.sql @@ -1,7 +1,13 @@ SELECT - oid, tmplname as name, tmpl.tmplnamespace AS schema + tmpl.oid, tmplname as name, tmpl.tmplnamespace AS schema, des.description FROM pg_catalog.pg_ts_template tmpl + LEFT OUTER JOIN pg_catalog.pg_description des +ON + ( + des.objoid=tmpl.oid + AND des.classoid='pg_ts_template'::regclass + ) WHERE {% if scid %} tmpl.tmplnamespace = {{scid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py index 910467492..75f77fa15 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py @@ -435,7 +435,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): row['name'], icon="icon-" + self.node_type, funcowner=row['funcowner'], - language=row['lanname'] + language=row['lanname'], + description=row['description'] ) ) @@ -447,7 +448,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): row['name'], icon="icon-" + self.node_type, funcowner=row['funcowner'], - language=row['lanname'] + language=row['lanname'], + description=row['description'] )) return make_json_response( @@ -977,7 +979,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): obj_name, icon="icon-" + self.node_type, language=resp_data['lanname'], - funcowner=resp_data['funcowner'] + funcowner=resp_data['funcowner'], + description=resp_data['description'] ) ) else: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/__init__.py index fce9632c0..78d3de8a9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/__init__.py @@ -230,7 +230,8 @@ class OperatorView(PGChildNodeView): row['oid'], scid, row['name'], - icon="icon-operator" + icon="icon-operator", + description=row['description'] )) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/templates/operators/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/templates/operators/sql/default/nodes.sql index ec8322c8e..d2444927a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/templates/operators/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/templates/operators/sql/default/nodes.sql @@ -7,7 +7,7 @@ SELECT op.oid, pg_catalog.pg_get_userbyid(op.oprowner) as owner, op.oprname || ' (' || pg_catalog.format_type(lt.oid, NULL) || ')' ELSE op.oprname || '()' END as name, -lt.typname as lefttype, rt.typname as righttype +lt.typname as lefttype, rt.typname as righttype, description FROM pg_catalog.pg_operator op LEFT OUTER JOIN pg_catalog.pg_type lt ON lt.oid=op.oprleft LEFT OUTER JOIN pg_catalog.pg_type rt ON rt.oid=op.oprright diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py index 73686a09a..5be371709 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/__init__.py @@ -239,7 +239,8 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['description'] ) ) @@ -249,7 +250,8 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['description'] )) return make_json_response( @@ -527,12 +529,17 @@ class PackageView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( pkgid, scid, name, - icon=self.node_icon + icon=self.node_icon, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/templates/packages/ppas/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/templates/packages/ppas/default/nodes.sql index 859e42690..ead30b1a5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/templates/packages/ppas/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/templates/packages/ppas/default/nodes.sql @@ -1,7 +1,8 @@ SELECT - nsp.oid, nspname AS name + nsp.oid, nspname AS name, des.description FROM pg_catalog.pg_namespace nsp + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass) WHERE nspparent = {{scid}}::oid {% if pkgid %} AND nsp.oid = {{pkgid}}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py index ae3bda023..5fbfa2741 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py @@ -229,7 +229,9 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['comment'] + ), status=200 ) @@ -240,7 +242,8 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['description'] )) return make_json_response( @@ -563,7 +566,8 @@ class SequenceView(PGChildNodeView, SchemaDiffObjectCompare): seid, row['schema'], row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['comment'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequences/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequences/sql/default/nodes.sql index 73f74e365..327dd1f66 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequences/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequences/sql/default/nodes.sql @@ -1,5 +1,7 @@ -SELECT cl.oid as oid, relname as name, relnamespace as schema +SELECT cl.oid as oid, relname as name, relnamespace as schema, description as comment FROM pg_catalog.pg_class cl +LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=cl.oid + AND des.classoid='pg_class'::regclass) {% if show_internal %} LEFT JOIN pg_catalog.pg_depend d1 ON d1.refobjid = cl.oid AND d1.deptype = 'i' {% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py index c05e24a87..35a696dd9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/__init__.py @@ -438,7 +438,8 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare): icon=icon, tigger_count=row['triggercount'], has_enable_triggers=row['has_enable_triggers'], - is_partitioned=self.is_table_partitioned(row) + is_partitioned=self.is_table_partitioned(row), + description=row['description'] )) return make_json_response( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/__init__.py index d81420f29..4e963a095 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/__init__.py @@ -291,7 +291,8 @@ class ColumnsView(PGChildNodeView, DataTypeReader): tid, row['name'], icon="icon-column", - datatype=row['datatype'] # We need datatype somewhere in + datatype=row['datatype'], # We need datatype somewhere in, + description=row['description'] ), status=200 ) @@ -303,7 +304,8 @@ class ColumnsView(PGChildNodeView, DataTypeReader): tid, row['name'], icon="icon-column", - datatype=row['datatype'] # We need datatype somewhere in + datatype=row['datatype'], # We need datatype somewhere in + description=row['description'] )) # exclusion constraint. return make_json_response( @@ -535,12 +537,17 @@ class ColumnsView(PGChildNodeView, DataTypeReader): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( clid, tid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py index b656b8e1d..e33063729 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/__init__.py @@ -398,7 +398,8 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare): row['name'], icon="icon-compound_trigger-bad" if row['is_enable_trigger'] == 'D' - else "icon-compound_trigger" + else "icon-compound_trigger", + description=row['description'] )) return make_json_response( @@ -671,7 +672,8 @@ class CompoundTriggerView(PGChildNodeView, SchemaDiffObjectCompare): name, icon="icon-%s-bad" % self.node_type if data['is_enable_trigger'] == 'D' else - "icon-%s" % self.node_type + "icon-%s" % self.node_type, + description=data['description'] ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/__init__.py index 72e43f99c..f7bc7597a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/__init__.py @@ -359,7 +359,8 @@ class CheckConstraintView(PGChildNodeView): tid, row['name'], icon=icon, - valid=valid + valid=valid, + description=row['comment'] )) return make_json_response( data=res, @@ -699,13 +700,18 @@ class CheckConstraintView(PGChildNodeView): icon = 'icon-check_constraint' valid = True + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( cid, tid, name, icon=icon, - valid=valid + valid=valid, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py index b43b13fc3..a12a7ae88 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/__init__.py @@ -419,7 +419,8 @@ class ExclusionConstraintView(PGChildNodeView): row['oid'], tid, row['name'], - icon="icon-exclusion_constraint" + icon="icon-exclusion_constraint", + description=row['comment'] )) return make_json_response( data=res, @@ -639,12 +640,17 @@ class ExclusionConstraintView(PGChildNodeView): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( exid, tid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/__init__.py index 55b87a28c..428b3d69f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/__init__.py @@ -442,7 +442,8 @@ class ForeignKeyConstraintView(PGChildNodeView): tid, row['name'], icon=icon, - valid=valid + valid=valid, + description=row['comment'] )) return make_json_response( data=res, @@ -702,6 +703,10 @@ class ForeignKeyConstraintView(PGChildNodeView): icon = "icon-foreign_key" valid = True + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( fkid, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py index 829348a30..cb5ecd140 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/__init__.py @@ -442,7 +442,8 @@ class IndexConstraintView(PGChildNodeView): row['oid'], tid, row['name'], - icon=self.node_icon + icon=self.node_icon, + description=row['comment'] ) ) return make_json_response( @@ -686,6 +687,10 @@ class IndexConstraintView(PGChildNodeView): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( cid, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py index e4c8ce71c..73400b176 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py @@ -462,7 +462,8 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): row['oid'], tid, row['name'], - icon="icon-index" + icon="icon-index", + description=row['description'] )) return make_json_response( @@ -770,12 +771,17 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( idx, tid, name, - icon="icon-%s" % self.node_type + icon="icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py index 45622a135..435c01d81 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py @@ -306,7 +306,8 @@ class PartitionsView(BaseTableView, DataTypeReader, SchemaDiffObjectCompare): is_partitioned=row['is_partitioned'], parent_schema_id=scid, schema_id=row['schema_id'], - schema_name=row['schema_name'] + schema_name=row['schema_name'], + description=row['description'] ) if ptid is not None: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py index ea95935b7..566371504 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/__init__.py @@ -274,7 +274,8 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): row['name'], icon="icon-rule-bad" if 'is_enable_rule' in row and - row['is_enable_rule'] == 'D' else "icon-rule" + row['is_enable_rule'] == 'D' else "icon-rule", + description=row['comment'] )) return make_json_response( @@ -381,6 +382,11 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): status, res = self.conn.execute_scalar(SQL) if not status: return internal_server_error(errormsg=res) + + other_node_info = {} + if 'comment' in data: + other_node_info['description'] = data['comment'] + return jsonify( node=self.blueprint.generate_browser_node( rid, @@ -389,7 +395,8 @@ class RuleView(PGChildNodeView, SchemaDiffObjectCompare): icon="icon-%s-bad" % self.node_type if 'is_enable_rule' in data and data['is_enable_rule'] == 'D' - else "icon-%s" % self.node_type + else "icon-%s" % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/nodes.sql index c859975e9..57e4b144a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/nodes.sql @@ -1,6 +1,9 @@ SELECT c.oid, conname as name, - NOT convalidated as convalidated, conislocal + NOT convalidated as convalidated, conislocal, description as comment FROM pg_catalog.pg_constraint c +LEFT OUTER JOIN + pg_catalog.pg_description des ON (des.objoid=c.oid AND + des.classoid='pg_constraint'::regclass) WHERE contype = 'c' AND conrelid = {{ tid }}::oid {% if cid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql index 171eb740d..660f12dd4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/columns/sql/default/nodes.sql @@ -1,5 +1,5 @@ SELECT DISTINCT att.attname as name, att.attnum as OID, pg_catalog.format_type(ty.oid,NULL) AS datatype, -att.attnotnull as not_null, att.atthasdef as has_default_val +att.attnotnull as not_null, att.atthasdef as has_default_val, des.description FROM pg_catalog.pg_attribute att JOIN pg_catalog.pg_type ty ON ty.oid=atttypid JOIN pg_catalog.pg_namespace tn ON tn.oid=ty.typnamespace @@ -10,6 +10,7 @@ FROM pg_catalog.pg_attribute att LEFT OUTER JOIN (pg_catalog.pg_depend JOIN pg_catalog.pg_class cs ON classid='pg_class'::regclass AND objid=cs.oid AND cs.relkind='S') ON refobjid=att.attrelid AND refobjsubid=att.attnum LEFT OUTER JOIN pg_catalog.pg_namespace ns ON ns.oid=cs.relnamespace LEFT OUTER JOIN pg_catalog.pg_index pi ON pi.indrelid=att.attrelid AND indisprimary + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=att.attrelid AND des.objsubid=att.attnum AND des.classoid='pg_class'::regclass) WHERE att.attrelid = {{ tid|qtLiteral(conn) }}::oid {% if clid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/compound_triggers/sql/ppas/12_plus/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/compound_triggers/sql/ppas/12_plus/nodes.sql index fa728fcb8..4e6d29453 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/compound_triggers/sql/ppas/12_plus/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/compound_triggers/sql/ppas/12_plus/nodes.sql @@ -1,6 +1,6 @@ -SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger +SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger, des.description FROM pg_catalog.pg_trigger t - +LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_trigger'::regclass) WHERE NOT tgisinternal AND tgrelid = {{tid}}::OID AND tgpackageoid != 0 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/nodes.sql index 2c09229ce..7091f1bb7 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/nodes.sql @@ -1,7 +1,9 @@ SELECT conindid as oid, conname as name, - NOT convalidated as convalidated + NOT convalidated as convalidated, + desp.description AS comment FROM pg_catalog.pg_constraint ct +LEFT OUTER JOIN pg_catalog.pg_description desp ON (desp.objoid=ct.oid AND desp.objsubid = 0 AND desp.classoid='pg_constraint'::regclass) WHERE contype='x' AND conrelid = {{tid}}::oid {% if exid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/nodes.sql index 765c0391a..bd925d846 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/nodes.sql @@ -1,7 +1,9 @@ SELECT ct.oid, conname as name, - NOT convalidated as convalidated + NOT convalidated as convalidated, + description as comment FROM pg_catalog.pg_constraint ct +LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=ct.oid AND des.classoid='pg_constraint'::regclass) WHERE contype='f' AND conrelid = {{tid}}::oid ORDER BY conname diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/nodes.sql index ca9d53a51..53c37f50a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/nodes.sql @@ -1,4 +1,10 @@ -SELECT cls.oid, cls.relname as name +SELECT cls.oid, cls.relname as name, + CASE contype + WHEN 'p' THEN desp.description + WHEN 'u' THEN desp.description + WHEN 'x' THEN desp.description + ELSE des.description + END AS comment FROM pg_catalog.pg_index idx JOIN pg_catalog.pg_class cls ON cls.oid=indexrelid LEFT JOIN pg_catalog.pg_depend dep ON (dep.classid = cls.tableoid AND @@ -10,6 +16,8 @@ LEFT JOIN pg_catalog.pg_depend dep ON (dep.classid = cls.tableoid AND dep.deptype='i') LEFT OUTER JOIN pg_catalog.pg_constraint con ON (con.tableoid = dep.refclassid AND con.oid = dep.refobjid) +LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=cls.oid AND des.classoid='pg_class'::regclass) +LEFT OUTER JOIN pg_catalog.pg_description desp ON (desp.objoid=con.oid AND desp.objsubid = 0 AND desp.classoid='pg_constraint'::regclass) WHERE indrelid = {{tid}}::oid AND contype='{{constraint_type}}' {% if cid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql index 7092aba24..9fc9323d4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/rules/sql/nodes.sql @@ -2,10 +2,11 @@ SELECT rw.oid AS oid, rw.rulename AS name, CASE WHEN rw.ev_enabled != 'D' THEN True ELSE False END AS enabled, - rw.ev_enabled AS is_enable_rule - + rw.ev_enabled AS is_enable_rule, + description AS comment FROM pg_catalog.pg_rewrite rw + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rw.oid AND des.classoid='pg_rewrite'::regclass) WHERE {% if tid %} rw.ev_class = {{ tid }} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/nodes.sql index 75ffacabf..db9749ab6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/tables/sql/default/nodes.sql @@ -3,8 +3,10 @@ SELECT rel.oid, rel.relname AS name, (SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=rel.oid AND tgisinternal = FALSE AND tgenabled = 'O') AS has_enable_triggers, (CASE WHEN rel.relkind = 'p' THEN true ELSE false END) AS is_partitioned, (SELECT count(1) FROM pg_catalog.pg_inherits WHERE inhrelid=rel.oid LIMIT 1) as is_inherits, - (SELECT count(1) FROM pg_catalog.pg_inherits WHERE inhparent=rel.oid LIMIT 1) as is_inherited + (SELECT count(1) FROM pg_catalog.pg_inherits WHERE inhparent=rel.oid LIMIT 1) as is_inherited, + des.description FROM pg_catalog.pg_class rel + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass) WHERE rel.relkind IN ('r','s','t','p') AND rel.relnamespace = {{ scid }}::oid AND NOT rel.relispartition {% if tid %} AND rel.oid = {{tid}}::OID {% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/nodes.sql index 20e9e6aef..183ff742c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/pg/default/nodes.sql @@ -1,6 +1,7 @@ -SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger +SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger, des.description FROM pg_catalog.pg_trigger t - WHERE NOT tgisinternal + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_trigger'::regclass) +WHERE NOT tgisinternal AND tgrelid = {{tid}}::OID {% if trid %} AND t.oid = {{trid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/nodes.sql index 20e9e6aef..183ff742c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/triggers/sql/ppas/default/nodes.sql @@ -1,6 +1,7 @@ -SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger +SELECT t.oid, t.tgname as name, t.tgenabled AS is_enable_trigger, des.description FROM pg_catalog.pg_trigger t - WHERE NOT tgisinternal + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_trigger'::regclass) +WHERE NOT tgisinternal AND tgrelid = {{tid}}::OID {% if trid %} AND t.oid = {{trid}}::OID diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py index 5bb10a3fc..356242b5e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py @@ -488,7 +488,8 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare): tid, row['name'], icon="icon-trigger-bad" if row['is_enable_trigger'] == 'D' - else "icon-trigger" + else "icon-trigger", + description=row['description'] )) return make_json_response( @@ -763,7 +764,8 @@ class TriggerView(PGChildNodeView, SchemaDiffObjectCompare): name, icon="icon-%s-bad" % self.node_type if data['is_enable_trigger'] == 'D' else - "icon-%s" % self.node_type + "icon-%s" % self.node_type, + description=data['description'] ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py index 1a4d63d49..920e11fdb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/utils.py @@ -1628,6 +1628,10 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings): else: icon = self.get_icon_css_class(res['rows'][0]) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( tid, @@ -1638,7 +1642,8 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings): parent_schema_id=scid, schema_id=rest['rows'][0]['scid'], schema_name=rest['rows'][0]['nspname'], - affected_partitions=partitions_oid + affected_partitions=partitions_oid, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/pg/default/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/pg/default/sql/nodes.sql index 5de3ee5b4..e9edaec48 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/pg/default/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/pg/default/sql/nodes.sql @@ -3,9 +3,12 @@ SELECT nsp.oid, {{ CATALOGS.LABELS('nsp', _) }}, pg_catalog.has_schema_privilege(nsp.oid, 'CREATE') as can_create, - pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage + pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage, + des.description FROM pg_catalog.pg_namespace nsp + LEFT OUTER JOIN pg_catalog.pg_description des ON + (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass) WHERE {% if scid %} nsp.oid={{scid}}::oid AND diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/ppas/default/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/ppas/default/sql/nodes.sql index 83db58499..82a532d04 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/ppas/default/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/ppas/default/sql/nodes.sql @@ -3,9 +3,12 @@ SELECT nsp.oid, {{ CATALOGS.LABELS('nsp', _) }}, pg_catalog.has_schema_privilege(nsp.oid, 'CREATE') as can_create, - pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage + pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage, + des.description FROM pg_catalog.pg_namespace nsp + LEFT OUTER JOIN pg_catalog.pg_description des ON + (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass) WHERE {% if scid %} nsp.oid={{scid}}::oid AND diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/pg/default/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/pg/default/sql/nodes.sql index c4b1197e6..2c31a53d4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/pg/default/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/pg/default/sql/nodes.sql @@ -3,9 +3,12 @@ SELECT nsp.oid, nsp.nspname as name, pg_catalog.has_schema_privilege(nsp.oid, 'CREATE') as can_create, - pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage + pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage, + des.description FROM pg_catalog.pg_namespace nsp + LEFT OUTER JOIN pg_catalog.pg_description des ON + (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass) WHERE {% if scid %} nsp.oid={{scid}}::oid AND diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/ppas/default/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/ppas/default/sql/nodes.sql index 7f1c94796..3e1f656a2 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/ppas/default/sql/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schemas/ppas/default/sql/nodes.sql @@ -3,9 +3,12 @@ SELECT nsp.oid, nsp.nspname as name, pg_catalog.has_schema_privilege(nsp.oid, 'CREATE') as can_create, - pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage + pg_catalog.has_schema_privilege(nsp.oid, 'USAGE') as has_usage, + des.description FROM pg_catalog.pg_namespace nsp + LEFT OUTER JOIN pg_catalog.pg_description des ON + (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass) WHERE nsp.nspparent = 0 AND {% if scid %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py index 7f9a13e86..592faad0e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py @@ -358,7 +358,8 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): row['oid'], scid, row['name'], - icon=self.icon_str % self.node_type + icon=self.icon_str % self.node_type, + description=row['description'] )) return make_json_response( @@ -1101,12 +1102,17 @@ class TypeView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare): if not status: return internal_server_error(errormsg=res) + other_node_info = {} + if 'description' in data: + other_node_info['description'] = data['description'] + return jsonify( node=self.blueprint.generate_browser_node( tid, scid, name, - icon=self.icon_str % self.node_type + icon=self.icon_str % self.node_type, + **other_node_info ) ) except Exception as e: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/nodes.sql index bc7eb8276..8032959e1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/pg/sql/default/nodes.sql @@ -1,8 +1,9 @@ -SELECT t.oid, t.typname AS name +SELECT t.oid, t.typname AS name, des.description FROM pg_catalog.pg_type t LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid {% if tid %} AND t.oid = {{tid}}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/nodes.sql index bc7eb8276..8032959e1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/types/ppas/sql/default/nodes.sql @@ -1,8 +1,9 @@ -SELECT t.oid, t.typname AS name +SELECT t.oid, t.typname AS name, des.description FROM pg_catalog.pg_type t LEFT OUTER JOIN pg_catalog.pg_type e ON e.oid=t.typelem LEFT OUTER JOIN pg_catalog.pg_class ct ON ct.oid=t.typrelid AND ct.relkind <> 'c' LEFT OUTER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = t.typnamespace + LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=t.oid AND des.classoid='pg_type'::regclass) WHERE t.typtype != 'd' AND t.typname NOT LIKE E'\\_%' AND t.typnamespace = {{scid}}::oid {% if tid %} AND t.oid = {{tid}}::oid diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/nodes.sql index 1566346d1..4b751d469 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/nodes.sql @@ -1,10 +1,14 @@ SELECT db.oid as did, db.datname as name, ta.spcname as spcname, db.datallowconn, db.datistemplate AS is_template, - pg_catalog.has_database_privilege(db.oid, 'CREATE') as cancreate, datdba as owner + pg_catalog.has_database_privilege(db.oid, 'CREATE') as cancreate, datdba as owner, + descr.description FROM pg_catalog.pg_database db LEFT OUTER JOIN pg_catalog.pg_tablespace ta ON db.dattablespace = ta.oid + LEFT OUTER JOIN pg_catalog.pg_shdescription descr ON ( + db.oid=descr.objoid AND descr.classoid='pg_database'::regclass + ) WHERE {% if did %} db.oid = {{ did|qtLiteral(conn) }}::OID {% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py index 93bec75d3..131807ef6 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py @@ -209,7 +209,8 @@ SELECT EXISTS( sid, rset['rows'][0]['jobname'], "icon-pga_job" if rset['rows'][0]['jobenabled'] else - "icon-pga_job-disabled" + "icon-pga_job-disabled", + description=rset['rows'][0]['jobdesc'] ), status=200 ) @@ -222,7 +223,8 @@ SELECT EXISTS( sid, row['jobname'], "icon-pga_job" if row['jobenabled'] else - "icon-pga_job-disabled" + "icon-pga_job-disabled", + description=row['jobdesc'] ) ) @@ -397,7 +399,8 @@ SELECT EXISTS( sid, row['jobname'], icon="icon-pga_job" if row['jobenabled'] - else "icon-pga_job-disabled" + else "icon-pga_job-disabled", + description=row['jobdesc'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py index 4278c0fce..4ca57b428 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py @@ -265,7 +265,8 @@ class JobScheduleView(PGChildNodeView): row['jscname'], icon="icon-pga_schedule" if row['jscenabled'] else "icon-pga_schedule-disabled", - enabled=row['jscenabled'] + enabled=row['jscenabled'], + description=row['jscdesc'] ) ) @@ -277,7 +278,8 @@ class JobScheduleView(PGChildNodeView): row['jscname'], icon="icon-pga_schedule" if row['jscenabled'] else "icon-pga_schedule-disabled", - enabled=row['jscenabled'] + enabled=row['jscenabled'], + description=row['jscdesc'] ) ) @@ -455,7 +457,8 @@ class JobScheduleView(PGChildNodeView): row['jscname'], icon="icon-pga_schedule" if row['jscenabled'] else "icon-pga_schedule-disabled", - enabled=row['jscenabled'] + enabled=row['jscenabled'], + description=row['jscdesc'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py index 02128934a..c6b564b7f 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py @@ -280,7 +280,8 @@ SELECT EXISTS( icon="icon-pga_jobstep" if row['jstenabled'] else "icon-pga_jobstep-disabled", enabled=row['jstenabled'], - kind=row['jstkind'] + kind=row['jstkind'], + description=row['jstdesc'] ) ) @@ -293,7 +294,8 @@ SELECT EXISTS( icon="icon-pga_jobstep" if row['jstenabled'] else "icon-pga_jobstep-disabled", enabled=row['jstenabled'], - kind=row['jstkind'] + kind=row['jstkind'], + description=row['jstdesc'] ) ) @@ -478,7 +480,8 @@ SELECT EXISTS( jid, row['jstname'], icon="icon-pga_jobstep" if row['jstenabled'] - else "icon-pga_jobstep-disabled" + else "icon-pga_jobstep-disabled", + description=row['jstdesc'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_job/sql/pre3.4/nodes.sql b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_job/sql/pre3.4/nodes.sql index 16ef3c316..0524d0cb6 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_job/sql/pre3.4/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_job/sql/pre3.4/nodes.sql @@ -1,5 +1,5 @@ SELECT - jobid, jobname, jobenabled + jobid, jobname, jobenabled, jobdesc FROM pgagent.pga_job {% if jid %} diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_jobstep/sql/pre3.4/nodes.sql b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_jobstep/sql/pre3.4/nodes.sql index 8c3143b69..444bd6279 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_jobstep/sql/pre3.4/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_jobstep/sql/pre3.4/nodes.sql @@ -1,5 +1,5 @@ SELECT - jstid, jstjobid, jstname, jstenabled, jstkind = 's'::bpchar AS jstkind + jstid, jstjobid, jstname, jstenabled, jstkind = 's'::bpchar AS jstkind, jstdesc FROM pgagent.pga_jobstep WHERE diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_schedule/sql/pre3.4/nodes.sql b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_schedule/sql/pre3.4/nodes.sql index 845119994..e33095118 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_schedule/sql/pre3.4/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/pgagent/templates/pga_schedule/sql/pre3.4/nodes.sql @@ -1,5 +1,5 @@ SELECT - jscid, jscjobid, jscname, jscenabled + jscid, jscjobid, jscname, jscenabled, jscdesc FROM pgagent.pga_schedule WHERE diff --git a/web/pgadmin/browser/server_groups/servers/roles/__init__.py b/web/pgadmin/browser/server_groups/servers/roles/__init__.py index 8e570986e..78402731e 100644 --- a/web/pgadmin/browser/server_groups/servers/roles/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/roles/__init__.py @@ -741,7 +741,8 @@ rolmembership:{ row['rolname'], 'icon-role' if row['rolcanlogin'] else 'icon-group', can_login=row['rolcanlogin'], - is_superuser=row['rolsuper'] + is_superuser=row['rolsuper'], + description=row['description'] ) ) @@ -1005,7 +1006,8 @@ rolmembership:{ row['rolname'], 'icon-role' if row['rolcanlogin'] else 'icon-group', can_login=row['rolcanlogin'], - is_superuser=row['rolsuper'] + is_superuser=row['rolsuper'], + description=row['description'] ) ) diff --git a/web/pgadmin/browser/server_groups/servers/roles/templates/roles/sql/default/nodes.sql b/web/pgadmin/browser/server_groups/servers/roles/templates/roles/sql/default/nodes.sql index 79911c029..28a03dea8 100644 --- a/web/pgadmin/browser/server_groups/servers/roles/templates/roles/sql/default/nodes.sql +++ b/web/pgadmin/browser/server_groups/servers/roles/templates/roles/sql/default/nodes.sql @@ -1,5 +1,6 @@ SELECT - r.oid, r.rolname, r.rolcanlogin, r.rolsuper + r.oid, r.rolname, r.rolcanlogin, r.rolsuper, + pg_catalog.shobj_description(r.oid, 'pg_authid') AS description FROM pg_catalog.pg_roles r {% if rid %} diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js index 7e46ef58f..f10a29eb4 100644 --- a/web/pgadmin/browser/static/js/browser.js +++ b/web/pgadmin/browser/static/js/browser.js @@ -1384,12 +1384,8 @@ define('pgadmin.browser', [ } if (this.new._id == _id) { // Found the current - _.extend(this.d, { - '_id': this.new._id, - '_label': this.new._label, - 'label': this.new.label, - }); - this.t.update(ctx.i, this.new); + _.extend(this.d, this.new); + this.t.update(ctx.i, this.d); this.t.setLabel(ctx.i, {label: this.new.label}); this.t.addIcon(ctx.i, {icon: this.new.icon}); this.t.setId(ctx.i, {id: this.new.id}); @@ -1632,11 +1628,8 @@ define('pgadmin.browser', [ // If server icon/background changes then also we need to re-create it if (( _old._type == 'server' && _new._type == 'server' && ( - _old._pid != _new._pid || - _old._label != _new._label || - _old.icon != _new.icon - )) || _old._pid != _new._pid || _old._label != _new._label || - _old._id != _new._id + _old._pid != _new._pid || _old.icon != _new.icon + )) || _old._pid != _new._pid || _old._id != _new._id ) { ctx.op = 'RECREATE'; traversePath(); diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index 2f2d0530b..cdd32d794 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -833,7 +833,7 @@ define('pgadmin.browser.node', [ background: ${bgcolor} !important; } ${fgcolor ? ` - .${dynamic_class} span.file-name { + .${dynamic_class} span.file-name, .${dynamic_class} span.file-name:hover, .${dynamic_class} span.file-name.pseudo-active { color: ${fgcolor} !important; } `:''} diff --git a/web/pgadmin/browser/static/scss/_browser.scss b/web/pgadmin/browser/static/scss/_browser.scss index 2f972b0ee..096bb0fac 100644 --- a/web/pgadmin/browser/static/scss/_browser.scss +++ b/web/pgadmin/browser/static/scss/_browser.scss @@ -53,8 +53,8 @@ samp, border-width: 1px; font-size: 1.15em; - color: $color-fg !important; - border-color: $border-color !important; + color: $color-fg; + border-color: $border-color; background-color: $color-secondary; } diff --git a/web/pgadmin/browser/templates/browser/index.html b/web/pgadmin/browser/templates/browser/index.html index a231996c8..975e753cb 100644 --- a/web/pgadmin/browser/templates/browser/index.html +++ b/web/pgadmin/browser/templates/browser/index.html @@ -98,6 +98,7 @@ require.onResourceLoad = function (context, map, depMaps) { {% else %}
{% endif %} +
{% include 'browser/messages.html' %} diff --git a/web/pgadmin/static/bundle/app.js b/web/pgadmin/static/bundle/app.js index 63a9d27cc..982088073 100644 --- a/web/pgadmin/static/bundle/app.js +++ b/web/pgadmin/static/bundle/app.js @@ -11,6 +11,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import MainMenuFactory from '../../browser/static/js/MainMenuFactory'; import AppMenuBar from '../js/AppMenuBar'; +import ObjectBreadcrumbs from '../js/components/ObjectBreadcrumbs'; import Theme from '../js/Theme'; define('app', [ @@ -52,6 +53,16 @@ define('app', [ const menuContainerEle = document.querySelector('#main-menu-container'); if(menuContainerEle) { - ReactDOM.render(, document.querySelector('#main-menu-container')); + ReactDOM.render( + + + , menuContainerEle + ); } + + ReactDOM.render( + + + , document.querySelector('#object-breadcrumbs') + ); }); diff --git a/web/pgadmin/static/js/components/ObjectBreadcrumbs.jsx b/web/pgadmin/static/js/components/ObjectBreadcrumbs.jsx new file mode 100644 index 000000000..3ffef8292 --- /dev/null +++ b/web/pgadmin/static/js/components/ObjectBreadcrumbs.jsx @@ -0,0 +1,120 @@ +import { Box, makeStyles } from '@material-ui/core'; +import React, { useState, useEffect } from 'react'; +import AccountTreeIcon from '@material-ui/icons/AccountTree'; +import CommentIcon from '@material-ui/icons/Comment'; +import ArrowForwardIosRoundedIcon from '@material-ui/icons/ArrowForwardIosRounded'; +import PropTypes from 'prop-types'; +import { useIsMounted } from '../custom_hooks'; + +const useStyles = makeStyles((theme)=>({ + root: { + position: 'absolute', + bottom: 0, + width: 'auto', + maxWidth: '99%', + zIndex: 9999, + padding: '0.25rem 0.5rem', + fontSize: '0.95em', + color: theme.palette.background.default, + backgroundColor: theme.palette.text.primary, + borderTopRightRadius: theme.shape.borderRadius, + }, + row: { + display: 'flex', + alignItems: 'center' + }, + overflow: { + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + overflow: 'hidden', + } +})); + + + +export default function ObjectBreadcrumbs({pgAdmin}) { + const classes = useStyles(); + const checkIsMounted = useIsMounted(); + const [preferences, setPreferences] = useState({ + breadcrumbs_enable: false, + breadcrumbs_show_comment: true, + }); + const [objectData, setObjectData] = useState({ + path: null, + description: null, + }); + const onItemHover = (item, _data)=>{ + // if(!checkIsMounted) return; + if(item && !_data?._type.startsWith('coll-')) { + setObjectData({ + path: pgAdmin.Browser.tree.getNodeDisplayPath(item, false), + description: item?._metadata?.data.description + }); + } else { + setObjectData({ + path: null, + description: null + }); + } + }; + + useEffect(()=>{ + const setPrefs = ()=>{ + if(!checkIsMounted()) return; + let pref = pgAdmin.Browser.get_preferences_for_module('browser'); + setPreferences({ + breadcrumbs_enable: pref.breadcrumbs_enable, + breadcrumbs_show_comment: pref.breadcrumbs_show_comment, + }); + }; + let cacheIntervalId = setInterval(function() { + if(pgAdmin.Browser.preference_version() > 0) { + clearInterval(cacheIntervalId); + setPrefs(); + } + },0); + + pgAdmin.Browser.onPreferencesChange('browser', function() { + setPrefs(); + }); + }, []); + + useEffect(()=>{ + if(preferences.breadcrumbs_enable) { + pgAdmin.Browser.Events.on('pgadmin-browser:tree:hovered', onItemHover); + } + return ()=>{ + pgAdmin.Browser.Events.off('pgadmin-browser:tree:hovered', onItemHover); + }; + }, [preferences.breadcrumbs_enable]); + + if(!objectData.path) { + return <>; + } + + return( + <> + +
+ +
+ { + objectData.path?.reduce((res, item)=>( + res.concat({item}, ) + ), []).slice(0, -1) + } +
+
+ {preferences.breadcrumbs_show_comment && objectData.description && +
+ +
{objectData.description}
+
} +
+ + ); +} + +ObjectBreadcrumbs.propTypes = { + pgAdmin: PropTypes.object, +}; diff --git a/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx b/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx index de880ca8a..268297dab 100644 --- a/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx +++ b/web/pgadmin/static/js/components/PgTree/FileTreeItem/index.tsx @@ -18,6 +18,9 @@ interface IItemRendererXProps { decorations: ClasslistComposite onClick: (ev: React.MouseEvent, item: FileEntry | Directory, type: ItemType) => void onContextMenu: (ev: React.MouseEvent, item: FileEntry | Directory) => void + onMouseEnter: (ev: React.MouseEvent, item: FileEntry | Directory) => void + onMouseLeave: (ev: React.MouseEvent, item: FileEntry | Directory) => void + onItemHovered: (ev: React.MouseEvent, item: FileEntry | Directory, type: ItemType) => void events: Notificar } @@ -81,6 +84,8 @@ export class FileTreeItem extends React.Component @@ -166,6 +171,20 @@ export class FileTreeItem extends React.Component { + const { item, itemType, onMouseEnter } = this.props; + if (itemType === ItemType.File || itemType === ItemType.Directory) { + onMouseEnter?.(ev, item as FileEntry); + } + }; + + private handleMouseLeave = (ev: React.MouseEvent) => { + const { item, itemType, onMouseLeave } = this.props; + if (itemType === ItemType.File || itemType === ItemType.Directory) { + onMouseLeave?.(ev, item as FileEntry); + } + }; + private handleDragStartItem = (e: React.DragEvent) => { const { item, itemType, events } = this.props; if (itemType === ItemType.File || itemType === ItemType.Directory) { diff --git a/web/pgadmin/static/js/components/PgTree/FileTreeX/index.tsx b/web/pgadmin/static/js/components/PgTree/FileTreeX/index.tsx index e6ef069cc..cd767aeba 100644 --- a/web/pgadmin/static/js/components/PgTree/FileTreeX/index.tsx +++ b/web/pgadmin/static/js/components/PgTree/FileTreeX/index.tsx @@ -29,6 +29,8 @@ export class FileTreeX extends React.Component { private disposables: DisposablesComposite; private keyboardHotkeys: KeyboardHotkeys; private fileTreeEvent: IFileTreeXTriggerEvents; + private hoverTimeoutId: React.RefObject = React.createRef(); + private hoverDispatchId: React.RefObject = React.createRef(); constructor(props: IFileTreeXProps) { super(props); this.events = new Notificar(); @@ -73,6 +75,8 @@ export class FileTreeX extends React.Component { onClick={this.handleItemClicked} onDoubleClick={this.handleItemDoubleClicked} onContextMenu={this.handleItemCtxMenu} + onMouseEnter={this.onItemMouseEnter} + onMouseLeave={this.onItemMouseLeave} changeDirectoryCount={this.changeDirectoryCount} events={this.events}/>} @@ -166,6 +170,22 @@ export class FileTreeX extends React.Component { } }; + private onItemMouseEnter = (ev: React.MouseEvent, item: FileEntry | Directory) => { + clearTimeout(this.hoverDispatchId.current??undefined); + (this.hoverDispatchId as any).current = setTimeout(()=>{ + clearTimeout(this.hoverTimeoutId.current??undefined); + this.events.dispatch(FileTreeXEvent.onTreeEvents, ev, 'hovered', item); + }, 500); + }; + + private onItemMouseLeave = (ev: React.MouseEvent) => { + clearTimeout(this.hoverTimeoutId.current??undefined); + clearTimeout(this.hoverDispatchId.current??undefined); + (this.hoverTimeoutId as any).current = setTimeout(()=>{ + this.events.dispatch(FileTreeXEvent.onTreeEvents, ev, 'hovered', null); + }, 100); + }; + private setActiveFile = async (fileOrDirOrPath: FileOrDir | string, ensureVisible, align): Promise => { const fileH = typeof fileOrDirOrPath === 'string' ? await this.fileTreeHandle.getFileHandle(fileOrDirOrPath) diff --git a/web/pgadmin/static/js/components/PgTree/scss/styles.scss b/web/pgadmin/static/js/components/PgTree/scss/styles.scss index b88b606f5..9d179804e 100644 --- a/web/pgadmin/static/js/components/PgTree/scss/styles.scss +++ b/web/pgadmin/static/js/components/PgTree/scss/styles.scss @@ -171,7 +171,7 @@ &:hover, &.pseudo-active { - color: $tree-fg-hover !important; + color: $tree-fg-hover; } } @@ -184,14 +184,14 @@ font: inherit; flex-grow: 1; user-select: none; - color: $tree-text-fg !important; + color: $tree-text-fg; margin-left: 3px; cursor: pointer !important; white-space: nowrap; &:hover, &.pseudo-active { - color: $tree-fg-hover !important; + color: $tree-fg-hover; } } } @@ -324,7 +324,7 @@ flex-grow: 1; user-select: none; cursor: default; - color: #c1c1c1; + color: $color-fg; margin-left: 3px; & input[type='text'] { diff --git a/web/pgadmin/static/js/tree/tree.js b/web/pgadmin/static/js/tree/tree.js index e01d7e4f1..bcfe9d304 100644 --- a/web/pgadmin/static/js/tree/tree.js +++ b/web/pgadmin/static/js/tree/tree.js @@ -29,6 +29,16 @@ function manageTreeEvents(event, eventName, item) { console.warn(e.stack || e); return false; } + } else if(eventName == 'hovered') { + /* Raise tree events for the nodes */ + try { + obj.Events.trigger( + 'pgadmin-browser:tree:' + eventName, item, d, node + ); + } catch (e) { + console.warn(e.stack || e); + return false; + } } else { // Events for browser tree. if (d && obj.Nodes[d._type]) { @@ -384,6 +394,23 @@ export class Tree { })(tree.tree.getModel().root); } + getNodeDisplayPath(item, separator='/', skip_coll=false) { + let retStack = []; + let currItem = item; + while(currItem?.fileName) { + const data = currItem._metadata?.data; + if(data._type.startsWith('coll-') && skip_coll) { + /* Skip collection */ + } else { + retStack.push(data._label); + } + currItem = currItem.parent; + } + retStack = retStack.reverse(); + if(separator == false) return retStack; + return retStack.join(separator); + } + findNodeByDomElement(domElement) { const path = domElement.path; if (!path || !path[0]) { diff --git a/web/pgadmin/static/scss/resources/_default.variables.scss b/web/pgadmin/static/scss/resources/_default.variables.scss index 35ee76233..2328b04e7 100644 --- a/web/pgadmin/static/scss/resources/_default.variables.scss +++ b/web/pgadmin/static/scss/resources/_default.variables.scss @@ -305,6 +305,9 @@ $card-header-fg: $color-fg !default; $card-header-border-color: $border-color !default; $no-border-radius: 0px !important; +$tooltip-color: $color-bg; +$tooltip-bg: $color-fg; + $btn-checkbox-padding: $input-btn-padding-y $input-btn-padding-x; $scrollbar-base-color: #bac1cd !default; diff --git a/web/pgadmin/utils/constants.py b/web/pgadmin/utils/constants.py index 61f147af8..5d25975a4 100644 --- a/web/pgadmin/utils/constants.py +++ b/web/pgadmin/utils/constants.py @@ -18,6 +18,7 @@ MIMETYPE_APP_JSON = 'application/json' # Preference labels PREF_LABEL_KEYBOARD_SHORTCUTS = gettext('Keyboard shortcuts') PREF_LABEL_DISPLAY = gettext('Display') +PREF_LABEL_BREADCRUMBS = gettext('Object Breadcrumbs') PREF_LABEL_OPTIONS = gettext('Options') PREF_LABEL_EXPLAIN = gettext('Explain') PREF_LABEL_EDITOR = gettext('Editor') diff --git a/web/regression/javascript/components/ObjectBreadcrumbs.spec.js b/web/regression/javascript/components/ObjectBreadcrumbs.spec.js new file mode 100644 index 000000000..8a97e3121 --- /dev/null +++ b/web/regression/javascript/components/ObjectBreadcrumbs.spec.js @@ -0,0 +1,105 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2023, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import jasmineEnzyme from 'jasmine-enzyme'; +import React from 'react'; +import '../helper/enzyme.helper'; +import { withTheme } from '../fake_theme'; +import { createMount } from '@material-ui/core/test-utils'; +import ObjectBreadcrumbs from '../../../pgadmin/static/js/components/ObjectBreadcrumbs'; +import EventBus from '../../../pgadmin/static/js/helpers/EventBus'; + +const pgAdmin = { + Browser: { + Events: new EventBus(), + get_preferences_for_module: function() { + return { + breadcrumbs_enable: true, + breadcrumbs_show_comment: true, + }; + }, + preference_version: ()=>123, + onPreferencesChange: ()=>{/*This is intentional (SonarQube)*/}, + tree: { + getNodeDisplayPath: jasmine.createSpy('getNodeDisplayPath').and.returnValue(['server', 'object']), + } + }, +}; + +describe('ObjectBreadcrumbs', ()=>{ + let mount; + + /* Use createMount so that material ui components gets the required context */ + /* https://material-ui.com/guides/testing/#api */ + beforeAll(()=>{ + mount = createMount(); + }); + + afterAll(() => { + mount.cleanUp(); + }); + + beforeEach(()=>{ + jasmineEnzyme(); + }); + + it('not hovered', (done)=>{ + let ThemedObjectBreadcrumbs = withTheme(ObjectBreadcrumbs); + let ctrl = mount(); + setTimeout(()=>{ + ctrl.update(); + expect(ctrl.find('ForwardRef(AccountTreeIcon)').length).toBe(0); + done(); + }, 0); + }); + + it('hovered object with comment', (done)=>{ + let ThemedObjectBreadcrumbs = withTheme(ObjectBreadcrumbs); + let ctrl = mount(); + setTimeout(()=>{ + ctrl.update(); + pgAdmin.Browser.Events.trigger('pgadmin-browser:tree:hovered', { + _metadata: { + data: { + description: 'some description' + } + }, + }, { + _type: 'object', + }); + setTimeout(()=>{ + ctrl.update(); + expect(ctrl.find('ForwardRef(AccountTreeIcon)').length).toBe(1); + expect(ctrl.find('ForwardRef(CommentIcon)').length).toBe(1); + done(); + }, 500); + }, 500); + }); + + it('hovered object with no comment', (done)=>{ + let ThemedObjectBreadcrumbs = withTheme(ObjectBreadcrumbs); + let ctrl = mount(); + setTimeout(()=>{ + ctrl.update(); + pgAdmin.Browser.Events.trigger('pgadmin-browser:tree:hovered', { + _metadata: { + data: {} + }, + }, { + _type: 'object', + }); + setTimeout(()=>{ + ctrl.update(); + expect(ctrl.find('ForwardRef(AccountTreeIcon)').length).toBe(1); + expect(ctrl.find('ForwardRef(CommentIcon)').length).toBe(0); + done(); + }, 500); + }, 500); + }); +}); diff --git a/web/yarn.lock b/web/yarn.lock index 2221ec8ea..c9d933b13 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -8368,20 +8368,13 @@ __metadata: languageName: node linkType: hard -"jasmine-core@npm:3.10.1": +"jasmine-core@npm:3.10.1, jasmine-core@npm:^3.6.0": version: 3.10.1 resolution: "jasmine-core@npm:3.10.1" checksum: 77ee26aaf29576e982a2ebe6586218ff4d7cc4305ad18c400954bbdeb3c7987e9a4a8ac6d6548b65838852f325395fc901d69bf8c24bdccfbd67b263fbf5d4fd languageName: node linkType: hard -"jasmine-core@npm:^3.6.0": - version: 3.99.1 - resolution: "jasmine-core@npm:3.99.1" - checksum: 4e4a89739d99e471b86c7ccc4c5c244a77cc6d1e17b2b0d87d81266b8415697354d8873f7e764790a10661744f73a753a6e9bcd9b3e48c66a0c9b8a092b071b7 - languageName: node - linkType: hard - "jasmine-enzyme@npm:^7.1.2": version: 7.1.2 resolution: "jasmine-enzyme@npm:7.1.2"