New Design
This commit is contained in:
637
html/index.html
637
html/index.html
@@ -4,263 +4,442 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Pixelserver Interface</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1, viewport-fit=auto"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
|
||||
<style>
|
||||
/* --- Base Styles & CSS Variables --- */
|
||||
:root {
|
||||
--bg-color: #f7fafc;
|
||||
--card-bg-color: #ffffff;
|
||||
--text-color: #2d3748;
|
||||
--header-color: #1a202c;
|
||||
--muted-text-color: #718096;
|
||||
--border-color: #e2e8f0;
|
||||
--input-bg-color: #f7fafc;
|
||||
--button-primary-bg: #3b82f6;
|
||||
--button-primary-hover-bg: #2563eb;
|
||||
--button-secondary-bg: #6b7280;
|
||||
--button-secondary-hover-bg: #4b5563;
|
||||
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-color: #111827;
|
||||
--card-bg-color: #1f2937;
|
||||
--text-color: #d1d5db;
|
||||
--header-color: #ffffff;
|
||||
--muted-text-color: #9ca3af;
|
||||
--border-color: #374151;
|
||||
--input-bg-color: #374151;
|
||||
--button-secondary-bg: #4b5563;
|
||||
--button-secondary-hover-bg: #374151;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
padding: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* --- Layout --- */
|
||||
.main-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: grid;
|
||||
grid-gap: 1rem;
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1.5rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media only screen {
|
||||
.main {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 800px) {
|
||||
.main {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1111px) {
|
||||
.main {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.col {
|
||||
background-color: var(--card-bg-color);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.5rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--border-color);
|
||||
flex: 1 1 320px; /* Flex-grow, flex-shrink, basis */
|
||||
min-width: 300px;
|
||||
/*max-width: 350px;*/
|
||||
}
|
||||
|
||||
.just, .just-col {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.just > * {
|
||||
flex: 1;
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.just-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.just-col > * {
|
||||
flex: 1;
|
||||
margin: 2px 1rem;
|
||||
/* --- Typography --- */
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: var(--header-color);
|
||||
margin-bottom: 2rem;
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
|
||||
h1 i {
|
||||
font-style: normal;
|
||||
color: var(--button-primary-bg);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
color: var(--header-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: var(--header-color);
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
/*margin-top: 0.5rem;*/
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* --- Forms & Inputs --- */
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
flex-grow: 1; /* Allow form to grow */
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
select {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--input-bg-color);
|
||||
color: var(--text-color);
|
||||
box-sizing: border-box;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
/* Hide original checkbox */
|
||||
display: none;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--button-primary-bg);
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: var(--button-primary-hover-bg);
|
||||
}
|
||||
|
||||
button.startstop {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
background-color: var(--button-secondary-bg);
|
||||
}
|
||||
|
||||
button.startstop:hover {
|
||||
background-color: var(--button-secondary-hover-bg);
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 300px;
|
||||
background-color: var(--input-bg-color);
|
||||
color: var(--text-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.5rem;
|
||||
font-family: monospace;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* --- Helper classes --- */
|
||||
.just-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.just-col label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#gammaform span {
|
||||
display: inline-block;
|
||||
width: 4rem;
|
||||
flex-basis: 4rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.logging {
|
||||
max-width: 500px;
|
||||
/* --- Button Checkbox Styles --- */
|
||||
.checkbox-button {
|
||||
display: block;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 5px solid var(--border-color);
|
||||
border-radius: 0.375rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background-color: var(--card-bg-color);
|
||||
color: var(--text-color);
|
||||
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.options {
|
||||
max-width: 350px;
|
||||
#flipform input[type="checkbox"]:checked + .checkbox-button {
|
||||
/*background-color: var(--button-primary-bg);*/
|
||||
/*color: white;*/
|
||||
border-color: var(--button-primary-bg);
|
||||
border-width: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="text-align: center;">Andreas <i>production-ready</i> Interface</h1>
|
||||
<div class="main">
|
||||
<div class="col">
|
||||
<h2><label for="list">Kommando:</label></h2>
|
||||
<form id="in" class="" onSubmit="return request()">
|
||||
<select id="list"></select>
|
||||
<input id="args"/>
|
||||
<button id="execute">Ausführen</button>
|
||||
</form>
|
||||
<div class="main-container">
|
||||
<h1>Andreas <i>production-ready</i> Interface</h1>
|
||||
<div class="main">
|
||||
<div class="col">
|
||||
<h2>Kommando</h2>
|
||||
<form id="in" onSubmit="return request()">
|
||||
<select id="list"></select>
|
||||
<input id="args" type="text" placeholder="Argumente..."/>
|
||||
<button>Ausführen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h2><label for="brightness">Intensität:</label></h2>
|
||||
<form id="brightnessform" class="just" onSubmit="return setbrightness()">
|
||||
<input id="brightness" value="1.0"><br/>
|
||||
<button id="sendbrightness">Setzen</button>
|
||||
</form>
|
||||
<div class="col">
|
||||
<h2>Intensität</h2>
|
||||
<form onSubmit="return setbrightness()">
|
||||
<input id="brightness" value="1.0" type="number" step="0.1"><br/>
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h2>Gamma</h2>
|
||||
<form id="gammaform" class="just-col" onSubmit="return setgamma()">
|
||||
<label><span>Rot: </span><input id="gammar" value="2.8" type="number" step="0.05"/></label>
|
||||
<label><span>Grün: </span><input id="gammag" value="2.65" type="number" step="0.05"/></label>
|
||||
<label><span>Blau: </span><input id="gammab" value="2.65" type="number" step="0.05"/></label>
|
||||
<label><span>Weiß: </span><input id="gammaw" value="2.65" type="number" step="0.05"/></label>
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h2>Flip</h2>
|
||||
<form id="flipform" onSubmit="return setFlip()">
|
||||
<label>
|
||||
<input id="flipx" type="checkbox"/>
|
||||
<span class="checkbox-button">Flip X</span>
|
||||
</label>
|
||||
<label>
|
||||
<input id="flipy" type="checkbox"/>
|
||||
<span class="checkbox-button">Flip Y</span>
|
||||
</label>
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h2>Filter</h2>
|
||||
<form onSubmit="return setFilter()">
|
||||
<h3><label for="filtername">Filterimage:</label></h3>
|
||||
<input id="filtername" value="test" type="text">
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
<form onSubmit="return setFilterExpr()">
|
||||
<h3><label for="filterexpr">Filter expression:</label></h3>
|
||||
<input id="filterexpr" value="0.5+0.25*sin(x/3+t)" type="text">
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h2>Crash Log
|
||||
<button id="crashlogbtn" class="startstop" type="button" onclick="return enableCrashLog()">start</button>
|
||||
</h2>
|
||||
<textarea readonly id="crashlogs" style="display: none;"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<h2>Log
|
||||
<button id="logbtn" class="startstop" type="button" onclick="return enableLog()">start</button>
|
||||
</h2>
|
||||
<textarea readonly id="logs" style="display: none;"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options col">
|
||||
<h2>Gamma:</h2>
|
||||
<form id="gammaform" class="just-col" onSubmit="return setgamma()">
|
||||
<label><span>Rot: </span><input id="gammar" value="2.8"/></label><br/>
|
||||
<label><span>Grün: </span><input id="gammag" value="2.65"/></label><br/>
|
||||
<label><span>Blau: </span><input id="gammab" value="2.65"/></label><br/>
|
||||
<label><span>Weiß: </span><input id="gammaw" value="2.65"/></label><br/>
|
||||
<button id="sendgamma">Setzen</button>
|
||||
</form>
|
||||
|
||||
<h2>Flip:</h2>
|
||||
<form id="flipform" class="just" onSubmit="return setFlip()">
|
||||
<label><input id="flipx" type="checkbox"/> Flip X</label>
|
||||
<label><input id="flipy" type="checkbox"/> Flip Y</label>
|
||||
<button id="sendflip">Setzen</button>
|
||||
</form>
|
||||
|
||||
<h2><label for="filtername">Filterimage:</label></h2>
|
||||
<form id="filterform" class="just" onSubmit="return setFilter()">
|
||||
<input id="filtername" value="test">
|
||||
<button id="filterflip">Setzen</button>
|
||||
</form>
|
||||
|
||||
<h2><label for="filterexpr">Filter expression:</label></h2>
|
||||
<form id="filterexprform" class="just" onSubmit="return setFilterExpr()">
|
||||
<input id="filterexpr" value="0.5+0.25*sin(x/3+t)">
|
||||
<button>Setzen</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="logging col">
|
||||
<h2>Crash Log:
|
||||
<button id="crashlogbtn" type="button" onclick="return enableCrashLog()">start</button>
|
||||
</h2>
|
||||
<textarea readonly id="crashlogs" style="width: 500px; height: 300px; display: none;"></textarea>
|
||||
|
||||
<h2>Log:
|
||||
<button id="logbtn" type="button" onclick="return enableLog()">start</button>
|
||||
</h2>
|
||||
<textarea readonly id="logs" style="width: 500px; height: 300px; display: none;"></textarea>
|
||||
</div>
|
||||
<script>
|
||||
function getRaw(url, callback) {
|
||||
const xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function () {
|
||||
if (this.readyState === 4 && this.status === 200)
|
||||
if (callback) callback(xhttp.responseText);
|
||||
};
|
||||
xhttp.open("GET", url, true);
|
||||
xhttp.send();
|
||||
}
|
||||
|
||||
function getJSON(url, callback) {
|
||||
getRaw(url, function (text) {
|
||||
callback(JSON.parse(text));
|
||||
});
|
||||
}
|
||||
|
||||
function post(url, data) {
|
||||
const formdata = new FormData();
|
||||
for (const key in data)
|
||||
formdata.append(key, data[key]);
|
||||
|
||||
const xhttp = new XMLHttpRequest();
|
||||
// xhttp.onreadystatechange = function () {
|
||||
// if (this.readyState === 4 && this.status === 200) {}
|
||||
// };
|
||||
xhttp.open("POST", url, true);
|
||||
xhttp.send(formdata);
|
||||
}
|
||||
|
||||
function populateForm(parameters) {
|
||||
const list = document.getElementById("list");
|
||||
|
||||
for (const i in parameters) {
|
||||
const app = parameters[i];
|
||||
const name = app["name"];
|
||||
const guiname = app["guiname"];
|
||||
const persistent = app["persistent"];
|
||||
const element = document.createElement("option");
|
||||
element.value = name;
|
||||
element.innerHTML = guiname;
|
||||
element.dataset.persistent = persistent;
|
||||
list.appendChild(element);
|
||||
}
|
||||
|
||||
list.onchange = function () {
|
||||
const app = document.getElementById('list');
|
||||
const persistent = app.options[app.selectedIndex].dataset.persistent;
|
||||
if (persistent == "true") {
|
||||
document.getElementById("args").style.display = "none";
|
||||
} else {
|
||||
document.getElementById("args").style.display = "inline";
|
||||
}
|
||||
};
|
||||
list.onchange();
|
||||
document.getElementById("container").style.display = "block";
|
||||
}
|
||||
|
||||
function request() {
|
||||
let app = document.getElementById('list');
|
||||
let val = app.options[app.selectedIndex].value;
|
||||
let parameter = document.getElementById('args').value;
|
||||
post("/apps/start/" + val, {"param": parameter});
|
||||
return false;
|
||||
}
|
||||
|
||||
function setgamma() {
|
||||
const r = document.getElementById('gammar').value;
|
||||
const g = document.getElementById('gammag').value;
|
||||
const b = document.getElementById('gammab').value;
|
||||
const w = document.getElementById('gammaw').value;
|
||||
getRaw(`/setgamma/${r}/${g}/${b}/${w}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setbrightness() {
|
||||
const i = document.getElementById('brightness').value;
|
||||
getRaw("/setbrightness/" + i);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFlip() {
|
||||
const x = document.getElementById('flipx').checked;
|
||||
const y = document.getElementById('flipy').checked;
|
||||
getRaw("/filter/flipx/" + x);
|
||||
getRaw("/filter/flipy/" + y);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFilter() {
|
||||
const i = document.getElementById('filtername').value;
|
||||
getRaw("/filter/img/" + i);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFilterExpr() {
|
||||
const expr = document.getElementById('filterexpr').value;
|
||||
post("/filter/expr/", {"expr": expr});
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateLog() {
|
||||
getRaw("/apps/log", function (text) {
|
||||
document.getElementById('logs').value = text;
|
||||
});
|
||||
}
|
||||
|
||||
function updateCrashLog() {
|
||||
getRaw("/apps/crashlog", function (text) {
|
||||
document.getElementById('crashlogs').value = text;
|
||||
});
|
||||
}
|
||||
|
||||
function enableCrashLog() {
|
||||
document.getElementById("crashlogbtn").remove();
|
||||
document.getElementById("crashlogs").style.display = "block";
|
||||
updateCrashLog();
|
||||
setInterval(updateCrashLog, 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
function enableLog() {
|
||||
document.getElementById("logbtn").remove();
|
||||
document.getElementById("logs").style.display = "block";
|
||||
updateLog();
|
||||
setInterval(updateLog, 1000);
|
||||
return false;
|
||||
}
|
||||
|
||||
getJSON("/apps/list", populateForm);
|
||||
</script>
|
||||
</div>
|
||||
<script>
|
||||
function getRaw(url, callback) {
|
||||
const xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function () {
|
||||
if (this.readyState === 4 && this.status === 200)
|
||||
if (callback) callback(xhttp.responseText);
|
||||
};
|
||||
xhttp.open("GET", url, true);
|
||||
xhttp.send();
|
||||
}
|
||||
|
||||
function getJSON(url, callback) {
|
||||
getRaw(url, function (text) {
|
||||
callback(JSON.parse(text));
|
||||
});
|
||||
}
|
||||
|
||||
function post(url, data) {
|
||||
const formdata = new FormData();
|
||||
for (const key in data)
|
||||
formdata.append(key, data[key]);
|
||||
|
||||
const xhttp = new XMLHttpRequest();
|
||||
// xhttp.onreadystatechange = function () {
|
||||
// if (this.readyState === 4 && this.status === 200) {}
|
||||
// };
|
||||
xhttp.open("POST", url, true);
|
||||
xhttp.send(formdata);
|
||||
}
|
||||
|
||||
function populateForm(parameters) {
|
||||
const list = document.getElementById("list");
|
||||
|
||||
for (const i in parameters) {
|
||||
const app = parameters[i];
|
||||
const name = app["name"];
|
||||
const guiname = app["guiname"];
|
||||
const persistent = app["persistent"];
|
||||
const element = document.createElement("option");
|
||||
element.value = name;
|
||||
element.innerHTML = guiname;
|
||||
element.dataset.persistent = persistent;
|
||||
list.appendChild(element);
|
||||
}
|
||||
|
||||
list.onchange = function () {
|
||||
const app = document.getElementById('list');
|
||||
const persistent = app.options[app.selectedIndex].dataset.persistent;
|
||||
if (persistent == "true") {
|
||||
document.getElementById("args").style.display = "none";
|
||||
} else {
|
||||
document.getElementById("args").style.display = "inline";
|
||||
}
|
||||
};
|
||||
list.onchange();
|
||||
}
|
||||
|
||||
function request() {
|
||||
let app = document.getElementById('list');
|
||||
let val = app.options[app.selectedIndex].value;
|
||||
let parameter = document.getElementById('args').value;
|
||||
post("/apps/start/" + val, {"param": parameter});
|
||||
return false;
|
||||
}
|
||||
|
||||
function setgamma() {
|
||||
const r = document.getElementById('gammar').value;
|
||||
const g = document.getElementById('gammag').value;
|
||||
const b = document.getElementById('gammab').value;
|
||||
const w = document.getElementById('gammaw').value;
|
||||
getRaw(`/setgamma/${r}/${g}/${b}/${w}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setbrightness() {
|
||||
const i = document.getElementById('brightness').value;
|
||||
getRaw("/setbrightness/" + i);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFlip() {
|
||||
const x = document.getElementById('flipx').checked;
|
||||
const y = document.getElementById('flipy').checked;
|
||||
getRaw("/filter/flipx/" + x);
|
||||
getRaw("/filter/flipy/" + y);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFilter() {
|
||||
const i = document.getElementById('filtername').value;
|
||||
getRaw("/filter/img/" + i);
|
||||
return false;
|
||||
}
|
||||
|
||||
function setFilterExpr() {
|
||||
const expr = document.getElementById('filterexpr').value;
|
||||
post("/filter/expr/", {"expr": expr});
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateLog() {
|
||||
getRaw("/apps/log", function (text) {
|
||||
document.getElementById('logs').value = text;
|
||||
});
|
||||
}
|
||||
|
||||
function updateCrashLog() {
|
||||
getRaw("/apps/crashlog", function (text) {
|
||||
document.getElementById('crashlogs').value = text;
|
||||
});
|
||||
}
|
||||
|
||||
function enableCrashLog() {
|
||||
const logArea = document.getElementById('crashlogs');
|
||||
const btn = document.getElementById('crashlogbtn');
|
||||
const isHidden = logArea.style.display === 'none';
|
||||
logArea.style.display = isHidden ? 'block' : 'none';
|
||||
btn.textContent = isHidden ? 'stop' : 'start';
|
||||
|
||||
clearInterval(window.crash_interval);
|
||||
if (isHidden) {
|
||||
updateCrashLog();
|
||||
window.crash_interval = setInterval(updateCrashLog, 1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function enableLog() {
|
||||
const logArea = document.getElementById('logs');
|
||||
const btn = document.getElementById('logbtn');
|
||||
const isHidden = logArea.style.display === 'none';
|
||||
logArea.style.display = isHidden ? 'block' : 'none';
|
||||
btn.textContent = isHidden ? 'stop' : 'start';
|
||||
|
||||
clearInterval(window.log_interval);
|
||||
if (isHidden) {
|
||||
updateLog();
|
||||
window.log_interval = setInterval(updateLog, 1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getJSON("/apps/list", populateForm);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user