Updated dependencies and CHANGELOG. Navbar tweaks.

This commit is contained in:
lllllllillllllillll 2024-09-18 00:47:50 -07:00
parent e16492e462
commit ec4746ebd3
10 changed files with 107 additions and 50 deletions

View file

@ -9,15 +9,38 @@
* New - 'Grid view' and 'List view' button (non-functioning).
* Added try blocks to volumes, images, and networks pages to address GitHub issues.
* Fixed HTTPS env.
* New - One-click sign-in if NO_AUTH env is set to 'true' and you're connecting from localhost.
* New - Authentication can be reduced or disabled.
* New (again) - PM2 to keep the app running if it encounters an error.
* New - User registration enabled/disabled from Settings page.
* Removed 'SECRET' environment variable.
* New - Custom container links.
* New - Custom container_card ports links.
* New - Custom container_card title links.
* Fixed issue updating view permission.
* Fixed issue viewing container logs.
* App icons are now determined by service label instead of image name.
* App icons sourced from new repo with 1000+ icons.
* Rewrote most of the app to use containerIDs and UUIDs universally.
* Dashboard updates now triggered by Docker events instead of constantly polling the API.
* Sessions now stored in sqlite database instead of memory.
* Updated tabler from 1.0.0-beta16 to 1.0.0-beta20.
* Updated htmx (2.0.1) and sse plugin (2.2.1).
* Seperated css and js customizations into dweebui.css and dweebui.js.
* New - Preferences page for individual user settings, like language choice.
* New - Hide username from dashboard.
* New - Footer displays version with build number.
* Updated hide container_card to be **instant**.
* Improved console.log and syslog messages.
* Fixed modal close buttons.
* Reduced amount of html being stored in js files.
* CSS and pages tweaks to make the style more consistent.
* Improved container cards to be more compact.
* Improved sponsors and credits pages.
* New - Secret supporter code.
* Fixed installs not appearing or appearing multiple times.
* Improved log view and fixed refresh button.
* Made app cards more compact.
## v0.60 (June 9th 2024) - Permissions system and import templates
* Converted JS template literals into HTML.

View file

@ -15,20 +15,20 @@
## Features
* [x] A dynamically updating dashboard that displays server metrics along with container metrics and container controls.
* [x] Multi-user support with permissions system.
* [ ] Multiple hosts (in development).
* [x] Container actions: Start, Stop, Pause, Restart, View Details, View Logs.
* [x] Multi-user support with permissions system.
* [x] Support for multiple hosts.
* [x] View and manage images, volumes, and networks.
* [x] Windows, Linux, and MacOS compatable.
* [x] Light/Dark Mode.
* [x] Mobile Friendly.
* [x] Manage your Docker networks, images, and volumes.
* [x] Easy to install app templates.
* [x] Docker Compose Support.
* [x] Easy to install app templates (Compatible with Portainer).
* [x] Docker Compose.
* [ ] Available updates without image pull (in development).
* [ ] Update containers (planned).
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
* [ ] Preset variables (planned).
* [ ] Themes (planned).
* [*] International language support (Languages still being updated).
## About
@ -39,7 +39,13 @@
## Setup
Docker Compose:
### Docker Run:
```
docker run -d --name=DweebUI -p 8000:8000 -v dweebui:/app/database -v /var/run/docker.sock:/var/run/docker.sock lllllllillllllillll/dweebui:v0.7X-dev
```
### Docker Compose:
```
version: "3.9"
services:

View file

@ -13,14 +13,8 @@ let container_link = 'http://localhost';
// Dashboard
export const Dashboard = async function (req, res) {
let host = req.params.host;
req.session.host = host;
// if (host != 1) {
// let test = await GetContainerLists(host);
// console.log(test);
// }
let host = req.params.host || 1;
req.session.host = `${host}`;
// Create the lists needed for the dashboard
const [list, created] = await ContainerLists.findOrCreate({
@ -36,7 +30,6 @@ export const Dashboard = async function (req, res) {
});
if (created) { console.log(`New entry created in ContainerLists for ${req.session.username}`); }
res.render("dashboard",{
alert: '',
username: req.session.username,
@ -250,11 +243,6 @@ async function createCard (details) {
container_card = container_card.replace(/AppService/g, containerService);
container_card = container_card.replace(/AppState/g, containerState);
container_card = container_card.replace(/StateColor/g, containerStateColor);
let update_status = `<div class="text-yellow">
<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>
</div>`;
if (details.external_port == 0 && details.internal_port == 0) {

View file

@ -50,10 +50,30 @@ export const submitRegister = async function(req,res){
else if (await User.findOne({ where: { [Op.or]: [{ username: username }, { email: email }] }})) {
error = "Username or email already exists";
await Syslog.create({ username: user.username, uniqueID: email, event: "Failed Registration", message: "Username or email already exists", ip: req.socket.remoteAddress });
await Syslog.create({ username: username, uniqueID: email, event: "Failed Registration", message: "Username or email already exists", ip: req.socket.remoteAddress });
}
if (error != '') {
let secret_input = '';
let user_registration = await ServerSettings.findOne({ where: { key: 'user_registration' }});
if (user_registration == null ) { user_registration = false; }
else { user_registration = user_registration.value; }
if (user_registration) {
secret_input = `<div class="mb-3"><label class="form-label">Secret</label>
<div class="input-group input-group-flat">
<input type="text" class="form-control" autocomplete="off" name="registration_secret">
</div>
</div>`}
res.render("register", {
"error": error,
"reg_secret": secret_input,
});
return;
}
if (error) { res.render("register", { "error": error }); return; }
// Returns 'admin' if no users have been created.
async function Role() {

View file

@ -1,6 +1,6 @@
import { ServerSettings } from '../database/config.js';
import { Alert, getLanguage, Navbar, Sidebar, Footer } from '../utils/system.js';
import { read, readdirSync, readFileSync } from 'fs';
import { read, readdirSync, readFileSync, writeFileSync } from 'fs';
export const Settings = async function(req,res){
@ -216,15 +216,16 @@ export const updateLanguages = async function(req,res){
if (language_dev != language_local) {
console.log(`\x1b[31mLanguage: ${languages[i].language} is out of date.\x1b[0m`);
console.log(`\x1b[31mUpdating ${languages[i].language}...\x1b[0m`);
writeFileSync(`./languages/${languages[i].language}`, language_dev);
console.log(`\x1b[32mLanguage: ${languages[i].language} has been updated.\x1b[0m`);
} else {
console.log(`\x1b[32mLanguage: ${languages[i].language} is up to date.\x1b[0m`);
}
}
setTimeout(() => {
inProgress = false;
console.log('Languages Updated');
}, 2000);
inProgress = false;
console.log('Language update complete');
return;
} else {

10
package-lock.json generated
View file

@ -1,27 +1,27 @@
{
"name": "dweebui",
"version": "0.70.453",
"version": "0.70.457",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dweebui",
"version": "0.70.453",
"version": "0.70.457",
"license": "MIT",
"dependencies": {
"adm-zip": "^0.5.15",
"adm-zip": "^0.5.16",
"bcrypt": "^5.1.1",
"connect-session-sequelize": "^7.1.7",
"dockerode": "^4.0.2",
"dockerode-compose": "^1.4.0",
"ejs": "^3.1.10",
"express": "^4.19.2",
"express": "^4.21.0",
"express-session": "^1.18.0",
"multer": "^1.4.5-lts.1",
"sequelize": "^6.37.3",
"sqlite3": "^5.1.7",
"systeminformation": "^5.23.5",
"yaml": "^2.5.0"
"yaml": "^2.5.1"
}
},
"node_modules/@balena/dockerignore": {

View file

@ -1,6 +1,6 @@
{
"name": "dweebui",
"version": "0.70.453",
"version": "0.70.457",
"main": "server.js",
"type": "module",
"scripts": {
@ -12,18 +12,18 @@
"license": "MIT",
"description": "DweebUI is a WebUI for managing your containers. https://dweebui.com",
"dependencies": {
"adm-zip": "^0.5.15",
"adm-zip": "^0.5.16",
"bcrypt": "^5.1.1",
"connect-session-sequelize": "^7.1.7",
"dockerode": "^4.0.2",
"dockerode-compose": "^1.4.0",
"ejs": "^3.1.10",
"express": "^4.19.2",
"express": "^4.21.0",
"express-session": "^1.18.0",
"multer": "^1.4.5-lts.1",
"sequelize": "^6.37.3",
"sqlite3": "^5.1.7",
"systeminformation": "^5.23.5",
"yaml": "^2.5.0"
"yaml": "^2.5.1"
}
}

View file

@ -14,7 +14,7 @@ export async function GetContainerLists(hostid) {
let host = hostid || 1;
if (host == 1) {
if (host == 1 || host == 0) {
let containers = await docker.listContainers({ all: true });
return containers;
}

View file

@ -8,6 +8,8 @@ export async function Navbar (req) {
let username = req.session.username;
let host = '' + req.session.host;
let language = await getLanguage(req);
// Check if the user wants to hide their profile name.
@ -20,9 +22,11 @@ export async function Navbar (req) {
let sponsored = await ServerSettings.findOne({ where: { key: 'sponsored' }});
if (sponsored) { username = `<label class="text-yellow">${username}</label>`; }
let [host2_toggle, host2_tag, host2_ip, host2_port] = ['', '', '', ''];
let [host3_toggle, host3_tag, host3_ip, host3_port] = ['', '', '', ''];
let [host4_toggle, host4_tag, host4_ip, host4_port] = ['', '', '', ''];
let [host0_active, host0_toggle, host0_tag, host0_ip, host0_port] = ['', '', '', '', ''];
let [host1_active, host1_toggle, host1_tag, host1_ip, host1_port] = ['', '', '', '', ''];
let [host2_active, host2_toggle, host2_tag, host2_ip, host2_port] = ['', '', '', '', ''];
let [host3_active, host3_toggle, host3_tag, host3_ip, host3_port] = ['', '', '', '', ''];
let [host4_active, host4_toggle, host4_tag, host4_ip, host4_port] = ['', '', '', '', ''];
const [host2, created2] = await ServerSettings.findOrCreate({ where: { key: 'host2' }, defaults: { key: 'host2', value: '' }});
const [host3, created3] = await ServerSettings.findOrCreate({ where: { key: 'host3' }, defaults: { key: 'host3', value: '' }});
@ -34,10 +38,17 @@ export async function Navbar (req) {
if (host4.value) { host4_toggle = 'checked'; [host4_tag, host4_ip, host4_port] = host4.value.split(','); }
let host_buttons = '';
if (host2_toggle || host3_toggle || host4_toggle) { host_buttons += '<a href="/0/dashboard" class="btn" title="All">All</a> <a href="/1/dashboard" class="btn" title="Host 1">Host 1</a>'; }
if (host2_toggle) { host_buttons += `<a href="/2/dashboard" class="btn" title="${host2_tag}">${host2_tag}</a>`; }
if (host3_toggle) { host_buttons += `<a href="/3/dashboard" class="btn" title="${host3_tag}">${host3_tag}</a>`; }
if (host4_toggle) { host_buttons += `<a href="/4/dashboard" class="btn" title="${host4_tag}">${host4_tag}</a>`; }
if (host == '0') { host0_active = 'text-yellow'; }
if (host == '1') { host1_active = 'text-yellow'; }
if (host == '2') { host2_active = 'text-yellow'; }
if (host == '3') { host3_active = 'text-yellow'; }
if (host == '4') { host4_active = 'text-yellow'; }
if (host2_toggle || host3_toggle || host4_toggle) { host_buttons += `<a href="/0/dashboard" class="btn ${host0_active}" title="All">All</a> <a href="/1/dashboard" class="btn ${host1_active}" title="Host 1">Host 1</a>`; }
if (host2_toggle) { host_buttons += `<a href="/2/dashboard" class="btn ${host2_active}" title="${host2_tag}">${host2_tag}</a>`; }
if (host3_toggle) { host_buttons += `<a href="/3/dashboard" class="btn ${host3_active}" title="${host3_tag}">${host3_tag}</a>`; }
if (host4_toggle) { host_buttons += `<a href="/4/dashboard" class="btn ${host4_active}" title="${host4_tag}">${host4_tag}</a>`; }
let navbar = readFileSync('./views/partials/navbar.html', 'utf8');
@ -68,6 +79,7 @@ export async function Navbar (req) {
navbar = navbar.replace(/Username/g, username);
navbar = navbar.replace(/Userrole/g, req.session.role);
navbar = navbar.replace(/HostButtons/g, host_buttons);
return navbar;
}
}

View file

@ -22,6 +22,13 @@
<form class="card card-md" action="/register" method="post" autocomplete="off" novalidate>
<div class="card-body">
<h2 class="card-title text-center mb-4">Create new account</h2>
<% if(error) { %>
<div class="alert alert-danger" role="alert">
<%= error %>
</div>
<% } %>
<div class="mb-3">
<label class="form-label">Name</label>
<input type="text" class="form-control" name="name">
@ -50,9 +57,9 @@
</div>
<% if(reg_secret) { %>
<%- reg_secret %>
<% } %>
<%- reg_secret %>
<!-- <div class="mb-3">
<label class="form-check">