diff --git a/web/package.json b/web/package.json index 693ff843e..ea65bf9d4 100644 --- a/web/package.json +++ b/web/package.json @@ -86,8 +86,6 @@ "@material-ui/icons": "^4.11.2", "@material-ui/lab": "4.0.0-alpha.58", "@material-ui/pickers": "^3.2.10", - "@mui/icons-material": "^5.4.2", - "@mui/material": "^5.4.3", "@projectstorm/react-diagrams": "^6.6.1", "@simonwep/pickr": "^1.5.1", "@szhsin/react-menu": "^2.2.0", diff --git a/web/pgadmin/browser/collection.py b/web/pgadmin/browser/collection.py index 6040cf651..aff57fcba 100644 --- a/web/pgadmin/browser/collection.py +++ b/web/pgadmin/browser/collection.py @@ -236,6 +236,16 @@ class CollectionNodeModule(PgAdminModule, PGChildModule): else: return False + @property + def show_user_defined_database_template(self): + """ + Show/Hide the user defined template in the database server. + """ + if self.pref_show_user_defined_templates: + return self.pref_show_user_defined_templates.get() + else: + return False + def register_preferences(self): """ register_preferences @@ -251,6 +261,8 @@ class CollectionNodeModule(PgAdminModule, PGChildModule): self.pref_show_system_objects = self.browser_preference.preference( 'show_system_objects' ) + self.pref_show_user_defined_templates = \ + self.browser_preference.preference('show_user_defined_templates') self.pref_show_node = self.browser_preference.register( 'node', 'show_node_' + self.node_type, self.collection_label, 'node', self.SHOW_ON_BROWSER, diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py index 5d3482be4..cb419f9c3 100644 --- a/web/pgadmin/browser/register_browser_preferences.py +++ b/web/pgadmin/browser/register_browser_preferences.py @@ -27,6 +27,13 @@ def register_browser_preferences(self): gettext("Show system objects?"), 'boolean', False, category_label=PREF_LABEL_DISPLAY ) + + self.show_user_defined_templates = self.preference.register( + 'display', 'show_user_defined_templates', + gettext("Show user defined templates?"), 'boolean', False, + category_label=PREF_LABEL_DISPLAY + ) + if config.SERVER_MODE: self.hide_shared_server = self.preference.register( 'display', 'hide_shared_server', diff --git a/web/pgadmin/browser/server_groups/servers/databases/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/__init__.py index 292d88d17..1552ff25d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/__init__.py @@ -230,21 +230,29 @@ class DatabaseView(PGChildNodeView): conn=self.conn, last_system_oid=last_system_oid, db_restrictions=db_disp_res, - show_system_objects=self.blueprint.show_system_objects, ) status, res = self.conn.execute_dict(SQL, params) if not status: return internal_server_error(errormsg=res) + result_set = [] for row in res['rows']: + row['is_sys_obj'] = ( + row['did'] <= self._DATABASE_LAST_SYSTEM_OID or + self.datistemplate) + if self.skip_db(row): + continue + if self.manager.db == row['name']: row['canDrop'] = False else: row['canDrop'] = True + result_set.append(row) + return ajax_response( - response=res['rows'], + response=result_set, status=200 ) @@ -256,6 +264,32 @@ class DatabaseView(PGChildNodeView): return last_system_oid + def get_icon(self, res, connected): + if not connected and not res['is_template']: + icon = "icon-database-not-connected" + elif not connected and res['is_template']: + icon = 'icon-database-template-not-connected' + elif connected and res['is_template']: + icon = 'icon-database-template-connected' + else: + icon = "pg-icon-database" + + return icon + + def skip_db(self, row): + + if not self.blueprint.show_system_objects \ + and row['is_sys_obj'] \ + and row['name'] not in ('postgres', 'edb'): + return True + + if not self.blueprint.show_user_defined_database_template \ + and row['is_template'] and \ + not row['is_sys_obj'] and \ + row['name'] not in ('postgres', 'edb'): + return True + return False + def get_nodes(self, gid, sid, is_schema_diff=False): res = [] last_system_oid = self.retrieve_last_system_oid() @@ -278,7 +312,6 @@ class DatabaseView(PGChildNodeView): "/".join([self.template_path, self._NODES_SQL]), last_system_oid=last_system_oid, db_restrictions=db_disp_res, - show_system_objects=self.blueprint.show_system_objects, ) status, rset = self.conn.execute_dict(SQL, params) @@ -287,6 +320,12 @@ class DatabaseView(PGChildNodeView): for row in rset['rows']: dbname = row['name'] + row['is_sys_obj'] = ( + row['did'] <= self._DATABASE_LAST_SYSTEM_OID or + self.datistemplate) + + if self.skip_db(row): + continue if self.manager.db == dbname: connected = True can_drop = can_dis_conn = False @@ -295,19 +334,21 @@ class DatabaseView(PGChildNodeView): connected = conn.connected() can_drop = can_dis_conn = True + icon = self.get_icon(row, connected) + res.append( self.blueprint.generate_browser_node( row['did'], sid, row['name'], - icon="icon-database-not-connected" if not connected - else "pg-icon-database", + icon=icon, connected=connected, tablespace=row['spcname'], allowConn=row['datallowconn'], canCreate=row['cancreate'], canDisconn=can_dis_conn, canDrop=can_drop, + isTemplate=row['is_template'], inode=True if row['datallowconn'] else False ) ) @@ -429,8 +470,7 @@ class DatabaseView(PGChildNodeView): result = res['rows'][0] result['is_sys_obj'] = ( - result['oid'] <= self._DATABASE_LAST_SYSTEM_OID or - self.datistemplate) + result['oid'] <= self._DATABASE_LAST_SYSTEM_OID) # Fetching variable for database SQL = render_template( "/".join([self.template_path, 'get_variables.sql']), @@ -650,7 +690,8 @@ class DatabaseView(PGChildNodeView): allowConn=True, canCreate=response['cancreate'], canDisconn=True, - canDrop=True + canDrop=True, + isTemplate=response['is_template'] ) ) @@ -829,14 +870,16 @@ class DatabaseView(PGChildNodeView): can_drop = can_dis_conn = is_can_drop + icon = self.get_icon(res, + self.conn.connected() + if self._db['datallowconn'] else False) + return jsonify( node=self.blueprint.generate_browser_node( did, sid, res['name'], - icon="pg-icon-{0}".format(self.node_type) if - self._db['datallowconn'] and self.conn.connected() else - "icon-database-not-connected", + icon=icon, connected=self.conn.connected() if self._db['datallowconn'] else False, tablespace=res['spcname'], @@ -844,7 +887,8 @@ class DatabaseView(PGChildNodeView): canCreate=res['cancreate'], canDisconn=can_dis_conn, canDrop=can_drop, - inode=True if res['datallowconn'] else False + inode=True if res['datallowconn'] else False, + isTemplate=res['is_template'], ) ) diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database.svg b/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database.svg new file mode 100644 index 000000000..998c073a4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database_bad.svg b/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database_bad.svg new file mode 100644 index 000000000..5bc006a2a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/static/img/template_database_bad.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js index 4f3e63329..df7656296 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js +++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js @@ -187,7 +187,8 @@ define('pgadmin.node.database', [ d.is_connecting = false; t.unload(i); t.setInode(i); - t.addIcon(i, {icon: 'icon-database-not-connected'}); + var dbIcon = d.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected'; + t.addIcon(i, {icon: dbIcon}); pgBrowser.Events.trigger( 'pgadmin:database:connect:cancelled', i, d, self ); @@ -237,7 +238,8 @@ define('pgadmin.node.database', [ Notify.success(_.unescape(res.info)); t.removeIcon(i); data.connected = false; - data.icon = 'icon-database-not-connected'; + data.icon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected'; + t.addIcon(i, {icon: data.icon}); t.unload(i); pgBrowser.Events.trigger('pgadmin:browser:tree:update-tree-state', i); @@ -294,7 +296,6 @@ define('pgadmin.node.database', [ if(!data || data._type != 'database') { return false; } - pgBrowser.tree.addIcon(item, {icon: data.icon}); if (!data.connected && data.allowConn && !data.is_connecting) { data.is_connecting = true; @@ -386,14 +387,16 @@ define('pgadmin.node.database', [ }, function(fun_error) { tree.setInode(_item); - tree.addIcon(_item, {icon: 'icon-database-not-connected'}); + var dbIcon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected'; + tree.addIcon(_item, {icon: dbIcon}); Notify.pgNotifier(fun_error, xhr, gettext('Connect to database.')); } ); } else { if (!_status) { tree.setInode(_item); - tree.addIcon(_item, {icon: 'icon-database-not-connected'}); + var dbIcon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected'; + tree.addIcon(_item, {icon: dbIcon}); } Notify.pgNotifier('error', xhr, error, function(msg) { @@ -422,7 +425,8 @@ define('pgadmin.node.database', [ if (typeof res.data.icon == 'string') { _tree.removeIcon(_item); _data.icon = res.data.icon; - _tree.addIcon(_item, {icon: _data.icon}); + var dbIcon = _data.isTemplate ? 'icon-database-template-connected':_data.icon; + _tree.addIcon(_item, {icon: dbIcon}); } if(res.data.already_connected) { res.info = gettext('Database already connected.'); @@ -457,7 +461,8 @@ define('pgadmin.node.database', [ _tree.unload(_item); _tree.setInode(_item); _tree.removeIcon(_item); - _tree.addIcon(_item, {icon: 'icon-database-not-connected'}); + var dbIcon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected'; + _tree.addIcon(_item, {icon: dbIcon}); obj.trigger('connect:cancelled', obj, _item, _data); pgBrowser.Events.trigger( 'pgadmin:database:connect:cancelled', _item, _data, obj diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js index 871b9db92..11050b02d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js @@ -52,7 +52,7 @@ export default class DatabaseSchema extends BaseUISchema { super({ name: undefined, owner: undefined, - is_sys_obj: undefined, + is_sys_obj: false, comment: undefined, encoding: 'UTF8', template: undefined, @@ -141,8 +141,8 @@ export default class DatabaseSchema extends BaseUISchema { min: -1, },{ id: 'is_template', label: gettext('Template?'), - editable: false, type: 'switch', group: gettext('Definition'), - readonly: true, mode: ['properties', 'edit'], + type: 'switch', group: gettext('Definition'), + mode: ['properties', 'edit'], readonly: function(state) {return (state.is_sys_obj); } },{ id: 'datallowconn', label: gettext('Allow connections?'), editable: false, type: 'switch', group: gettext('Definition'), diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css index 0c9ae10dd..bded90788 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css @@ -17,3 +17,24 @@ height: 1.3em; } + +.icon-database-template-connected { + background-image: url('{{ url_for('NODE-database.static', filename='img/template_database.svg') }}') !important; + border-radius: 10px; + background-size: 20px !important; + background-repeat: no-repeat; + vertical-align: middle; + align-content: center; + height: 1.3em; +} + +.icon-database-template-not-connected { + background-image: url('{{ url_for('NODE-database.static', filename='img/template_database_bad.svg') }}') !important; + border-radius: 10px; + background-size: 20px !important; + background-repeat: no-repeat; + vertical-align: middle; + align-content: center; + height: 1.3em; + +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql index 903cd096e..a8281380d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql @@ -29,7 +29,11 @@ FROM pg_catalog.pg_database db LEFT OUTER JOIN pg_catalog.pg_shdescription descr ON ( db.oid=descr.objoid AND descr.classoid='pg_database'::regclass ) -WHERE {% if did %} +WHERE +{% if show_user_defined_templates is defined %} + db.datistemplate = {{show_user_defined_templates}} AND +{% endif %} +{% if did %} db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %} db.datname = {{ name|qtLiteral }}::text{% else %} db.oid > {{ last_system_oid|qtLiteral }}::OID OR db.datname IN ('postgres', 'edb') @@ -40,6 +44,8 @@ AND db.datname in ({{db_restrictions}}) {% endif %} -AND db.datistemplate in (false, {{show_system_objects}}) +{% if show_user_defined_templates is defined %} + AND db.datistemplate = {{show_user_defined_templates}} +{% endif %} ORDER BY datname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql index 1a6b38dba..362a8fbf4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql @@ -36,7 +36,11 @@ FROM pg_catalog.pg_database db LEFT OUTER JOIN pg_catalog.pg_shdescription descr ON ( db.oid=descr.objoid AND descr.classoid='pg_database'::regclass ) -WHERE {% if did %} +WHERE +{% if show_user_defined_templates is defined %} + db.datistemplate = {{show_user_defined_templates}} AND +{% endif %} +{% if did %} db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %} db.datname = {{ name|qtLiteral }}::text{% else %} db.oid > {{ last_system_oid|qtLiteral }}::OID OR db.datname IN ('postgres', 'edb') @@ -47,6 +51,6 @@ AND db.datname in ({{db_restrictions}}) {% endif %} -AND db.datistemplate in (false, {{show_system_objects}}) + ORDER BY datname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql index 40ec137ba..65766d546 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql @@ -155,3 +155,8 @@ {% endif %} {% endif %} + +{# Change the connection limit #} +{% if data.is_template is defined %} +ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH IS_TEMPLATE = {{ data.is_template }}; +{% endif %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/alter_online.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/alter_online.sql index 9296ee6cb..60cf869b5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/alter_online.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/alter_online.sql @@ -136,3 +136,8 @@ {% endif %} {% endif %} {% endif %} + +{# Change the connection limit #} +{% data.is_template is defined %} +ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH IS_TEMPLATE = {{ data.is_template }}; +{% endif %} 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 328c073ca..350aeaf25 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,15 @@ 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 FROM pg_catalog.pg_database db LEFT OUTER JOIN pg_catalog.pg_tablespace ta ON db.dattablespace = ta.oid -WHERE {% if did %} +WHERE +{% if show_user_defined_templates is defined %} +db.datistemplate in (false, {{show_user_defined_templates}}) AND +{% endif %} +{% if did %} db.oid = {{ did|qtLiteral }}::OID{% else %} db.oid > {{ last_system_oid }}::OID OR db.datname IN ('postgres', 'edb') {% endif %} @@ -16,8 +21,6 @@ db.datname in ({{db_restrictions}}) {% if show_system_objects %} AND db.datistemplate in (false, {{show_system_objects}}) -{% else %} -AND db.datistemplate in (false) {% endif %} ORDER BY datname; diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/properties.sql index 5eced7dd8..6c4985bb6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/default/properties.sql @@ -20,7 +20,11 @@ FROM pg_catalog.pg_database db LEFT OUTER JOIN pg_catalog.pg_shdescription descr ON ( db.oid=descr.objoid AND descr.classoid='pg_database'::regclass ) -WHERE {% if did %} +WHERE +{% if show_user_defined_templates is defined %} + db.datistemplate = {{show_user_defined_templates}} AND +{% endif %} +{% if did %} db.oid = {{ did|qtLiteral }}::OID{% else %}{% if name %} db.datname = {{ name|qtLiteral }}::text{% else %} db.oid > {{ last_system_oid|qtLiteral }}::OID OR db.datname IN ('postgres', 'edb') @@ -31,6 +35,5 @@ AND db.datname in ({{db_restrictions}}) {% endif %} -AND db.datistemplate in (false, {{show_system_objects}}) ORDER BY datname; diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx index cb43f0305..0367015e8 100644 --- a/web/pgadmin/dashboard/static/js/Dashboard.jsx +++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx @@ -18,14 +18,14 @@ import Graphs from './Graphs'; import Notify from '../../../static/js/helpers/Notifier'; import { Box, Tab, Tabs } from '@material-ui/core'; import { PgIconButton } from '../../../static/js/components/Buttons'; -import CancelIcon from '@mui/icons-material/Cancel'; -import SquareIcon from '@mui/icons-material/Square'; -import ArrowRightOutlinedIcon from '@mui/icons-material/ArrowRightOutlined'; -import ArrowDropDownOutlinedIcon from '@mui/icons-material/ArrowDropDownOutlined'; +import CancelIcon from '@material-ui/icons/Cancel'; +import StopSharpIcon from '@material-ui/icons/StopSharp'; +import ArrowRightOutlinedIcon from '@material-ui/icons/ArrowRightOutlined'; +import ArrowDropDownOutlinedIcon from '@material-ui/icons/ArrowDropDownOutlined'; import WelcomeDashboard from './WelcomeDashboard'; import ActiveQuery from './ActiveQuery.ui'; import _ from 'lodash'; -import CachedIcon from '@mui/icons-material/Cached'; +import CachedOutlinedIcon from '@material-ui/icons/CachedOutlined'; import EmptyPanelMessage from '../../../static/js/components/EmptyPanelMessage'; import TabPanel from '../../../static/js/components/TabPanel'; @@ -287,7 +287,7 @@ export default function Dashboard({ } + icon={} onClick={() => { if (!canTakeAction(row, 'cancel')) return; @@ -774,7 +774,7 @@ export default function Dashboard({ size="xs" noBorder className={classes.refreshButton} - icon={} + icon={} onClick={(e) => { e.preventDefault(); setRefresh(!refresh);