Editing json file in dashboard with 100+ lines

Hi!

I have a json file with 100+ records.
I would like to crate a dashboard to edit this file and change settings that are saved in the file
But with 100 line it is a lot of work :wink:
So i try to make something "smart" so i do not need to edit so much
To start and test i created a json with one line

{
    "config" :{
        "location" : ".node-red/projects/test/"
    }
}

In my flow i use the file read to get it
Then i save it as a global and then i get a single line to send to a dashbaord note to edit.
I include a msg.field so i can use that later to save it.
In this way i only need to edit the change node 00+ times and can copy paste the rest.
But the msg.field isnt passed thru the dashboard fiels :frowning:
anyone an idea how to do it?
My flow is below

[{"id":"f36e682d398acbb4","type":"file in","z":"3e104e2074f28f17","name":"","filename":".node-red/json.json","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":350,"y":1740,"wires":[["e6f5553231f9d34b"]]},{"id":"409077a439cbb25b","type":"inject","z":"3e104e2074f28f17","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":1740,"wires":[["f36e682d398acbb4"]]},{"id":"e6f5553231f9d34b","type":"json","z":"3e104e2074f28f17","name":"","property":"payload","action":"","pretty":false,"x":550,"y":1740,"wires":[["45e5bcd9bc1af130"]]},{"id":"93e8e1656a7857ea","type":"ui_text_input","z":"3e104e2074f28f17","name":"","label":"","tooltip":"","group":"f9b037d48973d862","order":9,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"topicType":"msg","x":520,"y":1840,"wires":[["a1f9ee40c339edf0"]]},{"id":"271f03a218c962ed","type":"change","z":"3e104e2074f28f17","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.config.location","tot":"msg"},{"t":"set","p":"field","pt":"msg","to":"payload.config.location","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":1840,"wires":[["93e8e1656a7857ea"]]},{"id":"45e5bcd9bc1af130","type":"function","z":"3e104e2074f28f17","name":"","func":"global.set(\"testConfig\",msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":130,"y":1840,"wires":[["271f03a218c962ed"]]},{"id":"a1f9ee40c339edf0","type":"function","z":"3e104e2074f28f17","name":"","func":"var x = JSON.stringify(\"testConfig.\"+msg.field);\nglobal.set(x,msg.payload);\nmsg.pay = x;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":1840,"wires":[["0d82959f9a888853"]]},{"id":"0d82959f9a888853","type":"debug","z":"3e104e2074f28f17","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":820,"y":1840,"wires":[]},{"id":"f9b037d48973d862","type":"ui_group","name":"Overal","tab":"12a9741dd4b6a72f","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"12a9741dd4b6a72f","type":"ui_tab","name":"Game Settings","icon":"dashboard","order":5,"disabled":false,"hidden":false}]

Thanks!

I was just working on this exact problem earlier today!

I'm certain that someone who's more familiar than I am will tell us how to use a Template node for this. It seems certain that there's a way to populate an editable textbox in a Template node, and then have a button which causes the current contents of the text box to be passed out of the Template node as a string.

However, I don't know how to do that. I need to go through about a dozen temperature sensors attached to my Pi, and give each one a name to be associated with its "address". I start out with an array of objects, each of which has an "address", an empty "name", a temperature, and a last read timestamp.

So I did it this way, which I'm not claiming is a good way, but it will work for my purposes for a me-facing dashboard for essentially one-time edits:

I read the file like you do, and then make myself a string out of the contents of the array of objects, using a field and a line delimiter (could be , and ; for example, but I used : and <br>).

I used the Text dashboard node to display the string I'd created that's a list of sensors. Then, below that, I have a Form node with just one entry on it - a "multiline" entry, which gives a text box. I couldn't find any way to pre-populate the multiline text input box, or I would have.

Anyway, then I can copy the values in the Text node, paste them into the Form multiline box, edit them there, and submit the form.

Because I chose to do this with strings, I then have to re-parse the strings and add the names to the relevant sensors based on their address.

Again, I'm not saying this is a good way. But if it's at all useful to you, here's what it's like:


...and below this, there's a "Submit" button. The format I happened to use is just the read number of the sensor : its address which always starts with "28-..." : its name : its current temperature, just to help me figure out which is which before they're all named.

Here's the whole thing if you can make any use of it.

[{"id":"73b5101865bc19a6","type":"inject","z":"159c98d1.b0c3e7","name":"list sensors","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"sensors.temp","payloadType":"global","x":1740,"y":1560,"wires":[["a1cd7f218b34472d"]]},{"id":"156cd5b987468242","type":"function","z":"159c98d1.b0c3e7","name":"make list","func":"var text = \"\";\nvar list = msg.payload.list;\nvar IDlist = msg.payload.IDlist;\nfor (let i=0;i<list.length;i++) {\n    text += i+1 + \":\" + list[i].address + \":\" + list[i].name + \":\" + list[i].temp + \"<br>\";\n}\nmsg.payload = text;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":1580,"wires":[["e00688179bc41413","b7dd533b8f7def0b"]]},{"id":"e00688179bc41413","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":2170,"y":1540,"wires":[]},{"id":"7808030c9bd7ae02","type":"ui_form","z":"159c98d1.b0c3e7","name":"","label":"Paste any or all lines here and edit:","group":"8748aaffd2cf417e","order":3,"width":0,"height":0,"options":[{"label":"","value":"textReturn","type":"multiline","required":true,"rows":10}],"formValue":{"textReturn":""},"payload":"","submit":"submit","cancel":"","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":1720,"y":1640,"wires":[["15fa84fe7ad8d84e","01c2523abab46ad8"]]},{"id":"b7dd533b8f7def0b","type":"ui_text","z":"159c98d1.b0c3e7","group":"8748aaffd2cf417e","order":2,"width":"10","height":"5","name":"","label":"Copy from here:","format":"{{msg.payload}}","layout":"col-center","className":"","x":2180,"y":1580,"wires":[]},{"id":"2d786ce29643edf1","type":"ui_button","z":"159c98d1.b0c3e7","name":"","group":"8748aaffd2cf417e","order":1,"width":0,"height":0,"passthru":false,"label":"Get current (start here)","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":1700,"y":1520,"wires":[["a1cd7f218b34472d"]]},{"id":"a1cd7f218b34472d","type":"change","z":"159c98d1.b0c3e7","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"sensors.temp","tot":"global","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":1940,"y":1540,"wires":[["156cd5b987468242"]]},{"id":"15fa84fe7ad8d84e","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1970,"y":1680,"wires":[]},{"id":"01c2523abab46ad8","type":"function","z":"159c98d1.b0c3e7","name":"parse input and name sensors","func":"// @ts-nocheck\nvar input = msg.payload.textReturn;\nvar updated = global.get(\"sensors.temp.list\");\nvar inArr = input.split(\"\\n\");\nfor (i=0;i<inArr.length;i++) {\n    inArr[i]=inArr[i].split(\":\");\n    for (j=0;j<updated.length;j++){\n        if (updated[j].address == inArr[i][1]) {\n            updated[j].name = inArr[i][2];\n        }\n    }\n}\nglobal.set(\"sensors.temp.list\",updated); // happens anyway - no deep copy in preceding\nmsg.inArr = inArr;\nmsg.updated = updated;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2030,"y":1640,"wires":[["ef0fbf2b6d356c3f","cf97cdf0bd63f4eb","d0c61e3103f98ea9"]]},{"id":"ef0fbf2b6d356c3f","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"updated","targetType":"msg","statusVal":"","statusType":"auto","x":2310,"y":1660,"wires":[]},{"id":"cf97cdf0bd63f4eb","type":"debug","z":"159c98d1.b0c3e7","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"inArr","targetType":"msg","statusVal":"","statusType":"auto","x":2300,"y":1620,"wires":[]},{"id":"d0c61e3103f98ea9","type":"file in","z":"159c98d1.b0c3e7","name":"","filename":"sensors/tempList.json","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":2260,"y":1760,"wires":[["13513f18eb891ffd"]]},{"id":"13513f18eb891ffd","type":"json","z":"159c98d1.b0c3e7","name":"","property":"payload","action":"","pretty":false,"x":2290,"y":1800,"wires":[["656436447bd31306"]]},{"id":"656436447bd31306","type":"function","z":"159c98d1.b0c3e7","name":"update saved sensor names","func":"var history = msg.payload;\nvar updated = msg.updated;\nvar contains = false;\n\nfor (let i=0;i<updated.length;i++) {\n    contains = false;\n    for (let j=0;j<history.length;j++) {\n        if (history.address == updated.address) {\n            contains = true;\n        }\n    }\n    if (!contains) {\n        history.push(updated[i]);\n    }\n}\n\nmsg.payload = history;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2360,"y":1840,"wires":[[]]},{"id":"b0a30bed919bed62","type":"comment","z":"159c98d1.b0c3e7","name":"RogierQ can ignore everything past here.","info":"","x":2240,"y":1720,"wires":[]},{"id":"8748aaffd2cf417e","type":"ui_group","name":"Sensor Assignments","tab":"a0484681450dbb9b","order":2,"disp":true,"width":"10","collapse":false,"className":""},{"id":"a0484681450dbb9b","type":"ui_tab","name":"Pi Settings","icon":"gear","disabled":false,"hidden":false}]

@tymarbut i think i go over to php and try to create something there :wink: