First pass of new node-info style

This commit is contained in:
Nick O'Leary 2017-04-05 16:19:23 +01:00
parent 28ea22f0e1
commit 262db23f7d
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
5 changed files with 202 additions and 91 deletions

View File

@ -32,7 +32,12 @@ RED.sidebar.info = (function() {
content.style.paddingRight = "4px";
content.className = "sidebar-node-info"
var propertiesExpanded = false;
var expandedSections = {
"node": true,
"property": false,
"info": true,
"subflow": true
};
function init() {
RED.sidebar.addTab({
@ -80,12 +85,14 @@ RED.sidebar.info = (function() {
$(content).empty();
var table = $('<table class="node-info"></table>');
var tableBody = $('<tbody>').appendTo(table);
$('<tr class="blank"><td colspan="2">'+RED._("sidebar.info.node")+'</td></tr>').appendTo(tableBody);
$('<tr class="blank"><th colspan="2"><a href="#" class="node-info-node-header'+(expandedSections.node?" expanded":"")+'"><i class="fa fa-angle-right"></i> '+RED._("sidebar.info.node")+'</a></th></tr>').appendTo(tableBody);
if (node.type != "subflow" && node.name) {
$('<tr><td>'+RED._("common.label.name")+'</td><td>&nbsp;<span class="bidiAware" dir="'+RED.text.bidi.resolveBaseTextDir(node.name)+'">'+node.name+'</span></td></tr>').appendTo(tableBody);
$('<tr class="node-info-node-row'+(expandedSections.node?"":" hide")+'"><td>'+RED._("common.label.name")+'</td><td>&nbsp;<span class="bidiAware" dir="'+RED.text.bidi.resolveBaseTextDir(node.name)+'">'+node.name+'</span></td></tr>').appendTo(tableBody);
}
$("<tr><td>"+RED._("sidebar.info.type")+"</td><td>&nbsp;"+node.type+"</td></tr>").appendTo(tableBody);
$("<tr><td>"+RED._("sidebar.info.id")+"</td><td>&nbsp;"+node.id+"</td></tr>").appendTo(tableBody);
$('<tr class="node-info-node-row'+(expandedSections.node?"":" hide")+'"><td>'+RED._("sidebar.info.type")+"</td><td>&nbsp;"+node.type+"</td></tr>").appendTo(tableBody);
$('<tr class="node-info-node-row'+(expandedSections.node?"":" hide")+'"><td>'+RED._("sidebar.info.id")+"</td><td>&nbsp;"+node.id+"</td></tr>").appendTo(tableBody);
var m = /^subflow(:(.+))?$/.exec(node.type);
var subflowNode;
@ -96,7 +103,7 @@ RED.sidebar.info = (function() {
subflowNode = node;
}
$('<tr class="blank"><td colspan="2">'+RED._("sidebar.info.subflow")+'</td></tr>').appendTo(tableBody);
$('<tr class="blank"><th colspan="2"><a href="#" class="node-info-subflow-header'+(expandedSections.subflow?" expanded":"")+'"><i class="fa fa-angle-right"></i> '+RED._("sidebar.info.subflow")+'</a></th></tr>').appendTo(tableBody);
var userCount = 0;
var subflowType = "subflow:"+subflowNode.id;
@ -105,54 +112,54 @@ RED.sidebar.info = (function() {
userCount++;
}
});
$('<tr><td>'+RED._("common.label.name")+'</td><td><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+subflowNode.name+'</span></td></tr>').appendTo(tableBody);
$("<tr><td>"+RED._("sidebar.info.instances")+"</td><td>"+userCount+"</td></tr>").appendTo(tableBody);
$('<tr class="node-info-subflow-row'+(expandedSections.subflow?"":" hide")+'"><td>'+RED._("common.label.name")+'</td><td><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+subflowNode.name+'</span></td></tr>').appendTo(tableBody);
$('<tr class="node-info-subflow-row'+(expandedSections.subflow?"":" hide")+'"><td>'+RED._("sidebar.info.instances")+"</td><td>"+userCount+'</td></tr>').appendTo(tableBody);
}
if (!m && node.type != "subflow" && node.type != "comment") {
$('<tr class="blank"><td colspan="2"><a href="#" class="node-info-property-header"><i style="width: 10px; text-align: center;" class="fa fa-caret-'+(propertiesExpanded?"down":"right")+'"></i> '+RED._("sidebar.info.properties")+'</a></td></tr>').appendTo(tableBody);
$('<tr class="blank"><th colspan="2"><a href="#" class="node-info-property-header'+(expandedSections.property?" expanded":"")+'"><i class="fa fa-angle-right"></i> '+RED._("sidebar.info.properties")+'</a></th></tr>').appendTo(tableBody);
if (node._def) {
for (var n in node._def.defaults) {
if (n != "name" && node._def.defaults.hasOwnProperty(n)) {
var val = node[n];
var type = typeof val;
var propRow = $('<tr class="node-info-property-row'+(propertiesExpanded?"":" hide")+'"><td>'+n+"</td><td></td></tr>").appendTo(tableBody);
var propRow = $('<tr class="node-info-property-row'+(expandedSections.property?"":" hide")+'"><td>'+n+"</td><td></td></tr>").appendTo(tableBody);
RED.utils.createObjectElement(val).appendTo(propRow.children()[1]);
}
}
}
}
$(table).appendTo(content);
$("<hr/>").appendTo(content);
var infoText = "";
if (!subflowNode && node.type != "comment") {
var helpText = $("script[data-help-name$='"+node.type+"']").html()||"";
addTargetToExternalLinks($('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(helpText)+'">'+helpText+'</span></div>').appendTo(content));
infoText = helpText;
}
if (subflowNode) {
addTargetToExternalLinks($('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.info||"")+'">'+marked(subflowNode.info||"")+'</span></div>').appendTo(content));
infoText = marked(subflowNode.info||"");
} else if (node._def && node._def.info) {
var info = node._def.info;
var textInfo = (typeof info === "function" ? info.call(node) : info);
addTargetToExternalLinks($('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(textInfo)+'">'+marked(textInfo)+'</span></div>').appendTo(content));
//$('<div class="node-help">'+(typeof info === "function" ? info.call(node) : info)+'</div>';
infoText = marked(textInfo);
}
if (infoText) {
$('<tr class="blank"><th colspan="2"><a href="#" class="node-info-info-header'+(expandedSections.info?" expanded":"")+'"><i class="fa fa-angle-right"></i> '+RED._("sidebar.info.info")+'</a></th></tr>').appendTo(tableBody);
addTargetToExternalLinks($('<tr class="blank node-info-info-row'+(expandedSections.info?"":" hide")+'"><td colspan="2"><div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div></td></tr>')).appendTo(tableBody);
}
$(".node-info-property-header").click(function(e) {
var icon = $(this).find("i");
if (icon.hasClass("fa-caret-right")) {
icon.removeClass("fa-caret-right");
icon.addClass("fa-caret-down");
$(".node-info-property-row").show();
propertiesExpanded = true;
} else {
icon.addClass("fa-caret-right");
icon.removeClass("fa-caret-down");
$(".node-info-property-row").hide();
propertiesExpanded = false;
}
e.preventDefault();
});
["node","subflow","property","info"].forEach(function(t) {
$(".node-info-"+t+"-header").click(function(e) {
e.preventDefault();
console.log(t,expandedSections[t]);
expandedSections[t] = !expandedSections[t];
$(this).toggleClass("expanded",expandedSections[t]);
$(".node-info-"+t+"-row").toggle(expandedSections[t]);
})
})
}

View File

@ -22,64 +22,134 @@ table.node-info {
margin: 0px;
width: 97%;
}
table.node-info tr {
table.node-info tr:not(.blank) {
border: 1px solid #ddd;
}
table.node-info tr.blank {
border: none;
th {
text-align: left;
font-weight: bold;
color: #444;
}
>* {
padding-top: 8px;
border: none;
padding-left: 0px;
}
a {
display: block;
color: #444;
&:hover,&:focus {
color: #444;
text-decoration: none;
}
i {
width: 10px;
text-align: center;
transition: transform 0.2s ease-in-out;
}
&.expanded i {
transform: rotate(90deg);
}
}
&.node-info-info-row > td {
padding-left: 5px;
}
}
table.node-info tr.blank td {
padding-top: 8px;
border: none;
font-weight: bold;
padding-left: 0px;
}
table.node-info td:first-child{
table.node-info tr:not(.blank) td:first-child{
color: #666;
vertical-align: top;
width: 90px;
padding: 3px;
border-right: 1px solid #ddd;
}
table.node-info td:last-child{
table.node-info tr:not(.blank) td:last-child{
padding-left: 5px;
color: #666;
}
div.node-info {
margin: 5px;
}
.node-info-property-header {
color: #666;
}
.node-info-property-header:hover,
.node-info-property-header:focus {
color: #666;
text-decoration: none;
}
.node-help {
font-size: 14px;
line-height: 1.5em;
h1 {
font-weight: normal;
font-weight: 500;
font-size: 23px;
line-height: 1.3em;
margin: 8px auto;
}
h2 {
font-weight: normal;
font-weight: 500;
font-size: 18px;
margin: 8px auto;
line-height: 1.3em;
}
h3 {
font-weight: normal;
font-weight: 500;
font-size: 16px;
margin: 8px auto;
margin: 7px auto 5px;
line-height: 1.3em;
}
h4,
h5 {
font-weight: normal;
font-weight: 500;
font-size: 14px;
margin: 8px auto;
line-height: 1.3em;
margin: 8px auto 5px;
}
& > span > p:first-child {
}
dl.message-properties {
border: 1px solid #eee;
border-radius: 2px;
margin: 5px auto 10px;
&>dt {
padding: 0px 3px 2px 3px;
font-family: monospace;
font-weight: normal;
margin: 5px 3px 1px;
color: #AD1625;
white-space: nowrap;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
border-radius: 2px;
&.optional {
font-style: italic;
}
.property-type {
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;
color: #666;
font-style: italic;
font-size: 11px;
float: right;
}
&:after {
content: "";
display: table;
clear: both;
}
}
&>dd {
margin: 1px 8px 10px 10px;
}
}
ol.node-ports {
margin: 0;
li {
border: 1px solid #eee;
border-radius: 2px;
list-style-position: inside;
padding: 3px;
margin-bottom: 5px;
}
}
}
.node-info-tip {
position: absolute;

View File

@ -44,33 +44,55 @@
</script>
<script type="text/x-red" data-help-name="exec">
<p>Calls out to a system command.<br/></p>
<p><b>Inputs</b></p>
<ul><li><code>msg.payload</code> - optionally appended to the configured command.</li></ul>
<ul><li><code><i>msg.kill</i></code> - can be used to kill a running command, see below.</li></ul>
<ul><li><code><i>msg.pid</i></code> - can be used to kill a specific running command, see below.</li></ul>
<p><b>Outputs</b></p>
<ol>
<li>stdout, <code>msg.payload</code> containing the returned output from the command.</li>
<li>stderr, <code>msg.payload</code> containing any error output from the command.</li>
<li>return code, <code>msg.payload</code> containing the return (see below).</li>
<p>Calls out to a system command.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">msg.payload <span class="property-type">string</span></dt>
<dd>if configured to do so, will be appended to the executed command.</dd>
<dt class="optional">msg.kill <span class="property-type">string</span></dt>
<dd>the type of kill signal to send an existing exec node process.</dd>
<dt class="optional">msg.pid <span class="property-type">number|string</span></dt>
<dd>the process ID of an existing exec node process to kill.</dd>
</dl>
<h3>Outputs</h3>
<ol class="node-ports">
<li>Standard output
<dl class="message-properties">
<dt>msg.payload <span class="property-type">string</span></dt>
<dd>the standard output of the command.</dd>
</dl>
</li>
<li>Standard error
<dl class="message-properties">
<dt>msg.payload <span class="property-type">string</span></dt>
<dd>the standard error of the command.</dd>
</dl>
</li>
<li>Return code
<dl class="message-properties">
<dt>msg.payload <span class="property-type">number</span></dt>
<dd>the return code of the command.</dd>
</dl>
</li>
</ol>
<p><b>Details</b></p>
<h3>Details</h3>
<p>By default uses the <code>exec</code> system call which calls the command, waits for it to complete, and then
returns the output. For example a succesful command should have a return code of <code>{ code: 0 }</code>.</p>
returns the output. For example a successful command should have a return code of <code>{ code: 0 }</code>.</p>
<p>Optionally can use <code>spawn</code> instead, which returns the output from stdout and stderr
as the command runs, usually one line at a time. On completion it then returns a numeric return code
on the 3rd port. For example a successful command should return <code>0</code>.</p>
<p>The optional <b>append</b> gets added to the command after <code>msg.payload</code> - so you can do
things like pipe the result to another command.</p>
<p>Commands or parameters with spaces should be enclosed in quotes - <i>"This is a single parameter"</i></p>
on the 3rd port. For example, a successful command should return <code>0</code>.</p>
<p>The command that is run is defined within the node, with an option to append <code>msg.payload</code> and a further set of parameters.</p>
<p>Commands or parameters with spaces should be enclosed in quotes - <code>"This is a single parameter"</code></p>
<p>The returned <code>payload</code> is usually a <i>string</i>, unless non-UTF8 characters are detected, in which
case it contains a <i>buffer</i>.</p>
<p>The blue status icon and PID will be visible while the node is active. This can be read by a <code>status</code> node.</p>
case it is a <i>buffer</i>.</p>
<p>The node&apos;s status icon and PID will be visible while the node is active. Changes to this can be read by the <code>Status</code> node.</p>
<h4>Killing processes</h4>
<p>Sending <code>msg.kill</code> will kill a single active process. <code>msg.kill</code> should be a string containing
the type of signal to be sent, e.g. "SIGINT", "SIGQUIT", "SIGHUP", etc. Defaults to "SIGTERM" if blank ("").
If there is more than one process running then <code>msg.pid</code> must also be set with the value of the PID to be killed.</p>
<p><b>Tip</b>: If running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
the type of signal to be sent, for example, <code>SIGINT</code>, <code>SIGQUIT</code> or <code>SIGHUP</code>. Defaults to <code>SIGTERM</code> if set to an empty string.</p>
<p>If the node has more than one process running then <code>msg.pid</code> must also be set with the value of the PID to be killed.</p>
<p>Tip: if running a Python app you may need to use the <code>-u</code> parameter to stop the output being buffered.</p>
</script>
<script type="text/javascript">

View File

@ -35,15 +35,19 @@
</script>
<script type="text/x-red" data-help-name="mqtt in">
<p>Connects to a MQTT broker and subscribes to messages from the specified topic.</p>
<p><b>Outputs</b>
<ul>
<li><code>msg.payload</code> - <i>string | buffer</i> - a string unless detected as a binary buffer.</li>
<li><code>msg.topic</code> - <i>string</i> - the MQTT topic, uses / as a heirarchy separator.</li>
<li><code>msg.qos</code> - <i>number</i> - 0, fire and forget - 1, at least once - 2, once and once only.</li>
<li><code>msg.retain</code> - <i>boolean</i> - true indicates the message was retained and may be old.</li>
</ul>
<p><b>Details</b><br/>
<p>Connects to a MQTT broker and subscribes to messages from the specified topic.</p>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>msg.payload <span class="property-type">string | buffer</span></dt>
<dd>a string unless detected as a binary buffer.</dd>
<dt>msg.topic <span class="property-type">string</span></dt>
<dd>the MQTT topic, uses / as a heirarchy separator.</dd>
<dt>msg.qos <span class="property-type">number</span> </dt>
<dd>0, fire and forget - 1, at least once - 2, once and once only.</dd>
<dt>msg.retain <span class="property-type">boolean</span></dt>
<dd>true indicates the message was retained and may be old.</dd>
</dl>
<h3>Details</h3>
The subscription topic can include MQTT wildcards, + for one level, # for multiple levels.</p>
<p>This node requires a connection to a MQTT broker to be configured. This is configured by clicking
the pencil icon.</p>
@ -109,14 +113,21 @@
<script type="text/x-red" data-help-name="mqtt out">
<p>Connects to a MQTT broker and publishes messages.</p>
<p><b>Inputs</b>
<ul>
<li><code>msg.payload</code> - <i>string | buffer</i> - most users prefer simple text payloads, but binary buffers can also be published.</li>
<li><code><i>msg.topic</i></code> - <i>string</i> - the MQTT topic, uses / as a hierarchy separator.</li>
<li><code><i>msg.qos</i></code> - <i>number</i> - 0, fire and forget - 1, at least once - 2, once and once only. Default 0.</li>
<li><code><i>msg.retain</i></code> - <i>boolean</i> - set to true to retain the message on the broker. Default false.</li>
</ul>
<p><b>Details</b><br/>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>msg.payload <span class="property-type">string | buffer</span></dt>
<dd> most users prefer simple text payloads, but binary buffers can also be published.</dd>
<dt class="optional">msg.topic <span class="property-type">string</span></dt>
<dd> the MQTT topic to publish to.</dd>
<dt class="optional">msg.qos <span class="property-type">number</span></dt>
<dd>0, fire and forget - 1, at least once - 2, once and once only. Default 0.</dd>
<dt class="optional">msg.retain <span class="property-type">boolean</span></dt>
<dd>set to true to retain the message on the broker. Default false.</dd>
</dl>
<h3>Details</h3>
<code>msg.payload</code> is used as the payload of the published message.
If it contains an Object it will be converted to a JSON string before being sent.
If it contains a binary Buffer the message will be published as-is.</p>

View File

@ -348,6 +348,7 @@
"subflow": "Subflow",
"instances": "Instances",
"properties": "Properties",
"info": "Information",
"blank": "blank",
"null": "null",
"arrayItems": "__count__ items"