MeshCentral/views/task-user.handlebars

1070 lines
48 KiB
Handlebars

<html>
<head>
<script type="text/javascript" src="scripts/common-0.0.1.js"></script>
<style>
body {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
}
#dropBlock {
/*background-color: gray;
text-align: center;
height: 100%;
width: 100%;
position: absolute;
float:left;*/
width: 100%;
overflow: hidden;
position: absolute;
right: 437px;
padding-top: 100px;
text-align: center;
font-size: 1600%;
color: #AAA;
}
#scripts_endpoints {
width: 100%;
height: 100%;
}
#scriptContainer {
width: 35%;
height: 100%;
float: left;
}
#infoContainer {
width: 65%;
height: 100%;
float: right;
border-left: 1px;
}
.lifolder {
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAM2xV/Xur+XPgP///yH5BAEAAAMALAAAAAAQABAAAAJD3ISZIGHWUGihznesYDYATFVM+D2hJ4lgN1olxALAtAlmPCJvuMmJd6PJckDYwicrHhTD5o7plJmg0Uc0asNMkphHAQA7) no-repeat 16px;
padding-left: 35px;
cursor: pointer;
border: none;
margin-top: 1px;
}
.liscript {
background: url(data:image/gif;base64,R0lGODlhEAAQAJEDAPb19IGBgbq6uv///yH5BAEAAAMALAAAAAAQABAAAAIy3ISpxgcPH2ouQgFEw1YmxnUXKEaaEZZnVWZk66JwzKpvuwZzwOgwb/C1gIOA8Yg8DgoAOw==) no-repeat 16px;
padding-left: 35px;
cursor: pointer;
border: none;
margin-top: 1px;
}
.liselected {
background-color: lightgray;
}
#controlBar {
width: 100%;
height: 20px;
border-bottom: 1px solid black;
font-size: smaller;
margin-bottom: 7px;
}
#controlBar span {
cursor: pointer;
padding-left: 4px;
padding-right: 4px;
}
#controlBar > span:nth-child(n+2) {
border-left: 1px solid black;
}
.infoBar {
background-color: #777;
color: white;
cursor: pointer;
padding: 10px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.infoBar.active, .infoBar:hover {
background-color: #555;
}
.infoContent {
display: none;
}
#nHistTbl, #sHistTbl, #nSchTbl, #sSchTbl, #varTbl {
font-size: smaller;
width: 100%;
}
#nHistTbl td, #sHistTbl td, #nSchTbl td, #sSchTbl td, #varTbl td {
padding-left: 5px;
padding-right: 5px;
}
.stNHRow, .stSHRow, .stNSRow, .stSSRow {
height: 36px;
max-height: 40px;
width: 100%;
}
.stNHRow:nth-child(odd) {
background-color: #CCC;
}
.stSHRow:nth-child(odd) {
background-color: #CCC;
}
.stNSRow:nth-child(odd) {
background-color: #CCC;
}
.stSSRow:nth-child(odd) {
background-color: #CCC;
}
.stVRow:nth-child(odd) {
background-color: #CCC;
}
.delSched {
cursor: pointer;
}
.nIcon {
width: 16px;
margin-top: 1px;
margin-left: 2px;
height: 16px;
display: inline-block;
margin-right: 10px;
}
.j1 {
background: url(../images/icons16.png) 0px 0px;
height: 16px;
width: 16px;
border: none;
}
.j2 {
background: url(../images/icons16.png) -16px 0px;
height: 16px;
width: 16px;
border: none;
}
.j3 {
background: url(../images/icons16.png) -32px 0px;
height: 16px;
width: 16px;
border: none;
}
.j4 {
background: url(../images/icons16.png) -48px 0px;
height: 16px;
width: 16px;
border: none;
}
.j5 {
background: url(../images/icons16.png) -64px 0px;
height: 16px;
width: 16px;
border: none;
}
.j6 {
background: url(../images/icons16.png) -80px 0px;
height: 16px;
width: 16px;
border: none;
}
.ftype {
font-size: small;
}
.tblFloat {
float: left;
width: 33%;
}
.flink {
cursor: pointer;
}
</style>
</head>
<body onload="doOnLoad();">
<div id="scriptTaskUser">
<div id="dropBlock" style="display:none;"><b>&checkmark;</b></div>
Upload: <input type="file" id="files" name="files[]" multiple onchange="fileUpload();" />
<hr />
<div id="controlBar">
<span onclick="goNew();">New</span>
<span onclick="goRename();">Rename</span>
<span onclick="goEdit();">Edit</span>
<span onclick="goDelete();">Delete</span>
<span onclick="goNewFolder();">New Folder</span>
<span onclick="goDownload();">Download</span>
<span onclick="goRun();">Run</span>
</div>
<div id="scripts_endpoints">
<div id="scriptContainer">
</div>
<div id="infoContainer">
<div id="history">
<div class="infoBar">Advanced Run</div>
<div id="multiRun" class="infoContent">
<div style="padding-top: 15px;"><button onclick="goAdvancedRun();">Schedule on Selected</button></div>
<div class="tblFloat">
<table id="mRunTbl" cellspacing="0" cellpadding="0">
<tr><td><label><input type="checkbox" onclick="selAllNodes(this);"> Select All</label></td></tr>
</table>
</div>
<div class="tblFloat">
<table id="mRunTblMesh" cellspacing="0" cellpadding="0">
<tr><td>Meshes</td></tr>
</table>
</div>
<div class="tblFloat">
<table id="mRunTblTag" cellspacing="0" cellpadding="0">
<tr><td>Tags</td></tr>
</table>
</div>
</div>
<div class="infoBar">Node Schedules</div>
<div id="nSch" class="infoContent">
<table id="nSchTbl" cellspacing="0" cellpadding="0">
<th>Script</th>
<th>Author</th>
<th>Every</th>
<th>Starting</th>
<th>Ending</th>
<th>Last Run</th>
<th>Next Run</th>
<th>Action</th>
</table>
</div>
<div class="infoBar">Script Schedules</div>
<div id="sSch" class="infoContent">
<table id="sSchTbl" cellspacing="0" cellpadding="0">
<th>Node</th>
<th>Author</th>
<th>Every</th>
<th>Starting</th>
<th>Ending</th>
<th>Last Run</th>
<th>Next Run</th>
<th>Action</th>
</table>
</div>
<div class="infoBar">Node History</div>
<div id="nodeHistory" class="infoContent">
<table id="nHistTbl" cellspacing="0" cellpadding="0">
<th>Time</th>
<th>Run By</th>
<th>Script</th>
<th>Status</th>
<th>Return Value</th>
</table>
</div>
<div class="infoBar">Script History</div>
<div id="scriptHistory" class="infoContent">
<table id="sHistTbl" cellspacing="0" cellpadding="0">
<th>Time</th>
<th>Run By</th>
<th>Node</th>
<th>Status</th>
<th>Return Value</th>
</table>
</div>
<div class="infoBar">Variables</div>
<div id="variables" class="infoContent">
<table id="varTbl" cellspacing="0" cellpadding="0">
<th>Variable Name</th>
<th>Value</th>
<th>Scope</th>
<th>Scope Target</th>
<th>Action</th>
</table>
<br />
<span class="flink" onclick="newVar();return false;">[+]</span>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var scriptTree = {{{scriptTree}}};
var elementDragged = false;
var dragCounter = 0;
var draggedId = null;
var nodesObj = {};
var variables = [];
var varScopes = { global: 'Global', script: 'Script', mesh: 'Mesh', node: 'Node' };
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
function resizeIframe() {
document.body.style.height = 0;
parent.pluginHandler.scripttask.resizeContent();
}
function updateNodesTable() {
let dRows = document.querySelectorAll('.stNodeRow');
dRows.forEach((r) => {
r.parentNode.removeChild(r);
});
var tagList = [];
var nodeRowIns = document.querySelector('#mRunTbl');
parent.nodes.forEach(function(i) {
var item = {...i, ...{}};
if (item.mtype == 2) {
item.meshName = parent.meshes[item['meshid']].name;
if (item._id == parent.currentNode._id) item.checked = 'checked '; else item.checked = '';
let tpl = `<tr class="stNodeRow"><td><label><input type="checkbox" ${item.checked} name="runOn[]" value="${item._id}"> <div class="nIcon j${item.icon}"></div>${item.name}</label></td></tr>`;
nodeRowIns.insertAdjacentHTML('beforeend', tpl);
if (i.tags && i.tags.length) item.tags.forEach(function(t) { tagList.push(t) });
nodesObj[i._id] = i;
}
});
tagList = tagList.filter(onlyUnique); tagList = tagList.sort();
var nodeRowIns = document.querySelector('#mRunTblMesh');
for (const i in parent.meshes) { // parent.meshes.forEach(function(i) {
var item = {...parent.meshes[i], ...{}};
if (item.mtype == 2) {
let tpl = `<tr class="stNodeRow"><td><label><input type="checkbox" onclick="selNodesByMesh(this);" value="${item._id}"> ${item.name}</label></td></tr>`;
nodeRowIns.insertAdjacentHTML('beforeend', tpl);
}
}
var nodeRowIns = document.querySelector('#mRunTblTag');
tagList.forEach(function(i) {
let tpl = `<tr class="stNodeRow"><td><label><input type="checkbox" onclick="selNodesByTag(this)" value="${i}"> ${i}</label></td></tr>`;
nodeRowIns.insertAdjacentHTML('beforeend', tpl);
});
}
function selNodesByTag(el) {
var t = el.value;
var allNodes = Q('mRunTbl').querySelectorAll('input[type="checkbox"][name="runOn[]"]');
var checked = false;
if (el.checked) checked = true;
allNodes.forEach(function(n) {
if (nodesObj[n.value].tags && nodesObj[n.value].tags.indexOf(t) > -1) n.checked = checked;
});
return true;
}
function selNodesByMesh(el) {
var mid = el.value;
var allNodes = Q('mRunTbl').querySelectorAll('input[type="checkbox"][name="runOn[]"]');
var checked = false;
if (el.checked) checked = true;
allNodes.forEach(function(n) {
if (nodesObj[n.value].meshid == mid) n.checked = checked;
});
return true;
}
function selAllNodes(el) {
var allNodes = Q('mRunTbl').querySelectorAll('input[type="checkbox"][name="runOn[]"]');
var checked = false;
if (el.checked) checked = true;
allNodes.forEach(function(n) {
n.checked = checked;
});
return true;
}
function doOnLoad() {
redrawScriptTree();
selectPreviouslySelectedScript();
updateNodesTable();
parent.meshserver.send({ 'action': 'plugin', 'plugin': 'scripttask', 'pluginaction': 'loadNodeHistory', 'nodeId': parent.currentNode._id });
parent.meshserver.send({ 'action': 'plugin', 'plugin': 'scripttask', 'pluginaction': 'loadVariables', 'nodeId': parent.currentNode._id });
}
function selectPreviouslySelectedScript() {
var sel_item = parent.getstore('_scripttask_sel_item', null)
if (sel_item != null) {
var s = document.getElementById(sel_item);
if (s != null) {
s.classList.toggle('liselected');
goScript(s);
}
}
if (sel_item != null) parent.meshserver.send({ 'action': 'plugin', 'plugin': 'scripttask', 'pluginaction': 'loadScriptHistory', 'scriptId': sel_item });
}
function goRun() {
var selScript = document.querySelectorAll('.liselected');
if (selScript.length) {
var scriptId = selScript[0].getAttribute('x-data-id');
if (scriptId == selScript[0].getAttribute('x-folder-id'))
{
parent.setDialogMode(2, "Oops!", 1, null, 'Please select a script. A folder is currently selected.');
}
else {
parent.meshserver.send({ 'action': 'plugin', 'plugin': 'scripttask', 'pluginaction': 'runScript', 'scriptId': scriptId, 'nodes': [ parent.currentNode._id ], 'currentNodeId': parent.currentNode._id });
}
} else {
parent.setDialogMode(2, "Oops!", 1, null, 'No script has been selected to run on the machines.');
}
}
function goEdit() {
var selScript = document.querySelectorAll('.liselected');
if (selScript.length && (selScript[0].getAttribute('x-data-id') != selScript[0].getAttribute('x-data-folder'))) {
var scriptId = selScript[0].getAttribute('x-data-id');
window.open('/pluginadmin.ashx?pin=scripttask&user=1&edit=1&id=' + scriptId, '_blank');
window.callback = function(sd) {
parent.meshserver.send({ 'action': 'plugin', 'plugin': 'scripttask', 'pluginaction': 'editScript', 'scriptId': sd._id, 'scriptType': sd.type, 'scriptName': sd.name, 'scriptContent': sd.content, 'currentNodeId': parent.currentNode._id });
};
} else {
parent.setDialogMode(2, "Oops!", 1, null, 'No script has been selected to edit.');
}
}
function goAdvancedRun() {
var cboxes = document.getElementsByName("runOn[]");
var sel = [];
cboxes.forEach((n) => {
if (n.checked) sel.push(n.value);
});
if (sel.length == 0) {
parent.setDialogMode(2, "Oops!", 1, null, 'No machines have been selected.');
return;
}
var selScript = document.querySelectorAll('.liselected');
if (selScript.length) {
var scriptId = selScript[0].getAttribute('x-data-id');
var sWin = window.open('/pluginadmin.ashx?pin=scripttask&user=1&schedule=1', 'schedule', "width=800,height=600");
sWin.scriptId = scriptId;
sWin.nodes = sel;
window.schedCallback = function(opts) {
parent.meshserver.send({
'action': 'plugin',
'plugin': 'scripttask',
'pluginaction': 'addScheduledJob',
'scriptId': opts.scriptId,
'nodes': opts.nodes,
'currentNodeId': parent.currentNode._id,
'schedule': opts
});
};
} else {
parent.setDialogMode(2, "Oops!", 1, null, 'No script has been selected to run on the machines.');
}
}
var coll = document.getElementsByClassName("infoBar");
for (var i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
content.style.maxHeight = '300px';
content.style.overflowY = 'scroll';
resizeIframe();
});
}
function goDownload() {
var isSelected = document.querySelectorAll('.liselected');
if (isSelected.length == 0) return;
var sel = isSelected[0];
var id = sel.getAttribute('x-data-id');
if (id == sel.getAttribute('x-data-folder')) return;
window.location = '/pluginadmin.ashx?pin=scripttask&user=1&dl='+id;
}
function addScript(name, content, path) {
// file type testing
var n = name.split('.').pop().toLowerCase();
if (content.split('\n')[0][0] == '#' && content.split('\n')[0][1] == '!') n = 'bash';
if (['ps1', 'bat', 'bash'].indexOf(n) !== -1) {
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'addScript', name: name, content: content, path: path, filetype: n });
}
else {
parent.setDialogMode(2, "Oops!", 1, null, 'Currently accepted filetypes are .ps1, .bat, and bash scripts.');
}
}
function redrawScriptTree() {
var lastpath = null;
var str = '';
var indent = 0;
var folder_id = null;
scriptTree.forEach(function(f) {
if (f.path != lastpath && f.type == 'folder') {
indent = (f.path.match(/\//g) || []).length + 1;
var name = f.path.match(/[^\/]+$/);
folder_id = f._id;
str += '<div draggable="true" x-data-path="' + f.path + '" x-data-id="' + f._id + '" x-data-folder="' + folder_id + '" style="margin-left: ' + indent + 'em;" class="lifolder" onclick="toggleCollapse(this);"><span class="fname">' + name + '</span></div>';
lastpath = f.path;
indent += 1;
}
if (f.type != 'folder') {
str += '<div id="' + f._id + '" draggable="true" x-data-path="' + f.path + '" x-data-id="' + f._id + '" x-data-folder="' + folder_id + '" style="margin-left: ' + indent + 'em;" class="liscript" onclick="goScript(this);"><span class="fname">' + f.name + '</span> [<span class="ftype">' + f.filetype + '</span>]</div>';
}
document.getElementById('scriptContainer').innerHTML = str;
});
var liScripts = document.querySelectorAll('.liscript');
var liFolders = document.querySelectorAll('.lifolder');
liScripts.forEach(function(el) {
el.addEventListener('mousedown', function() { elementDragged = true; });
el.addEventListener('mouseup', function() { elementDragged = false; });
el.addEventListener('dragstart', function(evt) { evt.dataTransfer.setData('text/plain', evt.target.getAttribute('x-data-id')); });
});
liFolders.forEach(function(el) {
el.addEventListener('drop', dropMove);
el.addEventListener('dragover', function(e) { e.preventDefault(); });
el.addEventListener('mousedown', function() { elementDragged = true; });
el.addEventListener('mouseup', function() { elementDragged = false; });
el.addEventListener('dragstart', function(evt) { evt.dataTransfer.setData('text/plain', evt.target.getAttribute('x-data-id')); });
});
resizeIframe();
selectPreviouslySelectedScript();
}
parent.pluginHandler.scripttask.newScriptTree = function(message) {
scriptTree = message.event.tree;
redrawScriptTree();
}
parent.pluginHandler.scripttask.loadHistory = function(message) {
// cache script names
var nNames = {};
parent.nodes.forEach(function(n){
nNames[n._id] = n.name;
});
if (message.event.nodeHistory != null && message.event.nodeId == parent.currentNode._id) {
var nHistTbl = document.getElementById('nHistTbl');
var rows = nHistTbl.querySelectorAll('.stNHRow');
if (rows.length) {
rows.forEach(function(r) {
r.parentNode.removeChild(r);
});
}
if (message.event.nodeHistory.length) {
message.event.nodeHistory.forEach(function(nh) {
nh.latestTime = Math.max(nh.completeTime, nh.queueTime, nh.dispatchTime, nh.dontQueueUntil);
});
message.event.nodeHistory.sort((a, b) => (a.latestTime < b.latestTime) ? 1 : -1);
message.event.nodeHistory.forEach(function(nh) {
nh = prepHistory(nh);
let tpl = '<td>' + nh.timeStr + '</td> \
<td>' + nh.runBy + '</td> \
<td>' + nh.scriptName + '</td> \
<td>' + nh.statusTxt + '</td> \
<td>' + nh.returnTxt + '</td>';
let tr = nHistTbl.insertRow(-1);
tr.innerHTML = tpl;
tr.classList.add('stNHRow');
});
}
}
var currentScript = document.getElementById('scriptHistory');
var currentScriptId = currentScript.getAttribute('x-data-id');
if (message.event.scriptHistory != null && message.event.scriptId == currentScriptId) {
var sHistTbl = document.getElementById('sHistTbl');
var rows = sHistTbl.querySelectorAll('.stSHRow');
if (rows.length) {
rows.forEach(function(r) {
r.parentNode.removeChild(r);
});
}
if (message.event.scriptHistory.length) {
message.event.scriptHistory.forEach(function(nh) {
nh.latestTime = Math.max(nh.completeTime, nh.queueTime, nh.dispatchTime, nh.dontQueueUntil);
});
message.event.scriptHistory.sort((a, b) => (a.latestTime < b.latestTime) ? 1 : -1);
message.event.scriptHistory.forEach(function(nh) {
nh = prepHistory(nh);
let tpl = '<td>' + nh.timeStr + '</td> \
<td>' + nh.runBy + '</td> \
<td>' + nNames[nh.node] + '</td> \
<td>' + nh.statusTxt + '</td> \
<td>' + nh.returnTxt + '</td>';
let tr = sHistTbl.insertRow(-1);
tr.innerHTML = tpl;
tr.classList.add('stSHRow');
});
}
}
resizeIframe();
}
function prepHistory(nh) {
var nowTime = Math.floor(new Date() / 1000);
var d = new Date(0);
d.setUTCSeconds(nh.latestTime);
nh.timeStr = d.toLocaleString();
if (nh.errorVal != null) { nh.returnTxt = nh.errorVal; } else { nh.returnTxt = nh.returnVal; }
nh.statusTxt = 'Queued';
if (nh.dispatchTime != null) nh.statusTxt = 'Running';
if (nh.errorVal != null) nh.statusTxt = 'Error';
if (nh.returnVal != null) nh.statusTxt = 'Completed';
if (nh.dontQueueUntil > nowTime) nh.statusTxt = 'Scheduled';
if (nh.returnTxt == null) nh.returnTxt = '&nbsp;';
if (nh.statusTxt == 'Completed') {
nh.statusTxt = '<span title="Completed ' + secondsToHms((nh.completeTime - nh.dispatchTime)) + '">' + nh.statusTxt + '</span>';
}
if (isJsonString(nh.returnTxt)) {
try {
nh.returnObj = JSON.parse(nh.returnTxt);
nh.returnTxt = 'Object: ';
nh.returnTxt += '' + JSON.stringify(nh.returnObj, null, 2);
nh.returnTxt = nh.returnTxt.replace(/\n\s*\n/g, '\n');
nh.returnTxt = nh.returnTxt.replace(/(?:\r\n|\r|\n)/g, '<br />');
} catch(e) { }
} else {
if (typeof nh.returnTxt == 'string') {
nh.returnTxt = nh.returnTxt.replace(/\n\s*\n/g, '\n');
nh.returnTxt = nh.returnTxt.replace(/(?:\r\n|\r|\n)/g, '<br />');
}
}
return nh;
}
parent.pluginHandler.scripttask.loadVariables = function(message) {
if (message.event.vars.length) {
var vars = message.event.vars;
vars.forEach(function(vd) {
switch (vd.scope) {
case 'global':
vd.scopeTargetTxt = vd.scopeTargetHtml = 'N/A';
break;
case 'script':
var s = scriptTree.filter(obj => { return obj._id === vd.scopeTarget })[0]
vd.scopeTargetHtml = '<span title="' + s.path + '">' + s.name + '</span>';
vd.scopeTargetTxt = s.name;
break;
case 'mesh':
vd.scopeTargetTxt = vd.scopeTargetHtml = parent.meshes[vd.scopeTarget].name;
break;
case 'node':
var n = parent.nodes.filter(obj => { return obj._id === vd.scopeTarget })[0]
vd.scopeTargetHtml = '<span title="' + n.meshnamel + '">' + n.name + '</span>';
vd.scopeTargetTxt = n.name;
break;
default:
vd.scopeTargetTxt = vd.scopeTargetHtml = 'N/A';
break;
}
vd.scopeTxt = varScopes[vd.scope];
})
var ordering = { 'global': 0, 'script': 1, 'mesh': 2, 'node': 3 }
vars.sort((a, b) => {
return (ordering[a.scope] - ordering[b.scope])
|| a.name.localeCompare(b.name)
|| a.scopeTargetTxt.localeCompare(b.scopeTargetTxt);
});
variables = vars;
parseVariables();
}
}
function parseVariables() {
var vTbl = document.getElementById('varTbl');
var rows = vTbl.querySelectorAll('.stVRow');
if (rows.length) {
rows.forEach(function(r) {
r.parentNode.removeChild(r);
});
}
var scriptEl = document.querySelectorAll('.liselected');
if (scriptEl.length != 1) return;
var el = scriptEl[0];
scopeTargetScriptId = el.getAttribute('x-data-id');
variables.forEach(function(vd) {
if (vd.scope == 'script' && vd.scopeTarget != scopeTargetScriptId) return;
if (vd.scope == 'mesh' && vd.scopeTarget != parent.currentNode.meshid) return;
if (vd.scope == 'node' && vd.scopeTarget != parent.currentNode._id) return;
let actionHtml = '<span class="flink" onclick="editVar(this);">Edit</span> <span class="flink" onclick="delVar(this);">Delete</span>';
let tpl = '<td>' + vd.name + '</td> \
<td>' + vd.value + '</td> \
<td>' + vd.scopeTxt + '</td> \
<td>' + vd.scopeTargetHtml + '</td> \
<td>' + actionHtml + '</td>';
let tr = vTbl.insertRow(-1);
tr.innerHTML = tpl;
tr.classList.add('stVRow');
tr.setAttribute('x-data-id', vd._id);
})
}
parent.pluginHandler.scripttask.loadSchedule = function(message) {
// cache script names
var nNames = {}, sNames = {};
parent.nodes.forEach(function(n){
nNames[n._id] = n.name;
});
scriptTree.forEach(function(s) {
if (s.type == 'script') sNames[s._id] = s.name;
});
if (message.event.nodeSchedule != null && message.event.nodeId == parent.currentNode._id) {
var nTbl = document.getElementById('nSchTbl');
var rows = nTbl.querySelectorAll('.stNSRow');
if (rows.length) {
rows.forEach(function(r) {
r.parentNode.removeChild(r);
});
}
if (message.event.nodeSchedule.length) {
message.event.nodeSchedule.forEach(function(nh) {
nh = prepSchedule(nh);
let tpl = '<td>' + sNames[nh.scriptId] + '</td> \
<td>' + nh.scheduledBy + '</td> \
<td>' + nh.everyTxt + '</td> \
<td>' + nh.startedTxt + '</td> \
<td>' + nh.endingTxt + '</td> \
<td>' + nh.lastRunTxt + '</td> \
<td>' + nh.nextRunTxt + '</td> \
<td>' + nh.actionTxt + '</td>';
let tr = nTbl.insertRow(-1);
tr.innerHTML = tpl;
tr.classList.add('stNSRow');
tr.setAttribute('x-data-id', nh._id);
});
}
}
var currentScript = document.getElementById('scriptHistory');
var currentScriptId = currentScript.getAttribute('x-data-id');
if (message.event.scriptSchedule != null && message.event.scriptId == currentScriptId) {
var sTbl = document.getElementById('sSchTbl');
var rows = sTbl.querySelectorAll('.stSSRow');
if (rows.length) {
rows.forEach(function(r) {
r.parentNode.removeChild(r);
});
}
if (message.event.scriptSchedule.length) {
message.event.scriptSchedule.forEach(function(nh) {
nh = prepSchedule(nh);
let tpl = '<td>' + nNames[nh.node] + '</td> \
<td>' + nh.scheduledBy + '</td> \
<td>' + nh.everyTxt + '</td> \
<td>' + nh.startedTxt + '</td> \
<td>' + nh.endingTxt + '</td> \
<td>' + nh.lastRunTxt + '</td> \
<td>' + nh.nextRunTxt + '</td> \
<td>' + nh.actionTxt + '</td>';
let tr = sTbl.insertRow(-1);
tr.innerHTML = tpl;
tr.classList.add('stSSRow');
tr.setAttribute('x-data-id', nh._id);
});
}
}
resizeIframe();
}
function prepSchedule(nh) {
nh.everyTxt = nh.interval + ' ';
switch (nh.recur) {
case 'once':
nh.everyTxt = 'Once';
break;
case 'minutes':
nh.everyTxt += 'minute';
break;
case 'hourly':
nh.everyTxt += 'hour';
break;
case 'daily':
nh.everyTxt += 'day';
break;
case 'weekly':
nh.everyTxt += 'week';
break;
case 'monthly':
nh.everyTxt += 'month';
break;
}
if (nh.interval > 1) nh.everyTxt += 's';
if (nh.recur == 'weekly') {
nh.daysOfWeek = nh.daysOfWeek.map(el => Number(el));
nh.everyTxt += ' (';
nh.daysOfWeek.forEach(function(num) {
switch(num) {
case 0: nh.everyTxt += 'S'; break;
case 1: nh.everyTxt += 'M'; break;
case 2: nh.everyTxt += 'T'; break;
case 3: nh.everyTxt += 'W'; break;
case 4: nh.everyTxt += 'R'; break;
case 5: nh.everyTxt += 'F'; break;
case 6: nh.everyTxt += 'S'; break;
}
});
nh.everyTxt += ')';
}
var d = new Date(0); d.setUTCSeconds(nh.startAt);
nh.startedTxt = d.toLocaleString();
d = new Date(0); d.setUTCSeconds(nh.endAt);
nh.endingTxt = d.toLocaleString();
if (nh.endAt == null) nh.endingTxt = 'Never';
if (nh.recur == 'once') nh.endingTxt = 'After first run';
d = new Date(0); d.setUTCSeconds(nh.lastRun);
nh.lastRunTxt = d.toLocaleString();
if (nh.lastRun == null) nh.lastRunTxt = 'Never';
d = new Date(0); d.setUTCSeconds(nh.nextRun);
nh.nextRunTxt = d.toLocaleString();
if (nh.nextRun == null) nh.nextRunTxt = 'Never';
if (nh.nextRun < nh.lastRun) nh.nextRunTxt = 'Running now';
nh.actionTxt = '<span class="delSched" onclick="deleteSchedule(this);">Delete</span>';
return nh;
}
function secondsToHms(d) {
d = Number(d);
if (d == 0) return "immediately";
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return "in " + hDisplay + mDisplay + sDisplay;
}
function isJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
function newVarEx() {
var name = parent.document.getElementById('stvarname').value;
var scope = parent.document.getElementById('stvarscope').value;
var value = parent.document.getElementById('stvarvalue').value;
var scopeTarget = null;
if (scope == 'script') {
var scriptEl = document.querySelectorAll('.liselected');
if (scriptEl.length != 1) return;
var el = scriptEl[0];
scopeTarget = el.getAttribute('x-data-id');
} else if (scope == 'mesh') {
scopeTarget = parent.currentNode.meshid;
} else if (scope == 'node') {
scopeTarget = parent.currentNode._id;
}
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'newVar', name: name, scope: scope, scopeTarget: scopeTarget, value: value, currentNodeId: parent.currentNode._id });
}
function newVar() {
parent.setDialogMode(2, "New Variable", 3, newVarEx, 'Variable Name: <input type="text" id=stvarname /><br />Scope: <select id=stvarscope><option value="global">Global</option><option value="script">Script</option><option value="mesh">Mesh</option><option value="node">Node</option></select><br />Value: <input id="stvarvalue" type="text" />');
parent.focusTextBox('stvarname');
}
function editVarEx() {
var varid = parent.document.getElementById('stvarid').value;
var name = parent.document.getElementById('stvarname').value;
var scope = parent.document.getElementById('stvarscope').value;
var value = parent.document.getElementById('stvarvalue').value;
var scopeTarget = null;
if (scope == 'script') {
var scriptEl = document.querySelectorAll('.liselected');
if (scriptEl.length != 1) return;
var el = scriptEl[0];
scopeTarget = el.getAttribute('x-data-id');
} else if (scope == 'mesh') {
scopeTarget = parent.currentNode.meshid;
} else if (scope == 'node') {
scopeTarget = parent.currentNode._id;
}
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'editVar', id: varid, name: name, scope: scope, scopeTarget: scopeTarget, value: value, currentNodeId: parent.currentNode._id });
}
function editVar(el) {
var vid = el.parentNode.parentNode.getAttribute('x-data-id');
var v = variables.filter(obj => { return obj._id === vid })[0];
var soptHtml = '';
for (const [k, t] of Object.entries(varScopes)) {
soptHtml += '<option value="' + k + '"';
if (v.scope == k) soptHtml += ' selected';
soptHtml += '>' + t + '</option>';
}
parent.setDialogMode(2, "Edit Variable", 3, editVarEx, 'Variable Name: <input type="text" id=stvarname value="' + v.name + '" /><br />Scope: <select id=stvarscope>' + soptHtml + '</select><br />Value: <input id="stvarvalue" type="text" value="' + v.value + '" /><input type="hidden" id="stvarid" value="' + vid + '" />');
parent.focusTextBox('stvarname');
}
function delVarEx() {
var varid = parent.document.getElementById('stvarid').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'deleteVar', id: varid, currentNodeId: parent.currentNode._id });
}
function delVar(el) {
var vid = el.parentNode.parentNode.getAttribute('x-data-id');
var v = variables.filter(obj => { return obj._id === vid })[0];
parent.setDialogMode(2, "Delete Variable", 3, delVarEx, 'Are you sure you want to delete this?<input type="hidden" id="stvarid" value="' + vid + '" /><br />Name: '+ v.name +'<br />Scope: '+ varScopes[v.scope] +'<br />Value: '+ v.value);
}
function renameEx() {
var name = parent.document.getElementById('stfilename').value;
var id = parent.document.getElementById('stid').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'rename', name: name, id: id, currentNodeId: parent.currentNode._id });
}
function goRename() {
var scriptEl = document.querySelectorAll('.liselected');
if (scriptEl.length != 1) return;
var el = scriptEl[0];
var name = el.querySelector('.fname').innerHTML;
var id = el.getAttribute('x-data-id');
parent.setDialogMode(2, "Rename " + name, 3, renameEx, '<input type="text" value="' + name + '" id=stfilename style=width:100% /><input type="hidden" id="stid" value="' + id + '" />');
parent.focusTextBox('stfilename');
}
function newEx() {
var name = parent.document.getElementById('stfilename').value;
var parent_id = parent.document.getElementById('stfolderid').value;
var fileType = parent.document.getElementById('stfiletype').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'new', name: name, parent_id: parent_id, filetype: fileType, currentNodeId: parent.currentNode._id });
}
function goNew() {
var scriptEl = document.querySelectorAll('.liselected');
var folder_id = null;
if (scriptEl.length > 0) {
var el = scriptEl[0];
folder_id = el.getAttribute('x-data-folder');
}
parent.setDialogMode(2, "New Script", 3, newEx, 'Name: <input type="text" value="' + name + '" id=stfilename style=width:100% /><br />Type:<select id="stfiletype"><option value="bash">Bash</option><option value="bat">BAT</option><option value="ps1">PS1</option></select><input type="hidden" id="stfolderid" value="' + folder_id + '" />');
parent.focusTextBox('stfilename');
}
function newFolderEx() {
var name = parent.document.getElementById('stfoldername').value;
var parent_id = parent.document.getElementById('stfolderid').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'newFolder', name: name, parent_id: parent_id });
}
function goNewFolder() {
var scriptEl = document.querySelectorAll('.liselected');
var folder_id = null;
if (scriptEl.length > 0) {
var el = scriptEl[0];
folder_id = el.getAttribute('x-data-folder');
}
parent.setDialogMode(2, "New Folder", 3, newFolderEx, '<input type="text" value="" id=stfoldername style=width:100% /><input type="hidden" id="stfolderid" value="' + folder_id + '" />');
parent.focusTextBox('stfoldername');
}
function goScript(el) {
var xdi = el.getAttribute('x-data-id');
var scriptEls = document.querySelectorAll('.liselected');
parent.putstore('_scripttask_sel_item', xdi);
scriptEls.forEach(function(e) {
e.classList.remove('liselected');
})
el.classList.add('liselected');
Q('scriptHistory').setAttribute('x-data-id', el.getAttribute('x-data-id'));
if (xdi != el.getAttribute('x-data-folder')) {
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'loadScriptHistory', scriptId: xdi });
}
parseVariables();
}
function deleteEx() {
var id = parent.document.getElementById('stdelid').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'delete', id: id });
}
function goDelete() {
var els = document.querySelectorAll('.liselected');
if (els.length == 0) return;
var el = els[0];
var name = el.innerHTML;
var id = el.getAttribute('x-data-id');
parent.setDialogMode(2, "Delete " + name, 3, deleteEx, 'Are you sure? <input type="hidden" id="stdelid" value="' + id + '" />');
}
function deleteScheduleEx() {
var id = parent.document.getElementById('stdelid').value;
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'delete', id: id });
}
function deleteSchedule(el) {
var id = el.parentNode.parentNode.getAttribute('x-data-id');
parent.setDialogMode(2, "Delete Schedule", 3, deleteScheduleEx, 'Are you sure you want to delete this schedule? <input type="hidden" id="stdelid" value="' + id + '" />');
}
function toggleCollapse(el) {
var xdf = el.getAttribute('x-data-path');
var folderEls = document.querySelectorAll('.lifolder, .liscript');
var showHide = null;
folderEls.forEach(function(e){
if (e === el) return;
if (e.getAttribute('x-data-path').indexOf(xdf) !== -1) {
if (e.style.display == 'none') {
if (showHide === null) showHide = '';
} else {
if (showHide === null) showHide = 'none';
}
e.style.display = showHide;
}
});
goScript(el);
}
function handleFileSelect(evt) {
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object
// files is a FileList of File objects. List some properties.
QV('dropBlock', false);
var output = [];
fileUpload(files);
elementDragged = false;
if (dragTimer != null) dragTimer = null;
//document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
function fileUpload(files) {
if (files == null) files = document.getElementById('files').files;
var path = null;
var isSelected = document.querySelectorAll('.liselected');
if (isSelected.length) {
var sel = isSelected[0];
path = sel.getAttribute('x-data-path');
}
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
reader.fileName = f.name;
reader.readAsBinaryString(f);
reader.addEventListener('loadend', function(e, file){
addScript(e.currentTarget.fileName, e.currentTarget.result, path);
});
}
}
var dropZone = document.getElementById('scriptTaskUser');
var dropBlock = document.getElementById('dropBlock');
var dragTimer = null;
function allowDrag(e) {
if (!elementDragged) { // Test that the item being dragged is a valid one
e.dataTransfer.dropEffect = 'copy';
QV('dropBlock', true);
e.preventDefault();
clearTimeout(dragTimer);
dragTimer = setTimeout(function(){ dragCounter = 0; QV('dropBlock', false); }, 100);
}
}
function dropMove(evt) {
const move_id = evt.dataTransfer.getData('text');
const container_id = evt.target.parentNode.getAttribute('x-data-id');
parent.meshserver.send({ action: 'plugin', plugin: 'scripttask', pluginaction: 'move', id: move_id, to: container_id });
}
// file upload events
window.addEventListener('dragenter', function(e) {
dragCounter++;
});
dropZone.addEventListener('dragenter', allowDrag);
dropZone.addEventListener('dragover', allowDrag);
dropZone.addEventListener('dragleave', function(e) {
dragCounter--;
if (dragCounter == 0) {
QV('dropBlock', false);
elementDragged = false;
}
});
dropZone.addEventListener('drop', handleFileSelect);
</script>
</body>
</html>