|
[{"id":"38dea932ad8bf5b0","type":"group","z":"30fdd9a9702231b0","name":"UIBUILDER Node-RED debug page - with full output and copy (Read my description for details)","style":{"label":true,"fill":"#ffefbf","fill-opacity":"0.34","color":"#000000"},"nodes":["b2b9cd88db08056f","30f917ba22b7601a","465991cb13575bdc","2dcf170369271854","85e33c87a851fd7b","cd117dec98696547"],"env":[{"name":"debug_name","value":"Debug","type":"str"},{"name":"debug_property","value":"msg","type":"str"}],"x":514,"y":99,"w":578,"h":142,"info":"A simple debug output page using uibuilder.\r\n\r\nNote that this group has 2 defined environment\r\nvariables. \r\n\r\n`debug_name` and `debug_property`. These\r\ncan also be overridden using msg properties\r\nof the same name.\r\n\r\nSimple send any message to the `link-in` node\r\nin this group and view a formatted version of\r\nthe message on the debug web page.\r\n\r\nThe web page has pause/resume buttons and \r\nclear all entries buttons.\r\n\r\nEach entry on the page can be copied to the \r\nclipboard using the ❒ button. Or the entry \r\ncan be deleted using the ❌ button.\r\n\r\nThe formatted output for each entry appears in \r\na scrollable box. You can grab the bottom-right\r\ncorner and expand the box manually.\r\n\r\nUnlike Node-RED's debug panel, ALL of the msg\r\nobject is included in the output - up to the \r\nmax limit of the Socket.IO client. If you need\r\nto extend the limit, you can do so in the \r\nuibuilder settings in the `settings.js` file.\r\n\r\nHowever, as with any web app, be wary of How\r\nmuch data you keep in the browser window. If \r\nyou let it get too big, your browser will slow\r\ndown and eventually break."},{"id":"b2b9cd88db08056f","type":"function","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"","func":"// What msg property to debug (or the whole msg)\nconst debug_property = msg.debug_property || env.get('debug_property') || 'msg'\n// Each property part as an array. e.g `msg._ui` becomes ['msg','_ui']\nlet debug_property_array = []\n// Record any errors\nlet err = []\n\nlet dt = (new Date()).toLocaleString()\n\ntry {\n debug_property_array = RED.util.normalisePropertyExpression(debug_property)\n // node.send([null, {debug_property, debug_property_array}])\n} catch (e) {\n node.warn(e.message)\n err.push(e.message)\n}\n\nlet msg1 = {data: null}\ntry {\n // Try to get a specific msg property if requested\n let ans = RED.util.getMessageProperty(msg, debug_property)\n if (ans === undefined) {\n err.push(`Message property not found. '${debug_property}'`)\n } else {\n msg1.data = ans\n }\n} catch(e) {\n // Else get the whole msg\n msg1.data = RED.util.cloneMessage(msg)\n // but remove the debug meta data if it was passed in on the orig msg\n delete msg1.data.debug_name\n delete msg1.data.debug_property\n delete msg1.data.pass_debug_property\n delete msg1.data.debug_array\n err.push(e.message)\n}\n\nmsg1.topic = msg.topic\nmsg1.errors = err\nmsg1.debug_property = debug_property\nmsg1.debug_property_array = debug_property_array\n// Optional msg name - will default to original msg id\nmsg1.debug_name = msg.debug_name || env.get(\"debug_name\") || msg._msgid || \"name error\"\nmsg1.debug_dt = dt\n\nreturn [msg1,msg]","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":140,"wires":[["30f917ba22b7601a"],[]],"inputLabels":["msg to debug"],"outputLabels":["debug msg","Original msg"]},{"id":"30f917ba22b7601a","type":"uibuilder","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"","topic":"","url":"debug","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":false,"sourceFolder":"src","deployedVersion":"6.5.0","showMsgUib":false,"x":960,"y":140,"wires":[[],[]]},{"id":"465991cb13575bdc","type":"link in","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"link in 13","links":["0919ecfaa892d896","e81d0d1c57d90da7"],"x":555,"y":140,"wires":[["b2b9cd88db08056f"]]},{"id":"2dcf170369271854","type":"comment","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"index.html","info":"<!doctype html>\n<html lang=\"en\"><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>Debug - Node-RED uibuilder</title>\n <meta name=\"description\" content=\"Node-RED uibuilder - Debug\">\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=\"../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><body class=\"uib\">\n <h1 class=\"with-subtitle\">uibuilder - Debug</h1>\n <div role=\"doc-subtitle\">Using the IIFE library.</div>\n\n <div id=\"header\">\n <button id=\"pauser1\" value=\"pause\" onclick=\"doPause(event)\">Pause</button>\n <button onclick=\"doClear(event)\">Clear All</button>\n </div>\n\n <div id=\"more\"><!-- '#more' is used as a parent for dynamic HTML content in examples --></div>\n\n <div id=\"footer\">\n <button id=\"pauser2\" value=\"pause\" onclick=\"doPause(event)\">Pause</button>\n <button onclick=\"doClear(event)\">Clear All</button>\n </div>\n\n</body></html>\n","x":600,"y":200,"wires":[]},{"id":"85e33c87a851fd7b","type":"comment","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"index.js","info":"// uibuilder.logLevel = 2 // info\n\nconst elPaused1 = document.getElementById(\"pauser1\") || {innerText:''}\nconst elPaused2 = document.getElementById(\"pauser2\") || {innerText:''}\nlet paused = false\nlet msgCount = 0\n\n// Stop/resume inbound msgs\nfunction doPause(event) {\n if (paused === true) {\n elPaused1.innerText = \"Pause\"\n elPaused2.innerText = \"Pause\"\n paused = false\n uibuilder.log('info', 'uibuilder.debug', 'Visual debug messages flowing')\n } else {\n elPaused1.innerText = \"Resume\"\n elPaused2.innerText = \"Resume\"\n paused = true\n uibuilder.log('info', 'uibuilder.debug', 'Visual debug messages paused')\n }\n}\n\n// Remove the selected debug entry\nfunction cpy(event) {\n const elToCopy = event.target.parentElement.parentElement.querySelector('pre')\n window.prompt(\"Copy to clipboard: Ctrl+C, Enter\", elToCopy.innerText)\n}\n\nfunction del(event) {\n event.target.parentElement.parentElement.remove()\n}\n\n// Clears all debug entries\nfunction doClear(event) {\n document.querySelector('#more').textContent = ''\n}\n\nuibuilder.onChange('msg', (msg) => {\n console.log('DEBUG msg', msg)\n\n if (paused === true || msg._ui) return\n\n ++msgCount\n\n // use uibuilder's low-code capability to build the output structure for the new debug entry\n const toAdd = [{\n method: 'add',\n components: [\n {\n type: 'article',\n parent: '#more',\n position: 'first',\n id: `dbg_${msgCount}`,\n attributes: {\n class: 'dbg',\n },\n components: [\n {\n type: 'div',\n slot: `#${msgCount} | ${msg.debug_name} | ${msg.debug_dt} | <i title=\"msg property\">${msg.debug_property}</i> | <button title=\"copy\" onclick=\"cpy(event)\"> ❒ </button><button title=\"delete\" onclick=\"del(event)\"> ❌ </button> `,\n },\n ],\n }\n ],\n\n }]\n\n // If there are errors, output a list of them\n if (msg.errors.length > 0) {\n toAdd[0].components[0].components.push({\n type: 'div',\n slot: `<p class=\"error\">${msg.errors.join('</p><p class=\"error\">')}</p>`\n })\n } else {\n // otherwise output the msg.data highlighted\n toAdd[0].components[0].components.push({\n type: 'pre',\n attributes: {\n class: 'syntax-highlight',\n },\n // Formates the data using a simple JSON colour formatter\n slot: uibuilder.syntaxHighlight(msg.data)\n })\n }\n\n uibuilder.ui(toAdd)\n})\n","x":730,"y":200,"wires":[]},{"id":"cd117dec98696547","type":"comment","z":"30fdd9a9702231b0","g":"38dea932ad8bf5b0","name":"index.css","info":"/* Load defaults from `<userDir>/node_modules/node-red-contrib-uibuilder/front-end/uib-brand.css`\n * This version auto-adjusts for light/dark browser settings but might not be as complete.\n */\n@import url(\"../uibuilder/uib-brand.css\");\n\n#header {\n margin-bottom: 1em;\n padding-bottom: .5em;\n border-bottom: 1px solid silver;\n}\n#footer {\n margin-top: 1em;\n padding-top: .5em;\n border-top: 1px solid silver;\n}\n.dbg {\n border: 1px solid silver;\n padding: 1rem;\n}\n","x":860,"y":200,"wires":[]}] |