second commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
#relay-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--grid-columns, 3), 1fr);
|
||||
gap: 0.51em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0.5em;
|
||||
align-items: stretch;
|
||||
justify-items: stretch;
|
||||
}
|
||||
|
||||
.relay-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
min-width: 320px;
|
||||
}
|
||||
|
||||
.relay-meta {
|
||||
width: 100%;
|
||||
flex: 0 0 auto;
|
||||
padding: .5em;
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
|
||||
|
||||
class RelayOverlay {
|
||||
|
||||
constructor(parent, relay) {
|
||||
this.parent = parent;
|
||||
this.relay = relay;
|
||||
this.uuid = relay.uuid;
|
||||
this.sockets = parent.sockets;
|
||||
|
||||
this.init_controls();
|
||||
}
|
||||
|
||||
init_controls() {
|
||||
this.duration_box = sId('duration-'+this.uuid);
|
||||
this.start_box = sId('start-'+this.uuid);
|
||||
this.stop_box = sId('stop-'+this.uuid);
|
||||
this.flow_box = sId('flow-'+this.uuid);
|
||||
this.ts_box = sId('ts-'+this.uuid);
|
||||
this.rate_box = sId('rate-'+this.uuid);
|
||||
this.remaining_box = sId('remaining-'+this.uuid);
|
||||
this.duration_value = parseInt(this.duration_box.value);
|
||||
this.relay_state = 0;
|
||||
this.flow = 0.00;
|
||||
|
||||
this.start_box.onclick = () => {
|
||||
this.start();
|
||||
};
|
||||
this.stop_box.onclick = () => {
|
||||
this.stop();
|
||||
};
|
||||
this.duration_box.onchange = () => {
|
||||
this.duration_value = parseInt(this.duration_box.value);
|
||||
}
|
||||
}
|
||||
|
||||
update(payload) {
|
||||
if (payload.topic === "status") {
|
||||
this.relay_state = payload.relay_state;
|
||||
this.flow = parseFloat(payload.flow.toFixed(2));
|
||||
this.rate = parseFloat(payload.rate.toFixed(2));
|
||||
|
||||
this.start_box.disabled = this.relay_state === 1;
|
||||
this.stop_box.disabled = this.relay_state === 0;
|
||||
|
||||
if (payload.remaining>0) {
|
||||
this.remaining_box.textContent = `${payload.remaining} s restante(s)`;
|
||||
} else {
|
||||
this.remaining_box.textContent = "";
|
||||
}
|
||||
this.ts_box.textContent = new Date(payload.ts * 1000).toLocaleTimeString();
|
||||
this.duration_box.value = this.duration_value;
|
||||
this.flow_box.textContent = this.flow;
|
||||
this.rate_box.textContent = this.rate;
|
||||
}
|
||||
}
|
||||
|
||||
start() { this._send({ type: 'relay', topic: "start", value: this.duration_value }); }
|
||||
stop() { this._send({ type: 'relay', topic: "stop" }); }
|
||||
status() { this._send({ type: 'relay', topic: "status" }); }
|
||||
halt() { this._send({ type: 'relay', topic: "halt" }); }
|
||||
restart() { this._send({ type: 'relay', topic: "restart" }); }
|
||||
_send(message) { this.sockets[this.uuid].send(message); }
|
||||
}
|
||||
|
||||
class RelayManager {
|
||||
constructor(container, relay) {
|
||||
this.container = container;
|
||||
this.relay = relay;
|
||||
this.overlays = {};
|
||||
this.sockets = {};
|
||||
this.init_controls();
|
||||
}
|
||||
|
||||
init_controls() {
|
||||
this.all_relay_state = 0;
|
||||
this.startall_box = sId('start-all');
|
||||
this.stopall_box = sId('stop-all');
|
||||
this.flow_box = sId('flow-all');
|
||||
|
||||
this.startall_box.onclick = () => {
|
||||
this.all_relay_state = 1;
|
||||
this._broadcast({ type: 'relay-multi', action: "start" });
|
||||
};
|
||||
this.stopall_box.onclick = () => {
|
||||
this.all_relay_state = 0;
|
||||
this._broadcast({ type: 'relay-multi', action: "stop" });
|
||||
};
|
||||
this.update_button();
|
||||
}
|
||||
|
||||
async start() {
|
||||
for (const relay of this.relay) {
|
||||
const overlay = new RelayOverlay(this, relay);
|
||||
this.overlays[relay.uuid] = overlay;
|
||||
}
|
||||
}
|
||||
|
||||
registerSocket(uuid, socket) {
|
||||
this.sockets[uuid] = socket;
|
||||
}
|
||||
|
||||
update_button() {
|
||||
this.startall_box.disabled = this.all_relay_state === 1;
|
||||
this.stopall_box.disabled = this.all_relay_state === 0;
|
||||
}
|
||||
|
||||
flow_update() {
|
||||
let total_flow = 0.00;
|
||||
for (const relay of this.relay) {
|
||||
const overlay = this.overlays[relay.uuid];
|
||||
if (overlay) {
|
||||
total_flow = total_flow + overlay.flow;
|
||||
}
|
||||
}
|
||||
this.flow_box.textContent = total_flow.toFixed(2);
|
||||
}
|
||||
|
||||
update(uuid, payload) {
|
||||
const overlay = this.overlays[uuid];
|
||||
if (overlay) {
|
||||
overlay.update(payload);
|
||||
}
|
||||
}
|
||||
|
||||
_broadcast(message) {
|
||||
if (message.type === 'relay-multi') {
|
||||
const action = message.action;
|
||||
this.update_button();
|
||||
for (const relay of this.relay) {
|
||||
const overlay = this.overlays[relay.uuid];
|
||||
overlay[action]();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MetadataSocket {
|
||||
constructor(url, uuid) {
|
||||
this.url = url;
|
||||
this.uuid = uuid;
|
||||
this.ws = null;
|
||||
this.manager = null;
|
||||
this.reconnectDelay = 1000;
|
||||
this.shouldReconnect = true;
|
||||
this.reconnect = false;
|
||||
}
|
||||
|
||||
setOverlayManager(manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.ws = new WebSocket(this.url);
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
this.manager.update(this.uuid, data);
|
||||
this.manager.flow_update();
|
||||
};
|
||||
|
||||
this.ws.onopen = (event) => {
|
||||
const overlay = this.manager.overlays[this.uuid];
|
||||
if (overlay && !this.reconnect)
|
||||
overlay['status']();
|
||||
this.reconnect = false;
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
console.warn(`WebSocket closed ${this.uuid}`);
|
||||
if (this.shouldReconnect) {
|
||||
this.reconnect = true;
|
||||
setTimeout(() => {
|
||||
console.log("Reconnect WebSocket...");
|
||||
this.connect();
|
||||
}, this.reconnectDelay);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
send(obj) {
|
||||
if (this.ws?.readyState === WebSocket.OPEN) {
|
||||
this.ws.send(JSON.stringify(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
const cpu_used = sId('cpu-used');
|
||||
const shm_used = sId('shm-used');
|
||||
const mem_used = sId('mem-used');
|
||||
const disk_used = sId('disk-used');
|
||||
const ramdisk_used = sId('ramdisk-used');
|
||||
|
||||
let autoTimer = null;
|
||||
|
||||
async function fetchStats() {
|
||||
try {
|
||||
const r = await fetch(stats_endpoint, { credentials: 'same-origin' });
|
||||
if (!r.ok) throw new Error('HTTP ' + r.status);
|
||||
const j = await r.json();
|
||||
//console.log(j);
|
||||
const cpu_percent = j.cpu_info.cpu_percent+'%'; cpu_used.style.setProperty("--cpu-used", cpu_percent); cpu_used.title=`Cpu: ${cpu_percent}`;
|
||||
const shm_length = j.shm.length; shm_used.style.setProperty("--shm_used", shm_length); shm_used.title= `Shm: ${shm_length}`;
|
||||
const virtual_memory = j.memory_info.virtual_memory.percent+'%'; mem_used.style.setProperty("--mem-used", virtual_memory); mem_used.title=`Mem: ${virtual_memory}`;
|
||||
const root_percent = j.disk_info.root.percent+'%'; disk_used.style.setProperty("--disk-used", root_percent); disk_used.title=`Disk: ${root_percent}`;
|
||||
let ramdisk_percent = "0%";
|
||||
if (! j.ramdisk_info) ramdisk_percent = j.ramdisk_info.percent+'%';
|
||||
ramdisk_used.style.setProperty("--ramdisk-used", ramdisk_percent); ramdisk_used.title=`Ramdisk: ${ramdisk_percent}`;
|
||||
|
||||
} catch (e) {
|
||||
console.log('Error: ' + e.message);
|
||||
}
|
||||
}
|
||||
function auto_fetch_start() { fetchStats(); autoTimer = setInterval(fetchStats, 5000);}
|
||||
function auto_fetch_stop() { clearInterval(autoTimer); autoTimer = null; }
|
||||
|
||||
auto_fetch_start();
|
||||
Reference in New Issue
Block a user