UNPKG

@cgjgh/node-red-dashboard-2-ui-slide-confirm

Version:

A Slide to Confirm node for preventing accidental user actions in Node-RED Dashboard 2.0

290 lines (281 loc) 13.5 kB
<script type="text/javascript"> (function () { function hasProperty (obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop) } function getWidgetsInGroup (nodeGroup, nodeId) { const uiNodesInGroup = [] RED.nodes.eachNode(function (n) { if (/^ui-/.test(n.type) && n.group && n.group === nodeGroup && n.id !== nodeId) { uiNodesInGroup.push(n) } }) return uiNodesInGroup } function generateWidgetTable (node, group = null) { const nodeGroup = group !== null ? group : node.group const widgets = getWidgetsInGroup(nodeGroup, node.id) let widgetListHtml = '<table class="widget-table"><thead><tr><th>Type</th><th>Name</th><th>Include</th></tr></thead><tbody>' widgets.forEach(widget => { const isChecked = node.controlledWidgets.includes(widget.id) ? 'checked' : '' widgetListHtml += `<tr><td>${widget.type}</td><td>${widget.name}</td><td><input type="checkbox" name="widget" value="${widget.id}" ${isChecked}></td></tr>` }) widgetListHtml += '</tbody></table>' $('#node-input-controlledWidgets-container').html(widgetListHtml) } RED.nodes.registerType('ui-slide-confirm', { category: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.label.category'), color: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.colors.dark'), defaults: { group: { type: 'ui-group', required: true }, name: { value: '' }, label: { value: 'slide-confirm' }, order: { value: 0 }, width: { value: 0, validate: function (v) { const width = v || 0 const currentGroup = $('#node-input-group').val() || this.group const groupNode = RED.nodes.node(currentGroup) const valid = !groupNode || +width >= 0 $('#node-input-size').toggleClass('input-error', !valid) return valid } }, height: { value: 0 }, passthru: { value: false }, topic: { value: 'topic', validate: (hasProperty(RED.validators, 'typedInput') ? RED.validators.typedInput('topicType') : function (v) { return true }) }, topicType: { value: 'msg' }, className: { value: '' }, sliderHeight: { value: 50 }, textSize: { value: 24 }, iconSuccess: { value: 'mdi-check' }, text: { value: 'slide to confirm' }, successText: { value: 'confirmed' }, circle: { value: true }, animate: { value: true }, timeout: { value: 10 }, controlledWidgets: { value: [] } }, inputs: 1, outputs: 1, outputLabels: function () { return 'result' }, icon: 'font-awesome/fa-check-circle-o', paletteLabel: 'slide confirm', label: function () { return this.name || (~this.label.indexOf('{' + '{') ? null : this.label) || 'slide-confirm' }, labelStyle: function () { return this.name ? 'node_label_italic' : '' }, oneditprepare: function () { if (RED.nodes.subflow(this.z)) { $('#node-input-width').attr('type', 'text') $('#node-input-height').attr('type', 'text') $('div.form-row.nr-db-ui-element-sizer-row').hide() $('div.form-row.nr-db-ui-manual-size-row').show() } else { $('div.form-row.nr-db-ui-element-sizer-row').show() $('div.form-row.nr-db-ui-manual-size-row').hide() $('#node-input-size').elementSizer({ width: '#node-input-width', height: '#node-input-height', group: '#node-input-group' }) } $('#node-input-topic').typedInput({ default: 'str', typeField: $('#node-input-topicType'), types: ['str', 'msg', 'flow', 'global'] }) $('.ui-node-popover-title').tooltip({ show: { effect: 'slideDown', delay: 150 } }) const node = this if (!node.controlledWidgets) { node.controlledWidgets = [] } generateWidgetTable(node) $('#node-input-group').on('change', function () { generateWidgetTable(node, $(this).val()) }) }, oneditsave: function () { const node = this node.controlledWidgets = [] $('input[name="widget"]:checked').each(function () { const o = $(this).val() node.controlledWidgets.push(o) }) } }) })() </script> <script type="text/html" data-template-name="ui-slide-confirm"> <div class="form-row"> <label for="node-input-name"> <i class="fa fa-tag"></i> <span data-i18n="ui-slide-confirm.label.name"></span> </label> <input type="text" id="node-input-name"> <input type="hidden" id="node-input-topicType"> </div> <div class="ui-slide-confirm"> <div class="form-row"> <label for="node-input-group"> <i class="fa fa-table"></i> <span data-i18n="ui-slide-confirm.label.group"></span> </label> <input type="text" id="node-input-group"> </div> <div class="form-row nr-db-ui-element-sizer-row"> <label> <i class="fa fa-object-group"></i> <span data-i18n="ui-slide-confirm.label.size"></span> </label> <button class="editor-button" id="node-input-size"></button> </div> <div class="form-row nr-db-ui-manual-size-row"> <label> <i class="fa fa-arrows-h"></i> <span data-i18n="ui-slide-confirm.label.width"></span> </label> <input type="hidden" id="node-input-width"> </div> <div class="form-row nr-db-ui-manual-size-row"> <label> <i class="fa fa-arrows-v"></i> <span data-i18n="ui-slide-confirm.label.height"></span> </label> <input type="hidden" id="node-input-height"> </div> <div class="form-row"> <label for="node-input-className"> <i class="fa fa-code"></i> <span data-i18n="ui-slide-confirm.label.class"></span> </label> <div style="display: inline;"> <input style="width: 70%;" type="text" id="node-input-className" placeholder="Optional CSS class name(s)"> <a data-html="true" title="Dynamic Property: Send msg.class to append new classes to this widget. NOTE: classes set at runtime will be applied in addition to any class(es) set in the node's class field." class="red-ui-button ui-node-popover-title" style="margin-left: 4px; cursor: help; font-size: 0.625rem; border-radius: 50%; width: 24px; height: 24px; display: inline-flex; justify-content: center; align-items: center;"> <i style="font-family: ui-serif;">fx</i> </a> </div> </div> <div class="form-row"> <label for="node-input-label"> <i class="fa fa-font"></i> <span data-i18n="ui-slide-confirm.label.label"></span> </label> <input type="text" id="node-input-label"> </div> <div class="form-row"> <label for="node-input-sliderHeight"> <i class="fa fa-text-height"></i> <span data-i18n="ui-slide-confirm.label.sliderHeight"></span> </label> <input type="number" min="0" max="100" id="node-input-sliderHeight"> </div> <div class="form-row"> <label for="node-input-textSize"> <i class="fa fa-text-height"></i> <span data-i18n="ui-slide-confirm.label.textSize"></span> </label> <input type="number" min="10" max="48" id="node-input-textSize"> </div> <div class="form-row"> <label for="node-input-iconSuccess"> <i class="fa fa-check-circle-o"></i> <span data-i18n="ui-slide-confirm.label.iconSuccess"></span> </label> <input type="text" id="node-input-iconSuccess"> </div> <div class="form-row"> <label for="node-input-text"> <i class="fa fa-font"></i> <span data-i18n="ui-slide-confirm.label.text"></span> </label> <input type="text" id="node-input-text"> </div> <div class="form-row"> <label for="node-input-successText"> <i class="fa"></i> <span data-i18n="ui-slide-confirm.label.successText"></span> </label> <input type="text" id="node-input-successText"> </div> <div class="form-row"> <label for="node-input-timeout"> <i class="fa fa-hourglass-end"></i> <span data-i18n="ui-slide-confirm.label.timeout"></span> </label> <input type="number" min="0" max="60" id="node-input-timeout"> </div> <div class="form-row"> <label for="node-input-topic" style="padding-left:25px; margin-right:-25px"> <span data-i18n="ui-slide-confirm.label.topic"></span> </label> <input type="text" id="node-input-topic"> </div> <div class="form-row"> <label for="node-input-circle"> <i class="fa fa-circle"></i> <span data-i18n="ui-slide-confirm.label.circle"></span> </label> <input type="checkbox" id="node-input-circle" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row"> <label for="node-input-animate"> <i class="fa fa-play-circle-o"></i> <span data-i18n="ui-slide-confirm.label.animate"></span> </label> <input type="checkbox" id="node-input-animate" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row" style="margin-bottom: 2px;"> <h3 style="margin-bottom: 2px;"> <span data-i18n="ui-slide-confirm.label.controlledWidgetsHeader"></span> </h3> </div> <div class="form-row" style="margin-bottom: 2px;"> <span data-i18n="ui-slide-confirm.label.controlledWidgetsFromCurrentGroup"></span> </div> <div class="form-row widget-container widget-table" id="node-input-controlledWidgets-container"></div> </div> </script> <style id="nr-db2-ui-slide-confirm-styles"> .red-ui-editor div.ui-slide-confirm .form-row { display: flex; align-items: center; } .red-ui-editor div.ui-slide-confirm .form-row label { margin-bottom: 0; } .red-ui-editor div.ui-slide-confirm .widget-container { width: 100%; box-sizing: border-box; /* Ensures padding and border are included in the element's total width */ } .red-ui-editor .widget-table { width: 100%; border-collapse: collapse; /* Ensures there are no gaps between the table cells */ } .red-ui-editor .widget-table th, .red-ui-editor .widget-table td { padding: 8px; border: 1px solid #ddd; /* Adds a border to table cells */ text-align: left; /* Aligns text to the left */ } .red-ui-editor .widget-table td { width: calc(33.333% - 8px); /* Distributes the width evenly among the first two columns */ } .red-ui-editor .widget-table td:last-child { width: 1%; /* Sets the checkbox column width to fit its content */ white-space: nowrap; /* Prevents wrapping of checkbox content */ } </style>