mirror of
https://github.com/IoTManagerProject/IoTManagerWeb.git
synced 2026-03-26 15:02:21 +03:00
список устройств
This commit is contained in:
@@ -7,6 +7,12 @@
|
||||
"printWidth": 1000,
|
||||
"sxBracketSameLine": true,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "App.svelte",
|
||||
"options": {
|
||||
"printWidth": 1000
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "Input.svelte",
|
||||
"options": {
|
||||
@@ -18,6 +24,12 @@
|
||||
"options": {
|
||||
"printWidth": 600
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "Cross.svelte",
|
||||
"options": {
|
||||
"printWidth": 50
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
203
src/App.svelte
203
src/App.svelte
@@ -6,7 +6,7 @@
|
||||
router.mode.hash();
|
||||
|
||||
import Alarm from "./components/Alarm.svelte";
|
||||
import Progress from "./components/Progress.svelte";
|
||||
//import Progress from "./components/Progress.svelte";
|
||||
|
||||
import Modal from "./components/Modal.svelte";
|
||||
import DashboardPage from "./pages/Dashboard.svelte";
|
||||
@@ -17,6 +17,8 @@
|
||||
import ListPage from "./pages/List.svelte";
|
||||
import AboutPage from "./pages/About.svelte";
|
||||
|
||||
import CloudIcon from "./svg/Cloud.svelte";
|
||||
|
||||
//****************************************************constants section*********************************************************/
|
||||
//******************************************************************************************************************************/
|
||||
let debug = true;
|
||||
@@ -76,20 +78,16 @@
|
||||
|
||||
deviceList = [
|
||||
{
|
||||
name: "Устройство 1",
|
||||
name: "Устройство",
|
||||
id: "123456789",
|
||||
ip: "192.168.88.235",
|
||||
//ip: myip,
|
||||
status: false,
|
||||
},
|
||||
{
|
||||
name: "Устройство 2",
|
||||
id: "123456789",
|
||||
ip: "192.168.88.236",
|
||||
status: false,
|
||||
},
|
||||
];
|
||||
|
||||
let deviceListParced = false;
|
||||
|
||||
//***********************************************************blob**************************************************************/
|
||||
var MyBlobBuilder = function () {
|
||||
this.parts = [];
|
||||
@@ -102,7 +100,9 @@
|
||||
|
||||
MyBlobBuilder.prototype.getBlob = function () {
|
||||
if (!this.blob) {
|
||||
this.blob = new Blob(this.parts, { type: "binary" });
|
||||
this.blob = new Blob(this.parts, {
|
||||
type: "binary",
|
||||
});
|
||||
}
|
||||
return this.blob;
|
||||
};
|
||||
@@ -223,14 +223,14 @@
|
||||
let data = event.data;
|
||||
//if (debug) console.log("[i]", getIP(ws), "msg received", data); //
|
||||
//сборщик statusJson сообщений======================================
|
||||
if (data.includes("status")) {
|
||||
if (IsJsonParse(data)) {
|
||||
let statusJson = JSON.parse(data);
|
||||
udatelayoutJson(statusJson);
|
||||
wigetsUpdate();
|
||||
if (debug) console.log("[i]", "status json parced: ", statusJson);
|
||||
}
|
||||
}
|
||||
//if (data.includes("status")) {
|
||||
// if (IsJsonParse(data)) {
|
||||
// let statusJson = JSON.parse(data);
|
||||
// udatelayoutJson(statusJson);
|
||||
// wigetsUpdate();
|
||||
// if (debug) console.log("[i]", "status json parced: ", statusJson);
|
||||
// }
|
||||
//}
|
||||
//сборщик ssidJson сообщений======================================
|
||||
if (data.includes("ssid")) {
|
||||
if (IsJsonParse(data)) {
|
||||
@@ -241,6 +241,17 @@
|
||||
if (debug) console.log("[i]", "ssid json parced");
|
||||
}
|
||||
}
|
||||
//сборщик deviceList сообщений======================================
|
||||
if (data.includes("devicelist")) {
|
||||
if (IsJsonParse(data)) {
|
||||
deviceList = JSON.parse(data);
|
||||
delete deviceList.devicelist;
|
||||
deviceList = deviceList;
|
||||
deviceListParced = true;
|
||||
//connectToAllDevices();
|
||||
if (debug) console.log("[i]", "devicelist json parced", deviceList);
|
||||
}
|
||||
}
|
||||
//сборщик configJson пакетов========================================
|
||||
if (data === "/st/config.json") {
|
||||
//if (debug) console.log("[i]", "configJson start!");
|
||||
@@ -258,7 +269,7 @@
|
||||
configJson = JSON.parse(configJsonResult);
|
||||
configJson = configJson;
|
||||
configJsonParced = true;
|
||||
if (debug) console.log("[i]", "configJson parced!");
|
||||
if (debug) console.log("[ii]", "configJson parced!");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -279,7 +290,7 @@
|
||||
widgetsJson = JSON.parse(widgetsJsonResult);
|
||||
widgetsJson = widgetsJson;
|
||||
widgetsJsonParced = true;
|
||||
if (debug) console.log("[i]", "widgetsJson parced!");
|
||||
if (debug) console.log("[ii]", "widgetsJson parced!");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -300,7 +311,7 @@
|
||||
itemsJson = JSON.parse(itemsJsonResult);
|
||||
itemsJson = itemsJson;
|
||||
itemsJsonParced = true;
|
||||
if (debug) console.log("[i]", "itemsJson parced!");
|
||||
if (debug) console.log("[ii]", "itemsJson parced!");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -322,7 +333,7 @@
|
||||
layoutJson = layoutJson;
|
||||
wigetsUpdate();
|
||||
layoutJsonParced = true;
|
||||
if (debug) console.log("[i]", "layoutJson parced!");
|
||||
if (debug) console.log("[ii]", "layoutJson parced!");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -344,7 +355,7 @@
|
||||
settingsJson = settingsJson;
|
||||
wigetsUpdate();
|
||||
settingsJsonParced = true;
|
||||
if (debug) console.log("[i]", "settingsJson parced!");
|
||||
if (debug) console.log("[ii]", "settingsJson parced!");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -443,8 +454,6 @@
|
||||
settingsJsonParced = false;
|
||||
ssidJsonParced = false;
|
||||
|
||||
//ssidJson = {};
|
||||
|
||||
if (debug) console.log("[i]", "all app data cleared");
|
||||
}
|
||||
|
||||
@@ -484,7 +493,14 @@
|
||||
pages = [];
|
||||
const newPage = Array.from(new Set(Array.from(layoutJson, ({ page }) => page)));
|
||||
newPage.forEach(function (item, i, arr) {
|
||||
pages = [...pages, JSON.parse(JSON.stringify({ page: item }))];
|
||||
pages = [
|
||||
...pages,
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
page: item,
|
||||
})
|
||||
),
|
||||
];
|
||||
});
|
||||
pages.sort(function (a, b) {
|
||||
if (a.page < b.page) {
|
||||
@@ -507,7 +523,13 @@
|
||||
coreMessages = coreMessages.slice(0);
|
||||
}
|
||||
const time = new Date().getTime();
|
||||
coreMessages = [...coreMessages, { time, msg }];
|
||||
coreMessages = [
|
||||
...coreMessages,
|
||||
{
|
||||
time,
|
||||
msg,
|
||||
},
|
||||
];
|
||||
coreMessages.sort(function (a, b) {
|
||||
if (a.time > b.time) {
|
||||
return -1;
|
||||
@@ -520,6 +542,33 @@
|
||||
};
|
||||
|
||||
//***********************************************************dev list******************************************************************/
|
||||
function createDefaultDevice() {
|
||||
let find = false;
|
||||
let device;
|
||||
if (debug) console.log("[i]", "original dev ip (js): ", myip);
|
||||
if (debug) console.log("[i]", "original dev ip (esp): ", settingsJson.ip);
|
||||
for (let i = 0; i < deviceList.length; i++) {
|
||||
device = deviceList[i];
|
||||
if (debug) console.log("[i]", "start checking dev no: ", i, device.ip);
|
||||
if (device.ip === settingsJson.ip) {
|
||||
if (debug) console.log("[i]", "found ", device.ip);
|
||||
device.name = settingsJson.name;
|
||||
device.id = settingsJson.id;
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find) {
|
||||
if (debug) console.log("[i]", "not found, add to the end");
|
||||
deviceList.push({
|
||||
ip: settingsJson.ip,
|
||||
name: settingsJson.name,
|
||||
id: settingsJson.id,
|
||||
});
|
||||
}
|
||||
deviceList = deviceList;
|
||||
}
|
||||
|
||||
function devicesDropdownChange() {
|
||||
socketConnected = selectedDeviceData.status;
|
||||
wsSelected = selectedDeviceData.ws;
|
||||
@@ -532,6 +581,7 @@
|
||||
}
|
||||
|
||||
function devListSave() {
|
||||
//createDefaultDevice();
|
||||
if (!showInput) {
|
||||
if (newDevice.name !== undefined && newDevice.ip !== undefined && newDevice.id !== undefined) {
|
||||
newDevice.status = false;
|
||||
@@ -606,7 +656,13 @@
|
||||
if (debug) console.log("[i]", "request for edit file");
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
var formData = new FormData();
|
||||
formData.append("data", new Blob([data], { type: "text/json" }), "/" + filename);
|
||||
formData.append(
|
||||
"data",
|
||||
new Blob([data], {
|
||||
type: "text/json",
|
||||
}),
|
||||
"/" + filename
|
||||
);
|
||||
xmlHttp.open("POST", "http://" + url + "/edit");
|
||||
xmlHttp.onload = function () {
|
||||
//во время загрузки
|
||||
@@ -667,17 +723,6 @@
|
||||
|
||||
//************************************************elements and presets dropdown************************************************************/
|
||||
|
||||
function deleteLineFromDevlist(num) {
|
||||
for (let i = 0; i < deviceList.length; i++) {
|
||||
if (num === i) {
|
||||
deviceList.splice(i, 1);
|
||||
deviceList = deviceList;
|
||||
if (debug) console.log("[i]", "item " + num + " deleted from dev list");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ssidDropdownClick() {
|
||||
wsSendMsg(wsSelected, "/scan");
|
||||
}
|
||||
@@ -697,9 +742,9 @@
|
||||
<Modal show={showModalFlag} />
|
||||
|
||||
<header class="h-10 w-full bg-gray-100 overflow-auto shadow-md">
|
||||
<div class="flex justify-end content-center">
|
||||
<div class="px-15 py-2 z-50">
|
||||
<select class="border-indigo-500" bind:value={selectedDeviceData} on:change={() => devicesDropdownChange()}>
|
||||
<div class="flex content-center items-center justify-end">
|
||||
<div class="px-15 py-1 z-50 ">
|
||||
<select class="border border-indigo-500 border-4" bind:value={selectedDeviceData} on:change={() => devicesDropdownChange()}>
|
||||
{#each deviceList as device}
|
||||
<option value={device}>
|
||||
{device.name}
|
||||
@@ -707,8 +752,8 @@
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
<div class="pl-2 pr-4 py-1">
|
||||
<svg class="h-8 w-8 {socketConnected === true ? 'text-green-500' : 'text-red-500'}" 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" /> <path d="M7 18a4.6 4.4 0 0 1 0 -9h0a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-12" /></svg>
|
||||
<div class="pl-4 pr-4 py-1">
|
||||
<CloudIcon color={socketConnected === true ? "text-green-500" : "text-red-500"} />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -754,7 +799,7 @@
|
||||
<DashboardPage layoutJson={layoutJson} pages={pages} wsPush={(ws, topic, status) => wsPush(ws, topic, status)} />
|
||||
</Route>
|
||||
<Route path="/config">
|
||||
<ConfigPage configJson={configJson} widgetsJson={widgetsJson} itemsJson={itemsJson} saveConfig={() => saveConfig()} deleteLineFromConfig={(i) => deleteLineFromConfig(i)} />
|
||||
<ConfigPage configJson={configJson} widgetsJson={widgetsJson} itemsJson={itemsJson} saveConfig={() => saveConfig()} />
|
||||
</Route>
|
||||
<Route path="/connection">
|
||||
<ConnectionPage settingsJson={settingsJson} ssidJson={ssidJson} ssidDropdownClick={() => ssidDropdownClick()} saveSettings={() => saveSettings()} />
|
||||
@@ -770,13 +815,15 @@
|
||||
</Route>
|
||||
{/if}
|
||||
<Route path="/list">
|
||||
<ListPage deviceList={deviceList} showInput={showInput} deleteLineFromDevlist={(num) => deleteLineFromDevlist(num)} devListSave={() => devListSave()} newDevice={newDevice} />
|
||||
<ListPage deviceList={deviceList} showInput={showInput} devListSave={() => devListSave()} newDevice={newDevice} />
|
||||
</Route>
|
||||
</div>
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<footer class="h-4 bg-gray-100 border-gray-200 shadow-lg"><div class="flex justify-center content-center text-xxs text-gray-500">Developed by Dmitry Borisenko</div></footer>
|
||||
<footer class="h-4 bg-gray-100 border-gray-200 shadow-lg">
|
||||
<div class="flex justify-center content-center text-xxs text-gray-500">Developed by Dmitry Borisenko</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<style lang="postcss" global>
|
||||
@@ -785,29 +832,29 @@
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
/*==================================================cards grid=====================================================*/
|
||||
/* grid for cards */
|
||||
.grd-3cols {
|
||||
@apply grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-3 justify-items-center;
|
||||
}
|
||||
/* grid for cards for full screen */
|
||||
.grd-1cols {
|
||||
/*==================================================grids=====================================================*/
|
||||
.grd-1col1 {
|
||||
@apply grid grid-cols-1 justify-items-center;
|
||||
}
|
||||
.grd-2col1 {
|
||||
@apply grid gap-4 grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2 justify-items-center;
|
||||
}
|
||||
.grd-2col2 {
|
||||
@apply grid gap-4 grid-cols-2 justify-items-center;
|
||||
}
|
||||
.grd-3col1 {
|
||||
@apply grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-3 justify-items-center;
|
||||
}
|
||||
/*=============================================card and items inside===============================================*/
|
||||
/* 3. card items positioning*/
|
||||
.crd-itm-psn {
|
||||
@apply flex mb-3 h-8 items-center;
|
||||
}
|
||||
/* 4. widget description width*/
|
||||
.wgt-dscr-w {
|
||||
@apply w-2/3;
|
||||
}
|
||||
/* 5. widget descr style*/
|
||||
.wgt-dscr-stl {
|
||||
@apply pr-4 text-gray-500 font-bold;
|
||||
}
|
||||
/* 6. widget width*/
|
||||
.wgt-w {
|
||||
@apply flex justify-end w-1/3;
|
||||
}
|
||||
@@ -815,12 +862,6 @@
|
||||
.btn-i {
|
||||
@apply py-2 px-4 bg-indigo-500 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-opacity-75;
|
||||
}
|
||||
.wgt-ipt {
|
||||
@apply content-center px-2 h-8 bg-gray-50 border-2 border-gray-200 rounded w-full text-gray-700 leading-tight focus:outline-none focus:bg-white;
|
||||
}
|
||||
.jsn-ipt {
|
||||
@apply content-center px-2 h-8 bg-gray-50 border-2 border-gray-200 rounded w-full text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-indigo-500;
|
||||
}
|
||||
.wgt-adt-stl {
|
||||
@apply text-center text-gray-500 font-bold;
|
||||
}
|
||||
@@ -831,43 +872,45 @@
|
||||
.tbl-hd {
|
||||
@apply text-center px-1 break-words text-gray-500 font-bold;
|
||||
}
|
||||
.tbl-bdy {
|
||||
.tbl-bdy-lg {
|
||||
@apply text-center px-1 break-words;
|
||||
}
|
||||
.tbl-s-bdy {
|
||||
.tbl-bdy-sm {
|
||||
@apply px-1 break-words;
|
||||
}
|
||||
.tbl-ipt {
|
||||
@apply content-center mt-2 h-7 bg-gray-50 focus:bg-white border-2 border-gray-100 text-gray-700 leading-tight focus:outline-none text-center focus:border-indigo-500;
|
||||
/*====================================================inputs=====================================================*/
|
||||
.ipt-lg {
|
||||
@apply h-4 sm:h-7 md:h-7 lg:h-7 xl:h-7 2xl:h-7 content-center mt-2 bg-gray-50 focus:bg-white border-2 border-gray-100 text-gray-700 leading-tight focus:outline-none text-center focus:border-indigo-500;
|
||||
}
|
||||
.tbl-s-ipt {
|
||||
@apply content-center h-6 bg-gray-50 focus:bg-white border-2 border-gray-100 text-gray-700 leading-tight focus:outline-none text-center focus:border-indigo-500 rounded-sm;
|
||||
.ipt-sm {
|
||||
@apply h-3 sm:h-6 md:h-6 lg:h-6 xl:h-6 2xl:h-6 content-center bg-gray-50 focus:bg-white border-2 border-gray-100 text-gray-700 leading-tight focus:outline-none text-center focus:border-indigo-500 rounded-sm;
|
||||
}
|
||||
.tbl-s-txt {
|
||||
.ipt-rnd {
|
||||
@apply content-center px-2 h-8 bg-gray-50 border-2 border-gray-200 rounded w-full text-gray-700 leading-tight focus:outline-none focus:bg-white;
|
||||
}
|
||||
.ipt-big {
|
||||
@apply content-center px-2 h-8 bg-gray-50 border-2 border-gray-200 rounded w-full text-gray-700 leading-tight focus:outline-none focus:bg-white focus:border-indigo-500;
|
||||
}
|
||||
/*====================================================text=====================================================*/
|
||||
.txt-ita {
|
||||
@apply inline-block italic align-top text-right text-gray-500;
|
||||
}
|
||||
.tbl-txt-p {
|
||||
.txt-pad {
|
||||
@apply px-2 py-0 sm:py-0 md:py-0 lg:py-1 xl:py-2 2xl:py-2;
|
||||
}
|
||||
.tbl-txt-sz {
|
||||
.txt-sz {
|
||||
@apply text-xxs sm:text-base md:text-base lg:text-base xl:text-base 2xl:text-base;
|
||||
}
|
||||
/*====================================================buttons=====================================================*/
|
||||
.btn-lg {
|
||||
@apply flex justify-center break-words content-center bg-blue-100 hover:bg-blue-200 text-gray-500 font-bold h-8 w-full mt-0 border border-gray-300 rounded;
|
||||
@apply flex justify-center break-words content-center bg-blue-100 hover:bg-blue-200 text-gray-500 font-bold text-xxs sm:text-base md:text-base lg:text-base xl:text-base 2xl:text-base h-4 sm:h-8 md:h-8 lg:h-8 xl:h-8 2xl:h-8 w-full mt-0 border border-gray-300 rounded;
|
||||
}
|
||||
.btn-tbl {
|
||||
@apply flex justify-center content-center text-gray-500 font-bold w-6 h-auto border border-gray-300;
|
||||
}
|
||||
/*====================================================select=====================================================*/
|
||||
.grd-2colsfx {
|
||||
@apply grid gap-4 grid-cols-2 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2 justify-items-center;
|
||||
}
|
||||
.grd-2cols {
|
||||
@apply grid gap-4 grid-cols-1 sm:grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2 justify-items-center;
|
||||
}
|
||||
.slct-lg {
|
||||
@apply flex w-full justify-center break-words content-center bg-blue-100 hover:bg-blue-200 text-gray-500 font-bold h-8 mb-0 border border-gray-300 rounded;
|
||||
@apply flex w-full justify-center break-words content-center bg-blue-100 hover:bg-blue-200 text-gray-500 font-bold text-xxs sm:text-base md:text-base lg:text-base xl:text-base 2xl:text-base h-4 sm:h-8 md:h-8 lg:h-8 xl:h-8 2xl:h-8 mb-0 border border-gray-300 rounded;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,5 +10,5 @@
|
||||
|
||||
<button on:click={() => showModal()} type="button"> Toggle modal </button>
|
||||
<Card title="Редактор JSON">
|
||||
<textarea on:input={wigetsUpdate} rows="10" class="jsn-ipt w-full" id="text1">{syntaxHighlight(JSON.stringify(layoutJson))}</textarea>
|
||||
<textarea on:input={wigetsUpdate} rows="10" class="ipt-big w-full" id="text1">{syntaxHighlight(JSON.stringify(layoutJson))}</textarea>
|
||||
</Card>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script>
|
||||
import Card from "../components/Card.svelte";
|
||||
import CrossIcon from "../svg/Cross.svelte";
|
||||
import OpenIcon from "../svg/Open.svelte";
|
||||
|
||||
export let configJson;
|
||||
export let widgetsJson;
|
||||
@@ -40,9 +42,9 @@
|
||||
</script>
|
||||
|
||||
<!--{#if itemsJsonParced && widgetsJsonParced && configJsonParced && settingsJsonParced}-->
|
||||
<div class="grd-1cols">
|
||||
<div class="grd-1col1">
|
||||
<Card>
|
||||
<div class="grd-2colsfx">
|
||||
<div class="grd-2col2">
|
||||
<select class="slct-lg" bind:value={itemsJsonBind} on:change={() => elementsDropdownChange()}>
|
||||
{#each itemsJson as item}
|
||||
{#if item.header}
|
||||
@@ -59,7 +61,7 @@
|
||||
</div>
|
||||
<table class="tbl">
|
||||
<thead class="bg-gray-100">
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<tr class="txt-sz txt-pad">
|
||||
<th class="tbl-hd">Тип</th>
|
||||
<th class="tbl-hd">Id</th>
|
||||
<th class="tbl-hd">Виджет</th>
|
||||
@@ -71,34 +73,34 @@
|
||||
</thead>
|
||||
<tbody class="bg-white">
|
||||
{#each configJson as element, i}
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<td class="tbl-bdy">{element.subtype}</td>
|
||||
<td class="tbl-bdy"><input bind:value={element.id} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy"
|
||||
><select bind:value={element.widget} class="tbl-ipt w-full">
|
||||
<tr class="txt-sz txt-pad align-middle">
|
||||
<td class="tbl-bdy-lg">{element.subtype}</td>
|
||||
<td class="tbl-bdy-lg"><input bind:value={element.id} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg"
|
||||
><select bind:value={element.widget} class="ipt-lg w-full">
|
||||
{#each widgetsJson as select}
|
||||
<option value={select.name}>
|
||||
{select.label}
|
||||
</option>
|
||||
{/each}
|
||||
</select></td>
|
||||
<td class="tbl-bdy"><input bind:value={element.page} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy"><input bind:value={element.descr} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy"><svg on:click={() => (hideAllSubParams = !hideAllSubParams)} class="h-6 w-6 text-green-400 cursor-pointer" 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" /> <circle cx="5" cy="12" r="1" /> <circle cx="12" cy="12" r="1" /> <circle cx="19" cy="12" r="1" /></svg></td>
|
||||
<td class="tbl-bdy"><svg on:click={() => deleteLineFromConfig(i)} class="h-6 w-6 text-red-400 cursor-pointer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18" /> <line x1="6" y1="6" x2="18" y2="18" /></svg></td>
|
||||
<td class="tbl-bdy-lg"><input bind:value={element.page} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg"><input bind:value={element.descr} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg"><OpenIcon click={() => (hideAllSubParams = !hideAllSubParams)} /></td>
|
||||
<td class="tbl-bdy-lg"><CrossIcon i={i} click={(i) => deleteLineFromConfig(i)} /></td>
|
||||
</tr>
|
||||
{#if !hideAllSubParams}
|
||||
{#each Object.entries(element) as [key, param]}
|
||||
{#if key != "type" && key != "subtype" && key != "id" && key != "widget" && key != "page" && key != "descr"}
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<tr class="txt-sz txt-pad">
|
||||
<td />
|
||||
<td />
|
||||
<td />
|
||||
<td class="tbl-s-bdy text-right">
|
||||
<p class="tbl-s-txt">{key}</p>
|
||||
<td class="tbl-bdy-sm text-right">
|
||||
<p class="txt-ita">{key}</p>
|
||||
</td>
|
||||
<td class="tbl-s-bdy text-center">
|
||||
<input bind:value={element[key]} class="tbl-s-ipt w-full" type="text" />
|
||||
<td class="tbl-bdy-sm text-center">
|
||||
<input bind:value={element[key]} class="ipt-sm w-full" type="text" />
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
export let saveSettings = () => {};
|
||||
</script>
|
||||
|
||||
<div class="grd-2cols">
|
||||
<div class="grd-2col1">
|
||||
<Card title="Подключение к WiFi роутеру">
|
||||
<div class="crd-itm-psn">
|
||||
<div class="wgt-dscr-w">
|
||||
<p class="wgt-dscr-stl">Название устройства</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.name} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.name} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -23,7 +23,7 @@
|
||||
<p class="wgt-dscr-stl">Точка доступа</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.apssid} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.apssid} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -31,7 +31,7 @@
|
||||
<p class="wgt-dscr-stl">Пароль точки доступа</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.appass} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.appass} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -39,7 +39,7 @@
|
||||
<p class="wgt-dscr-stl">Название wifi сети</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<select class="wgt-ipt text-left focus:border-indigo-500" bind:value={settingsJson.routerssid} on:click={() => ssidDropdownClick()}>
|
||||
<select class="ipt-rnd text-left focus:border-indigo-500" bind:value={settingsJson.routerssid} on:click={() => ssidDropdownClick()}>
|
||||
{#each Object.entries(ssidJson) as [num, ssid]}
|
||||
<option value={ssid}>
|
||||
{ssid}
|
||||
@@ -53,11 +53,11 @@
|
||||
<p class="wgt-dscr-stl">Пароль</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.routerpass} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.routerpass} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
{#if settingsJson.pass_status === 1}
|
||||
<div class="grd-1cols">
|
||||
<div class="grd-1col1">
|
||||
<Alarm title="Введен неправильный пароль" />
|
||||
</div>
|
||||
{/if}
|
||||
@@ -69,7 +69,7 @@
|
||||
<p class="wgt-dscr-stl">Название сервера</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.mqttServer} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.mqttServer} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -77,7 +77,7 @@
|
||||
<p class="wgt-dscr-stl">Порт</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.mqttPort} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.mqttPort} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -85,7 +85,7 @@
|
||||
<p class="wgt-dscr-stl">Префикс</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.mqttPrefix} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.mqttPrefix} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -93,7 +93,7 @@
|
||||
<p class="wgt-dscr-stl">Имя пользователя</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.mqttUser} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.mqttUser} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="crd-itm-psn">
|
||||
@@ -101,7 +101,7 @@
|
||||
<p class="wgt-dscr-stl">Пароль</p>
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
<input bind:value={settingsJson.mqttPass} class="wgt-ipt text-left focus:border-indigo-500" type="text" />
|
||||
<input bind:value={settingsJson.mqttPass} class="ipt-rnd text-left focus:border-indigo-500" type="text" />
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn-lg" on:click={() => saveSettings()}>{"Сохранить и проверить подключение"}</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
export let wsPush = (ws, topic, status) => {};
|
||||
</script>
|
||||
|
||||
<div class="grd-3cols">
|
||||
<div class="grd-3col1">
|
||||
{#if layoutJson === []}
|
||||
<Card title={"Ваша панель управления пуста, вначале добавьте новые элементы в конфигураторе!"} />
|
||||
{/if}
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
<script>
|
||||
import Card from "../components/Card.svelte";
|
||||
|
||||
import CrossIcon from "../svg/Cross.svelte";
|
||||
import OpenIcon from "../svg/Open.svelte";
|
||||
|
||||
export let deviceList;
|
||||
export let showInput;
|
||||
|
||||
export let newDevice = {};
|
||||
|
||||
export let devListSave = () => {};
|
||||
export let deleteLineFromDevlist = (num) => {};
|
||||
|
||||
let debug = true;
|
||||
|
||||
function deleteLineFromDevlist(num) {
|
||||
for (let i = 0; i < deviceList.length; i++) {
|
||||
if (num === i) {
|
||||
deviceList.splice(i, 1);
|
||||
deviceList = deviceList;
|
||||
if (debug) console.log("[i]", "item " + num + " deleted from dev list");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grd-1cols">
|
||||
<div class="grd-1col1">
|
||||
<Card title={"Список устройств"}>
|
||||
<table class="tbl">
|
||||
<thead class="bg-gray-100">
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<tr class="txt-sz txt-pad">
|
||||
<th class="tbl-hd">Название устройства</th>
|
||||
<th class="tbl-hd">IP адрес</th>
|
||||
<th class="tbl-hd">Идентификатор</th>
|
||||
@@ -24,20 +38,20 @@
|
||||
</thead>
|
||||
<tbody class="bg-white">
|
||||
{#each deviceList as device, i}
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<td class="tbl-bdy tbl-ipt w-full">{device.name}</td>
|
||||
<td class="tbl-bdy tbl-ipt w-full"><a href={"http://" + device.ip}>{device.ip}</a></td>
|
||||
<td class="tbl-bdy tbl-ipt w-full">{device.id}</td>
|
||||
<td class="tbl-bdy tbl-ipt w-full {device.status ? 'bg-green-50' : 'bg-red-50'}">{device.status ? "online" : "offline"}</td>
|
||||
<td class="tbl-bdy"><svg on:click={() => deleteLineFromDevlist(i)} class="h-6 w-6 text-red-400 cursor-pointer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18" /> <line x1="6" y1="6" x2="18" y2="18" /></svg></td>
|
||||
<tr class="txt-sz txt-pad">
|
||||
<td class="tbl-bdy-lg ipt-lg w-full">{device.name}</td>
|
||||
<td class="tbl-bdy-lg ipt-lg w-full"><a href={"http://" + device.ip}>{device.ip}</a></td>
|
||||
<td class="tbl-bdy-lg ipt-lg w-full">{device.id}</td>
|
||||
<td class="tbl-bdy-lg ipt-lg w-full {device.status ? 'bg-green-50' : 'bg-red-50'}">{device.status ? "online" : "offline"}</td>
|
||||
<td class="tbl-bdy-lg"><CrossIcon i={i} click={(i) => deleteLineFromDevlist(i)} /></td>
|
||||
</tr>
|
||||
{/each}
|
||||
{#if showInput}
|
||||
<tr class="tbl-txt-sz tbl-txt-p">
|
||||
<td class="tbl-bdy"><input bind:value={newDevice.name} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy"><input bind:value={newDevice.ip} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy"><input bind:value={newDevice.id} class="tbl-ipt w-full" type="text" /></td>
|
||||
<td class="tbl-bdy" />
|
||||
<tr class="txt-sz txt-pad">
|
||||
<td class="tbl-bdy-lg"><input bind:value={newDevice.name} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg"><input bind:value={newDevice.ip} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg"><input bind:value={newDevice.id} class="ipt-lg w-full" type="text" /></td>
|
||||
<td class="tbl-bdy-lg" />
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
|
||||
7
src/svg/Cloud.svelte
Normal file
7
src/svg/Cloud.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
export let color;
|
||||
</script>
|
||||
|
||||
<svg class="h-8 w-8 {color}" 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" />
|
||||
<path d="M7 18a4.6 4.4 0 0 1 0 -9h0a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-12" /></svg>
|
||||
6
src/svg/Cross.svelte
Normal file
6
src/svg/Cross.svelte
Normal file
@@ -0,0 +1,6 @@
|
||||
<script>
|
||||
export let i;
|
||||
export let click = (i) => {};
|
||||
</script>
|
||||
|
||||
<svg on:click={click(i)} class="h-6 w-6 text-red-400 cursor-pointer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18" /> <line x1="6" y1="6" x2="18" y2="18" /></svg>
|
||||
5
src/svg/Open.svelte
Normal file
5
src/svg/Open.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<script>
|
||||
export let click = () => {};
|
||||
</script>
|
||||
|
||||
<svg on:click={click()} class="h-6 w-6 text-green-400 cursor-pointer" 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" /> <circle cx="5" cy="12" r="1" /> <circle cx="12" cy="12" r="1" /> <circle cx="19" cy="12" r="1" /></svg>
|
||||
@@ -12,16 +12,16 @@
|
||||
</div>
|
||||
<div class="wgt-w">
|
||||
{#if widget.type == "number"}
|
||||
<input class={widget["send"] == true ? "wgt-ipt text-right border-red-500" : "wgt-ipt text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} step="0.1" type="number" />
|
||||
<input class={widget["send"] == true ? "ipt-rnd text-right border-red-500" : "ipt-rnd text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} step="0.1" type="number" />
|
||||
{/if}
|
||||
{#if widget.type == "text"}
|
||||
<input class={widget["send"] == true ? "wgt-ipt text-right border-red-500" : "wgt-ipt text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="text" />
|
||||
<input class={widget["send"] == true ? "ipt-rnd text-right border-red-500" : "ipt-rnd text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="text" />
|
||||
{/if}
|
||||
{#if widget.type == "date"}
|
||||
<input class={widget["send"] == true ? "wgt-ipt text-right border-red-500" : "wgt-ipt text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="date" />
|
||||
<input class={widget["send"] == true ? "ipt-rnd text-right border-red-500" : "ipt-rnd text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="date" />
|
||||
{/if}
|
||||
{#if widget.type == "time"}
|
||||
<input class={widget["send"] == true ? "wgt-ipt text-right border-red-500" : "wgt-ipt text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="time" />
|
||||
<input class={widget["send"] == true ? "ipt-rnd text-right border-red-500" : "ipt-rnd text-right focus:border-indigo-500"} on:change={() => ((widget["send"] = true), wsPush(widget.ws, widget.topic, widget.status))} bind:value={widget.status} type="time" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user