From a79ce7883b666932e48664fef43545a423effeab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Gir=C3=B3n?= Date: Sat, 8 Jun 2024 09:03:58 +0200 Subject: [PATCH] web: main menu navigation rework (#394) * rework menu and add animation * add missing header * add even background color * add warning fixed size for mobile view * update const code * fix inverse warning message condition --- resources/style.css | 67 +++++++++++++++++++++++++++++++------ src/WebCfgServer.cpp | 50 +++++++++++++++------------ src/WebCfgServer.h | 1 + src/WebCfgServerConstants.h | 2 +- 4 files changed, 88 insertions(+), 32 deletions(-) diff --git a/resources/style.css b/resources/style.css index 6f1cce1e..ae8eb0cf 100644 --- a/resources/style.css +++ b/resources/style.css @@ -196,16 +196,6 @@ td>select { margin-bottom: 0px } -#tblnav td, th { - border: 0; - border-bottom: 1px solid; -} - -.tdbtn { - text-align: center; - vertical-align: middle; -} - .warning { color: #f00; } @@ -230,4 +220,61 @@ td>select { .adapt table td:first-child { border-bottom: 0; } .adapt table td:last-child { border-top: 0; } + + #tblnav a li>span { + max-width: 140px; + } +} + +#tblnav a { + border: 0; + border-bottom: 1px solid; + display: block; + font-size: 1rem; + font-weight: bold; + padding: .6rem 0; + line-height: 1; + color: var(--nc-tx-1); + text-decoration: none; + + background: linear-gradient(to left, transparent 50%, rgba(255,255,255,0.4) 50%) right; + background-size: 200% 100%; + transition:all .2s ease; +} + +#tblnav a:nth-child(even) { + background: linear-gradient(to left, var(--nc-bg-2) 50%, rgba(255,255,255,0.4) 50%) right; + background-size: 200% 100%; +} + +#tblnav a:hover { + background-position: left; + transition:all .45s ease; +} + +#tblnav a:active { + background: var(--nc-lk-1); + transition:all .15s ease; +} + +#tblnav a li { + list-style: none; + padding: .5rem; + display: inline-block; + width: 100%; +} + +#tblnav a li>span { + float: right; + text-align: right; + margin-right: 10px; + color: #f70; + font-weight: 100; + font-style: italic; + display: block; +} + +.tdbtn { + text-align: center; + vertical-align: middle; } diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index 287bd922..3f6b1f20 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -1179,36 +1179,29 @@ void WebCfgServer::buildHtml(String& response) if(_preferences->getBool(preference_check_updates)) printParameter(response, "Latest Firmware", _preferences->getString(preference_latest_version).c_str(), "/ota", "ota"); - response.concat("
"); - response.concat("
MQTT and Network Configuration
"); - buildNavigationButton(response, "Edit", "/mqttconfig", _brokerConfigured ? "" : "(!) Please configure MQTT broker"); - response.concat("
Nuki Configuration
"); - buildNavigationButton(response, "Edit", "/nukicfg"); - response.concat("
Access Level Configuration
"); - buildNavigationButton(response, "Edit", "/acclvl"); - response.concat("
Credentials
"); - buildNavigationButton(response, "Edit", "/cred", _pinsConfigured ? "" : "(!) Please configure PIN"); - response.concat("
GPIO Configuration
"); - buildNavigationButton(response, "Edit", "/gpiocfg"); - response.concat("
Firmware update
"); - buildNavigationButton(response, "Open", "/ota"); + response.concat("

"); + response.concat(""); } @@ -2306,6 +2299,21 @@ void WebCfgServer::buildNavigationButton(String &response, const char *caption, response.concat(""); } +void WebCfgServer::buildNavigationMenuEntry(String &response, const char *title, const char *targetPath, const char* warningMessage) +{ + response.concat(""); + response.concat("
  • "); + response.concat(title); + if(strcmp(warningMessage, "") != 0){ + response.concat(""); + response.concat(warningMessage); + response.concat(""); + } + response.concat("
  • "); +} + void WebCfgServer::printParameter(String& response, const char *description, const char *value, const char *link, const char *id) { response.concat(""); diff --git a/src/WebCfgServer.h b/src/WebCfgServer.h index dc8b76f8..40df2a72 100644 --- a/src/WebCfgServer.h +++ b/src/WebCfgServer.h @@ -60,6 +60,7 @@ class WebCfgServer void printTextarea(String& response, const char *token, const char *description, const char *value, const size_t& maxLength, const bool& enabled = true, const bool& showLengthRestriction = false); void printDropDown(String &response, const char *token, const char *description, const String preselectedValue, std::vector> options); void buildNavigationButton(String& response, const char* caption, const char* targetPath, const char* labelText = ""); + void buildNavigationMenuEntry(String &response, const char *title, const char *targetPath, const char* warningMessage = ""); const std::vector> getNetworkDetectionOptions() const; const std::vector> getGpioOptions() const; diff --git a/src/WebCfgServerConstants.h b/src/WebCfgServerConstants.h index a9031acb..4ed2a2a3 100644 --- a/src/WebCfgServerConstants.h +++ b/src/WebCfgServerConstants.h @@ -3,7 +3,7 @@ // escaped by https://www.cescaper.com/ // source: https://cdn.jsdelivr.net/npm/@exampledev/new.css@1.1.2/new.min.css -const char stylecss[] = ":root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000;--nc-tx-2:#1a1a1a;--nc-bg-1:#fff;--nc-bg-2:#f6f8fa;--nc-bg-3:#e5e7eb;--nc-lk-1:#0070f3;--nc-lk-2:#0366d6;--nc-lk-tx:#fff;--nc-ac-1:#79ffe1;--nc-ac-tx:#0c4047}@media(prefers-color-scheme:dark){:root{--nc-tx-1:#fff;--nc-tx-2:#eee;--nc-bg-1:#000;--nc-bg-2:#111;--nc-bg-3:#222;--nc-lk-1:#3291ff;--nc-lk-2:#0070f3;--nc-lk-tx:#fff;--nc-ac-1:#7928ca;--nc-ac-tx:#fff}}*{margin:0;padding:0}img,input,option,p,table,textarea,ul{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:normal;overflow-wrap:anywhere;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2)}abbr{cursor:help}abbr:hover{cursor:help}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}textarea{max-width:100%}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}td>input{margin-top:0;margin-bottom:0}td>textarea{margin-top:0;margin-bottom:0}td>select{margin-top:0;margin-bottom:0}#tblnav td,th{border:0;border-bottom:1px solid}.tdbtn{text-align:center;vertical-align:middle}.warning{color:red}@media only screen and (max-width:600px){.adapt td{display:block}.adapt input[type=text],.adapt input[type=password],.adapt input[type=submit],.adapt textarea,.adapt select{width:100%}.adapt td:has(input[type=checkbox]){text-align:center}.adapt input[type=checkbox]{width:1.5em;height:1.5em}.adapt table td:first-child{border-bottom:0}.adapt table td:last-child{border-top:0}}"; +const char stylecss[] = ":root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000;--nc-tx-2:#1a1a1a;--nc-bg-1:#fff;--nc-bg-2:#f6f8fa;--nc-bg-3:#e5e7eb;--nc-lk-1:#0070f3;--nc-lk-2:#0366d6;--nc-lk-tx:#fff;--nc-ac-1:#79ffe1;--nc-ac-tx:#0c4047}@media(prefers-color-scheme:dark){:root{--nc-tx-1:#fff;--nc-tx-2:#eee;--nc-bg-1:#000;--nc-bg-2:#111;--nc-bg-3:#222;--nc-lk-1:#3291ff;--nc-lk-2:#0070f3;--nc-lk-tx:#fff;--nc-ac-1:#7928ca;--nc-ac-tx:#fff}}*{margin:0;padding:0}img,input,option,p,table,textarea,ul{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:normal;overflow-wrap:anywhere;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2)}abbr{cursor:help}abbr:hover{cursor:help}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}textarea{max-width:100%}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}td>input{margin-top:0;margin-bottom:0}td>textarea{margin-top:0;margin-bottom:0}td>select{margin-top:0;margin-bottom:0}.warning{color:red}@media only screen and (max-width:600px){.adapt td{display:block}.adapt input[type=text],.adapt input[type=password],.adapt input[type=submit],.adapt textarea,.adapt select{width:100%}.adapt td:has(input[type=checkbox]){text-align:center}.adapt input[type=checkbox]{width:1.5em;height:1.5em}.adapt table td:first-child{border-bottom:0}.adapt table td:last-child{border-top:0}#tblnav a li>span{max-width:140px}}#tblnav a{border:0;border-bottom:1px solid;display:block;font-size:1rem;font-weight:bold;padding:.6rem 0;line-height:1;color:var(--nc-tx-1);text-decoration:none;background:linear-gradient(to left,transparent 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%;transition:all .2s ease}#tblnav a:nth-child(even){background:linear-gradient(to left,var(--nc-bg-2) 50%,rgba(255,255,255,0.4) 50%) right;background-size:200% 100%}#tblnav a:hover{background-position:left;transition:all .45s ease}#tblnav a:active{background:var(--nc-lk-1);transition:all .15s ease}#tblnav a li{list-style:none;padding:.5rem;display:inline-block;width:100%}#tblnav a li>span{float:right;text-align:right;margin-right:10px;color:#f70;font-weight:100;font-style:italic;display:block}.tdbtn{text-align:center;vertical-align:middle}"; // converted to char array by https://notisrac.github.io/FileToCArray/ const unsigned char favicon_32x32[] = {