Pārlūkot izejas kodu

Fixed app search and install

lllllllillllllillll 1 gadu atpakaļ
vecāks
revīzija
7c5670e92b
7 mainītis faili ar 79 papildinājumiem un 43 dzēšanām
  1. 2 0
      CHANGELOG.md
  2. 5 5
      README.md
  3. 27 3
      controllers/apps.js
  4. 32 2
      database/models.js
  5. 2 2
      docker-compose.yaml
  6. 0 7
      functions/install.js
  7. 11 24
      views/apps.html

+ 2 - 0
CHANGELOG.md

@@ -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.

+ 5 - 5
README.md

@@ -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.
-* Some UI elements are placeholders and every version may have breaking changes.
+* I started this as a personal project to get more familiar with Javascript and Node.js. 
+* 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

+ 27 - 3
controllers/apps.js

@@ -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]);
-        apps_list += app_card;
+      let appCard = readFileSync('./views/partials/appCard.html', 'utf8');
+      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

+ 32 - 2
database/models.js

@@ -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,
+  }
 });
 });

+ 2 - 2
docker-compose.yaml

@@ -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

+ 0 - 7
functions/install.js

@@ -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}`);
-                } 
                 
                 
             }
             }
 
 

+ 11 - 24
views/apps.html

@@ -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">
-                
-                <div class="text-secondary mt-1"><%= list_start %> - <%= list_end %> of <%= app_count %> Apps.</div>
+                <label class="text-secondary"><%= list_start %> - <%= list_end %> of <%= app_count %> Apps.</label>
               </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">
+                <div class="d-flex align-items-center">
+                  <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">