Show Off Your Dashboards!

Thanks. Hadn't seen that page. Got a great customized weather widget now!

@anon81541053 What is your CSS code that changes the color of your tiles?

@spelcheck I suck at page design, but one thing I can help with is injecting Javascript, here's an example driver that does that for a custom attribute tile. It could be used together with some real data so as to not end up with an unused tile.
There's some limitations in this as of now, to inject the javascript "clear" and then "refresh" have to be run AFTER opening the Dashboard on which this tile is displayed. This is a problem that can be fixed, I just haven't had the time yet. But throwing this out there and maybe someone with time can fix that last bit and we can get to see some cool things done. CSS needs to be saved in the Dashboard since there's only 2*1024 characters available. 1024 characters per attribute is available.
This example code just shows an ugly modal dialog, but it does showcase all you need to insert external JS as well as arbitrary HTML.
I want a temperature tile which changes color gradually depending on temperature... Anyone up for the challenge in javascript?

 metadata {
    definition(name: "JavaScript Injector", namespace: "markus-li", author: "Markus Liljergren") {
        command "refresh"
        command "clear"
        
        attribute "javascript", "string"
        attribute "javascriptLength", "number"
        attribute "html", "string"
        attribute "htmlLength", "number"
    }
    preferences {   
    }
}


void updated() {
    log.info "Updated..."
    refresh()
}

String escapeForInsert(String myInsert) {
    myInsert = myInsert.replace('"', '\\\"').replace("'", "'")
    escapedInsert = ""
    myInsert.eachLine { 
        escapedInsert += it.trim() // '\\\n'
    } 
    return escapedInsert
}

void refresh() {
    // Do NOT use single-quotes (') in tags or any markup, ONLY use doubles-quotes (")!
    // Don't put CSS directly after "'''", start on the line below
    // The CSS needs to be saved MANUALLY into the Dashboard
    // There's not enough characters to insert it from here...
    String myCSS = '''
.modal {
  font-family: -apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif;
  display: none;
  position: absolute;
  background-color: yellow;
  z-index: 9999;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 200px;
}

.modal.is-open {
  display: block;
}
.modal-close-btn {
  background-color: grey;
}
'''  // Make sure this is on an empty last line, no CSS on this line
    
    // Don't put HTML directly after "'''", start on the line below
    String myHTML = '''
<div id="modal-1" class="modal" aria-hidden="true">
  <div tabindex="-1" data-micromodal-close>
    <div role="dialog" aria-modal="true" aria-labelledby="modal-1-title" >
      <header>
        <h2 id="modal-1-title">
          Modal Title
        </h2>
        <button class="modal-close-btn" aria-label="Close modal" data-micromodal-close>Close Me</button>
      </header>
      <div id="modal-1-content">
        Modal Content
      </div>
    </div>
  </div>
</div>
''' // Make sure this is on an empty last line, no HTML on this line
    // <div style="display:none;"></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+function(){    
    String myScript = '''
<svg style="display: none;" onload='
var body = document.getElementsByTagName("body")[0];

var script = document.getElementById("inserted-body-script");
var hasScript = script != null;
if(!hasScript) {
    script = document.createElement("script");
    script.setAttribute("id", "inserted-body-script")
}

script.type = "text/javascript";

script.src = "https://cdn.jsdelivr.net/npm/micromodal/dist/micromodal.min.js";
if(!hasScript) {
   body.appendChild(script);
   alert(6);
} else {
    MicroModal.show("modal-1");
    alert(10);
}
script.onload = function() { 
MicroModal.init({debugMode: true});
MicroModal.show("modal-1");
alert(2);
}
'></svg>'''
//}()//</div>'>
//'''
    
    String myHTMLScript = '''
<a href="#" data-micromodal-trigger="modal-1">Open modal dialog</a>
<svg style="display: none;" onload='
var body = document.getElementsByTagName("body")[0];
var div = document.getElementById("inserted-body-html");
var hasDiv = div != null;
if(!hasDiv) {
    div = document.createElement("div")
    div.setAttribute("id", "inserted-body-html")
}
div.innerHTML = "\
''' + escapeForInsert(myHTML) + '''\
\
";
if(!hasDiv) {
    body.prepend(div);
}
var script = document.getElementById("inserted-body-script");
if(script!=null) { 
MicroModal.init({debugMode: true});
MicroModal.show("modal-1");
alert(9);
}
//alert(1);
'></svg>'''
    String myJSMsg = "ms1 ${now()} ${myScript}"
    
    sendEvent(name: "javascript", value: "${myJSMsg}", isStateChange: true)
    sendEvent(name: "javascriptLength", value: "${myJSMsg.length()}", isStateChange: true)
    
    String myHTMLMsg = "ht1 ${now()} ${myHTMLScript}"
    
    sendEvent(name: "html", value: "${myHTMLMsg}", isStateChange: true)
    sendEvent(name: "htmlLength", value: "${myHTMLMsg.length()}", isStateChange: true)
    
    log.debug "Now: ${now()}, JS length: ${myJSMsg.length()}, HTTP length: ${myHTMLMsg.length()} Maximum is 1024"
}

void clear() {
    sendEvent(name: "html", value: "No JS", isStateChange: true)
    sendEvent(name: "javascript", value: "No JS", isStateChange: true)
}

void installed() {
    log.info "Installed..."
    refresh()
}

For staff: PLEASE don't patch this without providing an official way of injecting Javascript into dashboards...

3 Likes

Here was my WIP on my Kindle Fire 8HD
Fits well enough and icons are large enough to be useful.

3 Likes

Bravo my man! I'll PM you when I start testing, but well done exactly what was needed.

Where I can see we'd really benefit from this would be a recursive find and insert to take the actual status class from tile-primary and placing it at the parent tile level. It's crazy that all tile status classes are far within the tile itself, and colors are instead hard-coded in style of the tile element itself. The second thing we could really use this for is fixing the annoyances of ios webkit, like overscroll bounce, scroll-through, z-index shenanigans and heck even font size adjustments. Another worthwhile thing would be to hide and show (or minimize and maximize) the header on scroll down and up. Having the header just hard cut-off the scrollable area below it containing the tiles is very harsh. Having a background color fade in, and the entire header minimize would be pretty slick.

The flashiest thing we could do with it is enable parallax background effect, but that would really be icing on the cake.

I'll reach out to you, but I promise this will be used. +1 to HE not patching something like this until they offer a legitimate way to insert JS.

1 Like

Considering that they do give us a way to use CSS it would be nice if they could tag the elements properly... But yes, now there is a way :slight_smile:

Looking forward to it! There are many minor annoyances to fix.

See these are the flashy things I was hoping someone could do with this! I wouldn't have the time, too many other projects as well as rest of life...

I'm really hoping for a temperature tile with gradually changing colors based on if the temperature is above or below a set range. Set range in green (most intense in the middle, gradually changing towards the edges), above range fade towards red, below towards blue... Something like that, maybe a bit differently since this might not be clear, but you get my idea.

With this we can do whatever we want really, just a matter of time and effort. The limiting factor is code-length, but external JS can take care of that. It can be hosted locally on anything that can serve static files, so should be feasible for just about anyone.

Combined with tagging attributes in a custom driver and then use JS to extract and insert that class we can get really nice dynamic designs. Looking forward to seeing what you come up with using this :wink:

I've still not thought of (or at least not implemented) a way to host the JS files on HE, but if I do, that would make this 100% local to the hub... Though it wouldn't work in the cloud version of the dashboard with any of the methods I have in mind trying.
Which do reminds me, I've not tested this in the cloud version of the dashboard since I don't use that, but it does require testing. It "should" work, but let's not assume anything...

Do you know of a way to "embed" JS inside the CSS markup (without screwing it up) and then extract that using JS and insert it into the DOM as JS? That could make it possible to host JS locally "inside" the CSS field... Or maybe in the JSON configuration structure and parse that, since JSON is easy to work with in JS anyway. Will see if the JSON config can be reached through some undocumented API...

EDIT: I checked, the JSON is readily available from "/apps/api/1/dashboard/<dashboard id>/layout" and you can store whatever your want in that JSON, for example a "customJS" attribute :slight_smile: Then just extract that attribute and insert it into the DOM...

EDIT 2: Moving this discussion to this thread.

1 Like

I've been playing around with my main dashboard recently, thought I'd share it on this post. I plan to mount a 10.1" tablet on the side of my fridge and decided to layout the dashboard in three sections across the screen, exactly the right size to fit nicely on my 6" phone screen. Not sure whether I will keep the layout or not, or setup separate dashboards for the phone and tablet, but thought it was an interesting option.

I normally use Sharptools as a dashboard largely due to the drastic simplicity in setting it up and changing it as devices are acquired. But I thought I would spend some of the time to build one in Hubitat to try out a local based dashboard rather than cloud based.

My thoughts:
-I like the idea of a local dashboard that will work regardless of internet
-the local dashboard is definitely super fast although sharptools isn't slow by any means
-setting up a dashboard on Hubitat is a crazy slow and painful process
-i wish Hubitat had a better selection of icons built in
-i wish Hubitat allowed more individual switch color modification - there are a couple virtual switches that I use as indicators and would like to be bright red if on but don't want all other switches to also be bright red.
-i wish I could easily modify the name of a tile if it's not the same name I actually use for the device
-i would miss having our family Google calendar on the dashboard like I do with sharptools but don't know of a way to do this with Hubitat

This is a dashboard I made for my wall mounted 10.1" screen tablet.

4 Likes

Does anyone have their HE dashboard running in an iFrame within DAKboard on a touch screen? I'm curious to know how that would work.

I sent them a replacement for the current framework that included click, drag and drop / resize which would improve the setup experience immensely. This was before their Dash 2.0 that we have now. I guess they didn't heed the advice because we got another iteration of arrow clicking in modals. I mean why would they take my advice? :stuck_out_tongue:

7 Likes

Drag and drop would be awesome especially with a lock button so you don't accidentally move icons and so when you lock-down the dashboard no one would be able to move them even if they tried. They also said at one point they would work on making the pass-codes work across dashboards so you didn't have to keep entering pass-codes when moving between screens but that hasn't gone anywhere and tying the portal users to dashboards would be very nice so you could give some users access to certain dashboards via their sign on credentials instead of a pin. I thought we'd see some more changes to the dashboard experience by now other than just the arrows to move things around.

1 Like

I'm thinking they no longer have their Dashboard developer.

.. and this 'UI' aspect was always less important than the 'automation engine / control / rules' and dare I say 'reliability' aspect of the hub. I'm sure there are lots of ideas Hubitat have on their to do list but there are other more important things to fix and add first . I agree with that prioritization.

You can do a lot via the Maker API with an external dashboard product - and UI eye candy and features absorb loads and loads of time in implementation.

But a nice tablet interface on your wall makes the product family friendly and also impresses your friends pulling them into wanting one themselves.. sales++

4 Likes

Nice Dashboard. How did you get the sizes of the tiles to be different? The "..." settings only allow you to make a tile bigger/smaller in increments of the original size.
Thanks, Alan

My latest iPad Dashboard using @spelcheck's Smartly skin.

3 Likes

I agree.

I don't know that they would need to patch this. The only way JavaScript would get injected is through an authorized user adding a device driver so it seems kind of safe unless it gets abused and causes slowdowns or something along those lines.

2 Likes

Need and do are two different things usually, we can't know why they would disable this. I guess all we can do is hope. For security reasons there really is no added benefit, besides, there's many additional vectors to inject JS for an authorized user on HE. For slowdowns that is up to the user to decide, in my opinion. The first advice usually is to disable all custom apps/drivers anyway.

EDIT: I'm sure there's more devs who knows other vectors for this, but no need to talk about all of them at once, leave some for the future :stuck_out_tongue:

I can't be sure how @cj_rezz did it on his dashboard, but all I did was to set the starting width setting for tiles to be relatively small, say 20-30, set within the dashboard config. When setting the width of an individual tile, I often set them to be 15-20 increments wide, sometimes more. Basically the smaller starting width of 20-30 compared to say 80, gives you more fine-grained control.

Yup, exactly. Here's my settings for that particular dashboard

So a normal tile will end up being 2 units tall and 2 units wide so that then you can have smaller tiles.

2 Likes

image
Little Bobby Tables

9 Likes