### Node-RED Dashboard Developer Setup Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Commands to clone the Node-RED Dashboard repository, install dependencies, and prepare for development. ```bash cd ~\.node-red\node_modules git clone https://github.com/node-red/node-red-dashboard.git cd node-red-dashboard npm install ``` -------------------------------- ### Install Latest Version from GitHub Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Install the latest development version of node-red-dashboard directly from its GitHub repository using npm. ```bash npm i node-red/node-red-dashboard ``` -------------------------------- ### Install Node-RED Dashboard Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Install the stable version of node-red-dashboard via the Node-RED Manage palette or using npm. Restart Node-RED after installation. ```bash npm i node-red-dashboard ``` -------------------------------- ### Widget Resize Start Event Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Handles the start of a widget resize operation within a group. It resets the group width to maintain layout integrity. ```javascript var resizeGroupWidget = function(id) { var gridID = '#grid'+id; var grid = $(gridID+'.grid-stack').data('gridstack'); $(gridID+'.grid-stack').on('resizestart', function(event, ui) { // Reset group width grid.setColumn(tabDatas.groups[id].width, true); }); } ``` -------------------------------- ### Set Unique ID and Watch for Messages Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/locales/en-US/ui_template.html This example demonstrates setting a unique ID for a template element, applying a default theme color, and updating the element's content when a new message arrives. ```html
Some text
``` -------------------------------- ### Styling Notification Widget with CSS Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Applies custom styles to the notification widget using CSS classes. This example demonstrates how to override default styles for warning toasts. ```html ``` -------------------------------- ### Combine Configuration Properties Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Demonstrates how to combine multiple UI configuration properties within the settings.js file for comprehensive customization. ```javascript ui: { path: "ui", middleware: function (req, res, next) { console.log('LOGGED') next() }, ioMiddleware: function (socket, next) { console.log('HELLO') next() }, readOnly: true, defaultGroup: "Better Default" } ``` -------------------------------- ### Initialize Form Options Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_form.html Iterates through existing options and calls generateOption for each to populate the form. Also initializes the topic typed input. ```javascript for (var i=0; i
``` -------------------------------- ### Widget Drag Start Event Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Handles the start of a widget drag operation within a group. It resets the group width to ensure consistent behavior. ```javascript var dragGroupWidget = function(id) { var gridID = '#grid'+id; var grid = $(gridID+'.grid-stack').data('gridstack'); $(gridID+'.grid-stack').on('dragstart', function(event, ui) { // Reset group width grid.setColumn(tabDatas.groups[id].width, true); }); } ``` -------------------------------- ### Get Base Font Name Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Returns the name of the base font. ```javascript calculate_base_font: function(base) { return baseFontName; } ``` -------------------------------- ### Widget Placement and Grid Initialization Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Calculates widget positions and initializes the grid stack for a group. Handles auto-sizing widgets and determines placement points. ```javascript var widgets = groups[cnt].widgets; widgets.sort(compareOrder); var tbl = {}; for (var cnt2 = 0; cnt2 < widgets.length; cnt2++) { // Set default value when there is auto width if (widgets[cnt2].auto == true) { widgets[cnt2].width = groupWidth; // Adjust to the group width } else if (widgets[cnt2].width > groupWidth) { widgets[cnt2].width = groupWidth; } // Auto support if (widgets[cnt2].auto === true || widgets[cnt2].type === 'ui_form') { widgets[cnt2].height = getDefaultHeight(widgets[cnt2].id, groupWidth); } // Calculate coordinates to be placed var point = search_point(Number(widgets[cnt2].width), Number(widgets[cnt2].height), groupWidth, 256, tbl); if (point) { widgets[cnt2].x = point.x; widgets[cnt2].y = point.y; } } ``` -------------------------------- ### Display Icofont Icon in Template Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Example of displaying an Icofont icon using an tag within an HTML template, with custom styling. ```html
``` -------------------------------- ### Use Iconify Icons in HTML Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Example of using Iconify icons within an HTML span element. The 'iconify-' prefix is required. ```html ``` -------------------------------- ### Configure Text Input Class and Name Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text_input.html HTML for the 'Class' and 'Name' input fields in the node editor. ```html
``` -------------------------------- ### Include Iconify Library Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Add this script to a ui_template node to load the Iconify library for general use. ```html ``` -------------------------------- ### Fill Matrix Position Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Marks a rectangular area in the matrix (tbl) as occupied, starting from position (px, py) with the given dimensions (width, height). ```javascript function fill_matrix(px, py, width, height, maxWidth, tbl) { for (var y=py; y < py+height; y++) { for (var x=px; x < px+width; x++) { tbl[maxWidth*y+x] = 1; } } } ``` -------------------------------- ### Configure Widget Options Source: https://github.com/node-red/node-red-dashboard/wiki/Creating-New-Dashboard-Widgets Defines basic widget properties like inputs, outputs, icon, and label. The `oneditprepare` function is used to initialize UI elements for widget configuration, such as size and group selection. ```javascript inputs:1, outputs:1, icon: ICON, paletteLabel: NAME, label: function() { return this.name || NAME; }, oneditprepare: function() { $("#node-input-size").elementSizer({ width: "#node-input-width", height: "#node-input-height", group: "#node-input-group" }); }, oneditsave: function() { }, oneditresize: function(size) { } }; return conf; }; RED.nodes.registerType('ui_cal', mk_conf('cal')); ``` -------------------------------- ### Check Node Type for Layout Tool Support Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Determines if a given node type is supported by the dashboard layout tools. Only nodes starting with 'ui_' are considered. ```javascript function isLayoutToolSupported(nodeType) { if (nodeType.indexOf("ui_") !== 0) { return false; } else { return true; } } ``` -------------------------------- ### Create Prompts with ui_toast Source: https://context7.com/node-red/node-red-dashboard/llms.txt Use `ui_toast` to create prompt dialogs for user confirmation. The user's choice ('Confirm' or 'Abort') is returned to the flow. If the user cancels, no message is emitted. ```javascript // ── Prompt (returns user choice to output) ──────────────────────────────── // Node configured: position="prompt", ok="Confirm", cancel="Abort" msg.payload = "Delete all historical data?"; msg.topic = "Confirm Action"; return msg; // On OK: { payload: { msg: } } // On Cancel: nothing emitted ``` -------------------------------- ### Get Tab Data From Nodes Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Retrieves tab and group information from the Node-RED node set. This function is used to build the data structure for dashboard layout editing. ```javascript function getTabDataFromNodes(tabID) { var nodes = RED.nodes.createCompleteNodeSet(false); var tab = {}; // Tab information for (var cnt = 0; cnt < nodes.length; cnt++) { if (nodes[cnt].id == tabID) { if (nodes[cnt].type == "ui_tab" || nodes[cnt].type == "ui_link") { tab = { id: nodes[cnt].id, name: nodes[cnt].name, type: nodes[cnt].type, order: nodes[cnt].order, groups: [] }; break; } } } // Group information for (var cnt = 0; cnt < nodes.length; cnt++) { if (nodes[cnt].type == "ui_group" && nodes[cnt].tab == tabID) { var group = { id: nodes[cnt].id, name: nodes[cnt].name, type: nodes[cnt].type, order: nodes[cnt].order, width: nodes[cnt].width, widgets: [] }; tab.groups.push ``` -------------------------------- ### Configure Text Input Payload and Topic Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text_input.html HTML for configuring the payload and topic sent by the text input node. Includes a typed input for the topic. ```html
``` -------------------------------- ### Get Current UI Layout Structure Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Retrieves the current hierarchical structure of the UI, including tabs, groups, and the widgets within each group. This is useful for saving or serializing the dashboard layout. ```javascript function getCurrentList() { var currentList = []; var tabs = tabContainer.editableList('items'); var open = false; tabs.each(function(i,el) { var tabData = el.data('data'); var tab = []; var groups = el.find('.nr-db-sb-group-list').editableList('items'); groups.each(function(j,el) { var group = []; var groupData = el.data('data'); var widgets = el.find('.nr-db-sb-widget-list').editableList('items'); widgets.each(function(k,el) { var widgetData = el.data('data'); group.push(widgetData.id); }) tab.push({id:groupData.node.id, widgets:group}); }); currentList.push({id:tabData.node.id,groups:tab}); }); return currentList; } ``` -------------------------------- ### Initialize and Update Theme Settings Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Initializes the theme settings in the UI and handles updates when the theme is customized. It uses jQuery to interact with form elements and the ACE editor for theme configuration. ```javascript if (editor === undefined) { editor = RED.editor.createEditor({ id: 'nr-db-field-format-editor', mode: 'ace/mode/javascript', value: JSON.stringify({theme:globalDashboardNode.theme.themeState, site:globalDashboardNode.site}) }); RED.library.create({ url:"themes", // where to get the data from type:"theme", // the type of object the library is for editor: editor, // the field name the main text body goes to mode:"ace/mode/javascript", fields:['name'], elementPrefix:"ui-sidebar-" }); } editor.on('input', function() { // Check for any changes on the editor object // i.e. has the theme been customised compared // to what is stored var editorObject = JSON.parse(editor.getValue()); //Update theme object if necessary if (JSON.stringify(editorObject.theme) !== JSON.stringify(globalDashboardNode.theme.themeState)) { globalDashboardNode.theme.themeState = editorObject.theme; if ($("#ui-sidebar-name").val() !== globalDashboardNode.theme.customTheme.name) { globalDashboardNode.theme.customTheme.name = $("#ui-sidebar-name").val(); globalDashboardNode.theme.customTheme.baseColor = globalDashboardNode.theme.themeState["base-color"].value; setColourPickerColour("base-color", globalDashboardNode.theme.customTheme.baseColor); generateColours(globalDashboardNode.theme.themeState["base-color"].value); RED.nodes.dirty(true); } } if (JSON.stringify(aTheme) !== JSON.stringify(globalDashboardNode.theme.angularTheme)) { globalDashboardNode.theme.angularTheme = aTheme; } //Update site object if necessary if (JSON.stringify(editorObject.site) !== JSON.stringify(globalDashboardNode.site)) { globalDashboardNode.site = editorObject.site; $("#nr-db-field-title").val(globalDashboardNode.site.name); $("#nr-db-field-hideToolbar").val(globalDashboardNode.site.hideToolbar); $("#nr-db-field-allowSwipe").val(globalDashboardNode.site.allowSwipe); $("#nr-db-field-allowTempTheme").val(globalDashboardNode.site.allowTempTheme); $("#nr-db-field-dateFormat").val(globalDashboardNode.site.dateFormat); $("#nr-db-field-sx").val(globalDashboardNode.site.sizes.sx); $("#nr-db-field-sy").val(globalDashboardNode.site.sizes.sy); $("#nr-db-field-px").val(globalDashboardNode.site.sizes.px); $("#nr-db-field-py").val(globalDashboardNode.site.sizes.py); $("#nr-db-field-gx").val(globalDashboardNode.site.sizes.gx); $("#nr-db-field-gy").val(globalDashboardNode.site.sizes.gy); $("#nr-db-field-cx").val(globalDashboardNode.site.sizes.cx); $("#nr-db-field-cy").val(globalDashboardNode.site.sizes.cy); RED.nodes.dirty(true); } }); ``` -------------------------------- ### Get Default Widget Height Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Calculates the default height for various Node-RED Dashboard widget types based on the group's width. This is used for widgets with automatic sizing enabled. ```javascript function getDefaultHeight(nodeID, groupWidth) { var redNode = RED.nodes.node(nodeID); var height = 1; if (redNode.type === 'ui_gauge') { if (redNode.gtype === 'gage') { height = Math.round(groupWidth/2)+1; } else if (redNode.gtype === 'wave') { if (groupWidth < 3) { height = 1; } else { height = Math.round(groupWidth*0.75); } } else { // donut or compass if (groupWidth < 3) { height = 1; } else if (groupWidth < 11) { height = groupWidth - 1; } else { height = Math.round(groupWidth*0.95); } } } else if (redNode.type === 'ui_chart') { height = Math.floor(groupWidth/2)+1; } else if (redNode.type === 'ui_form') { // var optNum = redNode.options.length; // Sub widget number // if (redNode.label) { // height = optNum + 2; // Label and Button // } else { // height = optNum + 1; // Button only // } height = redNode.rowCount } else if (redNode.type === 'ui_lineargauge') { if (redNode.unit && redNode.name) { height = 5; } else { height = 4; } } else if (redNode.type === 'ui_list') { height = 5; } else if (redNode.type === 'ui_vega') { height = 5; } return height; } ``` -------------------------------- ### Justgage Gauge Configuration Source: https://github.com/node-red/node-red-dashboard/blob/master/config-fields.md Configure Justgage parameters for a gauge widget. Use this to customize pointer visibility, gauge width, and direction. ```json {"options":{"pointer":false,"gaugeWidthScale":1.5}} ``` ```json {"options":{"pointer":true,"gaugeWidthScale":0.4,"reverse":true}} ``` -------------------------------- ### Configure Text Input Mode and Delay Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text_input.html Provides a select dropdown for choosing the input mode (e.g., text, email, password) and a text input for setting the delay in milliseconds. ```html
``` -------------------------------- ### Dynamically Apply CSS Class Source: https://context7.com/node-red/node-red-dashboard/llms.txt Apply custom CSS classes to any widget by setting the `msg.className` property. Ensure the corresponding CSS rules are defined, for example, via a `ui_template` node. ```javascript // ── Dynamically apply a CSS class to any widget ─────────────────────────── msg.className = "alert highlight"; // With a head-injected style: // md-card.alert { border: 2px solid red; } // md-card.highlight button { font-weight: bold; } ``` -------------------------------- ### Configure Widget Sizing and Spacing Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Dynamically updates widget size and spacing parameters (sx, sy, cx, cy, px, py, gx, gy) based on user input. Ensures changes are saved to the Node-RED configuration. ```javascript $("#nr-db-field-sx").val(48).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.sx=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-sy").val(48).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.sy=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-cx").val(6).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.cx=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-cy").val(6).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.cy=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-px").val(0).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.px=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-py").val(0).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.py=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-gx").val(6).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.gx=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); $("#nr-db-field-gy").val(6).css("width","20%") .on("change", function() { globalDashboardNode.site.sizes.gy=Number($(this).val()); RED.nodes.dirty(true); }) .appendTo(divSetSizes); ``` -------------------------------- ### Clear Local Storage and AJAX Logout Source: https://github.com/node-red/node-red-dashboard/blob/master/src/logout.html Clears Node-RED specific items from local storage and attempts an AJAX GET request to the current page. If the request fails, it redirects to the base URL after a delay. ```javascript for (var key in localStorage) { if (localStorage.hasOwnProperty(key)) { if (key.indexOf("nr-") === 0) { localStorage.removeItem(key); } } } $.ajax({ type: "GET", url: window.location.href, async: true, username: "some_non_user_name", password: "a_not_valid_password" }) .done(function() { alert('Error!') }) .fail(function() { var url = window.location.href.split("logout")[0]; setTimeout(function() { window.location.href = url; }, 1000); }); ``` -------------------------------- ### ui_toast - Notifications and Dialogs Source: https://context7.com/node-red/node-red-dashboard/llms.txt Demonstrates various ways to use the ui_toast node to display temporary notifications, modal dialogs, and prompts to the user. It covers basic messages, styled messages with custom CSS, modal alerts, and interactive prompts that return user input. ```APIDOC ## ui_toast ### Description Displays toast notifications, modal alert dialogs, or prompt dialogs. Prompts return the user's choice to the flow. Notifications can be styled via CSS class names and targeted to individual clients. ### Usage Examples #### Basic Toast Notification ```javascript msg.payload = "File saved successfully"; msg.topic = "✓ Success"; return msg; ``` #### Toast with Custom Styling ```javascript msg.payload = "High temperature warning!"; msg.topic = "⚠ Warning"; msg.highlight = "darkorange"; msg.className = "warn-toast"; return msg; ``` #### Modal Dialog (OK Button) ```javascript msg.payload = "Firmware update complete. Please restart."; msg.topic = "System Notice"; return msg; ``` #### Prompt Dialog (Confirm/Abort) ```javascript msg.payload = "Delete all historical data?"; msg.topic = "Confirm Action"; return msg; // On OK: { payload: { msg: } } // On Cancel: nothing emitted ``` #### Targeting a Specific Client ```javascript msg.payload = "Your timer has expired"; msg.socketid = "zXq8k..."; // from ui_ui_control connect event msg.timeout = 0; // 0 = permanent until dismissed return msg; ``` ``` -------------------------------- ### Formatting Gauge Value with Angular Filter Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/locales/en-US/ui_gauge.html Use Angular filters within the 'Value Format' field to format the displayed gauge value. For example, `{{value | number:1}}%` rounds the value to one decimal place and appends a percentage sign. ```HTML {{value | number:1}}% ``` -------------------------------- ### Load TinyColor Library Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Dynamically loads the TinyColor JavaScript library. It attempts to load from a local path first and falls back to a vendor path if the initial load fails. ```javascript var loadTinyColor = function(path) { $.ajax({ url: path, success: function (data) { var jsScript = document.createElement("script"); jsScript.type = "application/javascript"; jsScript.src = path; document.body.appendChild(jsScript); //console.log('Tiny Color Loaded:',path); }, error: function (xhr, ajaxOptions, thrownError) { if (xhr.status === 404 && !attemptedVendorLoad) { loadTinyColor('/'+uip+'/vendor/tinycolor2/dist/tinycolor-min.js'); attemptedVendorLoad = true; } //console.log('Tiny Color Failed to load:',path); } }); } // Try to load dist version first // then if fails, load non dist version loadTinyColor('ui_base/js/tinycolor-min.js'); ``` -------------------------------- ### Text Input Delay Tip Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text_input.html Provides a tip regarding the 'Delay' setting for the text input node, explaining its behavior when set to 0. ```html
Setting Delay to 0 waits for Enter or Tab key, to send input.
``` -------------------------------- ### Lint and Check JS Styles Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Run Gulp tasks to check code quality and JavaScript style consistency. ```bash gulp lint gulp jscs ``` -------------------------------- ### Configure ui_form with Fields and Pre-fill Values Source: https://context7.com/node-red/node-red-dashboard/llms.txt Defines the structure of a multi-field form and pre-fills its values. The form submits all field values as a single object keyed by the field's 'value' property. ```javascript // Form configured with three fields: // [ // { value: "name", label: "Full Name", type: "text", required: true }, // { value: "email", label: "Email", type: "email", required: true }, // { value: "age", label: "Age", type: "number", required: false }, // { value: "notes", label: "Notes", type: "multiline", rows: 3 } // ] // Pre-fill form fields: msg.payload = { name: "Alice Smith", email: "alice@example.com", age: 30 }; return msg; // Output on submit: // { payload: { name: "Alice Smith", email: "alice@example.com", age: 30, notes: "" } } // Output on cancel: // { payload: {} } ``` -------------------------------- ### Rebuild Dashboard Files with Gulp Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Use Gulp to update and rebuild minified files and the appcache manifest after making changes to the front-end code. ```bash gulp ``` -------------------------------- ### Serve Custom Icofont CSS Locally Source: https://github.com/node-red/node-red-dashboard/blob/master/README.md Link to a locally served Icofont CSS file within a ui_template node's header. ```html ``` -------------------------------- ### Type Initialization for Custom Widget Source: https://github.com/node-red/node-red-dashboard/wiki/Creating-New-Dashboard-Widgets Initializes the configuration for a custom widget type in Node-RED. This includes setting the category, color, default properties, and validation logic for widget dimensions. ```javascript function mk_conf(NAME) { var ICON = "icon.png"; var conf = { category: 'dashboard', color: 'rgb( 63, 173, 181)', defaults: { group: {type: 'ui_group', required:false}, name: {value: ''}, order: {value: 0}, width: { value: 0, validate: function(v) { var valid = true var width = v||0; var currentGroup = $('#node-input-group').val()|| this.group; var groupNode = RED.nodes.node(currentGroup); valid = !groupNode || +width <= +groupNode.width; $("#node-input-size").toggleClass("input-error",!valid); return valid; }}, height: {value: 0} }, ``` -------------------------------- ### Configure Text Input Pass-through and Send on Blur Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text_input.html HTML for checkboxes controlling whether messages arriving on the input are passed through to the output and whether the value is sent when the input loses focus. ```html
``` -------------------------------- ### UI Text Node Configuration Form Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_text.html HTML structure for the configuration form of the ui_text node, including input fields for group, size, label, format, layout, and styling. ```html
label value
Note: checking Accept raw HTML/JavaScript can allow injection of code. Ensure the input comes from trusted sources.
``` -------------------------------- ### Dropdown Options Format Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/locales/en-US/ui_dropdown.html Configure dropdown options using an array of strings or objects. If only strings are provided, the value and label are the same. Objects allow separate labels and values. ```javascript [ "Choice 1", "Choice 2", {"Choice 3":"3"} ] ``` -------------------------------- ### Configure X-Axis Format Input Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_chart.html Sets up the input options for the X-axis format, including predefined formats and a custom option. This is used to control how time-series data is displayed on the chart's x-axis. ```javascript var odef = {value: "", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.custom"), icon: "fa fa-cog"}; var ohms = {value: "time", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.time"), hasValue: false}; var ohm = {value: "hours", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.hours"), hasValue: false}; var oahm = {value: "minutes", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.minutes"), hasValue: false}; var odm = {value: "days", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.days"), hasValue: false}; var oymd = {value: "ymd", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.ymd"), hasValue: false}; var ocus = {value: "custom", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.custom"), icon: "red/images/typedInput/az.png"}; var oaut = {value: "auto", label: RED._("node-red-dashboard/ui_chart:ui_chart.label.automatic"), hasValue: false}; $("#node-input-xformat").typedInput({ default: odef, types:[ ohms, ohm, oahm, odm, oymd, ocus, oaut ] }); ``` -------------------------------- ### HTML for Node Setting UI Source: https://github.com/node-red/node-red-dashboard/wiki/Creating-New-Dashboard-Widgets Defines the default parameters for a widget's setting UI, including group, size, and name. This HTML fragment is used in the Node-RED editor for configuring custom widgets. ```html ``` -------------------------------- ### Configure Node-RED Dashboard Settings Source: https://context7.com/node-red/node-red-dashboard/llms.txt Customize global dashboard behavior, including URL path, HTTP and WebSocket middleware, read-only mode, and default group settings. Basic authentication can also be configured. ```javascript // ~/.node-red/settings.js module.exports = { // Default dashboard URL: http://localhost:1880/ui ui: { path: "ui", // Change URL to /ui // Express middleware for HTTP requests middleware: function (req, res, next) { if (!req.headers['x-custom-token']) { return res.status(401).send('Unauthorized'); } next(); }, // Socket.io middleware for WebSocket connections // Note: setting ioMiddleware disables the default CORS check ioMiddleware: [ function (socket, next) { console.log('Client connected:', socket.handshake.address); next(); } ], readOnly: false, // true = ignore all dashboard inputs defaultGroup: "Default" // i18n default group name }, // Secure dashboard with basic auth (use bcrypt hash for password) httpNodeAuth: { user: "admin", pass: "$2b$08$ները" } } ``` -------------------------------- ### Add Tab or Link Item Source: https://github.com/node-red/node-red-dashboard/blob/master/nodes/ui_base.html Handles the creation and addition of new 'ui_tab' or 'ui_link' items to the dashboard. It ensures the dashboard node is available, creates a default item if necessary, assigns an ID and order, adds it to the Node-RED registry, and updates the UI. It also handles updating configuration node users. ```javascript var addTabOrLinkItem = function(container,i,item) { ensureDashboardNode(true); // create node if needed if (!item.node) { var defaultItem = { 'ui_tab': { _def: RED.nodes.getType('ui_tab'), type: 'ui_tab', users: [], icon: 'dashboard', name: 'Tab' }, 'ui_link': { _def: RED.nodes.getType('ui_link'), type: 'ui_link', users: [], icon: 'open_in_browser', name: 'Link', target: 'newtab' } } item.node = defaultItem[item.type] item.node.id = RED.nodes.id() item.node.order = i+1 item.node.name += ' '+item.node.order listElements[item.node.id] = container; if (item.type === 'ui_tab') { item.groups = [] } RED.nodes.add(item.node); RED.editor.validateNode(item.node); RED.history.push({ t:'add', nodes:[item.node.id], dirty:RED.nodes.dirty() }); RED.nodes.dirty(true); } else if (item.type === undefined) { item.type = item.node.type } listElements[item.node.id] = container; if (RED.nodes.hasOwnProperty('updateConfigNodeUsers')) { RED.nodes.updateConfigNodeUsers(item.node); } // title var titleRow = $('
',{class:"nr-db-sb-list-header nr-db-sb-tab-list-header"}).appendTo(container); switch (item.type) { case 'ui_tab': { container.addClass("nr-db-sb-tab-list-item"); $('').appendTo(titleRow); var chevron = $('',{style:"width:10px;"}).appendTo(titleRow); var tabicon = "fa-object-group"; //var tabicon = item.node.disabled ? "fa-window-close-o" : item.node.hidden ? "fa-eye-slash" : "fa-object-group"; $('',{class:"nr-db-sb-icon nr-db-sb-tab-icon fa "+tabicon}).appendTo(titleRow); var tabhide = item.node.hidden ? " nr-db-sb-title-hidden" : ""; var tabable = item.node.disabled ? " nr-db-sb-title-disabled" : ""; $('',{class:"nr-db-sb-title"+tabhide+tabable}).text(item.node.name||"").appendTo(titleRow); break; } case 'ui_link': { $('').appendTo(titleRow); var title = $('