@gregoriusrippenstein/node-red-contrib-introspection 0.4.5 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -35
- package/examples/client-code.json +926 -0
- package/examples/drawsvg-flow.json +18 -14
- package/examples/get-flows.json +471 -31
- package/examples/orphans.json +220 -0
- package/examples/seeker-sink.json +349 -2465
- package/nodes/60-client-code.html +69 -9
- package/nodes/60-client-code.js +23 -0
- package/package.json +5 -6
- package/plugins/orphans.html +45 -0
- package/plugins/screenshot.html +74 -0
- package/examples/trigger-and-save-screenshot.json +0 -155
- package/nodes/15-screenshot.html +0 -576
- package/nodes/15-screenshot.js +0 -29
- package/nodes/20-orphans.html +0 -183
- package/nodes/20-orphans.js +0 -17
- package/nodes/25-ismobile.html +0 -49
- package/nodes/25-ismobile.js +0 -17
- package/nodes/30-navigator.html +0 -77
- package/nodes/30-navigator.js +0 -17
- package/nodes/40-drawsvg.html +0 -51
- package/nodes/40-drawsvg.js +0 -25
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
url: "ClientCode/" + nodeid,
|
|
16
16
|
type: "POST",
|
|
17
17
|
contentType: "application/json; charset=utf-8",
|
|
18
|
-
data:
|
|
18
|
+
data: JSON.stringify(data),
|
|
19
19
|
|
|
20
20
|
success: function (resp) {
|
|
21
21
|
},
|
|
@@ -31,6 +31,27 @@
|
|
|
31
31
|
});
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
var doStatus = (sts, nodeid, _msg) => {
|
|
35
|
+
$.ajax({
|
|
36
|
+
url: "ClientCode/" + nodeid + "/status",
|
|
37
|
+
type: "POST",
|
|
38
|
+
contentType: "application/json; charset=utf-8",
|
|
39
|
+
data: JSON.stringify(sts),
|
|
40
|
+
|
|
41
|
+
success: function (resp) {
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
error: function (jqXHR, textStatus, errorThrown) {
|
|
45
|
+
RED.notify("ClientCode Communcation Failure: " +
|
|
46
|
+
nodeid + ": " + textStatus, {
|
|
47
|
+
type: "error",
|
|
48
|
+
id: nodeid,
|
|
49
|
+
timeout: 3000
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
34
55
|
var doError = (msg, nodeid, _msg) => {
|
|
35
56
|
RED.notify("ClientCode Failed: " + nodeid + ": " + msg, {
|
|
36
57
|
type: "error",
|
|
@@ -43,15 +64,13 @@
|
|
|
43
64
|
|
|
44
65
|
var nodeid = data.nodeid;
|
|
45
66
|
var _msg = data._msg;
|
|
67
|
+
var msg = data._msg;
|
|
46
68
|
|
|
47
69
|
var node = {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
doError(mg, nodeid, _msg)
|
|
53
|
-
},
|
|
54
|
-
id: data.nodeid
|
|
70
|
+
id: data.nodeid,
|
|
71
|
+
send: (dt) => { doSend(dt, nodeid, _msg) },
|
|
72
|
+
error: (mg) => { doError(mg, nodeid, _msg) },
|
|
73
|
+
status: (sts) => { doStatus(sts, nodeid, _msg) }
|
|
55
74
|
};
|
|
56
75
|
|
|
57
76
|
var payload = data.payload;
|
|
@@ -105,8 +124,19 @@
|
|
|
105
124
|
|
|
106
125
|
this.editor = RED.editor.createEditor({
|
|
107
126
|
id: 'node-input-clientcode-editor',
|
|
108
|
-
mode: 'ace/mode/
|
|
127
|
+
mode: 'ace/mode/nrjavascript',
|
|
109
128
|
stateId: stateId,
|
|
129
|
+
globals: {
|
|
130
|
+
msg:true,
|
|
131
|
+
RED: true,
|
|
132
|
+
node: true,
|
|
133
|
+
console: true,
|
|
134
|
+
Buffer: true,
|
|
135
|
+
setTimeout: true,
|
|
136
|
+
clearTimeout: true,
|
|
137
|
+
setInterval: true,
|
|
138
|
+
clearInterval: true
|
|
139
|
+
},
|
|
110
140
|
value: $("#node-input-clientcode").val()
|
|
111
141
|
});
|
|
112
142
|
|
|
@@ -202,4 +232,34 @@
|
|
|
202
232
|
|
|
203
233
|
<script type="text/html" data-help-name="ClientCode">
|
|
204
234
|
<p>Execute Javascript code in the Node-RED frontend, triggered from the server.</p>
|
|
235
|
+
|
|
236
|
+
The code is executed in the users browser and has the following enviornment defined:
|
|
237
|
+
<pre>
|
|
238
|
+
<code>
|
|
239
|
+
Variables:
|
|
240
|
+
nodeid - id of this node
|
|
241
|
+
_msg - a reference to the msg object passed to this node
|
|
242
|
+
msg - alias for _msg
|
|
243
|
+
node.id - id of this node, same as `nodeid` above
|
|
244
|
+
payload - a reference to msg.payload as it was received by this node
|
|
245
|
+
topic - a reference to the msg.topic as it was recieved by this node
|
|
246
|
+
|
|
247
|
+
Functionality:
|
|
248
|
+
node.send({..}) - send data to the output port of this node
|
|
249
|
+
node.error("msg") - generate an error for the node
|
|
250
|
+
node.status( { fill: 'red', shape: 'dot', text: 'hello world'}) - generate a status for the node.
|
|
251
|
+
</code>
|
|
252
|
+
</pre>
|
|
253
|
+
|
|
254
|
+
<p>
|
|
255
|
+
This might be confusing since the code in the node <b>is not</b>
|
|
256
|
+
executed on the Node-RED server, rather it is executed in the client
|
|
257
|
+
browser.
|
|
258
|
+
<p>
|
|
259
|
+
This of course makes no sense for flows that are executed "head less"
|
|
260
|
+
on the server in the backgrond on some dark and stormy night. The ClientCode
|
|
261
|
+
node is intended for immediate, frontend-only use.
|
|
262
|
+
<p>
|
|
263
|
+
An example flow with some use cases is included and can be accessed either via
|
|
264
|
+
the Import Flow dialog or accessed online <a style="color: blue" href="https://flowhub.org/f/e02ba6e534f7a0f4" target="_blank">at here <i class="fa fa-external-link"></i></a>.
|
|
205
265
|
</script>
|
package/nodes/60-client-code.js
CHANGED
|
@@ -47,4 +47,27 @@ module.exports = function(RED) {
|
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
|
|
51
|
+
RED.httpAdmin.post("/ClientCode/:id/status",
|
|
52
|
+
RED.auth.needsPermission("ClientCode.write"),
|
|
53
|
+
(req, res) => {
|
|
54
|
+
var node = RED.nodes.getNode(req.params.id);
|
|
55
|
+
if (node != null) {
|
|
56
|
+
try {
|
|
57
|
+
if (req.body && node.type == "ClientCode") {
|
|
58
|
+
node.status(req.body);
|
|
59
|
+
res.sendStatus(200);
|
|
60
|
+
} else {
|
|
61
|
+
res.sendStatus(404);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
res.sendStatus(500);
|
|
65
|
+
node.error("ClientCode: Submission failed: " +
|
|
66
|
+
err.toString())
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
res.sendStatus(404);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
50
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gregoriusrippenstein/node-red-contrib-introspection",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"got": "latest"
|
|
6
6
|
},
|
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
},
|
|
16
16
|
"node-red": {
|
|
17
17
|
"version": ">=2.0.0",
|
|
18
|
+
"plugins": {
|
|
19
|
+
"screenshot": "plugins/screenshot.html",
|
|
20
|
+
"orphans": "plugins/orphans.html"
|
|
21
|
+
},
|
|
18
22
|
"nodes": {
|
|
19
23
|
"seeker": "nodes/05-seeker.js",
|
|
20
24
|
"sink": "nodes/10-sink.js",
|
|
21
|
-
"screenshot": "nodes/15-screenshot.js",
|
|
22
|
-
"orphans": "nodes/20-orphans.js",
|
|
23
|
-
"ismobile": "nodes/25-ismobile.js",
|
|
24
|
-
"navigator": "nodes/30-navigator.js",
|
|
25
|
-
"drawsvg": "nodes/40-drawsvg.js",
|
|
26
25
|
"getflows": "nodes/45-get-flows.js",
|
|
27
26
|
"sendflow": "nodes/50-send-flow.js",
|
|
28
27
|
"clientcode": "nodes/60-client-code.js"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function() {
|
|
3
|
+
function setupTreelist(){var e=collectOrphans();if(0==e.length){RED.notify("No Orphans Found",{type:"warning",timeout:2e3});try{$("#node-input-orphan-target-container-div").treeList("empty")}catch(e){}}else{try{$("#node-input-orphan-target-container-div").treeList("empty")}catch(e){$("#node-input-orphan-target-container-div").css({width:"100%",height:"400px"}).treeList({multi:!1}).on("treelistitemmouseover",function(e,t){t.node&&t.node.z==RED.workspaces.active()&&(RED.view.reveal(t.node.id,!0),RED.view.redraw())}).on("treelistitemmouseout",function(e,t){}).on("treelistselect",function(e,t){t.node&&(RED.workspaces.show(t.node.z,!1,!1,!0),RED.view.reveal(t.node.id,!0),RED.view.redraw())}),$("#node-input-orphan-target-filter").show();var n=$("#node-input-orphan-target-filter").searchBox({style:"compact",delay:300,change:function(){var e,t=$(this).val().trim().toLowerCase();""===t?($("#node-input-orphan-target-container-div").treeList("filter",null),n.searchBox("count","")):(e=$("#node-input-orphan-target-container-div").treeList("filter",function(e){return-1<e.label.toLowerCase().indexOf(t)||-1<e.node.type.toLowerCase().indexOf(t)}),n.searchBox("count",e+" / "+$("#node-input-orphan-target-container-div").treeList("data").length))}})}$("#node-input-orphan-target-container-div").treeList("data",e.sort((e,t)=>e.node.z>t.node.z))}}function collectOrphans(){const t=new Set;var n=[],r=(RED.nodes.eachLink(e=>{t.add(e.source),t.add(e.target)}),RED.nodes.eachNode(e=>{t.has(e)||n.push(e)}),[]),i={};return n.forEach(function(e){var t=RED.nodes.getType(e.type);if(t){var n=t.label,n=("function"==typeof n?n.call(e):n)||"",o=e.type;if(0===o.indexOf("subflow:"))return}t&&n||(n=e.type),i[e.id]={node:e,label:n,sublabel:o,selected:!1,checkbox:!1},r.push(i[e.id])}),r}
|
|
4
|
+
|
|
5
|
+
var initialiseSidebarOrphanNodeOnce = () => {
|
|
6
|
+
RED.events.off('runtime-state', initialiseSidebarOrphanNodeOnce);
|
|
7
|
+
|
|
8
|
+
// The html content of the sidebar has been specified below as a data-template, from where it can be loaded:
|
|
9
|
+
var content = $($('script[type="text/x-red"][data-template-name="Orphans"]').i18n().html());
|
|
10
|
+
|
|
11
|
+
// Add a "Your sidebar" tabsheet to the right sidebar panel, in which this sidebar panel can be displayed
|
|
12
|
+
// --> more details: https://nodered.org/docs/api/ui/sidebar/
|
|
13
|
+
RED.sidebar.addTab({
|
|
14
|
+
id: "Orphans",
|
|
15
|
+
label: "Orphans", // short name for the tab
|
|
16
|
+
name: "Orphan Nodes", // long name for the menu
|
|
17
|
+
content: content,
|
|
18
|
+
enableOnEdit: true,
|
|
19
|
+
iconClass: "fa fa-life-ring" // your fontawesome icon
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// When the user has entered new data in the sidebar, then store it into the config node
|
|
23
|
+
$("#node-input-orphan-find-btn").on("click", function(e) {
|
|
24
|
+
if ( e ) { e.preventDefault() }
|
|
25
|
+
setupTreelist();
|
|
26
|
+
})
|
|
27
|
+
};
|
|
28
|
+
RED.events.on('runtime-state', initialiseSidebarOrphanNodeOnce);
|
|
29
|
+
})();
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<!-- The html for the right sidebar plugin screen -->
|
|
33
|
+
<script type="text/x-red" data-template-name="Orphans">
|
|
34
|
+
<div class="form-row node-input-target-row" style="margin-left: 10px; margin-top: 30px">
|
|
35
|
+
<button id="node-input-orphan-find-btn"
|
|
36
|
+
class="red-ui-button">Find Orphans</button>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="form-row node-input-target-row node-input-target-list-row" style="margin-left: 10px; position: relative; min-height: 200px; margin-right: 15px;">
|
|
40
|
+
<div style="margin-bottom: 5px; width: 35%; padding-left: 60%;">
|
|
41
|
+
<input type="text" id="node-input-orphan-target-filter" style="display: none;">
|
|
42
|
+
</div>
|
|
43
|
+
<div id="node-input-orphan-target-container-div"></div>
|
|
44
|
+
</div>
|
|
45
|
+
</script>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function() {
|
|
3
|
+
var globalRefToSvgData;
|
|
4
|
+
|
|
5
|
+
function nr_intro_generate_svg_3_1(r){return e=>{try{handleSvgObject($($("svg[width=8000]")[0]),e)}catch(t){var n="Error Generating SVG: "+JSON.stringify(t);r.notify(n,{type:"error"}),e('<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="1000" height="1000" viewBox="0 0 1000 1000" pointer-events="all" style="cursor: crosshair; touch-action: none;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style>.small { font: bold 20px sans-serif; fill: red;}</style><text x="10" y="30" class="small">'+n+"</text></svg>")}}}function nr_intro_generate_svg_3_0(r){return e=>{try{handleSvgObject($($("svg")[0]),e)}catch(t){var n="Error Generating SVG: "+JSON.stringify(t);r.notify(n,{type:"error"}),e('<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="1000" height="1000" viewBox="0 0 1000 1000" pointer-events="all" style="cursor: crosshair; touch-action: none;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style>.small { font: bold 20px sans-serif; fill: red;}</style><text x="10" y="30" class="small">'+n+"</text></svg>")}}}function handleSvgObject(o,e){var t=o.clone();t.find("foreignObject").remove(),t.find("svg.__screenshot").remove();function a(t,e){for(var n=0;n<t.length;n++){var s=t.item(n),i=e[n];["stroke-width","fill-opacity","stroke-opacity","opacity","stroke-dasharray"].forEach(function(t){s.setAttribute(t,$(i).attr(t)||$(i).css(t))}),["fill","stroke"].forEach(function(t){var e,n,r=(e=$(i).attr(t)||$(i).css(t))&&null!==e&&"none"!=e?(n=e.match(/^#(.)(.)(.)$/))?"#"+n[1]+n[1]+n[2]+n[2]+n[3]+n[3]:(n=e.match(/^#......$/))?e:null===(n=e.match(/^rgb\(([0-9]+),\s+([0-9]+),\s+([0-9]+)/))?(r=e.match(/^rgba\(([0-9]+),\s+([0-9]+),\s+([0-9]+),\s+([0-9]+)/))?{clr:"#"+("0"+parseInt(r[1],10).toString(16)).slice(-2)+("0"+parseInt(r[2],10).toString(16)).slice(-2)+("0"+parseInt(r[3],10).toString(16)).slice(-2),opa:r[4]}:(console.log("Screenshot node: returned unknown color: "+e),e):"#"+("0"+parseInt(n[1],10).toString(16)).slice(-2)+("0"+parseInt(n[2],10).toString(16)).slice(-2)+("0"+parseInt(n[3],10).toString(16)).slice(-2):"none";"object"==typeof r?(s.setAttribute(t+"-opacity",r.opa),s.setAttribute(t,r.clr)):s.setAttribute(t,r)}),$(i).hasClass("hide")&&("g"==s.tagName&&s.setAttribute("opacity","0"),s.setAttribute("visibility","hidden"))}}var n='<?xml version="1.0" standalone="no"?>\r\n<svg '+('width="'+o.attr("width")+'" height="'+o.attr("height")+'"')+' pointer-events="all" style="cursor: crosshair; touch-action: none;" xmlns="http://www.w3.org/2000/svg" class="__screenshot" xmlns:xlink="http://www.w3.org/1999/xlink">\r\n',t=t.html(),l=(new DOMParser).parseFromString(n+t+"\r\n</svg>","image/svg+xml"),r=e=>(["g","rect","line","path","circle","image","text"].forEach(t=>{$(e.getElementsByTagName(t)).each((t,e)=>{e.setAttribute("class",""),e.setAttribute("id","")})}),e),s=(["g","rect","line","path","circle","image"].forEach(function(t){a(l.getElementsByTagName(t),o.find(t))}),["text"].forEach(function(t){a(l.getElementsByTagName(t),o.find(t));for(var e=l.getElementsByTagName(t),n=o.find(t),r=0;r<e.length;r++){var s=e.item(r),i=n[r];["font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","text-anchor","dominant-baseline"].forEach(function(t){s.setAttribute(t,$(i).attr(t)||$(i).css(t))})}}),l.getElementsByTagName("image")),g={},i=(n,r,s)=>{var i=n.getAttribute("xlink:href"),o=i.substr(-4,4).toLowerCase(),a={".jpg":"jpeg",jpeg:"jpeg",".png":"png",".svg":"svg+xml"};if(g[i])return n.setAttribute("xlink:href","data:image/"+a[o]+";base64,"+g[i]),s(r-1);switch(o){case".jpg":case"jpeg":case".png":var l=new XMLHttpRequest;l.open("GET",i,!0),l.responseType="arraybuffer";l.onload=function(t){var e=l.response;e&&(e=(t=>{for(var e="",n=new Uint8Array(t),r=n.byteLength,s=0;s<r;s++)e+=String.fromCharCode(n[s]);return window.btoa(e)})(e),g[i]=e,n.setAttribute("xlink:href","data:image/"+a[o]+";base64,"+e)),s(r-1)},l.send(null);break;case".svg":$.get(i,function(t){var e=new XMLSerializer,e=btoa(e.serializeToString(t));g[i]=e,n.setAttribute("xlink:href","data:image/svg+xml;base64,"+e),s(r-1)})}},c=t=>{t<0?e((new XMLSerializer).serializeToString(r(l))):i(s.item(t),t,c)};0<s.length?i(s.item(s.length-1),s.length-1,c):e((new XMLSerializer).serializeToString(r(l)))}function generatorFunctionForVersion(t){var n,e=t.settings.version.split("."),r=e[0],e=e[1];if("3"==r){if("0"==e)return nr_intro_generate_svg_3_0(t);if("1"==e)return nr_intro_generate_svg_3_1(t)}return n=t,t=>{var e="Node-RED version ("+n.settings.version+") not supported";n.notify(e,{type:"error"}),t&&t('<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="1000" height="1000" viewBox="0 0 1000 1000" pointer-events="all" style="cursor: crosshair; touch-action: none;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style>.small { font: bold 20px sans-serif; fill: red;}</style><text x="10" y="30" class="small">'+e+"</text></svg>")}}
|
|
6
|
+
|
|
7
|
+
// Add your plugin as a new tabsheet in the right sidebar AFTER the flow editor is completely started
|
|
8
|
+
var initialiseConfigNodeOnce = () => {
|
|
9
|
+
RED.events.off('runtime-state', initialiseConfigNodeOnce);
|
|
10
|
+
|
|
11
|
+
// The html content of the sidebar has been specified below as a data-template, from where it can be loaded:
|
|
12
|
+
var content = $($('script[type="text/x-red"][data-template-name="Screenshot"]').i18n().html());
|
|
13
|
+
|
|
14
|
+
// Add a "Your sidebar" tabsheet to the right sidebar panel, in which this sidebar panel can be displayed
|
|
15
|
+
// --> more details: https://nodered.org/docs/api/ui/sidebar/
|
|
16
|
+
RED.sidebar.addTab({
|
|
17
|
+
id: "Screenshot",
|
|
18
|
+
label: "Screenshot", // short name for the tab
|
|
19
|
+
name: "Screenshot", // long name for the menu
|
|
20
|
+
content: content,
|
|
21
|
+
enableOnEdit: true,
|
|
22
|
+
iconClass: "fa fa-camera" // your fontawesome icon
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
$('#node-screenshot-capture-btn').on("click", function (e) {
|
|
26
|
+
if ( e ) { e.preventDefault() }
|
|
27
|
+
|
|
28
|
+
$('#node-input-screenshot-svgcontainer').html( "Please wait, screenshot being prepared ..." );
|
|
29
|
+
|
|
30
|
+
generatorFunctionForVersion(RED)( (svgdata) => {
|
|
31
|
+
$('#node-input-screenshot-svgcontainer').html(svgdata);
|
|
32
|
+
globalRefToSvgData = svgdata;
|
|
33
|
+
});
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// handle the download button under the editor window.
|
|
37
|
+
$('#node-screenshot-download-svg').on("click", function (e) {
|
|
38
|
+
if (e) { e.preventDefault(); }
|
|
39
|
+
var svgBlob = new Blob([globalRefToSvgData], {type:"image/svg+xml;charset=utf-8"});
|
|
40
|
+
var svgUrl = URL.createObjectURL(svgBlob);
|
|
41
|
+
var downloadLink = document.createElement("a");
|
|
42
|
+
downloadLink.href = svgUrl;
|
|
43
|
+
downloadLink.download = "screenshot.svg";
|
|
44
|
+
document.body.appendChild(downloadLink);
|
|
45
|
+
downloadLink.click();
|
|
46
|
+
document.body.removeChild(downloadLink);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
$('#node-screenshot-copy-to-clipboard-svg').on("click", function (e) {
|
|
50
|
+
if (e) { e.preventDefault(); }
|
|
51
|
+
if ( RED.clipboard.copyText(globalRefToSvgData) ) {
|
|
52
|
+
RED.notify("SVG copied to clipboard", { type: "success" });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
RED.events.on('runtime-state', initialiseConfigNodeOnce);
|
|
57
|
+
})();
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<!-- The html for the right sidebar plugin screen -->
|
|
61
|
+
<script type="text/x-red" data-template-name="Screenshot">
|
|
62
|
+
<div class="form-row" style="margin-left: 10px; margin-top: 30px;">
|
|
63
|
+
<button type="button" id="node-screenshot-capture-btn" class="red-ui-button red-ui-button-large"><i class="fa fa-camera"></i> Capture</button>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div class="form-row" style="min-height: 300px; overflow: scroll; margin-left: 10px; margin-right: 15px; height: 300px; border: 1px rgb(196, 196, 196) solid; border-radius: 5px;">
|
|
67
|
+
<div id="node-input-screenshot-svgcontainer"></div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="form-row" style="margin-left: 10px; margin-top: 5px;">
|
|
71
|
+
<button type="button" id="node-screenshot-download-svg" class="red-ui-button red-ui-button-large"><i class="fa fa-download"></i>Download</button>
|
|
72
|
+
<button type="button" id="node-screenshot-copy-to-clipboard-svg" class="red-ui-button red-ui-button-large"><i class="fa fa-clipboard"></i>Copy to Clipboard</button>
|
|
73
|
+
</div>
|
|
74
|
+
</script>
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "e815c52d1e6a0d25",
|
|
4
|
-
"type": "tab",
|
|
5
|
-
"label": "Trigger Screenshot Example",
|
|
6
|
-
"disabled": false,
|
|
7
|
-
"info": "",
|
|
8
|
-
"env": []
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"id": "03f322255fd8cad1",
|
|
12
|
-
"type": "http in",
|
|
13
|
-
"z": "e815c52d1e6a0d25",
|
|
14
|
-
"name": "[POST] screenshot",
|
|
15
|
-
"url": "/screenshot",
|
|
16
|
-
"method": "post",
|
|
17
|
-
"upload": false,
|
|
18
|
-
"swaggerDoc": "",
|
|
19
|
-
"x": 388,
|
|
20
|
-
"y": 305,
|
|
21
|
-
"wires": [
|
|
22
|
-
[
|
|
23
|
-
"ddabce426445e225",
|
|
24
|
-
"a9f9ce494ec4edc1",
|
|
25
|
-
"c81d27b03cf13c69"
|
|
26
|
-
]
|
|
27
|
-
]
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"id": "ddabce426445e225",
|
|
31
|
-
"type": "debug",
|
|
32
|
-
"z": "e815c52d1e6a0d25",
|
|
33
|
-
"name": "debug 1",
|
|
34
|
-
"active": false,
|
|
35
|
-
"tosidebar": true,
|
|
36
|
-
"console": false,
|
|
37
|
-
"tostatus": false,
|
|
38
|
-
"complete": "true",
|
|
39
|
-
"targetType": "full",
|
|
40
|
-
"statusVal": "",
|
|
41
|
-
"statusType": "auto",
|
|
42
|
-
"x": 1175,
|
|
43
|
-
"y": 307,
|
|
44
|
-
"wires": []
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"id": "e62ae897ba4c777f",
|
|
48
|
-
"type": "http response",
|
|
49
|
-
"z": "e815c52d1e6a0d25",
|
|
50
|
-
"name": "",
|
|
51
|
-
"statusCode": "",
|
|
52
|
-
"headers": {
|
|
53
|
-
"content-type": "application/json"
|
|
54
|
-
},
|
|
55
|
-
"x": 817,
|
|
56
|
-
"y": 624,
|
|
57
|
-
"wires": []
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
"id": "a9f9ce494ec4edc1",
|
|
61
|
-
"type": "function",
|
|
62
|
-
"z": "e815c52d1e6a0d25",
|
|
63
|
-
"name": "respond with ok",
|
|
64
|
-
"func": "msg.payload = {\n status: \"ok\",\n data: {\n }\n};\nmsg.statusCode = 200;\nreturn msg;\n",
|
|
65
|
-
"outputs": 1,
|
|
66
|
-
"noerr": 0,
|
|
67
|
-
"initialize": "",
|
|
68
|
-
"finalize": "",
|
|
69
|
-
"libs": [],
|
|
70
|
-
"x": 622,
|
|
71
|
-
"y": 517,
|
|
72
|
-
"wires": [
|
|
73
|
-
[
|
|
74
|
-
"e62ae897ba4c777f"
|
|
75
|
-
]
|
|
76
|
-
]
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"id": "c81d27b03cf13c69",
|
|
80
|
-
"type": "function",
|
|
81
|
-
"z": "e815c52d1e6a0d25",
|
|
82
|
-
"name": "set filename & payload",
|
|
83
|
-
"func": "msg.filename = \"/data/content/screenshot-\" + Date.now() + \".svg\";\n\nmsg.payload = msg.payload[\"d\"];\n\nreturn msg;",
|
|
84
|
-
"outputs": 1,
|
|
85
|
-
"noerr": 0,
|
|
86
|
-
"initialize": "",
|
|
87
|
-
"finalize": "",
|
|
88
|
-
"libs": [],
|
|
89
|
-
"x": 744,
|
|
90
|
-
"y": 410,
|
|
91
|
-
"wires": [
|
|
92
|
-
[
|
|
93
|
-
"00c967aaf678c503"
|
|
94
|
-
]
|
|
95
|
-
]
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"id": "00c967aaf678c503",
|
|
99
|
-
"type": "file",
|
|
100
|
-
"z": "e815c52d1e6a0d25",
|
|
101
|
-
"name": "",
|
|
102
|
-
"filename": "filename",
|
|
103
|
-
"filenameType": "msg",
|
|
104
|
-
"appendNewline": false,
|
|
105
|
-
"createDir": true,
|
|
106
|
-
"overwriteFile": "true",
|
|
107
|
-
"encoding": "none",
|
|
108
|
-
"x": 1012,
|
|
109
|
-
"y": 505,
|
|
110
|
-
"wires": [
|
|
111
|
-
[
|
|
112
|
-
"ddabce426445e225"
|
|
113
|
-
]
|
|
114
|
-
]
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"id": "32cde1648d31e9b4",
|
|
118
|
-
"type": "Screenshot",
|
|
119
|
-
"z": "e815c52d1e6a0d25",
|
|
120
|
-
"name": "",
|
|
121
|
-
"screenshot": "",
|
|
122
|
-
"x": 461,
|
|
123
|
-
"y": 108,
|
|
124
|
-
"wires": []
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"id": "3957fb7da9d89393",
|
|
128
|
-
"type": "inject",
|
|
129
|
-
"z": "e815c52d1e6a0d25",
|
|
130
|
-
"name": "",
|
|
131
|
-
"props": [
|
|
132
|
-
{
|
|
133
|
-
"p": "payload"
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"p": "topic",
|
|
137
|
-
"vt": "str"
|
|
138
|
-
}
|
|
139
|
-
],
|
|
140
|
-
"repeat": "600",
|
|
141
|
-
"crontab": "",
|
|
142
|
-
"once": true,
|
|
143
|
-
"onceDelay": "2",
|
|
144
|
-
"topic": "",
|
|
145
|
-
"payload": "",
|
|
146
|
-
"payloadType": "date",
|
|
147
|
-
"x": 213,
|
|
148
|
-
"y": 108,
|
|
149
|
-
"wires": [
|
|
150
|
-
[
|
|
151
|
-
"32cde1648d31e9b4"
|
|
152
|
-
]
|
|
153
|
-
]
|
|
154
|
-
}
|
|
155
|
-
]
|