Working install cards and fixes for dashboard.js
This commit is contained in:
parent
8b8e30772f
commit
5c6e2a9eaa
6 changed files with 64 additions and 19 deletions
|
@ -8,7 +8,6 @@
|
||||||
* Dynamically generated avatars.
|
* Dynamically generated avatars.
|
||||||
* Updated database models.
|
* Updated database models.
|
||||||
* Persistent Database.
|
* Persistent Database.
|
||||||
* Removed automatic volume creation.
|
|
||||||
|
|
||||||
## v0.40 (Feb 26th 2024) - HTMX rewrite
|
## v0.40 (Feb 26th 2024) - HTMX rewrite
|
||||||
* Pages rewritten to use HTMX.
|
* Pages rewritten to use HTMX.
|
||||||
|
|
|
@ -105,6 +105,10 @@ async function createCard (details) {
|
||||||
state_color = 'orange';
|
state_color = 'orange';
|
||||||
trigger = 'data-hx-trigger="load"';
|
trigger = 'data-hx-trigger="load"';
|
||||||
break;
|
break;
|
||||||
|
case 'installing':
|
||||||
|
state_color = 'blue';
|
||||||
|
trigger = 'data-hx-trigger="load"';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// if (name.startsWith('dweebui')) { disable = 'disabled=""'; }
|
// if (name.startsWith('dweebui')) { disable = 'disabled=""'; }
|
||||||
let card = readFileSync('./views/partials/containerCard.html', 'utf8');
|
let card = readFileSync('./views/partials/containerCard.html', 'utf8');
|
||||||
|
@ -124,6 +128,30 @@ let [ cardList, newCards, containersArray, sentArray, updatesArray ] = [ '', '',
|
||||||
let hidden = await Container.findAll({ where: {visibility:false}});
|
let hidden = await Container.findAll({ where: {visibility:false}});
|
||||||
hidden = hidden.map((container) => container.name);
|
hidden = hidden.map((container) => container.name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function addCard (name, state) {
|
||||||
|
console.log(`Adding card for ${name}: ${state}`);
|
||||||
|
|
||||||
|
let details = {
|
||||||
|
name: name,
|
||||||
|
image: name,
|
||||||
|
service: name,
|
||||||
|
state: 'installing',
|
||||||
|
external_port: 0,
|
||||||
|
internal_port: 0,
|
||||||
|
ports: [],
|
||||||
|
link: 'localhost',
|
||||||
|
|
||||||
|
}
|
||||||
|
createCard(details).then(card => {
|
||||||
|
cardList += card;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// HTMX server-side events
|
// HTMX server-side events
|
||||||
export const SSE = (req, res) => {
|
export const SSE = (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' });
|
||||||
|
@ -180,7 +208,7 @@ export const SSE = (req, res) => {
|
||||||
sentArray = containersArray.slice();
|
sentArray = containersArray.slice();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 1000);
|
}, 500);
|
||||||
|
|
||||||
|
|
||||||
req.on('close', () => {
|
req.on('close', () => {
|
||||||
|
@ -211,14 +239,6 @@ export const Chart = async (req, res) => {
|
||||||
res.send(chart);
|
res.send(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const Installs = async (req, res) => {
|
|
||||||
let name = req.header('hx-trigger-name');
|
|
||||||
let all_containers = '';
|
|
||||||
res.send('ok');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const updateCards = async (req, res) => {
|
export const updateCards = async (req, res) => {
|
||||||
console.log('updateCards called');
|
console.log('updateCards called');
|
||||||
res.send(newCards);
|
res.send(newCards);
|
||||||
|
@ -232,13 +252,21 @@ export const Containers = async (req, res) => {
|
||||||
|
|
||||||
export const Card = async (req, res) => {
|
export const Card = async (req, res) => {
|
||||||
let name = req.header('hx-trigger-name');
|
let name = req.header('hx-trigger-name');
|
||||||
console.log(`Updated card for ${name}`);
|
console.log(`${name} requesting updated card`);
|
||||||
let details = await containerInfo(name);
|
// return nothing if in hidden or not found in containersArray
|
||||||
let card = await createCard(details);
|
if (hidden.includes(name) || !containersArray.find(c => c.container === name)) {
|
||||||
res.send(card);
|
res.send('');
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
let details = await containerInfo(name);
|
||||||
|
let card = await createCard(details);
|
||||||
|
res.send(card);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function status (state) {
|
function status (state) {
|
||||||
let status = `<span class="text-yellow align-items-center lh-1">
|
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>
|
<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>
|
||||||
|
@ -322,6 +350,10 @@ export const Action = async (req, res) => {
|
||||||
} else if ((action == 'pause') && (state == 'paused')) {
|
} else if ((action == 'pause') && (state == 'paused')) {
|
||||||
var containerName = docker.getContainer(name);
|
var containerName = docker.getContainer(name);
|
||||||
containerName.unpause();
|
containerName.unpause();
|
||||||
|
res.send(status('starting'));
|
||||||
|
} else if ((action == 'pause') && (state == 'running')) {
|
||||||
|
var containerName = docker.getContainer(name);
|
||||||
|
containerName.pause();
|
||||||
res.send(status('pausing'));
|
res.send(status('pausing'));
|
||||||
// Restart
|
// Restart
|
||||||
} else if (action == 'restart') {
|
} else if (action == 'restart') {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { execSync } from "child_process";
|
||||||
import { docker } from "../server.js";
|
import { docker } from "../server.js";
|
||||||
import DockerodeCompose from "dockerode-compose";
|
import DockerodeCompose from "dockerode-compose";
|
||||||
import { Syslog } from "../database/models.js";
|
import { Syslog } from "../database/models.js";
|
||||||
|
import { addCard } from "../controllers/dashboard.js";
|
||||||
|
|
||||||
// This entire page hurts to look at.
|
// This entire page hurts to look at.
|
||||||
export const Install = async (req, res) => {
|
export const Install = async (req, res) => {
|
||||||
|
@ -20,6 +21,8 @@ export const Install = async (req, res) => {
|
||||||
|
|
||||||
let docker_volumes = [];
|
let docker_volumes = [];
|
||||||
|
|
||||||
|
addCard(name, 'installing');
|
||||||
|
|
||||||
if (image.startsWith('https://')){
|
if (image.startsWith('https://')){
|
||||||
mkdirSync(`./appdata/${name}`, { recursive: true });
|
mkdirSync(`./appdata/${name}`, { recursive: true });
|
||||||
execSync(`curl -o ./appdata/${name}/${name}_stack.yml -L ${image}`);
|
execSync(`curl -o ./appdata/${name}/${name}_stack.yml -L ${image}`);
|
||||||
|
@ -88,6 +91,13 @@ export const Install = async (req, res) => {
|
||||||
if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] != '') && (data[`volume_${i}_container`] != '')) {
|
if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] != '') && (data[`volume_${i}_container`] != '')) {
|
||||||
compose_file += `\n - ${data[`volume_${i}_bind`]}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}`
|
compose_file += `\n - ${data[`volume_${i}_bind`]}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if bind is empty create a docker volume (ex container_name_config:/config) convert any '/' in container name to '_'
|
||||||
|
else if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] == '') && (data[`volume_${i}_container`] != '')) {
|
||||||
|
let volume_name = data[`volume_${i}_container`].replace(/\//g, '_');
|
||||||
|
compose_file += `\n - ${name}_${volume_name}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}`
|
||||||
|
docker_volumes.push(`${name}_${volume_name}`);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +180,7 @@ export const Install = async (req, res) => {
|
||||||
message: `${name} installation failed - error creating directory or compose file : ${err}`,
|
message: `${name} installation failed - error creating directory or compose file : ${err}`,
|
||||||
ip: req.socket.remoteAddress
|
ip: req.socket.remoteAddress
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
|
@ -10,7 +10,8 @@ export const Uninstall = async (req, res) => {
|
||||||
|
|
||||||
if (confirm == 'Yes') {
|
if (confirm == 'Yes') {
|
||||||
|
|
||||||
var containerName = docker.getContainer(`${service_name}`);
|
let containerName = docker.getContainer(service_name);
|
||||||
|
console.log(`Stopping ${service_name}...`)
|
||||||
try {
|
try {
|
||||||
await containerName.stop();
|
await containerName.stop();
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -18,6 +19,7 @@ export const Uninstall = async (req, res) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log(`Removing ${service_name}...`);
|
||||||
containerName.remove();
|
containerName.remove();
|
||||||
|
|
||||||
const syslog = await Syslog.create({
|
const syslog = await Syslog.create({
|
||||||
|
@ -38,7 +40,10 @@ export const Uninstall = async (req, res) => {
|
||||||
ip: req.socket.remoteAddress
|
ip: req.socket.remoteAddress
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`Didn't confirm uninstallation of ${service_name}...`);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, Logs, Modals, Stats, Chart, Installs, SSE, Card, updateCards, Containers, Action } from "../controllers/dashboard.js";
|
import { Dashboard, Logs, Modals, Stats, Chart, SSE, Card, updateCards, Containers, Action } from "../controllers/dashboard.js";
|
||||||
import { Apps, appSearch, InstallModal, LearnMore } from "../controllers/apps.js";
|
import { Apps, appSearch, InstallModal, LearnMore } 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";
|
||||||
|
@ -34,7 +34,6 @@ router.get("/logs", auth, Logs);
|
||||||
router.get("/modals", auth, Modals);
|
router.get("/modals", auth, Modals);
|
||||||
router.get("/stats", auth, Stats);
|
router.get("/stats", auth, Stats);
|
||||||
router.get("/chart", auth, Chart);
|
router.get("/chart", auth, Chart);
|
||||||
router.get("/installs", auth, Installs);
|
|
||||||
router.get("/sse_event", auth, SSE);
|
router.get("/sse_event", auth, SSE);
|
||||||
router.get("/containers", auth, Containers);
|
router.get("/containers", auth, Containers);
|
||||||
router.get("/card", auth, Card);
|
router.get("/card", auth, Card);
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-baseline">
|
<div class="d-flex align-items-baseline">
|
||||||
<div class="h1 me-2" title="AppName">
|
<div class="h1 me-2" title="AppName" style="margin-bottom: 0;">
|
||||||
<a href="http://${link}:${external_port}" target="_blank">
|
<a href="http://${link}:${external_port}" target="_blank">
|
||||||
AppShortName
|
AppShortName
|
||||||
</a>
|
</a>
|
||||||
|
|
Loading…
Add table
Reference in a new issue