Open ewowi opened 5 months ago
While I love the UI for Synology, I'm not sure it's really the best comparison, we aren't trying to build an entire OS gui, just controls for embedded devices so if be looking more at things like the UI for a WiFi access point, smart power plug etc
Yeah - agree we are not building an entire OS gui - But StarBase is a lightweight OS-like layer so maybe a bit of a OS GUI ... ;-)
A bit about the history:
I would like to keep most of these things in some way but realise it is too overwhelming / nerdy now. My next idea is instead of dragging them to another column is dragging them anywhere you like - so get rid of the column structure - see : https://www.w3schools.com/css/css_positioning.asp
I think implementing these absolute positions is not too difficult and it allows more freedom to organise it the way a user wants - this led me to Synology interface. Next to absolute position also width and height of a panel should be defined and panels scale / layout their elements within that boundary (scrolling if needed)
So long story short - would be nice to have this positioning implemented - as we are close to that - but for the rest we could make a control structure which makes it look much more straightforward as it is now.
What about Home Assistant interface? This also has panels which can be moved around?
Maybe you can share screenshots of simpler UI's we can use for inspiration?
[{"id":"Files","type":"sysmod","ro":true,"max":255,"n":[{"id":"fileTbl","type":"table","ro":false,"n":[{"id":"flName","type":"text","ro":true,"max":32},{"id":"flSize","type":"number","ro":true},{"id":"flTime","type":"number","ro":true},{"id":"flEdit","type":"fileEdit","ro":false,"value":["F_Fiber.json","F_Panel-128x64.json","F_Panel-32x32.json","F_Panel-64x64.json","F_Panel-80x80.json","F_Panel-8x8.json","F_Panel-90x90.json","F_Rings241-9.json","balls.sc","blink.sc","helloworld1.sc","helloworld2.sc","helloworld3.sc","model.json","octo.sc","blink.sc","helloworld1.sc","helloworld2.sc","helloworld3.sc","model.json","octo.sc"]}]},{"id":"upload","type":"fileUpload","ro":false},{"id":"drsize","type":"progress","ro":true,"max":262144}]},{"id":"System","type":"sysmod","ro":true,"max":255,"s":true,"n":[{"id":"upTime","type":"text","ro":true,"max":16},{"id":"reboot","type":"button","ro":false},{"id":"loops","type":"text","ro":true,"max":16},{"id":"chip","type":"text","ro":true,"max":16},{"id":"heap","type":"progress","ro":true,"max":292},{"id":"mainStack","type":"progress","ro":true,"max":8192},{"id":"tcpStack","type":"progress","ro":true,"max":16384},{"id":"reset0","type":"select","ro":true},{"id":"reset1","type":"select","ro":true},{"id":"restartReason","type":"select","ro":true},{"id":"build","type":"text","ro":true,"max":32},{"id":"update","type":"fileUpload","ro":false},{"id":"name","type":"text","ro":false,"max":24,"value":"Lab-16","oldValue":"Star3232-16"},{"id":"now","type":"number","ro":true,"max":-1},{"id":"timeBase","type":"number","ro":true,"max":-1}],"view":"vAll"},{"id":"Pins","type":"sysmod","ro":true,"max":255,"n":[{"id":"pinTbl","type":"table","ro":true,"n":[{"id":"pinNr","type":"pin","ro":true,"max":40},{"id":"pinOwner","type":"text","ro":true,"max":32},{"id":"pinDetails","type":"text","ro":true,"max":256}]},{"id":"board","type":"canvas","ro":true,"interval":100,"loopFun":0},{"id":"pin19","type":"checkbox","ro":false,"value":1}]},{"id":"Print","type":"sysmod","ro":true,"max":255,"n":[{"id":"pOut","type":"select","ro":false,"value":1,"oldValue":2},{"id":"log","type":"textarea","ro":false}]},{"id":"Web","type":"sysmod","ro":true,"max":255,"n":[{"id":"clTbl","type":"table","ro":true,"n":[{"id":"clNr","type":"number","ro":true,"max":999},{"id":"clIp","type":"text","ro":true,"max":16},{"id":"clIsFull","type":"checkbox","ro":true},{"id":"clStatus","type":"select","ro":true},{"id":"clLength","type":"number","ro":true,"max":64}]},{"id":"maxQueue","type":"number","ro":true,"max":64},{"id":"wsSend","type":"text","ro":true,"max":16},{"id":"wsRecv","type":"text","ro":true,"max":16},{"id":"udpSend","type":"text","ro":true,"max":16},{"id":"udpRecv","type":"text","ro":true,"max":16}]},{"id":"Network","type":"sysmod","ro":true,"max":255,"s":true,"n":[{"id":"ssid","type":"text","ro":false,"max":31,"value":"ewtr","oldValue":""},{"id":"pw","type":"password","ro":false,"value":"zonledmod","oldValue":"","max":63},{"id":"connect","type":"button","ro":false},{"id":"nwstatus","type":"text","ro":true,"max":32},{"id":"rssi","type":"text","ro":true,"max":32}]},{"id":"E131","type":"usermod","ro":true,"max":255,"n":[{"id":"dun","type":"number","ro":false,"max":7,"value":1},{"id":"dch","type":"number","ro":false,"min":1,"max":512,"value":1},{"id":"e131Tbl","type":"table","ro":true,"n":[{"id":"e131Channel","type":"number","ro":true,"min":1,"max":512},{"id":"e131Name","type":"text","ro":true,"max":32},{"id":"e131Max","type":"number","ro":true},{"id":"e131Value","type":"number","ro":true,"max":255}]}]},{"id":"Model","type":"sysmod","ro":true,"max":255,"s":true,"n":[{"id":"saveModel","type":"button","ro":false},{"id":"showObsolete","type":"checkbox","ro":false,"value":0},{"id":"deleteObsolete","type":"button","ro":false}]},{"id":"UI","type":"sysmod","ro":true,"max":255,"n":[{"id":"vlTbl","type":"table","ro":true,"n":[{"id":"vlVar","type":"text","ro":true,"max":32},{"id":"vlLoopps","type":"number","ro":true,"max":999}]}]},{"id":"Instances","type":"sysmod","ro":true,"max":255,"n":[{"id":"insTbl","type":"table","ro":true,"n":[{"id":"insName","type":"text","ro":false,"max":32},{"id":"insLink","type":"number","ro":true},{"id":"insIp","type":"text","ro":true,"max":16},{"id":"insType","type":"text","ro":true,"max":16},{"id":"insVersion","type":"number","ro":true,"max":-1},{"id":"insUp","type":"number","ro":true,"max":-1},{"id":"inson","type":"checkbox","ro":false},{"id":"insdch","type":"number","ro":false,"min":1,"max":512},{"id":"insbri","type":"range","ro":false,"max":255,"log":true},{"id":"insShow","type":"url","ro":true},{"id":"insTS","type":"number","ro":true,"max":-1},{"id":"insTT","type":"number","ro":true,"max":-1},{"id":"insTM","type":"number","ro":true,"max":-1},{"id":"insNow","type":"number","ro":true,"max":-1}]}]},{"id":"Modules","type":"sysmod","ro":true,"max":255,"n":[{"id":"mdlTbl","type":"table","ro":true,"n":[{"id":"mdlName","type":"text","ro":true,"max":32},{"id":"mdlSuccess","type":"checkbox","ro":true},{"id":"mdlEnabled","type":"checkbox","ro":false,"value":[true,true,true,true,true,true,true,false,false,true,true,true,true,true]}]}]},{"id":"Motion Tracking","type":"usermod","ro":true,"max":255,"n":[{"id":"mtReady","type":"checkbox","ro":true},{"id":"gyro","type":"coord3D","ro":true},{"id":"accell","type":"coord3D","ro":true}]},{"id":"AppMod Demo","type":"appmod","ro":true,"max":255,"n":[{"id":"on","type":"checkbox","ro":false,"value":1},{"id":"bri","type":"range","ro":false,"max":255,"value":10,"log":true},{"id":"textField","type":"text","ro":false,"max":32,"value":"text"},{"id":"blinkPin","type":"pin","ro":false,"max":40},{"id":"frequency","type":"range","ro":false,"max":255,"value":44}]},{"id":"Live","type":"usermod","ro":true,"max":255,"n":[{"id":"script","type":"select","ro":false},{"id":"fps1","type":"text","ro":true,"max":10},{"id":"fps2","type":"text","ro":true,"max":10}]}]
Above is contents of model.json, which is used by JavaScript to generate all the fields in the ui
see this discussion: https://discord.com/channels/700041398778331156/1262883283809603698
Copying discussion from discord here ...
@aaronaverill said on July 17
I've done UI design and dev for a few decades if you want to bounce ideas around.
For what I know of your app, it seems to be primarily tailored to an admin dashboard kind of look and feel. If that's true, I would go with a vertical left rail for primary navigation, and a main area to the right of that with a vertical scrolling overflow Like this.
Yeah this typically collapses into a hamburger menu on the left side on mobile with a vertical list that scrolls if needed just like you did! Icons are obviously opional You can set some cute horizontal transition css property if you want it to "slide" out the other mobile approach would be a max of 4 bottom main menus, and then they have to drill into detail pages, but I dont think thats appropriate for such a complex config this has essentially become standard UI for this type of app. Of course, you could get creative if you want to have a unique and memorable UI 🙂
Do you have the concept of module collections? You could offer that as a top level navigation on the side, with the modules being indented under, if you get a lot of modules this can be more easily navigated
This is adjacent to UI design, but related to the implementation, and forgive me if I'm telling you stuff you know but you should move to implementing your javascript inside of classes with private functions prefixed with # so the minimizer will obfuscate them and you can stick to human readable method names but not worry about performance
Apologies for a newb question but are you doing the new ui development in a separate branch in the starbase repo? I've moved to doing all my mcu ui development with es6 modules for the javascript and rollup to bundle the files. Its a decent system that gives good control over how you serve your html, css, js from the controller. And everything is clean and modern and modular as it should be in 2024.
I guess its a personal preference but for example I find the 3,000 line index.js file of wled to be inscrutable for anyone except the original developer. Modern js techniques will allow much easier contribution, maintenance and quicker feature innovation Its a much more scalable approach as well if you find a set of pages is getting too large to serve from the mcu in a single request you can easily break them into separate files served only when needed hitting certain pages. Browser support for dynamic imports now does all the work of loading modules on demand only when needed. Cool stuff
@ewowi July 18
I might do it just in the main branch as the old ui is still fully available, so the new ui is not interfering, it’s just
We now zip all the files using npm into html_ui.h so it’s just a c file instead of index.js etc to be copied to the file system (like done in WLED) as far as I know index.html must explicitly import index.js, index.css etc so not sure if dynamic import works here ?
Fully agree but see the remark, but the idea of splitting into more files is for sure a good idea! I will submit the setup for the new UI most likely tomorrow, then you could play with it and tell me what you think I could use some help in css magic, to nicely move nodes around the screen 🙂
@aaronaverill on July 18
So my first recommendation is to have your top nav by sticky by using a flex layout for the body and wrap the page contents in a div that has overflow-y as auto so you get a vertical scrollbar
I think the nav layout looks ok once that is fixed
@ewowi July 18
Although my advanced html and even more css skills are very limited this sounds good to me 🙂 Did you saw the way I generate html: by using the cE function which does createElement, instead of extending innerHTML as i understand it’s then part of the dom and allows things like addEventListener on the nodes created that way. Does that sound okay for you? (Also used in WLED )
@aaronaverill July 18
I have opinions hahaha It's definitely a preference thing, but typically you would put the markup in HTML, and then use something like mustache as a templating language. With the ESP32 I think you can get away with this, mustache comes to only 400 bytes gzipped! mustache is great, and it will be much cleaner looking code and faster to develop complex layouts You can append -OR- set innerHTML, either will be placed into the DOM and allow you to attach event listeners. So...
element.innerHTML = '<div onclick="nav.click()">Click me</div>'
Is equivalent to the same with append and add event handler, but it's maybe a lot less code on the mcu to serve back to the webpage
@ewowi July 18:
Thanls a lot for your feedback, this helps a lot!
So what can we do? Does this makes sense: 1) I push another commit, using innerHTML instead of createElement as much as possible? 2) Add the html suggestion above 3) make a separate branch with a moustache POC
Regarding 2 and also 3: I can add it, but I think it would be nicer if you fork and pull request it, by that your work is also visible 😉 (micromoustache: not updated the last 2 years, so thats not good I guess 😉 )
@aaronaverill on July 18
oh its also maybe worth mentioning, defining d = document and naming functions like cE doesn't really buy you any space savings since gzip is gonna squish all that down into a few bits if it's used everywhere in your code. Since vscode is doing function completion, it's pretty much just as easy to have the javascript say document.createElement ...etc... and then it's more maintainable by others that dont know the homegrown system of abbreviations.
I guess wled did this but maybe it was before there is so many build tools to squish files down for you probably the minifier and gzip are smarter than us.. they will eliminate functions you never use, etc i gotta hit work but will have a chance to check later on the weekend cheers
Sorry, I missed this earlier.
My opinion: If you're starting an entirely new project, and if you're requiring ESP32, use modern tools all the way, modern javascript languages and pull in any libraries that are useful and will work on the platform. Set up the project to be relevant for another 5-10 years.
To me that would also mean modern javascript, so just as an example. this:
let found = false; for (let module of model) { if (module.id == json.id) found = true; }
Becomes this:
const found = model.some(module => module.id == json.id) Beyond being quicker to develop and more friendly to web devs that might contribute, leveraging the full javascript api is going to make the code much smaller this is just one example but there is lots of language to leverage! ✌️ To your point. I feel like you should have an experimental UI branch thats not on main where you can really mess around with new tech and modern approaches and do some learning
I'm also happy to set up a base app framework window - body, top nav, pages, with a modern approach, if you wanna use that as a learning tool. I'm not sure if your goals are to just get this done or more a hobby where you're playing around learning new tech
@ewowi July 18
ounds like a good plan to use the latest insights in setting it up, I am not sure what the average level of our contributors is, mostly I am asked to do UI stuff and I am good at Google and copy and paste, so I took what WLED had and build on it
For sure! I did current commit in main as it is running side by side, and not interfering and allows more people to see it , instead of them needing to compile a different branch
That sound great, my goal is somewhat in between getting it done and play around with new tech, the way we work is continuous improvement so it can always be better But if you could help setting up a framework that would be great, but I don’t have the time to do it all by myself so I hope you can fork and pull request this framework - in another branch of course So one thing to keep in mind is that the ui is fully generated based on the json file, plus the ui on itself asks the server if it needs more info, eg list of values for drop down lists, also the server periodically sends info using websockets eg uptime etc but also the preview LEDs data. This is setup in a way that the ui has for sure not a single notion of LEDs and also very little notion of the system modules (with a few pragmatic exceptions). If I understood correctly moustache could help in json to html conversions / deal with this dynamic setup
Added this in latest commit:
https://github.com/ewowi/StarBase/commit/e41595a682547c4d8d145719d7db8851653c7d6a
Did not use innerHTML but cE calls here as otherwise I did not know how to place the call to the navBar class in between
navBar = new NavBar(body); //adds the navBar to <body>
This is an improvement, thx! GitHub newui: style body and content area and place all content here · ewo... idea by aaroneous newui: style body and content area and place all content here · ewo...
if you have suggestions for point 1 to 5, I am happy to hear 🙏 I think it are mostly changes in the css file
And I am thinking, shouldn’t these style options also be moved to css ?
@aaroneous not to overhelm you with questions (the nr 1 to 5), so no hurry, but maybe start with 1. Here you can see what I mean: I added a title bar (and some more temporary stuff) above the navbar and when I click on the hamburger, the nav-list is shown above the hamburger instead of below I think it might have to do with position: absolute / top 40px but when I change it to relative it didn't work well, so any suggestions: Here is the css file for reference: https://github.com/ewowi/StarBase/blob/main/data/newnavbar.css
@aaronaverill at July 19
definitely the absolute 40px, you need to set that px to be higher, or possibly have an empty positioning container around it that is positioned relatively, eg:
<div style="position:relative"> <!-- The drop down container -->
<div style="position:absolute"> <!-- the actual drop down -->
The position of any absolute element is based on the nearest parent that is relative, or in the case of none, the browser window. So without the container, your menu is going to be 40px from the top of the browser screen.
You need to keep the drop down "absolute" because that style will cause it to be removed from the flow of the page layout - it won't take up space pushing things below it and will sit on top like you want
I haven't looked closely at your code, but if you have your menu in an outer container, you can then show/hide that with the toggle, and when it's shrunk to mobile use CSS media queries to change it from position:relative to position:absolute with a 100% width/height and top/left = 0, so your mobile menu fills the entire screen until they click (when it hides)
Some of this you can do with css styles, so you can do with javascript. I'd start by adding a class to the menu called "top-nav" or something Sorry haven't had a look at your code in detail yet
I will try to have two project templates for you by Sunday based on your GUI here: A standard HTML/CSS/JS that shows modern standards and you can drop into the project as-is A ES6 module version which will require some changes to your node bundling scripts, but offers better options for modularity and control over the final output sized served from the mcu
If nothing else, maybe you can learn some techniques I found have helped with my web development I'll structure these so you can also run these projects in vscode "Live Server" which gives you an option to quickly do code changes and development without any compile, upload, reboot cycle. The vscode extension runs a webserver off your file system and hot reloads the browser every time you save a file for instant feedback
oh its delightful. in vscode click Extensions search for "Live Server" install restart vscode rightclick your html file and select "Open with Live Server" Works great on your codebase now Only small issue is that you have to comment out the websockets call and mock with a json file but it supports javascript fetch and serves from the file system so you can do this:
var json = await fetch('/server-response.json').json()
And here you have all your mocked data in the file server-response.json And then... instant browser updates while you edit and save html, js, css 😄
You can easily layer mobile navigation ui on later. Or change up the nav hierarchy but its something that can give you ideas if nothing else Yay json!! Its practically done right? 😅 I gotta work on some of my own hobby projects but feel free to ask anything about how I approached the structure or js functions that I'm using. I think you can pretty much drop in your websocket code, move it into starbase and in theroy it should just build and run off the chip You've got some areas to show alerts and sample code how to write a setter and update the UI to display things. Good luck!
this is decent https://www.youtube.com/watch?v=IEf1KAcK6A8
it doesn't cover private class properties (#) or setters, but I think you can see my code and figure that out in 2 seconds lol
@ewowi Maybe one question to give a hint on: my initial screens (after on load) are build up using the model.json but after that the ui is ‘starting to live’ using websockets communicating back and forth like give me the options of a select, or hey I got a new value for you, or there is a new row in a table (or I created a new row in a table). I implemented that now playing heavily with nodes. Can you give it a thought (not necessarily now) how that will be implemented ? (Links also welcome), is that where moustache could play a role ?
I think you can just refresh the whole UI by setting innerHTML on any main pages which are active. Until you find performance is too shitty then write incremental updates of different areas more smartly
@ewowi July 22
I am doing things step by step (to flatten the learning curve 😉 ): Added support for live server in the newui.js. See
https://github.com/ewowi/StarBase/commit/c5f0616e1e828f65779ddf58d747faf9297b4da5
Added there also a mini versie of your App class, which is invoked now if the ip is 127.0.0.1 (Live Server). Could you do a quick check there (although it is now a mix of old and new 😉 )
3 short questions: you don't use ; at the end if a line, are they not advised to use anymore? Also not in old style code? (I noticed that in case I forgot one, it was never a problem) what does # means in this.#updateUI etc? Why the # not sure about set yet, can you give a short explanation?
The live server is really cool by the way!!! so much easier now to develop
@aaronaverill on July 22
#
is a private function - it tells the code minifier when you package up the javascrip - this is not used anywhere outside, you can obfuscate the name to save space. usually they will convert to: #a, #b, #c etcthe advantage of a setter is you can then do things like refresh the UI, but it is functionally equivalent of writing a function to set a member variable
Added new commit https://github.com/ewowi/StarBase/commit/5e792194b46023f31da1c67565ea514508af7a4c
Implementing main navigation as proposed by @aaronaverill and made some modifications to make it fit for StarMod
https://github.com/user-attachments/assets/8b47f018-4686-45b6-9ca4-084267324833
Click on the commit changes to review what is done.
Main challenge: make it possible to use modern ui design while keeping it modular so also old style can be used to not have a big bang change which is a step to far for current devs including me ;-) So we take it step by step.
What has been done:
New version in NewUi-dev branch: https://github.com/ewowi/StarBase/commit/864477f341b48e06551025b089bdb65fb4cf2f82
Current StarMod UI is a POC UI, meaning it implements the StarMod architecture but is not the user friendliest.
So we need to redesign it.
Step 1: Inspiration
Inspiration 1: Synology UI
Requirements: