From ab31f34862d15525466f6715406d5759bcdb2e5b Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 20 Jun 2016 21:35:20 +0100 Subject: [PATCH 01/92] Initial debug pop-out window --- Gruntfile.js | 5 ++ nodes/core/core/58-debug.html | 74 +++++++---------------------- nodes/core/core/58-debug.js | 10 ++++ nodes/core/core/lib/debug/debug.js | 6 +++ nodes/core/core/lib/debug/style.css | 51 ++++++++++++++++++++ nodes/core/core/lib/debug/view.html | 8 ++++ 6 files changed, 98 insertions(+), 56 deletions(-) create mode 100644 nodes/core/core/lib/debug/debug.js create mode 100644 nodes/core/core/lib/debug/style.css create mode 100644 nodes/core/core/lib/debug/view.html diff --git a/Gruntfile.js b/Gruntfile.js index 2c5da4ab1..4c25cd822 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -150,6 +150,11 @@ module.exports = function(grunt) { "public/vendor/vendor.css": [ // TODO: resolve relative resource paths in // bootstrap/FA/jquery + ], + "public/vendor/vendor-jquery.js": [ + "editor/vendor/jquery/js/jquery-1.11.3.min.js", + "editor/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js", + "editor/vendor/jquery/js/jquery.ui.touch-punch.min.js", ] } } diff --git a/nodes/core/core/58-debug.html b/nodes/core/core/58-debug.html index 845c0ed72..05d6c25d2 100644 --- a/nodes/core/core/58-debug.html +++ b/nodes/core/core/58-debug.html @@ -46,7 +46,8 @@ - + diff --git a/nodes/core/core/58-debug.js b/nodes/core/core/58-debug.js index bf9b6610f..d080c38ee 100644 --- a/nodes/core/core/58-debug.js +++ b/nodes/core/core/58-debug.js @@ -18,6 +18,7 @@ module.exports = function(RED) { "use strict"; var util = require("util"); var events = require("events"); + var path = require("path"); var debuglength = RED.settings.debugMaxLength||1000; var useColors = false; // util.inspect.styles.boolean = "red"; @@ -153,4 +154,13 @@ module.exports = function(RED) { res.sendStatus(404); } }); + + RED.httpAdmin.get("/debug/view/*",RED.auth.needsPermission("debug.read"),function(req,res) { + var options = { + root: __dirname + '/lib/debug/', + dotfiles: 'deny' + }; + console.log("SERVING UP",req.params[0]); + res.sendFile(req.params[0], options); + }); }; diff --git a/nodes/core/core/lib/debug/debug.js b/nodes/core/core/lib/debug/debug.js new file mode 100644 index 000000000..3b8f419f5 --- /dev/null +++ b/nodes/core/core/lib/debug/debug.js @@ -0,0 +1,6 @@ +$(function() { + window.addEventListener('message',function(evt) { + console.log(evt.data); + $('
').text(evt.data).appendTo(document.body); + },false) +}); diff --git a/nodes/core/core/lib/debug/style.css b/nodes/core/core/lib/debug/style.css new file mode 100644 index 000000000..acd8bac0f --- /dev/null +++ b/nodes/core/core/lib/debug/style.css @@ -0,0 +1,51 @@ +#debug-content { + position: absolute; + top: 43px; + bottom: 0px; + left:0px; + right: 0px; + overflow-y: scroll; +} +.debug-message { + cursor: pointer; + border-bottom: 1px solid #eee; + border-left: 8px solid #eee; + border-right: 8px solid #eee; + padding: 2px; +} +.debug-message-date { + background: #fff; + font-size: 9px; + color: #aaa; + padding: 1px 5px 1px 1px; +} +.debug-message-topic { + display: block; + background: #fff; + padding: 1px; + font-size: 10px; + color: #a66; +} +.debug-message-name { + background: #fff; + padding: 1px 5px; + font-size: 9px; + color: #aac; +} +.debug-message-payload { + display: block; + padding: 2px; + background: #fff; +} +.debug-message-level-log { + border-left-color: #eee; + border-right-color: #eee; +} +.debug-message-level-30 { + border-left-color: #ffdf9d; + border-right-color: #ffdf9d; +} +.debug-message-level-20 { + border-left-color: #f99; + border-right-color: #f99; +} diff --git a/nodes/core/core/lib/debug/view.html b/nodes/core/core/lib/debug/view.html new file mode 100644 index 000000000..a18c7d584 --- /dev/null +++ b/nodes/core/core/lib/debug/view.html @@ -0,0 +1,8 @@ + + + + + + + + From 0cd20768f406f410874980fffdd6a2306b3881f8 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Mon, 20 Jun 2016 23:08:37 +0100 Subject: [PATCH 02/92] Style the debug window to match the sidebar --- nodes/core/core/58-debug.html | 2 +- nodes/core/core/58-debug.js | 1 - nodes/core/core/lib/debug/debug.js | 73 ++++++++++++++++++++++++++++- nodes/core/core/lib/debug/style.css | 5 ++ nodes/core/core/lib/debug/view.html | 12 ++++- 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/nodes/core/core/58-debug.html b/nodes/core/core/58-debug.html index 05d6c25d2..69c59f52c 100644 --- a/nodes/core/core/58-debug.html +++ b/nodes/core/core/58-debug.html @@ -148,7 +148,7 @@ if (subWindow) { try { - subWindow.postMessage(JSON.stringify(o),"*") + subWindow.postMessage(o,"*") } catch(err) { console.log(err); } diff --git a/nodes/core/core/58-debug.js b/nodes/core/core/58-debug.js index d080c38ee..be780c7ba 100644 --- a/nodes/core/core/58-debug.js +++ b/nodes/core/core/58-debug.js @@ -160,7 +160,6 @@ module.exports = function(RED) { root: __dirname + '/lib/debug/', dotfiles: 'deny' }; - console.log("SERVING UP",req.params[0]); res.sendFile(req.params[0], options); }); }; diff --git a/nodes/core/core/lib/debug/debug.js b/nodes/core/core/lib/debug/debug.js index 3b8f419f5..4529ada7f 100644 --- a/nodes/core/core/lib/debug/debug.js +++ b/nodes/core/core/lib/debug/debug.js @@ -1,6 +1,77 @@ $(function() { + function getTimestamp() { + var d = new Date(); + return d.toLocaleString(); + } + function sanitize(m) { + return m.replace(/&/g,"&").replace(//g,">"); + } window.addEventListener('message',function(evt) { console.log(evt.data); - $('
').text(evt.data).appendTo(document.body); + var o = evt.data; + + var msg = document.createElement("div"); + + //var sourceNode = RED.nodes.node(o.id) || RED.nodes.node(o.z); + + // msg.onmouseover = function() { + // msg.style.borderRightColor = "#999"; + // var n = RED.nodes.node(o.id) || RED.nodes.node(o.z); + // if (n) { + // n.highlighted = true; + // n.dirty = true; + // } + // RED.view.redraw(); + // }; + // msg.onmouseout = function() { + // msg.style.borderRightColor = ""; + // var n = RED.nodes.node(o.id) || RED.nodes.node(o.z); + // if (n) { + // n.highlighted = false; + // n.dirty = true; + // } + // RED.view.redraw(); + // }; + // msg.onclick = function() { + // var node = RED.nodes.node(o.id) || RED.nodes.node(o.z); + // if (node) { + // RED.workspaces.show(node.z); + // } + // + // }; + //console.log(o); + var name = sanitize(((o.name?o.name:o.id)||"").toString()); + var topic = sanitize((o.topic||"").toString()); + var property = sanitize(o.property?o.property:''); + var payload = sanitize((o.msg||"").toString()); + var format = sanitize((o.format||"").toString()); + + msg.className = 'debug-message'+(o.level?(' debug-message-level-'+o.level):''); + msg.innerHTML = ''+ + getTimestamp()+''+ + (name?''+name:'')+ + ''; + // NOTE: relying on function error to have a "type" that all other msgs don't + if (o.hasOwnProperty("type") && (o.type === "function")) { + var errorLvlType = 'error'; + var errorLvl = 20; + if (o.hasOwnProperty("level") && o.level === 30) { + errorLvl = 30; + errorLvlType = 'warn'; + } + msg.className = 'debug-message debug-message-level-' + errorLvl; + msg.innerHTML += 'function : (' + errorLvlType + ')'; + } else { + msg.innerHTML += ''+ + (o.topic?topic+' : ':'')+ + (o.property?'msg.'+property:'msg')+" : "+format+ + + ''; + } + msg.innerHTML += ''+ payload+ ''; + $("#debug-content").append(msg); + + + },false) }); diff --git a/nodes/core/core/lib/debug/style.css b/nodes/core/core/lib/debug/style.css index acd8bac0f..47d62efad 100644 --- a/nodes/core/core/lib/debug/style.css +++ b/nodes/core/core/lib/debug/style.css @@ -1,3 +1,8 @@ +.debug-window { + padding:0; + margin:0; + background: #fff; +} #debug-content { position: absolute; top: 43px; diff --git a/nodes/core/core/lib/debug/view.html b/nodes/core/core/lib/debug/view.html index a18c7d584..e89ea96dc 100644 --- a/nodes/core/core/lib/debug/view.html +++ b/nodes/core/core/lib/debug/view.html @@ -1,8 +1,18 @@ + + - + + +
+ From e30da2168deab3f5f567a7cee991b8fe97cee0ad Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Tue, 21 Jun 2016 22:50:09 +0100 Subject: [PATCH 03/92] Make Debug object explorable --- nodes/core/core/lib/debug/debug.js | 53 ++++++++++++++++++++++++++--- nodes/core/core/lib/debug/style.css | 31 +++++++++++++++++ nodes/core/core/lib/debug/view.html | 1 + 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/nodes/core/core/lib/debug/debug.js b/nodes/core/core/lib/debug/debug.js index 4529ada7f..839ddddbc 100644 --- a/nodes/core/core/lib/debug/debug.js +++ b/nodes/core/core/lib/debug/debug.js @@ -68,10 +68,55 @@ $(function() { ''; } - msg.innerHTML += ''+ payload+ ''; + if (format !== 'Object') { + msg.innerHTML += ''+ payload+ ''; + } else { + var el = $('').appendTo(msg); + buildMessageElement(JSON.parse(payload)).appendTo(el); + } $("#debug-content").append(msg); + $("#debug-content").scrollTop($("#debug-content")[0].scrollHeight); + },false); - - - },false) + function buildMessageElement(obj) { + var i; + var e; + var entryObj; + var element = $(''); + if (Array.isArray(obj)) { + $('').html('Array['+obj.length+']').appendTo(element); + for (i=0;i
').appendTo(element); + if (typeof obj[i] === 'object') { + $(' ').click(function(e) { + $(this).parent().toggleClass('collapsed'); + }).appendTo(entryObj); + } + $('').text(i).appendTo(entryObj); + $(': ').appendTo(entryObj); + e = $('').appendTo(entryObj); + buildMessageElement(obj[i]).appendTo(e); + } + } else if (typeof obj === 'object') { + $('').html('Object').appendTo(element); + var keys = Object.keys(obj); + for (i=0;i
').appendTo(element); + if (typeof obj[keys[i]] === 'object') { + $(' ').click(function(e) { + $(this).parent().toggleClass('collapsed'); + }).appendTo(entryObj); + } + $('').text(keys[i]).appendTo(entryObj); + $(': ').appendTo(entryObj); + e = $('').appendTo(entryObj); + buildMessageElement(obj[keys[i]]).appendTo(e); + } + } else if (typeof obj === 'string') { + $('').text('"'+obj+'"').appendTo(element); + } else { + $('').text(""+obj).appendTo(element); + } + return element; + } }); diff --git a/nodes/core/core/lib/debug/style.css b/nodes/core/core/lib/debug/style.css index 47d62efad..9a550afc7 100644 --- a/nodes/core/core/lib/debug/style.css +++ b/nodes/core/core/lib/debug/style.css @@ -3,6 +3,9 @@ margin:0; background: #fff; } +.debug-window .debug-message-payload { + font-size: 12px; +} #debug-content { position: absolute; top: 43px; @@ -54,3 +57,31 @@ border-left-color: #f99; border-right-color: #f99; } +.debug-message-object-entry { + padding-left: 15px; + padding-bottom: 3px; +} + +.debug-message-object-key { + color: #a66; +} +.debug-message-object-value { + +} +.debug-message-object-handle { + color: #999; + font-size: 0.8em; + width: 1em; + margin-left: -1em; + text-align: center; + transition: transform 0.2s ease-in-out; + transform: rotate(90deg); +} + +.debug-message-object-entry.collapsed>.debug-message-object-handle { + transform: rotate(0deg); +} + +.debug-message-object-entry.collapsed .debug-message-object-entry { + display:none; +} diff --git a/nodes/core/core/lib/debug/view.html b/nodes/core/core/lib/debug/view.html index e89ea96dc..bfbffac9c 100644 --- a/nodes/core/core/lib/debug/view.html +++ b/nodes/core/core/lib/debug/view.html @@ -3,6 +3,7 @@ + Node-RED Debug Tools ').appendTo(element); - if (typeof obj[i] === 'object') { - $(' ').click(function(e) { + header = $('').appendTo(entryObj); + if (typeof obj[i] === 'object' && obj[i] !== null) { + $(' ').appendTo(header); + header.addClass("debug-message-expandable"); + header.click(function(e) { $(this).parent().toggleClass('collapsed'); - }).appendTo(entryObj); + }); } - $('').text(i).appendTo(entryObj); + $('').text(i).appendTo(header); $(': ').appendTo(entryObj); e = $('').appendTo(entryObj); - buildMessageElement(obj[i]).appendTo(e); + buildMessageElement(obj[i],false).appendTo(e); } + if (length < obj.length) { + $('
...
').appendTo(element); + } + } else if (obj === null) { + $('null').appendTo(element); } else if (typeof obj === 'object') { - $('').html('Object').appendTo(element); + + header = $('').html((topLevel?(JSON.stringify(obj,2).substring(0,200)):'Object')).appendTo(element); + if (topLevel) { + $(' ').prependTo(header); + header.addClass("debug-message-expandable"); + header.click(function(e) { + $(this).parent().toggleClass('collapsed'); + }); + } var keys = Object.keys(obj); for (i=0;i