UNPKG

@5minds/node-red-dashboard-2-processcube-dynamic-table

Version:
418 lines (376 loc) 19.4 kB
<script type="text/javascript"> (function () { function hasProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } RED.nodes.registerType('ui-dynamic-table', { category: 'ProcessCube UI', color: '#00aed7', defaults: { name: { value: '' }, tableName: { value: '' }, group: { type: 'ui-group', required: true }, order: { value: 1 }, data: { value: 'payload' }, data_type: { value: 'msg' }, options: { value: [{ label: '', label_type: 'str', condition: '' }], validate: function (v) { const unique = new Set( v.map(function (o) { return o.label; }) ); return v.length === unique.size; }, }, columns: { value: [{ value: '', label: '' }], validate: function (v) { const unique = new Set( v.map(function (o) { return o.value; }) ); return v.length === unique.size; }, }, 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 <= +groupNode.width; $('#node-input-size').toggleClass('input-error', !valid); return valid; }, }, height: { value: 0 }, outputs: { value: 1 }, title_text: { value: '' }, title_style: { value: 'default' }, title_custom_text_styling: { value: '' }, title_icon: { value: '' }, }, inputs: 1, outputs: 1, outputLabels: function (index) { return this.options[index].label; }, icon: 'ui_dynamic_table.svg', paletteLbel: 'file', label: function () { return this.name || 'dynamic-table'; }, oneditprepare: function () { $('#node-input-size').elementSizer({ width: '#node-input-width', height: '#node-input-height', group: '#node-input-group', }); $('#node-input-title_style').typedInput({ types: [ { value: 'default', label: 'Default', hasValue: false, }, { value: 'minimal', label: 'Minimal', hasValue: false, }, { value: 'outside', label: 'Outside of card', hasValue: false, }, ], }); function generateOption(i, option) { const container = $('<li/>', { style: 'background: var(--red-ui-secondary-background, #fff); margin:0; padding:8px 0px 0px;', }); // Create input fields for value and label const row = $('<div/>').appendTo(container); $('<input/>', { class: 'node-input-option-label', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: 'Label', value: option.label, }) .appendTo(row) .typedInput({ default: option.label_type || 'str', types: [ 'msg', 'str', 'jsonata', { value: 'row', label: 'row.', hasValue: true, }, ], }); // Set the typed input value and type const labelInput = row.find('.node-input-option-label'); if (option.label_type) { labelInput.typedInput('type', option.label_type); } if (option.label) { labelInput.typedInput('value', option.label); } $('<input/>', { class: 'node-input-option-condition', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: 'Condition', value: option.condition, }) .appendTo(row) .typedInput({ type: 'str', types: ['str'], }); // Create delete button for the option const finalSpan = $('<span/>', { style: 'float:right; margin-right:8px;', }).appendTo(row); const deleteButton = $('<a/>', { href: '#', class: 'editor-button editor-button-small', style: 'margin-top:7px; margin-left:5px;', }).appendTo(finalSpan); $('<i/>', { class: 'fa fa-remove' }).appendTo(deleteButton); deleteButton.click(function () { container.css({ background: 'var(--red-ui-secondary-background-inactive, #fee)', }); container.fadeOut(300, function () { $(this).remove(); }); }); $('#node-input-option-container').append(container); } function generateColumn(i, column) { const container = $('<li/>', { style: 'background: var(--red-ui-secondary-background, #fff); margin:0; padding:8px 0px 0px;', }); // Create input fields for value and label const row = $('<div/>').appendTo(container); $('<input/>', { class: 'node-input-column-value', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: 'Value', value: column.value, }) .appendTo(row) .typedInput({ default: column.type || 'str', types: ['str'] }); $('<input/>', { class: 'node-input-column-label', type: 'text', style: 'margin-left:7px; width:calc(50% - 32px);', placeholder: 'Label', value: column.label, }) .appendTo(row) .typedInput({ type: 'str', types: ['str'], }); // Create delete button for the column const finalSpan = $('<span/>', { style: 'float:right; margin-right:8px;', }).appendTo(row); const deleteButton = $('<a/>', { href: '#', class: 'editor-button editor-button-small', style: 'margin-top:7px; margin-left:5px;', }).appendTo(finalSpan); $('<i/>', { class: 'fa fa-remove' }).appendTo(deleteButton); deleteButton.click(function () { container.css({ background: 'var(--red-ui-secondary-background-inactive, #fee)', }); container.fadeOut(300, function () { $(this).remove(); }); }); $('#node-input-column-container').append(container); } $('#node-input-add-column').click(function () { generateColumn($('#node-input-column-container').children().length + 1, {}); $('#node-input-column-container-div').scrollTop( $('#node-input-column-container-div').get(0).scrollHeight ); }); for (let i = 0; i < this.columns.length; i++) { const column = this.columns[i]; generateColumn(i + 1, column); } $('#node-input-column-container').sortable({ axis: 'y', handle: '.node-input-column-handle', cursor: 'move', }); $('#node-input-add-option').click(function () { generateOption($('#node-input-option-container').children().length + 1, {}); $('#node-input-option-container-div').scrollTop( $('#node-input-option-container-div').get(0).scrollHeight ); }); for (let i = 0; i < this.options.length; i++) { const option = this.options[i]; generateOption(i + 1, option); } $('#node-input-option-container').sortable({ axis: 'y', handle: '.node-input-option-handle', cursor: 'move', }); $('#node-input-data').typedInput({ default: 'msg', types: ['msg', 'json', 'flow', 'global'], }); $('#node-input-data').typedInput('value', this.data); $('#node-input-data').typedInput('type', this.data_type); }, oneditsave: function () { const options = $('#node-input-option-container').children(); const node = this; node.options = []; options.each(function (i) { const option = $(this); const o = { label: option.find('.node-input-option-label').typedInput('value'), label_type: option.find('.node-input-option-label').typedInput('type'), condition: option.find('.node-input-option-condition').val(), }; node.options.push(o); }); const columns = $('#node-input-column-container').children(); node.columns = []; columns.each(function (i) { const column = $(this); const c = { label: column.find('.node-input-column-label').val(), value: column.find('.node-input-column-value').typedInput('value'), type: column.find('.node-input-column-value').typedInput('type'), }; if (column.find('.node-input-column-value').typedInput('type') === 'num') { c.value = Number(c.value); } if (column.find('.node-input-column-value').typedInput('type') === 'bool') { c.value = c.value === 'true'; } node.columns.push(c); }); this.outputs = node.options.length || 1; (this.data = $('#node-input-data').typedInput('value')), (this.data_type = $('#node-input-data').typedInput('type')); }, }); })(); </script> <script type="text/html" data-template-name="ui-dynamic-table"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Name"> </div> <div class="form-row"> <label for="node-input-tableName"><i class="fa fa-tag"></i> Table name</label> <input type="text" id="node-input-tableName" placeholder="My Table"> </div> <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> <span data-i18n="ui-dynamic-table.label.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-data"><i class="fa fa-tag"></i> Data</label> <input type="text" id="node-input-data" placeholder="Data"> </div> <div class="form-row form-row-flex node-input-option-container-row" style="margin-bottom: 0px;width: 100%"> <label for="node-input-width" style="vertical-align:top"><i class="fa fa-list-alt"></i> Actions</label> <div id="node-input-option-container-div" style="box-sizing:border-box; border-radius:5px; height:257px; padding:5px; border:1px solid var(--red-ui-form-input-border-color, #ccc); overflow-y:scroll; display:inline-block; width: 70%;"> <span id="valWarning" style="color: var(--red-ui-text-color-error, #910000)"><b>All Values must be unique.</b></span> <ol id="node-input-option-container" style="list-style-type:none; margin:0;"></ol> </div> <a data-html="true" title="Dynamic Property: Send 'msg.options' in order to override this property." 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> <!-- Add Option Button --> <div class="form-row"> <a href="#" class="editor-button editor-button-small" id="node-input-add-option" style="margin-top:4px; margin-left:103px;"><i class="fa fa-plus"></i> <span>action</span></a> </div> <div class="form-row form-row-flex node-input-column-container-row" style="margin-bottom: 0px;width: 100%"> <label for="node-input-width" style="vertical-align:top"><i class="fa fa-list-alt"></i> Columns</label> <div id="node-input-column-container-div" style="box-sizing:border-box; border-radius:5px; height:257px; padding:5px; border:1px solid var(--red-ui-form-input-border-color, #ccc); overflow-y:scroll; display:inline-block; width: 70%;"> <span id="valWarning" style="color: var(--red-ui-text-color-error, #910000)"><b>All Values must be unique.</b></span> <ol id="node-input-column-container" style="list-style-type:none; margin:0;"></ol> </div> <a data-html="true" title="Dynamic Property: Send 'msg.columns' in order to override this property." 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> <!-- Add Column Button --> <div class="form-row"> <a href="#" class="editor-button editor-button-small" id="node-input-add-column" style="margin-top:4px; margin-left:103px;"><i class="fa fa-plus"></i> <span>column</span></a> </div> <hr /> <h4>Title Configuration</h4> <div class="form-row"> <label for="node-input-title_text"><i class="fa fa-hand"></i>Title text</label> <input type="text" id="node-input-title_text" title="Enter the text to show as a title."> </div> <div class="form-row"> <label for="node-input-title_style"><i class="fa fa-hand"></i>Style</label> <input type="text" id="node-input-title_style" title="Select the base styling layout for your title."> </div> <div class="form-row"> <label for="node-input-title_custom_text_styling"><i class="fa fa-hand"></i>Custom text styling</label> <input type="text" id="node-input-title_custom_text_styling" title="Use CSS properties like font-size, color or padding to influence the appearance of the title"> </div> <div class="form-row"> <label for="node-input-title_icon"><i class="fa fa-hand"></i>Title icon</label> <input type="text" id="node-input-title_icon" title="Enter an URL to fetch an icon from. Use a dataurl for images, that are not available online. This value will be used as a HTML <img>'s src value."> </div> <hr /> </script> <script type="text/markdown" data-help-name="ui-dynamic-table"> A Node to dynamicly display arrays of data in a table with actions for every row. ## Actions Define a label for the action button that is going be displayed and a condition for when it should be displayed. Inside the condition you have access to every key from the current row. ### Inputs : Table name (string) : The name of the table. : Group (string) : The groud in which the Component is rendered. : Size (string) : The size of the table within the group. : Data (string) : The property of msg.payload from where the table data is sourced. : Actions (string) : The actions of each row. Each action corresponds to an output of the node. : Columns (string) : The columns of the table. Must correspond to a key of the data property. ### Outputs The outputs are generated dynamicly based on the actions of the table. ### Details `msg.payload` is used as the base for the data form there on the data source can be specified further with the `data` input field. ### Referece [https://processcube.io/docs/solutions/node-red](https://processcube.io/docs/solutions/node-red) </script>