Forráskód Böngészése

created pages for images, networks, and volumes

lllllllillllllillll 1 éve
szülő
commit
9a065a8883

+ 4 - 6
README.md

@@ -1,7 +1,7 @@
 # DweebUI
 DweebUI is a simple Docker web interface created using Javascript, Node.JS, and Express.
 
-Pre-Pre-Pre-Pre-Pre Alpha v0.09 ( :fire: Experimental. Don't install on any servers you care about :fire: )
+v0.09
 
 [![GitHub Stars](https://img.shields.io/github/stars/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll)
 [![GitHub Activity](https://img.shields.io/github/commit-activity/y/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll)
@@ -9,10 +9,6 @@ Pre-Pre-Pre-Pre-Pre Alpha v0.09 ( :fire: Experimental. Don't install on any serv
 [![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE)
 
 
-* This is a personal project that I decided to share. I'm sure it has plenty of bugs and mistakes.
-* I haven't used Github very much and I'm still new to Javascript.
-* I probably should have waited a lot longer to share this :|
-
 <a href="https://raw.githubusercontent.com//lllllllillllllillll/DweebUI/main/screenshots/dashboard.png"><img src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard.png" width="50%"/></a>
 
 <a href="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/apps.png"><img src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/apps.png" width="50%"/></a>
@@ -100,4 +96,6 @@ sudo ./setup.sh
 * Icons from Walkxcode with some renames and additions: https://github.com/walkxcode/dashboard-icons
 
 
-## Supporters
+## Supporters
+
+* MM (Patreon)

+ 6 - 1
app.js

@@ -9,7 +9,7 @@ const PORT = process.env.PORT || 8000;
 const routes = require("./routes");
 
 // Functions and variables
-const { serverStats, containerList, containerStats, containerAction, containerLogs, hiddenContainers } = require('./functions/system');
+const { serverStats, containerList, containerStats, containerAction, containerLogs, hiddenContainers, dockerImages, dockerVolumes, dockerNetworks } = require('./functions/system');
 let sentList, clicked;
 app.locals.site_list = '';
 
@@ -58,6 +58,11 @@ io.on('connection', (socket) => {
     if (sentList != null) { socket.emit('cards', sentList); }
     if((app.locals.install != '') && (app.locals.install != null)){ socket.emit('install', app.locals.install); }
 
+
+    console.log(`Imags: ${dockerImages()}`);
+    console.log(`Volumes: ${dockerVolumes()}`);
+    console.log(`Networks: ${dockerNetworks()}`);
+
     // Send server metrics
     let ServerStats = setInterval(async () => {
         socket.emit('metrics', await serverStats());

+ 54 - 0
controllers/images.js

@@ -0,0 +1,54 @@
+const User = require('../database/UserModel');
+
+exports.Users = async function(req, res) {
+    if (req.session.role == "admin") {
+
+        // Get the user.
+        let user = await User.findOne({ where: { UUID: req.session.UUID }});
+        let user_list = `
+        <tr>
+            <th><input class="form-check-input" type="checkbox"></th>
+            <th>ID</th>
+            <th>Avatar</th>
+            <th>Name</th>
+            <th>Username</th>
+            <th>Email</th>
+            <th>UUID</th>
+            <th>Role</th>
+            <th>Status</th>
+            <th>Actions</th>
+        </tr>`
+
+        let users = await User.findAll();
+        users.forEach((account) => {
+            full_name = account.first_name + ' ' + account.last_name;
+            user_info = `
+            <tr>
+                <td><input class="form-check-input" type="checkbox"></td>
+                <td>${user.id}</td>
+                <td><span class="avatar me-2">${account.avatar}</span></td>
+                <td>${full_name}</td>
+                <td>${account.username}</td>
+                <td>${account.email}</td>
+                <td>${account.UUID}</td>
+                <td>${account.role}</td>
+                <td><span class="badge badge-outline text-green">Active</span></td>
+                <td><a href="#" class="btn">Edit</a></td>
+            </tr>`
+
+            user_list += user_info;
+        });
+
+        // Render the home page
+        res.render("pages/users", {
+            name: user.first_name + ' ' + user.last_name,
+            role: user.role,
+            avatar: user.avatar,
+            isLoggedIn: true,
+            user_list: user_list
+        });
+    } else {
+        // Redirect to the login page
+        res.redirect("/login");
+    }
+}

+ 54 - 0
controllers/networks.js

@@ -0,0 +1,54 @@
+const User = require('../database/UserModel');
+
+exports.Users = async function(req, res) {
+    if (req.session.role == "admin") {
+
+        // Get the user.
+        let user = await User.findOne({ where: { UUID: req.session.UUID }});
+        let user_list = `
+        <tr>
+            <th><input class="form-check-input" type="checkbox"></th>
+            <th>ID</th>
+            <th>Avatar</th>
+            <th>Name</th>
+            <th>Username</th>
+            <th>Email</th>
+            <th>UUID</th>
+            <th>Role</th>
+            <th>Status</th>
+            <th>Actions</th>
+        </tr>`
+
+        let users = await User.findAll();
+        users.forEach((account) => {
+            full_name = account.first_name + ' ' + account.last_name;
+            user_info = `
+            <tr>
+                <td><input class="form-check-input" type="checkbox"></td>
+                <td>${user.id}</td>
+                <td><span class="avatar me-2">${account.avatar}</span></td>
+                <td>${full_name}</td>
+                <td>${account.username}</td>
+                <td>${account.email}</td>
+                <td>${account.UUID}</td>
+                <td>${account.role}</td>
+                <td><span class="badge badge-outline text-green">Active</span></td>
+                <td><a href="#" class="btn">Edit</a></td>
+            </tr>`
+
+            user_list += user_info;
+        });
+
+        // Render the home page
+        res.render("pages/users", {
+            name: user.first_name + ' ' + user.last_name,
+            role: user.role,
+            avatar: user.avatar,
+            isLoggedIn: true,
+            user_list: user_list
+        });
+    } else {
+        // Redirect to the login page
+        res.redirect("/login");
+    }
+}

+ 54 - 0
controllers/volumes.js

@@ -0,0 +1,54 @@
+const User = require('../database/UserModel');
+
+exports.Users = async function(req, res) {
+    if (req.session.role == "admin") {
+
+        // Get the user.
+        let user = await User.findOne({ where: { UUID: req.session.UUID }});
+        let user_list = `
+        <tr>
+            <th><input class="form-check-input" type="checkbox"></th>
+            <th>ID</th>
+            <th>Avatar</th>
+            <th>Name</th>
+            <th>Username</th>
+            <th>Email</th>
+            <th>UUID</th>
+            <th>Role</th>
+            <th>Status</th>
+            <th>Actions</th>
+        </tr>`
+
+        let users = await User.findAll();
+        users.forEach((account) => {
+            full_name = account.first_name + ' ' + account.last_name;
+            user_info = `
+            <tr>
+                <td><input class="form-check-input" type="checkbox"></td>
+                <td>${user.id}</td>
+                <td><span class="avatar me-2">${account.avatar}</span></td>
+                <td>${full_name}</td>
+                <td>${account.username}</td>
+                <td>${account.email}</td>
+                <td>${account.UUID}</td>
+                <td>${account.role}</td>
+                <td><span class="badge badge-outline text-green">Active</span></td>
+                <td><a href="#" class="btn">Edit</a></td>
+            </tr>`
+
+            user_list += user_info;
+        });
+
+        // Render the home page
+        res.render("pages/users", {
+            name: user.first_name + ' ' + user.last_name,
+            role: user.role,
+            avatar: user.avatar,
+            isLoggedIn: true,
+            user_list: user_list
+        });
+    } else {
+        // Redirect to the login page
+        res.redirect("/login");
+    }
+}

+ 77 - 1
functions/system.js

@@ -312,4 +312,80 @@ module.exports.containerLogs = function (data) {
             });
         });
     });
-};
+};
+
+
+
+module.exports.dockerImages = async function () {
+    let image_list = '';
+
+    const data = await docker.listImages();
+
+    return data;
+
+    // for (const image of data) {
+
+    //     let imageVersion = image.RepoTags[0].split('/');
+    //     let service = imageVersion[imageVersion.length - 1].split(':')[0];
+
+    //     let image_info = {
+    //         name: image.RepoTags[0],
+    //         service: service,
+    //         id: image.Id,
+    //         size: image.Size,
+    //         style: "Compact"
+    //     }
+
+    //     let dockerCard = dashCard(image_info);
+
+    //     image_list += dockerCard;
+    // }
+
+    // return image_list;
+}
+
+
+module.exports.dockerVolumes = async function () {
+    let volume_list = '';
+
+    const data = await docker.listVolumes();
+
+    return data;
+
+    // for (const volume of data.Volumes) {
+
+    //     let volume_info = {
+    //         name: volume.Name,
+    //         style: "Compact"
+    //     }
+
+    //     let dockerCard = dashCard(volume_info);
+
+    //     volume_list += dockerCard;
+    // }
+
+    // return volume_list;
+}
+
+
+module.exports.dockerNetworks = async function () {
+    let network_list = '';
+
+    const data = await docker.listNetworks();
+
+    return data;
+
+    // for (const network of data) {
+
+    //     let network_info = {
+    //         name: network.Name,
+    //         style: "Compact"
+    //     }
+
+    //     let dockerCard = dashCard(network_info);
+
+    //     network_list += dockerCard;
+    // }
+
+    // return network_list;
+}

+ 7 - 4
routes/index.js

@@ -5,6 +5,10 @@ const { Dashboard, AddSite, RemoveSite, RefreshSites, DisableSite, EnableSite }
 const { Login, processLogin, Logout, Register, processRegister } = require("../controllers/auth");
 const { Apps, searchApps, Install, Uninstall } = require("../controllers/apps");
 
+const { Images } = require("../controllers/images");
+const { Volumes } = require("../controllers/volumes");
+const { Networks } = require("../controllers/networks");
+
 const { Users } = require("../controllers/users");
 const { Account } = require("../controllers/account");
 const { Settings } = require("../controllers/settings");
@@ -12,10 +16,7 @@ const { Settings } = require("../controllers/settings");
 // Authentication middleware
 const authenticate = (req, res, next) => {
     if (req.session && req.session.user) {
-        console.log("User:", req.session.user);
-        console.log("UUID:", req.session.UUID);
-        console.log("Role:", req.session.role);
-        console.log("Page:", req.originalUrl);
+        console.log(`User ${req.session.user} [${req.session.role} : ${req.session.UUID}] accessed ${req.originalUrl}`)
         next();
     } else {
         res.redirect("/login");
@@ -30,6 +31,8 @@ router.get("/refreshsites", authenticate, RefreshSites);
 router.post("/disablesite", authenticate, DisableSite);
 router.post("/enablesite", authenticate, EnableSite);
 
+router.get("/images", authenticate, Images);
+
 // Auth
 router.get("/login", Login);
 router.post("/login", processLogin);

+ 366 - 0
views/pages/images.ejs

@@ -0,0 +1,366 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
+    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
+    <title>Images</title>
+    <link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
+    <link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
+    <style>
+      @import url('https://rsms.me/inter/inter.css');
+      :root {
+      	--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
+      }
+      body {
+      	font-feature-settings: "cv03", "cv04", "cv11";
+      }
+    </style>
+  </head>
+  <body >
+    <script src="/js/demo-theme.min.js?1685973381"></script>
+    <div class="page">
+
+
+      <%- include('../partials/navbar.ejs') %>
+
+      <div class="page-wrapper">
+
+        <div class="page-header d-print-none">
+          <div class="container-xl">
+            <div class="row g-2 align-items-center">
+              <div class="col">
+                <h2 class="page-title">
+                  Users
+                </h2>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="page-body">
+          <div class="container-xl">
+            
+
+
+
+            <div class="card">
+              <div class="card-body">
+                <div id="table-default" class="table-responsive">
+                  <table class="table">
+                    <thead>
+                      <tr>
+                        <th><button class="table-sort" data-sort="sort-name">Name</button></th>
+                        <th><button class="table-sort" data-sort="sort-city">City</button></th>
+                        <th><button class="table-sort" data-sort="sort-type">Type</button></th>
+                        <th><button class="table-sort" data-sort="sort-score">Score</button></th>
+                        <th><button class="table-sort" data-sort="sort-date">Date</button></th>
+                        <th><button class="table-sort" data-sort="sort-quantity">Quantity</button></th>
+                        <th><button class="table-sort" data-sort="sort-progress">Progress</button></th>
+                      </tr>
+                    </thead>
+                    <tbody class="table-tbody"><tr>
+                        <td class="sort-name">Steel Vengeance</td>
+                        <td class="sort-city">Cedar Point, United States</td>
+                        <td class="sort-type">RMC Hybrid</td>
+                        <td class="sort-score">100,0%</td>
+                        <td class="sort-date" data-date="1628122643">August 05, 2021</td>
+                        <td class="sort-quantity">74</td>
+                        <td class="sort-progress" data-progress="30">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">30%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 30%" role="progressbar" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100" aria-label="30% Complete">
+                                  <span class="visually-hidden">30% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Fury 325</td>
+                        <td class="sort-city">Carowinds, United States</td>
+                        <td class="sort-type">B&amp;M Giga, Hyper, Steel</td>
+                        <td class="sort-score">99,3%</td>
+                        <td class="sort-date" data-date="1546344668">January 01, 2019</td>
+                        <td class="sort-quantity">49</td>
+                        <td class="sort-progress" data-progress="48">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">48%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 48%" role="progressbar" aria-valuenow="48" aria-valuemin="0" aria-valuemax="100" aria-label="48% Complete">
+                                  <span class="visually-hidden">48% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Wildfire</td>
+                        <td class="sort-city">Kolmården  Sweden</td>
+                        <td class="sort-type">RMC Twister, Wooden, Terrain</td>
+                        <td class="sort-score">99,3%</td>
+                        <td class="sort-date" data-date="1545977105">December 28, 2018</td>
+                        <td class="sort-quantity">8</td>
+                        <td class="sort-progress" data-progress="9">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">9%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 9%" role="progressbar" aria-valuenow="9" aria-valuemin="0" aria-valuemax="100" aria-label="9% Complete">
+                                  <span class="visually-hidden">9% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Lightning Rod</td>
+                        <td class="sort-city">Dollywood, United States</td>
+                        <td class="sort-type">RMC Wooden</td>
+                        <td class="sort-score">99,1%</td>
+                        <td class="sort-date" data-date="1605096500">November 11, 2020</td>
+                        <td class="sort-quantity">104</td>
+                        <td class="sort-progress" data-progress="98">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">98%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 98%" role="progressbar" aria-valuenow="98" aria-valuemin="0" aria-valuemax="100" aria-label="98% Complete">
+                                  <span class="visually-hidden">98% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Maverick</td>
+                        <td class="sort-city">Cedar Point, United States</td>
+                        <td class="sort-type">Intamin Rocket, Steel</td>
+                        <td class="sort-score">99,1%</td>
+                        <td class="sort-date" data-date="1636929477">November 14, 2021</td>
+                        <td class="sort-quantity">86</td>
+                        <td class="sort-progress" data-progress="46">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">46%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 46%" role="progressbar" aria-valuenow="46" aria-valuemin="0" aria-valuemax="100" aria-label="46% Complete">
+                                  <span class="visually-hidden">46% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">El Toro</td>
+                        <td class="sort-city">Six Flags Great Adventure, United States</td>
+                        <td class="sort-type">Intamin Twister, Wooden</td>
+                        <td class="sort-score">99,0%</td>
+                        <td class="sort-date" data-date="1613007167">February 11, 2021</td>
+                        <td class="sort-quantity">130</td>
+                        <td class="sort-progress" data-progress="29">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">29%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 29%" role="progressbar" aria-valuenow="29" aria-valuemin="0" aria-valuemax="100" aria-label="29% Complete">
+                                  <span class="visually-hidden">29% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Twisted Colossus</td>
+                        <td class="sort-city">Six Flags Magic Mountain, United States</td>
+                        <td class="sort-type">RMC Hybrid</td>
+                        <td class="sort-score">98,9%</td>
+                        <td class="sort-date" data-date="1572695602">November 02, 2019</td>
+                        <td class="sort-quantity">30</td>
+                        <td class="sort-progress" data-progress="57">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">57%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 57%" role="progressbar" aria-valuenow="57" aria-valuemin="0" aria-valuemax="100" aria-label="57% Complete">
+                                  <span class="visually-hidden">57% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Eejanaika new</td>
+                        <td class="sort-city">Fuji-Q Highland, Japan</td>
+                        <td class="sort-type">S&amp;S Power 4th Dimension, Steel</td>
+                        <td class="sort-score">98,6%</td>
+                        <td class="sort-date" data-date="1615765992">March 14, 2021</td>
+                        <td class="sort-quantity">162</td>
+                        <td class="sort-progress" data-progress="91">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">91%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 91%" role="progressbar" aria-valuenow="91" aria-valuemin="0" aria-valuemax="100" aria-label="91% Complete">
+                                  <span class="visually-hidden">91% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Wicked Cyclone</td>
+                        <td class="sort-city">Six Flags New England, United States</td>
+                        <td class="sort-type">RMC Hybrid</td>
+                        <td class="sort-score">98,2%</td>
+                        <td class="sort-date" data-date="1570144735">October 03, 2019</td>
+                        <td class="sort-quantity">174</td>
+                        <td class="sort-progress" data-progress="3">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">3%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 3%" role="progressbar" aria-valuenow="3" aria-valuemin="0" aria-valuemax="100" aria-label="3% Complete">
+                                  <span class="visually-hidden">3% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Shambhala</td>
+                        <td class="sort-city">Port Aventura, Spain</td>
+                        <td class="sort-type">B&amp;M Hyper, Steel</td>
+                        <td class="sort-score">98,2%</td>
+                        <td class="sort-date" data-date="1536285945">September 07, 2018</td>
+                        <td class="sort-quantity">111</td>
+                        <td class="sort-progress" data-progress="24">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">24%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 24%" role="progressbar" aria-valuenow="24" aria-valuemin="0" aria-valuemax="100" aria-label="24% Complete">
+                                  <span class="visually-hidden">24% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Taron</td>
+                        <td class="sort-city">Phantasialand, Germany</td>
+                        <td class="sort-type">Intamin Sit Down, Steel</td>
+                        <td class="sort-score">98,2%</td>
+                        <td class="sort-date" data-date="1543072573">November 24, 2018</td>
+                        <td class="sort-quantity">130</td>
+                        <td class="sort-progress" data-progress="48">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">48%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 48%" role="progressbar" aria-valuenow="48" aria-valuemin="0" aria-valuemax="100" aria-label="48% Complete">
+                                  <span class="visually-hidden">48% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Expedition Ge Force</td>
+                        <td class="sort-city">Holiday Park, Germany</td>
+                        <td class="sort-type">Intamin Megacoaster, Steel</td>
+                        <td class="sort-score">98,2%</td>
+                        <td class="sort-date" data-date="1562384190">July 06, 2019</td>
+                        <td class="sort-quantity">157</td>
+                        <td class="sort-progress" data-progress="57">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">57%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 57%" role="progressbar" aria-valuenow="57" aria-valuemin="0" aria-valuemax="100" aria-label="57% Complete">
+                                  <span class="visually-hidden">57% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Storm Chaser</td>
+                        <td class="sort-city">Kentucky Kingdom, United States</td>
+                        <td class="sort-type">RMC Steel</td>
+                        <td class="sort-score">97,9%</td>
+                        <td class="sort-date" data-date="1567543123">September 03, 2019</td>
+                        <td class="sort-quantity">43</td>
+                        <td class="sort-progress" data-progress="42">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">42%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 42%" role="progressbar" aria-valuenow="42" aria-valuemin="0" aria-valuemax="100" aria-label="42% Complete">
+                                  <span class="visually-hidden">42% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Helix</td>
+                        <td class="sort-city">Liseberg, Sweden</td>
+                        <td class="sort-type">Mack Looper, Steel, Terrain</td>
+                        <td class="sort-score">97,9%</td>
+                        <td class="sort-date" data-date="1524703250">April 26, 2018</td>
+                        <td class="sort-quantity">151</td>
+                        <td class="sort-progress" data-progress="54">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">54%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 54%" role="progressbar" aria-valuenow="54" aria-valuemin="0" aria-valuemax="100" aria-label="54% Complete">
+                                  <span class="visually-hidden">54% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr><tr>
+                        <td class="sort-name">Outlaw Run</td>
+                        <td class="sort-city">Silver Dollar City, United States</td>
+                        <td class="sort-type">RMC Hybrid</td>
+                        <td class="sort-score">96,6%</td>
+                        <td class="sort-date" data-date="1559333540">May 31, 2019</td>
+                        <td class="sort-quantity">131</td>
+                        <td class="sort-progress" data-progress="64">
+                          <div class="row align-items-center">
+                            <div class="col-12 col-lg-auto">64%</div>
+                            <div class="col">
+                              <div class="progress" style="width: 5rem">
+                                <div class="progress-bar" style="width: 64%" role="progressbar" aria-valuenow="64" aria-valuemin="0" aria-valuemax="100" aria-label="64% Complete">
+                                  <span class="visually-hidden">64% Complete</span>
+                                </div>
+                              </div>
+                            </div>
+                          </div>
+                        </td>
+                      </tr></tbody>
+                  </table>
+                </div>
+              </div>
+            </div>
+
+
+
+
+          </div>
+        </div>
+        <%- include('../partials/footer.ejs') %>
+      </div>
+    </div>
+    <!-- Libs JS -->
+    <!-- Tabler Core -->
+    <script src="/js/tabler.min.js?1685973381" defer></script>
+    <script src="/js/demo.min.js?1685973381" defer></script>
+  </body>
+</html>

+ 71 - 0
views/pages/networks.ejs

@@ -0,0 +1,71 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
+    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
+    <title>Users</title>
+    <link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
+    <link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
+    <style>
+      @import url('https://rsms.me/inter/inter.css');
+      :root {
+      	--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
+      }
+      body {
+      	font-feature-settings: "cv03", "cv04", "cv11";
+      }
+    </style>
+  </head>
+  <body >
+    <script src="/js/demo-theme.min.js?1685973381"></script>
+    <div class="page">
+
+
+      <%- include('../partials/navbar.ejs') %>
+
+      <div class="page-wrapper">
+
+        <div class="page-header d-print-none">
+          <div class="container-xl">
+            <div class="row g-2 align-items-center">
+              <div class="col">
+                <h2 class="page-title">
+                  Users
+                </h2>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="page-body">
+          <div class="container-xl">
+            <div class="row row-cards">
+              
+              <div class="col-12">
+                <div class="card">
+                  <div class="table-responsive">
+                    <table class="table table-vcenter table-mobile-md card-table">
+                      <tbody>
+
+                        <%- user_list %>
+                      
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+
+            
+            </div>
+          </div>
+        </div>
+        <%- include('../partials/footer.ejs') %>
+      </div>
+    </div>
+    <!-- Libs JS -->
+    <!-- Tabler Core -->
+    <script src="/js/tabler.min.js?1685973381" defer></script>
+    <script src="/js/demo.min.js?1685973381" defer></script>
+  </body>
+</html>

+ 4 - 14
views/pages/users.ejs

@@ -1,19 +1,10 @@
 <!doctype html>
-<!--
-* Tabler - Premium and Open Source dashboard template with responsive and high quality UI.
-* @version 1.0.0-beta19
-* @link https://tabler.io
-* Copyright 2018-2023 The Tabler Authors
-* Copyright 2018-2023 codecalm.net Paweł Kuna
-* Licensed under MIT (https://github.com/tabler/tabler/blob/master/LICENSE)
--->
 <html lang="en">
   <head>
     <meta charset="utf-8"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
     <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
     <title>Users</title>
-    <!-- CSS files -->
     <link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
     <link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
     <style>
@@ -29,12 +20,12 @@
   <body >
     <script src="/js/demo-theme.min.js?1685973381"></script>
     <div class="page">
-      <!-- Navbar -->
-      
+
+
       <%- include('../partials/navbar.ejs') %>
 
       <div class="page-wrapper">
-        <!-- Page header -->
+
         <div class="page-header d-print-none">
           <div class="container-xl">
             <div class="row g-2 align-items-center">
@@ -46,12 +37,11 @@
             </div>
           </div>
         </div>
-        <!-- Page body -->
+
         <div class="page-body">
           <div class="container-xl">
             <div class="row row-cards">
               
-              
               <div class="col-12">
                 <div class="card">
                   <div class="table-responsive">

+ 71 - 0
views/pages/volumes.ejs

@@ -0,0 +1,71 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
+    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
+    <title>Users</title>
+    <link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
+    <link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
+    <style>
+      @import url('https://rsms.me/inter/inter.css');
+      :root {
+      	--tblr-font-sans-serif: 'Inter Var', -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
+      }
+      body {
+      	font-feature-settings: "cv03", "cv04", "cv11";
+      }
+    </style>
+  </head>
+  <body >
+    <script src="/js/demo-theme.min.js?1685973381"></script>
+    <div class="page">
+
+
+      <%- include('../partials/navbar.ejs') %>
+
+      <div class="page-wrapper">
+
+        <div class="page-header d-print-none">
+          <div class="container-xl">
+            <div class="row g-2 align-items-center">
+              <div class="col">
+                <h2 class="page-title">
+                  Users
+                </h2>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="page-body">
+          <div class="container-xl">
+            <div class="row row-cards">
+              
+              <div class="col-12">
+                <div class="card">
+                  <div class="table-responsive">
+                    <table class="table table-vcenter table-mobile-md card-table">
+                      <tbody>
+
+                        <%- user_list %>
+                      
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+
+            
+            </div>
+          </div>
+        </div>
+        <%- include('../partials/footer.ejs') %>
+      </div>
+    </div>
+    <!-- Libs JS -->
+    <!-- Tabler Core -->
+    <script src="/js/tabler.min.js?1685973381" defer></script>
+    <script src="/js/demo.min.js?1685973381" defer></script>
+  </body>
+</html>

+ 16 - 17
views/partials/navbar.ejs

@@ -185,25 +185,25 @@
           </li>
 
           <li class="nav-item">
-            <a class="nav-link" href="/apps">
+            <a class="nav-link" href="#">
               <span
-                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/apps -->
-                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-apps" 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="M4 4m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M4 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M14 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M14 7l6 0"></path> <path d="M17 4l0 6"></path> </svg>
+                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/user -->
+                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-augmented-reality" 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 d="M4 8v-2a2 2 0 0 1 2 -2h2" /><path d="M4 16v2a2 2 0 0 0 2 2h2" /><path d="M16 4h2a2 2 0 0 1 2 2v2" /><path d="M16 20h2a2 2 0 0 0 2 -2v-2" /><path d="M12 12.5l4 -2.5" /><path d="M8 10l4 2.5v4.5l4 -2.5v-4.5l-4 -2.5z" /><path d="M8 10v4.5l4 2.5" /></svg>
               </span>
               <span class="nav-link-title">
-                Apps
+                Images
               </span>
             </a>
           </li>
 
           <li class="nav-item">
-            <a class="nav-link" href="/users">
+            <a class="nav-link" href="#">
               <span
-                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/user -->
-                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-user" 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="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0"></path> <path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"></path> </svg>
+                class="nav-link-icon d-md-none d-lg-inline-block">
+                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-database" 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 6m-8 0a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"></path> <path d="M4 6v6a8 3 0 0 0 16 0v-6"></path> <path d="M4 12v6a8 3 0 0 0 16 0v-6"></path></svg>
               </span>
               <span class="nav-link-title">
-                Users
+                Volumes
               </span>
             </a>
           </li>
@@ -221,26 +221,25 @@
           </li>
 
           <li class="nav-item">
-            <a class="nav-link" href="#">
+            <a class="nav-link" href="/apps">
               <span
-                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/user -->
-                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-augmented-reality" 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 d="M4 8v-2a2 2 0 0 1 2 -2h2" /><path d="M4 16v2a2 2 0 0 0 2 2h2" /><path d="M16 4h2a2 2 0 0 1 2 2v2" /><path d="M16 20h2a2 2 0 0 0 2 -2v-2" /><path d="M12 12.5l4 -2.5" /><path d="M8 10l4 2.5v4.5l4 -2.5v-4.5l-4 -2.5z" /><path d="M8 10v4.5l4 2.5" /></svg>
+                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/apps -->
+                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-apps" 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="M4 4m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M4 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M14 14m0 1a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1z"></path> <path d="M14 7l6 0"></path> <path d="M17 4l0 6"></path> </svg>
               </span>
               <span class="nav-link-title">
-                Images
+                Apps
               </span>
             </a>
           </li>
 
-
           <li class="nav-item">
-            <a class="nav-link" href="#">
+            <a class="nav-link" href="/users">
               <span
-                class="nav-link-icon d-md-none d-lg-inline-block">
-                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-database" 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 6m-8 0a8 3 0 1 0 16 0a8 3 0 1 0 -16 0"></path> <path d="M4 6v6a8 3 0 0 0 16 0v-6"></path> <path d="M4 12v6a8 3 0 0 0 16 0v-6"></path></svg>
+                class="nav-link-icon d-md-none d-lg-inline-block"><!-- Download SVG icon from https://tabler-icons.io/i/user -->
+                <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-user" 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="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0"></path> <path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"></path> </svg>
               </span>
               <span class="nav-link-title">
-                Volumes
+                Users
               </span>
             </a>
           </li>