Fixed following issues:

- Process watcher made fixed width with header changes, time details rounded to 2 decimals
 - Query history will show "No query history" if no query fired. Query editor default size increased.
 - Fixed a bug where New folder create button not working when in List mode and No files/folder present.
 - Other minor improvements.
This commit is contained in:
Aditya Toshniwal
2019-01-16 11:55:08 +05:30
committed by Akshay Joshi
parent 2a359d9d77
commit 7ac4e2a9d9
31 changed files with 168 additions and 100 deletions

View File

@@ -108,6 +108,7 @@ define('pgadmin.node.function', [
collection_type: 'coll-function',
hasSQL: true,
hasDepends: true,
width: pgBrowser.stdW.md + 'px',
hasStatistics: (treeInformation) => {
return treeInformation.server.server_type !== 'gpdb';
},

View File

@@ -348,7 +348,7 @@ define('pgadmin.node.type', [
id: 'typtype', label: gettext('Type'),
mode: ['create','edit'], disabled: 'inSchemaWithModelCheck',
group: gettext('Definition'),
select2: { width: '50%', allowClear: false },
select2: { allowClear: false },
options: function() {
return [
{label: 'Composite', value: 'c'},
@@ -553,11 +553,13 @@ define('pgadmin.node.type', [
},{
type: 'nested', control: 'tab', group: gettext('Definition'),
label: gettext('External Type'), deps: ['typtype'],
mode: ['create', 'edit'],
mode: ['create', 'edit'], tabPanelExtraClasses:'inline-tab-panel-padded',
visible: function(m) {
return m.get('typtype') === 'b';
},
schema:[{
id: 'spacer_ctrl', group: gettext('Required'), mode: ['edit', 'create'], type: 'spacer',
},{
id: 'typinput', label: gettext('Input function'),
cell: 'string',type: 'text',
mode: ['properties', 'create', 'edit'], group: gettext('Required'),
@@ -574,6 +576,8 @@ define('pgadmin.node.type', [
,control: 'node-ajax-options', url: 'get_external_functions',
transform: 'external_func_combo',
select2: { allowClear: true, placeholder: '', width: '100%' },
},{
id: 'spacer_ctrl_optional_1', group: gettext('Optional-1'), mode: ['edit', 'create'], type: 'spacer',
},{
id: 'typreceive', label: gettext('Receive function'),
cell: 'string', type: 'text', group: gettext('Optional-1'),
@@ -675,6 +679,8 @@ define('pgadmin.node.type', [
type: 'switch', mode: ['properties', 'create','edit'],
disabled: 'inSchemaWithModelCheck',
group: gettext('Optional-1'),
},{
id: 'spacer_ctrl_optional_2', group: gettext('Optional-2'), mode: ['edit', 'create'], type: 'spacer',
},{
id: 'element', label: gettext('Element type'), cell: 'string',
control: 'node-ajax-options', group: gettext('Optional-2'),

View File

@@ -1,7 +1,4 @@
/** CSS for Wizard **/
.pgadmin_grant_wizard_body .ajs-content {
padding: 0px !important;
}
.wizard-header h3 {
font-size: 14px;

View File

@@ -96,7 +96,7 @@ window.onload = function(e){
<div class="row"><div class="col-12 pg-sp-text">{{ _('Loading {0} v{1}...').format(config.APP_NAME, config.APP_VERSION) }}</div></div>
</div>
</div>
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary pg-navbar">
<nav class="navbar fixed-top navbar-expand-lg navbar-dark pg-navbar">
<a class="navbar-brand pgadmin_header_logo" onClick="return false;" href="{{ '#' }}"
title="{{ config.APP_NAME }} {{ _('logo') }}">
<i class="app-icon {{ config.APP_ICON }}"></i>

View File

@@ -606,11 +606,13 @@ class BatchProcess(object):
for arg in args_reader:
args = args + arg
details = desc.details(p.command, args)
type_desc = desc.type_desc
desc = desc.message
res.append({
'id': p.pid,
'desc': desc,
'type_desc': type_desc,
'details': details,
'stime': stime,
'etime': p.end_time,
@@ -627,13 +629,7 @@ class BatchProcess(object):
@staticmethod
def total_seconds(dt):
# Keep backward compatibility with Python 2.6 which doesn't have
# this method
if hasattr(dt, 'total_seconds'):
return dt.total_seconds()
else:
return (dt.microseconds + (dt.seconds + dt.days * 24 * 3600) *
10**6) / 10**6
return round(dt.total_seconds(), 2)
@staticmethod
def acknowledge(_pid):

View File

@@ -41,7 +41,7 @@ define('misc.bgprocess', [
<div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div>
</div>`),
failed_status_tpl: _.template(`
<div class="d-flex px-2 py-1 bg-danger-light border border-danger rounded">
<div class="d-flex px-2 py-1 bg-danger-lighter border border-danger rounded">
<div class="pr-2">
<i class="fa fa-close fa-lg text-danger pg-bg-status-icon" aria-hidden="true"></i>
</div>
@@ -63,6 +63,7 @@ define('misc.bgprocess', [
completed: false,
id: info['id'],
type_desc: null,
desc: null,
detailed_desc: null,
stime: null,
@@ -145,6 +146,9 @@ define('misc.bgprocess', [
if ('execution_time' in data)
self.execution_time = parseFloat(data.execution_time);
if ('type_desc' in data)
self.type_desc = data.type_desc;
if ('desc' in data)
self.desc = data.desc;
@@ -288,12 +292,13 @@ define('misc.bgprocess', [
let content = $(`
<div class="card">
<div class="card-header bg-primary d-flex">
<div>${_.unescape(self.desc)}</div>
<div>${_.escape(self.type_desc)}</div>
<div class="ml-auto">
<button class="btn btn-sm-sq btn-primary pg-bg-close"><i class="fa fa-lg fa-close"></i></button>
</div>
</div>
<div class="card-body px-2">
<div class="py-1">${_.unescape(self.desc)}</div>
<div class="py-1">${self.stime.toString()}</div>
<div class="d-flex py-1">
<div class="my-auto mr-2">
@@ -384,7 +389,7 @@ define('misc.bgprocess', [
panel = this.panel =
pgBrowser.BackgroundProcessObsorver.create_panel();
panel.title('Process Watcher - ' + _.escape(self.desc));
panel.title('Process Watcher - ' + _.escape(self.type_desc));
panel.focus();
}

View File

@@ -6,6 +6,8 @@ $bgproc-container-pad: 2px;
padding: 0px !important;
text-align: left;
color: $color-fg-theme;
min-width: 500px;
max-width: 500px;
.card {
border:none;
& .card-header {

View File

@@ -670,12 +670,15 @@ define([
if ($('.fileinfo').data('view') == 'grid') {
result += '<ul id="contents" class="grid"></ul>';
} else {
result += '<table id="contents" class="table table-bordered table-noouter-border table-empty-rows ablesorter">';
/* file_listing_table class makes height 100%, because of which No folder message is not displayed
* file_listing_table_no_data will be removed when new folder is created
*/
result += '<table id="contents" class="table table-bordered table-noouter-border table-bottom-border table-hover tablesorter file_listing_table file_listing_table_no_data">';
result += '<thead><tr><th><span>' + lg.name + '</span></th>' +
'<th><span>' + lg.size + '</span></th>' +
'<th><span>' + lg.modified + '</span></th>' +
'</tr></thead>';
result += '</tbody>';
'</tr></thead>' +
'<tbody></tbody>';
result += '</table>';
}
result += '<div class="no_folder_found">' + lg.could_not_retrieve_folder + '</div>';
@@ -1576,6 +1579,7 @@ define([
$('.file_manager button.create').attr('disabled', 'disabled');
$('.no_folder_found').addClass('d-none');
if ($('.fileinfo').data('view') == 'grid') {
// template for creating new folder
@@ -1630,7 +1634,10 @@ define([
);
$file_element_list = $(folder_div);
$('.fileinfo #contents.file_listing_table tbody').prepend($file_element_list);
let tableEl = $('.fileinfo #contents.file_listing_table');
tableEl.removeClass('file_listing_table_no_data');
tableEl.find('tbody').prepend($file_element_list);
$file_element_list.find('td span.less_text').toggle();
$file_element_list.find('td input').toggle().val(lg.new_folder).select();

View File

@@ -6,6 +6,10 @@
.file_listing {
min-width: 100%;
.file_listing_table_no_data {
height: unset !important;
}
.file_listing_table {
height: 100%;
display: block;

View File

@@ -329,6 +329,17 @@ define('pgadmin.preferences', [
if (!d)
return true;
/* Bind events to enable clicking anywhere and not only text, button */
item.on('dblclick', function(e) {
e.preventDefault();
e.stopPropagation();
api.toggle(item);
});
item.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
api.select(item);
});
// We will add the preferences in to the preferences data
// collection.
if (d.preferences && _.isArray(d.preferences)) {

View File

@@ -2112,11 +2112,16 @@ define([
tagName: 'div',
className: 'inline-tab-panel',
tabPanelClassName: 'inline-tab-panel',
tabPanelExtraClasses: '',
initialize: function(opts) {
Backform.FieldsetControl.prototype.initialize.apply(
this, arguments
);
this.tabIndex = (opts.tabIndex || parseInt(Math.random() * 1000)) + 1;
if(opts.field.get('tabPanelExtraClasses')) {
this.tabPanelExtraClasses = opts.field.get('tabPanelExtraClasses');
}
this.tabPanelClassName = this.tabPanelClassName + ' ' + this.tabPanelExtraClasses;
},
// Render using Backform.Dialog (tabular UI) (only if this control is
// visible).

View File

@@ -13,6 +13,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import SplitPane from 'react-split-pane';
import _ from 'underscore';
import gettext from 'sources/gettext';
import QueryHistoryDetail from './query_history_detail';
import QueryHistoryEntries from './query_history_entries';
@@ -90,17 +91,23 @@ export default class QueryHistory extends React.Component {
}
render() {
return (
<SplitPane defaultSize='50%' split='vertical' pane1Style={queryEntryListDivStyle}
pane2Style={queryDetailDivStyle}>
<QueryHistoryEntries historyEntries={this.state.history}
selectedEntry={this.state.selectedEntry}
onSelectEntry={this.selectHistoryEntry}
/>
<QueryHistoryDetail historyEntry={this.state.currentHistoryDetail}
sqlEditorPref={this.props.sqlEditorPref}
/>
</SplitPane>);
if(this.state.history.length == 0) {
return(
<div className="alert alert-info pg-panel-message">{gettext('No history found')}</div>
);
} else {
return (
<SplitPane defaultSize='50%' split='vertical' pane1Style={queryEntryListDivStyle}
pane2Style={queryDetailDivStyle}>
<QueryHistoryEntries historyEntries={this.state.history}
selectedEntry={this.state.selectedEntry}
onSelectEntry={this.selectHistoryEntry}
/>
<QueryHistoryDetail historyEntry={this.state.currentHistoryDetail}
sqlEditorPref={this.props.sqlEditorPref}
/>
</SplitPane>);
}
}
}

View File

@@ -1,22 +1,18 @@
.aciTree .aciTreeLi {
display: grid !important;
cursor: pointer;
}
.aciTree .aciTreeText {
font-family: $font-family-primary;
font-size: 0.815rem;
}
.aciTree.aciTreeFocus .aciTreeFocus > .aciTreeLine {
background-color: $color-primary-light;
border-right: $active-border;
background-color: $color-primary-light !important;
}
.aciTree .aciTreeSelected > .aciTreeLine {
background-color: $color-primary-light;
border-color: $color-primary-light;
border-right: $active-border;
border-left: none !important;
border-top: none !important;
border-bottom: none !important;
-webkit-border-radius: none !important;
background-color: $color-primary-light !important;
-webkit-border-radius: none !important;
-moz-border-radius: none !important;
border-radius: none !important;
}

View File

@@ -22,7 +22,7 @@
}
.alert.alert-info {
padding: 15px;
padding: 0.5rem;
}
.success-icon {
@@ -48,7 +48,7 @@
.alert-info {
border-color: $color-primary;
background-color: $color-primary-light;
color : $color-primary;
color : $color-fg-theme;
background-image: none;
}

View File

@@ -28,14 +28,6 @@
& .ajs-content {
top: $title-height;
}
&.pgadmin_grant_wizard_body {
border-top-left-radius: $panel-border-radius;
border-top-right-radius: $panel-border-radius;
& .ajs-content {
top: 0 !important;
border-radius: inherit;
}
}
}
& .ajs-header{
@@ -52,6 +44,7 @@
& .ajs-body {
& .ajs-content {
top: 0 !important;
padding: 0px;
}
}
}
@@ -234,3 +227,8 @@
.alertify .ajs-dimmer {
background-color: $loading-bg;
}
/* It sometimes is applied to dialog and blocks the dialog from editing */
.alertify .ajs-dialog.ajs-capture:before {
display: none;
}

View File

@@ -285,11 +285,12 @@ td.switch-cell > div.bootstrap-switch {
.navbar-brand {
color: $color-brand !important;
background: $color-brand-bg !important;
background: $navbar-brand-bg !important;
margin-right: 0rem;
padding-left: 0.5rem !important;
padding-right: 1rem !important;
min-height: $navbar-height;
height: $navbar-height;
padding: 0rem;
display: flex;
align-items: center !important;

View File

@@ -155,6 +155,7 @@
.pg-navbar {
font-size: $navbar-font-size;
background-color: $navbar-color-bg;
padding-left: 0rem;
padding-right: 0.5rem;
& .nav-item .nav-link{
@@ -162,7 +163,7 @@
}
.pg-navbar-brand-arrow {
border: $navbar-height/2 solid $color-fg;
border: $navbar-height/2 solid $navbar-brand-arrow-bg;
border-right-color: transparent;
border-bottom-color: transparent;
border-top-color: transparent;
@@ -436,7 +437,7 @@ fieldset.inline-fieldset {
fieldset.inline-fieldset-without-border {
margin: 0px; margin-left: 0px; margin-right: 0px;
padding-right: 0px; padding-left: 0px; padding-top: 0px; padding-bottom: 0px;
border: 0px solid; border-radius: 0px; display: inline-block;
border: 0px solid; border-radius: 0px;
}
fieldset.inline-fieldset > legend {
@@ -678,12 +679,17 @@ div.rolmembership {
border-bottom-left-radius: 5px; border-style: solid solid;
}
.inline-tab-panel > .tab-content {
padding: 0px;
margin: 0px;
border-top: none;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
.inline-tab-panel {
& > .tab-content {
padding: 0px;
margin: 0px;
border-top: none;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
&.inline-tab-panel-padded > .tab-content {
padding: 0.5rem;
}
}
.inline-tab-panel > .tab-content > div.tab-pane {

View File

@@ -63,6 +63,10 @@
}
.wcLayout {
display: block;
}
.wcLayoutGrid, .wcLayoutGrid tr, .wcLayoutGrid td {
border: 1px solid $panel-border-color;
}

View File

@@ -37,7 +37,6 @@ $color-gray-light: #ebeef3;
$color-gray-lighter: #f3f5f9;
$color-brand: $white !default;
$color-brand-bg: #222222;
$color-editor-bg: $color-bg !default;
$color-editor-keyword: #908 !default;
@@ -68,6 +67,7 @@ $border-radius: 0.25rem; //no change
$text-color: $color-fg-theme;
$text-muted: $color-gray-dark;
$navbar-dark-color: #fff;
$navbar-dark-hover-color: #fff;
$navbar-dark-active-color: #fff;
@@ -153,6 +153,10 @@ $title-height: ($line-height-base*16px) + 5px + 2px + $border-width;
$footer-padding: 0.5rem;
$footer-min-height: 2rem;
$footer-height-calc: $footer-min-height+$footer-padding*2;
$navbar-brand-bg: #222222; //place image url if image
$navbar-brand-arrow-bg: #222222;
$navbar-color-bg: $color-primary;
$navbar-font-size: 0.925rem;
$navbar-user-font-size: 0.875rem;

View File

@@ -125,6 +125,18 @@ class BackupMessage(IProcessDesc):
return s.name, host, port
@property
def type_desc(self):
if self.backup_type == BACKUP.OBJECT:
return _("Backing up an object on the server")
if self.backup_type == BACKUP.GLOBALS:
return _("Backing up the global objects")
elif self.backup_type == BACKUP.SERVER:
return _("Backing up the server")
else:
# It should never reach here.
return _("Unknown Backup")
@property
def message(self):
name, host, port = self.get_server_details()
@@ -132,7 +144,7 @@ class BackupMessage(IProcessDesc):
if self.backup_type == BACKUP.OBJECT:
return _(
"Backing up an object on the server '{0}' "
"from database '{1}'..."
"from database '{1}'"
).format(
"{0} ({1}:{2})".format(
name, host, port
@@ -141,13 +153,13 @@ class BackupMessage(IProcessDesc):
)
if self.backup_type == BACKUP.GLOBALS:
return _("Backing up the global objects on "
"the server '{0}'...").format(
"the server '{0}'").format(
"{0} ({1}:{2})".format(
name, host, port
)
)
elif self.backup_type == BACKUP.SERVER:
return _("Backing up the server '{0}'...").format(
return _("Backing up the server '{0}'").format(
"{0} ({1}:{2})".format(
name, host, port
)

View File

@@ -47,7 +47,7 @@ class BackupMessageTest(BaseTestGenerator):
cmd="/test_path/pg_dump"
),
extected_msg="Backing up the server"
" 'test_backup_server (localhost:5444)'...",
" 'test_backup_server (localhost:5444)'",
expetced_details_cmd='/test_path/pg_dump --file '
'"backup_file" --host "localhost" '
'--port "5444" --username "postgres" '
@@ -80,7 +80,7 @@ class BackupMessageTest(BaseTestGenerator):
cmd="/test_path/pg_dump"
),
extected_msg="Backing up the global objects on the server "
"'test_backup_server (localhost:5444)'...",
"'test_backup_server (localhost:5444)'",
expetced_details_cmd='/test_path/pg_dump --file "backup_file" '
'--host "localhost"'
' --port "5444" --username "postgres" '
@@ -114,7 +114,7 @@ class BackupMessageTest(BaseTestGenerator):
),
extected_msg="Backing up an object on the server "
"'test_backup_server (localhost:5444)'"
" from database 'postgres'...",
" from database 'postgres'",
expetced_details_cmd='/test_path/pg_dump --file "backup_file" '
'--host "localhost" '
'--port "5444" --username "postgres" '

View File

@@ -218,14 +218,6 @@ define([
},
};
},
hooks: {
onshow: function() {
// Add pgadmin_grant_wizard_body class to dialog
$(this.elements.body).addClass('pgadmin_grant_wizard_body');
},
},
/**
Returns a Paginator Class Object which is again to be rendered

View File

@@ -114,11 +114,15 @@ class IEMessage(IProcessDesc):
return _(
"Copying table data '{0}.{1}' on database '{2}' "
"and server ({3}:{4})..."
"and server ({3}:{4})"
).format(
self.schema, self.table, self.database, s.host, s.port
)
@property
def type_desc(self):
return _("Copying table data")
def details(self, cmd, args):
# Fetch the server details like hostname, port, roles etc
s = Server.query.filter_by(
@@ -128,7 +132,7 @@ class IEMessage(IProcessDesc):
res = '<div>'
res += _(
"Copying table data '{0}.{1}' on database '{2}' "
"for the server '{3}'..."
"for the server '{3}'"
).format(
html.safe_str(self.schema),
html.safe_str(self.table),
@@ -140,11 +144,11 @@ class IEMessage(IProcessDesc):
)
)
res += '</div><div>'
res += '</div><div class="py-1">'
res += _("Running command:")
res += '</b><br><span class="pg-bg-cmd enable-selection">'
res += '<div class="pg-bg-cmd enable-selection p-1">'
res += html.safe_str(self._cmd)
res += '</span></div>'
res += '</div></div>'
return res

View File

@@ -93,6 +93,10 @@ class Message(IProcessDesc):
if self.data['op'] == "CLUSTER":
return res.format(_('Cluster'))
@property
def type_desc(self):
return _("Maintenance")
def details(self, cmd, args):
res = None

View File

@@ -105,10 +105,14 @@ class RestoreMessage(IProcessDesc):
def message(self):
name, host, port = self.get_server_details()
return _("Restoring backup on the server '{0}'...").format(
return _("Restoring backup on the server '{0}'").format(
"{0} ({1}:{2})".format(name, host, port),
)
@property
def type_desc(self):
return _("Restoring backup on the server")
def details(self, cmd, args):
name, host, port = self.get_server_details()
res = '<div>'

View File

@@ -46,7 +46,7 @@ class RestoreMessageTest(BaseTestGenerator):
cmd="/test_path/pg_restore"
),
extected_msg="Restoring backup on the server "
"'test_restore_server (localhost:5444)'...",
"'test_restore_server (localhost:5444)'",
expetced_details_cmd='/test_path/pg_restore --file '
'"restore_file" --host "localhost"'
' --port "5444" --username "postgres" '

View File

@@ -14,10 +14,6 @@
bottom: 0;
}
#editor-panel {
z-index: 0;
}
.sql-editor-grid-container {
height: 100%;
overflow: auto;
@@ -55,12 +51,6 @@
max-width: 35px !important;
min-width: 35px !important;
}
.sql-editor-history-container {
height: 100%;
overflow: auto;
}
.sql-status-cell {
max-width: 30px;
}

View File

@@ -185,7 +185,7 @@ define('tools.querytool', [
name: 'sql_panel',
title: gettext('Query Editor'),
width: '100%',
height: '20%',
height: '50%',
isCloseable: false,
isPrivate: true,
});

View File

@@ -2,6 +2,7 @@
height: 100%;
.list-item {
border-bottom: $panel-border;
background-color: $color-bg-theme;
}
.entry {
@@ -76,11 +77,19 @@
display: block;
}
.sql-editor-history-container {
height: 100%;
overflow: auto;
background-color: $negative-bg;
}
.query-detail {
width: 100%;
display: flex;
flex-direction: column;
background-color: $color-bg-theme;
.error-message-block {
background: $sql-history-error-bg;
flex: 0.3;

View File

@@ -18,6 +18,14 @@
z-index: 0;
}
.editor-title {
padding: $sql-title-padding;
background: $sql-title-bg;
color: $sql-title-fg;
}
#editor-panel {
z-index: 0;
position: absolute;
@@ -209,6 +217,7 @@ li.CodeMirror-hint-active {
/* color the first column */
#datagrid .slick-row .slick-cell.l0.r0.selected {
background-color: $color-primary;
color: $color-primary-fg;
}
#datagrid .slick-row > .slick-cell:not(.l0):not(.r0).selected {
@@ -233,12 +242,6 @@ li.CodeMirror-hint-active {
box-shadow: $dropdown-box-shadow;
}
.editor-title {
padding: $sql-title-padding;
background: $sql-title-bg;
color: $sql-title-fg;
}
.pg_text_editor textarea {
resize: both;
}

View File

@@ -61,7 +61,7 @@ describe('QueryHistory', () => {
it('nothing is displayed in the history details panel', (done) => {
let foundChildren = historyWrapper.find(QueryHistoryDetail);
expect(foundChildren.length).toBe(1);
expect(foundChildren.length).toBe(0);
done();
});
});