diff --git a/web/pgadmin/dashboard/static/css/dashboard.css b/web/pgadmin/dashboard/static/css/dashboard.css index 735aebf..c188795 100644 --- a/web/pgadmin/dashboard/static/css/dashboard.css +++ b/web/pgadmin/dashboard/static/css/dashboard.css @@ -88,3 +88,83 @@ margin-top: 13px; display: block; } + +/* CSS to make subnode control look preety in backgrid - START */ +.dashboard-tab-container .subnode-dialog .form-control { + font-size: inherit; +} + +#server_activity .CodeMirror, +#database_activity .CodeMirror, +#server_activity .CodeMirror-scroll, +#database_activity .CodeMirror-scroll { + height: auto; + max-height:100px; +} + +.dashboard-tab-container .sub-node-form > ul.tab-content { + padding-left: 0px; + left: 0px; +} + +.dashboard-tab-container .sub-node-form > ul.pg-el-sm-12, +.dashboard-tab-container .sub-node-form > ul.pg-el-md-12, +.dashboard-tab-container .sub-node-form > ul.pg-el-lg-12, +.dashboard-tab-container .sub-node-form > ul.pg-el-xs-12 { + padding: 0px; +} + +.dashboard-tab-container .subnode-dialog { + background-color: white; + border: 0px solid #e8e8e8; +} + +.dashboard-tab-container .subnode-dialog .control-label { + font-weight: inherit; +} + +.dashboard-tab-container .sub-node-form { + padding: 0px 0px 0px 1px; + background-color: #f8f8f8; +} + +.dashboard-tab-container .subnode-body { + background-color: #f8f8f8; +} + +.dashboard-tab-container .sub-node-form > .nav-tabs { + background-color: #f8f8f8 !important; +} + +.dashboard-tab-container .subnode-dialog .nav > li > a { + font-weight: bold; + border-color: #f8f8f8; +} + +.dashboard-tab-container .subnode-dialog .nav-tabs > li.active > a, +.dashboard-tab-container .subnode-dialog .nav-tabs > li.active > a:hover { + border-top: 1px solid #cccccc; + border-left: 1px solid #cccccc; + border-right: 1px solid #cccccc; + margin-bottom: -1px; + z-index: 10; +} + +.dashboard-tab-container .backgrid .editor { + background-color: #f8f8f8 !important; + border-bottom-color: #f8f8f8; +} + +.dashboard-tab-container .backgrid.presentation td.editable:not(.edit-cell) { + padding-right: 25px +} + +.dashboard-tab-container .subnode-dialog .pgadmin-control-group { + padding: 5px; +} + +.dashboard-tab-container .subnode-dialog .tab-pane { + border: 1px solid #cccccc; +} + +/* CSS to make subnode control look preety in backgrid - END */ diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js index 86ebe38..1bda76e 100644 --- a/web/pgadmin/dashboard/static/js/dashboard.js +++ b/web/pgadmin/dashboard/static/js/dashboard.js @@ -88,6 +88,68 @@ function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr, } }); + // Subnode Cell, which will display subnode control + var SessionDetailsCell = Backgrid.Extension.ObjectCell.extend({ + enterEditMode: function () { + // Notify that we are about to enter in edit mode for current cell. + this.model.trigger("enteringEditMode", [this]); + + Backgrid.Cell.prototype.enterEditMode.apply(this, arguments); + /* Make sure - we listen to the click event */ + this.delegateEvents(); + var editable = Backgrid.callByNeed(this.column.editable(), this.column, this.model); + + if (editable) { + this.$el.html( + "" + ); + this.model.trigger( + "pg-sub-node:opened", this.model, this + ); + } + }, + render: function(){ + this.$el.empty(); + this.$el.html( + "" + ); + this.delegateEvents(); + if (this.grabFocus) + this.$el.focus(); + return this; + } + }); + + // Subnode Model + var ActiveQueryDetailsModel = Backbone.Model.extend({ + defaults: { + version: null /* Postgres version */ + }, + schema: [{ + id: 'backend_type', label: gettext('Backend type'), + type: 'text', editable: true, disabled: true, + group: gettext('Details'), + visible: function(m) { + return m.get('version') >= 100000; + } + },{ + id: 'query_start', label: gettext('Query started at'), + type: 'text', editable: false, disabled: true, + group: gettext('Details') + },{ + id: 'state_change', label: gettext('Last state changed at'), + type: 'text', editable: true, disabled: true, + group: gettext('Details') + },{ + id: 'query', label: gettext('SQL'), + type: 'text', editable: true, disabled: true, + control: Backform.SqlFieldControl, + group: gettext('Details') + }] + }); + pgAdmin.Dashboard = { init: function() { if (this.initialized) @@ -580,6 +642,23 @@ function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr, }]); } + var newActiveQueryDetailsModel = new ActiveQueryDetailsModel( + {'version': version} + ); + + var subNodeFieldsModel = Backform.generateViewSchema( + null, newActiveQueryDetailsModel, 'create', null, null, true + ); + + // Add cancel active query button + server_activity_columns.unshift({ + name: "pg-backform-expand", label: "", + cell: SessionDetailsCell, + cell_priority: -1, + postgres_version: version, + schema: subNodeFieldsModel + }); + // Add cancel active query button server_activity_columns.unshift({ name: "pg-backform-delete", label: "", @@ -737,6 +816,10 @@ function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr, bio_stats_refresh ); + // To align subnode controls properly + $(div_server_activity).addClass('pg-el-container'); + $(div_server_activity).attr('el', 'sm'); + // Render the tabs, but only get data for the activity tab for now pgAdmin.Dashboard.render_grid( div_server_activity, sid, did, @@ -893,6 +976,23 @@ function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr, }]); } + var newActiveQueryDetailsModel = new ActiveQueryDetailsModel( + {'version': version} + ); + + var subNodeFieldsModel = Backform.generateViewSchema( + null, newActiveQueryDetailsModel, 'create', null, null, true + ); + + // Add cancel active query button + database_activity_columns.unshift({ + name: "pg-backform-expand", label: "", + cell: SessionDetailsCell, + cell_priority: -1, + postgres_version: version, + schema: subNodeFieldsModel + }); + database_activity_columns.unshift({ name: "pg-backform-delete", label: "", cell: cancelQueryCell, @@ -1012,6 +1112,10 @@ function(url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr, bio_stats_refresh ); + // To align subnode controls properly + $(div_database_activity).addClass('pg-el-container'); + $(div_database_activity).attr('el', 'sm'); + // Render the tabs, but only get data for the activity tab for now pgAdmin.Dashboard.render_grid( div_database_activity, sid, did, url_for('dashboard.activity'), diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql b/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql index 912d4b1..9b067a8 100644 --- a/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql +++ b/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql @@ -7,9 +7,13 @@ SELECT to_char(backend_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS backend_start, state, wait_event_type || ': ' || wait_event AS wait_event, - pg_blocking_pids(pid) AS blocking_pids + pg_blocking_pids(pid) AS blocking_pids, + query, + to_char(state_change, 'YYYY-MM-DD HH24:MI:SS TZ') AS state_change, + to_char(query_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS query_start, + backend_type FROM pg_stat_activity {% if did %}WHERE datname = (SELECT datname FROM pg_database WHERE oid = {{ did }}){% endif %} -ORDER BY pid \ No newline at end of file +ORDER BY pid diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql index f79ae1b..b0f747a 100644 --- a/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql +++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql @@ -6,9 +6,12 @@ SELECT client_addr, to_char(backend_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS backend_start, state, - CASE WHEN waiting THEN '{{ _('yes') }}' ELSE '{{ _('no') }}' END AS waiting + CASE WHEN waiting THEN '{{ _('yes') }}' ELSE '{{ _('no') }}' END AS waiting, + query, + to_char(state_change, 'YYYY-MM-DD HH24:MI:SS TZ') AS state_change, + to_char(query_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS query_start FROM pg_stat_activity {% if did %}WHERE datname = (SELECT datname FROM pg_database WHERE oid = {{ did }}){% endif %} -ORDER BY pid \ No newline at end of file +ORDER BY pid diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js index 87ef146..c4860e0 100644 --- a/web/pgadmin/static/js/backgrid.pgadmin.js +++ b/web/pgadmin/static/js/backgrid.pgadmin.js @@ -217,12 +217,14 @@ postRender: function(model, column) { var editor = this, el = this.el, - columns_length = this.columns_length; + columns_length = this.columns_length, + // To render schema directly from Backgrid cell we use columns schema attribute + schema = this.schema.length ? this.schema : this.column.get('schema'); if (column != null && column.get("name") != this.column.get("name")) return false; - if (!_.isArray(this.schema)) throw new TypeError("schema must be an array"); + if (!_.isArray(schema)) throw new TypeError("schema must be an array"); // Create a Backbone model from our object if it does not exist var $dialog = this.createDialog(columns_length); @@ -235,7 +237,7 @@ var back_el = $dialog.find('form.form-dialog'); this.objectView = new Backform.Dialog({ - el: back_el, model: this.model, schema: this.schema, + el: back_el, model: this.model, schema: schema, tabPanelClassName: function() { return 'sub-node-form col-sm-12'; }