// Page script for monitorJobs.html. Shared bootstrapping lives in js/app.js;
// this file just wires the three DataTables (running, scheduled, completed)
// once the user is confirmed authorized.
CollabCentral.init(function (ctx) {
document.getElementById('jobsPanel').classList.remove('hidden');
initJobTables(ctx.appName);
});
function jobDetailLink(appName, jobId, label) {
if (jobId === undefined || jobId === null) return CollabCentral.escapeHtml(label);
return '' +
CollabCentral.escapeHtml(label) + '';
}
function renderDate(val) {
return val ? CollabCentral.escapeHtml(CollabCentral.formatDate(val)) : '';
}
function renderSuccessRate(pct) {
if (pct === undefined || pct === null || pct === '') return '';
var n = typeof pct === 'number' ? pct : parseFloat(pct);
if (isNaN(n)) return CollabCentral.escapeHtml(pct);
return n.toFixed(1) + '%';
}
function renderDelivered(row) {
var s = row.stats || {};
if (s.succeededMsgs === undefined || s.totalMsgs === undefined) return '';
return s.succeededMsgs + ' / ' + s.totalMsgs;
}
function initJobTables(appName) {
$('#runningJobs').dataTable({
ajax: {
url: '/CollabCentral/' + appName + '/jobs/list/running',
dataSrc: '',
},
columns: [
{ data: 'senderDisplayName' },
{ data: 'appName' },
{ data: 'startTime', render: function (v) { return renderDate(v); } },
{ data: 'totalRecipients' },
{
data: 'completedRecipients',
render: function (val, type, row) {
if (type !== 'display' || row.jobId === undefined || row.jobId === null) return val;
var text = (val === undefined || val === null) ? 'view' : val + ' · view';
return jobDetailLink(appName, row.jobId, text);
},
},
],
searching: false,
info: false,
ordering: false,
paging: false,
language: { emptyTable: 'No running jobs.' },
});
$('#scheduledJobs').dataTable({
ajax: {
url: '/CollabCentral/' + appName + '/jobs/list/scheduled',
dataSrc: '',
},
columns: [
{ data: 'senderDisplayName' },
{ data: 'appName' },
{
data: 'message',
render: function (val, type, row) {
if (type !== 'display') return '';
// Message is stored per-language; prefer english.html or english.markdown.
var m = (val && (val.english || val)) || {};
var html = m.html || m.markdown || m.text || '';
// Truncate to keep the row compact
var text = html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
if (text.length > 120) text = text.slice(0, 117) + '…';
return CollabCentral.escapeHtml(text);
},
},
{ data: 'totalRecipients' },
{ data: 'scheduledFor', render: function (v) { return renderDate(v); } },
],
searching: false,
info: false,
ordering: false,
paging: false,
language: { emptyTable: 'No scheduled jobs.' },
});
$('#completedJobs').dataTable({
ajax: {
url: '/CollabCentral/' + appName + '/jobs/list/completed',
dataSrc: '',
},
columns: [
{
data: 'jobId',
render: function (jobId, type) {
if (type !== 'display') return jobId;
return jobDetailLink(appName, jobId, '#' + jobId);
},
},
{ data: 'senderDisplayName' },
{ data: 'appName' },
{ data: 'startTime', render: function (v) { return renderDate(v); } },
{ data: 'endTime', render: function (v) { return renderDate(v); } },
{ data: 'stats.totalTime' },
{
data: null,
render: function (row, type) {
if (type !== 'display') return '';
return renderDelivered(row);
},
},
{ data: 'stats.succeededMsgPct', render: function (v) { return renderSuccessRate(v); } },
],
order: [[3, 'desc']],
pageLength: 25,
lengthMenu: [10, 25, 50, 100],
searching: true,
info: true,
paging: true,
language: { emptyTable: 'No completed jobs in the last 30 days.' },
});
}