node-red-contrib-dashbored
Version:
A customizable dashboard for NodeRed
295 lines (278 loc) • 11.9 kB
HTML
<script type="text/x-red" data-template-name="dashbored-dashbored">
<div class="form-row">
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-config-input-name" placeholder="Name">
</div>
<hr>
<!-- Page Adder -->
<div class="form-row">
<label for="node-input-pageName">Page</label>
<div style="display: inline">
<input type="text" id="node-input-pageName" value="Home" style="width: 30%"/>
<input type="text" id="node-input-pageIcon" value="fa-home" style="width: 30%"/>
</div>
<button type="button" class="red-ui-button" id="node-input-page-add"><i class="fa fa-clipboard" aria-hidden="true"></i></button>
</div>
<!-- Widget Adder -->
<div class="form-row">
<label for="node-input-widget">Widget</label>
<input type="text" id="node-input-widgets">
<button type="button" class="red-ui-button" id="node-input-widgets-add"><i class="fa fa-clipboard" aria-hidden="true"></i></button>
</div>
<p><a href="https://fontawesome.com/icons" target="_blank">Font Awesome Icons</a></p>
<p><a href="https://github.com/haydendonald/NodeRed-Dashbored" target="_blank">See the GitHub for more options</a></p>
<!-- HTML Editor -->
<div class="form-row">
<label for="node-input-html-editor">HTML</label>
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-html-editor"></div>
</div>
<!-- CSS Editor -->
<div class="form-row">
<label for="node-input-css-editor">CSS</label>
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-css-editor"></div>
</div>
<hr>
<div class="form-row">
<label for="node-config-input-server"><i class="icon-bookmark"></i> Server</label>
<input type="text" id="node-config-input-server">
</div>
<div class="form-row">
<label for="node-config-input-endpoint"><i class="icon-tag"></i> Path</label>
<input type="text" id="node-config-input-endpoint" placeholder="dashbored">
</div>
<div class="form-row">
<label for="node-config-input-password"><i class="icon-tag"></i> Password</label>
<input type="text" id="node-config-input-password" placeholder="">
</div>
<div class="form-row">
<label for="node-config-input-headerImage"><i class="icon-tag"></i> Header Image</label>
<input type="text" id="node-config-input-headerImage">
</div>
<div class="form-row">
<label for="node-config-input-headerText"><i class="icon-tag"></i> Header Title</label>
<input type="text" id="node-config-input-headerText" placeholder="Dashbored">
</div>
<div class="form-row">
<label for="node-config-input-showClock"><i class="icon-tag"></i> Show Clock</label>
<input type="checkbox" id="node-config-input-showClock" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-showWeather"><i class="icon-tag"></i> Show Weather</label>
<input type="checkbox" id="node-config-input-showWeather" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-showHeader"><i class="icon-tag"></i> Show Header</label>
<input type="checkbox" id="node-config-input-showHeader" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-showNav"><i class="icon-tag"></i> Show Navigation</label>
<input type="checkbox" id="node-config-input-showNav" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-alwaysShowLockButton"><i class="icon-tag"></i> Show Lock Button</label>
<input type="checkbox" id="node-config-input-alwaysShowLockButton" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-htmlToDOM"><i class="icon-tag"></i> Add console messages to HTML (for debugging)</label>
<input type="checkbox" id="node-config-input-htmlToDOM" placeholder="true">
</div>
<div class="form-row">
<label for="node-config-input-navMode"><i class="icon-tag"></i> Navigation Bar Position</label>
<input type="text" id="node-config-input-navMode" placeholder="right">
</div>
<div class="form-row">
<label for="node-config-input-baseWidth"><i class="icon-tag"></i> Widget Width</label>
<input type="text" id="node-config-input-baseWidth" placeholder="200px">
</div>
<div class="form-row">
<label for="node-config-input-baseHeight"><i class="icon-tag"></i> Widget Height</label>
<input type="text" id="node-config-input-baseHeight" placeholder="150px">
</div>
<div class="form-row">
<label for="node-config-input-headerHeight"><i class="icon-tag"></i> Header Size</label>
<input type="text" id="node-config-input-headerHeight" placeholder="60px">
</div>
<div class="form-row">
<label for="node-config-input-navHeight"><i class="icon-tag"></i> Navigation Size</label>
<input type="text" id="node-config-input-navHeight" placeholder="100px">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType("dashbored-dashbored", {
category: "config",
defaults: {
name: {
value: "Dashbored"
},
server: {
value: "",
required: true,
type: "dashbored-server"
},
endpoint: {
value: "dashbored",
required: true
},
password: {
value: "",
required: false
},
headerImage: {
value: "",
required: false
},
headerText: {
value: "Dashbored",
required: false
},
showClock: {
value: true
},
showWeather: {
value: true
},
showHeader: {
value: true
},
showNav: {
value: true
},
alwaysShowLockButton: {
value: false
},
htmlToDOM: {
value: false
},
navMode: {
value: "right",
required: true
},
baseHeight: {
value: "150px",
required: true
},
baseWidth: {
value: "200px",
required: true
},
headerHeight: {
value: "60px",
required: true
},
navHeight: {
value: "100px",
required: true
},
//The default HTML for the dashbored
HTML: {
value: `
<page name="Example 1" icon="fa-home">
<widget id="example-button1" type="toggleButton" text="Toggle Button" title="Toggle Button"></widget>
<widget id="example-buttonSelector" type="buttonSelector" title="Button Selector"></widget>
</page>
<page name="Locked Page" icon="fa-lock" always-password="yes">
<h1>This is a locked page :O</h1>
</page>
`.replace(/^\s+|\s+$/gm, ''),
required: true
},
//The default CSS for the dashbored
CSS: {
value: `
/* You can add custom CSS styling here, see https://github.com/haydendonald/NodeRed-Dashbored/blob/main/doc/dashbored.md#css-classes */
`.replace(/^\s+|\s+$/gm, ''),
required: true
}
},
label: function () {
return (this.name || "Dashbored");
},
oneditprepare: async function () {
console.log(this);
//Do a call to the server and request the widgets in memory
var widgets = await $.ajax({
type: "GET",
url: RED.settings.httpNodeRoot + "dashboredAPI",
data: "widgets"
});
var options = [];
var wids = {};
for (var i = 0; i < widgets.length; i++) {
options.push({
label: widgets[i].label,
value: widgets[i].id
});
wids[widgets[i].id] = widgets[i];
}
$("#node-input-widgets").typedInput({
types: [{
value: "widgets",
multiple: "true",
options: options
}]
});
//Add the nav bar options
$("#node-config-input-navMode").typedInput({
types: [{
value: "navMode",
options: [
{ value: "bottom", label: "Bottom" },
{ value: "top", label: "Top" },
{ value: "left", label: "Left" },
]
}]
});
//Copy the page to the clipboard
$("#node-input-page-add").click(() => {
var name = $("#node-input-pageName").val();
var icon = $("#node-input-pageIcon").val();
if(window.isSecureContext) {
navigator.clipboard.writeText(`<page name="${name}" icon="${icon}"></page>`);
}
else {
prompt(`Sorry copying without HTTPs is not allowed, copy it from here`, `<page name="${name}" icon="${icon}"></page>`);
}
});
//Copy the selected widgets to the clipboard
$("#node-input-widgets-add").click(() => {
var selected = $("#node-input-widgets").val().split(",");
var clipboard = "";
for (var i = 0; i < selected.length; i++) {
console.log(selected[i]);
clipboard += `<widget name="${wids[selected[i]].label}" id="${wids[selected[i]].id}"></widget>`;
}
if(window.isSecureContext) {
navigator.clipboard.writeText(clipboard);
}
else {
prompt(`Sorry copying without HTTPs is not allowed, copy it from here`, `${clipboard}`);
}
});
//Setup the editors
this.htmlEditor = RED.editor.createEditor({
id: "node-input-html-editor",
mode: "ace/mode/html",
value: this.HTML
});
this.cssEditor = RED.editor.createEditor({
id: "node-input-css-editor",
mode: "ace/mode/css",
value: this.CSS
});
},
oneditsave: function () {
this.HTML = this.htmlEditor.getValue();
this.htmlEditor.destroy();
delete this.htmlEditor;
this.CSS = this.cssEditor.getValue();
this.cssEditor.destroy();
delete this.cssEditor;
},
oneditcancel: function () {
this.htmlEditor.destroy();
delete this.htmlEditor;
this.cssEditor.destroy();
delete this.cssEditor;
},
});
</script>