Dashboard 2.0 is now Generally Available

That heavily bended level got some improvements so you can:
change size of it just by configuring one number
adjusting led count does not break whole thing
there was more but I didn't kept the diary

So it is easier to use, (until we get the proper thing)

[{"id":"9f3c815ec5f4ba93","type":"ui-template","z":"4eb808f5e19fb7e2","group":"5d78082af21e201d","page":"","ui":"","name":"Round Led Gauge","order":7,"width":"2","height":"2","head":"","format":"<template>\n    <div class=\"round-led-level\" :style=\"`--dot-count:${count}; --size:${size}; --ledsize:${ledSize};`\" >\n        <header>\n            <div class=\"round-led-level-text\">\n                <span class=\"round-led-level-label\">{{label}}</span>\n            </div>\n        </header>\n        <div>\n            <div class=\"round-led-level-stripe\">\n                <div v-for=\"(color, index) in colors\" :key=\"index\" class=\"round-led-level-led\" :ref=\"'dot-' + index +'-'+this.id\">\n                </div>\n            </div>\n            <div class=\"round-led-level-centered-text\">\n                <span class=\"round-led-level-value\">{{formattedValue}}</span>\n                <span class=\"round-led-level-unit\">{{unit}}</span>\n            </div>\n            <div class=\"round-led-level-limits\">\n                <span>{{min}}</span>\n                <span>{{max}}</span>\n            </div>\n        </div>     \n    <div>\n</template>\n\n<script>\nexport default {\n    data(){\n        return {\n            //define me here\n            label:\"MEASURE\", // the label\n            min:0, //smallest expected value\n            max:100, //higest expected value\n            unit:\"cm³\",// unit of the measurement\n            size:140, // ovaerall size. (think in pixels) under 100 will be too small.                                   \n            animate:true,// animating leds is not most performant thing in the world.                          \n            dark:0.4, // how dim is led when not glowing  \n            //define colors as you wish but the thing works clockwise.\n            //led size depends on how many colors is defined.         \n            colors:[                   \n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-primary))\",\n                    \"rgb(var(--v-theme-warning))\",\n                    \"rgb(var(--v-theme-warning))\",\n                    \"rgb(var(--v-theme-warning))\",\n                    \"rgb(var(--v-theme-error))\",\n                    \"rgb(var(--v-theme-error))\",\n                   ],            \n            //no need to change those\n            value:0,\n            previousValue:0,\n            inited:false\n        }\n    },\n\n   \n    methods: {        \n        getElement: function(name,base){\n            if(base){\n                return this.$refs[name]\n            }\n            return this.$refs[name][0]\n        },\n\n        full: function(){\n            return Math.floor(this.colors.length*this.percentage/100)\n        },\n        half: function (){\n            let p = this.colors.length*this.percentage/100;\n            p -= this.full()\n            p *= .5\n            p += this.dark;\n            return p;\n        },\n\n        lit: function(){\n            if(this.inited == false){\n                return\n            }\n            const down = this.previousValue > this.value\n\n            let time = .01\n            this.colors.forEach((e,i) => {\n                let dot = this.getElement(\"dot-\"+i+\"-\"+this.id);\n                if(!dot){\n                    console.log(\"no dots found\")\n                    return\n                }                \n                if(i<this.full()){\n                    dot.style.filter= \"brightness(1.1)\";\n                }\n                else if(i==this.full()){                   \n                    dot.style.filter = \"brightness(\"+this.half()+\")\";\n                }\n                else{\n                    dot.style.filter= \"brightness(\"+this.dark+\")\";\n                }\n                if(down){\n                    time = (this.colors.length - i) * .12                    \n                }\n                dot.style.transition = this.animate ? \"filter \"+time+\"s\" : \"unset\";\n            })\n            this.previousValue = this.value\n        }\n    },\n    watch: {\n        msg: function(){    \n            if(this.msg.payload != undefined){           \n                this.value = this.msg.payload                \n                this.lit()\n            }\n        }\n    },\n    computed: {\n        formattedValue: function () {\n            return this.value.toFixed(2)\n        },\n        percentage: function(){\n            return Math.floor(((this.value - this.min) / (this.max - this.min)) * 100);\n        },\n        count: function() {\n            return this.colors.length;\n        },        \n        ledSize:function(){\n            const s = 4.71239 * ((this.size - (this.size*0.3))/2)            \n            return s / this.colors.length\n        }\n    },\n    mounted(){\n        let angle;\n        const step = 270 / this.colors.length; //this.ledSize/2;//270 / (this.colors.length + 2);\n        const radius = (this.size - (this.size*0.1))/2//this.size / 2;\n        const s = this.ledSize / -2;        \n        this.colors.forEach((c,i) => {\n                let dot = this.getElement(\"dot-\"+i+\"-\"+this.id);\n                if(!dot){\n                    console.log(\"no dots found\")\n                    return\n                }\n                dot.style.backgroundColor = c               \n                dot.style.transition = \"filter 0.1s\";\n                dot.style.setProperty('--dot',i);\n                angle = ((i+1)*step) * Math.PI / 180;\n                dot.style.left = s + radius * Math.cos(angle) + 'px';\n                dot.style.top = s + radius * Math.sin(angle) + 'px';\n                dot.style.transform = 'translate('+s+'px, '+s+'px)'; \n                dot.style.rotate = (angle - 0.08)+\"rad\"               \n            }\n        )\n       \n        this.inited = true;\n    },\n        \n}\n</script>\n","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":630,"y":360,"wires":[[]]},{"id":"2545d92a227a8572","type":"ui-template","z":"4eb808f5e19fb7e2","group":"","page":"","ui":"da26eafa8eb48ab3","name":"Round Led Gauge for Dasboard 2.0 CSS","order":0,"width":0,"height":0,"head":"","format":".round-led-level{\n    display: grid;\n    grid-template-rows: 1em 1fr;\n    height: calc(var(--size) * 1px);\n    aspect-ratio: 1/1;\n    position: relative;\n    margin: auto;\n}\n.round-led-level>div{\n    position: relative;;\n}\n.round-led-level-stripe{\n    display: block;\n    position: absolute;\n    left: 50%;\n    top: 56%;\n    rotate: 135deg;  \n}    \n.round-led-level-led {\n    background: #ffffff;\n    position: absolute;\n    width: calc(var(--ledsize) * 1px);\n    aspect-ratio: 1/1;\n    border-radius: 4px;\n    box-shadow: inset 0px 0px calc(var(--ledsize) / 3 * 1px) 0px #00000099, 0px 0px calc(var(--ledsize) / 7 * 1px) 0px #00000099;\n    filter: brightness(0.4);\n    transform-origin: center center;\n    \n\n}\n.round-led-level-text{    \n    font-size: 1rem;\n    line-height: 1rem;\n    text-align: center;\n    user-select: none;\n}\n.round-led-level-centered-text{\n    position: absolute;\n    inset: 0;\n    font-size: 1rem;\n    line-height: 1;\n    display: grid;\n    text-align: center;\n    grid-template-rows: 1fr 1fr;\n    gap: .25em;\n    user-select: none;\n    padding-block: 42%;\n    align-items: center;\n}\n.round-led-level-value{       \n    font-weight:bold;\n    font-size: calc(var(--size) * .15 * 1px);\n}\n.round-led-level-unit{\n    font-size:calc(var(--size) * .1 * 1px);\n    font-weight:normal;\n    padding-inline-start: 0.15em;\n}\n.round-led-level-limits{\n    position: absolute;\n    inset:0; \n    display: flex;\n    justify-content: space-between;\n    font-size: calc(var(--size) * .06 * 1px);\n    line-height: calc(var(--size) * .06 * 1px);\n    align-content: flex-end;\n    flex-wrap: wrap;\n    padding-inline:1em;\n    user-select: none;\n}","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"site:style","className":"","x":700,"y":320,"wires":[[]]},{"id":"5d78082af21e201d","type":"ui-group","name":"Some stuff","page":"71097e9858ab99f9","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"da26eafa8eb48ab3","type":"ui-base","name":"Board","path":"/dashboard"},{"id":"71097e9858ab99f9","type":"ui-page","name":"Test page","ui":"da26eafa8eb48ab3","path":"/second","icon":"home","layout":"grid","theme":"a965ccfef139317a","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"a965ccfef139317a","type":"ui-theme","name":"Default","colors":{"surface":"#575757","primary":"#0fb8ad","bgPage":"#474747","groupBg":"#525252","groupOutline":"#7c837e"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

And with that I'm going to shut up in terms of indicator widget prototypes and let the thread to be Dashboard 2.0 again :slight_smile:

Don't even know what do now ... :thinking:

8 Likes