Dashboard One Level Widget Replacement

I have been considering a move to Dashboard Two, but see there is no DashBoard Two equivalent of the Dashboard One Level Widget. Like this:

What are my alternatives to do this in Dashboard Two?

Alan

I do have a web component version:

Might work with D2.

1 Like

Closest should be the Linear gauge

4 Likes

hotNIpi Thanks. perfect. Alan

Just to add, this kind of thing is perfectly possible in a template node:

chrome_f3qrNmJ8HU

Demo flow (Use CTRL+I to import)

[{"id":"d10f4be8b83cb824","type":"ui-template","z":"7ecf422396bf31b4","group":"d92eb51f258edce2","page":"","ui":"","name":"","order":1,"width":0,"height":0,"head":"","format":"<template>\n    <div class=\"meter-container\">\n        <div class=\"meter-header\">\n            <span class=\"meter-label\">{{ msg.label || '' }}</span>\n            <span class=\"meter-value\">\n                <span class=\"value-num\">{{ msg.payload }}</span>\n                <span class=\"value-unit\">{{ msg.topic }}</span>\n            </span>\n        </div>\n        \n        <div class=\"meter-scale-labels\">\n            <span>{{ min }}</span>\n            <span>{{ max }}</span>\n        </div>\n\n        <div class=\"meter-bar\">\n            <div \n                v-for=\"i in segments\" \n                :key=\"i\" \n                class=\"segment\"\n                :class=\"getSegmentClass(i - 1)\"\n            ></div>\n        </div>\n    </div>\n</template>\n\n<script>\nexport default {\n    data() {\n        return {\n            segments: 60, // Increased density for a smoother look\n        }\n    },\n    computed: {\n        min() { return this.msg.min ?? 0 },\n        max() { return this.msg.max ?? 100 },\n        low() { return this.msg.low ?? 10 },\n        high() { return this.msg.high ?? 90 }\n    },\n    methods: {\n        getSegmentClass(index) {\n            // Calculate value based on a 0-indexed segment\n            const segmentValue = this.min + (index / (this.segments - 1)) * (this.max - this.min)\n            \n            // Is this bar filled?\n            const isActive = segmentValue <= this.msg.payload\n            \n            // Determine the color zone for this specific segment\n            const isLowZone = segmentValue <= this.low\n            const isHighZone = segmentValue >= this.high\n            \n            return {\n                'active': isActive,\n                'is-low': isLowZone,\n                'is-high': isHighZone,\n                'is-neutral': !isLowZone && !isHighZone\n            }\n        }\n    }\n}\n</script>\n\n<style scoped>\n.meter-container {\n    background: #000;\n    color: #fff;\n    padding: 20px;\n    border-radius: 4px;\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n}\n\n.meter-header {\n    display: flex;\n    justify-content: center;\n    align-items: baseline;\n    gap: 12px;\n    margin-bottom: 8px;\n}\n\n.meter-label { font-size: 1.4rem; font-weight: 300; }\n.meter-value { font-size: 2.8rem; font-weight: 700; }\n.value-unit { font-size: 1.6rem; font-weight: 400; margin-left: 4px; }\n\n.meter-scale-labels {\n    display: flex;\n    justify-content: space-between;\n    font-size: 1.1rem;\n    color: #ccc;\n    margin-bottom: 4px;\n}\n\n.meter-bar {\n    display: flex;\n    flex-direction: row;\n    gap: 2px;\n    height: 35px; /* Increased height to match image */\n    width: 100%;\n}\n\n.segment {\n    flex: 1;\n    background: #222; /* Dimmer background for inactive segments */\n    transition: background 0.1s ease;\n}\n\n/* Logic for Active Segments */\n.segment.active.is-low { background: #ff4444; }     /* Red */\n.segment.active.is-neutral { background: #44ff44; } /* Green */\n.segment.active.is-high { background: #ff4444; }    /* Red */\n\n/* Small Glow effect (Optional - remove if you want flat look) */\n.segment.active {\n    box-shadow: 0 0 2px rgba(255,255,255,0.1);\n}\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":2340,"y":700,"wires":[[]]},{"id":"79e5124bf9bed370","type":"inject","z":"7ecf422396bf31b4","name":"","props":[{"p":"label","v":"Bus 1:","vt":"str"},{"p":"payload"},{"p":"topic","vt":"str"},{"p":"min","v":"12","vt":"num"},{"p":"max","v":"15","vt":"num"},{"p":"low","v":"12.5","vt":"num"},{"p":"high","v":"14.75","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"volts","payload":"(\t    $minimum := 12.1;\t    $maximum := 14.95;\t    $round(($random() * ($maximum-$minimum)) + $minimum, 2)\t)","payloadType":"jsonata","x":2187,"y":700,"wires":[["d10f4be8b83cb824"]]},{"id":"d92eb51f258edce2","type":"ui-group","name":"Group 1","page":"58c1725ba4ca6bda","width":6,"height":1,"order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"58c1725ba4ca6bda","type":"ui-page","name":"Page 1","ui":"03482f22997a66ac","path":"/page1cdl","icon":"home","layout":"grid","theme":"0ac22d5584a0964a","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":2,"className":"","visible":"true","disabled":"false"},{"id":"03482f22997a66ac","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control","ui-chat"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":1,"showDisconnectNotification":true,"allowInstall":false},{"id":"0ac22d5584a0964a","type":"ui-theme","name":"Theme Name","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"density":"compact","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"22px"}},{"id":"6c3e3bac07c65e20","type":"global-config","env":[],"modules":{"@flowfuse/node-red-dashboard":"1.30.2"}}]
3 Likes