diff --git a/ESP32_AP-Flasher/data/www/index.html.gz b/ESP32_AP-Flasher/data/www/index.html.gz index fe1abbdb..be72d2d9 100644 Binary files a/ESP32_AP-Flasher/data/www/index.html.gz and b/ESP32_AP-Flasher/data/www/index.html.gz differ diff --git a/ESP32_AP-Flasher/data/www/main.css.gz b/ESP32_AP-Flasher/data/www/main.css.gz index b6c94419..9f1639be 100644 Binary files a/ESP32_AP-Flasher/data/www/main.css.gz and b/ESP32_AP-Flasher/data/www/main.css.gz differ diff --git a/ESP32_AP-Flasher/data/www/main.js.gz b/ESP32_AP-Flasher/data/www/main.js.gz index fba96a15..cf128d0c 100644 Binary files a/ESP32_AP-Flasher/data/www/main.js.gz and b/ESP32_AP-Flasher/data/www/main.js.gz differ diff --git a/ESP32_AP-Flasher/wwwroot/index.html b/ESP32_AP-Flasher/wwwroot/index.html index 808e1449..9bd39e77 100644 --- a/ESP32_AP-Flasher/wwwroot/index.html +++ b/ESP32_AP-Flasher/wwwroot/index.html @@ -8,15 +8,419 @@ Open EPaper Link Access Point +
+
-
-
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ check_circle + + initialising... +
+ sell + + tags + + 0 +
+ hourglass_empty + + pending data + + 0 +
+ battery_low + + low battery + + 0 +
+ signal_disconnected + + timeout + + 0 +
+
+ +
+
+

Currently active tags

+
+
+
+
+
group by
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
sort by
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
filter
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ↻
+
⚠ +
+
+
+
+
+ +
+
+
+
+
+
    +
+
+ +
+

Active access points

+ +
+
+

194.109.6.66

+

AP kitchen

+
+ + sell + + 13 + + cell_tower + + 25 +
+

+ fetching software version... +

+
+
+
+ +
+ Work in progress... +
+ +
+

Access Point config

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ + + and + +

+

+ + +

+

+ + +

+

+ + +

+

+ +

+

Manage

+

+ Saves the tagDB and instantly reboots the Access + Point +

+

+ Download tagDB +

+

+ Manage firmware of the ESP32 +

+

+ WiFi config Opens a new window with WiFi + config options +

+

+
+ Github + OpenEPaperLink
+ OpenEPaperLink + Wiki
+

+
+ +
+ + +
+
+ + + + + + +

00000000

@@ -50,183 +454,33 @@ - +

- - -
-
-

Access Point config

-

- - -

-

- - -

-

- - -

-

- - -

-

- - -

-

- - -

-

- - - and - -

-

- - -

-

- - -

-

- - -

-

- -

-

- Active access points:
- - - - - - - - -
ipaliastagschAP ver
-

-

- reboot AP - download tagDB - update - WiFi config -

-

- Github OpenEPaperLink -

-
+

Update dashboard

+
- -
download latest version
+ + +
download latest version
+
@@ -235,84 +489,8 @@ to save file system space"> style="display: none; position: absolute; background: white; border: 1px solid gray; padding: 0; list-style: none;"> -
-
- -
- -
-
-
Currently active tags:
-
-
-
loading
-
AP config
- -
-
-
-
group by
-
-
-
-
-
-
-
sort by
-
-
-
-
-
-
-
filter
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- -
- -
-
-
-
-
-
-
-
-
-
- -
-

- logging - - -

-
    -
-
-
- - -
-
- - + \ No newline at end of file diff --git a/ESP32_AP-Flasher/wwwroot/main.css b/ESP32_AP-Flasher/wwwroot/main.css index b32f2ce8..441ca4ee 100644 --- a/ESP32_AP-Flasher/wwwroot/main.css +++ b/ESP32_AP-Flasher/wwwroot/main.css @@ -1,7 +1,7 @@ * { - margin:0; - padding:0; - border:0; + margin: 0; + padding: 0; + border: 0; list-style-type: none; outline: none; font-weight: 400; @@ -12,7 +12,8 @@ -webkit-font-smoothing: antialiased; } -html, body { +html, +body { height: 100%; } @@ -24,60 +25,263 @@ body { } header { - height: 50px; background-color: #646260; + z-index: 999; + position: sticky; + top: 0px; + width: 100%; } -label { - width: 120px; - display: inline-block; - vertical-align: top; - padding: 3px 0px; -} - -.logo { - margin: 0 auto; - height: 50px; - text-indent: 50px; - overflow:hidden; - font-size: 2.5em; - color: white; -} - -.window { - margin: 0 auto; - max-width: 94%; -} - -.actionbox { - margin: 5px; -} - -.actionbox>div:first-child>div:first-child { +nav>div:first-child>div:first-child { flex-grow: 2; } -.actionbox>div { - display:flex; +nav>div { + display: flex; gap: 20px; padding: 10px; background-color: white; } -.actionbox label { +nav label { padding: 0px 5px; vertical-align: text-bottom; width: auto; cursor: pointer; } -#rebootbutton, #updatebutton, #downloadDBbutton, #apconfigbutton, .filebutton { - padding: 2px 5px; - background-color: #cccccc; +footer { + padding: 5px; + position: fixed; + bottom: 0; + width: 100%; + background-color: white; + + #sysinfo { + float: right; + } +} + +.logo { + margin: 0 auto; + height: 50px; + text-indent: 50px; + overflow: hidden; + font-size: 2.5em; + color: white; +} + +h3 { + padding-bottom: 10px; + font-size: 1.5em; +} + +/* tabs */ + +.tab-container { + display: flex; + gap: 1rem; +} + +.tablinks { + background-color: #f2f2f2; + padding: 5px 10px; + border: none; + cursor: pointer; + transition: background-color 0.3s; + transition: all 0.2s ease-in-out; + + &:hover { + background-color: #ddd; + } +} + +.tab-container .active { + background-color: #ccc; + margin-top: 10px; + margin-bottom: -10px; + padding-bottom: 0px; +} + +.tabcontent { + display: none; + border-top: 1px solid #ccc; +} + + +label { + width: 200px; + display: inline-block; + vertical-align: top; + padding: 4px 20px; +} + +.container { + padding-bottom: 20px; + ; +} + +#hometab { + font-size: 24px; + + & table { + margin: 20px; + background: #fff; + padding: 5px 20px; + border-spacing: 0px; + } + + & td { + padding: 10px 12px; + } + + & td:nth-child(3) { + text-align: right; + font-size: 32px; + } + + & tr:hover { + background-color: #ccc; + cursor: pointer; + } + + & .material-symbols-outlined { + font-size: 48px; + } +} + +.tagheader { + width: 100%; + padding: 10px 10px; + display: flex; + gap: 2em; + justify-content: space-between; + + & #toggleFilters { + padding: 0px 10px; + } + + & h3 { + padding-bottom: 0px; + } + + & #activefilter { + flex-grow: 2; + align-self: center; + } +} + +.tabheader { + background-color: white; + padding: 5px 10px; + display: flex; + gap: 2em; +} + +#filterOptions { + background-color: white; + max-height: 0; + padding: 0px 10px; + overflow: hidden; + transition: all 0.3s ease-in-out; + display: flex; + gap: 1rem; + + &.active { + padding: 10px 10px; + max-height: 100px; + margin-bottom: 10px; + } + + & label { + width: inherit; + display: inline-block; + vertical-align: top; + padding: 0px 5px; + } +} + +#aptab, +#configtab { + padding: 10px; + + & p { + padding: 3px; + } +} + +#aplist { + display: flex; + gap: 1em; + flex-flow: wrap; +} + +.apcard { + background-color: #fff; + border: 1px solid #ccc; + padding: 10px; + width: 300px; + + & .apalias { + font-size: 1.5em; + } + + & .space { + padding-left: 20px; + } + + & div { + display: flex; + font-size: 2.0em; + align-items: center; + gap: 0.2em; + } + +} + +#apcard { + display: none; +} + +#apcfgsave { + margin: 20px 205px; +} + +.filebutton { + width: inherit; + padding: 5px 10px; + margin-bottom: 0px; + margin-top: -1px; + background-color: #ccc; text-decoration: none; color: black; cursor: pointer; white-space: nowrap; + text-align: center; + + &:hover { + background-color: #aaa; + } +} + +#rebootbutton, +#updatebutton, +#downloadDBbutton, +.wifibutton { + padding: 4px 5px; + background-color: #ccc; + text-decoration: none; + color: black; + cursor: pointer; + white-space: nowrap; + width: 120px; + margin: 2px 5px 2px 20px; + display: inline-block; + text-align: center; + + &:hover { + background-color: #aaa; + } } .columns div { @@ -100,15 +304,17 @@ input { border-radius: 0px; } -input[type=button], button { +input[type=button], +button { border: 0px; padding: 4px 10px; - cursor:pointer; + cursor: pointer; + background-color: #ccc; } input[type=button]:hover, button:hover { - background-color:#aaaaaa; + background-color: #aaaaaa; } select { @@ -117,7 +323,8 @@ select { border: solid 1px #cccccc; } -#configbox, #apconfigbox, #apupdatebox { +#apconfigbox, +#apupdatebox { display: none; position: fixed; top: 65px; @@ -131,19 +338,35 @@ select { max-height: calc(100vh - 75px); } -#configbox p, #apconfigbox p, #apupdatebox p { +#configbox { + margin: auto; + min-width: 380px; + padding: 15px; + background-color: #f0e6d3; + z-index: 999; + box-shadow: 7px 10px 52px -19px rgba(0, 0, 0, 0.63); + overflow: auto; + max-height: calc(100vh - 75px); +} + +#configbox p, +#apconfigbox p, +#apupdatebox p { padding: 5px; display: flex; gap: 5px; align-items: flex-start; } -#configbox h3, #apconfigbox h3, #apupdatebox h3 { +#configbox h3, +#apconfigbox h3, +#apupdatebox h3 { font-size: 1.5em; font-weight: bold; } -#configbox input, #apconfigbox input { +#configbox input, +#apconfigbox input { border: solid 1px #cccccc; } @@ -191,31 +414,6 @@ select { background-color: #e6f0d3; } -#aptable { - width: 100%; - border-spacing: 0; -} - -#aptable th { - text-align: left; - background-color: #00000020; - padding: 0px 3px; -} - -#aptable th, #aptable td { - border-right: 1px solid #000010; - padding: 0px 3px; -} - -#aptable td:nth-child(1), #aptable th:nth-child(1) { - border-left: 1px solid #000010; -} - -#aptable td:nth-child(3), -#aptable td:nth-child(4) { - text-align: right; -} - #apupdatebox { background-color: #f0d0c8; width: 700px; @@ -228,7 +426,8 @@ select { padding: 2px 10px; } -.closebtn { +.closebtn, +.closebtn2 { border: 1px solid black; float: right; width: 19px; @@ -239,22 +438,21 @@ select { cursor: pointer; } -.logbox { - margin: 5px; -} +#logtab { + & img { + vertical-align: bottom; + cursor: pointer; + } -.logbox p { - background-color: #ffffff; - padding: 5px 10px; -} + & label { + width: inherit; + vertical-align: top; + padding: 4px 10px; + } -.logbox img { - vertical-align: bottom; - cursor:pointer; -} - -.logbox #sysinfo { - float: right; + & input { + vertical-align: text-bottom; + } } .blink-red { @@ -265,10 +463,11 @@ select { .taglist { display: flex; flex-wrap: wrap; + margin: 0px 10px 30px 10px; } #tagtemplate { - display:none; + display: none; } .tagcard { @@ -280,12 +479,12 @@ select { background-color: #ffffff; border: 1px solid #cccccc; transition: box-shadow 0.3s ease; -} -.tagcard:hover { - cursor:pointer; - box-shadow: 7px 10px 52px -19px rgba(0, 0, 0, 0.63); - filter: brightness(1.02); + &:hover { + cursor: pointer; + box-shadow: 7px 10px 52px -19px rgba(0, 0, 0, 0.63); + filter: brightness(1.02); + } } .tagflash { @@ -305,30 +504,19 @@ select { margin: 0px 5px; } -#filterOptions { - max-height: 0; - padding: 0 10px; - overflow: hidden; - transition: max-height 0.3s ease-in-out, padding 0.3s ease-in-out; -} - -#filterOptions.active { - max-height: 100px; - padding: 10px 10px; -} - .currimg { float: right; } -.currimg img, .currimg canvas { +.currimg img, +.currimg canvas { max-width: 50px; border: 1px solid #c0c0c0; } .mac { font-size: 0.9em; - cursor:pointer; + cursor: pointer; } .alias { @@ -344,6 +532,7 @@ select { font-size: .85em; padding-bottom: 5px; } + .received div { display: inline-block; } @@ -354,16 +543,19 @@ select { padding-bottom: 5px; } -.lastseen, .nextcheckin, .nextupdate { +.lastseen, +.nextcheckin, +.nextupdate { font-size: 0.9em; } .lastseen span, .nextcheckin span, .nextupdate span { - width:105px; - display:inline-block; + width: 105px; + display: inline-block; } + .corner { position: absolute; right: 0px; @@ -383,7 +575,7 @@ select { } .warningicon { - display:none; + display: none; font-size: 1.3em; background-color: yellow; color: black; @@ -412,12 +604,24 @@ ul.messages li.new { color: red; } +.mono { + font-family: monospace; + word-break: break-all; + background-color: #666; + color: #ccc; + padding: 2px; +} + +.quote { + color: white; +} + #paintbutton { padding: 1px 3px; border: 1px solid black; font-size: 1.3em; vertical-align: top; - margin-left:12px; + margin-left: 12px; cursor: pointer; } @@ -472,6 +676,7 @@ ul.messages li.new { background-color: #dddddd; width: 40px; } + #buttonbar button { font-size: 1.2em; font-weight: bold; @@ -513,7 +718,7 @@ ul.messages li.new { /* updatescreens */ -#easyupdate{ +#easyupdate { margin-top: 10px; } @@ -578,7 +783,7 @@ ul.messages li.new { .console { width: 100%; background-color: black; - font-family: 'lucida console','ui-monospace'; + font-family: 'lucida console', 'ui-monospace'; color: white; padding: 5px 10px; margin: 20px 0px; @@ -587,6 +792,7 @@ ul.messages li.new { overflow-y: scroll; white-space: break-spaces; } + .console div { word-break: break-all; } @@ -594,36 +800,62 @@ ul.messages li.new { /* media */ @media(max-width: 460px) { - .messages li div, ul.messages li div.date, ul.messages li div.message { - display:block; - position:relative; + + .messages li div, + ul.messages li div.date, + ul.messages li div.message { + display: block; + position: relative; padding: 0; left: auto; } - .messages li div.message, li.pending { + + .messages li div.message, + li.pending { margin-bottom: 8px; } + ul.messages { padding-bottom: 4px; } } @keyframes new { - 0% { background-color: rgba(255, 255, 204, 1); } - 50% { background-color: rgba(255, 255, 204, .5); } - 100% { background-color: rgba(255, 255, 204, 0); } + 0% { + background-color: rgba(255, 255, 204, 1); + } + + 50% { + background-color: rgba(255, 255, 204, .5); + } + + 100% { + background-color: rgba(255, 255, 204, 0); + } } @keyframes tagflash { - 0% { opacity: 1; } - 50% { opacity: 0; } - 100% { opacity: 1; } + 0% { + opacity: 1; + } + + 50% { + opacity: 0; + } + + 100% { + opacity: 1; + } } @keyframes pending { - 0% { } - 50% { background-color: #d4d4f5;} - 100% { } + 0% {} + + 50% { + background-color: #d4d4f5; + } + + 100% {} } @media screen and (max-width: 480px) { @@ -638,7 +870,7 @@ ul.messages li.new { min-height: 200px; } - .logbox #sysinfo { + footer #sysinfo { float: none; display: block; } @@ -682,4 +914,4 @@ ul.messages li.new { padding: 1px 1px; } -} +} \ No newline at end of file diff --git a/ESP32_AP-Flasher/wwwroot/main.js b/ESP32_AP-Flasher/wwwroot/main.js index bb36360e..a4294d93 100644 --- a/ESP32_AP-Flasher/wwwroot/main.js +++ b/ESP32_AP-Flasher/wwwroot/main.js @@ -41,7 +41,7 @@ let finishedInitialLoading = false; let getTagtypeBusy = false; const loadConfig = new Event("loadConfig"); -window.addEventListener("loadConfig", function() { +window.addEventListener("loadConfig", function () { fetch("/get_ap_config") .then(response => response.json()) .then(data => { @@ -55,6 +55,7 @@ window.addEventListener("loadConfig", function() { }); window.addEventListener("load", function () { + initTabs(); fetch('/content_cards.json') .then(response => response.json()) .then(data => { @@ -69,12 +70,36 @@ window.addEventListener("load", function () { }); window.dispatchEvent(loadConfig); - + dropUpload(); populateTimes($('#apcnight1')); populateTimes($('#apcnight2')); }); +/* tabs */ +let activeTab = ''; +function initTabs() { + const tabLinks = document.querySelectorAll(".tablinks"); + const tabContents = document.querySelectorAll(".tabcontent"); + + tabLinks.forEach(tabLink => { + tabLink.addEventListener("click", function () { + const targetId = this.getAttribute("data-target"); + const loadTabEvent = new CustomEvent('loadTab', { detail: targetId }); + document.dispatchEvent(loadTabEvent); + tabContents.forEach(tabContent => { + tabContent.style.display = "none"; + }); + tabLinks.forEach(link => { + link.classList.remove("active"); + }); + document.getElementById(targetId).style.display = "block"; + this.classList.add("active"); + }); + }); + tabLinks[0].click(); +}; + function loadTags(pos) { fetch("/get_db?pos=" + pos) .then(response => response.json()) @@ -94,7 +119,10 @@ function connect() { }); socket.addEventListener("message", (event) => { - console.log(event.data) + if ($('#showdebug').checked) { + showMessage(event.data); + console.log(event.data); + } const msg = JSON.parse(event.data); if (msg.logMsg) { showMessage(msg.logMsg, false); @@ -115,17 +143,12 @@ function connect() { $("#apstatecolor").style.color = apstate[msg.sys.apstate].color; $("#apstate").innerHTML = apstate[msg.sys.apstate].state; $("#runstate").innerHTML = runstate[msg.sys.runstate].state; - if (msg.sys.temp) $("#temp").innerHTML = msg.sys.temp.toFixed(1) + '°C'; + $('#dashboardStatus').innerHTML = apstate[msg.sys.apstate].state; } servertimediff = (Date.now() / 1000) - msg.sys.currtime; } if (msg.apitem) { - let row = $("#aptable").insertRow(); - row.insertCell(0).innerHTML = "" + msg.apitem.ip + ""; - row.insertCell(1).innerHTML = msg.apitem.alias; - row.insertCell(2).innerHTML = msg.apitem.count; - row.insertCell(3).innerHTML = msg.apitem.channel; - row.insertCell(4).innerHTML = msg.apitem.version; + populateAPCard(msg.apitem); } if (msg.console) { if (otamodule && typeof (otamodule.print) === "function") { @@ -301,9 +324,16 @@ function processTags(tagArray) { function updatecards() { if (servertimediff > 1000000000) servertimediff = 0; + let tagcount = 0; + let pendingcount = 0; + let timeoutcount = 0; + let lowbattcount = 0; + $('#taglist').querySelectorAll('[data-mac]').forEach(item => { let tagmac = item.dataset.mac; - + tagcount++; + if (tagDB[tagmac].pending) pendingcount++; + if (tagDB[tagmac].batteryMv < 2400 && tagDB[tagmac].batteryMv != 0 && tagDB[tagmac].batteryMv != 1337) lowbattcount++; if (item.dataset.lastseen && item.dataset.lastseen > (Date.now() / 1000) - servertimediff - 30 * 24 * 3600 * 60) { let idletime = (Date.now() / 1000) - servertimediff - item.dataset.lastseen; $('#tag' + tagmac + ' .lastseen').innerHTML = "last seen" + displayTime(Math.floor(idletime)) + " ago"; @@ -311,6 +341,7 @@ function updatecards() { $('#tag' + tagmac + ' .warningicon').style.display = 'inline-block'; $('#tag' + tagmac).classList.remove("tagpending") $('#tag' + tagmac).style.background = '#e0e0a0'; + timeoutcount++; } if (idletime > 24 * 3600) { $('#tag' + tagmac).style.opacity = '.5'; @@ -331,6 +362,11 @@ function updatecards() { $('#tag' + tagmac + ' .nextcheckin').innerHTML = ""; } }) + + $('#dashboardTagCount').innerHTML = tagcount; + $('#dashboardPending').innerHTML = pendingcount; + $('#dashboardLowBatt').innerHTML = lowbattcount; + $('#dashboardTimeout').innerHTML = timeoutcount; } $('#clearlog').onclick = function () { @@ -344,6 +380,13 @@ document.querySelectorAll('.closebtn').forEach(button => { }); }); +document.querySelectorAll('.closebtn2').forEach(button => { + button.addEventListener('click', (event) => { + event.target.parentNode.close(); + $('#advancedoptions').style.height = '0px'; + }); +}); + //clicking on a tag: load config dialog for tag $('#taglist').addEventListener("click", (event) => { let currentElement = event.target; @@ -382,7 +425,7 @@ function loadContentCard(mac) { $('#cfgrotate').value = tagdata.rotate; $('#cfglut').value = tagdata.lut; $('#cfgmore').innerHTML = '▼'; - $('#configbox').style.display = 'block'; + $('#configbox').showModal(); }) } @@ -444,7 +487,7 @@ $('#cfgsave').onclick = function () { .catch(error => showMessage('Error: ' + error)); $('#advancedoptions').style.height = '0px'; - $('#configbox').style.display = 'none'; + $('#configbox').close(); } function sendCmd(mac, cmd) { @@ -463,7 +506,7 @@ function sendCmd(mac, cmd) { }) .catch(error => showMessage('Error: ' + error)); $('#advancedoptions').style.height = '0px'; - $('#configbox').style.display = 'none'; + $('#configbox').close(); } $('#cfgdelete').onclick = function () { @@ -494,7 +537,8 @@ $('#cfgreset').onclick = function () { sendCmd($('#cfgmac').dataset.mac, "reset"); } -$('#rebootbutton').onclick = function () { +$('#rebootbutton').onclick = function (event) { + event.preventDefault(); showMessage("rebooting AP....", true); fetch("/reboot", { method: "POST" @@ -502,30 +546,37 @@ $('#rebootbutton').onclick = function () { socket.close(); } -$('#apconfigbutton').onclick = function () { - let table = document.getElementById("aptable"); - const rowCount = table.rows.length; - for (let i = rowCount - 1; i > 0; i--) { - table.deleteRow(i); +$('#configbox').addEventListener('click', (event) => { + if (event.target.nodeName === 'DIALOG') { + $('#configbox').close(); } - fetch("/get_ap_config") - .then(response => response.json()) - .then(data => { - apConfig = data; - $('#apcfgalias').value = data.alias; - $('#apcfgchid').value = data.channel; - $("#apcfgledbrightness").value = data.led; - $("#apcfglanguage").value = data.language; - $("#apclatency").value = data.maxsleep; - $("#apcpreventsleep").value = data.stopsleep; - $("#apcpreview").value = data.preview; - $("#apcwifipower").value = data.wifipower; - $("#apctimezone").value = data.timezone; - $("#apcnight1").value = data.sleeptime1; - $("#apcnight2").value = data.sleeptime2; - }) - $('#apconfigbox').style.display = 'block' -} +}); + +document.addEventListener("loadTab", function (event) { + activeTab = event.detail; + switch (event.detail) { + case 'configtab': + case 'aptab': + fetch("/get_ap_config") + .then(response => response.json()) + .then(data => { + apConfig = data; + $('#apcfgalias').value = data.alias; + $('#apcfgchid').value = data.channel; + $("#apcfgledbrightness").value = data.led; + $("#apcfglanguage").value = data.language; + $("#apclatency").value = data.maxsleep; + $("#apcpreventsleep").value = data.stopsleep; + $("#apcpreview").value = data.preview; + $("#apcwifipower").value = data.wifipower; + $("#apctimezone").value = data.timezone; + $("#apcnight1").value = data.sleeptime1; + $("#apcnight2").value = data.sleeptime2; + }) + $('#apcfgmsg').innerHTML = ''; + break; + } +}); $('#apcfgsave').onclick = function () { let formData = new FormData(); @@ -549,14 +600,13 @@ $('#apcfgsave').onclick = function () { .then(data => { showMessage(data); window.dispatchEvent(loadConfig); + $('#apcfgmsg').innerHTML = 'OK, Saved'; }) .catch(error => showMessage('Error: ' + error)); - - $('#apconfigbox').style.display = 'none'; } -$('#updatebutton').onclick = function () { - $('#apconfigbox').style.display = 'none'; +$('#updatebutton').onclick = function (event) { + event.preventDefault(); $('#apupdatebox').style.display = 'block'; loadOTA(); } @@ -720,7 +770,9 @@ function showMessage(message, iserr) { const messages = $('#messages'); const date = new Date(); const time = date.toLocaleTimeString('nl-NL', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); - if (iserr) { + if (message.startsWith('{')) { + messages.insertAdjacentHTML("afterbegin", '
  • ' + htmlEncode(time) + ' ' + message.replace(/"([^"]+)"/g, '"$1"') + '
  • '); + } else if (iserr) { messages.insertAdjacentHTML("afterbegin", '
  • ' + htmlEncode(time + ' ' + message) + '
  • '); } else { messages.insertAdjacentHTML("afterbegin", '
  • ' + htmlEncode(time + ' ' + message) + '
  • '); @@ -887,12 +939,18 @@ function GroupSortFilter() { } let show = true; + let batteryMv = tagDB[item.dataset.mac].batteryMv; if ($('input[name="filter"][value="remote"]').checked && item.dataset.isexternal == "false") show = false; if ($('input[name="filter"][value="local"]').checked && item.dataset.isexternal == "true") show = false; if ($('input[name="filter"][value="inactive"]').checked && item.querySelector('.warningicon').style.display != 'inline-block') show = false; if ($('input[name="filter"][value="pending"]').checked && !item.classList.contains("tagpending")) show = false; + if ($('input[name="filter"][value="lowbatt"]').checked && (batteryMv >= 2400 || batteryMv == 0 || batteryMv == 1337)) show = false; if (!show) item.style.display = 'none'; else item.style.display = 'block'; item.style.order = order++; + const checkedValues = Array.from(document.querySelectorAll('input[name="filter"]:checked')) + .map(checkbox => checkbox.value) + .join(', '); + $('#activefilter').innerHTML = (checkedValues ? 'filtered by ' + checkedValues : ''); }); headItems = Array.from($('#taglist').getElementsByClassName('taggroup')); @@ -901,7 +959,7 @@ function GroupSortFilter() { }) } -$('#toggleFilters').addEventListener('click', () => { +$('#toggleFilters').addEventListener('click', (event) => { event.preventDefault(); const filterOptions = $('#filterOptions'); filterOptions.classList.toggle('active'); @@ -912,6 +970,13 @@ $('#toggleFilters').addEventListener('click', () => { } }); +$('#activefilter').addEventListener('click', (event) => { + event.preventDefault(); + const filterOptions = $('#filterOptions'); + filterOptions.classList.add('active'); + filterOptions.style.maxHeight = filterOptions.scrollHeight + 20 + 'px'; +}); + async function getTagtype(hwtype) { if (tagTypes[hwtype]) { return tagTypes[hwtype]; @@ -1156,4 +1221,83 @@ function populateTimes(element) { option.text = i.toString().padStart(2, "0") + ":00"; element.appendChild(option); } +} + +function populateAPCard(msg) { + let apip = msg.ip; + let apid = apip.replace(/\./g, "-"); + if (!$('#ap' + apid)) { + div = $('#apcard').cloneNode(true); + div.setAttribute('id', 'ap' + apid); + $('#aplist').appendChild(div); + } + let alias = msg.alias; + if (!alias) alias = apip; + $('#ap' + apid + ' .apip').innerHTML = "" + apip + ""; + $('#ap' + apid + ' .apalias').innerHTML = alias; + $('#ap' + apid + ' .aptagcount').innerHTML = msg.count; + $('#ap' + apid + ' .apchannel').innerHTML = msg.channel; + + const elements = document.querySelectorAll('.apchannel'); + Array.from(elements).forEach(element => { + if (element.textContent === msg.channel && element.id !== 'ap' + apid) { + $('#ap' + apid + ' .apchannel').style.color = 'red'; + $('#ap' + apid + ' .apchannel').innerHTML += ' conflict'; + } + }); + + // $('#ap' + apid + ' .apversion').innerHTML = msg.version; + if (activeTab == 'aptab') { + populateAPInfo(apip); + } +} + +function populateAPInfo(apip) { + let apid = apip.replace(/\./g, "-"); + fetch('http://' + apip + '/sysinfo') + .then(response => { + if (response.status != 200) { + $('#ap' + apid + ' .apswversion').innerHTML = "Error fetching sysinfo: " + response.status; + return {}; + } else { + return response.json(); + } + }) + .then(data => { + if (data.env) { + let version = ''; + version += `env: ${data.env}
    `; + version += `build date: ${formatEpoch(data.buildtime)}
    `; + version += `esp32 version: ${data.buildversion}
    `; + version += `psram size: ${data.psramsize}
    `; + version += `flash size: ${data.flashsize}
    `; + $('#ap' + apid + ' .apswversion').innerHTML = version; + // if (data.env == 'ESP32_S3_16_8_YELLOW_AP') $("#c6Option").style.display = 'block'; + } + }) + .catch(error => { + $('#ap' + apid + ' .apswversion').innerHTML = "Error fetching sysinfo: " + error; + }); +} + +function formatEpoch(epochTime) { + const date = new Date(epochTime * 1000); // Convert seconds to milliseconds + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}`; +} + +function setFilterAndShow(filter) { + $('input[name="filter"][value="remote"]').checked = false; + $('input[name="filter"][value="local"]').checked = false; + $('input[name="filter"][value="inactive"]').checked = (filter == 'inactive'); + $('input[name="filter"][value="pending"]').checked = (filter == 'pending'); + $('input[name="filter"][value="lowbatt"]').checked = (filter == 'lowbatt'); + GroupSortFilter(); + $(`[data-target='tagtab']`).click(); } \ No newline at end of file