Files
cmd-palette/cmd.html
T

91 lines
3.6 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>cmd</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; background: #0f1117; color: #e0e0e0; font-family: monospace; }
body { padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.cmd-row { display: flex; gap: 8px; align-items: flex-start; }
.cmd-text { flex: 1; background: #1a1d27; color: #7ec8e3; border: 1px solid #2a2d37;
border-radius: 6px; padding: 10px 12px; font-size: 0.78rem; font-family: monospace;
white-space: pre-wrap; word-break: break-all; cursor: default; user-select: text; }
.cmd-copy { padding: 6px 10px; background: #2a2d37; color: #aaa; border: 1px solid #3a3d47;
border-radius: 4px; font-family: monospace; font-size: 0.75rem; cursor: pointer;
white-space: nowrap; flex-shrink: 0; }
.cmd-copy:hover { background: #3a3d47; color: #e0e0e0; }
.cmd-copy.ok { color: #22c55e; }
</style>
</head>
<body>
<div id="status-bar" style="font-size:0.7rem;color:#444;margin-bottom:2px">refreshing in 5s</div>
<div id="loaded-ts" style="font-size:0.68rem;color:#555;margin-bottom:6px">loaded: —</div>
<div id="commands"></div>
<script>
/* COMMANDS_START */
var _ts = "";
var _cmds = [
"sudo curl -s -u \"admin:Git.jhestyr.net123\" \"https://git.jhestyr.net/api/v1/repos/admin/istrain/raw/sdr/software/analyzer/server.js?ref=e844af2\" -o /mnt/tank/apps/istrain-analyzer/server.js && sudo docker restart istrain-analyzer-1 && echo \"analyzer ok\"",
"echo \"[]\" | sudo tee /mnt/tank/apps/istrain/data/train_events.json && echo \"cleared\""
];
/* COMMANDS_END */
function render(cmds) {
const el = document.getElementById('commands');
el.innerHTML = '';
cmds.forEach(cmd => {
const row = document.createElement('div');
row.className = 'cmd-row';
const text = document.createElement('div');
text.className = 'cmd-text';
text.textContent = cmd;
const btn = document.createElement('button');
btn.className = 'cmd-copy';
btn.textContent = 'copy';
btn.onclick = () => {
navigator.clipboard.writeText(cmd).then(() => {
btn.textContent = 'ok'; btn.classList.add('ok');
setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('ok'); }, 1500);
});
};
row.appendChild(text);
row.appendChild(btn);
el.appendChild(row);
});
}
function timeAgo(tsStr) {
if (!tsStr) return '';
const d = new Date(tsStr.replace(' ', 'T'));
if (isNaN(d)) return '';
const secs = Math.floor((Date.now() - d) / 1000);
if (secs < 60) return secs + 's ago';
if (secs < 3600) return Math.floor(secs / 60) + 'm ago';
return Math.floor(secs / 3600) + 'h ' + Math.floor((secs % 3600) / 60) + 'm ago';
}
function updateTs(ts) {
const ago = timeAgo(ts);
document.getElementById('loaded-ts').textContent = 'loaded: ' + (ts || '—') + (ago ? ' · ' + ago : '');
}
render(_cmds);
updateTs(_ts);
let countdown = 5;
let _currentTs = _ts;
const bar = document.getElementById('status-bar');
setInterval(() => {
countdown--;
updateTs(_currentTs);
bar.textContent = countdown > 0 ? 'refreshing in ' + countdown + 's' : 'refreshing...';
if (countdown <= 0) {
countdown = 5;
fetch(location.href + '?t=' + Date.now()).then(r => r.text()).then(html => {
const m = html.match(/\/\* COMMANDS_START \*\/[\s\S]*?var _cmds = (\[[\s\S]*?\]);\s*\/\* COMMANDS_END \*\//);
const tm = html.match(/var _ts = "([^"]*)";/);
if (m) render(JSON.parse(m[1]));
if (tm) { _currentTs = tm[1]; updateTs(_currentTs); }
}).catch(() => {});
}
}, 1000);
</script>
</body>
</html>