Retain column sizing in the query tool results grid when the same query is re-run multiple times in a row. Fixes #1971

This commit is contained in:
Surinder Kumar 2017-06-08 12:41:56 +01:00 committed by Dave Page
parent 678b891ff7
commit 2fddf750e6
3 changed files with 129 additions and 76 deletions

View File

@ -0,0 +1,58 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
// This file contains common utilities functions used in sqleditor modules
define(['jquery'],
function ($) {
var sqlEditorUtils = {
/* Reference link http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
* Modified as per requirement.
*/
epicRandomString: function(length) {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(
Math.floor(Math.random() * 0x10), 1
);
}
// bits 12-15 of the time_hi_and_version field to 0010
s[14] = "4";
// bits 6-7 of the clock_seq_hi_and_reserved to 01
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid.replace(/-/g, '').substr(0, length);
},
// Returns a unique hash for input string
getHash: function(input) {
var hash = 0, len = input.length;
for (var i = 0; i < len; i++) {
hash = ((hash << 5) - hash) + input.charCodeAt(i);
hash |= 0; // to 32bit integer
}
return hash;
},
calculateColumnWidth: function (text) {
// Calculate column header width based on column name or type
// Create a temporary element with given label, append to body
// calculate its width and remove the element.
$('body').append(
'<span id="pg_text" style="visibility: hidden;">'+ text + '</span>'
);
var width = $('#pg_text').width() + 30;
$('#pg_text').remove(); // remove element
return width;
}
};
return sqlEditorUtils;
});

View File

@ -3,7 +3,7 @@ define([
'pgadmin', 'backbone', 'backgrid', 'codemirror', 'pgadmin.misc.explain', 'pgadmin', 'backbone', 'backgrid', 'codemirror', 'pgadmin.misc.explain',
'sources/selection/grid_selector', 'sources/selection/clipboard', 'sources/selection/grid_selector', 'sources/selection/clipboard',
'sources/selection/copy_data', 'sources/selection/copy_data',
'sources/selection/set_staged_rows', 'sources/selection/set_staged_rows', 'sources/sqleditor_utils',
'slickgrid', 'bootstrap', 'pgadmin.browser', 'wcdocker', 'slickgrid', 'bootstrap', 'pgadmin.browser', 'wcdocker',
'codemirror/mode/sql/sql', 'codemirror/addon/selection/mark-selection', 'codemirror/mode/sql/sql', 'codemirror/addon/selection/mark-selection',
'codemirror/addon/selection/active-line', 'codemirror/addon/fold/foldcode', 'codemirror/addon/selection/active-line', 'codemirror/addon/fold/foldcode',
@ -26,7 +26,7 @@ define([
'slickgrid/slick.grid' 'slickgrid/slick.grid'
], function( ], function(
gettext, $, _, S, alertify, pgAdmin, Backbone, Backgrid, CodeMirror, gettext, $, _, S, alertify, pgAdmin, Backbone, Backgrid, CodeMirror,
pgExplain, GridSelector, clipboard, copyData, setStagedRows pgExplain, GridSelector, clipboard, copyData, setStagedRows, SqlEditorUtils
) { ) {
/* Return back, this has been called more than once */ /* Return back, this has been called more than once */
if (pgAdmin.SqlEditor) if (pgAdmin.SqlEditor)
@ -38,28 +38,6 @@ define([
pgBrowser = pgAdmin.Browser, pgBrowser = pgAdmin.Browser,
Slick = window.Slick; Slick = window.Slick;
/* Reference link
* http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
* Modified as per requirement.
*/
function epicRandomString(b) {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(
Math.floor(Math.random() * 0x10), 1
);
}
// bits 12-15 of the time_hi_and_version field to 0010
s[14] = "4";
// bits 6-7 of the clock_seq_hi_and_reserved to 01
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid.replace(/-/g, '').substr(0, b);
};
// Define key codes for shortcut keys // Define key codes for shortcut keys
var F5_KEY = 116, var F5_KEY = 116,
F7_KEY = 118, F7_KEY = 118,
@ -72,6 +50,7 @@ define([
initialize: function(opts) { initialize: function(opts) {
this.$el = opts.el; this.$el = opts.el;
this.handler = opts.handler; this.handler = opts.handler;
this.handler['col_size'] = {};
}, },
// Bind all the events // Bind all the events
@ -409,11 +388,16 @@ define([
/* To prompt user for unsaved changes */ /* To prompt user for unsaved changes */
user_confirmation: function(panel, msg) { user_confirmation: function(panel, msg) {
// If there is anything to save then prompt user // If there is anything to save then prompt user
var that = this;
alertify.confirm(gettext("Unsaved changes"), msg, alertify.confirm(gettext("Unsaved changes"), msg,
function() { function() {
// Do nothing as user do not want to save, just continue // Do nothing as user do not want to save, just continue
window.onbeforeunload = null; window.onbeforeunload = null;
panel.off(wcDocker.EVENT.CLOSING); panel.off(wcDocker.EVENT.CLOSING);
// remove col_size object on panel close
if (!_.isUndefined(that.handler.col_size)) {
delete that.handler.col_size;
}
window.top.pgAdmin.Browser.docker.removePanel(panel); window.top.pgAdmin.Browser.docker.removePanel(panel);
}, },
function() { function() {
@ -425,53 +409,6 @@ define([
return false; return false;
}, },
get_column_width: function (column_type, grid_width) {
switch(column_type) {
case "bigint":
case "bigint[]":
case "bigserial":
case "bit":
case "bit[]":
case "bit varying":
case "bit varying[]":
case "\"char\"":
case "decimal":
case "decimal[]":
case "double precision":
case "double precision[]":
case "int4range":
case "int4range[]":
case "int8range":
case "int8range[]":
case "integer":
case "integer[]":
case "money":
case "money[]":
case "numeric":
case "numeric[]":
case "numrange":
case "numrange[]":
case "oid":
case "oid[]":
case "real":
case "real[]":
case "serial":
case "smallint":
case "smallint[]":
case "smallserial":
return 80;
case "boolean":
case "boolean[]":
return 60;
}
/* In case of other data types we will calculate
* 20% of the total container width and return it.
*/
return Math.round((grid_width * 20)/ 100)
},
/* Regarding SlickGrid usage in render_grid function. /* Regarding SlickGrid usage in render_grid function.
SlickGrid Plugins: SlickGrid Plugins:
@ -584,8 +521,22 @@ define([
} }
var grid_columns = []; var grid_columns = [];
var column_size = self.handler['col_size'],
query = self.handler.query,
// Extract table name from query
table_list = query.match(/select.*from\s+(\w+)/i);
var grid_width = $($('#editor-panel').find('.wcFrame')[1]).width() if (!table_list) {
table_name = SqlEditorUtils.getHash(query);
}
else {
table_name = table_list[1];
}
self.handler['table_name'] = table_name;
column_size[table_name] = column_size[table_name] || {};
var grid_width = $($('#editor-panel').find('.wcFrame')[1]).width();
_.each(columns, function(c) { _.each(columns, function(c) {
var options = { var options = {
id: c.name, id: c.name,
@ -596,8 +547,18 @@ define([
has_default_val: c.has_default_val has_default_val: c.has_default_val
}; };
// Get the columns width based on data type // Get the columns width based on longer string among data type or
options['width'] = self.get_column_width(c.type, grid_width); // column name.
var label = c.label.split('<br>');
label = label[0].length > label[1].length ? label[0] : label[1];
if (_.isUndefined(column_size[table_name][c.name])) {
options['width'] = SqlEditorUtils.calculateColumnWidth(label)
column_size[table_name][c.name] = SqlEditorUtils.calculateColumnWidth(label);
}
else {
options['width'] = column_size[table_name][c.name];
}
// If grid is editable then add editor else make it readonly // If grid is editable then add editor else make it readonly
if(c.cell == 'Json') { if(c.cell == 'Json') {
@ -641,7 +602,7 @@ define([
// Add our own custom primary key to keep track of changes // Add our own custom primary key to keep track of changes
_.each(collection, function(row){ _.each(collection, function(row){
row['__temp_PK'] = epicRandomString(15); row['__temp_PK'] = SqlEditorUtils.epicRandomString(15);
}); });
// Add-on function which allow us to identify the faulty row after insert/update // Add-on function which allow us to identify the faulty row after insert/update
@ -696,6 +657,13 @@ define([
setStagedRows.bind(editor_data)); setStagedRows.bind(editor_data));
} }
grid.onColumnsResized.subscribe(function (e, args) {
var columns = this.getColumns();
_.each(columns, function(col, key) {
var column_size = self.handler['col_size'];
column_size[self.handler['table_name']][col['id']] = col['width'];
});
});
// Listener function which will be called before user updates existing cell // Listener function which will be called before user updates existing cell
// This will be used to collect primary key for that row // This will be used to collect primary key for that row
@ -844,7 +812,7 @@ define([
// Listener function which will be called when user adds new rows // Listener function which will be called when user adds new rows
grid.onAddNewRow.subscribe(function (e, args) { grid.onAddNewRow.subscribe(function (e, args) {
// self.handler.data_store.added will holds all the newly added rows/data // self.handler.data_store.added will holds all the newly added rows/data
var _key = epicRandomString(10), var _key = SqlEditorUtils.epicRandomString(10),
column = args.column, column = args.column,
item = args.item, item = args.item,
data_length = this.grid.getDataLength(), data_length = this.grid.getDataLength(),

View File

@ -0,0 +1,27 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2017, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
define(["sources/sqleditor_utils"],
function (SqlEditorUtils) {
describe("SqlEditorUtils", function () {
describe("Generate a random string of size 10", function () {
it("returns string of length 10", function () {
expect(SqlEditorUtils.epicRandomString(10).length).toEqual(10);
});
});
describe("Generate a unique hash for given string", function () {
it("returns unique hash", function () {
expect(SqlEditorUtils.getHash('select * from test')).toEqual(403379630);
});
});
});
});