diff --git a/web/pgadmin/static/scss/_alert.scss b/web/pgadmin/static/scss/_alert.scss index 0e7e234d1..4c47a222d 100644 --- a/web/pgadmin/static/scss/_alert.scss +++ b/web/pgadmin/static/scss/_alert.scss @@ -86,6 +86,12 @@ } } } +.alertify_tools_dialog_properties .pg-prop-status-bar { + position: absolute; + right: 0; + left: 0; + bottom: 0; +} .pg-prop-status-bar { padding: 5px; diff --git a/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js b/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js index 627ae3cdf..a45af72cc 100644 --- a/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js +++ b/web/pgadmin/tools/backup/static/js/backup_dialog_wrapper.js @@ -106,11 +106,22 @@ export class BackupDialogWrapper extends DialogWrapper { const dialog = this.createDialog(node, treeInfo, this.typeOfDialog, $container); this.addAlertifyClassToBackupNodeChildNodes(); dialog.render(); + const statusBar = this.jquery( + '
').appendTo($container); this.elements.content.appendChild($container.get(0)); this.focusOnDialog(this); - this.setListenersForFilenameChanges(); + this.setListenersForFilenameChanges(statusBar); } callback(event) { @@ -231,16 +242,27 @@ export class BackupDialogWrapper extends DialogWrapper { return treeInfo.server._id; } - setListenersForFilenameChanges() { + setListenersForFilenameChanges(statusBar) { const self = this; this.view.model.on('change', function () { + const ctx = this; + var errmsg; + + const showError = function(errorField, errormsg) { + ctx.errorModel.set(errorField, errormsg); + statusBar.removeClass('d-none'); + statusBar.find('.alert-text').html(errormsg); + }; + if (!_.isUndefined(this.get('file')) && this.get('file') !== '') { this.errorModel.clear(); + statusBar.addClass('d-none'); self.enableBackupButton(); } else { self.disableBackupButton(); - this.errorModel.set('file', gettext('Please provide a filename')); + errmsg = gettext('Please provide a filename'); + showError('file', errmsg); } }); } diff --git a/web/pgadmin/tools/import_export/static/js/import_export.js b/web/pgadmin/tools/import_export/static/js/import_export.js index 3c4ce652e..305a75e40 100644 --- a/web/pgadmin/tools/import_export/static/js/import_export.js +++ b/web/pgadmin/tools/import_export/static/js/import_export.js @@ -624,37 +624,63 @@ define([ ); view.render(); + const statusBar = $( + '').appendTo($container); this.elements.content.appendChild($container.get(0)); // Listen to model & if filename is provided then enable OK button // For the 'Quote', 'escape' and 'delimiter' only one character is allowed to enter this.view.model.on('change', function() { + const ctx = this; + var errmsg; + const showError = function(errorField, errormsg) { + ctx.errorModel.set(errorField, errormsg); + statusBar.removeClass('d-none'); + statusBar.find('.alert-text').html(errormsg); + }; if (!_.isUndefined(this.get('filename')) && this.get('filename') !== '') { this.errorModel.clear(); + statusBar.addClass('d-none'); if (!_.isUndefined(this.get('delimiter')) && !_.isNull(this.get('delimiter'))) { this.errorModel.clear(); + statusBar.addClass('d-none'); if (!_.isUndefined(this.get('quote')) && this.get('quote') !== '' && this.get('quote').length == 1) { this.errorModel.clear(); + statusBar.addClass('d-none'); if (!_.isUndefined(this.get('escape')) && this.get('escape') !== '' && this.get('escape').length == 1) { this.errorModel.clear(); + statusBar.addClass('d-none'); self.__internal.buttons[1].element.disabled = false; } else { self.__internal.buttons[1].element.disabled = true; - this.errorModel.set('escape', gettext('Escape should contain only one character')); + errmsg = gettext('Escape should contain only one character'); + showError('escape', errmsg); } } else { self.__internal.buttons[1].element.disabled = true; - this.errorModel.set('quote', gettext('Quote should contain only one character')); + errmsg = gettext('Quote should contain only one character'); + showError('quote', errmsg); } } else { self.__internal.buttons[1].element.disabled = true; - this.errorModel.set('delimiter', gettext('Delimiter should contain only one character')); + errmsg = gettext('Delimiter should contain only one character'); + showError('delimiter', errmsg); } } else { self.__internal.buttons[1].element.disabled = true; - this.errorModel.set('filename', gettext('Please provide filename')); + errmsg = gettext('Please provide filename'); + showError('filename', errmsg); } }); diff --git a/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js b/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js index 712d70cbc..be5bbb49a 100644 --- a/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js +++ b/web/pgadmin/tools/restore/static/js/restore_dialog_wrapper.js @@ -98,11 +98,22 @@ export class RestoreDialogWrapper extends DialogWrapper { const dialog = this.createDialog(node, treeInfo, $container); this.addAlertifyClassToRestoreNodeChildNodes(); dialog.render(); + const statusBar = this.jquery( + '').appendTo($container); this.elements.content.appendChild($container.get(0)); this.focusOnDialog(this); - this.setListenersForFilenameChanges(); + this.setListenersForFilenameChanges(statusBar); } callback(event) { @@ -218,16 +229,27 @@ export class RestoreDialogWrapper extends DialogWrapper { return treeInfo.server._id; } - setListenersForFilenameChanges() { + setListenersForFilenameChanges(statusBar) { const self = this; this.view.model.on('change', function () { + const ctx = this; + var errmsg; + + const showError = function(errorField, errormsg) { + ctx.errorModel.set(errorField, errormsg); + statusBar.removeClass('d-none'); + statusBar.find('.alert-text').html(errormsg); + }; + if (!_.isUndefined(this.get('file')) && this.get('file') !== '') { this.errorModel.clear(); + statusBar.addClass('d-none'); self.enableRestoreButton(); } else { self.disableRestoreButton(); - this.errorModel.set('file', gettext('Please provide a filename')); + errmsg = gettext('Please provide a filename'); + showError('file', errmsg); } }); } diff --git a/web/regression/javascript/backup/backup_dialog_wrapper_spec.js b/web/regression/javascript/backup/backup_dialog_wrapper_spec.js index c90ac39ec..aa129af35 100644 --- a/web/regression/javascript/backup/backup_dialog_wrapper_spec.js +++ b/web/regression/javascript/backup/backup_dialog_wrapper_spec.js @@ -94,6 +94,8 @@ describe('BackupDialogWrapper', () => { return backupJQueryContainerSpy; } else if (selector === backupNode.elements.body.childNodes[0]) { return backupNodeChildNodeSpy; + } else { + return jasmine.createSpyObj('obj', ['appendTo']); } }); alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']); diff --git a/web/regression/javascript/restore/restore_dialog_wrapper_spec.js b/web/regression/javascript/restore/restore_dialog_wrapper_spec.js index f08d50ab2..fe5bfe43c 100644 --- a/web/regression/javascript/restore/restore_dialog_wrapper_spec.js +++ b/web/regression/javascript/restore/restore_dialog_wrapper_spec.js @@ -87,6 +87,8 @@ describe('RestoreDialogWrapper', () => { return restoreJQueryContainerSpy; } else if (selector === restoreNode.elements.body.childNodes[0]) { return restoreNodeChildNodeSpy; + } else { + return jasmine.createSpyObj('obj', ['appendTo']); } }); });