|
|
<html>
|
|
|
<head>
|
|
|
<include src="common.htm" />
|
|
|
<style src="log.css" />
|
|
|
<script>
|
|
|
const VTable = importModule("vlist.mjs").VTable;
|
|
|
|
|
|
var log, data = [],
|
|
|
payload = $("#payload"),
|
|
|
logmenu = $("#logmenu");
|
|
|
|
|
|
view.minSize = [300, 300];
|
|
|
|
|
|
function recordView(record, isCurrent, isSelected) {
|
|
|
if (!record) return;
|
|
|
var icon = record.icon == "" ? [] : <img src="themepicsingle:${record.icon}" />;
|
|
|
return <tr key={record.key} state-current={isCurrent} state-checked={isSelected}>
|
|
|
<td>{icon}</td>
|
|
|
<td>{record.time}</td>
|
|
|
<td>{record.method}</td>
|
|
|
<td>{record.caption}</td>
|
|
|
</tr>;
|
|
|
}
|
|
|
|
|
|
function init() {
|
|
|
view.loadIcon("themepicsingle:log");
|
|
|
view.caption = _("Log");
|
|
|
updateTranslation();
|
|
|
for (let pic of logmenu.$$("div[pic]")) pic.setupIcon();
|
|
|
}
|
|
|
|
|
|
function showLog(scr) {
|
|
|
if (data.length > 0) log.vtbody?.advanceLast();
|
|
|
if (view.screen != scr) {
|
|
|
var [wx, wy] = view.box("position", "border", "monitor");
|
|
|
var [sx1, sy1] = View.screenBox(view.screen, "frame", "position");
|
|
|
var [sx2, sy2] = View.screenBox(scr, "frame", "position");
|
|
|
view.move(sx2 + wx - sx1, sy2 + wy - sy1, false);
|
|
|
}
|
|
|
view.state = View.WINDOW_SHOWN;
|
|
|
log.focusList();
|
|
|
}
|
|
|
|
|
|
function addEntry(entry) {
|
|
|
var atEnd = data.length == 0 || log.vtbody?.value === data[data.length - 1];
|
|
|
entry.key = data.length + 1;
|
|
|
data.push(entry);
|
|
|
if (view.state == View.WINDOW_SHOWN) {
|
|
|
log.componentUpdate();
|
|
|
if (atEnd) log.vtbody?.advanceLast();
|
|
|
} else {
|
|
|
//log.timer(1s, () => log.componentUpdate());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function updateTranslation() {
|
|
|
translateWindow("span");
|
|
|
}
|
|
|
|
|
|
$("#main").append(<VTable class="log" recordview={recordView} recordset={data} unanimated>
|
|
|
<columns>
|
|
|
<th></th><th></th><th></th><th></th>
|
|
|
</columns>
|
|
|
</VTable>);
|
|
|
|
|
|
log = $(".log");
|
|
|
log.init(20);
|
|
|
log.vtbody.on("currentchange", function(e) {
|
|
|
payload.attr["nosyntax"] = !this.value.json;
|
|
|
payload.loadContent(this.value.text);
|
|
|
payload.scrollTo({
|
|
|
position: [0, 0],
|
|
|
behavior: "instant"
|
|
|
});
|
|
|
})
|
|
|
.on("contextmenu", (e) => {
|
|
|
logmenu.$("#mcopy").state.disabled = data.length == 0 || log.vtbody.value == null;
|
|
|
logmenu.$("#mclear").state.disabled = data.length == 0;
|
|
|
e.source = logmenu;
|
|
|
return true;
|
|
|
});
|
|
|
|
|
|
setMenuListener(logmenu, function() {
|
|
|
switch (this.id) {
|
|
|
case "mcopy":
|
|
|
Clipboard.writeText(log.vtbody.value?.original);
|
|
|
break;
|
|
|
case "mclear":
|
|
|
data.length = 0;
|
|
|
log.componentUpdate();
|
|
|
payload.value = "";
|
|
|
break;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
document.on("closerequest", function(e){
|
|
|
e.preventDefault();
|
|
|
view.state = View.WINDOW_HIDDEN;
|
|
|
}).on("keydown", (e) => {
|
|
|
if (e.keyCode == Event.VK_ESCAPE || (e.ctrlKey && e.keyCode == Event.VK_W)) view.close();
|
|
|
});
|
|
|
|
|
|
view.on("activate", (e) => {
|
|
|
let isActive = e.reason !== 0;
|
|
|
if (isActive && log) log.componentUpdate();
|
|
|
})
|
|
|
</script>
|
|
|
</head>
|
|
|
<body>
|
|
|
<frameset rows="180dip, *">
|
|
|
<div id="main"></div>
|
|
|
<splitter/>
|
|
|
<div id="detail">
|
|
|
<plaintext id="payload" type="application/json" readonly></plaintext>
|
|
|
</div>
|
|
|
</frameset>
|
|
|
<menu id="logmenu" class="context custom">
|
|
|
<li id="mcopy"><div pic="copy"></div><span>Copy to сlipboard</span></li>
|
|
|
<li id="mclear"><div pic="delete"></div><span>Clear</span></li>
|
|
|
</menu>
|
|
|
</body>
|
|
|
</html> |