Running Node-RED on Ubuntu 24.04
I am trying to load Justgage into UIBUILDER and I am having problems. It appears through the Browser Console (Vivaldi and Firefox) that Raphael and Justgage are not being run because of some security problem.
Space is left for the gauge, but nothing appears in it after injecting the payload and topic. I have followed @Paul-Reed instructions from his detailed post and also confirmed that the instructions are still valid.
Any ideas gladly accepted!!
Using CDN
VM1099:18 callback globalThis.ns_setupCallback is not a function (undefined).
(anonymous) @ VM1099:18
(anonymous) @ VM1099:26
panel/:1 [Report Only] Refused to load the script 'https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
panel/:1 [Report Only] Refused to load the script 'https://cdnjs.cloudflare.com/ajax/libs/justgage/1.7.0/justgage.min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
panel/:1 [Report Only] Refused to load the script 'http://localhost:1880/uibuilder/uibuilder.iife.min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
Using local
VM889:18 callback globalThis.ns_setupCallback is not a function (undefined).
(anonymous) @ VM889:18
(anonymous) @ VM889:26
panel/:1 [Report Only] Refused to load the script 'http://localhost:1880/uibuilder/vendor/raphael/raphael.min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
panel/:1 [Report Only] Refused to load the script 'http://localhost:1880/uibuilder/vendor/justgage/dist/justgage.min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
panel/:1 [Report Only] Refused to load the script 'http://localhost:1880/uibuilder/uibuilder.iife.min.js' because it violates the following Content Security Policy directive: "script-src-elem 'none'".
panel/:25 GET http://localhost:1880/uibuilder/vendor/raphael/raphael.min.js net::ERR_ABORTED 404 (Not Found)
panel/:35 Refused to execute script from 'http://localhost:1880/uibuilder/vendor/raphael/raphael.min.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
justgage.js:20 Uncaught ReferenceError: Raphael is not defined
at justgage.js:20:29
at justgage.js:8:1
(anonymous) @ justgage.js:20
(anonymous) @ justgage.js:8
[{"id":"b48f1cec0c424cac","type":"catch","z":"584f914f499733a6","name":"","scope":null,"uncaught":false,"x":140,"y":60,"wires":[["0396434b195a9d23"]]},{"id":"0396434b195a9d23","type":"debug","z":"584f914f499733a6","name":"Catch Err","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":320,"y":60,"wires":[]},{"id":"1990d038d58b543b","type":"group","z":"584f914f499733a6","name":"Static Dashboard","style":{"fill":"#bfdbef","fill-opacity":"0.31","label":true,"color":"#000000"},"nodes":["9a66ac6446246585","7d9436c9535bb04e","bc90cd16ec35bc86","227db5eabf708658","9c3eb8d9afa912ea","c0acb041b0ace082","ab9ab2ee1e1e982b","53d8e4c892caae0f","131dc3f34ef3f4be","b4f102b6d584e292","339b98e312dc1cc3","17da9997449ebc65","d000b4c883b4723d","f7d7a879f4c4db1e","7f620b906e81dd64","18e3e837e73c7048","657d42630f1da5b0"],"x":74,"y":139,"w":1012,"h":448},{"id":"9a66ac6446246585","type":"inject","z":"584f914f499733a6","g":"1990d038d58b543b","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":215,"y":220,"wires":[["53d8e4c892caae0f"]],"l":false},{"id":"7d9436c9535bb04e","type":"uibuilder","z":"584f914f499733a6","g":"1990d038d58b543b","name":"","topic":"","url":"panel","okToGo":true,"fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":true,"sourceFolder":"src","deployedVersion":"7.4.1","showMsgUib":false,"title":"","descr":"","editurl":"vscode://file/home/colin/.node-red/projects/2801101/uibuilder/panel/?windowId=_blank","x":580,"y":280,"wires":[["bc90cd16ec35bc86"],["227db5eabf708658","657d42630f1da5b0"]]},{"id":"bc90cd16ec35bc86","type":"debug","z":"584f914f499733a6","g":"1990d038d58b543b","name":"debug 452","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":775,"y":260,"wires":[],"l":false},{"id":"227db5eabf708658","type":"debug","z":"584f914f499733a6","g":"1990d038d58b543b","name":"debug 453","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":935,"y":280,"wires":[],"l":false},{"id":"9c3eb8d9afa912ea","type":"comment","z":"584f914f499733a6","g":"1990d038d58b543b","name":"Design","info":"This layout is designed to roughly replicate\nthe Node-RED Dashboard grid layout.\n\nIt keeps the outer layout from the content/blog\nstyle (header, footer, left-sidebar, main).\n\nBut the sidebar now has the navigation menu\ninstead of the header.\n\nThe main content area is now a sub-grid. It has\nthe `id` of `more` which means that you can\neasily add new content using uibuilder's \nno-code nodes.\n\nEach `<article>` or `<div>` tag in the main \ncontent sub-grid can be considered the \nequivalent of a \"widget\" in Node-RED Dashboard \nterms. It can contain whatever you want it to.\nIt has a slightly different background colour\nand a rounded border.\n\nIn the example all of the layout can be\ncontrolled from the CSS variables in `:root`.\n\nThe sub-grid has 12 columns by default, you\ncan change that to whatever is useful to you.\n\nThe articles have a default width of 3. You can\neasily override a single article by adding:\n`--article-width: 6` or however many columns\nyou want it to take up.\n\nBy default, specific grid rows are undefined\n(set to `auto`) so articles take up whatever\nheight they need. If you want to define the\nrows, you can easily do so by changing\n`--main-rows` to `repeat(12, 1fr)` or some\nother number. You have lots of control over the\ncolumn/row layout but it can get a bit complex\nso you are advised to keep it simple, at least\nto start with.\n\n-----------------\n\n## NOTES\n\nIt is very likely that much of the\ndefined CSS in this example will be incorporated\ninto UIBUILDER's `uib-brand.css` in the \nfuture.\n\nThe Markdown-IT library has been included in\n`index.html`, loaded from a public Internet\nCDN. Install & use the library locally using \nUIBUILDER's library manager if you prefer.\nOr remove completely if you don't need to use\nMarkdown dynamic content.","x":940,"y":180,"wires":[]},{"id":"c0acb041b0ace082","type":"group","z":"584f914f499733a6","g":"1990d038d58b543b","name":"Setup - run this first to set up the page and style - only needs to run once","style":{"fill":"#ffffff","fill-opacity":"0.31","label":true,"color":"#000000"},"nodes":["428ce314901f3767","de7eb158dfc01708","5d994d5ed445588e","d1613f2217e9ecb1","5dcdb42f869e188f","65ed85522e1f51ac","3234eca4ec17a21a","a3d2eb3e24fefdbf"],"x":134,"y":399,"w":652,"h":162},{"id":"428ce314901f3767","type":"template","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.html","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!doctype html>\n<html lang=\"en\">\n\n<head>\n\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link rel=\"icon\" href=\"../uibuilder/images/node-blue.ico\">\n\n <title>Theodore</title>\n <meta name=\"description\" content=\"Theodore - Dashboard Layout\">\n\n <!-- Your own CSS (defaults to loading uibuilders css)-->\n <link type=\"text/css\" rel=\"stylesheet\" href=\"./index.css\" media=\"all\">\n\n <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->\n <!-- <script defer src=\"https://cdn.jsdelivr.net/npm/markdown-it/dist/markdown-it.min.js\"></script> -->\n\n <!-- Raphael must be included before justgage -->\n\n <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js\"></script>\n <script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/justgage/1.7.0/justgage.min.js\"></script>\n\n<!--\n <script defer src=\"../uibuilder/vendor/raphael/raphael.min.js\"></script>\n <script defer src=\"../uibuilder/vendor/justgage/dist/justgage.min.js\"></script>\n-->\n <script defer src=\"../uibuilder/uibuilder.iife.min.js\"></script>\n <!-- <script defer src=\"./index.js\">/* <= OPTIONAL: Put your custom code in that */</script> -->\n <!-- #endregion -->\n\n</head>\n\n<body>\n <div class=\"container\">\n <!--\n <header class=\"header\">\n <h1 class=\"with-subtitle\">Theodore Dashboard</h1>\n </header>\n -->\n\n<div id=\"gauge-temp\" class=\"gauge\"></div>\n\n <main id=\"more\">\n <!-- '#more' is used as a parent for dynamic HTML content in examples -->\n <article>\n <h2>Temperatures °C</h2>\n </article>\n\n <article>\n <h2>Fridge °C</h2>\n </article>\n </main>\n </div>\n</body>\n\n</html>","output":"str","x":530,"y":440,"wires":[["d1613f2217e9ecb1"]]},{"id":"de7eb158dfc01708","type":"inject","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"2","topic":"setup all FE files","x":195,"y":440,"wires":[["5d994d5ed445588e","5dcdb42f869e188f","3234eca4ec17a21a"]],"l":false},{"id":"5d994d5ed445588e","type":"change","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.html","rules":[{"t":"set","p":"fname","pt":"msg","to":"index.html","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":440,"wires":[["428ce314901f3767"]]},{"id":"d1613f2217e9ecb1","type":"uib-save","z":"584f914f499733a6","g":"c0acb041b0ace082","url":"panel","uibId":"7d9436c9535bb04e","folder":"src","fname":"","createFolder":false,"reload":true,"usePageName":false,"encoding":"utf8","mode":438,"name":"","topic":"","x":710,"y":440,"wires":[]},{"id":"5dcdb42f869e188f","type":"change","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.css","rules":[{"t":"set","p":"fname","pt":"msg","to":"index.css","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":480,"wires":[["65ed85522e1f51ac"]]},{"id":"65ed85522e1f51ac","type":"template","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.css","field":"payload","fieldType":"msg","format":"css","syntax":"plain","template":"/* Load defaults from `<userDir>/node_modules/node-red-contrib-uibuilder/front-end/uib-brand.min.css`\n * This version auto-adjusts for light/dark browser settings.\n */\n@import url(\"../uibuilder/uib-brand.min.css\");\n\n.gauge {\n width: 325px;\n height: 200px;\n display: inline-block;\n}","output":"str","x":520,"y":480,"wires":[["d1613f2217e9ecb1"]]},{"id":"3234eca4ec17a21a","type":"change","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.js","rules":[{"t":"set","p":"fname","pt":"msg","to":"index.js","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":520,"wires":[["a3d2eb3e24fefdbf"]]},{"id":"a3d2eb3e24fefdbf","type":"template","z":"584f914f499733a6","g":"c0acb041b0ace082","name":"index.js","field":"payload","fieldType":"msg","format":"css","syntax":"plain","template":"\ndocument.addEventListener('DOMContentLoaded', ()=> {\n\n // Create just one gauge up front\n const tempGauge=new JustGage( {\n\n id: 'gauge-temp',\n value: 0,\n min: 0,\n max: 100,\n symbol: '°C',\n pointer: true,\n pointerOptions: {\n toplength: -15,\n bottomlength: 10,\n bottomwidth: 12,\n color: '#8e8e93',\n stroke: '#ffffff',\n stroke_width: 3,\n stroke_linecap: 'round'\n }\n\n ,\n title: 'Temperature (°C)',\n label: 'Temperature',\n labelMinFontSize: 14,\n valueFontColor: '#a2a2a2'\n }\n\n );\n\n // Handle incoming data via uibuilder\n uibuilder.onChange('msg', (msg)=> {\n if (msg.topic==='sensorTemp') {\n tempGauge.refresh(Number(msg.payload));\n }\n\n else {\n console.warn('Unhandled topic', msg.topic, msg.payload);\n }\n }\n\n );\n }\n\n);","output":"str","x":520,"y":520,"wires":[["d1613f2217e9ecb1"]]},{"id":"ab9ab2ee1e1e982b","type":"link in","z":"584f914f499733a6","g":"1990d038d58b543b","name":"uib input","links":["101a4ac6efce50b6","0a7182f9c1d85b85","18e3e837e73c7048"],"x":255,"y":320,"wires":[["53d8e4c892caae0f"]]},{"id":"53d8e4c892caae0f","type":"junction","z":"584f914f499733a6","g":"1990d038d58b543b","x":320,"y":280,"wires":[["131dc3f34ef3f4be"]]},{"id":"131dc3f34ef3f4be","type":"uib-cache","z":"584f914f499733a6","g":"1990d038d58b543b","cacheall":false,"cacheKey":"topic","newcache":false,"num":"15","storeName":"memory","name":"Cache","storeContext":"context","varName":"uib_cache","x":390,"y":280,"wires":[["7d9436c9535bb04e"]]},{"id":"b4f102b6d584e292","type":"comment","z":"584f914f499733a6","g":"1990d038d58b543b","name":"msg.topic and msg.payload pass through to UIBUILDER","info":"","x":320,"y":360,"wires":[]},{"id":"339b98e312dc1cc3","type":"debug","z":"584f914f499733a6","d":true,"g":"1990d038d58b543b","name":"uib client connect/disconnect Output","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":1025,"y":340,"wires":[],"l":false},{"id":"17da9997449ebc65","type":"inject","z":"584f914f499733a6","g":"1990d038d58b543b","name":"Clear Cache","props":[{"p":"uibuilderCtrl","v":"clear cache","vt":"str"},{"p":"cacheControl","v":"CLEAR","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":190,"y":280,"wires":[["53d8e4c892caae0f"]]},{"id":"d000b4c883b4723d","type":"debug","z":"584f914f499733a6","g":"1990d038d58b543b","name":"debug 17","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":630,"y":180,"wires":[]},{"id":"f7d7a879f4c4db1e","type":"inject","z":"584f914f499733a6","g":"1990d038d58b543b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"sensorTemp","payload":"37","payloadType":"num","x":400,"y":180,"wires":[["7d9436c9535bb04e","d000b4c883b4723d"]]},{"id":"7f620b906e81dd64","type":"debug","z":"584f914f499733a6","g":"1990d038d58b543b","name":"route changes","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"","statusType":"counter","x":910,"y":380,"wires":[]},{"id":"18e3e837e73c7048","type":"link out","z":"584f914f499733a6","g":"1990d038d58b543b","name":"To input","mode":"link","links":["ab9ab2ee1e1e982b"],"x":780,"y":340,"wires":[]},{"id":"657d42630f1da5b0","type":"switch","z":"584f914f499733a6","g":"1990d038d58b543b","name":"Route different control msgs","property":"uibuilderCtrl","propertyType":"msg","rules":[{"t":"regex","v":"client (dis)?connect","vt":"str","case":false},{"t":"eq","v":"route change","vt":"str"},{"t":"eq","v":"visibility","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":4,"x":720,"y":360,"wires":[["18e3e837e73c7048","339b98e312dc1cc3"],["7f620b906e81dd64"],[],[]],"outputLabels":["Network (socket) client connect/disconnect","uibrouter route changes","page visibility","Anything else"],"l":false}]