Skip to content

Commit

Permalink
Merge pull request #32 from lllllllillllllillll/dev
Browse files Browse the repository at this point in the history
v0.07
  • Loading branch information
lllllllillllllillll authored Dec 8, 2023
2 parents 36cc3ff + e35dbb5 commit 649c728
Show file tree
Hide file tree
Showing 19 changed files with 706 additions and 585 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
## v0.06 ( Nov 24th 2023 )
## v0.07 (Dec 8th 2023)
* View container logs.
* Removed Redis.
* Improved uninstall function and form id fix.
* WebUI Port can be changed in compose.yml
* Code clean-up.
* Updated dependencies (systeminformation).

## v0.06 (Nov 24th 2023)
* Multi-platform image (amd64/arm64).
* Removed Caddy from compose file.
* Proxy Manager UI can be enabled from environment variable.
* Removed hardcoded redis passwords.
* Repo change: Implemented image build-and-publish and dependabot (Thank you, gaby).
* Updated dependencies.

## v0.05 ( Nov 17th 2023 )
## v0.05 (Nov 17th 2023)
* Environment Variables and Labels are now unchecked by default.
* Support for Docker volumes.
* Fixed app uninstall.
Expand Down
52 changes: 20 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# DweebUI
DweebUI is a simple Docker web interface created with javascript and node.js

Pre-Pre-Pre-Pre-Pre Alpha v0.06 ( :fire: Experimental. Don't install on any servers you care about :fire: )
Pre-Pre-Pre-Pre-Pre Alpha v0.07 ( :fire: Experimental. Don't install on any servers you care about :fire: )

[![GitHub Stars](https://img.shields.io/github/stars/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll)
[![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE)
Expand All @@ -27,7 +27,7 @@ Pre-Pre-Pre-Pre-Pre Alpha v0.06 ( :fire: Experimental. Don't install on any serv
* [ ] User pages: Shortcuts, Requests, Support. (planned)
* [x] Support for Windows, Linux, and MacOS.
* [ ] Import compose files. (planned)
* [x] Pure javascript. No frameworks or typescript.
* [x] Javascript, Node.js, and Express.
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
* [ ] Manage your Docker networks, images, and volumes. (planned)
* [ ] Preset variables. (planned)
Expand All @@ -39,36 +39,24 @@ Pre-Pre-Pre-Pre-Pre Alpha v0.06 ( :fire: Experimental. Don't install on any serv
* Docker compose.yaml:
```
services:
dweebui:
container_name: DweebUI
image: lllllllillllllillll/dweebui:v0.06
environment:
NODE_ENV: production
REDIS_PASS: replace_with_password_for_redis
# Proxy_Manager: enabled
restart: unless-stopped
ports:
- 8000:8000
depends_on:
- cache
links:
- cache
volumes:
- dweebui:/app
- caddyfiles:/app/caddyfiles
- /var/run/docker.sock:/var/run/docker.sock
cache:
container_name: DweebCache
image: redis:6.2-alpine
restart: always
command: redis-server --save 20 1 --loglevel warning --requirepass replace_with_password_for_redis
volumes:
- cache:/data
  dweebui:
    container_name: DweebUI
    image: lllllllillllllillll/dweebui:v0.07
    environment:
      NODE_ENV: production
      PORT: 8000
      # Proxy_Manager: enabled
    restart: unless-stopped
    ports:
      - 8000:8000
    volumes:
      - dweebui:/app
      - caddyfiles:/app/caddyfiles
      - /var/run/docker.sock:/var/run/docker.sock
volumes:
dweebui:
cache:
caddyfiles:
  dweebui:
  caddyfiles:
```

* Using setup.sh:
Expand All @@ -83,5 +71,5 @@ sudo ./setup.sh
## Credit

* UI was built using HTML and CSS elements from https://tabler.io/
* Apps template based on Portainer template provided by Lissy93 here: https://github.com/Lissy93/portainer-templates
* Most of the app icons were sourced from Walkxcode's dashboard icons here: https://github.com/walkxcode/dashboard-icons
* Apps template based on Portainer template provided by Lissy93: https://github.com/Lissy93/portainer-templates
* Icons from Walkxcode with some renames and additions: https://github.com/walkxcode/dashboard-icons
80 changes: 44 additions & 36 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
// Express
const express = require("express");
const session = require("express-session");
const redis = require('connect-redis');
const app = express();
const routes = require("./routes");
const session = require("express-session");
const PORT = process.env.PORT || 8000;

const { serverStats, containerList, containerStats, containerAction } = require('./functions/system_information');
const { RefreshSites } = require('./controllers/site_actions');
// Router
const routes = require("./routes");

let sent_list, clicked;
// Functions and variables
const { serverStats, containerList, containerStats, containerAction, containerLogs } = require('./functions/system');
let sentList, clicked;
app.locals.site_list = '';

const redisClient = require('redis').createClient({
url: 'redis://DweebCache:6379',
password: process.env.REDIS_PASS,
legacyMode:true
});
redisClient.connect().catch(console.log);
const RedisStore = redis(session);

// Configure Session
const sessionMiddleware = session({
store:new RedisStore({client:redisClient}),
secret: "keyboard cat",
resave: false,
saveUninitialized: false,
cookie:{
secure:false, // Only set to true if you are using HTTPS.
httpOnly:false, // Only set to true if you are using HTTPS.
maxAge:3600000 * 8// Session max age in milliseconds. 3600000 = 1 hour.
maxAge:3600000 * 8 // Session max age in milliseconds. 3600000 = 1 hour.
}
})

// Middleware
app.set('view engine', 'ejs');
app.use([
express.static("public"),
Expand All @@ -39,49 +34,49 @@ app.use([
routes
]);

const server = app.listen(8000, async () => {
console.log(`App listening on port 8000`);
// Start Express server
const server = app.listen(PORT, async () => {
console.log(`App listening on port ${PORT}`);
});

// Start Socket.io
const io = require('socket.io')(server);
io.engine.use(sessionMiddleware);


io.on('connection', (socket) => {
// set user session

// Set user session
const user_session = socket.request.session;
console.log(`${user_session.user} connected from ${socket.handshake.headers.host} ${socket.handshake.address}`);

// check if a list of containers needs to be sent
if (sent_list != null) { socket.emit('cards', sent_list); }

// check if an install card has to be sent
// Check if a list of containers or an install card needs to be sent
if (sentList != null) { socket.emit('cards', sentList); }
if((app.locals.install != '') && (app.locals.install != null)){ socket.emit('install', app.locals.install); }

// send server metrics
// Send server metrics
let ServerStats = setInterval(async () => {
socket.emit('metrics', await serverStats());
}, 1000);

// send container list
// Send list of containers
let ContainerList = setInterval(async () => {
let card_list = await containerList();
if (sent_list !== card_list) {
sent_list = card_list;
let cardList = await containerList();
if (sentList !== cardList) {
sentList = cardList;
app.locals.install = '';
socket.emit('cards', card_list);
socket.emit('cards', cardList);
}
}, 1000);

// send container metrics
// Send container metrics
let ContainerStats = setInterval(async () => {
let container_stats = await containerStats();
for (let i = 0; i < container_stats.length; i++) {
socket.emit('container_stats', container_stats[i]);
let stats = await containerStats();
for (let i = 0; i < stats.length; i++) {
socket.emit('containerStats', stats[i]);
}
}, 1000);

// play/pause/stop/restart container
// Container controls
socket.on('clicked', (data) => {
if (clicked == true) { return; } clicked = true;
let buttonPress = {
Expand All @@ -94,7 +89,20 @@ io.on('connection', (socket) => {
containerAction(buttonPress);
clicked = false;
});



// Container logs
socket.on('logs', (data) => {
containerLogs(data.container)
.then(logs => {
socket.emit('logString', logs);
})
.catch(err => {
console.error(err);
});
});

// On disconnect
socket.on('disconnect', () => {
clearInterval(ServerStats);
clearInterval(ContainerList);
Expand Down
83 changes: 4 additions & 79 deletions components/dashCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ module.exports.dashCard = function dashCard(data) {
</a>
<div class="dropdown-menu dropdown-menu-end">
<a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#${name}_modal-details" href="#">Details</a>
<a class="dropdown-item" onclick="viewLogs(this)" name="${name}" data-bs-toggle="modal" data-bs-target="#${name}_logs" href="#">Logs</a>
<a class="dropdown-item" onclick="viewLogs(this)" name="${name}" data-bs-toggle="modal" data-bs-target="#log_view" href="#">Logs</a>
<a class="dropdown-item" href="#">Edit</a>
<a class="dropdown-item text-primary" href="#">Update</a>
<a class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#${name}_modal-danger" href="#">Remove</a>
Expand Down Expand Up @@ -184,8 +184,8 @@ module.exports.dashCard = function dashCard(data) {
<!-- Download SVG icon from http://tabler-icons.io/i/alert-triangle -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon mb-2 text-danger icon-lg" 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 9v2m0 4v.01"></path><path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"></path></svg>
<h3>Remove ${name}?</h3>
<form action="/uninstall" id="uninstall" method="POST">
<input type="text" class="form-control" name="service_name" value="${app_name}" hidden/>
<form action="/uninstall" id="${name}_uninstall" method="POST">
<input type="text" class="form-control" name="service_name" value="${name}" hidden/>
<div class="mb-3"> </div>
<div class="mb-2">
Expand Down Expand Up @@ -246,7 +246,7 @@ module.exports.dashCard = function dashCard(data) {
</a>
</div>
<div class="col">
<input type="submit" form="uninstall" class="btn btn-danger w-100" value="Uninstall"/>
<input type="submit" form="${name}_uninstall" class="btn btn-danger w-100" value="Uninstall"/>
</div>
</div>
</div>
Expand All @@ -255,82 +255,7 @@ module.exports.dashCard = function dashCard(data) {
</div>
</div>
<div class="modal modal-blur fade" id="${name}_logs" tabindex="-1" style="display: none;" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Scrollable modal</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas
eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue
laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl
consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Save changes</button>
</div>
</div>
</div>
</div>
<div class="modal modal-blur fade" id="${name}_modal-details" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" role="document">
Expand Down
16 changes: 2 additions & 14 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
services:
dweebui:
container_name: DweebUI
image: lllllllillllllillll/dweebui:v0.06
image: lllllllillllllillll/dweebui:v0.07
environment:
NODE_ENV: production
REDIS_PASS: replace_with_password_for_redis
PORT: 8000
# Proxy_Manager: enabled
restart: unless-stopped
ports:
- 8000:8000
depends_on:
- cache
links:
- cache
volumes:
- dweebui:/app
- caddyfiles:/app/caddyfiles
- /var/run/docker.sock:/var/run/docker.sock
cache:
container_name: DweebCache
image: redis:6.2-alpine
restart: always
command: redis-server --save 20 1 --loglevel warning --requirepass replace_with_password_for_redis
volumes:
- cache:/data

volumes:
dweebui:
cache:
caddyfiles:
Loading

0 comments on commit 649c728

Please sign in to comment.