node-red-dashboard
Version:
A set of dashboard nodes for Node-RED
256 lines (250 loc) • 12.9 kB
HTML
<style>
input.series-color {
width: 100px;
text-align: center;
}
input.series-color::-webkit-color-swatch {
border: none;
}
</style>
<script type="text/javascript">
RED.nodes.registerType('ui_chart',{
category: 'dashboard',
color: 'rgb(119, 198, 204)',
defaults: {
name: {value: ''},
group: {type: 'ui_group', required: true},
order: {value: 0},
width: {value: 0, validate: function(v) {
var width = v||0;
var currentGroup = $('#node-input-group').val()||this.group;
var groupNode = RED.nodes.node(currentGroup);
var valid = !groupNode || +width <= +groupNode.width;
$("#node-input-size").toggleClass("input-error",!valid);
return valid;
}},
height: {value: 0},
label: {value: 'chart'},
chartType: {value: 'line'},
legend: {value: 'false'},
xformat: {value: 'HH:mm:ss'},
interpolate: {value: 'linear', required:true},
nodata: {value: ''},
ymin: {value: '', validate:function(value) { return value === '' || RED.validators.number(); }},
ymax: {value: '', validate:function(value) { return value === '' || RED.validators.number(); }},
removeOlder: {value: 1, validate:RED.validators.number(), required:true},
removeOlderPoints: {value: '', validate:function(value) { return value === '' || RED.validators.number(); }},
removeOlderUnit: {value: '3600', required:true},
cutout: {value: 0},
colors: {value: ['#1F77B4', '#AEC7E8', '#FF7F0E', '#2CA02C', '#98DF8A', '#D62728', '#FF9896', '#9467BD', '#C5B0D5']},
},
inputs:1,
outputs:2,
outputLabels: ["chart state","(deprecated)"],
align: "right",
icon: "ui_chart.png",
paletteLabel: 'chart',
label: function() { return this.name || (~this.label.indexOf("{{") ? null : this.label) || 'chart'; },
oneditprepare: function() {
$("#node-input-size").elementSizer({
width: "#node-input-width",
height: "#node-input-height",
group: "#node-input-group"
});
$("#node-input-chartType").change(function() {
if ($(this).val() === "horizontalBar") {
$("#y-label-show").hide();
$("#x-label-show").show();
}
else {
$("#y-label-show").show();
$("#x-label-show").hide();
}
if ($(this).val() === "line") {
$("#x-axis-show").show();
$("#x-axis-label-show").show();
$("#interpolate-show").show();
$("#legend-show").show();
$("#y-axis-show").show();
$("#hole-size-show").hide();
} else {
$("#x-axis-show").hide();
$("#x-axis-label-show").hide();
$("#interpolate-show").hide();
if ($(this).val() === "pie") {
$("#y-axis-show").hide();
$("#legend-show").show();
$("#hole-size-show").show();
} else {
$("#y-axis-show").show();
$("#legend-show").hide();
$("#hole-size-show").hide();
}
}
});
var setColour = function(id, value) {
$(id).val(value);
$(id).css("background-color", value);
var rgb = tinycolor(value).toRgb();
var level = ((rgb.r*299) + (rgb.g*587) + (rgb.b*114))/1000;
var textColor = (level >= 128) ? '#111111' : '#eeeeee';
$(id).css("color", textColor);
}
$(".series-color").change(function() {
setColour("#"+$(this).attr("id"), $(this).val());
});
if (!$("#node-input-chartType").val()) {
$("#node-input-chartType").val("line");
}
var oval = $("#node-input-xformat").val();
if (!oval) { $("#node-input-xformat").val("HH:mm:ss"); }
var odef = 'custom';
if (oval === "HH:mm:ss") { odef = oval; }
if (oval === "HH:mm") { odef = oval; }
if (oval === "Y-M-D") { odef = oval; }
if (oval === "D/M") { odef = oval; }
if (oval === "dd HH:mm") { odef = oval; }
var ohms = {value:"HH:mm:ss", label:"HH:mm:ss", hasValue:false};
var ohm = {value:"HH:mm", label:"HH:mm", hasValue:false};
var oymd = {value:"Y-M-D", label:"Year-Month-Date", hasValue:false};
var odm = {value:"D/M", label:"Date/Month", hasValue:false};
var oahm = {value:"dd HH:mm", label:"Day HH:mm", hasValue:false};
var ocus = {value:"custom", label:"custom", icon:"red/images/typedInput/az.png"};
$("#node-input-xformat").typedInput({
default: odef,
types:[ ohms, ohm, oahm, odm, oymd, ocus ]
});
var defaultColors = ['#1F77B4', '#AEC7E8', '#FF7F0E', '#2CA02C', '#98DF8A', '#D62728', '#FF9896', '#9467BD', '#C5B0D5'];
if (this.colors) {
for (var i=0; i<this.colors.length; i++) {
var value = this.colors[i] || defaultColors[i];
setColour("#node-input-color"+(i+1), value);
}
}
else {
for (var c=0; c<defaultColors.length; c++) {
setColour("#node-input-color"+(c+1), defaultColors[c]);
}
}
},
oneditsave: function() {
if ($("#node-input-xformat").typedInput('type') !== 'custom') {
$("#node-input-xformat").val($("#node-input-xformat").typedInput('type'));
}
this.colors = [$("#node-input-color1").val(),$("#node-input-color2").val(),$("#node-input-color3").val(),
$("#node-input-color4").val(),$("#node-input-color5").val(),$("#node-input-color6").val(),
$("#node-input-color7").val(),$("#node-input-color8").val(),$("#node-input-color9").val()];
}
});
</script>
<script type="text/x-red" data-template-name="ui_chart">
<div class="form-row">
<label for="node-input-group"><i class="fa fa-table"></i> Group</label>
<input type="text" id="node-input-group">
</div>
<div class="form-row">
<label><i class="fa fa-object-group"></i> Size</label>
<input type="hidden" id="node-input-width">
<input type="hidden" id="node-input-height">
<button class="editor-button" id="node-input-size"></button>
</div>
<div class="form-row">
<label for="node-input-label"><i class="fa fa-i-cursor"></i> Label</label>
<input type="text" id="node-input-label" placeholder="optional chart title">
</div>
<div class="form-row">
<label for="node-input-removeOlder"><i class="fa fa-line-chart"></i> Type</label>
<select id="node-input-chartType" style="width:159px; font-family:'FontAwesome','Helvetica Neue', Helvetica, Arial, sans-serif">
<option value="line">  Line chart</option>
<option value="bar">  Bar chart</option>
<option value="horizontalBar">  Bar chart (H)</option>
<option value="pie">  Pie chart</option>
</select>
</div>
<div class="form-row" id="x-axis-show">
<label for="node-input-removeOlder">X-axis</label>
<label for="node-input-removeOlder" style="width: auto">last</label>
<input type="text" id="node-input-removeOlder" style="width:50px;">
<select id="node-input-removeOlderUnit" style="width:80px;">
<option value="1">seconds</option>
<option value="60">minutes</option>
<option value="3600">hours</option>
<option value="86400">days</option>
<option value="604800">weeks</option>
</select>
<label for="node-input-removeOlderPoints" style="width: auto; margin-left: 10px; margin-right: 10px;">OR</label>
<input type="text" id="node-input-removeOlderPoints" style="width:60px;" placeholder="1000">
<span style="margin-left: 5px;">points</span>
</div>
<div class="form-row" id="x-axis-label-show">
<label for="node-input-xformat">X-axis Label</label>
<input type="text" id="node-input-xformat" style="width:268px;">
</div>
<div class="form-row" id="y-axis-show">
<label id="y-label-show" for="node-input-ymin">Y-axis</label>
<label id="x-label-show" for="node-input-ymin">X-axis</label>
<label for="node-input-ymin" style="width:auto">min</label>
<input type="text" id="node-input-ymin" style="width:80px">
<label for="not-input-ymax" style="width:auto; margin-left: 20px;">max</label>
<input type="text" id="node-input-ymax" style="width:80px">
</div>
<div class="form-row" id="legend-show">
<label for="node-input-legend">Legend</label>
<select id="node-input-legend" style="width:120px;">
<option value="false">None</option>
<option value="true">Show</option>
</select>
<span id="interpolate-show"> Interpolate
<select id="node-input-interpolate" style="width:120px;">
<option value="linear">linear</option>
<option value="step">step</option>
<option value="bezier">bezier</option>
</select>
</span>
<span id="hole-size-show"> Cutout
<input type="text" id="node-input-cutout" style="width:35px"> %
</span>
</div>
<div class="form-row" id="ui-chart-colours">
<label for="node-input-color1">Series Colours</label>
<input type="color" id="node-input-color1" class="series-color"/>
<input type="color" id="node-input-color2" class="series-color"/>
<input type="color" id="node-input-color3" class="series-color"/>
<div style="margin-top: 5px; margin-left: 104px;">
<input type="color" id="node-input-color4" class="series-color"/>
<input type="color" id="node-input-color5" class="series-color"/>
<input type="color" id="node-input-color6" class="series-color"/>
</div>
<div style="margin-top: 5px; margin-left: 104px;">
<input type="color" id="node-input-color7" class="series-color"/>
<input type="color" id="node-input-color8" class="series-color"/>
<input type="color" id="node-input-color9" class="series-color"/>
</div>
</div>
<div class="form-row">
<label for="node-input-nodata">Blank label</label>
<input type="text" id="node-input-nodata" placeholder="display this text before valid data arrives">
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name">
</div>
</script>
<script type="text/x-red" data-help-name="ui_chart">
<p>Plots the input values on a chart. This can either be a time based line chart, a bar chart (vertical or horizontal),
or a pie chart.</p>
<p>Each input <code>msg.payload</code> value will be converted to a number. If the
conversion fails, the message is ignored.</p>
<p>Minimum and Maximum <b>Y</b> axis values are optional. The graph will auto-scale to any values received.</p>
<p>Multiple lines can be shown on the same chart by using a different <code>msg.topic</code>
value on each input message.</p>
<p>The <b>X</b> axis defines a time window or a maximum number of points to display. Older data will be automatically removed from the graph.
The axis labels can be formatted using a <a href="http://momentjs.com/docs/#/displaying/format/" target="_blank">
Moment.js time formatted</a> string.</p>
<p>Inputting a `msg.payload` containing a blank array `[]` will clear the chart.</p>
<p>The <b>Blank label</b> field can be used to display some text before any valid data is received.</p>
<p>The node output contains an array of the chart state that can be persisted if needed. This can be passed
into the chart node to display the persisted data.
The node second output should no longer be used and will be removed in a future release. Use the
<code>ui_control</code> node to trigger a restore if needed.</p>
</script>