Added support to download utility files at the client-side. Fixes #3318

This commit is contained in:
Rahul Shirsat
2020-10-23 16:14:55 +05:30
committed by Akshay Joshi
parent 7573fac29f
commit c2ad97d0ab
24 changed files with 1842 additions and 61 deletions

View File

@@ -22,7 +22,7 @@ from subprocess import Popen, PIPE
import logging
from pgadmin.utils import u_encode, file_quote, fs_encoding, \
get_complete_file_path
get_complete_file_path, get_storage_directory, IS_WIN
import pytz
from dateutil import parser
@@ -59,6 +59,48 @@ class IProcessDesc(object, metaclass=ABCMeta):
def details(self, cmd, args):
pass
@property
def current_storage_dir(self):
if config.SERVER_MODE:
file = self.bfile
try:
# check if file name is encoded with UTF-8
file = self.bfile.decode('utf-8')
except Exception as e:
str(e)
# do nothing if bfile is not encoded.
path = get_complete_file_path(file)
path = file if path is None else path
if IS_WIN:
path = os.path.realpath(path)
storage_directory = os.path.basename(get_storage_directory())
if storage_directory in path:
start = path.index(storage_directory)
end = start + (len(storage_directory))
last_dir = os.path.dirname(path[end:])
else:
last_dir = file
if IS_WIN:
if '\\' in last_dir:
if len(last_dir) == 1:
last_dir = last_dir.replace('\\', '\\\\')
else:
last_dir = last_dir.replace('\\', '/')
else:
last_dir = last_dir.replace('\\', '/')
return None if hasattr(self, 'is_import') and self.is_import \
else last_dir
return None
class BatchProcess(object):
def __init__(self, **kwargs):
@@ -543,8 +585,12 @@ class BatchProcess(object):
desc = loads(p.desc)
details = desc
type_desc = ''
current_storage_dir = None
if isinstance(desc, IProcessDesc):
from pgadmin.tools.backup import BackupMessage
from pgadmin.tools.import_export import IEMessage
args = []
args_csv = StringIO(
p.arguments.encode('utf-8')
@@ -555,9 +601,11 @@ class BatchProcess(object):
args = args + arg
details = desc.details(p.command, args)
type_desc = desc.type_desc
if isinstance(desc, (BackupMessage, IEMessage)):
current_storage_dir = desc.current_storage_dir
desc = desc.message
return desc, details, type_desc
return desc, details, type_desc, current_storage_dir
@staticmethod
def list():
@@ -584,7 +632,8 @@ class BatchProcess(object):
execution_time = BatchProcess.total_seconds(etime - stime)
desc, details, type_desc = BatchProcess._check_process_desc(p)
desc, details, type_desc, current_storage_dir = BatchProcess.\
_check_process_desc(p)
res.append({
'id': p.pid,
@@ -596,7 +645,8 @@ class BatchProcess(object):
'exit_code': p.exit_code,
'acknowledge': p.acknowledge,
'execution_time': execution_time,
'process_state': p.process_state
'process_state': p.process_state,
'current_storage_dir': current_storage_dir,
})
if changed:

View File

@@ -57,3 +57,7 @@ ol.pg-bg-process-logs {
.pg-bg-bgprocess:hover .bg-close {
opacity: 0.95;
}
.icon-storage-manager:before {
font-icon: url('../img/storage_manager.svg');
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<g>
<path d="M4.3,5.3h8.8V4c0-0.7-0.6-1.3-1.3-1.3H7.5L5.8,1H1.5C0.8,1,0.2,1.6,0.2,2.3v7.4L2,6.5C2.6,5.8,3.4,5.3,4.3,5.3z"/>
<path d="M7.5,8.9c0-1.2,0.7-2.3,1.6-2.8H4.3C3.7,6.1,3.1,6.4,2.8,7l-1.9,3.3c-0.2,0.4,0.1,1,0.6,1h7C7.8,10.7,7.5,9.8,7.5,8.9z"/>
<path d="M15,6.1h-2.6c1,0.6,1.6,1.6,1.6,2.8c0,0.3-0.1,0.6-0.1,0.9L15.5,7C15.8,6.7,15.5,6.1,15,6.1z"/>
<circle cx="10.8" cy="8.9" r="2.8"/>
</g>
<path d="M14,11.8l-1.2-0.3c-1.3,0.9-2.9,0.8-3.8,0l-1.2,0.3C7,12,6.5,12.7,6.5,13.5v0.7c0,0.4,0.3,0.9,0.9,0.9h2.3l1.1-2.4l1.3,2.4
h2.4c0.4,0,0.9-0.3,0.9-0.9v-0.8C15.2,12.6,14.8,11.9,14,11.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 944 B

View File

@@ -20,6 +20,8 @@ define('misc.bgprocess', [
return pgBrowser.BackgroundProcessObsorver;
}
var isServerMode = (function() { return pgAdmin.server_mode == 'True'; })();
var wcDocker = window.wcDocker;
var BGProcess = function(info, notify) {
@@ -61,6 +63,7 @@ define('misc.bgprocess', [
curr_status: null,
state: 0, // 0: NOT Started, 1: Started, 2: Finished, 3: Terminated
completed: false,
current_storage_dir: null,
id: info['id'],
type_desc: null,
@@ -161,6 +164,9 @@ define('misc.bgprocess', [
if ('process_state' in data)
self.state = data.process_state;
if ('current_storage_dir' in data)
self.current_storage_dir = data.current_storage_dir;
if ('out' in data) {
self.out = data.out && data.out.pos;
@@ -325,8 +331,8 @@ define('misc.bgprocess', [
</div>
<div class="pg-bg-etime my-auto mr-2"></div>
<div class="ml-auto">
<button class="btn btn-secondary pg-bg-more-details"><span class="fa fa-info-circle" role="img"></span>&nbsp;` + gettext('More details...') + `</button>
<button class="btn btn-danger bg-process-stop" disabled><span class="fa fa-times-circle" role="img"></span>&nbsp;` + gettext('Stop Process') + `</button>
<button class="btn btn-secondary pg-bg-more-details" title="More Details"><span class="fa fa-info-circle" role="img"></span>&nbsp;` + gettext('More details...') + `</button>
<button class="btn btn-danger bg-process-stop" disabled><span class="fa fa-times-circle" role="img" title="Stop the operation"></span>&nbsp;` + gettext('Stop Process') + `</button>
</div>
</div>
<div class="pg-bg-status py-1">
@@ -387,6 +393,7 @@ define('misc.bgprocess', [
var $status_bar = $(self.container.find('.pg-bg-status'));
$status_bar.html(self.curr_status);
var $btn_stop_process = $(self.container.find('.bg-process-stop'));
// Enable Stop Process button only when process is running
if (parseInt(self.state) === 1) {
$btn_stop_process.attr('disabled', false);
@@ -415,7 +422,27 @@ define('misc.bgprocess', [
$logs = container.find('.bg-process-watcher'),
$header = container.find('.bg-process-details'),
$footer = container.find('.bg-process-footer'),
$btn_stop_process = container.find('.bg-process-stop');
$btn_stop_process = container.find('.bg-process-stop'),
$btn_storage_manager = container.find('.bg-process-storage-manager');
if(self.current_storage_dir && isServerMode) { //for backup & exports with server mode, operate over storage manager
if($btn_storage_manager.length == 0) {
var str_storage_manager_btn = '<button id="bg-process-storage-manager" class="btn btn-secondary bg-process-storage-manager" title="Click to open file location" aria-label="Storage Manager" tabindex="0" disabled><span class="pg-font-icon icon-storage-manager" role="img"></span></button>&nbsp;';
container.find('.bg-process-details .bg-btn-section').prepend(str_storage_manager_btn);
$btn_storage_manager = container.find('.bg-process-storage-manager');
}
// Disable storage manager button only when process is running
if (parseInt(self.state) === 1) {
$btn_storage_manager.attr('disabled', true);
}
else {
$btn_storage_manager.attr('disabled', false);
}
// On Click event for storage manager button.
$btn_storage_manager.off('click').on('click', self.storage_manager.bind(this));
}
// Enable Stop Process button only when process is running
if (parseInt(self.state) === 1) {
@@ -526,6 +553,15 @@ define('misc.bgprocess', [
});
},
storage_manager: function() {
var self = this;
if(self.current_storage_dir) {
pgBrowser.Events.trigger(
'pgadmin:tools:storage_manager', self.current_storage_dir
);
}
},
});
_.extend(
@@ -634,7 +670,7 @@ define('misc.bgprocess', [
'<span>' + gettext('Start time') + ': <span class="bgprocess-start-time"></span>' +
'</span>'+
'</div>' +
'<div class="ml-auto">' +
'<div class="ml-auto bg-btn-section">' +
'<button type="button" class="btn btn-danger bg-process-stop" disabled><span class="fa fa-times-circle" role="img"></span>&nbsp;' + gettext('Stop Process') + '</button>' +
'</div>' +
'</div>' +