Fixed app search and install

This commit is contained in:
lllllllillllllillll 2024-03-17 19:32:02 -07:00
parent c2f06639f5
commit 7c5670e92b
7 changed files with 79 additions and 43 deletions

View File

@ -6,6 +6,8 @@
* Independently updating container cards. * Independently updating container cards.
* Container cards display pending actions (starting, stopping, pausing, restarting). * Container cards display pending actions (starting, stopping, pausing, restarting).
* Dynamically generated avatars. * Dynamically generated avatars.
* Updated database models.
* Persistent Database.
## v0.40 (Feb 26th 2024) - HTMX rewrite ## v0.40 (Feb 26th 2024) - HTMX rewrite
* Pages rewritten to use HTMX. * Pages rewritten to use HTMX.

View File

@ -12,8 +12,8 @@ Alpha v0.50 ( :fire: Experimental :fire: )
[![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE) [![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE)
[![Coffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/lllllllillllllillll) [![Coffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/lllllllillllllillll)
* This is a personal project I started to get more familiar with Javascript and Node.js. * I started this as a personal project to get more familiar with Javascript and Node.js.
* Some UI elements are placeholders and every version may have breaking changes. * I'm open to any contributions, but you may want to wait until I reach v1.0 first.
* Please post issues and discussions so I know what bugs and features to focus on. * Please post issues and discussions so I know what bugs and features to focus on.
<a href="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard1.png"><img src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard1.png" width="25%"/></a> <a href="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard1.png"><img src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard1.png" width="25%"/></a>
@ -30,6 +30,7 @@ Alpha v0.50 ( :fire: Experimental :fire: )
## Features ## Features
* [x] Dashboard provides server metrics, container metrics, and container controls, on a single page. * [x] Dashboard provides server metrics, container metrics, and container controls, on a single page.
* [x] View container logs. * [x] View container logs.
* [x] View container logs.
* [ ] Update containers (planned). * [ ] Update containers (planned).
* [x] Manage your Docker networks, images, and volumes. * [x] Manage your Docker networks, images, and volumes.
* [x] Light/Dark Mode. * [x] Light/Dark Mode.
@ -38,9 +39,8 @@ Alpha v0.50 ( :fire: Experimental :fire: )
* [x] Multi-User built-in. * [x] Multi-User built-in.
* [ ] Permissions system (in development). * [ ] Permissions system (in development).
* [x] Support for Windows, Linux, and MacOS. * [x] Support for Windows, Linux, and MacOS.
* [ ] Docker compose import (in development). * [ ] Docker compose (in development).
* [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.
* [ ] Preset variables (planned). * [ ] Preset variables (planned).
* [ ] Themes (planned). * [ ] Themes (planned).
@ -53,7 +53,7 @@ version: "3.9"
services: services:
dweebui: dweebui:
container_name: dweebui container_name: dweebui
image: lllllllillllllillll/dweebui:v0.40 image: lllllllillllllillll/dweebui:v0.50
environment: environment:
PORT: 8000 PORT: 8000
SECRET: MrWiskers SECRET: MrWiskers

View File

@ -103,8 +103,32 @@ export const appSearch = async (req, res) => {
searchTemplates(search); searchTemplates(search);
for (let i = 0; i < results.length; i++) { for (let i = 0; i < results.length; i++) {
let app_card = appCard(results[i]); let appCard = readFileSync('./views/partials/appCard.html', 'utf8');
apps_list += app_card; let name = results[i].name || results[i].title.toLowerCase();
let desc = results[i].description.slice(0, 60) + "...";
let description = results[i].description.replaceAll(". ", ".\n") || "no description available";
let note = results[i].note ? results[i].note.replaceAll(". ", ".\n") : "no notes available";
let image = results[i].image;
let logo = results[i].logo;
let categories = '';
// set data.catagories to 'other' if data.catagories is empty or undefined
if (results[i].categories == null || results[i].categories == undefined || results[i].categories == '') {
results[i].categories = ['Other'];
}
for (let c = 0; c < results[i].categories.length; c++) {
categories += CatagoryColor(results[i].categories[c]);
}
appCard = appCard.replace(/AppName/g, name);
appCard = appCard.replace(/AppShortName/g, name);
appCard = appCard.replace(/AppDesc/g, desc);
appCard = appCard.replace(/AppLogo/g, logo);
appCard = appCard.replace(/AppCategories/g, categories);
apps_list += appCard;
} }
res.render("apps", { res.render("apps", {
@ -113,7 +137,7 @@ export const appSearch = async (req, res) => {
avatar: req.session.avatar, avatar: req.session.avatar,
list_start: list_start + 1, list_start: list_start + 1,
list_end: list_end, list_end: list_end,
app_count: templates.length, app_count: results.length,
prev: prev, prev: prev,
next: next, next: next,
apps_list: apps_list apps_list: apps_list

View File

@ -154,10 +154,10 @@ export const Permission = sequelize.define('Permission', {
hide: { hide: {
type: DataTypes.STRING type: DataTypes.STRING
}, },
view: { reset_view: {
type: DataTypes.STRING type: DataTypes.STRING
}, },
reset_view: { view: {
type: DataTypes.STRING type: DataTypes.STRING
}, },
}); });
@ -207,10 +207,40 @@ export const Notification = sequelize.define('Notification', {
color: { color: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
read: {
type: DataTypes.STRING,
},
createdAt : { createdAt : {
type: DataTypes.STRING type: DataTypes.STRING
}, },
createdBy : { createdBy : {
type: DataTypes.STRING type: DataTypes.STRING
}, },
});
export const Settings = sequelize.define('Settings', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
key: {
type: DataTypes.STRING,
allowNull: false
},
value: {
type: DataTypes.STRING,
allowNull: false
}
});
export const Variables = sequelize.define('Variables', {
find: {
type: DataTypes.STRING,
},
replace: {
type: DataTypes.STRING,
}
}); });

View File

@ -7,10 +7,10 @@ services:
PORT: 8000 PORT: 8000
SECRET: MrWiskers SECRET: MrWiskers
restart: unless-stopped restart: unless-stopped
expose: ports:
- 8000:8000 - 8000:8000
volumes: volumes:
- dweebui:/app - dweebui:/app/database/
# Docker socket # Docker socket
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
# Podman socket # Podman socket

View File

@ -88,13 +88,6 @@ export const Install = async (req, res) => {
if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] != '') && (data[`volume_${i}_container`] != '')) { if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] != '') && (data[`volume_${i}_container`] != '')) {
compose_file += `\n - ${data[`volume_${i}_bind`]}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}` compose_file += `\n - ${data[`volume_${i}_bind`]}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}`
} }
// if bind is empty create a docker volume (ex container_name_config:/config) convert any '/' in container name to '_'
else if ((data[`volume${i}`] == 'on') && (data[`volume_${i}_bind`] == '') && (data[`volume_${i}_container`] != '')) {
let volume_name = data[`volume_${i}_container`].replace(/\//g, '_');
compose_file += `\n - ${name}_${volume_name}:${data[`volume_${i}_container`]}:${data[`volume_${i}_readwrite`]}`
docker_volumes.push(`${name}_${volume_name}`);
}
} }

View File

@ -27,45 +27,32 @@
<div class="page-wrapper"> <div class="page-wrapper">
<!-- Page header --> <!-- Page header -->
<div class="page-header d-print-none"> <div class="mt-3 d-print-none">
<div class="container-xl"> <div class="container-xl">
<div class="row g-2 align-items-center"> <div class="row g-2 align-items-center">
<div class="col"> <div class="col">
<label class="text-secondary"><%= list_start %> - <%= list_end %> of <%= app_count %> Apps.</label>
<div class="text-secondary mt-1"><%= list_start %> - <%= list_end %> of <%= app_count %> Apps.</div>
</div> </div>
<!-- Page title actions --> <!-- Page title actions -->
<div class="col-auto ms-auto d-print-none"> <div class="col-auto ms-auto d-print-none">
<div class="d-flex align-items-center">
<div class="d-flex"> <div class="me-2">
<select class="form-select">
<option>Templates.json (default)</option>
<option>Compose</option>
</select>
</div>
<form action="/apps" id="search" name="search" method="POST"> <form action="/apps" id="search" name="search" method="POST">
<input type="search" class="form-control" name="search" placeholder="Search apps…"> <input type="search" class="form-control" name="search" placeholder="Search apps…" >
</form> </form>
<input type="submit" form="search" class="btn btn-outline-success h-50" value="search"> <input type="submit" form="search" class="btn btn-outline-success h-50" value="search">
<div class="card-actions btn-actions">
<div class="card-actions btn-actions">
<div class="dropdown">
<a href="#" class="btn-action dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Change Templates">
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-settings" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z" /><path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" /></svg>
</a>
<div class="dropdown-menu dropdown-menu-end">
<a class="dropdown-item" href="#">Default Template</a>
<a class="dropdown-item" href="#">Compose Files</a>
<a class="dropdown-item" href="#">Custom Template</a>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Page body --> <!-- Page body -->
<div class="page-body"> <div class="mt-3">
<div class="container-xl"> <div class="container-xl">
<div class="row row-cards"> <div class="row row-cards">