From 1d71fb3554c52902e40ac5dc3b042d8dac15123d Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones <conway@uk.ibm.com>
Date: Thu, 14 May 2020 15:38:48 +0100
Subject: [PATCH] Let debug node show status indpendent of main output

---
 .../@node-red/nodes/core/common/21-debug.html | 51 +++++++++-----
 .../@node-red/nodes/core/common/21-debug.js   | 66 ++++++++++++++-----
 .../nodes/locales/en-US/messages.json         |  1 +
 3 files changed, 85 insertions(+), 33 deletions(-)

diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.html b/packages/node_modules/@node-red/nodes/core/common/21-debug.html
index 6a87cbf21..20772c0de 100644
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.html
+++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.html
@@ -6,25 +6,30 @@
         <input id="node-input-complete" type="hidden">
         <input id="node-input-targetType" type="hidden">
     </div>
-
     <div class="form-row">
         <label for="node-input-tosidebar"><i class="fa fa-random"></i> <span data-i18n="debug.to"></span></label>
         <label for="node-input-tosidebar" style="width:70%">
-        <input type="checkbox" id="node-input-tosidebar" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toSidebar"></span>
+        <input type="checkbox" id="node-input-tosidebar" style="display:inline-block; width:22px; vertical-align:top;"><span data-i18n="debug.toSidebar"></span>
         </label>
     </div>
     <div class="form-row">
         <label for="node-input-console"> </label>
         <label for="node-input-console" style="width:70%">
-        <input type="checkbox" id="node-input-console" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toConsole"></span>
+        <input type="checkbox" id="node-input-console" style="display:inline-block; width:22px; vertical-align:top;"><span data-i18n="debug.toConsole"></span>
         </label>
     </div>
-    <div class="form-row" id="node-tostatus-line">
+    <div class="form-row">
     <label for="node-input-tostatus"> </label>
     <label for="node-input-tostatus" style="width:70%">
-        <input type="checkbox" id="node-input-tostatus" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="debug.toStatus"></span>
+        <input type="checkbox" id="node-input-tostatus" style="display:inline-block; width:22px; vertical-align:top;"><span data-i18n="debug.toStatus"></span>
     </label>
     </div>
+    <div class="form-row" id="node-tostatus-line">
+        <label for="node-input-typed-status"><i class="fa fa-ellipsis-h"></i> <span data-i18n="debug.status"></span></label>
+        <input id="node-input-typed-status" type="text" style="width: 70%">
+        <input id="node-input-statusVal" type="hidden">
+        <input id="node-input-statusType" type="hidden">
+    </div>
     <div class="form-row">
         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
         <input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
@@ -45,7 +50,9 @@
             console: {value:false},
             tostatus: {value:false},
             complete: {value:"false", required:true},
-            targetType: {value:undefined}
+            targetType: {value:undefined},
+            statusVal: {value:""},
+            statusType: {value:"msg"}
         },
         label: function() {
             var suffix = "";
@@ -308,7 +315,6 @@
             window.removeEventListener("message",this.handleWindowMessage);
             RED.actions.remove("core:show-debug-tab");
             RED.actions.remove("core:clear-debug-messages");
-
             delete RED._debug;
         },
         oneditprepare: function() {
@@ -331,6 +337,7 @@
                 label: RED._("node-red:debug.msgobj"),
                 hasValue: false
             };
+
             $("#node-input-typed-complete").typedInput({
                 default: "msg",
                 types:['msg', fullType, "jsonata"],
@@ -354,17 +361,30 @@
                 ) {
                     $("#node-input-typed-complete").typedInput('value','payload');
                 }
-                if ($("#node-input-typed-complete").typedInput('type') === 'full') {
-                    $("#node-tostatus-line").hide();
-                } else {
+            });
+
+            $("#node-input-typed-status").typedInput({
+                default: "msg",
+                types:['msg',"jsonata"],
+                typeField: $("#node-input-statusType")
+            });
+            var that = this;
+            $("#node-input-tostatus").on('change',function() {
+                if ($(this).is(":checked")) {
+                    if (!that.hasOwnProperty("statusVal") || that.statusVal === "") {
+                        that.statusType = "msg";
+                        that.statusVal = (that.complete === "false") ? "payload" : ((that.complete === "true") ? "payload" : that.complete+"");  
+                    }
+                    $("#node-input-typed-status").typedInput('type',that.statusType);
+                    $("#node-input-typed-status").typedInput('value',that.statusVal);
                     $("#node-tostatus-line").show();
                 }
-            });
-            $("#node-input-complete").on('change',function() {
-                if ($("#node-input-typed-complete").typedInput('type') === 'full') {
+                else {
                     $("#node-tostatus-line").hide();
-                } else {
-                    $("#node-tostatus-line").show();
+                    that.statusType = "msg";
+                    that.statusVal = "";
+                    $("#node-input-typed-status").typedInput('type',that.statusType);
+                    $("#node-input-typed-status").typedInput('value',that.statusVal);
                 }
             });
         },
@@ -375,6 +395,7 @@
             } else {
                 $("#node-input-complete").val($("#node-input-typed-complete").typedInput('value'));
             }
+            $("#node-input-statusVal").val($("#node-input-typed-status").typedInput('value'));
         }
     });
 })();
diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.js b/packages/node_modules/@node-red/nodes/core/common/21-debug.js
index b00371bbd..07d75378e 100644
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.js
+++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.js
@@ -15,13 +15,17 @@ module.exports = function(RED) {
         this.complete = hasEditExpression ? null : (n.complete||"payload").toString();
         if (this.complete === "false") { this.complete = "payload"; }
         this.console = ""+(n.console || false);
-        this.tostatus = (this.complete !== "true") && (n.tostatus || false);
+        this.tostatus = n.tostatus || false;
+        this.statusType = n.statusType || "msg";
+        this.statusVal = n.statusVal || this.complete;
         this.tosidebar = n.tosidebar;
         if (this.tosidebar === undefined) { this.tosidebar = true; }
         this.severity = n.severity || 40;
         this.active = (n.active === null || typeof n.active === "undefined") || n.active;
         if (this.tostatus) { this.status({fill:"grey", shape:"ring"}); }
         else { this.status({}); }
+        var hasStatExpression = (n.statusType === "jsonata");
+        var statExpression = hasStatExpression ? n.statusVal : null;
 
         var node = this;
         var levels = {
@@ -45,6 +49,7 @@ module.exports = function(RED) {
             "60": "blue"
         };
         var preparedEditExpression = null;
+        var preparedStatExpression = null;
         if (editExpression) {
             try {
                 preparedEditExpression = RED.util.prepareJSONataExpression(editExpression, this);
@@ -54,16 +59,22 @@ module.exports = function(RED) {
                 return;
             }
         }
+        if (statExpression) {
+            try {
+                preparedStatExpression = RED.util.prepareJSONataExpression(statExpression, this);
+            }
+            catch (e) {
+                node.error(RED._("debug.invalid-exp", {error: editExpression}));
+                return;
+            }
+        }
 
         function prepareValue(msg, done) {
             // Either apply the jsonata expression or...
             if (preparedEditExpression) {
                 RED.util.evaluateJSONataExpression(preparedEditExpression, msg, (err, value) => {
-                    if (err) {
-                        done(RED._("debug.invalid-exp", {error: editExpression}));
-                    } else {
-                        done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value});
-                    }
+                    if (err) { done(RED._("debug.invalid-exp", {error: editExpression})); } 
+                    else { done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value}); }
                 });
             } else {
                 // Extract the required message property
@@ -71,17 +82,41 @@ module.exports = function(RED) {
                 var output = msg[property];
                 if (node.complete !== "false" && typeof node.complete !== "undefined") {
                     property = node.complete;
-                    try {
-                        output = RED.util.getMessageProperty(msg,node.complete);
-                    } catch(err) {
-                        output = undefined;
-                    }
+                    try { output = RED.util.getMessageProperty(msg,node.complete); } 
+                    catch(err) { output = undefined; }
                 }
                 done(null,{id:node.id, z:node.z, _alias: node._alias,  path:node._flow.path, name:node.name, topic:msg.topic, property:property, msg:output});
             }
         }
 
+        function prepareStatus(msg, done) {
+            // Either apply the jsonata expression or...
+            if (preparedStatExpression) {
+                RED.util.evaluateJSONataExpression(preparedStatExpression, msg, (err, value) => {
+                    if (err) { done(RED._("debug.invalid-exp", {error:editExpression})); } 
+                    else { done(null,{msg:value}); }
+                });
+            } else {
+                // Extract the required message property
+                var output;
+                try { output = RED.util.getMessageProperty(msg,node.statusVal); }
+                catch(err) { output = undefined; }
+                done(null,{msg:output});
+            }
+        }
+
         this.on("input", function(msg, send, done) {
+            if (node.tostatus === true) {
+                prepareStatus(msg,function(err,debugMsg) {
+                    if (err) { node.error(err); return; }
+                    var output = debugMsg.msg;
+                    var st = (typeof output === 'string') ? output : util.inspect(output);
+                    var severity = msg.errorlevel || node.severity;
+                    if (st.length > 32) { st = st.substr(0,32) + "..."; }
+                    node.status({fill:colors[severity] || "grey", shape:"dot", text:st});
+                });
+            }
+
             if (this.complete === "true") {
                 // debug complete msg object
                 if (this.console === "true") {
@@ -91,7 +126,8 @@ module.exports = function(RED) {
                     sendDebug({id:node.id, z:node.z, _alias: node._alias,  path:node._flow.path, name:node.name, topic:msg.topic, msg:msg});
                 }
                 done();
-            } else {
+            } 
+            else {
                 prepareValue(msg,function(err,debugMsg) {
                     if (err) {
                         node.error(err);
@@ -107,12 +143,6 @@ module.exports = function(RED) {
                             node.log(util.inspect(output, {colors:useColors}));
                         }
                     }
-                    if (node.tostatus === true) {
-                        var st = (typeof output === 'string')?output:util.inspect(output);
-                        var severity = node.severity;
-                        if (st.length > 32) { st = st.substr(0,32) + "..."; }
-                        node.status({fill:colors[severity], shape:"dot", text:st});
-                    }
                     if (node.active) {
                         if (node.tosidebar == true) {
                             sendDebug(debugMsg);
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index 73c09d0d1..76d1fcc3d 100755
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -118,6 +118,7 @@
     },
     "debug": {
         "output": "Output",
+        "status": "status",
         "none": "None",
         "invalid-exp": "Invalid JSONata expression: __error__",
         "msgprop": "message property",