node-red-contrib-dashbored
Version:
A customizable dashboard for NodeRed
238 lines (219 loc) • 9.35 kB
HTML
<!-- NodeRed Documentation https://nodered.org/docs/creating-nodes/edit-dialog -->
<script type="text/x-red" data-template-name="dashbored-widget">
<div class="form-row">
<label for="node-config-input-name">Name</label>
<input type="text" id="node-config-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-config-input-server">Server</label>
<input type="text" id="node-config-input-server">
</div>
<div class="form-row">
<label for="node-config-input-widgetType">Type</label>
<input type="text" id="node-config-input-widgetType">
</div>
<div class="form-row">
<label>Size (W x H)</label>
<input type="float" style="width: 10%" id="node-config-input-widthMultiplier" min="0">
x
<input type="float" style="width: 10%" id="node-config-input-heightMultiplier" min="0">
</div>
<div class="form-row">
<label for="node-config-input-title">Title</label>
<input type="text" id="node-config-input-title">
</div>
<div class="form-row">
<label for="node-config-input-setsState">Set the value locally</label>
<input type="checkbox" id="node-config-input-setsState">
</div>
<div class="form-row">
<label for="node-config-input-restoreState">Restore State on Redeploy</label>
<input type="checkbox" id="node-config-input-restoreState">
</div>
<p id="widget-id" style="color: gray"><p>
<hr>
<div class="form-row" id="widget-type-populate-area">
<p style="color: red">Please deploy to create the widget and populate the settings here</p>
</div>
<div class="form-row">
<label for="copyFrom">Copy from:</label>
<input type="text" id="copyFrom">
</div>
<button id="reset">Copy Configuration</button>
</script>
<script type="text/javascript">
async function generate() {
var defaults = {
name: {
value: "Widget",
required: true
},
server: {
value: "",
required: true,
type: "dashbored-server"
},
widgetType: {
value: "",
required: true
},
widthMultiplier: {
value: 1,
required: true
},
heightMultiplier: {
value: 1,
required: true
},
title: {
value: "",
required: false
},
restoreState: {
value: true
},
setsState: {
value: true
}
}
//Get the widget types
try {
var widgetTypes = await $.ajax({
type: "GET",
url: RED.settings.httpNodeRoot + "dashboredAPI",
data: "widgetTypes"
});
}
catch (e) { console.error("Failed to get the widget types!!"); return; }
//Add the default configs for the widgets
for (var i in widgetTypes) {
for (var j in widgetTypes[i].defaultConfig) {
defaults[i + "-" + j] = widgetTypes[i].defaultConfig[j];
}
}
RED.nodes.registerType("dashbored-widget", {
category: "config",
defaults,
label: function () {
return (this.name || "Toggle Button");
},
oneditprepare: async function () {
var self = this;
$("#widget-id").html("ID: " + this.id);
//Grab the widget
try {
var widgets = await $.ajax({
type: "GET",
url: RED.settings.httpNodeRoot + "dashboredAPI",
data: "widgets"
});
} catch (e) { }
var widget;
var widgetOfSameType = [];
for (var i in widgets) {
if (widgets[i].id == this.id) {
widget = widgets[i];
break;
}
}
if (widget && widget.widgetType) {
for (var i in widgets) {
if (widgets[i].widgetType == widget.widgetType) {
widgetOfSameType.push(widgets[i]);
}
}
}
//Set the widget type selector
var types = [];
for (var i in widgetTypes) {
types.push({
label: widgetTypes[i].name,
value: i
});
}
$("#node-config-input-widgetType").typedInput({
types: [{
value: "widgetType",
options: types
}]
});
//Add the widgets of same type to be copied from
var types = [];
for (var i in widgetOfSameType) {
types.push({
label: widgetOfSameType[i].label,
value: i
});
}
types.push({
label: "Reset",
value: "reset"
});
$("#copyFrom").typedInput({
types: [{
value: "copyFrom",
options: types
}]
});
if (!widget) { return; }
var currentWidgetType;
var setupWidgetType = function (element) {
//Populate the widget type config options
var div = $("#widget-type-populate-area");
div.html("");
div.append(currentWidgetType.configHTML);
//Set the field values
for (var i in currentWidgetType.defaultConfig) {
$(`#node-config-input-${currentWidgetType.widget}-${i}`).val(element[`${currentWidgetType.widget}-${i}`]);
}
//Run any oneditprepare scripts
if (currentWidgetType.configScript.oneditprepare) { eval(currentWidgetType.configScript.oneditprepare); }
}
$("#reset").on("click", function () {
var element = self;
if ($("#copyFrom").val() == "reset") {
if (currentWidgetType.configScript.update) {
window.eval.call(window, `(function (element, settings) {${currentWidgetType.configScript.update}})`)(element, currentWidgetType.defaultConfig);
}
}
else {
var copy = widgetOfSameType[$("#copyFrom").val()];
if (copy && copy.settings) {
var temp = {};
for (var i in copy.settings) {
temp[i] = { value: copy.settings[i] }
}
window.eval.call(window, `(function (element, settings) {${currentWidgetType.configScript.update}})`)(element, temp);
}
}
});
//https://nodered.org/docs/api/ui/typedInput/#methods
$("#node-config-input-widgetType").typedInput("value", this.widgetType);
currentWidgetType = widgetTypes[this.widgetType];
this.currentWidgetType = currentWidgetType;
setupWidgetType(self);
//When the user changes the type rerender
$("#node-config-input-widgetType").on("change", function (event, type) {
currentWidgetType = widgetTypes[event.target.value];
self.currentWidgetType = currentWidgetType;
setupWidgetType(self);
});
},
oneditsave: function () {
//Find all the elements generated and save their values
for (var i in this.currentWidgetType.defaultConfig) {
this[`${this.currentWidgetType.widget}-${i}`] = $(`#node-config-input-${this.currentWidgetType.widget}-${i}`).val();
}
//Call the widget type to do any more
var element = this;
if (this.currentWidgetType.configScript.oneditsave) { eval(this.currentWidgetType.configScript.oneditsave); }
this.widgetType = $("#node-config-input-widgetType").val();
},
oneditcancel: function () {
var element = this;
if (this.currentWidgetType.configScript.oneditcancel) { eval(this.currentWidgetType.configScript.oneditcancel); }
},
});
}
generate();
</script>