removed extra if statements and sqlite queries.
added list.js for sorting tables. removed Caddy Proxy Manager from docker-compose.yaml
This commit is contained in:
parent
837c21fdb8
commit
e99dc8470b
20 changed files with 2445 additions and 463 deletions
|
@ -21,7 +21,6 @@ v0.09
|
||||||
* [ ] Manage your Docker networks, images, and volumes (planned).
|
* [ ] Manage your Docker networks, images, and volumes (planned).
|
||||||
* [x] Light/Dark Mode.
|
* [x] Light/Dark Mode.
|
||||||
* [x] Easy to install app templates.
|
* [x] Easy to install app templates.
|
||||||
* [x] Proxy manager for Caddy (Optional).
|
|
||||||
* [x] Multi-User built-in.
|
* [x] Multi-User built-in.
|
||||||
* [ ] User pages (planned).
|
* [ ] User pages (planned).
|
||||||
* [x] Support for Windows, Linux, and MacOS.
|
* [x] Support for Windows, Linux, and MacOS.
|
||||||
|
@ -29,7 +28,7 @@ v0.09
|
||||||
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
|
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
|
||||||
* [x] Automatically persists data in docker volumes if bind mount isn't used.
|
* [x] Automatically persists data in docker volumes if bind mount isn't used.
|
||||||
* [ ] Preset variables (planned).
|
* [ ] Preset variables (planned).
|
||||||
* [ ] Offline/Local Icons (planned).
|
* [ ] Proxy manager for Caddy (Disabled).
|
||||||
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
@ -48,7 +47,6 @@ services:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
PORT: 8000
|
PORT: 8000
|
||||||
SECRET: MrWiskers
|
SECRET: MrWiskers
|
||||||
#Proxy_Manager: enabled
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 8000:8000
|
- 8000:8000
|
||||||
|
|
12
app.js
12
app.js
|
@ -59,9 +59,15 @@ io.on('connection', (socket) => {
|
||||||
if((app.locals.install != '') && (app.locals.install != null)){ socket.emit('install', app.locals.install); }
|
if((app.locals.install != '') && (app.locals.install != null)){ socket.emit('install', app.locals.install); }
|
||||||
|
|
||||||
|
|
||||||
console.log(`Imags: ${dockerImages()}`);
|
async function dockerStuff(){
|
||||||
console.log(`Volumes: ${dockerVolumes()}`);
|
let i = await dockerImages();
|
||||||
console.log(`Networks: ${dockerNetworks()}`);
|
let v = await dockerVolumes();
|
||||||
|
let n = await dockerNetworks();
|
||||||
|
|
||||||
|
// console.log(i, v, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerStuff();
|
||||||
|
|
||||||
// Send server metrics
|
// Send server metrics
|
||||||
let ServerStats = setInterval(async () => {
|
let ServerStats = setInterval(async () => {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
const User = require('../database/UserModel');
|
|
||||||
const { appCard } = require('../components/appCard')
|
const { appCard } = require('../components/appCard')
|
||||||
const { dashCard } = require('../components/dashCard');
|
const { dashCard } = require('../components/dashCard');
|
||||||
const { install, uninstall } = require('../functions/package_manager');
|
const { install, uninstall } = require('../functions/package_manager');
|
||||||
|
@ -16,118 +15,103 @@ templates = templates.sort((a, b) => {
|
||||||
|
|
||||||
exports.Apps = async function(req, res) {
|
exports.Apps = async function(req, res) {
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
let page = Number(req.params.page) || 1;
|
||||||
|
let list_start = (page - 1) * 28;
|
||||||
|
let list_end = (page * 28);
|
||||||
|
let last_page = Math.ceil(templates.length / 28);
|
||||||
|
|
||||||
// Get the user.
|
let prev = '/apps/' + (page - 1);
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
let next = '/apps/' + (page + 1);
|
||||||
|
if (page == 1) {
|
||||||
let page = Number(req.params.page) || 1;
|
prev = '/apps/' + (page);
|
||||||
let list_start = (page - 1) * 28;
|
|
||||||
let list_end = (page * 28);
|
|
||||||
let last_page = Math.ceil(templates.length / 28);
|
|
||||||
|
|
||||||
let prev = '/apps/' + (page - 1);
|
|
||||||
let next = '/apps/' + (page + 1);
|
|
||||||
if (page == 1) {
|
|
||||||
prev = '/apps/' + (page);
|
|
||||||
}
|
|
||||||
if (page == last_page) {
|
|
||||||
next = '/apps/' + (page);
|
|
||||||
}
|
|
||||||
|
|
||||||
let apps_list = '';
|
|
||||||
for (let i = list_start; i < list_end && i < templates.length; i++) {
|
|
||||||
let app_card = appCard(templates[i]);
|
|
||||||
|
|
||||||
apps_list += app_card;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the home page
|
|
||||||
res.render("pages/apps", {
|
|
||||||
name: user.first_name + ' ' + user.last_name,
|
|
||||||
role: user.role,
|
|
||||||
avatar: user.avatar,
|
|
||||||
isLoggedIn: true,
|
|
||||||
list_start: list_start + 1,
|
|
||||||
list_end: list_end,
|
|
||||||
app_count: templates.length,
|
|
||||||
prev: prev,
|
|
||||||
next: next,
|
|
||||||
apps_list: apps_list
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
}
|
||||||
|
if (page == last_page) {
|
||||||
|
next = '/apps/' + (page);
|
||||||
|
}
|
||||||
|
|
||||||
|
let apps_list = '';
|
||||||
|
for (let i = list_start; i < list_end && i < templates.length; i++) {
|
||||||
|
let app_card = appCard(templates[i]);
|
||||||
|
|
||||||
|
apps_list += app_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the home page
|
||||||
|
res.render("pages/apps", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
list_start: list_start + 1,
|
||||||
|
list_end: list_end,
|
||||||
|
app_count: templates.length,
|
||||||
|
prev: prev,
|
||||||
|
next: next,
|
||||||
|
apps_list: apps_list
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.searchApps = async function(req, res) {
|
exports.searchApps = async function(req, res) {
|
||||||
if (req.session.role == "admin") {
|
|
||||||
|
|
||||||
// Get the user.
|
let page = Number(req.query.page) || 1;
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
let list_start = (page - 1) * 28;
|
||||||
|
let list_end = (page * 28);
|
||||||
|
let last_page = Math.ceil(templates.length / 28);
|
||||||
|
|
||||||
let page = Number(req.query.page) || 1;
|
let prev = '/apps?page=' + (page - 1);
|
||||||
let list_start = (page - 1) * 28;
|
let next = '/apps?page=' + (page + 1);
|
||||||
let list_end = (page * 28);
|
if (page == 1) {
|
||||||
let last_page = Math.ceil(templates.length / 28);
|
prev = '/apps?page=' + (page);
|
||||||
|
|
||||||
let prev = '/apps?page=' + (page - 1);
|
|
||||||
let next = '/apps?page=' + (page + 1);
|
|
||||||
if (page == 1) {
|
|
||||||
prev = '/apps?page=' + (page);
|
|
||||||
}
|
|
||||||
if (page == last_page) {
|
|
||||||
next = '/apps?page=' + (page);
|
|
||||||
}
|
|
||||||
|
|
||||||
let apps_list = '';
|
|
||||||
let search_results = [];
|
|
||||||
|
|
||||||
let search = req.body.search;
|
|
||||||
|
|
||||||
// split value of search into an array of words
|
|
||||||
search = search.split(' ');
|
|
||||||
try {console.log(search[0]);} catch (error) {}
|
|
||||||
try {console.log(search[1]);} catch (error) {}
|
|
||||||
try {console.log(search[2]);} catch (error) {}
|
|
||||||
|
|
||||||
function searchTemplates(word) {
|
|
||||||
|
|
||||||
for (let i = 0; i < templates.length; i++) {
|
|
||||||
if ((templates[i].description.includes(word)) || (templates[i].name.includes(word)) || (templates[i].title.includes(word))) {
|
|
||||||
search_results.push(templates[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log(search_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
searchTemplates(search);
|
|
||||||
|
|
||||||
for (let i = 0; i < search_results.length; i++) {
|
|
||||||
let app_card = appCard(search_results[i]);
|
|
||||||
apps_list += app_card;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the home page
|
|
||||||
res.render("pages/apps", {
|
|
||||||
name: user.first_name + ' ' + user.last_name,
|
|
||||||
role: user.role,
|
|
||||||
avatar: user.avatar,
|
|
||||||
isLoggedIn: true,
|
|
||||||
list_start: list_start + 1,
|
|
||||||
list_end: list_end,
|
|
||||||
app_count: templates.length,
|
|
||||||
prev: prev,
|
|
||||||
next: next,
|
|
||||||
apps_list: apps_list
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
}
|
||||||
|
if (page == last_page) {
|
||||||
|
next = '/apps?page=' + (page);
|
||||||
|
}
|
||||||
|
|
||||||
|
let apps_list = '';
|
||||||
|
let search_results = [];
|
||||||
|
|
||||||
|
let search = req.body.search;
|
||||||
|
|
||||||
|
// split value of search into an array of words
|
||||||
|
search = search.split(' ');
|
||||||
|
try {console.log(search[0]);} catch (error) {}
|
||||||
|
try {console.log(search[1]);} catch (error) {}
|
||||||
|
try {console.log(search[2]);} catch (error) {}
|
||||||
|
|
||||||
|
function searchTemplates(word) {
|
||||||
|
|
||||||
|
for (let i = 0; i < templates.length; i++) {
|
||||||
|
if ((templates[i].description.includes(word)) || (templates[i].name.includes(word)) || (templates[i].title.includes(word))) {
|
||||||
|
search_results.push(templates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(search_results);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchTemplates(search);
|
||||||
|
|
||||||
|
for (let i = 0; i < search_results.length; i++) {
|
||||||
|
let app_card = appCard(search_results[i]);
|
||||||
|
apps_list += app_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the home page
|
||||||
|
res.render("pages/apps", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
list_start: list_start + 1,
|
||||||
|
list_end: list_end,
|
||||||
|
app_count: templates.length,
|
||||||
|
prev: prev,
|
||||||
|
next: next,
|
||||||
|
apps_list: apps_list
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ exports.processLogin = async function(req,res){
|
||||||
req.session.user = existingUser.username;
|
req.session.user = existingUser.username;
|
||||||
req.session.UUID = existingUser.UUID;
|
req.session.UUID = existingUser.UUID;
|
||||||
req.session.role = existingUser.role;
|
req.session.role = existingUser.role;
|
||||||
|
req.session.avatar = existingUser.avatar;
|
||||||
|
|
||||||
|
|
||||||
// Redirect to the home page.
|
// Redirect to the home page.
|
||||||
|
@ -128,6 +129,7 @@ exports.processRegister = async function(req,res){
|
||||||
req.session.user = newUser.username;
|
req.session.user = newUser.username;
|
||||||
req.session.UUID = newUser.UUID;
|
req.session.UUID = newUser.UUID;
|
||||||
req.session.role = newUser.role;
|
req.session.role = newUser.role;
|
||||||
|
req.session.avatar = newUser.avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to the home page.
|
// Redirect to the home page.
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
const User = require('../database/UserModel');
|
|
||||||
const Containers = require('../database/ContainerSettings');
|
|
||||||
|
|
||||||
const { readFileSync, writeFileSync, appendFileSync, readdirSync } = require('fs');
|
const { readFileSync, writeFileSync, appendFileSync, readdirSync } = require('fs');
|
||||||
const { execSync } = require("child_process");
|
const { execSync } = require("child_process");
|
||||||
const { siteCard } = require('../components/siteCard');
|
const { siteCard } = require('../components/siteCard');
|
||||||
|
@ -10,30 +7,22 @@ const { containerExec } = require('../functions/system')
|
||||||
|
|
||||||
exports.Dashboard = async function (req, res) {
|
exports.Dashboard = async function (req, res) {
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
let caddy = 'd-none';
|
||||||
|
|
||||||
// get user data with matching UUID from sqlite database
|
if (process.env.Proxy_Manager == 'enabled') {
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID } });
|
caddy = '';
|
||||||
|
|
||||||
let caddy = 'd-none';
|
|
||||||
|
|
||||||
if (process.env.Proxy_Manager == 'enabled') {
|
|
||||||
caddy = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the home page
|
|
||||||
res.render("pages/dashboard", {
|
|
||||||
name: user.first_name + ' ' + user.last_name,
|
|
||||||
role: user.role,
|
|
||||||
avatar: user.avatar,
|
|
||||||
isLoggedIn: true,
|
|
||||||
site_list: req.app.locals.site_list,
|
|
||||||
caddy: caddy
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render the home page
|
||||||
|
res.render("pages/dashboard", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
site_list: req.app.locals.site_list,
|
||||||
|
caddy: caddy
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +31,7 @@ exports.AddSite = async function (req, res) {
|
||||||
|
|
||||||
let { domain, type, host, port } = req.body;
|
let { domain, type, host, port } = req.body;
|
||||||
|
|
||||||
if ((req.session.role == "admin") && ( domain && type && host && port)) {
|
if ( domain && type && host && port) {
|
||||||
|
|
||||||
|
|
||||||
let { domain, type, host, port } = req.body;
|
let { domain, type, host, port } = req.body;
|
||||||
|
@ -107,7 +96,7 @@ exports.AddSite = async function (req, res) {
|
||||||
res.redirect("/");
|
res.redirect("/");
|
||||||
} else {
|
} else {
|
||||||
// Redirect
|
// Redirect
|
||||||
console.log('not admin or missing info')
|
console.log('missing info')
|
||||||
res.redirect("/");
|
res.redirect("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,32 +104,27 @@ exports.AddSite = async function (req, res) {
|
||||||
|
|
||||||
exports.RemoveSite = async function (req, res) {
|
exports.RemoveSite = async function (req, res) {
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
for (const [key, value] of Object.entries(req.body)) {
|
||||||
|
|
||||||
|
execSync(`rm ./caddyfiles/sites/${value}.Caddyfile`, (err, stdout, stderr) => {
|
||||||
|
if (err) { console.error(`error: ${err.message}`); return; }
|
||||||
|
if (stderr) { console.error(`stderr: ${stderr}`); return; }
|
||||||
|
console.log(`removed ${value}.Caddyfile`);
|
||||||
|
});
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(req.body)) {
|
|
||||||
|
|
||||||
execSync(`rm ./caddyfiles/sites/${value}.Caddyfile`, (err, stdout, stderr) => {
|
|
||||||
if (err) { console.error(`error: ${err.message}`); return; }
|
|
||||||
if (stderr) { console.error(`stderr: ${stderr}`); return; }
|
|
||||||
console.log(`removed ${value}.Caddyfile`);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let reload = {
|
|
||||||
container: 'DweebProxy',
|
|
||||||
command: `caddy reload --config /etc/caddy/Caddyfile`
|
|
||||||
}
|
|
||||||
await containerExec(reload);
|
|
||||||
|
|
||||||
|
|
||||||
console.log('Removed Site(s)')
|
|
||||||
|
|
||||||
res.redirect("/refreshsites");
|
|
||||||
} else {
|
|
||||||
res.redirect("/");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let reload = {
|
||||||
|
container: 'DweebProxy',
|
||||||
|
command: `caddy reload --config /etc/caddy/Caddyfile`
|
||||||
|
}
|
||||||
|
await containerExec(reload);
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Removed Site(s)')
|
||||||
|
|
||||||
|
res.redirect("/refreshsites");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,100 +134,82 @@ exports.RefreshSites = async function (req, res) {
|
||||||
let domain, type, host, port;
|
let domain, type, host, port;
|
||||||
let id = 1;
|
let id = 1;
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
// Clear site_list.ejs
|
||||||
|
req.app.locals.site_list = "";
|
||||||
|
|
||||||
|
|
||||||
|
// check if ./caddyfiles/sites contains any .json files, then delete them
|
||||||
// Clear site_list.ejs
|
try {
|
||||||
req.app.locals.site_list = "";
|
let files = readdirSync('./caddyfiles/sites/');
|
||||||
|
files.forEach(file => {
|
||||||
|
if (file.includes(".json")) {
|
||||||
// check if ./caddyfiles/sites contains any .json files, then delete them
|
execSync(`rm ./caddyfiles/sites/${file}`, (err, stdout, stderr) => {
|
||||||
try {
|
if (err) { console.error(`error: ${err.message}`); return; }
|
||||||
let files = readdirSync('./caddyfiles/sites/');
|
if (stderr) { console.error(`stderr: ${stderr}`); return; }
|
||||||
files.forEach(file => {
|
console.log(`removed ${file}`);
|
||||||
if (file.includes(".json")) {
|
});
|
||||||
execSync(`rm ./caddyfiles/sites/${file}`, (err, stdout, stderr) => {
|
|
||||||
if (err) { console.error(`error: ${err.message}`); return; }
|
|
||||||
if (stderr) { console.error(`stderr: ${stderr}`); return; }
|
|
||||||
console.log(`removed ${file}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) { console.log("No .json files to delete") }
|
|
||||||
|
|
||||||
// get list of Caddyfiles
|
|
||||||
let sites = readdirSync('./caddyfiles/sites/');
|
|
||||||
|
|
||||||
|
|
||||||
sites.forEach(site_name => {
|
|
||||||
// convert the caddyfile of each site to json
|
|
||||||
let convert = {
|
|
||||||
container: 'DweebProxy',
|
|
||||||
command: `caddy adapt --config ./caddyfiles/sites/${site_name} --pretty >> ./caddyfiles/sites/${site_name}.json`
|
|
||||||
}
|
}
|
||||||
containerExec(convert);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// read the json file
|
|
||||||
let site_file = readFileSync(`./caddyfiles/sites/${site_name}.json`, 'utf8');
|
|
||||||
// fix whitespace and parse the json file
|
|
||||||
site_file = site_file.replace(/ /g, " ");
|
|
||||||
site_file = JSON.parse(site_file);
|
|
||||||
} catch (error) { console.log("No .json file to read") }
|
|
||||||
|
|
||||||
|
|
||||||
// get the domain, type, host, and port from the json file
|
|
||||||
try { domain = site_file.apps.http.servers.srv0.routes[0].match[0].host[0] } catch (error) { console.log("No Domain") }
|
|
||||||
try { type = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].handler } catch (error) { console.log("No Type") }
|
|
||||||
try { host = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].upstreams[0].dial.split(":")[0] } catch (error) { console.log("Not Localhost") }
|
|
||||||
try { port = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].upstreams[0].dial.split(":")[1] } catch (error) { console.log("No Port") }
|
|
||||||
|
|
||||||
// build the site card
|
|
||||||
let site = siteCard(type, domain, host, port, id);
|
|
||||||
|
|
||||||
// append the site card to site_list
|
|
||||||
req.app.locals.site_list += site;
|
|
||||||
|
|
||||||
id++;
|
|
||||||
});
|
});
|
||||||
|
} catch (error) { console.log("No .json files to delete") }
|
||||||
|
|
||||||
res.redirect("/");
|
// get list of Caddyfiles
|
||||||
} else {
|
let sites = readdirSync('./caddyfiles/sites/');
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/");
|
|
||||||
}
|
sites.forEach(site_name => {
|
||||||
|
// convert the caddyfile of each site to json
|
||||||
|
let convert = {
|
||||||
|
container: 'DweebProxy',
|
||||||
|
command: `caddy adapt --config ./caddyfiles/sites/${site_name} --pretty >> ./caddyfiles/sites/${site_name}.json`
|
||||||
|
}
|
||||||
|
containerExec(convert);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// read the json file
|
||||||
|
let site_file = readFileSync(`./caddyfiles/sites/${site_name}.json`, 'utf8');
|
||||||
|
// fix whitespace and parse the json file
|
||||||
|
site_file = site_file.replace(/ /g, " ");
|
||||||
|
site_file = JSON.parse(site_file);
|
||||||
|
} catch (error) { console.log("No .json file to read") }
|
||||||
|
|
||||||
|
|
||||||
|
// get the domain, type, host, and port from the json file
|
||||||
|
try { domain = site_file.apps.http.servers.srv0.routes[0].match[0].host[0] } catch (error) { console.log("No Domain") }
|
||||||
|
try { type = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].handler } catch (error) { console.log("No Type") }
|
||||||
|
try { host = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].upstreams[0].dial.split(":")[0] } catch (error) { console.log("Not Localhost") }
|
||||||
|
try { port = site_file.apps.http.servers.srv0.routes[0].handle[0].routes[0].handle[1].upstreams[0].dial.split(":")[1] } catch (error) { console.log("No Port") }
|
||||||
|
|
||||||
|
// build the site card
|
||||||
|
let site = siteCard(type, domain, host, port, id);
|
||||||
|
|
||||||
|
// append the site card to site_list
|
||||||
|
req.app.locals.site_list += site;
|
||||||
|
|
||||||
|
id++;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
res.redirect("/");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.DisableSite = async function (req, res) {
|
exports.DisableSite = async function (req, res) {
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
|
||||||
|
|
||||||
|
|
||||||
console.log(req.body)
|
console.log(req.body)
|
||||||
console.log('Disable Site')
|
console.log('Disable Site')
|
||||||
|
|
||||||
|
res.redirect("/");
|
||||||
|
|
||||||
res.redirect("/");
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exports.EnableSite = async function (req, res) {
|
exports.EnableSite = async function (req, res) {
|
||||||
|
|
||||||
|
console.log(req.body)
|
||||||
|
console.log('Enable Site')
|
||||||
|
|
||||||
if (req.session.role == "admin") {
|
res.redirect("/");
|
||||||
|
|
||||||
|
|
||||||
console.log(req.body)
|
|
||||||
console.log('Enable Site')
|
|
||||||
|
|
||||||
res.redirect("/");
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,54 +1,48 @@
|
||||||
const User = require('../database/UserModel');
|
const User = require('../database/UserModel');
|
||||||
|
|
||||||
exports.Images = async function(req, res) {
|
exports.Images = async function(req, res) {
|
||||||
if (req.session.role == "admin") {
|
|
||||||
|
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>`
|
||||||
|
|
||||||
// Get the user.
|
let users = await User.findAll();
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
users.forEach((account) => {
|
||||||
let user_list = `
|
full_name = account.first_name + ' ' + account.last_name;
|
||||||
|
user_info = `
|
||||||
<tr>
|
<tr>
|
||||||
<th><input class="form-check-input" type="checkbox"></th>
|
<td><input class="form-check-input" type="checkbox"></td>
|
||||||
<th>ID</th>
|
<td>${user.id}</td>
|
||||||
<th>Avatar</th>
|
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||||
<th>Name</th>
|
<td>${full_name}</td>
|
||||||
<th>Username</th>
|
<td>${account.username}</td>
|
||||||
<th>Email</th>
|
<td>${account.email}</td>
|
||||||
<th>UUID</th>
|
<td>${account.UUID}</td>
|
||||||
<th>Role</th>
|
<td>${account.role}</td>
|
||||||
<th>Status</th>
|
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||||
<th>Actions</th>
|
<td><a href="#" class="btn">Edit</a></td>
|
||||||
</tr>`
|
</tr>`
|
||||||
|
|
||||||
let users = await User.findAll();
|
user_list += user_info;
|
||||||
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/images", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
user_list: user_list
|
||||||
|
});
|
||||||
|
|
||||||
// Render the home page
|
|
||||||
res.render("pages/images", {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,54 +1,48 @@
|
||||||
const User = require('../database/UserModel');
|
const User = require('../database/UserModel');
|
||||||
|
|
||||||
exports.Users = async function(req, res) {
|
exports.Networks = async function(req, res) {
|
||||||
if (req.session.role == "admin") {
|
|
||||||
|
|
||||||
// Get the user.
|
let user_list = `
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
<tr>
|
||||||
let user_list = `
|
<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>
|
<tr>
|
||||||
<th><input class="form-check-input" type="checkbox"></th>
|
<td><input class="form-check-input" type="checkbox"></td>
|
||||||
<th>ID</th>
|
<td>${user.id}</td>
|
||||||
<th>Avatar</th>
|
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||||
<th>Name</th>
|
<td>${full_name}</td>
|
||||||
<th>Username</th>
|
<td>${account.username}</td>
|
||||||
<th>Email</th>
|
<td>${account.email}</td>
|
||||||
<th>UUID</th>
|
<td>${account.UUID}</td>
|
||||||
<th>Role</th>
|
<td>${account.role}</td>
|
||||||
<th>Status</th>
|
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||||
<th>Actions</th>
|
<td><a href="#" class="btn">Edit</a></td>
|
||||||
</tr>`
|
</tr>`
|
||||||
|
|
||||||
let users = await User.findAll();
|
user_list += user_info;
|
||||||
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: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
user_list: user_list
|
||||||
|
});
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -2,21 +2,13 @@ const User = require('../database/UserModel.js');
|
||||||
const Server = require('../database/ServerSettings.js');
|
const Server = require('../database/ServerSettings.js');
|
||||||
|
|
||||||
exports.Settings = async function(req, res) {
|
exports.Settings = async function(req, res) {
|
||||||
if (req.session.role == "admin") {
|
|
||||||
// Get the user.
|
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
|
||||||
|
|
||||||
|
// Render the home page
|
||||||
|
res.render("pages/settings", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true
|
||||||
|
});
|
||||||
|
|
||||||
// Render the home page
|
|
||||||
res.render("pages/settings", {
|
|
||||||
name: user.first_name + ' ' + user.last_name,
|
|
||||||
role: user.role,
|
|
||||||
avatar: user.avatar,
|
|
||||||
isLoggedIn: true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Redirect to the login page
|
|
||||||
res.redirect("/login");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,54 +1,48 @@
|
||||||
const User = require('../database/UserModel');
|
const User = require('../database/UserModel');
|
||||||
|
|
||||||
exports.Users = async function(req, res) {
|
exports.Users = async function(req, res) {
|
||||||
if (req.session.role == "admin") {
|
|
||||||
|
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>`
|
||||||
|
|
||||||
// Get the user.
|
let users = await User.findAll();
|
||||||
let user = await User.findOne({ where: { UUID: req.session.UUID }});
|
users.forEach((account) => {
|
||||||
let user_list = `
|
full_name = account.first_name + ' ' + account.last_name;
|
||||||
|
user_info = `
|
||||||
<tr>
|
<tr>
|
||||||
<th><input class="form-check-input" type="checkbox"></th>
|
<td><input class="form-check-input" type="checkbox"></td>
|
||||||
<th>ID</th>
|
<td>${user.id}</td>
|
||||||
<th>Avatar</th>
|
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||||
<th>Name</th>
|
<td>${full_name}</td>
|
||||||
<th>Username</th>
|
<td>${account.username}</td>
|
||||||
<th>Email</th>
|
<td>${account.email}</td>
|
||||||
<th>UUID</th>
|
<td>${account.UUID}</td>
|
||||||
<th>Role</th>
|
<td>${account.role}</td>
|
||||||
<th>Status</th>
|
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||||
<th>Actions</th>
|
<td><a href="#" class="btn">Edit</a></td>
|
||||||
</tr>`
|
</tr>`
|
||||||
|
|
||||||
let users = await User.findAll();
|
user_list += user_info;
|
||||||
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: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
user_list: user_list
|
||||||
|
});
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,54 +1,49 @@
|
||||||
const User = require('../database/UserModel');
|
const User = require('../database/UserModel');
|
||||||
|
|
||||||
exports.Users = async function(req, res) {
|
exports.Volumes = 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 = `
|
||||||
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>
|
<tr>
|
||||||
<th><input class="form-check-input" type="checkbox"></th>
|
<td><input class="form-check-input" type="checkbox"></td>
|
||||||
<th>ID</th>
|
<td>${user.id}</td>
|
||||||
<th>Avatar</th>
|
<td><span class="avatar me-2">${account.avatar}</span></td>
|
||||||
<th>Name</th>
|
<td>${full_name}</td>
|
||||||
<th>Username</th>
|
<td>${account.username}</td>
|
||||||
<th>Email</th>
|
<td>${account.email}</td>
|
||||||
<th>UUID</th>
|
<td>${account.UUID}</td>
|
||||||
<th>Role</th>
|
<td>${account.role}</td>
|
||||||
<th>Status</th>
|
<td><span class="badge badge-outline text-green">Active</span></td>
|
||||||
<th>Actions</th>
|
<td><a href="#" class="btn">Edit</a></td>
|
||||||
</tr>`
|
</tr>`
|
||||||
|
|
||||||
let users = await User.findAll();
|
user_list += user_info;
|
||||||
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/volumes", {
|
||||||
|
name: req.session.user,
|
||||||
|
role: req.session.role,
|
||||||
|
avatar: req.session.avatar,
|
||||||
|
isLoggedIn: true,
|
||||||
|
user_list: user_list
|
||||||
|
});
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -9,7 +9,6 @@ services:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
PORT: 8000
|
PORT: 8000
|
||||||
SECRET: MrWiskers
|
SECRET: MrWiskers
|
||||||
#Proxy_Manager: enabled
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 8000:8000
|
- 8000:8000
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const { currentLoad, mem, networkStats, fsSize, dockerContainerStats, networkInterfaces } = require('systeminformation');
|
const { currentLoad, mem, networkStats, fsSize, dockerContainerStats, dockerImages, networkInterfaces } = require('systeminformation');
|
||||||
var Docker = require('dockerode');
|
var Docker = require('dockerode');
|
||||||
var docker = new Docker({ socketPath: '/var/run/docker.sock' });
|
var docker = new Docker({ socketPath: '/var/run/docker.sock' });
|
||||||
const { dashCard } = require('../components/dashCard');
|
const { dashCard } = require('../components/dashCard');
|
||||||
|
@ -317,31 +317,16 @@ module.exports.containerLogs = function (data) {
|
||||||
|
|
||||||
|
|
||||||
module.exports.dockerImages = async function () {
|
module.exports.dockerImages = async function () {
|
||||||
let image_list = '';
|
|
||||||
|
const data = await dockerImages({ all: true });
|
||||||
|
|
||||||
const data = await docker.listImages();
|
for ( i = 0; i < data.length; i++) {
|
||||||
|
console.log(`Image ${i}:`)
|
||||||
|
console.log(`repoTags: ${data[i].repoTags}`)
|
||||||
|
// console.log(`repoDigest: ${data[i].repoDigests}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
2020
public/libs/list.js/dist/list.js
vendored
Normal file
2020
public/libs/list.js/dist/list.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
1
public/libs/list.js/dist/list.js.map
vendored
Normal file
1
public/libs/list.js/dist/list.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/libs/list.js/dist/list.min.js
vendored
Normal file
2
public/libs/list.js/dist/list.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/list.js/dist/list.min.js.map
vendored
Normal file
1
public/libs/list.js/dist/list.min.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"list.min.js","sources":["webpack://List/list.min.js"],"mappings":"AAAA","sourceRoot":""}
|
|
@ -15,10 +15,11 @@ const { Settings } = require("../controllers/settings");
|
||||||
|
|
||||||
// Authentication middleware
|
// Authentication middleware
|
||||||
const authenticate = (req, res, next) => {
|
const authenticate = (req, res, next) => {
|
||||||
if (req.session && req.session.user) {
|
if (req.session && req.session.role == "admin") {
|
||||||
console.log(`User ${req.session.user} [${req.session.role} : ${req.session.UUID}] accessed ${req.originalUrl}`)
|
console.log(`User ${req.session.user} [${req.session.role}] accessed ${req.originalUrl}`)
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
console.log('Not admin')
|
||||||
res.redirect("/login");
|
res.redirect("/login");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<div class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h2 class="page-title">
|
<h2 class="page-title">
|
||||||
Users
|
Images
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -359,8 +359,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Libs JS -->
|
<!-- Libs JS -->
|
||||||
|
<script src="/libs/list.js/dist/list.min.js?1692870487" defer></script>
|
||||||
<!-- Tabler Core -->
|
<!-- Tabler Core -->
|
||||||
<script src="/js/tabler.min.js?1685973381" defer></script>
|
<script src="/js/tabler.min.js?1685973381" defer></script>
|
||||||
<script src="/js/demo.min.js?1685973381" defer></script>
|
<script src="/js/demo.min.js?1685973381" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const list = new List('table-default', {
|
||||||
|
sortClass: 'table-sort',
|
||||||
|
listClass: 'table-tbody',
|
||||||
|
valueNames: [ 'sort-name', 'sort-type', 'sort-city', 'sort-score',
|
||||||
|
{ attr: 'data-date', name: 'sort-date' },
|
||||||
|
{ attr: 'data-progress', name: 'sort-progress' },
|
||||||
|
'sort-quantity'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
<title>Users</title>
|
<title>Networks</title>
|
||||||
<link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
|
<link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
|
||||||
<link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
|
<link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
|
||||||
<style>
|
<style>
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<div class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h2 class="page-title">
|
<h2 class="page-title">
|
||||||
Users
|
Networks
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,8 +64,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Libs JS -->
|
<!-- Libs JS -->
|
||||||
|
<script src="/libs/list.js/dist/list.min.js?1692870487" defer></script>
|
||||||
<!-- Tabler Core -->
|
<!-- Tabler Core -->
|
||||||
<script src="/js/tabler.min.js?1685973381" defer></script>
|
<script src="/js/tabler.min.js?1685973381" defer></script>
|
||||||
<script src="/js/demo.min.js?1685973381" defer></script>
|
<script src="/js/demo.min.js?1685973381" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const list = new List('table-default', {
|
||||||
|
sortClass: 'table-sort',
|
||||||
|
listClass: 'table-tbody',
|
||||||
|
valueNames: [ 'sort-name', 'sort-type', 'sort-city', 'sort-score',
|
||||||
|
{ attr: 'data-date', name: 'sort-date' },
|
||||||
|
{ attr: 'data-progress', name: 'sort-progress' },
|
||||||
|
'sort-quantity'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
<title>Users</title>
|
<title>Volumes</title>
|
||||||
<link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
|
<link href="/css/tabler.min.css?1685973381" rel="stylesheet"/>
|
||||||
<link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
|
<link href="/css/demo.min.css?1685973381" rel="stylesheet"/>
|
||||||
<style>
|
<style>
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<div class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h2 class="page-title">
|
<h2 class="page-title">
|
||||||
Users
|
Volumes
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,8 +64,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Libs JS -->
|
<!-- Libs JS -->
|
||||||
|
<script src="/libs/list.js/dist/list.min.js?1692870487" defer></script>
|
||||||
<!-- Tabler Core -->
|
<!-- Tabler Core -->
|
||||||
<script src="/js/tabler.min.js?1685973381" defer></script>
|
<script src="/js/tabler.min.js?1685973381" defer></script>
|
||||||
<script src="/js/demo.min.js?1685973381" defer></script>
|
<script src="/js/demo.min.js?1685973381" defer></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const list = new List('table-default', {
|
||||||
|
sortClass: 'table-sort',
|
||||||
|
listClass: 'table-tbody',
|
||||||
|
valueNames: [ 'sort-name', 'sort-type', 'sort-city', 'sort-score',
|
||||||
|
{ attr: 'data-date', name: 'sort-date' },
|
||||||
|
{ attr: 'data-progress', name: 'sort-progress' },
|
||||||
|
'sort-quantity'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Add table
Reference in a new issue