@theotherwillembotha/node-red-nginxproxymanager 0.1.0 → 0.4.0

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.
Files changed (34) hide show
  1. package/build/GenerateNodes.d.ts +2 -0
  2. package/build/GenerateNodes.d.ts.map +1 -0
  3. package/build/GenerateNodes.js +7 -6
  4. package/build/Nodes.html +653 -420
  5. package/build/Nodes.js +34995 -12
  6. package/build/Plugins.html +37 -0
  7. package/build/Plugins.js +34650 -54
  8. package/build/index.d.ts +5 -0
  9. package/build/index.d.ts.map +1 -0
  10. package/build/nginx/node/NginxGetHostsNode.d.ts +19 -0
  11. package/build/nginx/node/NginxGetHostsNode.d.ts.map +1 -0
  12. package/build/nginx/node/NginxGetHostsNode.js +2 -2
  13. package/build/nginx/node/NginxProxyManagerConfigNode.d.ts +15 -0
  14. package/build/nginx/node/NginxProxyManagerConfigNode.d.ts.map +1 -0
  15. package/build/nginx/node/NginxProxyManagerConfigNode.js +4 -3
  16. package/build/nginx/node/UpdateHostNode.d.ts +18 -0
  17. package/build/nginx/node/UpdateHostNode.d.ts.map +1 -0
  18. package/build/nginx/node/UpdateHostNode.js +2 -3
  19. package/build/nginx/service/NginxProxyManagerClient.d.ts +9 -0
  20. package/build/nginx/service/NginxProxyManagerClient.d.ts.map +1 -0
  21. package/build/nginx/service/NginxProxyManagerService.d.ts +9 -0
  22. package/build/nginx/service/NginxProxyManagerService.d.ts.map +1 -0
  23. package/build/nginx/service/NginxProxyManagerService.js +21 -5
  24. package/build/nginx/service/client/NginxClient.d.ts +69 -0
  25. package/build/nginx/service/client/NginxClient.d.ts.map +1 -0
  26. package/build/nginx/service/client/NginxHttpClient.d.ts +26 -0
  27. package/build/nginx/service/client/NginxHttpClient.d.ts.map +1 -0
  28. package/build/nginx/service/client/types.d.ts +291 -0
  29. package/build/nginx/service/client/types.d.ts.map +1 -0
  30. package/build/runtime/NodeManagerRuntime.js +140 -0
  31. package/package.json +10 -6
  32. package/documentation/GetHostsNode.png +0 -0
  33. package/documentation/NginxProxyManagerConfig.png +0 -0
  34. package/documentation/UpdateHostNode.png +0 -0
package/build/Nodes.html CHANGED
@@ -7,113 +7,110 @@
7
7
  You have been warned.
8
8
 
9
9
  -->
10
-
11
10
  <!-- ui-helper -->
12
- <style>
13
- /* ─── PluginCore Dialog overlay ─────────────────────────────────────────── */
14
- .plugincore-overlay {
15
- position: fixed;
16
- top: 0;
17
- left: 0;
18
- right: 0;
19
- bottom: 0;
20
- background: rgba(0, 0, 0, 0.5);
21
- z-index: 2000;
22
- display: flex;
23
- align-items: center;
24
- justify-content: center;
25
- }
11
+
26
12
 
27
- .plugincore-dialog {
28
- background: #fff;
29
- border: 1px solid #aaa;
30
- border-radius: 4px;
31
- box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
32
- min-width: 540px;
33
- max-width: 85vw;
34
- max-height: 80vh;
35
- display: flex;
36
- flex-direction: column;
37
- overflow: hidden;
38
- }
13
+ <style>
14
+ /* ─── PluginCore Dialog overlay ─────────────────────────────────────────── */
15
+
16
+ .plugincore-overlay {
17
+ position: fixed;
18
+ top: 0; left: 0; right: 0; bottom: 0;
19
+ background: rgba(0, 0, 0, 0.5);
20
+ z-index: 2000;
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ }
39
25
 
40
- /* Title bar — matches Node-RED's main nav bar colour */
41
- .plugincore-dialog-titlebar {
42
- display: flex;
43
- align-items: center;
44
- background: #3d3d3d;
45
- color: #fff;
46
- padding: 6px 8px 6px 12px;
47
- flex-shrink: 0;
48
- }
26
+ .plugincore-dialog {
27
+ background: #fff;
28
+ border: 1px solid #aaa;
29
+ border-radius: 4px;
30
+ box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
31
+ min-width: 540px;
32
+ max-width: 85vw;
33
+ max-height: 80vh;
34
+ display: flex;
35
+ flex-direction: column;
36
+ overflow: hidden;
37
+ }
49
38
 
50
- .plugincore-dialog-title {
51
- flex: 1;
52
- font-weight: 600;
53
- font-size: 13px;
54
- }
39
+ /* Title bar - matches Node-RED's main nav bar colour */
40
+ .plugincore-dialog-titlebar {
41
+ display: flex;
42
+ align-items: center;
43
+ background: #3d3d3d;
44
+ color: #fff;
45
+ padding: 6px 8px 6px 12px;
46
+ flex-shrink: 0;
47
+ }
55
48
 
56
- /* Close button — jQuery UI styling as used in Node-RED dialogs */
57
- .plugincore-dialog-close {
58
- color: #ccc !important;
59
- background: transparent !important;
60
- border-color: transparent !important;
61
- }
49
+ .plugincore-dialog-title {
50
+ flex: 1;
51
+ font-weight: 600;
52
+ font-size: 13px;
53
+ }
62
54
 
63
- .plugincore-dialog-close:hover {
64
- color: #fff !important;
65
- background: rgba(255, 255, 255, 0.15) !important;
66
- border-color: rgba(255, 255, 255, 0.3) !important;
67
- }
55
+ /* Close button - jQuery UI styling as used in Node-RED dialogs */
56
+ .plugincore-dialog-close {
57
+ color: #ccc !important;
58
+ background: transparent !important;
59
+ border-color: transparent !important;
60
+ }
68
61
 
69
- /* Scrollable body that contains the jQuery UI tab widget */
70
- .plugincore-dialog-body {
71
- flex: 1;
72
- overflow: auto;
73
- padding: 10px;
74
- }
62
+ .plugincore-dialog-close:hover {
63
+ color: #fff !important;
64
+ background: rgba(255, 255, 255, 0.15) !important;
65
+ border-color: rgba(255, 255, 255, 0.3) !important;
66
+ }
75
67
 
76
- /* ─── PluginCore Table ───────────────────────────────────────────────────── */
77
- .plugincore-table {
78
- width: 100%;
79
- border-collapse: collapse;
80
- font-size: 12px;
81
- }
68
+ /* Scrollable body that contains the jQuery UI tab widget or plain content */
69
+ .plugincore-dialog-body {
70
+ flex: 1 1 auto;
71
+ overflow: auto;
72
+ padding: 10px;
73
+ }
82
74
 
83
- .plugincore-table th {
84
- background: #f3f3f3;
85
- border: 1px solid #ddd;
86
- padding: 5px 10px;
87
- text-align: left;
88
- font-weight: 600;
89
- white-space: nowrap;
90
- }
75
+ /* ─── PluginCore Table ───────────────────────────────────────────────────── */
91
76
 
92
- .plugincore-table td {
93
- border: 1px solid #eee;
94
- padding: 5px 10px;
95
- vertical-align: middle;
96
- }
77
+ .plugincore-table {
78
+ width: 100%;
79
+ border-collapse: collapse;
80
+ font-size: 12px;
81
+ }
97
82
 
98
- .plugincore-table tbody tr:nth-child(even) td {
99
- background: #fafafa;
100
- }
83
+ .plugincore-table th {
84
+ background: #f3f3f3;
85
+ border: 1px solid #ddd;
86
+ padding: 5px 10px;
87
+ text-align: left;
88
+ font-weight: 600;
89
+ white-space: nowrap;
90
+ }
101
91
 
102
- .plugincore-table tbody tr:hover td {
103
- background: #f0f6ff;
104
- }
92
+ .plugincore-table td {
93
+ border: 1px solid #eee;
94
+ padding: 5px 10px;
95
+ vertical-align: middle;
96
+ }
105
97
 
106
- .plugincore-status-enabled {
107
- color: #27ae60;
108
- }
98
+ .plugincore-table tbody tr:nth-child(even) td {
99
+ background: #fafafa;
100
+ }
109
101
 
110
- .plugincore-status-disabled {
111
- color: #c0392b;
112
- }
102
+ .plugincore-table tbody tr:hover td {
103
+ background: #f0f6ff;
104
+ }
113
105
 
106
+ .plugincore-status-enabled { color: #27ae60; }
107
+ .plugincore-status-disabled { color: #c0392b; }
114
108
  </style>
109
+
115
110
  <script type="text/javascript">
111
+
116
112
  window.PluginCore = window.PluginCore || {};
113
+
117
114
  /**
118
115
  * PluginCore.table(config) → jQuery <table>
119
116
  *
@@ -123,108 +120,248 @@
123
120
  * }
124
121
  */
125
122
  PluginCore.table = function(config) {
126
- var $table = $('<table class="plugincore-table">');
127
- // Header
128
- var $thead = $('<thead>');
129
- var $hr = $('<tr>');
130
- config.columns.forEach(function(col) {
131
- $hr.append($('<th>').text(col.label));
132
- });
133
- $thead.append($hr);
134
- $table.append($thead);
135
- // Body
136
- var $tbody = $('<tbody>');
137
- (config.rows || []).forEach(function(row) {
138
- var $tr = $('<tr>');
123
+ var $table = $('<table class="plugincore-table">');
124
+
125
+ // Header
126
+ var $thead = $('<thead>');
127
+ var $hr = $('<tr>');
139
128
  config.columns.forEach(function(col) {
140
- var $td = $('<td>');
141
- var val = row[col.key];
142
- if (col.render) {
143
- var rendered = col.render(val, row);
144
- if (rendered && typeof rendered === 'object' && rendered.jquery) {
145
- $td.append(rendered);
146
- } else {
147
- $td.html(rendered != null ? String(rendered) : '');
148
- }
149
- } else {
150
- $td.text(val != null ? String(val) : '');
151
- }
152
- $tr.append($td);
129
+ $hr.append($('<th>').text(col.label));
153
130
  });
154
- $tbody.append($tr);
155
- });
156
- $table.append($tbody);
157
- return $table;
131
+ $thead.append($hr);
132
+ $table.append($thead);
133
+
134
+ // Body
135
+ var $tbody = $('<tbody>');
136
+ (config.rows || []).forEach(function(row) {
137
+ var $tr = $('<tr>');
138
+ config.columns.forEach(function(col) {
139
+ var $td = $('<td>');
140
+ var val = row[col.key];
141
+ if (col.render) {
142
+ var rendered = col.render(val, row);
143
+ if (rendered && typeof rendered === 'object' && rendered.jquery) {
144
+ $td.append(rendered);
145
+ } else {
146
+ $td.html(rendered != null ? String(rendered) : '');
147
+ }
148
+ } else {
149
+ $td.text(val != null ? String(val) : '');
150
+ }
151
+ $tr.append($td);
152
+ });
153
+ $tbody.append($tr);
154
+ });
155
+ $table.append($tbody);
156
+
157
+ return $table;
158
158
  };
159
+
160
+ /**
161
+ * PluginCore.tabs(tabs) → jQuery element
162
+ *
163
+ * tabs: [{ label: string, render($container) }]
164
+ *
165
+ * Builds and returns a jQuery UI tab widget element.
166
+ * Can be embedded in any container, including inside PluginCore.dialog render().
167
+ */
168
+ PluginCore.tabs = function(tabs) {
169
+ var uid = 'plugincore-tabs-' + Date.now();
170
+ var $tabsEl = $('<div>').attr('id', uid);
171
+ var $ul = $('<ul>');
172
+
173
+ (tabs || []).forEach(function(tab, i) {
174
+ var paneId = uid + '-pane-' + i;
175
+ $ul.append(
176
+ $('<li>').append($('<a>').attr('href', '#' + paneId).text(tab.label))
177
+ );
178
+ var $pane = $('<div>').attr('id', paneId);
179
+ if (tab.render) { tab.render($pane); }
180
+ $tabsEl.append($pane);
181
+ });
182
+
183
+ $tabsEl.prepend($ul);
184
+ $tabsEl.tabs();
185
+
186
+ return $tabsEl;
187
+ };
188
+
159
189
  /**
160
190
  * PluginCore.dialog(options) → { close() }
161
191
  *
162
192
  * options: {
163
- * title : string,
164
- * tabs : [{ label: string, render($container) }]
193
+ * title : string,
194
+ * render : function($container) - simple dialog; body passed directly
195
+ * tabs : [{ label: string, render($c) }] - tabbed dialog; delegates to PluginCore.tabs
165
196
  * }
166
197
  *
167
- * Uses jQuery UI tabs for the tab widget (already bundled with Node-RED).
198
+ * render and tabs can coexist: render is called first, then the tab widget is appended.
168
199
  * Closes on: close button click, overlay click, or Escape key.
169
200
  */
170
201
  PluginCore.dialog = function(options) {
171
- // Only one dialog at a time
172
- $('.plugincore-overlay').remove();
173
- var uid = 'plugincore-' + Date.now();
174
- var $overlay = $('<div class="plugincore-overlay">');
175
- var $dialog = $('<div class="plugincore-dialog">');
176
- // ── Title bar ──────────────────────────────────────────────────────
177
- var $titlebar = $('<div class="plugincore-dialog-titlebar">');
178
- $titlebar.append($('<span class="plugincore-dialog-title">').text(options.title || ''));
179
- var $closeBtn = $('<button type="button" class="ui-button ui-corner-all ui-widget plugincore-dialog-close" title="Close">' + '<span class="ui-icon ui-icon-closethick"></span></button>');
180
- $titlebar.append($closeBtn);
181
- // ── Body + jQuery UI tabs ──────────────────────────────────────────
182
- var $body = $('<div class="plugincore-dialog-body">');
183
- var $tabsEl = $('<div>').attr('id', uid + '-tabs');
184
- var $ul = $('<ul>');
185
- (options.tabs || []).forEach(function(tab, i) {
186
- var paneId = uid + '-pane-' + i;
187
- $ul.append($('<li>').append($('<a>').attr('href', '#' + paneId).text(tab.label)));
188
- var $pane = $('<div>').attr('id', paneId);
189
- if (tab.render) {
190
- tab.render($pane);
202
+ // Only one dialog at a time
203
+ $('.plugincore-overlay').remove();
204
+
205
+ var uid = 'plugincore-' + Date.now();
206
+
207
+ var $overlay = $('<div class="plugincore-overlay">');
208
+ var $dialog = $('<div class="plugincore-dialog">');
209
+
210
+ // ── Title bar ──────────────────────────────────────────────────────
211
+ var $titlebar = $('<div class="plugincore-dialog-titlebar">');
212
+ $titlebar.append(
213
+ $('<span class="plugincore-dialog-title">').text(options.title || '')
214
+ );
215
+ var $closeBtn = $(
216
+ '<button type="button" class="ui-button ui-corner-all ui-widget plugincore-dialog-close" title="Close">' +
217
+ '<span class="ui-icon ui-icon-closethick"></span></button>'
218
+ );
219
+ $titlebar.append($closeBtn);
220
+
221
+ // ── Body ──────────────────────────────────────────────────────────
222
+ var $body = $('<div class="plugincore-dialog-body">');
223
+
224
+ if (options.render) { options.render($body); }
225
+ if (options.tabs) { $body.append(PluginCore.tabs(options.tabs)); }
226
+
227
+ // ── Assemble ───────────────────────────────────────────────────────
228
+ $dialog.append($titlebar).append($body);
229
+ $overlay.append($dialog);
230
+ $('body').append($overlay);
231
+
232
+ // ── Close logic ───────────────────────────────────────────────────
233
+ var escNs = 'keydown.plugincore-dialog-' + uid;
234
+
235
+ function close() {
236
+ $overlay.fadeOut(150, function() { $overlay.remove(); });
237
+ $(document).off(escNs);
191
238
  }
192
- $tabsEl.append($pane);
193
- });
194
- $tabsEl.prepend($ul);
195
- $body.append($tabsEl);
196
- // ── Assemble ───────────────────────────────────────────────────────
197
- $dialog.append($titlebar).append($body);
198
- $overlay.append($dialog);
199
- $('body').append($overlay);
200
- // Initialise jQuery UI tabs (bundled with Node-RED)
201
- $tabsEl.tabs();
202
- // ── Close logic ───────────────────────────────────────────────────
203
- var escNs = 'keydown.plugincore-dialog-' + uid;
204
-
205
- function close() {
206
- $overlay.fadeOut(150, function() {
207
- $overlay.remove();
239
+
240
+ $closeBtn.on('click', close);
241
+ $overlay.on('click', function(e) {
242
+ if ($(e.target).is($overlay)) { close(); }
208
243
  });
209
- $(document).off(escNs);
210
- }
211
- $closeBtn.on('click', close);
212
- $overlay.on('click', function(e) {
213
- if ($(e.target).is($overlay)) {
214
- close();
215
- }
216
- });
217
- $(document).on(escNs, function(e) {
218
- if (e.key === 'Escape') {
219
- close();
220
- }
221
- });
222
- return {
223
- close: close
224
- };
244
+ $(document).on(escNs, function(e) {
245
+ if (e.key === 'Escape') { close(); }
246
+ });
247
+
248
+ return { close: close };
225
249
  };
226
250
 
227
251
  </script>
252
+
253
+
254
+
255
+ <!-- UpdateNginxHostNode -->
256
+
257
+ <style>
258
+ .node_label_white {
259
+ fill:white
260
+ }
261
+ </style>
262
+
263
+
264
+ <!-- logger -->
265
+
266
+ <style>
267
+ .editorgroupborder {
268
+ border-width:1px;
269
+ border-style:solid;
270
+ border-color:lightgray;
271
+ padding: 3px;
272
+ margin-top: 2px;
273
+ margin-bottom: 2px;
274
+ }
275
+
276
+ .editorsectionheading {
277
+ font-weight: 600;
278
+ margin-bottom:1px !important;
279
+ margin-top:6px !important;
280
+ }
281
+
282
+ .nomargin {
283
+ margin-bottom:1px !important;
284
+ margin-top:1px !important;
285
+ }
286
+
287
+ .slidecontainer {
288
+ width: 100%;
289
+ }
290
+
291
+ .slider {
292
+ -webkit-appearance: none;
293
+ appearance: none;
294
+ width: 100%;
295
+ height: 25px;
296
+ background: #d3d3d3;
297
+ outline: none;
298
+ opacity: 0.7;
299
+ -webkit-transition: .2s;
300
+ transition: opacity .2s;
301
+ }
302
+
303
+ .slider:hover {
304
+ opacity: 1;
305
+ }
306
+
307
+ .slider::-webkit-slider-thumb {
308
+ -webkit-appearance: none;
309
+ appearance: none;
310
+ width: 25px;
311
+ height: 25px;
312
+ background: #04AA6D;
313
+ cursor: pointer;
314
+ }
315
+
316
+ .slider::-moz-range-thumb {
317
+ width: 25px;
318
+ height: 25px;
319
+ background: #04AA6D;
320
+ cursor: pointer;
321
+ }
322
+
323
+ .towb_editorlabel {
324
+ width: 120px !important;
325
+ }
326
+ input.towb_editorfield, select.towb_editorfield, textarea.towb_editorfield {
327
+ width: 70% !important;
328
+ }
329
+ input.towb_editorfield_short, select.towb_editorfield_short {
330
+ width: 30% !important;
331
+ }
332
+
333
+ </style>
334
+
335
+ <script type="text/javascript">
336
+
337
+ // CSS
338
+ dropdownStyles = `
339
+ .loggertype-dropdown {
340
+ position: absolute;
341
+ background: white;
342
+ border: 1px solid #ccc;
343
+ border-radius: 4px;
344
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
345
+ max-height: 150px;
346
+ overflow-y: auto;
347
+ z-index: 1000;
348
+ min-width: 150px;
349
+ }
350
+ .loggertype-dropdown .dropdown-item {
351
+ padding: 6px 12px;
352
+ cursor: pointer;
353
+ }
354
+ .loggertype-dropdown .dropdown-item:hover {
355
+ background: #f0f0f0;
356
+ }
357
+ `;
358
+ $('<style>').text(dropdownStyles).appendTo('head');
359
+
360
+ </script>
361
+
362
+
363
+
364
+
228
365
  <script type="text/javascript">
229
366
  RED.nodes.registerType('NginxProxyManagerConfigNode', {
230
367
  category: 'config',
@@ -440,112 +577,7 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
440
577
  - [Nginx Proxy Manager - Project](https://nginxproxymanager.com/)
441
578
  - [Nginx Proxy Manager - GitHub](https://github.com/NginxProxyManager/nginx-proxy-manager)
442
579
  </script>
443
- <!-- UpdateNginxHostNode -->
444
- <style>
445
- .node_label_white {
446
- fill: white
447
- }
448
-
449
- </style>
450
- <!-- logger -->
451
- <style>
452
- .editorgroupborder {
453
- border-width: 1px;
454
- border-style: solid;
455
- border-color: lightgray;
456
- padding: 3px;
457
- margin-top: 2px;
458
- margin-bottom: 2px;
459
- }
460
-
461
- .editorsectionheading {
462
- font-weight: 600;
463
- margin-bottom: 1px !important;
464
- margin-top: 6px !important;
465
- }
466
-
467
- .nomargin {
468
- margin-bottom: 1px !important;
469
- margin-top: 1px !important;
470
- }
471
-
472
- .slidecontainer {
473
- width: 100%;
474
- }
475
-
476
- .slider {
477
- -webkit-appearance: none;
478
- appearance: none;
479
- width: 100%;
480
- height: 25px;
481
- background: #d3d3d3;
482
- outline: none;
483
- opacity: 0.7;
484
- -webkit-transition: .2s;
485
- transition: opacity .2s;
486
- }
487
-
488
- .slider:hover {
489
- opacity: 1;
490
- }
491
-
492
- .slider::-webkit-slider-thumb {
493
- -webkit-appearance: none;
494
- appearance: none;
495
- width: 25px;
496
- height: 25px;
497
- background: #04AA6D;
498
- cursor: pointer;
499
- }
500
-
501
- .slider::-moz-range-thumb {
502
- width: 25px;
503
- height: 25px;
504
- background: #04AA6D;
505
- cursor: pointer;
506
- }
507
580
 
508
- .towb_editorlabel {
509
- width: 120px !important;
510
- }
511
-
512
- input.towb_editorfield,
513
- select.towb_editorfield,
514
- textarea.towb_editorfield {
515
- width: 70% !important;
516
- }
517
-
518
- input.towb_editorfield_short,
519
- select.towb_editorfield_short {
520
- width: 30% !important;
521
- }
522
-
523
- </style>
524
- <script type="text/javascript">
525
- // CSS
526
- dropdownStyles = `
527
- .loggertype-dropdown {
528
- position: absolute;
529
- background: white;
530
- border: 1px solid #ccc;
531
- border-radius: 4px;
532
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
533
- max-height: 150px;
534
- overflow-y: auto;
535
- z-index: 1000;
536
- min-width: 150px;
537
- }
538
- .loggertype-dropdown .dropdown-item {
539
- padding: 6px 12px;
540
- cursor: pointer;
541
- }
542
- .loggertype-dropdown .dropdown-item:hover {
543
- background: #f0f0f0;
544
- }
545
- `;
546
- $('<style>').text(dropdownStyles).appendTo('head');
547
-
548
- </script>
549
581
  <script type="text/javascript">
550
582
  RED.nodes.registerType('UpdateNginxHostNode', {
551
583
  category: 'nginxproxymanager',
@@ -592,8 +624,9 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
592
624
  required: true
593
625
  },
594
626
  metricsReference: {
595
- type: 'MetricsConfigNode',
596
- required: false
627
+ required: false,
628
+ value: '',
629
+ type: 'DelegatedConfigReferenceNode'
597
630
  },
598
631
  },
599
632
  oneditprepare: function() {
@@ -604,11 +637,14 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
604
637
  // **** logger **** //
605
638
  {
606
639
  let node = this;
640
+ let templateConfig = {};
607
641
  // controls.
608
642
  let logEnabled = $("#node-input-logEnabled");
609
643
  let logTemplateEnabled = $("#node-input-logTemplateOverrideEnabled");
610
644
  let logTemplateEnabledSection = $("#section_logTemplateOverrideEnabled");
611
645
  let logEnabledSection = $("#section_logEnabled");
646
+ let loggerSection = $("#section_loggerconfig");
647
+ loggerSection.hide();
612
648
  // functions.
613
649
  let getLoggerTypes = async function() {
614
650
  let types = [];
@@ -732,26 +768,148 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
732
768
  loggerEditButton.removeClass("disabled")
733
769
  }
734
770
  });
735
- // lastly, make sure that we set the correct value on the logger selector.
736
- updateLoggerSelectorList().then(() => {
737
- loggerSelector.val(node.logger);
738
- loggerSelector.trigger('change');
771
+ // Show the logger section only if at least one logger type is registered.
772
+ // If nodered_logging (or any other logger provider) is not installed, the section stays hidden.
773
+ getLoggerTypes().then(loggerTypes => {
774
+ if (loggerTypes.length === 0) return;
775
+ loggerSection.show();
776
+ updateLoggerSelectorList().then(() => {
777
+ loggerSelector.val(node.logger);
778
+ loggerSelector.trigger('change');
779
+ });
739
780
  });
740
781
  }
741
782
  // **** metrics **** //
742
783
  {
743
784
  let node = this;
785
+ let templateConfig = {};
744
786
  let metricsEnabled = $("#node-input-metricsEnabled");
745
- let metricsEnabledSection = $("#section_metricsEnabled");
787
+ let metricsSection = $("#section_metricsconfig");
788
+ let metricsContainer = metricsEnabled.closest(".editorgroupborder");
789
+ let metricsEnabledSection = metricsContainer.find("#section_metricsEnabled");
790
+ let metricsEnableCheck = metricsContainer.find(".metricsEnableCheck");
791
+ metricsSection.hide();
792
+ if (templateConfig.showBorder === false) {
793
+ metricsSection.find(".editorsectionheading").hide();
794
+ metricsSection.find(".editorgroupborder").css({
795
+ border: "none",
796
+ padding: 0,
797
+ margin: 0
798
+ });
799
+ }
800
+ if (templateConfig.showEnable === false) {
801
+ metricsEnableCheck.hide();
802
+ metricsEnabledSection.show();
803
+ }
804
+ let getMetricsProviderTypes = async function() {
805
+ let types = [];
806
+ await $.ajax({
807
+ url: "nodetypeservice/find?tag=MetricsProvider",
808
+ type: "GET",
809
+ contentType: "application/json; charset=utf-8",
810
+ success: (response) => {
811
+ types = response;
812
+ },
813
+ error: (jqXHR, textStatus, errorThrown) => {
814
+ console.log(jqXHR, textStatus, errorThrown);
815
+ },
816
+ });
817
+ return types;
818
+ };
819
+ let getMetricsProviders = async () => {
820
+ let providers = [];
821
+ let providerTypes = (await getMetricsProviderTypes()).map(t => t.id);
822
+ RED.nodes.eachConfig(cfg => {
823
+ if (providerTypes.includes(cfg.type)) {
824
+ providers.push({
825
+ id: cfg.id,
826
+ name: cfg.label(),
827
+ type: cfg.type
828
+ });
829
+ }
830
+ });
831
+ return providers;
832
+ };
833
+ let updateMetricsSelectorList = async () => {
834
+ metricsSelector.empty();
835
+ (await getMetricsProviders()).forEach(provider => {
836
+ $('<option value="' + provider.id + '">' + provider.name + '</option>').appendTo(metricsSelector);
837
+ });
838
+ $('<option value="_ADD_">none</option>').appendTo(metricsSelector);
839
+ };
746
840
  metricsEnabled.on('change', function() {
747
841
  if (metricsEnabled.prop("checked")) {
748
842
  metricsEnabledSection.show();
749
- node._def.defaults.metricsReference.required = true;
750
843
  } else {
751
- metricsEnabledSection.hide()
752
- node._def.defaults.metricsReference.required = false;
844
+ metricsEnabledSection.hide();
845
+ }
846
+ });
847
+ let metricsSelector = metricsContainer.find("#metrics-selector");
848
+ let metricsEditButton = metricsContainer.find("#metrics-edit-btn");
849
+ let metricsAddButton = metricsContainer.find("#metrics-add-btn");
850
+ metricsEditButton.on('click', async function(event) {
851
+ event.stopPropagation();
852
+ if (metricsEditButton.hasClass("disabled")) return;
853
+ let selectedProvider = (await getMetricsProviders()).find(p => p.id === metricsSelector.val());
854
+ if (selectedProvider) {
855
+ RED.editor.editConfig("#metrics-selector", selectedProvider.type, selectedProvider.id);
856
+ }
857
+ });
858
+ metricsAddButton.on('click', function(event) {
859
+ event.stopPropagation();
860
+ let $btn = $(event.currentTarget);
861
+ let btnOffset = $btn.offset();
862
+ let btnH = $btn.outerHeight();
863
+ let btnW = $btn.outerWidth();
864
+ $('.metricstype-dropdown').remove();
865
+ getMetricsProviderTypes().then(providerTypes => {
866
+ let $dropdown = $('<div class="metricstype-dropdown red-ui-editor"></div>').css({
867
+ position: 'absolute',
868
+ zIndex: 1000
869
+ });
870
+ providerTypes.forEach(providerType => {
871
+ $('<div class="dropdown-item"></div>').text(providerType.name).data('value', providerType.id).css({
872
+ padding: '4px 8px',
873
+ cursor: 'pointer'
874
+ }).appendTo($dropdown);
875
+ });
876
+ $('body').append($dropdown);
877
+ $dropdown.css({
878
+ top: btnOffset.top + btnH,
879
+ left: Math.max(0, btnOffset.left + btnW - $dropdown.outerWidth())
880
+ });
881
+ $(document).on('mousedown.metricsdropdown', function(e) {
882
+ if (!$(e.target).closest('.metricstype-dropdown').length) {
883
+ $dropdown.remove();
884
+ $(document).off('mousedown.metricsdropdown');
885
+ }
886
+ });
887
+ $dropdown.on('click', '.dropdown-item', function(e) {
888
+ e.stopPropagation();
889
+ const selectedValue = $(this).data('value');
890
+ $dropdown.remove();
891
+ RED.editor.editConfig("#metrics-selector", selectedValue, "_ADD_");
892
+ });
893
+ });
894
+ });
895
+ metricsSelector.on("focus", updateMetricsSelectorList);
896
+ metricsSelector.on('change', function() {
897
+ if ("_ADD_" === metricsSelector.val()) {
898
+ metricsEditButton.addClass("disabled");
899
+ } else {
900
+ metricsEditButton.removeClass("disabled");
753
901
  }
754
902
  });
903
+ // Show the metrics section only if at least one metrics provider type is registered.
904
+ // If nodered_prometheus (or any other provider) is not installed, the section stays hidden.
905
+ getMetricsProviderTypes().then(providerTypes => {
906
+ if (providerTypes.length === 0) return;
907
+ metricsSection.show();
908
+ updateMetricsSelectorList().then(() => {
909
+ metricsSelector.val(node.metricsReference);
910
+ metricsSelector.trigger('change');
911
+ });
912
+ });
755
913
  }
756
914
  },
757
915
  oneditsave: function() {
@@ -761,6 +919,8 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
761
919
  }
762
920
  // **** logger **** //
763
921
  {
922
+ let node = this;
923
+ let templateConfig = {};
764
924
  node = this;
765
925
  var selectedLogger = $("#logger-selector").val();
766
926
  node.logger = (selectedLogger && selectedLogger !== "_ADD_") ? selectedLogger : '';
@@ -769,7 +929,16 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
769
929
  delete node.logTemplateOverrideEditor;
770
930
  }
771
931
  // **** metrics **** //
772
- {}
932
+ {
933
+ let node = this;
934
+ let templateConfig = {};
935
+ node = this;
936
+ var selectedProvider = $("#metrics-selector").val();
937
+ node.metricsReference = (selectedProvider && selectedProvider !== "_ADD_") ? selectedProvider : '';
938
+ if (templateConfig.showEnable === false) {
939
+ node.metricsEnabled = !!node.metricsReference;
940
+ }
941
+ }
773
942
  },
774
943
  oneditcancel: function() {},
775
944
  oneditdelete: function() {},
@@ -799,13 +968,14 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
799
968
  </div>
800
969
  <div class="editorgroupborder">
801
970
  <div class="form-row nomargin logEnableCheck">
802
- <input type="checkbox" id="node-input-logEnabled" placeholder="logEnabled" value="false" style="margin:8px 0 10px 102px; width:20px;">
803
- <label style="width:auto" for="node-input-logEnabled"><span>Enable Logging</span></label>
971
+ <label class="towb_editorlabel">&nbsp;</label>
972
+ <input class="towb_checkbox" type="checkbox" id="node-input-logEnabled" placeholder="logEnabled" value="false">
973
+ <label class="towb_checkboxlabel" for="node-input-logEnabled"><span>Enable Logging</span></label>
804
974
  </div>
805
975
 
806
976
  <div id="section_logEnabled">
807
977
  <div class="form-row nomargin">
808
- <label for="logger-selector">Logger</label>
978
+ <label class="towb_editorlabel" for="logger-selector">Logger</label>
809
979
  <div style="width: 70%; display: inline-flex;">
810
980
  <select id="logger-selector" style="flex-grow: 1;" class="">
811
981
  <option value="_ADD_">none</option>
@@ -820,8 +990,9 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
820
990
  </div>
821
991
 
822
992
  <div class="form-row nomargin">
823
- <input type="checkbox" id="node-input-logTemplateOverrideEnabled" placeholder="" value="false" style="margin:8px 0 10px 102px; width:20px;">
824
- <label style="width:auto" for="node-input-logTemplateOverrideEnabled"><span>Override Template</span></label>
993
+ <label class="towb_editorlabel">&nbsp;</label>
994
+ <input class="towb_checkbox" type="checkbox" id="node-input-logTemplateOverrideEnabled" placeholder="" value="false">
995
+ <label class="towb_checkboxlabel" for="node-input-logTemplateOverrideEnabled"><span>Override Template</span></label>
825
996
  </div>
826
997
 
827
998
  <div id="section_logTemplateOverrideEnabled">
@@ -843,14 +1014,25 @@ Connection configuration for an Nginx Proxy Manager instance. Referenced by all
843
1014
  </div>
844
1015
  <div class="editorgroupborder">
845
1016
  <div class="form-row nomargin metricsEnableCheck">
846
- <input type="checkbox" id="node-input-metricsEnabled" value="false" style="margin:8px 0 10px 102px; width:20px;" />
847
- <label style="width:auto" for="node-input-metricsEnabled"><span>Enable Metrics</span></label>
1017
+ <label class="towb_editorlabel">&nbsp;</label>
1018
+ <input class="towb_checkbox" type="checkbox" id="node-input-metricsEnabled" value="false" />
1019
+ <label class="towb_checkboxlabel" for="node-input-metricsEnabled"><span>Enable Metrics</span></label>
848
1020
  </div>
849
1021
 
850
1022
  <div id="section_metricsEnabled">
851
1023
  <div class="form-row nomargin">
852
- <label class="towb_editorlabel" for="node-input-metricsReference">Metric Collector</label>
853
- <input id="node-input-metricsReference" placeholder="metrics" />
1024
+ <label class="towb_editorlabel" for="metrics-selector">Metric Provider</label>
1025
+ <div style="width: 70%; display: inline-flex;">
1026
+ <select id="metrics-selector" style="flex-grow: 1; min-width: 0;">
1027
+ <option value="_ADD_">none</option>
1028
+ </select>
1029
+ <a id="metrics-edit-btn" class="red-ui-button disabled" style="margin-left: 10px; flex-shrink: 0;">
1030
+ <i class="fa fa-pencil"></i>
1031
+ </a>
1032
+ <a id="metrics-add-btn" class="red-ui-button" style="margin-left: 10px; flex-shrink: 0;">
1033
+ <i class="fa fa-plus"></i>
1034
+ </a>
1035
+ </div>
854
1036
  </div>
855
1037
  </div>
856
1038
  </div>
@@ -931,107 +1113,9 @@ The original message is forwarded unchanged after the operation completes.
931
1113
 
932
1114
  ### Metrics
933
1115
  : *enable metrics* (boolean) : if checked, then the node will produce metrics output to the specified metrics provider.
934
- : *metric collector* (metricconfig) : the collection point or grouping where this particular metric will be attached.
1116
+ : *metric provider* (metricsconfig) : the metrics backend that this node will report to.
935
1117
  </script>
936
- <!-- logger -->
937
- <style>
938
- .editorgroupborder {
939
- border-width: 1px;
940
- border-style: solid;
941
- border-color: lightgray;
942
- padding: 3px;
943
- margin-top: 2px;
944
- margin-bottom: 2px;
945
- }
946
-
947
- .editorsectionheading {
948
- font-weight: 600;
949
- margin-bottom: 1px !important;
950
- margin-top: 6px !important;
951
- }
952
-
953
- .nomargin {
954
- margin-bottom: 1px !important;
955
- margin-top: 1px !important;
956
- }
957
-
958
- .slidecontainer {
959
- width: 100%;
960
- }
961
-
962
- .slider {
963
- -webkit-appearance: none;
964
- appearance: none;
965
- width: 100%;
966
- height: 25px;
967
- background: #d3d3d3;
968
- outline: none;
969
- opacity: 0.7;
970
- -webkit-transition: .2s;
971
- transition: opacity .2s;
972
- }
973
-
974
- .slider:hover {
975
- opacity: 1;
976
- }
977
-
978
- .slider::-webkit-slider-thumb {
979
- -webkit-appearance: none;
980
- appearance: none;
981
- width: 25px;
982
- height: 25px;
983
- background: #04AA6D;
984
- cursor: pointer;
985
- }
986
-
987
- .slider::-moz-range-thumb {
988
- width: 25px;
989
- height: 25px;
990
- background: #04AA6D;
991
- cursor: pointer;
992
- }
993
-
994
- .towb_editorlabel {
995
- width: 120px !important;
996
- }
997
-
998
- input.towb_editorfield,
999
- select.towb_editorfield,
1000
- textarea.towb_editorfield {
1001
- width: 70% !important;
1002
- }
1003
-
1004
- input.towb_editorfield_short,
1005
- select.towb_editorfield_short {
1006
- width: 30% !important;
1007
- }
1008
-
1009
- </style>
1010
- <script type="text/javascript">
1011
- // CSS
1012
- dropdownStyles = `
1013
- .loggertype-dropdown {
1014
- position: absolute;
1015
- background: white;
1016
- border: 1px solid #ccc;
1017
- border-radius: 4px;
1018
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
1019
- max-height: 150px;
1020
- overflow-y: auto;
1021
- z-index: 1000;
1022
- min-width: 150px;
1023
- }
1024
- .loggertype-dropdown .dropdown-item {
1025
- padding: 6px 12px;
1026
- cursor: pointer;
1027
- }
1028
- .loggertype-dropdown .dropdown-item:hover {
1029
- background: #f0f0f0;
1030
- }
1031
- `;
1032
- $('<style>').text(dropdownStyles).appendTo('head');
1033
1118
 
1034
- </script>
1035
1119
  <script type="text/javascript">
1036
1120
  RED.nodes.registerType('NginxGetHostsNode', {
1037
1121
  category: 'nginxproxymanager',
@@ -1078,8 +1162,9 @@ The original message is forwarded unchanged after the operation completes.
1078
1162
  required: true
1079
1163
  },
1080
1164
  metricsReference: {
1081
- type: 'MetricsConfigNode',
1082
- required: false
1165
+ required: false,
1166
+ value: '',
1167
+ type: 'DelegatedConfigReferenceNode'
1083
1168
  },
1084
1169
  },
1085
1170
  oneditprepare: function() {
@@ -1093,11 +1178,14 @@ The original message is forwarded unchanged after the operation completes.
1093
1178
  // **** logger **** //
1094
1179
  {
1095
1180
  let node = this;
1181
+ let templateConfig = {};
1096
1182
  // controls.
1097
1183
  let logEnabled = $("#node-input-logEnabled");
1098
1184
  let logTemplateEnabled = $("#node-input-logTemplateOverrideEnabled");
1099
1185
  let logTemplateEnabledSection = $("#section_logTemplateOverrideEnabled");
1100
1186
  let logEnabledSection = $("#section_logEnabled");
1187
+ let loggerSection = $("#section_loggerconfig");
1188
+ loggerSection.hide();
1101
1189
  // functions.
1102
1190
  let getLoggerTypes = async function() {
1103
1191
  let types = [];
@@ -1221,26 +1309,148 @@ The original message is forwarded unchanged after the operation completes.
1221
1309
  loggerEditButton.removeClass("disabled")
1222
1310
  }
1223
1311
  });
1224
- // lastly, make sure that we set the correct value on the logger selector.
1225
- updateLoggerSelectorList().then(() => {
1226
- loggerSelector.val(node.logger);
1227
- loggerSelector.trigger('change');
1312
+ // Show the logger section only if at least one logger type is registered.
1313
+ // If nodered_logging (or any other logger provider) is not installed, the section stays hidden.
1314
+ getLoggerTypes().then(loggerTypes => {
1315
+ if (loggerTypes.length === 0) return;
1316
+ loggerSection.show();
1317
+ updateLoggerSelectorList().then(() => {
1318
+ loggerSelector.val(node.logger);
1319
+ loggerSelector.trigger('change');
1320
+ });
1228
1321
  });
1229
1322
  }
1230
1323
  // **** metrics **** //
1231
1324
  {
1232
1325
  let node = this;
1326
+ let templateConfig = {};
1233
1327
  let metricsEnabled = $("#node-input-metricsEnabled");
1234
- let metricsEnabledSection = $("#section_metricsEnabled");
1328
+ let metricsSection = $("#section_metricsconfig");
1329
+ let metricsContainer = metricsEnabled.closest(".editorgroupborder");
1330
+ let metricsEnabledSection = metricsContainer.find("#section_metricsEnabled");
1331
+ let metricsEnableCheck = metricsContainer.find(".metricsEnableCheck");
1332
+ metricsSection.hide();
1333
+ if (templateConfig.showBorder === false) {
1334
+ metricsSection.find(".editorsectionheading").hide();
1335
+ metricsSection.find(".editorgroupborder").css({
1336
+ border: "none",
1337
+ padding: 0,
1338
+ margin: 0
1339
+ });
1340
+ }
1341
+ if (templateConfig.showEnable === false) {
1342
+ metricsEnableCheck.hide();
1343
+ metricsEnabledSection.show();
1344
+ }
1345
+ let getMetricsProviderTypes = async function() {
1346
+ let types = [];
1347
+ await $.ajax({
1348
+ url: "nodetypeservice/find?tag=MetricsProvider",
1349
+ type: "GET",
1350
+ contentType: "application/json; charset=utf-8",
1351
+ success: (response) => {
1352
+ types = response;
1353
+ },
1354
+ error: (jqXHR, textStatus, errorThrown) => {
1355
+ console.log(jqXHR, textStatus, errorThrown);
1356
+ },
1357
+ });
1358
+ return types;
1359
+ };
1360
+ let getMetricsProviders = async () => {
1361
+ let providers = [];
1362
+ let providerTypes = (await getMetricsProviderTypes()).map(t => t.id);
1363
+ RED.nodes.eachConfig(cfg => {
1364
+ if (providerTypes.includes(cfg.type)) {
1365
+ providers.push({
1366
+ id: cfg.id,
1367
+ name: cfg.label(),
1368
+ type: cfg.type
1369
+ });
1370
+ }
1371
+ });
1372
+ return providers;
1373
+ };
1374
+ let updateMetricsSelectorList = async () => {
1375
+ metricsSelector.empty();
1376
+ (await getMetricsProviders()).forEach(provider => {
1377
+ $('<option value="' + provider.id + '">' + provider.name + '</option>').appendTo(metricsSelector);
1378
+ });
1379
+ $('<option value="_ADD_">none</option>').appendTo(metricsSelector);
1380
+ };
1235
1381
  metricsEnabled.on('change', function() {
1236
1382
  if (metricsEnabled.prop("checked")) {
1237
1383
  metricsEnabledSection.show();
1238
- node._def.defaults.metricsReference.required = true;
1239
1384
  } else {
1240
- metricsEnabledSection.hide()
1241
- node._def.defaults.metricsReference.required = false;
1385
+ metricsEnabledSection.hide();
1386
+ }
1387
+ });
1388
+ let metricsSelector = metricsContainer.find("#metrics-selector");
1389
+ let metricsEditButton = metricsContainer.find("#metrics-edit-btn");
1390
+ let metricsAddButton = metricsContainer.find("#metrics-add-btn");
1391
+ metricsEditButton.on('click', async function(event) {
1392
+ event.stopPropagation();
1393
+ if (metricsEditButton.hasClass("disabled")) return;
1394
+ let selectedProvider = (await getMetricsProviders()).find(p => p.id === metricsSelector.val());
1395
+ if (selectedProvider) {
1396
+ RED.editor.editConfig("#metrics-selector", selectedProvider.type, selectedProvider.id);
1397
+ }
1398
+ });
1399
+ metricsAddButton.on('click', function(event) {
1400
+ event.stopPropagation();
1401
+ let $btn = $(event.currentTarget);
1402
+ let btnOffset = $btn.offset();
1403
+ let btnH = $btn.outerHeight();
1404
+ let btnW = $btn.outerWidth();
1405
+ $('.metricstype-dropdown').remove();
1406
+ getMetricsProviderTypes().then(providerTypes => {
1407
+ let $dropdown = $('<div class="metricstype-dropdown red-ui-editor"></div>').css({
1408
+ position: 'absolute',
1409
+ zIndex: 1000
1410
+ });
1411
+ providerTypes.forEach(providerType => {
1412
+ $('<div class="dropdown-item"></div>').text(providerType.name).data('value', providerType.id).css({
1413
+ padding: '4px 8px',
1414
+ cursor: 'pointer'
1415
+ }).appendTo($dropdown);
1416
+ });
1417
+ $('body').append($dropdown);
1418
+ $dropdown.css({
1419
+ top: btnOffset.top + btnH,
1420
+ left: Math.max(0, btnOffset.left + btnW - $dropdown.outerWidth())
1421
+ });
1422
+ $(document).on('mousedown.metricsdropdown', function(e) {
1423
+ if (!$(e.target).closest('.metricstype-dropdown').length) {
1424
+ $dropdown.remove();
1425
+ $(document).off('mousedown.metricsdropdown');
1426
+ }
1427
+ });
1428
+ $dropdown.on('click', '.dropdown-item', function(e) {
1429
+ e.stopPropagation();
1430
+ const selectedValue = $(this).data('value');
1431
+ $dropdown.remove();
1432
+ RED.editor.editConfig("#metrics-selector", selectedValue, "_ADD_");
1433
+ });
1434
+ });
1435
+ });
1436
+ metricsSelector.on("focus", updateMetricsSelectorList);
1437
+ metricsSelector.on('change', function() {
1438
+ if ("_ADD_" === metricsSelector.val()) {
1439
+ metricsEditButton.addClass("disabled");
1440
+ } else {
1441
+ metricsEditButton.removeClass("disabled");
1242
1442
  }
1243
1443
  });
1444
+ // Show the metrics section only if at least one metrics provider type is registered.
1445
+ // If nodered_prometheus (or any other provider) is not installed, the section stays hidden.
1446
+ getMetricsProviderTypes().then(providerTypes => {
1447
+ if (providerTypes.length === 0) return;
1448
+ metricsSection.show();
1449
+ updateMetricsSelectorList().then(() => {
1450
+ metricsSelector.val(node.metricsReference);
1451
+ metricsSelector.trigger('change');
1452
+ });
1453
+ });
1244
1454
  }
1245
1455
  },
1246
1456
  oneditsave: function() {
@@ -1250,6 +1460,8 @@ The original message is forwarded unchanged after the operation completes.
1250
1460
  }
1251
1461
  // **** logger **** //
1252
1462
  {
1463
+ let node = this;
1464
+ let templateConfig = {};
1253
1465
  node = this;
1254
1466
  var selectedLogger = $("#logger-selector").val();
1255
1467
  node.logger = (selectedLogger && selectedLogger !== "_ADD_") ? selectedLogger : '';
@@ -1258,7 +1470,16 @@ The original message is forwarded unchanged after the operation completes.
1258
1470
  delete node.logTemplateOverrideEditor;
1259
1471
  }
1260
1472
  // **** metrics **** //
1261
- {}
1473
+ {
1474
+ let node = this;
1475
+ let templateConfig = {};
1476
+ node = this;
1477
+ var selectedProvider = $("#metrics-selector").val();
1478
+ node.metricsReference = (selectedProvider && selectedProvider !== "_ADD_") ? selectedProvider : '';
1479
+ if (templateConfig.showEnable === false) {
1480
+ node.metricsEnabled = !!node.metricsReference;
1481
+ }
1482
+ }
1262
1483
  },
1263
1484
  oneditcancel: function() {},
1264
1485
  oneditdelete: function() {},
@@ -1293,13 +1514,14 @@ The original message is forwarded unchanged after the operation completes.
1293
1514
  </div>
1294
1515
  <div class="editorgroupborder">
1295
1516
  <div class="form-row nomargin logEnableCheck">
1296
- <input type="checkbox" id="node-input-logEnabled" placeholder="logEnabled" value="false" style="margin:8px 0 10px 102px; width:20px;">
1297
- <label style="width:auto" for="node-input-logEnabled"><span>Enable Logging</span></label>
1517
+ <label class="towb_editorlabel">&nbsp;</label>
1518
+ <input class="towb_checkbox" type="checkbox" id="node-input-logEnabled" placeholder="logEnabled" value="false">
1519
+ <label class="towb_checkboxlabel" for="node-input-logEnabled"><span>Enable Logging</span></label>
1298
1520
  </div>
1299
1521
 
1300
1522
  <div id="section_logEnabled">
1301
1523
  <div class="form-row nomargin">
1302
- <label for="logger-selector">Logger</label>
1524
+ <label class="towb_editorlabel" for="logger-selector">Logger</label>
1303
1525
  <div style="width: 70%; display: inline-flex;">
1304
1526
  <select id="logger-selector" style="flex-grow: 1;" class="">
1305
1527
  <option value="_ADD_">none</option>
@@ -1314,8 +1536,9 @@ The original message is forwarded unchanged after the operation completes.
1314
1536
  </div>
1315
1537
 
1316
1538
  <div class="form-row nomargin">
1317
- <input type="checkbox" id="node-input-logTemplateOverrideEnabled" placeholder="" value="false" style="margin:8px 0 10px 102px; width:20px;">
1318
- <label style="width:auto" for="node-input-logTemplateOverrideEnabled"><span>Override Template</span></label>
1539
+ <label class="towb_editorlabel">&nbsp;</label>
1540
+ <input class="towb_checkbox" type="checkbox" id="node-input-logTemplateOverrideEnabled" placeholder="" value="false">
1541
+ <label class="towb_checkboxlabel" for="node-input-logTemplateOverrideEnabled"><span>Override Template</span></label>
1319
1542
  </div>
1320
1543
 
1321
1544
  <div id="section_logTemplateOverrideEnabled">
@@ -1337,14 +1560,25 @@ The original message is forwarded unchanged after the operation completes.
1337
1560
  </div>
1338
1561
  <div class="editorgroupborder">
1339
1562
  <div class="form-row nomargin metricsEnableCheck">
1340
- <input type="checkbox" id="node-input-metricsEnabled" value="false" style="margin:8px 0 10px 102px; width:20px;" />
1341
- <label style="width:auto" for="node-input-metricsEnabled"><span>Enable Metrics</span></label>
1563
+ <label class="towb_editorlabel">&nbsp;</label>
1564
+ <input class="towb_checkbox" type="checkbox" id="node-input-metricsEnabled" value="false" />
1565
+ <label class="towb_checkboxlabel" for="node-input-metricsEnabled"><span>Enable Metrics</span></label>
1342
1566
  </div>
1343
1567
 
1344
1568
  <div id="section_metricsEnabled">
1345
1569
  <div class="form-row nomargin">
1346
- <label class="towb_editorlabel" for="node-input-metricsReference">Metric Collector</label>
1347
- <input id="node-input-metricsReference" placeholder="metrics" />
1570
+ <label class="towb_editorlabel" for="metrics-selector">Metric Provider</label>
1571
+ <div style="width: 70%; display: inline-flex;">
1572
+ <select id="metrics-selector" style="flex-grow: 1; min-width: 0;">
1573
+ <option value="_ADD_">none</option>
1574
+ </select>
1575
+ <a id="metrics-edit-btn" class="red-ui-button disabled" style="margin-left: 10px; flex-shrink: 0;">
1576
+ <i class="fa fa-pencil"></i>
1577
+ </a>
1578
+ <a id="metrics-add-btn" class="red-ui-button" style="margin-left: 10px; flex-shrink: 0;">
1579
+ <i class="fa fa-plus"></i>
1580
+ </a>
1581
+ </div>
1348
1582
  </div>
1349
1583
  </div>
1350
1584
  </div>
@@ -1386,7 +1620,6 @@ The original message is forwarded with the specified property set to an array of
1386
1620
 
1387
1621
  ### Metrics
1388
1622
  : *enable metrics* (boolean) : if checked, then the node will produce metrics output to the specified metrics provider.
1389
- : *metric collector* (metricconfig) : the collection point or grouping where this particular metric will be attached.
1623
+ : *metric provider* (metricsconfig) : the metrics backend that this node will report to.
1390
1624
  </script>
1391
-
1392
1625