|
@@ -3,7 +3,6 @@ import { Permission, Container, User } from '../database/models.js';
|
|
|
import { docker } from '../server.js';
|
|
|
import { dockerContainerStats } from 'systeminformation';
|
|
|
import { readFileSync } from 'fs';
|
|
|
-import { currentLoad, mem, networkStats, fsSize } from 'systeminformation';
|
|
|
|
|
|
let hidden = '';
|
|
|
|
|
@@ -21,6 +20,7 @@ export const Portal = (req, res) => {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+
|
|
|
async function containerInfo (containerName) {
|
|
|
let container = docker.getContainer(containerName);
|
|
|
let info = await container.inspect();
|
|
@@ -126,6 +126,72 @@ export async function addCard (name, state) {
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
+// HTMX server-side events
|
|
|
+export const SSE = (req, res) => {
|
|
|
+ res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' });
|
|
|
+
|
|
|
+ let eventCheck = setInterval(async () => {
|
|
|
+ // builds array of containers and their states
|
|
|
+ containersArray = [];
|
|
|
+ await docker.listContainers({ all: true }).then(containers => {
|
|
|
+ containers.forEach(container => {
|
|
|
+ let name = container.Names[0].replace('/', '');
|
|
|
+ if (!hidden.includes(name)) { // if not hidden
|
|
|
+ containersArray.push({ container: name, state: container.State });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ if ((JSON.stringify(containersArray) !== JSON.stringify(sentArray))) {
|
|
|
+ cardList = '';
|
|
|
+ newCards = '';
|
|
|
+ containersArray.forEach(container => {
|
|
|
+ const { container: containerName, state } = container;
|
|
|
+ const existingContainer = sentArray.find(c => c.container === containerName);
|
|
|
+ if (!existingContainer) {
|
|
|
+ containerInfo(containerName).then(details => {
|
|
|
+ createCard(details).then(card => {
|
|
|
+ newCards += card;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ res.write(`event: update\n`);
|
|
|
+ res.write(`data: 'update cards'\n\n`);
|
|
|
+ } else if (existingContainer.state !== state) {
|
|
|
+ updatesArray.push(containerName);
|
|
|
+ }
|
|
|
+ containerInfo(containerName).then(details => {
|
|
|
+ createCard(details).then(card => {
|
|
|
+ cardList += card;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ sentArray.forEach(container => {
|
|
|
+ const { container: containerName } = container;
|
|
|
+ const existingContainer = containersArray.find(c => c.container === containerName);
|
|
|
+ if (!existingContainer) {
|
|
|
+ updatesArray.push(containerName);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ for (let i = 0; i < updatesArray.length; i++) {
|
|
|
+ res.write(`event: ${updatesArray[i]}\n`);
|
|
|
+ res.write(`data: 'update cards'\n\n`);
|
|
|
+ }
|
|
|
+ updatesArray = [];
|
|
|
+ sentArray = containersArray.slice();
|
|
|
+ }
|
|
|
+
|
|
|
+ }, 500);
|
|
|
+
|
|
|
+
|
|
|
+ req.on('close', () => {
|
|
|
+ clearInterval(eventCheck);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
export const updateCards = async (req, res) => {
|
|
|
console.log('updateCards called');
|
|
|
res.send(newCards);
|
|
@@ -152,8 +218,6 @@ export const Card = async (req, res) => {
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
function status (state) {
|
|
|
let status = `<span class="text-yellow align-items-center lh-1">
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-point-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 7a5 5 0 1 1 -4.995 5.217l-.005 -.217l.005 -.217a5 5 0 0 1 4.995 -4.783z" stroke-width="0" fill="currentColor"></path></svg>
|