From 5633c5224e7da4dc94b64862653b998deb497cd1 Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Tue, 29 Mar 2022 20:59:35 +0100 Subject: [PATCH] Add system info UI --- Gruntfile.js | 1 + .../@node-red/editor-client/src/js/red.js | 1 + .../editor-client/src/js/ui/diagnostics.js | 61 +++++++++++++ .../editor-client/src/js/ui/editors/json.js | 89 ++++++++++++------- .../editor-client/src/sass/editor.scss | 8 ++ .../@node-red/runtime/lib/api/settings.js | 7 ++ 6 files changed, 136 insertions(+), 31 deletions(-) create mode 100644 packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js diff --git a/Gruntfile.js b/Gruntfile.js index f1f0aaefd..979b38051 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -165,6 +165,7 @@ module.exports = function(grunt) { "packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js", "packages/node_modules/@node-red/editor-client/src/js/ui/actions.js", "packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js", + "packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js", "packages/node_modules/@node-red/editor-client/src/js/ui/diff.js", "packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js", "packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js", diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js index 046fec988..dc36e5c1e 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/red.js +++ b/packages/node_modules/@node-red/editor-client/src/js/red.js @@ -730,6 +730,7 @@ var RED = (function() { RED.search.init(); RED.actionList.init(); RED.editor.init(); + RED.diagnostics.init(); RED.diff.init(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js b/packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js new file mode 100644 index 000000000..89bd093c4 --- /dev/null +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/diagnostics.js @@ -0,0 +1,61 @@ + +RED.diagnostics = (function () { + + function init() { + if (RED.settings.get('diagnostics.ui', true) === false) { + return; + } + RED.actions.add("core:show-system-info", function () { show(); }); + } + + function show() { + $.ajax({ + headers: { + "Accept": "application/json" + }, + cache: false, + url: 'diagnostics', + success: function (data) { + var json = JSON.stringify(data || {}, "", 4); + if (json === "{}") { + json = "{\n\n}"; + } + RED.editor.editJSON({ + title: "System Info", //RED._('sidebar.project.editDependencies'), + value: json, + requireValid: true, + readOnly: true, + jsonButtons: [ + { + text: 'Copy', + icon: 'fa fa-copy', + click: function () { + RED.clipboard.copyText(json, $(this), "Copied to clipboard") + } + }, + { + text: 'Download', + icon: 'fa fa-download', + click: function () { + var element = document.createElement('a'); + element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(json)); + element.setAttribute('download', "system-info.json"); + element.style.display = 'none'; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + } + }, + ] + }); + }, + error: function (jqXHR, textStatus, errorThrown) { + console.log("Unexpected error loading system info:", jqXHR.status, textStatus, errorThrown); + } + }); + } + + return { + init: init, + }; +})(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js index 52ab820ac..7687abee5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/json.js @@ -34,7 +34,7 @@ var activeTab; - function insertNewItem(parent,index,copyIndex) { + function insertNewItem(parent,index,copyIndex,readOnly) { var newValue = ""; if (parent.children.length > 0) { @@ -60,26 +60,26 @@ newKey = keyRoot+"-"+(keySuffix++); } } - var newItem = handleItem(newKey,newValue,parent.depth+1,parent); + var newItem = handleItem(newKey,newValue,parent.depth+1,parent,readOnly); parent.treeList.insertChildAt(newItem, index, true); parent.treeList.expand(); } - function showObjectMenu(button,item) { + function showObjectMenu(button,item,readOnly) { var elementPos = button.offset(); var options = []; if (item.parent) { options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){ var index = item.parent.children.indexOf(item); - insertNewItem(item.parent,index,index); + insertNewItem(item.parent,index,index,readOnly); }}); options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){ var index = item.parent.children.indexOf(item)+1; - insertNewItem(item.parent,index,index-1); + insertNewItem(item.parent,index,index-1,readOnly); }}); } if (item.type === 'array' || item.type === 'object') { options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){ - insertNewItem(item,item.children.length,item.children.length-1); + insertNewItem(item,item.children.length,item.children.length-1,readOnly); }}); } if (item.parent) { @@ -121,7 +121,7 @@ newKey = keyRoot+"-"+(keySuffix++); } } - var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent); + var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent,readOnly); var index = item.parent.children.indexOf(item)+1; item.parent.treeList.insertChildAt(newItem, index, true); @@ -171,24 +171,24 @@ menuOptionMenu.show(); } - function parseObject(obj,depth,parent) { + function parseObject(obj,depth,parent,readOnly) { var result = []; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { - result.push(handleItem(prop,obj[prop],depth,parent)); + result.push(handleItem(prop,obj[prop],depth,parent,readOnly)); } } return result; } - function parseArray(obj,depth,parent) { + function parseArray(obj,depth,parent,readOnly) { var result = []; var l = obj.length; for (var i=0;i'); if (key != null) { @@ -204,11 +204,14 @@ if (parent && parent.type === "array") { keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key") } - + if(readOnly) { + keyLabel.addClass("readonly") + } keyLabel.on("click", function(evt) { if (item.parent.type === 'array') { return; } + if (readOnly) { return; } evt.preventDefault(); evt.stopPropagation(); var w = Math.max(150,keyLabel.width()); @@ -253,10 +256,10 @@ item.expanded = depth < 2; item.type = "array"; item.deferBuild = depth >= 2; - item.children = parseArray(val,depth+1,item); + item.children = parseArray(val,depth+1,item,readOnly); } else if (val !== null && item.type === "object") { item.expanded = depth < 2; - item.children = parseObject(val,depth+1,item); + item.children = parseObject(val,depth+1,item,readOnly); item.deferBuild = depth >= 2; } else { item.value = val; @@ -287,7 +290,11 @@ // var orphanedChildren; var valueLabel = $('').addClass(valClass).text(valValue).appendTo(container); + if (readOnly) { + valueLabel.addClass("readonly") + } valueLabel.on("click", function(evt) { + if (readOnly) { return; } evt.preventDefault(); evt.stopPropagation(); if (valType === 'str') { @@ -395,17 +402,19 @@ valueLabel.hide(); }) item.gutter = $(''); - - if (parent) {//red-ui-editor-type-json-editor-item-handle - $('').appendTo(item.gutter); - } else { - $('').appendTo(item.gutter); + if(!readOnly) { + if (parent) { + $('').appendTo(item.gutter); + } else { + $('').appendTo(item.gutter); + } + $('').appendTo(item.gutter).on("click", function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + showObjectMenu($(this), item, readOnly); + }); } - $('').appendTo(item.gutter).on("click", function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - showObjectMenu($(this), item); - }); + item.element = container; return item; } @@ -498,7 +507,25 @@ open: function(tray) { var trayBody = tray.find('.red-ui-tray-body'); var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor'); - + var jsonButtons = options.jsonButtons || []; + if (jsonButtons.length) { + jsonButtons.forEach(function (button) { + var element = $('') + .insertBefore("#node-input-json-reformat") + .on("click", function (evt) { + evt.preventDefault(); + if (button.click !== undefined) { + button.click(evt); + } + }); + if (button.id) { element.attr("id", button.id); } + if (button.title) { element.attr("title", button.title); } + if (button.icon) { element.append($("").attr("class", button.icon)); } + if (button.label || button.text) { + element.append($("").text(" " + (button.label || button.text))); + } + }); + } var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"}); var filterDepth = Infinity; var list = $('
').appendTo(container).treeList({ @@ -528,11 +555,11 @@ }) }); - expressionEditor = RED.editor.createEditor({ id: 'node-input-json', value: "", - mode:"ace/mode/json" + mode:"ace/mode/json", + readOnly: !!options.readOnly }); expressionEditor.getSession().setValue(value||"",-1); if (options.requireValid) { @@ -571,7 +598,7 @@ var raw = expressionEditor.getValue().trim() ||"{}"; try { var parsed = JSON.parse(raw); - rootNode = handleItem(null,parsed,0,null); + rootNode = handleItem(null,parsed,0,null,options.readOnly); rootNode.class = "red-ui-editor-type-json-root-node" list.treeList('data',[rootNode]); } catch(err) { @@ -589,12 +616,12 @@ tabs.addTab({ id: 'json-raw', - label: RED._('jsonEditor.rawMode'), + label: options.readOnly ? "JSON" : RED._('jsonEditor.rawMode'), content: $("#red-ui-editor-type-json-tab-raw") }); tabs.addTab({ id: 'json-ui', - label: RED._('jsonEditor.uiMode'), + label: options.readOnly ? "Visual" : RED._('jsonEditor.uiMode'), content: $("#red-ui-editor-type-json-tab-ui") }); finishedBuild = true; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss index 473571042..df2d3cc6f 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss @@ -685,6 +685,10 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle { border-color: $list-item-background-hover; border-style: dashed; } + &.readonly { + cursor: pointer; + pointer-events: none; + } } .red-ui-editor-type-json-editor-item-gutter { width: 48px; @@ -704,6 +708,10 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle { > span, > button { display: none; } + &.readonly { + cursor: pointer; + pointer-events: none; + } } diff --git a/packages/node_modules/@node-red/runtime/lib/api/settings.js b/packages/node_modules/@node-red/runtime/lib/api/settings.js index 0224c0ca6..f56b8ab61 100644 --- a/packages/node_modules/@node-red/runtime/lib/api/settings.js +++ b/packages/node_modules/@node-red/runtime/lib/api/settings.js @@ -142,6 +142,13 @@ var api = module.exports = { } safeSettings.flowEncryptionType = runtime.nodes.getCredentialKeyType(); + + safeSettings.diagnostics = { + //unless diagnostics.ui and diagnostics.enabled are explicitly false, they will default to true. + enabled: (runtime.settings.diagnostics && runtime.settings.diagnostics.enabled === false) ? false : true, + ui: (runtime.settings.diagnostics && runtime.settings.diagnostics.ui === false) ? false : true + } + runtime.settings.exportNodeSettings(safeSettings); runtime.plugins.exportPluginSettings(safeSettings); }