updated web interface design

This commit is contained in:
Nic Limper
2023-09-26 10:27:57 +02:00
parent 75c6a6c0f9
commit 33ba6a7aa7
6 changed files with 966 additions and 412 deletions

Binary file not shown.

View File

@@ -8,15 +8,419 @@
<title>Open EPaper Link Access Point</title>
<link rel="stylesheet" href="main.css" type="text/css" />
<link rel="icon" type="image/vnd.icon" href="favicon.ico">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
</head>
<body>
<header>
<div class="logo">Open EPaper Link Access Point</div>
<nav>
<div>
<!-- tabs -->
<div class="tab-container">
<div class="tablinks material-symbols-outlined" data-target="hometab" title="Dashboard">home</div>
<div class="tablinks material-symbols-outlined" data-target="tagtab" title="Tags">sell</div>
<div class="tablinks material-symbols-outlined" data-target="aptab" title="Access Points">cell_tower
</div>
<!--<div class="tablinks material-symbols-outlined" data-target="templatetab" title="Templates">browse
</div>-->
<div class="tablinks material-symbols-outlined" data-target="configtab" title="Settings">settings
</div>
<div class="tablinks material-symbols-outlined" data-target="logtab" title="Logging">text_snippet
</div>
</div>
<!-- /tabs -->
<div><span id="runstate"></div>
<div><span id="apstatecolor">&#11044;</span> <span id="apstate">loading</span></div>
<div><a href="/edit" target="littlefs" class="filebutton material-symbols-outlined">folder_open</a>
</div>
</div>
</nav>
</header>
<div id="configbox">
<div class="closebtn">&#10006;</div>
<form>
<div class="container">
<div class="window">
<div id="hometab" class="tabcontent">
<table>
<tr onclick="setFilterAndShow('')">
<td class="material-symbols-outlined" style="color:#239f26" id="dashboardStatusIcon">
check_circle
</td>
<td id="dashboardStatus" style="color:#239f26" colspan="2">
initialising...
</td>
</tr>
<tr onclick="setFilterAndShow('')">
<td class="material-symbols-outlined" style="color:#77239e">
sell
</td>
<td>
tags
</td>
<td id="dashboardTagCount" style="color:#77239e">
0
</td>
</tr>
<tr onclick="setFilterAndShow('pending')">
<td class="material-symbols-outlined" style="color:#235f9e">
hourglass_empty
</td>
<td>
pending data
</td>
<td id="dashboardPending" style="color:#235f9e">
0
</td>
</tr>
<tr onclick="setFilterAndShow('lowbatt')">
<td class="material-symbols-outlined" style="color:#9e9223">
battery_low
</td>
<td>
low battery
</td>
<td id="dashboardLowBatt" style="color:#9e9223">
0
</td>
</tr>
<tr onclick="setFilterAndShow('inactive')">
<td class="material-symbols-outlined" style="color:#9e2323">
signal_disconnected
</td>
<td>
timeout
</td>
<td id="dashboardTimeout" style="color:#9e2323">
0
</td>
</tr>
<!--
<tr onclick="$(`[data-target='aptab']`).click()">
<td class="material-symbols-outlined" style="color:#239f26">
cell_tower
</td>
<td>
access points
</td>
<td id="dashboardApCount" style="color:#239f26">
</td>
</tr>
-->
</table>
</div>
<div id="tagtab" class="tabcontent">
<div class="tagheader">
<h3>Currently active tags</h3>
<div id="activefilter"></div><button class="material-symbols-outlined"
id="toggleFilters">filter_alt</button>
</div>
<div id="filterOptions">
<div>
<div>group by</div>
<div>
<input type="radio" name="group" value="" id="rnone" checked><label
for="rnone">None</label>
</div>
<div>
<input type="radio" name="group" value="model" id="rtagtype"><label for="rtagtype">Tag
model</label>
</div>
<div>
<input type="radio" name="group" value="contentmode" id="rcontent"><label
for="rcontent">Content</label>
</div>
<div>
<input type="radio" name="group" value="data-channel" id="rchannel"><label
for="rchannel">Channel</label>
</div>
</div>
<div>
<div>sort by</div>
<div>
<input type="radio" name="sort" value="alias" id="ralias" checked><label
for="ralias">Alias</label>
</div>
<div>
<input type="radio" name="sort" value="mac" id="rmac"><label for="rmac">Mac</label>
</div>
<div>
<input type="radio" name="sort" value="data-lastseen" id="rlastseen"><label
for="rlastseen">Last seen</label>
</div>
<div>
<input type="radio" name="sort" value="data-nextupdate" id="rnext"><label
for="rnext">Next update</label>
</div>
</div>
<div>
<div>filter</div>
<div>
<input type="checkbox" name="filter" value="local" id="rlocal"><label
for="rlocal">local</label>
</div>
<div>
<input type="checkbox" name="filter" value="remote" id="rremote"><label
for="rremote">remote</label>
</div>
<div>
<input type="checkbox" name="filter" value="inactive" id="rinactive"><label
for="rinactive">timed out</label>
</div>
<div>
<input type="checkbox" name="filter" value="pending" id="rpending"><label
for="rpending">pending</label>
</div>
<div>
<input type="checkbox" name="filter" value="lowbatt" id="rlowbatt"><label
for="rlowbatt">low battery</label>
</div>
</div>
</div>
<div id="taglist" class="taglist">
<div class="tagcard" id="tagtemplate">
<div class="currimg"><canvas class="tagimg"></div>
<div class="mac"></div>
<div class="alias"></div>
<div class="model"></div>
<div class="received"></div>
<div class="contentmode"></div>
<div class="lastseen"></div>
<div class="nextcheckin"></div>
<div class="nextupdate"></div>
<div class="corner">
<div class="pendingicon" title="A new message is waiting for the tag to pick up">
&circlearrowright;</div>
<div class="warningicon" title="This tag has not been seen for a long time">&#9888;
</div>
</div>
</div>
</div>
</div>
<div id="logtab" class="tabcontent">
<div class="tabheader">
<div><img id="clearlog" src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw==
"></div>
<div><input type="checkbox" id="showdebug" value="1"><label for="showdebug">Show all websocket
traffic</label></div>
</div>
<ul id="messages" class="messages">
</ul>
</div>
<div id="aptab" class="tabcontent">
<h3>Active access points</h3>
<div id="aplist">
<div id="apcard" class="apcard">
<p class="apip">194.109.6.66</p>
<p class="apalias">AP kitchen</p>
<div>
<span class="material-symbols-outlined">
sell
</span>
<span class="aptagcount">13</span>
<span class="material-symbols-outlined space">
cell_tower
</span>
<span class="apchannel">25</span>
</div>
<p class="apswversion">
fetching software version...
</p>
</div>
</div>
</div>
<div id="templatetab" class="tabcontent">
Work in progress...
</div>
<div id="configtab" class="tabcontent">
<h3>Access Point config</h3>
<p>
<label for="apcfgalias">Alias</label>
<input id="apcfgalias" type="text">
</p>
<p>
<label for="apcfgchid">Channel</label>
<select id="apcfgchid">
<option value="0" selected>auto</option>
<option value="11">11</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
</select>
</p>
<p>
<label for="apcfgledbrightness">LED brightness</label>
<select id="apcfgledbrightness">
<option value="-1">off</option>
<option value="20">10%</option>
<option value="64">25%</option>
<option value="128" selected>50%</option>
<option value="192">75%</option>
<option value="255">100%</option>
</select>
</p>
<p>
<label for="apcfglanguage">Content language</label>
<select id="apcfglanguage">
<option value="0" selected>EN English</option>
<option value="1">NL Nederlands</option>
<option value="2">DE Deutsch</option>
</select>
</p>
<p title="Depending on the content, a tag can sleep for
longer periods when no updates are expected
(like a date display). This setting specifies
the maximum sleep time.">
<label for="apclatency">Maximum sleep</label>
<select id="apclatency">
<option value="0" selected>shortest (40 sec)</option>
<option value="5">5 minutes</option>
<option value="10">10 minute</option>
<option value="30">30 minutes</option>
<option value="60">1 hour</option>
</select>
</p>
<p title="If connected to the website, don't sleep extra.
Latency will be around 40 seconds.">
<label for="apcpreventsleep">Shorten latency during config</label>
<select id="apcpreventsleep">
<option value="0">no</option>
<option value="1" selected>yes</option>
</select>
</p>
<p
title="Stops updates at night, and put the tags to sleep. During the configured night time, this overrides the maximum sleep time.">
<label for="apcnight1">No updates between</label>
<select id="apcnight1"></select>
<span style="align-self:center;">and</span>
<select id="apcnight2"></select>
</p>
<p title="Turn off preview images on the webpage if you want to manage many tags,
to save file system space">
<label for="apcpreview">Preview images</label>
<select id="apcpreview">
<option value="1" selected>yes</option>
<option value="0">no</option>
</select>
</p>
<p title="Wifi transmit power">
<label for="apcwifipower">Wifi power</label>
<select id="apcwifipower">
<option value="78">19.5 dBm</option>
<option value="76">19.0 dBm</option>
<option value="74">18.5 dBm</option>
<option value="68">17.0 dBm</option>
<option value="60">15.0 dBm</option>
<option value="52">13.0 dBm</option>
<option value="44">11.0 dBm</option>
<option value="34" selected>8.5 dBm</option>
<option value="28">7.0 dBm</option>
<option value="20">5.0 dBm</option>
<option value="8">2.0 dBm</option>
</select>
</p>
<p title="Your local time zone">
<label for="apctimezone">Local time zone</label>
<select id="apctimezone">
<optgroup label="Europe">
<option value="CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" selected>Central European
Time</option>
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Athens, Greece</option>
<option value="GMT+0IST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">Dublin, Ireland</option>
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Helsinki, Finland</option>
<option value="WET-0WEST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">Lisbon, Portugal</option>
<option value="GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">London, Great Britain
</option>
<option value="EET-2EEST,M3.5.0/3,M10.5.0/4">Kyiv, Ukraine</option>
</optgroup>
<optgroup label="USA / Canada">
<option value="HAW10">Hawaii Time</option>
<option value="AKST9AKDT">Alaska Time</option>
<option value="PST8PDT">Pacific Time</option>
<option value="MST7MDT">Mountain Time</option>
<option value="MST7">Arizona, no DST</option>
<option value="CST6CDT">Central Time</option>
<option value="EST5EDT">Eastern Time</option>
</optgroup>
<optgroup label="Australia / New Zealand">
<option value="EST-10EDT-11,M10.5.0/02:00:00,M3.5.0/03:00:00">Melbourne, Sydney</option>
<option value="WST-8">Perth</option>
<option value="EST-10">Brisbane</option>
<option value="CST-9:30CDT-10:30,M10.5.0/02:00:00,M3.5.0/03:00:00">Adelaide</option>
<option value="CST-9:30">Darwin</option>
<option value="EST-10EDT-11,M10.1.0/02:00:00,M3.5.0/03:00:00">Hobart</option>
<option value="NZST-12NZDT-13,M9.4.0/02:00:00,M4.1.0/03:00:00">New Zealand</option>
</optgroup>
<optgroup label="Asia">
<option value="JST-9">Tokyo</option>
<option value="WIB-7">Jakarta</option>
<option value="GMT+2">Jerusalem</option>
<option value="SGT-8">Singapore</option>
<option value="ULAT-8ULAST,M3.5.0/2,M9.5.0/2">Ulaanbaatar, Mongolia</option>
</optgroup>
<optgroup label="Central and South America">
<option value="BRST+3BRDT+2,M10.3.0,M2.3.0">Brazil, Sao Paulo</option>
<option value="UTC+3">Argentina</option>
<option value="CST+6">Central America</option>
</optgroup>
</select>
</p>
<p>
<input type="button" value="Save" id="apcfgsave"><span id="apcfgmsg"></span>
</p>
<h3>Manage</h3>
<p>
<button id="rebootbutton">Reboot AP</button> Saves the tagDB and instantly reboots the Access
Point
</p>
<p>
<a href="/backup_db" id="downloadDBbutton">Download tagDB</a>
</p>
<p>
<button id="updatebutton">Update</button> Manage firmware of the ESP32
</p>
<p>
<a href="/setup" target="setup" class="wifibutton">WiFi config</a> Opens a new window with WiFi
config options
</p>
<p>
<br>
<a href="https://github.com/jjwbruijn/OpenEPaperLink" target="_new">Github
OpenEPaperLink</a><br>
<a href="https://github.com/jjwbruijn/OpenEPaperLink/wiki" target="_new">OpenEPaperLink
Wiki</a><br>
</p>
</div>
</div>
</div>
</form>
<footer class="logbox">
<p>
<span>&nbsp;</span>
<span id="sysinfo"></span>
</p>
</footer>
<!-- -->
<dialog id="configbox">
<div class="closebtn2">&#10006;</div>
<h3 id="cfgmac">00000000</h3>
<p>
<label for="cfgalias">Alias</label>
@@ -50,183 +454,33 @@
<button id="cfgscan">scan</button>
<button id="cfgdeepsleep">deep sleep</button>
<button id="cfgreset">reset settings</button>
<button id="cfgdelete" title="remove"><img src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw== "></button>
<button id="cfgdelete" title="remove"><img
src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw== "></button>
</p>
</div>
<p id="savebar">
<span><input type="button" value="Save" id="cfgsave"></span>
<span id="cfgmore" title="advanced options">&#x25BC;</span>
</p>
</div>
<div id="apconfigbox">
<div class="closebtn">&#10006;</div>
<h3>Access Point config</h3>
<p>
<label for="apcfgalias">Alias</label>
<input id="apcfgalias" type="text">
</p>
<p>
<label for="apcfgchid">Channel</label>
<select id="apcfgchid">
<option value="0" selected>auto</option>
<option value="11">11</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
</select>
</p>
<p>
<label for="apcfgledbrightness">LED brightness</label>
<select id="apcfgledbrightness">
<option value="-1">off</option>
<option value="20">10%</option>
<option value="64">25%</option>
<option value="128" selected>50%</option>
<option value="192">75%</option>
<option value="255">100%</option>
</select>
</p>
<p>
<label for="apcfglanguage">Content language</label>
<select id="apcfglanguage">
<option value="0" selected>EN English</option>
<option value="1">NL Nederlands</option>
<option value="2">DE Deutsch</option>
</select>
</p>
<p title="Depending on the content, a tag can sleep for
longer periods when no updates are expected
(like a date display). This setting specifies
the maximum sleep time.">
<label for="apclatency">Maximum sleep</label>
<select id="apclatency">
<option value="0" selected>shortest (40 sec)</option>
<option value="5">5 minutes</option>
<option value="10">10 minute</option>
<option value="30">30 minutes</option>
<option value="60">1 hour</option>
</select>
</p>
<p title="If connected to the website, don't sleep extra.
Latency will be around 40 seconds.">
<label for="apcpreventsleep">Shorten latency during config</label>
<select id="apcpreventsleep">
<option value="0">no</option>
<option value="1" selected>yes</option>
</select>
</p>
<p title="Stops updates at night, and put the tags to sleep. During the configured night time, this overrides the maximum sleep time.">
<label for="apcnight1">No updates between</label>
<select id="apcnight1"></select>
<span style="align-self:center;">and</span>
<select id="apcnight2"></select>
</p>
<p title="Turn off preview images on the webpage if you want to manage many tags,
to save file system space">
<label for="apcpreview">Preview images</label>
<select id="apcpreview">
<option value="1" selected>yes</option>
<option value="0">no</option>
</select>
</p>
<p title="Wifi transmit power">
<label for="apcwifipower">Wifi power</label>
<select id="apcwifipower">
<option value="78">19.5 dBm</option>
<option value="76">19.0 dBm</option>
<option value="74">18.5 dBm</option>
<option value="68">17.0 dBm</option>
<option value="60">15.0 dBm</option>
<option value="52">13.0 dBm</option>
<option value="44">11.0 dBm</option>
<option value="34" selected>8.5 dBm</option>
<option value="28">7.0 dBm</option>
<option value="20">5.0 dBm</option>
<option value="8">2.0 dBm</option>
</select>
</p>
<p title="Your local time zone">
<label for="apctimezone">Local time zone</label>
<select id="apctimezone">
<optgroup label="Europe">
<option value="CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" selected>Central European Time</option>
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Athens, Greece</option>
<option value="GMT+0IST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">Dublin, Ireland</option>
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Helsinki, Finland</option>
<option value="WET-0WEST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">Lisbon, Portugal</option>
<option value="GMT+0BST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">London, Great Britain</option>
<option value="EET-2EEST,M3.5.0/3,M10.5.0/4">Kyiv, Ukraine</option>
</optgroup>
<optgroup label="USA / Canada">
<option value="HAW10">Hawaii Time</option>
<option value="AKST9AKDT">Alaska Time</option>
<option value="PST8PDT">Pacific Time</option>
<option value="MST7MDT">Mountain Time</option>
<option value="MST7">Arizona, no DST</option>
<option value="CST6CDT">Central Time</option>
<option value="EST5EDT">Eastern Time</option>
</optgroup>
<optgroup label="Australia / New Zealand">
<option value="EST-10EDT-11,M10.5.0/02:00:00,M3.5.0/03:00:00">Melbourne, Sydney</option>
<option value="WST-8">Perth</option>
<option value="EST-10">Brisbane</option>
<option value="CST-9:30CDT-10:30,M10.5.0/02:00:00,M3.5.0/03:00:00">Adelaide</option>
<option value="CST-9:30">Darwin</option>
<option value="EST-10EDT-11,M10.1.0/02:00:00,M3.5.0/03:00:00">Hobart</option>
<option value="NZST-12NZDT-13,M9.4.0/02:00:00,M4.1.0/03:00:00">New Zealand</option>
</optgroup>
<optgroup label="Asia">
<option value="JST-9">Tokyo</option>
<option value="WIB-7">Jakarta</option>
<option value="GMT+2">Jerusalem</option>
<option value="SGT-8">Singapore</option>
<option value="ULAT-8ULAST,M3.5.0/2,M9.5.0/2">Ulaanbaatar, Mongolia</option>
</optgroup>
<optgroup label="Central and South America">
<option value="BRST+3BRDT+2,M10.3.0,M2.3.0">Brazil, Sao Paulo</option>
<option value="UTC+3">Argentina</option>
<option value="CST+6">Central America</option>
</optgroup>
</select>
</p>
<p>
<input type="button" value="Save" id="apcfgsave">
</p>
<p>
Active access points:<br>
<table id="aptable">
<tr>
<th>ip</th>
<th>alias</th>
<th>tags</th>
<th>ch</th>
<th>AP ver</th>
</tr>
</table>
</p>
<p>
<span id="rebootbutton">reboot AP</span>
<a href="/backup_db" id="downloadDBbutton">download tagDB</a>
<span id="updatebutton">update</span>
<a href="/setup" target="setup" class="filebutton">WiFi config</a>
</p>
<p>
<a href="https://github.com/jjwbruijn/OpenEPaperLink" target="_new">Github OpenEPaperLink</a>
</p>
</div>
</dialog>
<div id="apupdatebox">
<div class="closebtn">&#10006;</div>
<h3>Update dashboard</h3>
<div id="easyupdate"></div>
<div id="advanceddiv">
<!--<div>
repo: <input type="text" name="repo"> <button id="switchRepo">Switch</button><br>
environment: <span id="environment">environment</span>
</div>-->
<div id="releasetable"></div>
<div>
<div id="rollbackOption" style="display:none"><button id="rollbackBtn">Rollback to previous firmware</button></div>
<span id="c6Option"><div id="updateC6Option"><button id="updateC6Btn">Update ESP32-C6</button> <input type="checkbox" value="1" checked id="c6download"> download latest version</div></span>
<div id="rollbackOption" style="display:none"><button id="rollbackBtn">Rollback to previous
firmware</button></div>
<span id="c6Option">
<div id="updateC6Option"><button id="updateC6Btn">Update ESP32-C6</button> <input type="checkbox"
value="1" checked id="c6download"> download latest version</div>
</span>
</div>
</div>
</div>
@@ -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;">
</ul>
<form>
<div class="container">
<div class="window">
<div class="actionbox">
<div>
<div>Currently active tags: <button class="filebutton" id="toggleFilters">arrange</button></div>
<div><span id="temp"></div>
<div><span id="runstate"></div>
<div><span id="apstatecolor">&#11044;</span> <span id="apstate">loading</span></div>
<div><span id="apconfigbutton">AP config</span></div>
<div><a href="/edit" target="littlefs" class="filebutton">File System</a></div>
</div>
<div id="filterOptions">
<div>
<div>group by</div>
<div><input type="radio" name="group" value="" id="rnone" checked><label for="rnone">None</label></div>
<div><input type="radio" name="group" value="model" id="rtagtype"><label for="rtagtype">Tag model</label></div>
<div><input type="radio" name="group" value="contentmode" id="rcontent"><label for="rcontent">Content</label></div>
<div><input type="radio" name="group" value="data-channel" id="rchannel"><label for="rchannel">Channel</label></div>
</div>
<div>
<div>sort by</div>
<div><input type="radio" name="sort" value="alias" id="ralias" checked><label for="ralias">Alias</label></div>
<div><input type="radio" name="sort" value="mac" id="rmac"><label for="rmac">Mac</label></div>
<div><input type="radio" name="sort" value="data-lastseen" id="rlastseen"><label for="rlastseen">Last seen</label></div>
<div><input type="radio" name="sort" value="data-nextupdate" id="rnext"><label for="rnext">Next update</label></div>
</div>
<div>
<div>filter</div>
<div><input type="checkbox" name="filter" value="local" id="rlocal"><label for="rlocal">only local</label></div>
<div><input type="checkbox" name="filter" value="remote" id="rremote"><label for="rremote">only remote</label></div>
<div><input type="checkbox" name="filter" value="inactive" id="rinactive"><label for="rinactive">only inactive</label></div>
<div><input type="checkbox" name="filter" value="pending" id="rpending"><label for="rpending">only pending</label>
</div>
</div>
</div>
</div>
<div id="taglist" class="taglist">
<div class="tagcard" id="tagtemplate">
<div class="currimg"><canvas class="tagimg"></div>
<div class="mac"></div>
<div class="alias"></div>
<div class="model"></div>
<div class="received"></div>
<div class="contentmode"></div>
<div class="lastseen"></div>
<div class="nextcheckin"></div>
<div class="nextupdate"></div>
<div class="corner">
<div class="pendingicon" title="A new message is waiting for the tag to pick up">&circlearrowright;</div>
<div class="warningicon" title="This tag has not been seen for a long time">&#9888;</div>
</div>
</div>
</div>
<div class="logbox">
<p>
<span>logging</span>
<span><img id="clearlog" src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw==
"></span>
<span id="sysinfo"></span>
</p>
<ul id="messages" class="messages">
</ul>
</div>
</div>
</div>
</form>
<script src="main.js"></script>
</body>
</html>
</html>

View File

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

View File

@@ -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 = "<a href=\"http://" + msg.apitem.ip + "\" target=\"_new\">" + msg.apitem.ip + "</a>";
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 = "<span>last seen</span>" + 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 = '&#x25BC;';
$('#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", '<li class="new">' + htmlEncode(time) + ' <span class="mono">' + message.replace(/"([^"]+)"/g, '"<span class="quote">$1</span>"') + '</span></li>');
} else if (iserr) {
messages.insertAdjacentHTML("afterbegin", '<li class="new error">' + htmlEncode(time + ' ' + message) + '</li>');
} else {
messages.insertAdjacentHTML("afterbegin", '<li class="new">' + htmlEncode(time + ' ' + message) + '</li>');
@@ -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 = "<a href=\"http://" + apip + "\" target=\"_new\">" + apip + "</a>";
$('#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}<br>`;
version += `build date: ${formatEpoch(data.buildtime)}<br>`;
version += `esp32 version: ${data.buildversion}<br>`;
version += `psram size: ${data.psramsize}<br>`;
version += `flash size: ${data.flashsize}<br>`;
$('#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();
}