reduced server.js to 99 lines. bug fixes.

This commit is contained in:
lllllllillllllillll 2024-02-23 00:41:54 -08:00
parent b62e209e6f
commit eb992f706e
11 changed files with 116 additions and 165 deletions

View file

@ -1,4 +1,4 @@
## v0.30 (dev) - Another rewrite ## v0.30 (dev) - HTMX rewrite
* Rewrote the dashboard to use HTMX. * Rewrote the dashboard to use HTMX.
* Removed Socket.io. * Removed Socket.io.
* Views are now HTML instead of EJS. * Views are now HTML instead of EJS.
@ -11,6 +11,8 @@
* Fixed list.js sorting. * Fixed list.js sorting.
* Removed stackfiles from templates.json and updated some icons. * Removed stackfiles from templates.json and updated some icons.
* New logo. * New logo.
* Improved handling of Docker events.
* Improved dashboard responsiveness.
## v0.20 (Jan 20th 2024) - The rewrite. Jumping all the way to v0.20. ## v0.20 (Jan 20th 2024) - The rewrite. Jumping all the way to v0.20.
* Changed to ES6 imports. * Changed to ES6 imports.

View file

@ -93,3 +93,4 @@ Compose setup:
## Supporters ## Supporters
* MM (Patreon) * MM (Patreon)
* PD (Buymeacoffee)

View file

@ -356,13 +356,6 @@ export const permissionsModal = (data) => {
<div class="modal-footer"> <div class="modal-footer">
<div class="row"> <div class="row">
<div class="col">
<label class="form-check form-switch col">
<span class="form-check-label">Reset</span>
<input class="form-check-input" type="checkbox">
</label>
</div>
<div class="col"> <div class="col">
<button type="button" class="btn btn-danger" data-bs-dismiss="modal" disabled="">Reset</button> <button type="button" class="btn btn-danger" data-bs-dismiss="modal" disabled="">Reset</button>
</div> </div>

View file

@ -6,7 +6,7 @@ import { setEvent, cpu, ram, tx, rx, disk, docker } from '../server.js';
import { dockerContainerStats } from 'systeminformation'; import { dockerContainerStats } from 'systeminformation';
import { containerCard } from '../components/containerCard.js'; import { containerCard } from '../components/containerCard.js';
let [ hidden, cardList, sentList ] = [ '', '', '']; let [ hidden, cardList ] = [ '', '' ];
export const Dashboard = (req, res) => { export const Dashboard = (req, res) => {
res.render("dashboard", { res.render("dashboard", {
@ -16,62 +16,6 @@ export const Dashboard = (req, res) => {
}); });
} }
export const Start = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state == 'stopped') {
var containerName = docker.getContainer(name);
containerName.start();
} else if (state == 'paused') {
var containerName = docker.getContainer(name);
containerName.unpause();
}
res.send("ok");
}
export const Stop = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state != 'stopped') {
var containerName = docker.getContainer(name);
containerName.stop();
}
res.send("ok");
}
export const Pause = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state == 'running') {
var containerName = docker.getContainer(name);
containerName.pause();
} else if (state == 'paused') {
var containerName = docker.getContainer(name);
containerName.unpause();
}
res.send("ok");
}
export const Restart = (req, res) => {
let name = req.header('hx-trigger-name');
var containerName = docker.getContainer(name);
containerName.restart();
res.send("ok");
}
export const Logs = (req, res) => { export const Logs = (req, res) => {
let name = req.header('hx-trigger-name'); let name = req.header('hx-trigger-name');
function containerLogs (data) { function containerLogs (data) {
@ -101,18 +45,15 @@ export const Logs = (req, res) => {
}); });
} }
export const Modal = async (req, res) => { export const Modal = async (req, res) => {
let name = req.header('hx-trigger-name'); let name = req.header('hx-trigger-name');
let id = req.header('hx-trigger'); let id = req.header('hx-trigger');
if (id == 'permissions') { if (id == 'permissions') {
let containerPermissions = await Permission.findAll({ where: {containerName: name}}); let containerPermissions = await Permission.findAll({ where: {containerName: name}});
let form = permissionsModal(); let form = permissionsModal();
res.send(form); res.send(form);
return; return;
} }
let containerId = docker.getContainer(name); let containerId = docker.getContainer(name);
let containerInfo = await containerId.inspect(); let containerInfo = await containerId.inspect();
let ports_list = []; let ports_list = [];
@ -127,7 +68,6 @@ export const Modal = async (req, res) => {
ports_list.push(ports); ports_list.push(ports);
} }
} catch {} } catch {}
let external_port = ports_list[0]?.external || 0; let external_port = ports_list[0]?.external || 0;
let internal_port = ports_list[0]?.internal || 0; let internal_port = ports_list[0]?.internal || 0;
@ -142,7 +82,6 @@ export const Modal = async (req, res) => {
} }
let form = modal(container_info); let form = modal(container_info);
res.send(form); res.send(form);
} }
export const Stats = async (req, res) => { export const Stats = async (req, res) => {
@ -190,8 +129,6 @@ export const Reset = async (req, res) => {
} }
let stats = {}; let stats = {};
export const Chart = async (req, res) => { export const Chart = async (req, res) => {
let name = req.header('hx-trigger-name'); let name = req.header('hx-trigger-name');
@ -219,27 +156,6 @@ export const Chart = async (req, res) => {
res.send(chart); res.send(chart);
} }
export const Installing = (req, res) => {
let install_info = {
name: 'App Name',
service: '',
id: '',
state: 'Installing',
image: '',
external_port: 0,
internal_port: 0,
ports: '',
link: 'localhost',
}
let card = containerCard(install_info);
res.send(card);
}
// Get hidden containers // Get hidden containers
async function getHidden() { async function getHidden() {
hidden = await Container.findAll({ where: {visibility:false}}); hidden = await Container.findAll({ where: {visibility:false}});
@ -296,3 +212,46 @@ export const Containers = async (req, res) => {
await containerCards(); await containerCards();
res.send(cardList); res.send(cardList);
} }
export const Start = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state == 'stopped') {
var containerName = docker.getContainer(name);
containerName.start();
} else if (state == 'paused') {
var containerName = docker.getContainer(name);
containerName.unpause();
}
res.send("ok");
}
export const Stop = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state != 'stopped') {
var containerName = docker.getContainer(name);
containerName.stop();
}
res.send("ok");
}
export const Pause = (req, res) => {
let name = req.header('hx-trigger-name');
let state = req.header('hx-trigger');
if (state == 'running') {
var containerName = docker.getContainer(name);
containerName.pause();
} else if (state == 'paused') {
var containerName = docker.getContainer(name);
containerName.unpause();
}
res.send("ok");
}
export const Restart = (req, res) => {
let name = req.header('hx-trigger-name');
var containerName = docker.getContainer(name);
containerName.restart();
res.send("ok");
}

View file

@ -2,7 +2,7 @@ version: "3.9"
services: services:
dweebui: dweebui:
container_name: dweebui container_name: dweebui
image: lllllllillllllillll/dweebui:v0.21-dev image: lllllllillllllillll/dweebui:v0.30-dev
environment: environment:
PORT: 8000 PORT: 8000
SECRET: MrWiskers SECRET: MrWiskers

View file

@ -4,7 +4,7 @@ export const router = express.Router();
// Controllers // Controllers
import { Login, submitLogin, Logout } from "../controllers/login.js"; import { Login, submitLogin, Logout } from "../controllers/login.js";
import { Register, submitRegister } from "../controllers/register.js"; import { Register, submitRegister } from "../controllers/register.js";
import { Dashboard, Start, Stop, Pause, Restart, Logs, Modal, Stats, Hide, Reset, Chart, Installing, Containers } from "../controllers/dashboard.js"; import { Dashboard, Start, Stop, Pause, Restart, Logs, Modal, Stats, Hide, Reset, Chart, Containers } from "../controllers/dashboard.js";
import { Apps, appSearch } from "../controllers/apps.js"; import { Apps, appSearch } from "../controllers/apps.js";
import { Users } from "../controllers/users.js"; import { Users } from "../controllers/users.js";
import { Images, removeImage } from "../controllers/images.js"; import { Images, removeImage } from "../controllers/images.js";
@ -39,7 +39,6 @@ router.get("/stats", auth, Stats);
router.post("/hide", auth, Hide); router.post("/hide", auth, Hide);
router.post("/reset", auth, Reset); router.post("/reset", auth, Reset);
router.get("/chart", auth, Chart); router.get("/chart", auth, Chart);
router.get("/installing", auth, Installing);
router.get("/images", auth, Images); router.get("/images", auth, Images);
router.post("/removeImage", auth, removeImage); router.post("/removeImage", auth, removeImage);

View file

@ -13,6 +13,8 @@ export { setEvent, cpu, ram, tx, rx, disk }
const app = express(); const app = express();
const MemoryStore = memorystore(session); const MemoryStore = memorystore(session);
const port = process.env.PORT || 8000; const port = process.env.PORT || 8000;
let [ cpu, ram, tx, rx, disk ] = [0, 0, 0, 0, 0];
let [ event, sse, eventType ] = [false, false, ''];
// Session middleware // Session middleware
const sessionMiddleware = session({ const sessionMiddleware = session({
@ -52,9 +54,6 @@ app.listen(port, async () => {
}); });
}); });
let [ cpu, ram, tx, rx, disk ] = [0, 0, 0, 0, 0];
let [ event, sse, eventType ] = [false, false, ''];
function setEvent(value, type) { function setEvent(value, type) {
event = value; event = value;
eventType = type; eventType = type;
@ -78,24 +77,19 @@ let serverMetrics = async () => {
} }
setInterval(serverMetrics, 1000); setInterval(serverMetrics, 1000);
let sent_list = ''; let sent_list = '';
router.get('/sse_event', (req, res) => { router.get('/sse_event', (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }); res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', });
let eventCheck = setInterval(async() => { let eventCheck = setInterval(async() => {
let all_containers = ''; let all_containers = '';
await docker.listContainers({ all: true }).then(containers => { await docker.listContainers({ all: true }).then(containers => {
containers.forEach(container => { containers.forEach(container => {
all_containers += `${container.Names}: ${container.State}\n`; all_containers += `${container.Names}: ${container.State}\n`;
}); });
}); });
if (all_containers != sent_list) { if ((all_containers != sent_list) || event) {
sent_list = all_containers; sent_list = all_containers;
setEvent(true, 'docker'); res.write(`event: docker\n`);
res.write(`event: ${eventType}\n`);
res.write(`data: there was an event!\n\n`); res.write(`data: there was an event!\n\n`);
} }
}, 1000); }, 1000);

View file

@ -82,11 +82,11 @@
prev prev
</a> </a>
</li> </li>
<li class="page-item"><a class="page-link" href="/apps?page=1">1</a></li> <li class="page-item"><a class="page-link" href="/apps/1">1</a></li>
<li class="page-item"><a class="page-link" href="/apps?page=2">2</a></li> <li class="page-item"><a class="page-link" href="/apps/2">2</a></li>
<li class="page-item"><a class="page-link" href="/apps?page=3">3</a></li> <li class="page-item"><a class="page-link" href="/apps/3">3</a></li>
<li class="page-item"><a class="page-link" href="/apps?page=4">4</a></li> <li class="page-item"><a class="page-link" href="/apps/4">4</a></li>
<li class="page-item"><a class="page-link" href="/apps?page=5">5</a></li> <li class="page-item"><a class="page-link" href="/apps/5">5</a></li>
<li class="page-item"> <li class="page-item">
<a class="page-link" href="<%- next %>"> <a class="page-link" href="<%- next %>">
next <!-- Download SVG icon from http://tabler-icons.io/i/chevron-right --> next <!-- Download SVG icon from http://tabler-icons.io/i/chevron-right -->

View file

@ -145,6 +145,7 @@
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"> <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
<!-- <a href="#" class="dropdown-item">Status</a> --> <!-- <a href="#" class="dropdown-item">Status</a> -->
<a href="/account" class="dropdown-item">Account</a> <a href="/account" class="dropdown-item">Account</a>
<a href="/variables" class="dropdown-item">Variables</a>
<!-- <a href="#" class="dropdown-item">Feedback</a> --> <!-- <a href="#" class="dropdown-item">Feedback</a> -->
<a href="/settings" class="dropdown-item">Settings</a> <a href="/settings" class="dropdown-item">Settings</a>
<!-- <div class="dropdown-divider"></div> --> <!-- <div class="dropdown-divider"></div> -->

View file

@ -50,9 +50,9 @@
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col"> <div class="col">
<span type="button" class="avatar avatar-md bg-green-lt" hx-trigger="load, click" hx-post="/thank" hx-target="#count" name="MM" title="Micheal M" style="margin-right: 5px;">mm</span> <span type="button" class="avatar avatar-md bg-green-lt" hx-trigger="load, click" hx-post="/thank" hx-target="#count" name="MM" title="MM" style="margin-right: 5px;">mm</span>
<span type="button" class="avatar avatar-md bg-cyan-lt" hx-trigger="click" hx-post="/thank" hx-target="#count" name="PD" title="Peter D" style="margin-right: 5px;">pd</span> <span type="button" class="avatar avatar-md bg-cyan-lt" hx-trigger="click" hx-post="/thank" hx-target="#count" name="PD" title="PD" style="margin-right: 5px;">pd</span>
</div> </div>

View file

@ -44,60 +44,62 @@
<div class="col d-flex flex-column"> <div class="col d-flex flex-column">
<div class="card-body"> <div class="card-body">
<h2 class="mb-2">Settings</h2> <h2 class="mb-2">Variables</h2>
<p class="text-muted mb-4">Configure server below</p> <p class="text-muted mb-4">Configure default variables below.</p>
<div class="row align-items-center"> <!-- <div class="row align-items-center">
<div class="col"> <div class="col">
</div>
</div> -->
<div class="row mt-4">
<div class="col-md">
<div class="form-label">Match 1</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Match 2</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Default</div>
<input type="text" class="form-control" value="" readonly="">
</div>
</div>
<div class="row mt-4">
<div class="col-md">
<div class="form-label">Match 1</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Match 2</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Default</div>
<input type="text" class="form-control" value="" readonly="">
</div>
</div> </div>
</div>
<div class="row mt-4">
<div class="col-md"> <div class="row mt-4">
<div class="form-label">Full Name</div> <div class="col-md">
<input type="text" class="form-control" value="" readonly=""> <div class="form-label">Match 1</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Match 2</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Default</div>
<input type="text" class="form-control" value="" readonly="">
</div>
</div> </div>
<div class="col-md">
<div class="form-label">First Name</div>
<input type="text" class="form-control" value="" readonly="">
</div>
<div class="col-md">
<div class="form-label">Last Name</div>
<input type="text" class="form-control" value="" readonly="">
</div>
</div>
<h3 class="card-title mt-4">Email</h3>
<p class="card-subtitle">This contact will be shown to others publicly, so choose it carefully.</p>
<div>
<div class="row g-2">
<div class="col-auto">
<input type="text" class="form-control w-auto" value="" readonly="">
</div>
<div class="col-auto">
<a href="#" class="btn">Change</a>
</div>
</div>
</div>
<h3 class="card-title mt-4">Password</h3>
<p class="card-subtitle">You can set a permanent password if you don't want to use temporary login codes.</p>
<div>
<a href="#" class="btn">
Set new password
</a>
</div>
<h3 class="card-title mt-4">Public profile</h3>
<p class="card-subtitle">Making your profile public means that anyone on the Dashkit network will be able to find
you.</p>
<div>
<label class="form-check form-switch form-switch-lg">
<input class="form-check-input" type="checkbox" >
<span class="form-check-label form-check-label-on">You're currently visible</span>
<span class="form-check-label form-check-label-off">You're
currently invisible</span>
</label>
</div>
</div> </div>
</div> </div>