mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-29 15:45:13 +08:00
update 2026-09-26 11:07:27
This commit is contained in:
1 parent
7b88b273d0
commit
97ae9f68da
4898 files changed
-1712274
No files matched your search
@@ -1,151 +0,0 @@
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#tasks_detail_container {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: #0008;
|
||||
}
|
||||
#tasks_dialog {
|
||||
position: absolute;
|
||||
width: 770px;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: #000;
|
||||
|
||||
border-radius: 10px;
|
||||
box-shadow: 2px 2px 6px #000a;
|
||||
padding: 20px;
|
||||
|
||||
color: white;
|
||||
}
|
||||
.dialog-title-bar {
|
||||
margin-top: -10px;
|
||||
margin-right: -10px;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
.dialog-title-bar .dialog-title {
|
||||
word-break: break-all;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dialog-content {
|
||||
position: relative;
|
||||
max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
margin-right: -10px;
|
||||
}
|
||||
.dialog-icons {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.dialog-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
color: black;
|
||||
border-radius: 50%;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
margin-left: 10px;
|
||||
line-height: 1;
|
||||
font-family: sans-serif;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dialog-icon.dialog-icon-min {
|
||||
background-color: darkorange;
|
||||
}
|
||||
.dialog-icon.dialog-icon-close {
|
||||
background-color: #ff5f56;
|
||||
}
|
||||
.dialog-icons:hover .dialog-icon.dialog-icon-min:before {
|
||||
content: "_";
|
||||
}
|
||||
.dialog-icons:hover .dialog-icon.dialog-icon-close:before {
|
||||
content: "X";
|
||||
}
|
||||
|
||||
.tasks_stopped .dialog-icon.dialog-icon-close {
|
||||
background-color: #27c840;
|
||||
}
|
||||
.tasks_stopped #tasks_dialog, .tasks_unknown #tasks_dialog {
|
||||
padding: 19px;
|
||||
border: 1px #27c840 solid;
|
||||
|
||||
animation: border-blink 1s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.tasks_failed #tasks_dialog {
|
||||
border-color: #ff0000;
|
||||
}
|
||||
|
||||
.tasks_failed .dialog-icon.dialog-icon-close {
|
||||
background-color: #ff0000;
|
||||
}
|
||||
|
||||
.tasks_unknown #tasks_dialog {
|
||||
border-color: darkorange;
|
||||
}
|
||||
|
||||
#tasks_result_mask {
|
||||
display: none;
|
||||
background-color: #000d;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.tasks_stopped #tasks_result_mask {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tasks_result_success, .tasks_stopped.tasks_failed .tasks_result_success, .tasks_result_failed {
|
||||
display: none;
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
.tasks_stopped .tasks_result_success {
|
||||
display: initial;
|
||||
color: #27c840;
|
||||
}
|
||||
|
||||
.tasks_failed .tasks_result_failed {
|
||||
display: initial;
|
||||
color: darkorange;
|
||||
}
|
||||
|
||||
@keyframes border-blink { 50% { border-color:#fff ; } }
|
||||
@@ -1,246 +0,0 @@
|
||||
|
||||
(function(){
|
||||
const taskd={};
|
||||
const $gettext = function(str) {
|
||||
return taskd.i18n[str] || str;
|
||||
};
|
||||
const retryPromise = function(fn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const retry = function() {
|
||||
fn(resolve, reject, retry);
|
||||
};
|
||||
retry();
|
||||
});
|
||||
};
|
||||
const retry403XHR = function(url, method, responseType) {
|
||||
return retryPromise((resolve, reject, retry) => {
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.onerror = reject;
|
||||
oReq.open(method || 'GET', url, true);
|
||||
if (responseType) {
|
||||
oReq.responseType = responseType;
|
||||
}
|
||||
oReq.onload = function (oEvent) {
|
||||
if (oReq.status == 403) {
|
||||
alert($gettext("Lost login status"));
|
||||
location.href = location.href.replace(/#.*$/,'');
|
||||
} else if (oReq.status >= 400) {
|
||||
reject(oEvent);
|
||||
} else {
|
||||
resolve(oReq);
|
||||
}
|
||||
};
|
||||
if (method=='POST') {
|
||||
oReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
oReq.send(method=='POST'?("token="+taskd.csrfToken):null);
|
||||
});
|
||||
};
|
||||
const request = function(url, method) {
|
||||
return retry403XHR(url, method).then(oReq => oReq.responseText);
|
||||
};
|
||||
const getBin = function(url) {
|
||||
return retry403XHR(url, null, "arraybuffer").then(oReq => {return {status: oReq.status, buffer: new Uint8Array(oReq.response)}});
|
||||
};
|
||||
const getTaskDetail = function(task_id) {
|
||||
return request("/cgi-bin/luci/admin/system/tasks/status?task_id="+task_id).then(data=>JSON.parse(data));
|
||||
};
|
||||
const create_dialog = function(cfg) {
|
||||
const container = document.createElement('div');
|
||||
container.id = "tasks_detail_container";
|
||||
container.innerHTML = taskd.dialog_template;
|
||||
|
||||
document.body.appendChild(container);
|
||||
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
|
||||
title_view.innerText = cfg.title;
|
||||
|
||||
const term = new Terminal({convertEol: cfg.convertEol||false});
|
||||
if (cfg.nohide) {
|
||||
container.querySelector(".dialog-icon-min").hidden = true;
|
||||
} else {
|
||||
container.querySelector(".dialog-icon-min").onclick = function(){
|
||||
container.hidden=true;
|
||||
term.dispose();
|
||||
document.body.removeChild(container);
|
||||
cfg.onhide && cfg.onhide();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
const tasks_result_mask = container.querySelector("#tasks_result_mask");
|
||||
if (taskd.show_mask_on_stopped) {
|
||||
tasks_result_mask.onclick = function(){
|
||||
tasks_result_mask.hidden=true;
|
||||
};
|
||||
} else {
|
||||
tasks_result_mask.hidden=true;
|
||||
}
|
||||
term.open(document.getElementById("tasks_xterm_log"));
|
||||
|
||||
return {term,container};
|
||||
};
|
||||
const show_log_txt = function(title, content, onclose) {
|
||||
const dialog = create_dialog({title, convertEol:true, onhine:onclose});
|
||||
const container = dialog.container;
|
||||
const term = dialog.term;
|
||||
container.querySelector(".dialog-icon-close").hidden = true;
|
||||
term.write(content);
|
||||
};
|
||||
const show_log = function(task_id, nohide, onExit) {
|
||||
let showing = true;
|
||||
let running = true;
|
||||
const dialog = create_dialog({title:task_id, nohide, onhide:function(){showing=false;}});
|
||||
const container = dialog.container;
|
||||
const term = dialog.term;
|
||||
|
||||
const title_view = container.querySelector(".dialog-title-bar .dialog-title");
|
||||
container.querySelector(".dialog-icon-close").onclick = function(){
|
||||
if (!running || confirm($gettext("Stop running task?"))) {
|
||||
running=false;
|
||||
showing=false;
|
||||
del_task(task_id).then(()=>{
|
||||
location.href = location.href.replace(/#.*$/,'');
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const checkTask = function() {
|
||||
if (!showing) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
return getTaskDetail(task_id).then(data=>{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
running = data.running;
|
||||
let title = task_id;
|
||||
if (!data.running && data.stop) {
|
||||
title += " (" + (data.exit_code?$gettext("Failed at:"):$gettext("Finished at:")) + " " + new Date(data.stop * 1000).toLocaleString() + ")";
|
||||
}
|
||||
title += " > " + (data.command || '');
|
||||
title_view.title = title;
|
||||
title_view.innerText = title;
|
||||
if (!data.running) {
|
||||
container.classList.add('tasks_stopped');
|
||||
if (data.exit_code) {
|
||||
container.classList.add('tasks_failed');
|
||||
}
|
||||
onExit && onExit(data.exit_code);
|
||||
}
|
||||
// last pull
|
||||
return showing;
|
||||
});
|
||||
};
|
||||
let logoffset = 0;
|
||||
const pulllog = function(check) {
|
||||
let starter = Promise.resolve(showing);
|
||||
if (check) {
|
||||
starter = checkTask();
|
||||
}
|
||||
starter.then(again => {
|
||||
if (again)
|
||||
return getBin("/cgi-bin/luci/admin/system/tasks/log?task_id="+task_id+"&offset="+logoffset);
|
||||
else
|
||||
return {status: 204};
|
||||
}).then(function(res){
|
||||
if (!showing) {
|
||||
return false;
|
||||
}
|
||||
switch(res.status){
|
||||
case 205:
|
||||
term.reset();
|
||||
logoffset = 0;
|
||||
return running;
|
||||
break;
|
||||
case 204:
|
||||
return running && checkTask();
|
||||
break;
|
||||
case 200:
|
||||
logoffset += res.buffer.byteLength;
|
||||
term.write(res.buffer);
|
||||
return running;
|
||||
break;
|
||||
}
|
||||
}).then(again => {
|
||||
if (again) {
|
||||
setTimeout(pulllog, 0);
|
||||
}
|
||||
}).catch(err => {
|
||||
if (showing) {
|
||||
console.error(err);
|
||||
if (err.target) {
|
||||
if (err.target.status == 0 || err.target.status == 502) {
|
||||
title_view.innerText = task_id + ' (' + $gettext("Fetch log failed, retrying...") + ')';
|
||||
} else if (err.target.status == 403 || err.target.status == 404) {
|
||||
title_view.innerText = task_id + ' (' + $gettext(err.target.status == 403?"Lost login status":"Task does not exist or has been deleted") + ')';
|
||||
container.querySelector(".dialog-icon-close").hidden = true;
|
||||
container.classList.add('tasks_unknown');
|
||||
return
|
||||
}
|
||||
}
|
||||
setTimeout(()=>pulllog(true), 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
pulllog(true);
|
||||
};
|
||||
const del_task = function(task_id) {
|
||||
return request("/cgi-bin/luci/admin/system/tasks/stop?task_id="+task_id, "POST");
|
||||
};
|
||||
taskd.show_log = show_log;
|
||||
taskd.remove = del_task;
|
||||
taskd.show_log_txt = show_log_txt;
|
||||
window.taskd=taskd;
|
||||
})();
|
||||
|
||||
(function(){
|
||||
// compat
|
||||
if (typeof(window.findParent) !== 'function') {
|
||||
const elem = function(e) {
|
||||
return (e != null && typeof(e) == 'object' && 'nodeType' in e);
|
||||
};
|
||||
const matches = function(node, selector) {
|
||||
var m = elem(node) ? node.matches || node.msMatchesSelector : null;
|
||||
return m ? m.call(node, selector) : false;
|
||||
};
|
||||
window.findParent = function (node, selector) {
|
||||
if (elem(node) && node.closest)
|
||||
return node.closest(selector);
|
||||
|
||||
while (elem(node))
|
||||
if (matches(node, selector))
|
||||
return node;
|
||||
else
|
||||
node = node.parentNode;
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
if (typeof(window.cbi_submit) !== 'function') {
|
||||
const makeHidden = function(name) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = name;
|
||||
return input;
|
||||
};
|
||||
window.cbi_submit = function(elem, name, value, action) {
|
||||
var form = elem.form || findParent(elem, 'form');
|
||||
|
||||
if (!form)
|
||||
return false;
|
||||
|
||||
if (action)
|
||||
form.action = action;
|
||||
|
||||
if (name) {
|
||||
var hidden = form.querySelector('input[type="hidden"][name="%s"]'.format(name)) ||
|
||||
makeHidden(name);
|
||||
|
||||
hidden.value = value || '1';
|
||||
form.appendChild(hidden);
|
||||
}
|
||||
|
||||
form.submit();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user