浏览代码

Initial commit

Denis V. Dedkov 1 年之前
当前提交
a407fafb65
共有 6 个文件被更改,包括 182 次插入0 次删除
  1. 6 0
      Dockerfile
  2. 29 0
      README.md
  3. 二进制
      src/favicon.ico
  4. 二进制
      src/images/lamp.png
  5. 二进制
      src/images/off.png
  6. 147 0
      src/index.html

+ 6 - 0
Dockerfile

@@ -0,0 +1,6 @@
+FROM docker.angie.software/angie:minimal
+
+WORKDIR /usr/share/angie/html
+
+COPY src/. .
+

+ 29 - 0
README.md

@@ -0,0 +1,29 @@
+# noolite-client
+Simple web UI for lights control
+
+Is the frontend for application [noolite-srv](https://gogs.dended.ru/ded/noolite-srv.git)
+
+# Building
+Just build docker image:
+
+```
+docker build . -t noolite-client
+```
+Or build crossplatform images:
+```
+docker buildx build --platform linux/amd64,linux/arm64 -t <your_tag> --push .
+```
+
+# Installation
+Install from docker registry:
+
+```
+docker pull docker.dended.ru/noolite-client
+```
+
+# Using
+Run docker container:
+
+```
+docker run -p 8000:80 -v -d --restart unless-stopped noolite-srv
+```

二进制
src/favicon.ico


二进制
src/images/lamp.png


二进制
src/images/off.png


+ 147 - 0
src/index.html

@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>nooLight</title>
+    <style>
+        html, body {
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            display: flex;
+            flex-direction: row;
+	    justify-content: center;
+        }
+
+        .list-view {
+            flex: 1;
+            display: flex;
+            flex-direction: column;
+	    max-width: 500px;
+	    min-width: 400px;
+            gap: 5px;
+            overflow-y: auto;
+            padding: 5px;
+        }
+
+        .item {
+            display: flex;
+            flex-direction: column;
+            gap: 5px;
+        }
+
+        .button {
+            display: flex;
+            align-items: center;
+            justify-content: flex-start;
+            background-color: #f0f0f0;
+            border: 1px solid #ccc;
+	    border-radius: 5px;
+	    user-select: none;
+            height: 4vh;
+        }
+
+        .button img {
+            margin-left: 10px;
+            height: 60%;
+        }
+
+        .button span {
+            flex-grow: 1;
+            text-align: center;
+        }
+
+        .row {
+            display: flex;
+            gap: 5px;
+        }
+
+        .lamp-button {
+            flex: 1;
+            border: 1px solid #ccc;
+            border-radius: 5px;
+            text-align: center;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+	    cursor: pointer;
+	    user-select: none;
+            height: 10vh; /* 10% от высоты экрана */
+
+	    &:active {
+                background-color: #f0f0f0;
+	    }
+        }
+
+        .lamp-button img {
+            height: 50%; /* 50% высоты кнопки */
+        }
+
+        .lamp-button span {
+            margin-top: 5px;
+        }
+    </style>
+</head>
+<body>
+    <div class="list-view" id="listView">
+        <!-- Items will be dynamically added here -->
+    </div>
+
+    <script>
+       fetch('static/channels.js').
+		    then( (response) => response.json() ).
+		    then( (data) => appendData(data['groups']) ).
+		    catch( (err) => console.log('error: ' + err) );
+
+        function switchLamp(channelId) {
+            fetch('noolite/switch/' + channelId).
+				    catch( (err) => console.log('error: ' + err));
+        }
+
+        function appendData(lightsModel) {
+            const listView = document.getElementById("listView");
+
+            lightsModel.forEach(group => {
+                const itemContainer = document.createElement("div");
+                itemContainer.classList.add("item");
+
+                if (group.groupName) {
+                    const button = document.createElement("div");
+                    button.classList.add("button");
+                    const img = document.createElement("img");
+                    img.src = "/images/off.png";
+                    const span = document.createElement("span");
+                    span.textContent = group.groupName;
+                    button.appendChild(img);
+                    button.appendChild(span);
+                    itemContainer.appendChild(button);
+                }
+
+                const row = document.createElement("div");
+                row.classList.add("row");
+
+                group.channels.forEach(channel => {
+                    const lampButton = document.createElement("div");
+                    lampButton.classList.add("lamp-button");
+
+                    const img = document.createElement("img");
+                    img.src = "/images/lamp.png";
+                    const span = document.createElement("span");
+                    span.textContent = channel.name;
+
+                    lampButton.appendChild(img);
+                    lampButton.appendChild(span);
+
+                    lampButton.addEventListener("click", () => switchLamp(channel.id) )
+                    row.appendChild(lampButton);
+                });
+
+                itemContainer.appendChild(row);
+                listView.appendChild(itemContainer);
+            });
+        }
+    </script>
+</body>
+</html>