فهرست منبع

Dashboard cards are now html components.

lllllllillllllillll 1 سال پیش
والد
کامیت
cfe9660ac2
7فایلهای تغییر یافته به همراه151 افزوده شده و 34 حذف شده
  1. 1 1
      README.md
  2. 63 26
      controllers/dashboard.js
  3. 1 1
      docker-compose.yaml
  4. 1 0
      server.js
  5. 80 0
      views/components/containerCard.html
  6. 4 4
      views/dashboard.html
  7. 1 2
      views/footer.html

+ 1 - 1
README.md

@@ -1,7 +1,7 @@
 # DweebUI
 DweebUI is a web interface for managing Docker, with a zero-config dashboard for controlling and monitoring your containers.
 
-Alpha v0.40 ( :fire: Experimental :fire: )
+Alpha v0.50 ( :fire: Experimental :fire: )
 
    
 [:warning: DweebUI is a management interface and should not be directly exposed to the internet :warning:](https://github.com/lllllllillllllillll/DweebUI/wiki/Exposing-DweebUI-to-the-Internet)

+ 63 - 26
controllers/dashboard.js

@@ -4,7 +4,10 @@ import { modal } from '../components/modal.js';
 import { permissionsModal } from '../components/permissions_modal.js';
 import { setEvent, cpu, ram, tx, rx, disk, docker } from '../server.js';
 import { dockerContainerStats } from 'systeminformation';
-import { containerCard } from '../components/containerCard.js';
+// import { containerCard } from '../components/containerCard.js';
+import { readFileSync } from 'fs';
+
+let containerCard = readFileSync('./views/components/containerCard.html', 'utf8');
 
 let [ hidden, cardList ] = [ '', '' ];
 
@@ -200,13 +203,69 @@ async function containerCards() {
                 ports: ports_list,
                 link: 'localhost',
             }
-            let card = containerCard(container_info);
+            
+            let name = container.Names[0].slice(1);
+            let state = container.State;
+            
+            let wrapped = name;
+            let disable = "";
+            let chartName = name.replace(/-/g, '');
+          
+            // shorten long names
+            if (name.length > 13) { wrapped = name.slice(0, 10) + '...'; }
+            // disable buttons for dweebui
+            if (name.startsWith('dweebui')) { disable = 'disabled=""'; }
+          
+            // if ( external_port == undefined ) { external_port = 0; }
+            // if ( internal_port == undefined ) { internal_port = 0; }
+          
+            let state_indicator = 'green';
+            if (state == 'exited') {
+                state = 'stopped';
+                state_indicator = 'red';
+            } else if (state == 'paused') {
+                state_indicator = 'orange';
+            }
+          
+            let noChart = 'hx-swap="none"';
+            if (state == 'running') { noChart = ''; }
+          
+            let ports_data = [];
+            // if (ports) {
+            //   ports_data = ports;
+            // } else {
+            //   for (let i = 0; i < 12; i++) {
+          
+            //     let port_check = "checked";
+            //     let external = i;
+            //     let internal = i;
+            //     let protocol = "tcp";
+          
+            //     ports_data.push({
+            //       check: port_check,
+            //       external: external,
+            //       internal: internal,
+            //       protocol: protocol
+            //     });
+            //   }
+            // }
+          
+            let card = containerCard;
+            card = card.replace(/AppName/g, name);
+            card = card.replace(/AppShortName/g, wrapped);
+            card = card.replace(/ChartName/g, chartName);
+            card = card.replace(/AppIcon/g, service);
+            card = card.replace(/AppState/g, state);
+            card = card.replace(/StateColor/g, state_indicator);
             list += card;
         }
     }
     cardList = list;
 }
 
+
+
+
 export const Containers = async (req, res) => {
     await getHidden();
     await containerCards();
@@ -271,28 +330,6 @@ export const Installs = async (req, res) => {
     let name = req.header('hx-trigger-name');
     let all_containers = '';
 
-    await docker.listContainers({ all: true }).then(containers => {
-        containers.forEach(container => {
-            if (container.Names[0].slice(1) == name) {
-                return;
-            }
-        });
-
-        let install_info = {
-            name: name,
-            service: 'Service Name',
-            id: '',
-            state: '',
-            image: '',
-            external_port: 0,
-            internal_port: 0,
-            ports: '',
-            link: 'localhost',
-        }
-        let card = containerCard(install_info);
-        res.send(card);
-
-    });
-
-    
+    res.send('ok');
+   
 }

+ 1 - 1
docker-compose.yaml

@@ -2,7 +2,7 @@ version: "3.9"
 services:
   dweebui:
     container_name: dweebui
-    image: lllllllillllllillll/dweebui:v0.40
+    image: lllllllillllllillll/dweebui:v0.50
     environment:
       PORT: 8000
       SECRET: MrWiskers

+ 1 - 0
server.js

@@ -88,6 +88,7 @@ router.get('/sse_event', (req, res) => {
             });
         });
         if ((all_containers != sent_list) || (event == true)) {
+            console.log('event triggered');
             sent_list = all_containers;
             event = false;
             res.write(`event: ${eventType}\n`);

+ 80 - 0
views/components/containerCard.html

@@ -0,0 +1,80 @@
+  <div class="col-sm-6 col-lg-3 pt-1">
+    <div class="card">
+      <div class="card-body">
+        <div class="card-stamp card-stamp-sm">
+          <img width="100px" src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/AppIcon.png" onerror="this.onerror=null;this.src='https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/docker.png';"></img>
+        </div>
+        <div class="d-flex align-items-center">
+          <div class="subheader text-yellow">0:0</div>
+          <div class="ms-auto lh-1">
+            <div class="card-actions btn-actions">
+              <div class="card-actions btn-actions">
+                <button class="btn-action" title="Start" data-hx-post="/start" data-hx-trigger="click" data-hx-target="#AppNamestate" name="AppName" id="${state}" ${disable}>
+                  <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-play" 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><path d="M7 4v16l13 -8z"></path></svg>
+                </button>
+                <button class="btn-action" title="Stop" data-hx-post="/stop" data-hx-trigger="click" data-hx-target="#AppNamestate" name="AppName" id="${state}" ${disable}>
+                  <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-stop" 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><path d="M5 5m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z"></path></svg>
+                </button>
+                <button class="btn-action" title="Pause" data-hx-post="/pause" data-hx-trigger="click" data-hx-target="#AppNamestate" name="AppName" id="${state}" ${disable}>
+                  <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-pause" 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><path d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path><path d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path></svg>
+                </button>
+                <button class="btn-action" title="Restart" data-hx-post="/restart" data-hx-trigger="click" data-hx-target="#AppNamestate" name="AppName" id="${state}" ${disable}>
+                  <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-reload" 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><path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path><path d="M20 4v5h-5"></path></svg>                          
+                </button>
+                <div class="dropdown">
+                  <a href="#" class="btn-action dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                    <svg xmlns="http://www.w3.org/2000/svg" class="" 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><circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="19" r="1"></circle><circle cx="12" cy="5" r="1"></circle></svg>
+                  </a>
+                  <div class="dropdown-menu dropdown-menu-end">
+                    <button class="dropdown-item text-secondary" name="AppName" data-hx-get="/modal" data-hx-target="#modals-here" data-hx-trigger="click" data-bs-toggle="modal" data-bs-target="#modals-here">Details</button>
+                    <button class="dropdown-item text-secondary" name="AppName" id="logs" data-hx-get="/logs" data-hx-target="#logView" data-bs-toggle="modal" data-bs-target="#log_view">Logs</button>
+                    <button class="dropdown-item text-secondary" name="AppName" id="edit">Edit</button>
+                    <button class="dropdown-item text-primary" name="AppName" id="update" disabled="">Update</button>
+                    <button class="dropdown-item text-danger" name="AppName" id="remove" data-bs-toggle="modal" data-bs-target="#AppName_uninstall_modal" href="#">Remove</button>
+                  </div>
+                </div>
+                <div class="dropdown">
+                  <a href="#" class="btn-action dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                    <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-eye" 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 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" /> </svg>
+                  </a>
+                  <div class="dropdown-menu dropdown-menu-end">
+                    <button class="dropdown-item text-secondary" data-hx-post="/hide" data-hx-trigger="click" data-hx-swap="none" name="AppName" id="hide" value="hide">Hide</button>
+                    <button class="dropdown-item text-secondary" data-hx-post="/reset" data-hx-trigger="click" data-hx-swap="none" name="AppName" id="reset" value="reset">Reset View</button>
+                    <button class="dropdown-item text-secondary" name="AppName" id="permissions" data-hx-get="/modal" data-hx-target="#modals-here" data-hx-trigger="click" data-bs-toggle="modal" data-bs-target="#modals-here">Permissions</button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="d-flex align-items-baseline">
+          <div class="h1 me-2" title="AppName" style="margin-bottom: 0;">
+            <a href="http://${link}:${external_port}" target="_blank">
+              AppShortName
+            </a>
+          </div>
+          <div class="ms-auto">
+            <label id="AppState">
+              <span class="text-StateColor align-items-center lh-1">
+                  <svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-point-filled" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 7a5 5 0 1 1 -4.995 5.217l-.005 -.217l.005 -.217a5 5 0 0 1 4.995 -4.783z" stroke-width="0" fill="currentColor"></path></svg>
+                  AppState
+              </span>
+            </label>
+          </div>
+        </div>
+        
+        <script>
+          var ChartNamechart = new ApexCharts(document.querySelector("#ChartName_chart"), options);
+      </script>
+
+      <div class="chart-sm">
+        <div id="ChartName_chart" data-hx-trigger="load, every 2s" data-hx-get="/chart" name="ChartName" ${noChart}>
+          <script>
+            ChartNamechart.render();
+          </script>
+        </div>
+        
+      </div>
+      </div>
+    </div>
+  </div>

+ 4 - 4
views/dashboard.html

@@ -143,17 +143,17 @@
             
             <!-- HTMX -->
             <div class="col-12">
-              <div class="row row-cards" id="containerCards" data-hx-get="/containers" data-hx-trigger="load, sse:docker" data-hx-swap="innerHTML">
+              <div class="row row-cards" id="containerCards" data-hx-get="/containers" data-hx-trigger="load" data-hx-swap="beforeend">
 
               </div>
             </div>
 
             <!-- HTMX -->
-            <!-- <div class="col-12">
-              <div class="row row-cards" data-hx-get="/installs" name="jellyfin" data-hx-trigger="load delay:2s, sse:install" data-hx-swap="beforeend" hx-target="#containerCards">
+            <div class="col-12">
+              <div class="row row-cards" data-hx-get="/installs" data-hx-trigger="" data-hx-swap="beforeend" hx-target="#containerCards">
 
               </div>
-            </div> -->
+            </div>
             
             <!-- HTMX Target-->
             <div id="modals-here" class="modal modal-blur fade" style="display: none" aria-hidden="false" tabindex="-1">

+ 1 - 2
views/footer.html

@@ -8,7 +8,6 @@
           <li class="list-inline-item"><a href="https://github.com/lllllllillllllillll/DweebUI/tree/main" target="_blank" class="link-secondary" rel="noopener">Source code</a></li>
           <li class="list-inline-item">
             <a href="https://github.com/lllllllillllllillll/DweebUI/tree/main" target="_blank" class="link-secondary" rel="noopener">
-              <!-- Download SVG icon from http://tabler-icons.io/i/heart -->
               <svg xmlns="http://www.w3.org/2000/svg" class="icon text-pink icon-filled icon-inline" 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="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" /></svg>
               Sponsor
             </a>
@@ -24,7 +23,7 @@
           </li>
           <li class="list-inline-item">
             <a href="https://github.com/lllllllillllllillll/DweebUI/releases" class="link-secondary" rel="noopener">
-              v0.40
+              v0.50
             </a>
           </li>
         </ul>