mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-20 11:48:31 -06:00
- Loading 'pgadmin' as 'sources/pgadmin', as found under the 'sources' reference directory to be consistent with other files. - Removed the 'pgadmin' reference from the base.html template. - Renamed 'pgadmin.slickgrid.editors.js', and 'pgadmin.slickgrid.formatters.js' as 'editors.js', and 'formatters.js' respectively, as they're already in the 'pgadmin/static/js/slickgrid' directory. - Removed the duplicate entry of 'translations' from the webpack.shim.js
537 lines
16 KiB
JavaScript
537 lines
16 KiB
JavaScript
define('misc.bgprocess', [
|
|
'sources/pgadmin', 'sources/gettext', 'sources/url_for', 'underscore',
|
|
'underscore.string', 'jquery', 'pgadmin.browser', 'alertify',
|
|
'pgadmin.browser.messages'
|
|
], function(
|
|
pgAdmin, gettext, url_for, _, S, $, pgBrowser, alertify, pgMessages
|
|
) {
|
|
|
|
pgBrowser.BackgroundProcessObsorver = pgBrowser.BackgroundProcessObsorver || {};
|
|
|
|
if (pgBrowser.BackgroundProcessObsorver.initialized) {
|
|
return pgBrowser.BackgroundProcessObsorver;
|
|
}
|
|
|
|
var BGProcess = function(info, notify) {
|
|
var self = this;
|
|
setTimeout(
|
|
function() {
|
|
self.initialize.apply(self, [info, notify]);
|
|
}, 1
|
|
);
|
|
};
|
|
|
|
_.extend(
|
|
BGProcess.prototype, {
|
|
initialize: function(info, notify) {
|
|
_.extend(this, {
|
|
details: false,
|
|
notify: (_.isUndefined(notify) || notify),
|
|
curr_status: null,
|
|
state: 0, // 0: NOT Started, 1: Started, 2: Finished
|
|
completed: false,
|
|
|
|
id: info['id'],
|
|
desc: null,
|
|
detailed_desc: null,
|
|
stime: null,
|
|
exit_code: null,
|
|
acknowledge: info['acknowledge'],
|
|
execution_time: null,
|
|
out: -1,
|
|
err: -1,
|
|
lot_more: false,
|
|
|
|
notifier: null,
|
|
container: null,
|
|
panel: null,
|
|
logs: $('<ol></ol>', {class: 'pg-bg-process-logs'})
|
|
});
|
|
|
|
if (this.notify) {
|
|
pgBrowser.Events && pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:started:' + this.id,
|
|
function(process) {
|
|
if (!process.notifier)
|
|
process.show.apply(process);
|
|
}
|
|
);
|
|
pgBrowser.Events && pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:finished:' + this.id,
|
|
function(process) {
|
|
if (!process.notifier)
|
|
process.show.apply(process);
|
|
}
|
|
)
|
|
}
|
|
var self = this;
|
|
|
|
setTimeout(
|
|
function() {
|
|
self.update.apply(self, [info]);
|
|
}, 1
|
|
);
|
|
},
|
|
|
|
bgprocess_url: function(type) {
|
|
switch (type) {
|
|
case 'status':
|
|
if (this.details && this.out != -1 && this.err != -1) {
|
|
return url_for(
|
|
'bgprocess.detailed_status', {
|
|
'pid': this.id,
|
|
'out': this.out,
|
|
'err': this.err
|
|
}
|
|
);
|
|
}
|
|
return url_for('bgprocess.status', {'pid': this.id});
|
|
case 'acknowledge':
|
|
return url_for('bgprocess.acknowledge', {'pid': this.id});
|
|
default:
|
|
return url_for('bgprocess.list');
|
|
}
|
|
},
|
|
|
|
update: function(data) {
|
|
var self = this,
|
|
out = [],
|
|
err = [],
|
|
idx = 0;
|
|
|
|
if ('stime' in data)
|
|
self.stime = new Date(data.stime);
|
|
|
|
if ('execution_time' in data)
|
|
self.execution_time = parseFloat(data.execution_time);
|
|
|
|
if ('desc' in data)
|
|
self.desc = data.desc;
|
|
|
|
if ('details' in data)
|
|
self.detailed_desc = data.details;
|
|
|
|
if ('exit_code' in data)
|
|
self.exit_code = data.exit_code;
|
|
|
|
if ('out' in data) {
|
|
self.out = data.out && data.out.pos;
|
|
|
|
if (data.out && data.out.lines) {
|
|
out = data.out.lines;
|
|
}
|
|
}
|
|
|
|
if ('err' in data) {
|
|
self.err = data.err && data.err.pos;
|
|
|
|
if (data.err && data.err.lines) {
|
|
err = data.err.lines;
|
|
}
|
|
}
|
|
self.completed = self.completed || (
|
|
'err' in data && 'out' in data && data.err.done && data.out.done
|
|
) || (
|
|
!self.details && !_.isNull(self.exit_code)
|
|
);
|
|
|
|
var io = 0,
|
|
ie = 0,
|
|
res = [],
|
|
escapeEl = document.createElement('textarea'),
|
|
escapeHTML = function(html) {
|
|
escapeEl.textContent = html;
|
|
return escapeEl.innerHTML;
|
|
};
|
|
|
|
while (io < out.length && ie < err.length) {
|
|
if (pgAdmin.natural_sort(out[io][0], err[ie][0]) <= 0){
|
|
res.push('<li class="pg-bg-res-out">' + escapeHTML(out[io++][1]) + '</li>');
|
|
} else {
|
|
res.push('<li class="pg-bg-res-err">' + escapeHTML(err[ie++][1]) + '</li>');
|
|
}
|
|
}
|
|
|
|
while (io < out.length) {
|
|
res.push('<li class="pg-bg-res-out">' + escapeHTML(out[io++][1]) + '</li>');
|
|
}
|
|
|
|
while (ie < err.length) {
|
|
res.push('<li class="pg-bg-res-err">' + escapeHTML(err[ie++][1]) + '</li>');
|
|
}
|
|
if (res.length) {
|
|
self.logs.append(res.join(''));
|
|
}
|
|
|
|
if (self.stime) {
|
|
self.curr_status = gettext('Started');
|
|
|
|
if (self.execution_time >= 2) {
|
|
self.curr_status = gettext['Running...'];
|
|
}
|
|
|
|
if (!_.isNull(self.exit_code)) {
|
|
if (self.exit_code == 0) {
|
|
self.curr_status = gettext('Successfully completed.');
|
|
} else {
|
|
self.curr_status = S(
|
|
gettext("Failed (exit code: %s).")
|
|
).sprintf(String(self.exit_code)).value();
|
|
}
|
|
}
|
|
|
|
if (self.state == 0 && self.stime) {
|
|
self.state = 1;
|
|
pgBrowser.Events && pgBrowser.Events.trigger(
|
|
'pgadmin-bgprocess:started:' + self.id, self, self
|
|
);
|
|
}
|
|
|
|
if (self.state == 1 && !_.isNull(self.exit_code)) {
|
|
self.state = 2;
|
|
pgBrowser.Events && pgBrowser.Events.trigger(
|
|
'pgadmin-bgprocess:finished:' + self.id, self, self
|
|
);
|
|
}
|
|
|
|
setTimeout(function() {self.show.apply(self)}, 10);
|
|
}
|
|
|
|
if (!self.completed) {
|
|
setTimeout(
|
|
function() {
|
|
self.status.apply(self);
|
|
}, 1000
|
|
);
|
|
}
|
|
},
|
|
|
|
status: function() {
|
|
var self = this;
|
|
|
|
$.ajax({
|
|
typs: 'GET',
|
|
timeout: 30000,
|
|
url: self.bgprocess_url('status'),
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
setTimeout(function() { self.update(res); }, 10);
|
|
},
|
|
error: function(res) {
|
|
// Try after some time only if job id present
|
|
if (res.status != 410)
|
|
setTimeout(function() { self.update(res); }, 10000);
|
|
}
|
|
});
|
|
},
|
|
|
|
show: function() {
|
|
var self = this;
|
|
|
|
if (self.notify && !self.details) {
|
|
if (!self.notifier) {
|
|
var header = $('<div></div>', {
|
|
class: "h5 pg-bg-notify-header"
|
|
}).append($('<span></span>').text(self.desc)),
|
|
content = $('<div class="pg-bg-bgprocess row"></div>').append(
|
|
header
|
|
).append(
|
|
$('<div></div>', {class: 'pg-bg-notify-body h6' }).append(
|
|
$('<div></div>', {class: 'pg-bg-start col-xs-12' }).append(
|
|
$('<div></div>').text(self.stime.toString())
|
|
).append(
|
|
$('<div class="pg-bg-etime"></div>')
|
|
)
|
|
)
|
|
),
|
|
for_details = $('<div></div>', {
|
|
class: "col-xs-12 text-center pg-bg-click h6"
|
|
}).append(
|
|
$('<span></span>').text(gettext('Click here for details.'))
|
|
).appendTo(content),
|
|
status = $('<div></div>', {
|
|
class: "pg-bg-status col-xs-12 h5 " + ((self.exit_code === 0) ?
|
|
'bg-success': (self.exit_code == 1) ?
|
|
'bg-failed' : '')
|
|
}).appendTo(content),
|
|
close_me = $(
|
|
'<div class="bg-close"><i class="fa fa-close"></i></div>'
|
|
).appendTo(header);
|
|
|
|
self.container = content;
|
|
self.notifier = alertify.notify(
|
|
content.get(0), 'bg-bgprocess', 0, null
|
|
);
|
|
|
|
for_details.on('click', function(ev) {
|
|
ev = ev || window.event;
|
|
ev.cancelBubble = true;
|
|
ev.stopPropagation();
|
|
|
|
this.notifier.dismiss();
|
|
this.notifier = null;
|
|
this.completed = false;
|
|
|
|
this.show_detailed_view.apply(this);
|
|
}.bind(self));
|
|
|
|
close_me.on('click', function(ev) {
|
|
this.notifier.dismiss();
|
|
this.notifier = null;
|
|
this.acknowledge_server.apply(this);
|
|
}.bind(this));
|
|
|
|
// Do not close the notifier, when clicked on the container, which
|
|
// is a default behaviour.
|
|
content.on('click', function(ev) {
|
|
ev = ev || window.event;
|
|
ev.cancelBubble = true;
|
|
ev.stopPropagation();
|
|
|
|
return;
|
|
});
|
|
}
|
|
// TODO:: Formatted execution time
|
|
self.container.find('.pg-bg-etime').empty().append(
|
|
$('<span></span>').text(
|
|
String(self.execution_time)
|
|
)
|
|
).append(
|
|
$('<span></span>').text(' ' + gettext('seconds'))
|
|
);
|
|
self.container.find('.pg-bg-status').empty().append(
|
|
self.curr_status
|
|
);
|
|
} else {
|
|
self.show_detailed_view.apply(self)
|
|
}
|
|
},
|
|
|
|
show_detailed_view: function() {
|
|
var self = this,
|
|
panel = this.panel,
|
|
is_new = false;
|
|
|
|
if (!self.panel) {
|
|
is_new = true;
|
|
panel = this.panel =
|
|
pgBrowser.BackgroundProcessObsorver.create_panel();
|
|
|
|
panel.title('Process Watcher - ' + _.escape(self.desc));
|
|
panel.focus();
|
|
}
|
|
|
|
var container = panel.$container,
|
|
status_class = (
|
|
(self.exit_code === 0) ?
|
|
'bg-bgprocess-success': (self.exit_code == 1) ?
|
|
'bg-bgprocess-failed' : ''
|
|
),
|
|
$logs = container.find('.bg-process-watcher'),
|
|
$header = container.find('.bg-process-details'),
|
|
$footer = container.find('.bg-process-footer');
|
|
|
|
if (is_new) {
|
|
// set logs
|
|
$logs.html(self.logs);
|
|
|
|
// set bgprocess detailed description
|
|
$header.find('.bg-detailed-desc').html(self.detailed_desc);
|
|
}
|
|
|
|
// set bgprocess start time
|
|
$header.find('.bg-process-stats .bgprocess-start-time').html(
|
|
self.stime
|
|
);
|
|
|
|
// set status
|
|
$footer.find('.bg-process-status p').removeClass().addClass(
|
|
status_class
|
|
).html(self.curr_status);
|
|
|
|
// set bgprocess execution time
|
|
$footer.find('.bg-process-exec-time p').empty().append(
|
|
$('<span></span>').text(
|
|
String(self.execution_time)
|
|
)
|
|
).append(
|
|
$('<span></span>').text(' ' + gettext('seconds'))
|
|
);
|
|
|
|
if (is_new) {
|
|
self.details = true;
|
|
self.err = 0;
|
|
self.out = 0;
|
|
setTimeout(
|
|
function() {
|
|
self.status.apply(self);
|
|
}, 1000
|
|
);
|
|
|
|
var resize_log_container = function($logs, $header, $footer) {
|
|
var h = $header.outerHeight() + $footer.outerHeight();
|
|
$logs.css('padding-bottom', h);
|
|
}.bind(panel, $logs, $header, $footer);
|
|
|
|
panel.on(wcDocker.EVENT.RESIZED, resize_log_container);
|
|
panel.on(wcDocker.EVENT.ATTACHED, resize_log_container);
|
|
panel.on(wcDocker.EVENT.DETACHED, resize_log_container);
|
|
|
|
resize_log_container();
|
|
|
|
panel.on(wcDocker.EVENT.CLOSED, function(process) {
|
|
process.panel = null;
|
|
|
|
process.details = false;
|
|
if (process.exit_code != null) {
|
|
process.acknowledge_server.apply(process);
|
|
}
|
|
}.bind(panel, this));
|
|
}
|
|
},
|
|
|
|
acknowledge_server: function() {
|
|
var self = this;
|
|
$.ajax({
|
|
type: 'PUT',
|
|
timeout: 30000,
|
|
url: self.bgprocess_url('acknowledge'),
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
return;
|
|
},
|
|
error: function(res) {
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
_.extend(
|
|
pgBrowser.BackgroundProcessObsorver, {
|
|
bgprocesses: {},
|
|
init: function() {
|
|
var self = this;
|
|
|
|
if (self.initialized) {
|
|
return;
|
|
}
|
|
self.initialized = true;
|
|
|
|
setTimeout(
|
|
function() {
|
|
self.update_process_list.apply(self);
|
|
}, 1000
|
|
);
|
|
|
|
pgBrowser.Events.on(
|
|
'pgadmin-bgprocess:created',
|
|
function() {
|
|
setTimeout(
|
|
function() {
|
|
pgBrowser.BackgroundProcessObsorver.update_process_list(true);
|
|
}, 1000
|
|
);
|
|
}
|
|
)
|
|
},
|
|
|
|
update_process_list: function(recheck) {
|
|
var observer = this;
|
|
|
|
$.ajax({
|
|
typs: 'GET',
|
|
timeout: 30000,
|
|
url: url_for('bgprocess.list'),
|
|
cache: false,
|
|
async: true,
|
|
contentType: "application/json",
|
|
success: function(res) {
|
|
var cnt = 0;
|
|
if (!res || !_.isArray(res)) {
|
|
return;
|
|
}
|
|
for (var idx in res) {
|
|
var process = res[idx];
|
|
if ('id' in process) {
|
|
if (!(process.id in observer.bgprocesses)) {
|
|
observer.bgprocesses[process.id] = new BGProcess(process);
|
|
}
|
|
}
|
|
}
|
|
if (recheck && res.length == 0) {
|
|
// Recheck after some more time
|
|
setTimeout(
|
|
function() {
|
|
observer.update_process_list(false);
|
|
}, 3000
|
|
);
|
|
}
|
|
},
|
|
error: function(res) {
|
|
// FIXME:: What to do now?
|
|
}
|
|
});
|
|
},
|
|
|
|
create_panel: function() {
|
|
this.register_panel();
|
|
|
|
return pgBrowser.docker.addPanel(
|
|
'bg_process_watcher',
|
|
wcDocker.DOCK.FLOAT,
|
|
null, {
|
|
w: (screen.width < 700 ?
|
|
screen.width * 0.95 : screen.width * 0.5),
|
|
h: (screen.height < 500 ?
|
|
screen.height * 0.95 : screen.height * 0.5),
|
|
x: (screen.width < 700 ? '2%' : '25%'),
|
|
y: (screen.height < 500 ? '2%' : '25%')
|
|
});
|
|
},
|
|
|
|
register_panel: function() {
|
|
var w = pgBrowser.docker,
|
|
panels = w.findPanels('bg_process_watcher');
|
|
|
|
if (panels && panels.length >= 1)
|
|
return;
|
|
|
|
var p = new pgBrowser.Panel({
|
|
name: 'bg_process_watcher',
|
|
showTitle: true,
|
|
isCloseable: true,
|
|
isPrivate: true,
|
|
content: '<div class="bg-process-details col-xs-12">'+
|
|
'<p class="bg-detailed-desc"></p>'+
|
|
'<div class="bg-process-stats">'+
|
|
'<span><b>' + gettext('Start time') + ': </b>'+
|
|
'<span class="bgprocess-start-time"></span>'+
|
|
'</span></div>'+
|
|
'</div>'+
|
|
'<div class="bg-process-watcher col-xs-12">'+
|
|
'</div>'+
|
|
'<div class="bg-process-footer col-xs-12">'+
|
|
'<div class="bg-process-status col-xs-6">'+
|
|
'<span><b>' + gettext('Status') + ':</b></span><p></p>'+
|
|
'</div>'+
|
|
'<div class="bg-process-exec-time col-xs-6">'+
|
|
'<div class="exec-div pull-right">'+
|
|
'<span><b>' + gettext('Execution time') + ':</b></span><p></p>'+
|
|
'</div>'+
|
|
'</div>'+
|
|
'</div>',
|
|
onCreate: function(myPanel, $container) {
|
|
$container.addClass('pg-no-overflow');
|
|
}
|
|
});
|
|
p.load(pgBrowser.docker);
|
|
}
|
|
});
|
|
|
|
return pgBrowser.BackgroundProcessObsorver;
|
|
});
|