mirror of
https://github.com/cesanta/mongoose.git
synced 2026-11-13 17:00:19 +00:00
Dash updates
This commit is contained in:
1 parent
c5b74babab
commit
59f9b36ddd
8 files changed
+1114
-824
No files matched your search
+34
-6
@@ -7,7 +7,7 @@
|
||||
function Rpc(url, onev) {
|
||||
let ws, id = 1, oncall, q = [];
|
||||
const pending = new Map();
|
||||
const realsend = s => { ws.send(s); on('send', s); };
|
||||
const realsend = s => { ws.send(s); onev && onev('send', s); };
|
||||
const fail = e => { for (const p of pending.values()) p[1](e || 'disconnected'); pending.clear(); };
|
||||
const send = x => ws && ws.readyState === 1
|
||||
? realsend(JSON.stringify(x))
|
||||
@@ -61,7 +61,7 @@
|
||||
const isMock = !!window.frameElement || (window !== window.top);
|
||||
const settings = {data: {}, edits: {}, debug: true};
|
||||
const userhandlers = {}; // User event handlers
|
||||
const status = { online: true, username: '', userlevel: 0, lastseen: '' };
|
||||
const status = { online: true, username: '', userlevel: 0, lastseen: '', initialized: false };
|
||||
const rpc = isMock ? null : Rpc('api/websocket', function (evname, args) {
|
||||
if (evname == 'open') status.online = true, rescan();
|
||||
if (evname == 'close') status.online = false, rescan();
|
||||
@@ -152,8 +152,15 @@
|
||||
el.classList.toggle('error', false);
|
||||
}
|
||||
if (!el.bound) el.addEventListener("input", ev => edit(el, key, el.type == 'checkbox' ? ev.target.checked : ev.target.value)), el.bound = true;
|
||||
} else if (el.tagName == 'BUTTON') {
|
||||
if (!el.bound) {
|
||||
el.addEventListener("pointerdown", ev => Dashboard.call('set', set({}, key, true)));
|
||||
el.addEventListener("pointerup", ev => Dashboard.call('set', set({}, key, false)));
|
||||
el.bound = true;
|
||||
el.dataset.autosave = 1;
|
||||
}
|
||||
} else {
|
||||
el.innerHTML = v;
|
||||
el.innerHTML = v;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -317,19 +324,40 @@
|
||||
userhandlers[name] = fn;
|
||||
};
|
||||
|
||||
const setbody = visibility => document.body.style.visibility = visibility;
|
||||
|
||||
function init(conf) {
|
||||
apply_and_rescan(settings, conf);
|
||||
if (rpc) {
|
||||
rpc.handle((method, args) => {
|
||||
if (method == 'change') apply_and_rescan(settings.data, args);
|
||||
if (method == 'change') {
|
||||
// "initialized" means that the device has sent us all initial
|
||||
// data change notifications, and our settings.data contain
|
||||
// actual refreshed device data - not the UI mock
|
||||
if (!args) {
|
||||
setbody('visible');
|
||||
status.initialized = true;
|
||||
}
|
||||
if (args) apply_and_rescan(settings.data, args);
|
||||
}
|
||||
if (method != 'change') console.log('UNKNOWN REQUEST', method, args);
|
||||
if (userhandlers[method]) userhandlers[method](args);
|
||||
});
|
||||
|
||||
// After init, fetch all device data
|
||||
rpc.call('get').then(r => apply_and_rescan(settings.data, r));
|
||||
//rpc.call('get').then(r => apply_and_rescan(settings.data, r));
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
status.initialized = true;
|
||||
setbody('visible');
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => setbody('hidden'), { once: true });
|
||||
} else {
|
||||
setbody('hidden');
|
||||
}
|
||||
|
||||
global.Dashboard = { init, call, on, status };
|
||||
})(window);
|
||||
+17
-5
@@ -28,10 +28,17 @@ if (watchTargets.length === 0 || command.length === 0) {
|
||||
|
||||
let child = null;
|
||||
let restartTimeout = null;
|
||||
let ignoreEventsUntil = 0;
|
||||
let lastStartAt = 0;
|
||||
const MIN_RESTART_MS = 250;
|
||||
|
||||
function start() {
|
||||
// Prevent restart loops caused by the command touching watched paths.
|
||||
ignoreEventsUntil = Date.now() + 200;
|
||||
lastStartAt = Date.now();
|
||||
|
||||
if (child) {
|
||||
child.kill();
|
||||
child.kill('SIGTERM');
|
||||
}
|
||||
console.log(`Starting: ${command.join(' ')}`);
|
||||
child = spawn(command[0], command.slice(1), { stdio: 'inherit', shell: true });
|
||||
@@ -45,20 +52,25 @@ function start() {
|
||||
function watch(target) {
|
||||
const stats = fs.statSync(target);
|
||||
if (stats.isFile()) {
|
||||
fs.watchFile(target, (curr, prev) => {
|
||||
if (curr.mtime !== prev.mtime) {
|
||||
// fs.watchFile is polling-based; use a small interval to react quickly.
|
||||
fs.watchFile(target, { interval: 100 }, (curr, prev) => {
|
||||
if (Date.now() < ignoreEventsUntil) return;
|
||||
if (curr.mtimeMs !== prev.mtimeMs) {
|
||||
console.log(`File changed: ${target}`);
|
||||
clearTimeout(restartTimeout);
|
||||
restartTimeout = setTimeout(start, 100);
|
||||
const delay = Math.max(25, MIN_RESTART_MS - (Date.now() - lastStartAt));
|
||||
restartTimeout = setTimeout(start, delay);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const dir = target;
|
||||
fs.watch(dir, { recursive: true }, (eventType, filename) => {
|
||||
if (Date.now() < ignoreEventsUntil) return;
|
||||
if (filename) {
|
||||
console.log(`File changed: ${filename}`);
|
||||
clearTimeout(restartTimeout);
|
||||
restartTimeout = setTimeout(start, 100);
|
||||
const delay = Math.max(25, MIN_RESTART_MS - (Date.now() - lastStartAt));
|
||||
restartTimeout = setTimeout(start, delay);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user