node-red-contrib-uos-nats 0.1.53 → 0.1.55
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/nodes/datahub-input.html +224 -554
- package/nodes/datahub-input.js +2 -2
- package/package.json +1 -1
package/nodes/datahub-input.html
CHANGED
|
@@ -1,334 +1,283 @@
|
|
|
1
1
|
<script type="text/javascript">
|
|
2
2
|
RED.nodes.registerType('datahub-input', {
|
|
3
|
-
category: '
|
|
4
|
-
color: '#
|
|
3
|
+
category: 'u-OS',
|
|
4
|
+
color: '#ff9900',
|
|
5
5
|
defaults: {
|
|
6
|
-
name: { value:
|
|
7
|
-
connection: { type:
|
|
8
|
-
providerId: { value:
|
|
9
|
-
variablesText: { value:
|
|
10
|
-
manualVariables: { value:
|
|
11
|
-
|
|
6
|
+
name: { value: "" },
|
|
7
|
+
connection: { type: "uos-config", required: true },
|
|
8
|
+
providerId: { value: "", required: true },
|
|
9
|
+
variablesText: { value: "" },
|
|
10
|
+
manualVariables: { value: "" },
|
|
11
|
+
singleName: { value: "" },
|
|
12
|
+
singleId: { value: "" },
|
|
13
|
+
mode: { value: "auto" },
|
|
14
|
+
triggerMode: { value: "event" }, // event or poll
|
|
15
|
+
pollingInterval: { value: 0, validate: RED.validators.number() }
|
|
12
16
|
},
|
|
13
17
|
inputs: 1,
|
|
14
18
|
outputs: 1,
|
|
15
19
|
icon: "white/datahub-input.svg",
|
|
20
|
+
label: function () {
|
|
21
|
+
if (this.name) return this.name;
|
|
22
|
+
if (this.mode === 'manual_single' && this.singleName) return this.singleName;
|
|
23
|
+
return "u-OS " + (this.providerId || "Data Hub");
|
|
24
|
+
},
|
|
25
|
+
paletteLabel: "u-OS Input",
|
|
16
26
|
oneditprepare: function () {
|
|
17
27
|
const node = this;
|
|
18
|
-
const $config = $('#node-input-connection');
|
|
19
|
-
const $providerHidden = $('#node-input-providerId');
|
|
20
|
-
const $providerSelect = $('#datahub-provider-select');
|
|
21
|
-
const $providerManual = $('#datahub-provider-manual');
|
|
22
|
-
const $providerRefresh = $('#datahub-provider-refresh');
|
|
23
|
-
const $providerStatus = $('#datahub-provider-status');
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
const $
|
|
27
|
-
const $
|
|
28
|
-
const $
|
|
29
|
-
const $
|
|
29
|
+
// --- Mode Visibility Logic ---
|
|
30
|
+
const $modeSelect = $('#node-input-mode');
|
|
31
|
+
const $autoRow = $('#mode-auto-row');
|
|
32
|
+
const $manualSingleRow = $('#mode-manual-single-row');
|
|
33
|
+
const $manualMultiRow = $('#mode-manual-multi-row');
|
|
34
|
+
|
|
35
|
+
const updateModeVisibility = () => {
|
|
36
|
+
const mode = $modeSelect.val();
|
|
37
|
+
$autoRow.hide();
|
|
38
|
+
$manualSingleRow.hide();
|
|
39
|
+
$manualMultiRow.hide();
|
|
40
|
+
|
|
41
|
+
if (mode === 'auto') $autoRow.show();
|
|
42
|
+
else if (mode === 'manual_single') $manualSingleRow.show();
|
|
43
|
+
else if (mode === 'manual_multi') $manualMultiRow.show();
|
|
44
|
+
};
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.split(',')
|
|
34
|
-
.map((entry) => entry.trim())
|
|
35
|
-
.filter((entry) => entry.length > 0);
|
|
46
|
+
$modeSelect.on('change', updateModeVisibility);
|
|
47
|
+
updateModeVisibility();
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
if (Array.isArray(payload)) {
|
|
43
|
-
return payload;
|
|
44
|
-
}
|
|
45
|
-
if (Array.isArray(payload.providers)) {
|
|
46
|
-
return payload.providers;
|
|
47
|
-
}
|
|
48
|
-
return [];
|
|
49
|
-
};
|
|
49
|
+
// --- Trigger Mode (Event/Poll) Visibility ---
|
|
50
|
+
const $triggerMode = $('#node-input-triggerMode');
|
|
51
|
+
const $pollRow = $('#poll-interval-row');
|
|
50
52
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (Array.isArray(payload)) {
|
|
57
|
-
return payload;
|
|
58
|
-
}
|
|
59
|
-
if (Array.isArray(payload.variables)) {
|
|
60
|
-
return payload.variables;
|
|
53
|
+
const updateTriggerVisibility = () => {
|
|
54
|
+
if ($triggerMode.val() === 'poll') {
|
|
55
|
+
$pollRow.show();
|
|
56
|
+
} else {
|
|
57
|
+
$pollRow.hide();
|
|
61
58
|
}
|
|
62
|
-
return [];
|
|
63
59
|
};
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const providerValue = (provider) => provider.id || provider.providerId || provider.name || '';
|
|
68
|
-
|
|
69
|
-
// API returns [{ "key": "..." }] for variables
|
|
70
|
-
const variableValue = (variable) => variable.key || variable.name || variable.path || variable.id || '';
|
|
71
|
-
const variableLabel = (variable) => variable.tagName || variable.key || variable.name || variable.path || variable.id || 'Unnamed variable';
|
|
61
|
+
$triggerMode.on('change', updateTriggerVisibility);
|
|
62
|
+
updateTriggerVisibility();
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
// --- Provider & Variables Loading (Auto Mode) ---
|
|
65
|
+
const $config = $('#node-input-connection');
|
|
66
|
+
const $providerSelect = $('#node-input-providerId');
|
|
67
|
+
const $providerRefresh = $('#node-input-provider-refresh');
|
|
68
|
+
const $varsContainer = $('#node-input-variables-container');
|
|
69
|
+
const $varsRefresh = $('#node-input-vars-refresh');
|
|
70
|
+
const $varsStatus = $('#vars-status');
|
|
71
|
+
const $variablesHidden = $('#node-input-variablesText');
|
|
77
72
|
|
|
78
73
|
let providerRequest = 0;
|
|
79
74
|
let variableRequest = 0;
|
|
80
75
|
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
$providerStatus.hide();
|
|
86
|
-
}
|
|
76
|
+
const normalizeProviders = (payload) => {
|
|
77
|
+
if (Array.isArray(payload)) return payload;
|
|
78
|
+
if (payload && Array.isArray(payload.providers)) return payload.providers;
|
|
79
|
+
return [];
|
|
87
80
|
};
|
|
88
|
-
const setVariableStatus = (text) => $variablesStatus.text(text || '');
|
|
89
81
|
|
|
90
|
-
const
|
|
91
|
-
|
|
82
|
+
const normalizeVariables = (payload) => {
|
|
83
|
+
if (Array.isArray(payload)) return payload;
|
|
84
|
+
if (payload && Array.isArray(payload.variables)) return payload.variables;
|
|
85
|
+
return [];
|
|
92
86
|
};
|
|
93
87
|
|
|
94
|
-
const
|
|
88
|
+
const providerValue = (p) => p.id || p.providerId || p.name;
|
|
89
|
+
const providerLabel = (p) => p.name || p.displayName || p.providerId || p.id;
|
|
90
|
+
const variableValue = (v) => v.key || v.name || v.path || v.id;
|
|
91
|
+
const variableLabel = (v) => v.tagName || v.key || v.name || v.path || v.id;
|
|
95
92
|
|
|
96
|
-
const
|
|
97
|
-
$providerSelect.hide().prop('disabled', true);
|
|
98
|
-
$providerManual.show().prop('disabled', false);
|
|
99
|
-
$providerManual.val(getProviderValue());
|
|
100
|
-
setProviderStatus(message || 'Enter the provider ID manually.');
|
|
101
|
-
};
|
|
93
|
+
const setVarsStatus = (msg) => $varsStatus.text(msg || '');
|
|
102
94
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
$
|
|
95
|
+
const syncVariablesField = () => {
|
|
96
|
+
const selected = [];
|
|
97
|
+
$varsContainer.find('input[type="checkbox"]:checked').each(function () {
|
|
98
|
+
selected.push($(this).val());
|
|
99
|
+
});
|
|
100
|
+
$variablesHidden.val(selected.join(','));
|
|
101
|
+
setVarsStatus(`${selected.length} variable(s) selected`);
|
|
106
102
|
};
|
|
107
103
|
|
|
108
104
|
const loadVariables = (providerId, keepSelection = false) => {
|
|
109
105
|
const configId = $config.val();
|
|
110
106
|
if (!configId || !providerId) {
|
|
111
|
-
$
|
|
112
|
-
|
|
107
|
+
$varsContainer.empty().append('<div style="color:#999; padding:10px; text-align:center;">Select a provider first</div>');
|
|
108
|
+
setVarsStatus('');
|
|
113
109
|
return;
|
|
114
110
|
}
|
|
111
|
+
|
|
115
112
|
const seq = ++variableRequest;
|
|
116
|
-
|
|
113
|
+
setVarsStatus('Loading...');
|
|
114
|
+
$varsContainer.empty().append('<div style="color:#999; padding:10px; text-align:center;"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
|
|
117
115
|
|
|
118
116
|
$.getJSON(`uos/providers/${configId}/${encodeURIComponent(providerId)}/variables`)
|
|
119
117
|
.done((payload) => {
|
|
120
118
|
if (seq !== variableRequest) return;
|
|
121
119
|
|
|
122
120
|
const vars = normalizeVariables(payload);
|
|
123
|
-
$
|
|
121
|
+
$varsContainer.empty();
|
|
122
|
+
|
|
124
123
|
if (!vars.length) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
syncVariablesField();
|
|
124
|
+
$varsContainer.append('<div style="color:#999; padding:10px; text-align:center;">No variables found</div>');
|
|
125
|
+
setVarsStatus('No variables');
|
|
128
126
|
return;
|
|
129
127
|
}
|
|
130
128
|
|
|
131
|
-
const preset = keepSelection
|
|
129
|
+
const preset = keepSelection
|
|
130
|
+
? ($variablesHidden.val() || '').split(',').map(e => e.trim()).filter(Boolean)
|
|
131
|
+
: (node.variablesText || '').split(',').map(e => e.trim()).filter(Boolean);
|
|
132
132
|
const currentSet = new Set(preset);
|
|
133
133
|
|
|
134
|
+
vars.sort((a, b) => (variableLabel(a) || '').localeCompare(variableLabel(b) || ''));
|
|
135
|
+
|
|
134
136
|
vars.forEach((variable) => {
|
|
135
137
|
const value = variableValue(variable);
|
|
136
138
|
if (!value) return;
|
|
137
139
|
|
|
138
|
-
const isChecked = currentSet.has(value)
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
$variablesContainer.find('input[type="checkbox"]').on('change', () => {
|
|
150
|
-
const selected = [];
|
|
151
|
-
$variablesContainer.find('input[type="checkbox"]:checked').each(function () {
|
|
152
|
-
selected.push($(this).val());
|
|
153
|
-
});
|
|
154
|
-
$variablesHidden.val(selected.join(','));
|
|
140
|
+
const isChecked = currentSet.has(value);
|
|
141
|
+
const row = $('<div style="margin-bottom:2px;"></div>');
|
|
142
|
+
const checkbox = $('<input type="checkbox">')
|
|
143
|
+
.val(value)
|
|
144
|
+
.prop('checked', isChecked)
|
|
145
|
+
.on('change', syncVariablesField);
|
|
146
|
+
const label = $('<label style="cursor:pointer; margin-bottom:0;"></label>')
|
|
147
|
+
.append(checkbox)
|
|
148
|
+
.append(' ' + variableLabel(variable));
|
|
149
|
+
row.append(label);
|
|
150
|
+
$varsContainer.append(row);
|
|
155
151
|
});
|
|
156
152
|
|
|
157
153
|
syncVariablesField();
|
|
158
|
-
setVariableStatus('Select variables. Leave all unchecked to receive EVERYTHING.');
|
|
159
154
|
})
|
|
160
155
|
.fail((xhr) => {
|
|
161
|
-
|
|
156
|
+
if (seq !== variableRequest) return;
|
|
162
157
|
const error = xhr?.responseJSON?.error;
|
|
163
|
-
let msg = error || xhr.statusText || 'Failed to load
|
|
158
|
+
let msg = error || xhr.statusText || 'Failed to load';
|
|
164
159
|
if (xhr.status === 404 && error === 'config not found') {
|
|
165
|
-
msg = 'Config not deployed
|
|
160
|
+
msg = 'Config not deployed. Deploy first.';
|
|
166
161
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
syncVariablesField();
|
|
162
|
+
$varsContainer.empty().append(`<div style="color:#c55; padding:10px;">${msg}</div>`);
|
|
163
|
+
setVarsStatus('Error');
|
|
170
164
|
});
|
|
171
165
|
};
|
|
172
166
|
|
|
173
167
|
const loadProviders = (force = false) => {
|
|
174
168
|
const configId = $config.val();
|
|
175
169
|
if (!configId) {
|
|
176
|
-
$providerSelect.empty().append('<option value="">Select
|
|
177
|
-
setVariableStatus('');
|
|
178
|
-
$variablesContainer.empty().append('<div style="color:#aaa; font-style:italic; padding:5px;">Select a provider to load variables...</div>');
|
|
170
|
+
$providerSelect.empty().append('<option value="">Select Config first</option>').prop('disabled', true);
|
|
179
171
|
return;
|
|
180
172
|
}
|
|
181
173
|
|
|
182
174
|
const seq = ++providerRequest;
|
|
183
|
-
|
|
184
|
-
// Use cache only if not forced
|
|
185
|
-
if (!force && window.uOSProvidersCache && window.uOSProvidersCache[configId]) {
|
|
186
|
-
console.log('Using cached providers for', configId);
|
|
187
|
-
setTimeout(() => {
|
|
188
|
-
if (seq === providerRequest) populateProviders(window.uOSProvidersCache[configId]);
|
|
189
|
-
}, 0);
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
setProviderStatus('Loading providers…');
|
|
194
175
|
$providerSelect.prop('disabled', true);
|
|
195
|
-
// Removed showManualProvider/showSelectProvider logic - always assume Select
|
|
196
176
|
|
|
197
177
|
$.getJSON(`uos/providers/${configId}`)
|
|
198
178
|
.done((payload) => {
|
|
199
179
|
if (seq !== providerRequest) return;
|
|
200
|
-
// Update cache on success
|
|
201
180
|
const list = normalizeProviders(payload);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const error = xhr?.responseJSON?.error;
|
|
208
|
-
let msg = error || xhr.statusText || 'Failed to load providers.';
|
|
209
|
-
if (xhr.status === 404 && error === 'config not found') {
|
|
210
|
-
msg = 'Config not deployed yet. Please use "Test Connection" in Config Node or Deploy first.';
|
|
181
|
+
$providerSelect.empty();
|
|
182
|
+
|
|
183
|
+
if (!list.length) {
|
|
184
|
+
$providerSelect.append('<option value="">No providers found</option>').prop('disabled', true);
|
|
185
|
+
return;
|
|
211
186
|
}
|
|
212
|
-
$providerSelect.empty().append('<option value="">Error loading providers</option>').prop('disabled', true);
|
|
213
|
-
setProviderStatus(`Error: ${msg} - Click Refresh to retry.`);
|
|
214
|
-
// Do NOT switch to manual input
|
|
215
|
-
});
|
|
216
|
-
};
|
|
217
187
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
list.forEach((prov) => {
|
|
228
|
-
const value = providerValue(prov);
|
|
229
|
-
if (!value) return;
|
|
230
|
-
const option = $('<option></option>').attr('value', value).text(providerLabel(prov));
|
|
231
|
-
$providerSelect.append(option);
|
|
232
|
-
if (value === initialProvider) foundInitial = true;
|
|
233
|
-
});
|
|
234
|
-
$providerSelect.prop('disabled', false);
|
|
235
|
-
|
|
236
|
-
if (initialProvider && foundInitial) {
|
|
237
|
-
$providerSelect.val(initialProvider);
|
|
238
|
-
} else if (initialProvider) {
|
|
239
|
-
// Valid case: provider set but not in list? Or manual override needed?
|
|
240
|
-
// User said "no input", so we just show what we have.
|
|
241
|
-
// Optionally add the current unknown provider as an option
|
|
242
|
-
$providerSelect.append($('<option></option>').attr('value', initialProvider).text(initialProvider + ' (unknown)'));
|
|
243
|
-
$providerSelect.val(initialProvider);
|
|
244
|
-
}
|
|
188
|
+
let foundInitial = false;
|
|
189
|
+
list.forEach((prov) => {
|
|
190
|
+
const val = providerValue(prov);
|
|
191
|
+
if (!val) return;
|
|
192
|
+
const opt = $('<option></option>').val(val).text(providerLabel(prov));
|
|
193
|
+
$providerSelect.append(opt);
|
|
194
|
+
if (val === node.providerId) foundInitial = true;
|
|
195
|
+
});
|
|
196
|
+
$providerSelect.prop('disabled', false);
|
|
245
197
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
198
|
+
if (node.providerId && foundInitial) {
|
|
199
|
+
$providerSelect.val(node.providerId);
|
|
200
|
+
} else if (node.providerId) {
|
|
201
|
+
$providerSelect.append($('<option></option>').val(node.providerId).text(node.providerId + ' (unknown)'));
|
|
202
|
+
$providerSelect.val(node.providerId);
|
|
203
|
+
}
|
|
250
204
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
loadVariables(selected, false); // Reload vars for selected
|
|
255
|
-
};
|
|
205
|
+
if (!$providerSelect.val()) {
|
|
206
|
+
$providerSelect.val($providerSelect.find('option:first').val());
|
|
207
|
+
}
|
|
256
208
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
209
|
+
const selected = $providerSelect.val();
|
|
210
|
+
if (selected) loadVariables(selected, false);
|
|
211
|
+
})
|
|
212
|
+
.fail((xhr) => {
|
|
213
|
+
if (seq !== providerRequest) return;
|
|
214
|
+
$providerSelect.empty().append('<option value="">Error loading providers</option>').prop('disabled', true);
|
|
215
|
+
});
|
|
216
|
+
};
|
|
260
217
|
|
|
261
218
|
$providerSelect.on('change', () => {
|
|
262
|
-
const value = $providerSelect.val();
|
|
263
|
-
setProviderValue(value);
|
|
264
219
|
$variablesHidden.val('');
|
|
265
|
-
|
|
266
|
-
loadVariables(
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
$providerRefresh.on('click', () => {
|
|
270
|
-
loadProviders(true); // Force refresh
|
|
220
|
+
const val = $providerSelect.val();
|
|
221
|
+
if (val) loadVariables(val, false);
|
|
271
222
|
});
|
|
272
223
|
|
|
224
|
+
$providerRefresh.on('click', () => loadProviders(true));
|
|
273
225
|
$varsRefresh.on('click', () => {
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
226
|
+
const val = $providerSelect.val();
|
|
227
|
+
if (val) loadVariables(val, true);
|
|
276
228
|
});
|
|
277
229
|
|
|
278
|
-
$('#
|
|
279
|
-
$
|
|
230
|
+
$('#node-input-select-all').on('click', () => {
|
|
231
|
+
$varsContainer.find('input[type="checkbox"]').prop('checked', true).trigger('change');
|
|
280
232
|
});
|
|
281
233
|
|
|
282
|
-
$('#
|
|
283
|
-
$
|
|
234
|
+
$('#node-input-select-none').on('click', () => {
|
|
235
|
+
$varsContainer.find('input[type="checkbox"]').prop('checked', false).trigger('change');
|
|
284
236
|
});
|
|
285
237
|
|
|
286
|
-
// Removed $providerManual listeners as per instruction
|
|
287
|
-
|
|
288
238
|
$config.on('change', () => {
|
|
289
|
-
loadProviders(false);
|
|
239
|
+
setTimeout(() => loadProviders(false), 50);
|
|
290
240
|
});
|
|
291
241
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const $manualList = $('#node-input-manual-defs-container');
|
|
242
|
+
setTimeout(() => loadProviders(false), 100);
|
|
243
|
+
|
|
244
|
+
// --- Manual Table Logic ---
|
|
245
|
+
const $manualList = $('#node-input-manual-def-list');
|
|
297
246
|
const $manualHidden = $('#node-input-manualVariables');
|
|
298
247
|
|
|
299
248
|
$manualList.editableList({
|
|
300
249
|
addItem: function (row, index, data) {
|
|
301
250
|
row.css({ display: 'flex', alignItems: 'center', gap: '5px' });
|
|
302
251
|
|
|
303
|
-
$('<input/>', { class: 'node-input-manual-name', type: 'text', placeholder: 'Name
|
|
252
|
+
$('<input/>', { class: 'node-input-manual-name', type: 'text', placeholder: 'Name', style: 'flex:1;' })
|
|
304
253
|
.val(data.name || '')
|
|
305
254
|
.appendTo(row);
|
|
306
255
|
|
|
307
|
-
$('<input/>', { class: 'node-input-manual-id', type: 'number', placeholder: 'ID', style: 'width:
|
|
256
|
+
$('<input/>', { class: 'node-input-manual-id', type: 'number', placeholder: 'ID', style: 'width:80px;' })
|
|
308
257
|
.val(data.id || '')
|
|
309
258
|
.appendTo(row);
|
|
310
259
|
},
|
|
311
260
|
removable: true,
|
|
312
261
|
header: $('<div></div>').append(
|
|
313
|
-
$.parseHTML('<div style="display:flex; gap:5px; padding-left:5px;"><div style="flex:1;">Variable Name
|
|
262
|
+
$.parseHTML('<div style="display:flex; gap:5px; padding-left:5px;"><div style="flex:1;">Variable Name</div><div style="width:80px;">ID</div></div>')
|
|
314
263
|
),
|
|
315
|
-
addButton: 'Add
|
|
264
|
+
addButton: 'Add Variable'
|
|
316
265
|
});
|
|
317
266
|
|
|
318
|
-
|
|
319
|
-
const currentManual = $manualHidden.val() || '';
|
|
267
|
+
const currentManual = node.manualVariables || '';
|
|
320
268
|
if (currentManual) {
|
|
321
269
|
currentManual.split(',').forEach(entry => {
|
|
322
270
|
const parts = entry.split(':');
|
|
323
271
|
if (parts.length === 2) {
|
|
324
|
-
|
|
272
|
+
const n = parts[0].trim();
|
|
273
|
+
const i = parts[1].trim();
|
|
274
|
+
if (n && i) $manualList.editableList('addItem', { name: n, id: i });
|
|
325
275
|
}
|
|
326
276
|
});
|
|
327
277
|
}
|
|
328
|
-
|
|
329
278
|
},
|
|
330
279
|
oneditsave: function () {
|
|
331
|
-
const $manualList = $('#node-input-manual-
|
|
280
|
+
const $manualList = $('#node-input-manual-def-list');
|
|
332
281
|
const items = [];
|
|
333
282
|
$manualList.editableList('items').each(function () {
|
|
334
283
|
const name = $(this).find('.node-input-manual-name').val().trim();
|
|
@@ -338,110 +287,106 @@
|
|
|
338
287
|
}
|
|
339
288
|
});
|
|
340
289
|
$('#node-input-manualVariables').val(items.join(','));
|
|
341
|
-
},
|
|
342
|
-
label: function () {
|
|
343
|
-
return this.name || `Input ${this.providerId || ''}`;
|
|
344
|
-
},
|
|
345
|
-
labelStyle: function () {
|
|
346
|
-
return this.name ? 'node_label_italic' : '';
|
|
347
290
|
}
|
|
348
291
|
});
|
|
349
292
|
</script>
|
|
350
293
|
|
|
351
294
|
<script type="text/html" data-template-name="datahub-input">
|
|
352
|
-
|
|
353
|
-
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
354
|
-
<input type="text" id="node-input-name">
|
|
355
|
-
</div>
|
|
356
|
-
<!-- Polling (ms) removed in favor of Input Port triggering -->
|
|
357
|
-
<div class="form-row">
|
|
358
|
-
<label for="node-input-connection"><i class="fa fa-cube"></i> u-OS Config</label>
|
|
359
|
-
<input type="text" id="node-input-connection">
|
|
295
|
+
<div class="form-row">
|
|
360
296
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
361
|
-
<input type="text" id="node-input-name" placeholder="
|
|
297
|
+
<input type="text" id="node-input-name" placeholder="Optional">
|
|
362
298
|
</div>
|
|
299
|
+
|
|
363
300
|
<div class="form-row">
|
|
364
301
|
<label for="node-input-connection"><i class="fa fa-globe"></i> Config</label>
|
|
365
302
|
<input type="text" id="node-input-connection">
|
|
366
303
|
</div>
|
|
304
|
+
|
|
367
305
|
<div class="form-row">
|
|
368
306
|
<label for="node-input-providerId"><i class="fa fa-server"></i> Provider</label>
|
|
369
|
-
<div style="display:
|
|
370
|
-
<select id="node-input-providerId" style="flex
|
|
371
|
-
<button id="node-input-
|
|
307
|
+
<div style="display:inline-flex; width:70%;">
|
|
308
|
+
<select id="node-input-providerId" style="flex:1;"></select>
|
|
309
|
+
<button id="node-input-provider-refresh" class="red-ui-button" type="button" style="margin-left:5px;">
|
|
310
|
+
<i class="fa fa-refresh"></i>
|
|
311
|
+
</button>
|
|
372
312
|
</div>
|
|
373
313
|
</div>
|
|
314
|
+
|
|
374
315
|
<div class="form-row">
|
|
375
316
|
<label for="node-input-mode"><i class="fa fa-sliders"></i> Mode</label>
|
|
376
317
|
<select id="node-input-mode">
|
|
377
|
-
<option value="auto">Auto-Discovery
|
|
318
|
+
<option value="auto">Auto-Discovery</option>
|
|
378
319
|
<option value="manual_single">Manual: Single Variable</option>
|
|
379
|
-
<option value="manual_multi">Manual:
|
|
320
|
+
<option value="manual_multi">Manual: Multiple Variables</option>
|
|
380
321
|
</select>
|
|
381
322
|
</div>
|
|
382
323
|
|
|
383
|
-
<!-- Mode
|
|
384
|
-
<div id="mode-auto-row" class="mode-row">
|
|
385
|
-
<div class="form-row"
|
|
324
|
+
<!-- Auto Mode -->
|
|
325
|
+
<div id="mode-auto-row" class="mode-row" style="display:none;">
|
|
326
|
+
<div class="form-row">
|
|
386
327
|
<label><i class="fa fa-list"></i> Variables</label>
|
|
387
|
-
<div style="display:
|
|
388
|
-
<div style="margin-bottom:
|
|
389
|
-
<button id="node-input-refresh
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
<
|
|
328
|
+
<div style="display:inline-block; width:70%;">
|
|
329
|
+
<div style="margin-bottom:5px;">
|
|
330
|
+
<button id="node-input-vars-refresh" class="red-ui-button red-ui-button-small" type="button">
|
|
331
|
+
<i class="fa fa-refresh"></i> Refresh
|
|
332
|
+
</button>
|
|
333
|
+
<button id="node-input-select-all" class="red-ui-button red-ui-button-small" type="button" style="margin-left:5px;">All</button>
|
|
334
|
+
<button id="node-input-select-none" class="red-ui-button red-ui-button-small" type="button" style="margin-left:5px;">None</button>
|
|
335
|
+
<span id="vars-status" style="margin-left:10px; font-style:italic; color:#888;"></span>
|
|
393
336
|
</div>
|
|
394
337
|
</div>
|
|
395
338
|
</div>
|
|
396
339
|
<div class="form-row">
|
|
397
340
|
<input type="hidden" id="node-input-variablesText">
|
|
398
|
-
<div id="node-input-variables-container" style="border:
|
|
399
|
-
|
|
400
|
-
<
|
|
401
|
-
Select a Provider to load variables...
|
|
402
|
-
</div>
|
|
403
|
-
</div>
|
|
404
|
-
<div class="form-tips" style="margin-top: 5px;">
|
|
405
|
-
<i class="fa fa-info-circle"></i> Requires <b>Deploy</b> or active connection.
|
|
341
|
+
<div id="node-input-variables-container" style="border:1px solid #ccc; border-radius:4px; height:200px; overflow-y:auto; padding:5px; background:#fff; width:100%;"></div>
|
|
342
|
+
<div class="form-tips" style="margin-top:5px;">
|
|
343
|
+
<i class="fa fa-info-circle"></i> Requires <b>Deploy</b> first
|
|
406
344
|
</div>
|
|
407
345
|
</div>
|
|
408
346
|
</div>
|
|
409
347
|
|
|
410
|
-
<!--
|
|
411
|
-
<div id="mode-manual-single-row" class="mode-row">
|
|
348
|
+
<!-- Manual Single Mode -->
|
|
349
|
+
<div id="mode-manual-single-row" class="mode-row" style="display:none;">
|
|
412
350
|
<div class="form-row">
|
|
413
|
-
<label for="node-input-singleName"><i class="fa fa-font"></i>
|
|
414
|
-
<input type="text" id="node-input-singleName" placeholder="e.g.
|
|
351
|
+
<label for="node-input-singleName"><i class="fa fa-font"></i> Variable Name</label>
|
|
352
|
+
<input type="text" id="node-input-singleName" placeholder="e.g. manufacturer_name">
|
|
415
353
|
</div>
|
|
416
354
|
<div class="form-row">
|
|
417
|
-
<label for="node-input-singleId"><i class="fa fa-hashtag"></i>
|
|
355
|
+
<label for="node-input-singleId"><i class="fa fa-hashtag"></i> Variable ID</label>
|
|
418
356
|
<input type="number" id="node-input-singleId" placeholder="e.g. 0">
|
|
419
357
|
</div>
|
|
420
358
|
<div class="form-tips">
|
|
421
|
-
<i class="fa fa-info-circle"></i>
|
|
359
|
+
<i class="fa fa-info-circle"></i> Use Manual Mode if Auto-Discovery fails (Permission 403)
|
|
422
360
|
</div>
|
|
423
361
|
</div>
|
|
424
362
|
|
|
425
|
-
<!--
|
|
426
|
-
<div id="mode-manual-multi-row" class="mode-row">
|
|
363
|
+
<!-- Manual Multi Mode -->
|
|
364
|
+
<div id="mode-manual-multi-row" class="mode-row" style="display:none;">
|
|
427
365
|
<div class="form-row">
|
|
428
|
-
<label
|
|
429
|
-
<div
|
|
366
|
+
<label><i class="fa fa-table"></i> Variables</label>
|
|
367
|
+
<div style="width:100%; margin-top:8px;">
|
|
430
368
|
<ol id="node-input-manual-def-list"></ol>
|
|
431
369
|
</div>
|
|
432
|
-
|
|
433
|
-
<input type="hidden" id="node-input-manualVariables" />
|
|
370
|
+
<input type="hidden" id="node-input-manualVariables">
|
|
434
371
|
</div>
|
|
435
372
|
<div class="form-tips">
|
|
436
|
-
<i class="fa fa-info-circle"></i>
|
|
373
|
+
<i class="fa fa-info-circle"></i> Map Variable Names to IDs
|
|
437
374
|
</div>
|
|
438
375
|
</div>
|
|
439
376
|
|
|
440
|
-
<hr>
|
|
441
|
-
|
|
377
|
+
<hr style="margin:15px 0;">
|
|
378
|
+
|
|
442
379
|
<div class="form-row">
|
|
443
|
-
<label for="node-input-
|
|
444
|
-
<
|
|
380
|
+
<label for="node-input-triggerMode"><i class="fa fa-bolt"></i> Trigger</label>
|
|
381
|
+
<select id="node-input-triggerMode">
|
|
382
|
+
<option value="event">Event (on change)</option>
|
|
383
|
+
<option value="poll">Poll (interval)</option>
|
|
384
|
+
</select>
|
|
385
|
+
</div>
|
|
386
|
+
|
|
387
|
+
<div id="poll-interval-row" class="form-row" style="display:none;">
|
|
388
|
+
<label for="node-input-pollingInterval"><i class="fa fa-clock-o"></i> Interval (ms)</label>
|
|
389
|
+
<input type="number" id="node-input-pollingInterval" placeholder="e.g. 1000">
|
|
445
390
|
</div>
|
|
446
391
|
</script>
|
|
447
392
|
|
|
@@ -453,303 +398,28 @@
|
|
|
453
398
|
<dt>Mode</dt>
|
|
454
399
|
<dd>
|
|
455
400
|
<ul>
|
|
456
|
-
<li><b>Auto-Discovery:</b>
|
|
457
|
-
<li><b>Manual
|
|
458
|
-
<li><b>Manual
|
|
401
|
+
<li><b>Auto-Discovery:</b> Downloads variable list from hub (requires permissions)</li>
|
|
402
|
+
<li><b>Manual Single:</b> Enter one variable's Name and ID manually</li>
|
|
403
|
+
<li><b>Manual Multi:</b> Enter multiple variables via table</li>
|
|
459
404
|
</ul>
|
|
460
405
|
</dd>
|
|
461
406
|
|
|
462
|
-
<dt>
|
|
463
|
-
<dd>
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
407
|
+
<dt>Trigger</dt>
|
|
408
|
+
<dd>
|
|
409
|
+
<ul>
|
|
410
|
+
<li><b>Event:</b> Outputs only when value changes (default)</li>
|
|
411
|
+
<li><b>Poll:</b> Queries values at fixed interval</li>
|
|
412
|
+
</ul>
|
|
413
|
+
</dd>
|
|
467
414
|
</dl>
|
|
468
415
|
|
|
469
|
-
<h3>
|
|
416
|
+
<h3>Permissions / 403 Error</h3>
|
|
470
417
|
<p>
|
|
471
|
-
If
|
|
472
|
-
|
|
473
|
-
In Manual Mode, you provide the `ID` (Number) which works even without Discovery permissions.
|
|
418
|
+
If Auto-Discovery fails with "Permission Violation" or "Empty List", use <b>Manual Mode</b>.
|
|
419
|
+
You need the Variable ID (number) which works even without discovery permissions.
|
|
474
420
|
</p>
|
|
475
421
|
|
|
476
|
-
<div style="margin-top:
|
|
422
|
+
<div style="margin-top:10px; font-size:0.8em; color:#666; border-top:1px solid #eee; padding-top:5px;">
|
|
477
423
|
Developed by <a href="https://github.com/iotueli" target="_blank">iotueli</a>. Not an official Weidmüller product.
|
|
478
424
|
</div>
|
|
479
|
-
</script>
|
|
480
|
-
|
|
481
|
-
<script type="text/javascript">
|
|
482
|
-
RED.nodes.registerType('datahub-input', {
|
|
483
|
-
category: 'u-OS',
|
|
484
|
-
color: '#ff9900',
|
|
485
|
-
defaults: {
|
|
486
|
-
name: { value: "" },
|
|
487
|
-
connection: { type: "uos-config", required: true },
|
|
488
|
-
providerId: { value: "", required: true },
|
|
489
|
-
variablesText: { value: "" }, // Legacy / Auto-Mode list
|
|
490
|
-
manualVariables: { value: "" }, // Manual Table JSON/CSV
|
|
491
|
-
singleName: { value: "" }, // Manual Single Name
|
|
492
|
-
singleId: { value: "" }, // Manual Single ID
|
|
493
|
-
mode: { value: "auto" }, // auto | manual_single | manual_multi
|
|
494
|
-
pollingInterval: { value: 0, validate: RED.validators.number() }
|
|
495
|
-
},
|
|
496
|
-
inputs: 1,
|
|
497
|
-
outputs: 1,
|
|
498
|
-
icon: "datahub-input.svg",
|
|
499
|
-
label: function () {
|
|
500
|
-
if (this.name) return this.name;
|
|
501
|
-
if (this.mode === 'manual_single' && this.singleName) return this.singleName;
|
|
502
|
-
return "u-OS " + (this.providerId || "Data Hub");
|
|
503
|
-
},
|
|
504
|
-
paletteLabel: "u-OS Data Hub",
|
|
505
|
-
oneditprepare: function () {
|
|
506
|
-
const node = this;
|
|
507
|
-
|
|
508
|
-
// --- 1. Mode Visibility Logic ---
|
|
509
|
-
const modeSelect = $('#node-input-mode');
|
|
510
|
-
const autoRow = $('#mode-auto-row');
|
|
511
|
-
const manualSingleRow = $('#mode-manual-single-row');
|
|
512
|
-
const manualMultiRow = $('#mode-manual-multi-row');
|
|
513
|
-
|
|
514
|
-
// Set default if missing (backward compat)
|
|
515
|
-
if (!$('#node-input-mode').val()) {
|
|
516
|
-
$('#node-input-mode').val('auto');
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
const updateVisibility = () => {
|
|
520
|
-
const mode = modeSelect.val();
|
|
521
|
-
autoRow.hide();
|
|
522
|
-
manualSingleRow.hide();
|
|
523
|
-
manualMultiRow.hide();
|
|
524
|
-
|
|
525
|
-
if (mode === 'auto') autoRow.show();
|
|
526
|
-
else if (mode === 'manual_single') manualSingleRow.show();
|
|
527
|
-
else if (mode === 'manual_multi') manualMultiRow.show();
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
modeSelect.on('change', updateVisibility);
|
|
531
|
-
updateVisibility(); // Initial trigger
|
|
532
|
-
|
|
533
|
-
// --- 2. Existing "Auto" Logic (Providers & Checkboxes) ---
|
|
534
|
-
const $config = $('#node-input-connection');
|
|
535
|
-
const $providerRefresh = $('#node-input-check-custom-provider');
|
|
536
|
-
const $variables = $('input[type="checkbox"]');
|
|
537
|
-
const $variablesHidden = $('#node-input-variablesText');
|
|
538
|
-
const $varsRefresh = $('#node-input-refresh-vars');
|
|
539
|
-
|
|
540
|
-
let initialProvider = node.providerId;
|
|
541
|
-
let providerRequest = 0;
|
|
542
|
-
|
|
543
|
-
// Define Helpers (providerValue, providerLabel etc) from original code
|
|
544
|
-
const providerValue = (p) => p.id || p.providerId || p.name;
|
|
545
|
-
const providerLabel = (p) => p.name || p.displayName || p.providerId || p.id;
|
|
546
|
-
|
|
547
|
-
// --- 3. Existing Loading Logic ---
|
|
548
|
-
const setProviderStatus = (msg) => { /* No-op or custom div if needed */ };
|
|
549
|
-
const setProviderValue = (val) => { $('#node-input-providerId').val(val); };
|
|
550
|
-
|
|
551
|
-
const setVariableStatus = (msg) => { $('#vars-status').text(msg); };
|
|
552
|
-
|
|
553
|
-
const normalizeVariables = (payload) => {
|
|
554
|
-
if (Array.isArray(payload)) return payload;
|
|
555
|
-
if (payload && Array.isArray(payload.variables)) return payload.variables;
|
|
556
|
-
return [];
|
|
557
|
-
};
|
|
558
|
-
|
|
559
|
-
const normalizeProviders = (payload) => {
|
|
560
|
-
if (Array.isArray(payload)) return payload;
|
|
561
|
-
if (payload && Array.isArray(payload.providers)) return payload.providers;
|
|
562
|
-
return [];
|
|
563
|
-
};
|
|
564
|
-
|
|
565
|
-
const variableValue = (v) => v.key || v.name || v.path || v.id;
|
|
566
|
-
const variableLabel = (v) => v.tagName || v.key || v.name || v.path || v.id;
|
|
567
|
-
|
|
568
|
-
const syncVariablesField = () => {
|
|
569
|
-
const selected = [];
|
|
570
|
-
varsContainer.find('input[type="checkbox"]:checked').each(function () {
|
|
571
|
-
selected.push($(this).val());
|
|
572
|
-
});
|
|
573
|
-
varsHiddenInput.val(selected.join(','));
|
|
574
|
-
setVariableStatus(`${selected.length} selected`);
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
const loadVariables = (providerId, force = false) => {
|
|
578
|
-
const configId = $config.val();
|
|
579
|
-
if (!configId || !providerId) return;
|
|
580
|
-
|
|
581
|
-
setVariableStatus('Loading...');
|
|
582
|
-
varsContainer.empty().append('<div style="padding:10px; text-align:center; color:#888;"><i class="fa fa-spinner fa-spin"></i> Loading variables...</div>');
|
|
583
|
-
|
|
584
|
-
$.getJSON(`uos/providers/${configId}/${providerId}/variables`)
|
|
585
|
-
.done((payload) => {
|
|
586
|
-
const list = normalizeVariables(payload);
|
|
587
|
-
varsContainer.empty();
|
|
588
|
-
if (!list.length) {
|
|
589
|
-
varsContainer.append('<div style="padding:10px; text-align:center; color:#888;">No variables found for this provider.</div>');
|
|
590
|
-
setVariableStatus('No variables found');
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
const currentVal = varsHiddenInput.val().split(',');
|
|
595
|
-
// Sort by name/key
|
|
596
|
-
list.sort((a, b) => (variableLabel(a) || '').localeCompare(variableLabel(b) || ''));
|
|
597
|
-
|
|
598
|
-
list.forEach((v) => {
|
|
599
|
-
const val = variableValue(v);
|
|
600
|
-
const lbl = variableLabel(v);
|
|
601
|
-
const checked = currentVal.includes(val) ? 'checked' : '';
|
|
602
|
-
const row = $('<div/>').appendTo(varsContainer);
|
|
603
|
-
$('<label/>').css({ display: 'block', cursor: 'pointer' })
|
|
604
|
-
.append($('<input type="checkbox"/>').val(val).prop('checked', !!checked).on('change', syncVariablesField))
|
|
605
|
-
.append($('<span/>').text(' ' + lbl))
|
|
606
|
-
.appendTo(row);
|
|
607
|
-
});
|
|
608
|
-
syncVariablesField();
|
|
609
|
-
})
|
|
610
|
-
.fail((xhr) => {
|
|
611
|
-
const error = xhr?.responseJSON?.error;
|
|
612
|
-
let msg = error || xhr.statusText || 'Failed to load variables.';
|
|
613
|
-
if (xhr.status === 404 && error === 'config not found') {
|
|
614
|
-
msg = 'Config not deployed yet. Please Deploy first.';
|
|
615
|
-
}
|
|
616
|
-
varsContainer.empty().append(`<div style="padding:10px; color:#d66;">${msg}</div>`);
|
|
617
|
-
setVariableStatus('Error loading variables');
|
|
618
|
-
});
|
|
619
|
-
};
|
|
620
|
-
|
|
621
|
-
const populateProviders = (payload) => {
|
|
622
|
-
const list = normalizeProviders(payload);
|
|
623
|
-
providerSelect.empty();
|
|
624
|
-
if (!list.length) {
|
|
625
|
-
providerSelect.append('<option value="">No providers found</option>').prop('disabled', true);
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
let foundInitial = false;
|
|
629
|
-
list.forEach((prov) => {
|
|
630
|
-
const val = providerValue(prov);
|
|
631
|
-
if (!val) return;
|
|
632
|
-
const opt = $('<option/>').val(val).text(providerLabel(prov));
|
|
633
|
-
providerSelect.append(opt);
|
|
634
|
-
if (val === initialProvider) foundInitial = true;
|
|
635
|
-
});
|
|
636
|
-
providerSelect.prop('disabled', false);
|
|
637
|
-
|
|
638
|
-
if (initialProvider && foundInitial) {
|
|
639
|
-
providerSelect.val(initialProvider);
|
|
640
|
-
} else if (initialProvider) {
|
|
641
|
-
// Preserve unknown provider (e.g. from manual entry or offline)
|
|
642
|
-
providerSelect.append($('<option/>').val(initialProvider).text(initialProvider + ' (unknown)'));
|
|
643
|
-
providerSelect.val(initialProvider);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (!providerSelect.val()) {
|
|
647
|
-
providerSelect.val(providerSelect.find('option:first').val());
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// Trigger variable load for selected
|
|
651
|
-
const selected = providerSelect.val();
|
|
652
|
-
if (selected) loadVariables(selected);
|
|
653
|
-
};
|
|
654
|
-
|
|
655
|
-
const loadProviders = (force = false) => {
|
|
656
|
-
const configId = $config.val();
|
|
657
|
-
if (!configId) {
|
|
658
|
-
providerSelect.empty().append('<option value="">Select Config Node first</option>').prop('disabled', true);
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const seq = ++providerRequest;
|
|
663
|
-
// Cache logic omitted for brevity/safety - simplified direct load
|
|
664
|
-
providerSelect.prop('disabled', true);
|
|
665
|
-
|
|
666
|
-
$.getJSON(`uos/providers/${configId}`)
|
|
667
|
-
.done((payload) => {
|
|
668
|
-
if (seq !== providerRequest) return;
|
|
669
|
-
populateProviders(payload);
|
|
670
|
-
})
|
|
671
|
-
.fail((xhr) => {
|
|
672
|
-
const error = xhr?.responseJSON?.error;
|
|
673
|
-
const msg = error || 'Failed to load providers';
|
|
674
|
-
providerSelect.empty().append('<option value="">Error loading providers</option>').prop('disabled', true);
|
|
675
|
-
});
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
// Event Listeners
|
|
679
|
-
providerSelect.on('change', () => {
|
|
680
|
-
const val = providerSelect.val();
|
|
681
|
-
varsHiddenInput.val('');
|
|
682
|
-
syncVariablesField();
|
|
683
|
-
loadVariables(val);
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
$providerRefresh.on('click', () => loadProviders(true));
|
|
687
|
-
$varsRefresh.on('click', () => {
|
|
688
|
-
const v = providerSelect.val();
|
|
689
|
-
if (v) loadVariables(v, true);
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
$('#node-input-select-all').on('click', () => {
|
|
693
|
-
varsContainer.find('input[type="checkbox"]').prop('checked', true).trigger('change');
|
|
694
|
-
});
|
|
695
|
-
$('#node-input-select-none').on('click', () => {
|
|
696
|
-
varsContainer.find('input[type="checkbox"]').prop('checked', false).trigger('change');
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
$config.on('change', () => {
|
|
700
|
-
setTimeout(() => loadProviders(false), 50);
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
// Initial Load
|
|
704
|
-
setTimeout(() => loadProviders(false), 100);
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
// --- 4. Manual Table Logic ---
|
|
708
|
-
const $manualList = $('#node-input-manual-def-list');
|
|
709
|
-
const $manualHidden = $('#node-input-manualVariables');
|
|
710
|
-
|
|
711
|
-
$manualList.editableList({
|
|
712
|
-
addItem: function (row, index, data) {
|
|
713
|
-
row.css({ display: 'flex', alignItems: 'center', gap: '5px' });
|
|
714
|
-
|
|
715
|
-
$('<input/>', { class: 'node-input-manual-name', type: 'text', placeholder: 'Name', style: 'flex:1;' })
|
|
716
|
-
.val(data.name || '')
|
|
717
|
-
.appendTo(row);
|
|
718
|
-
|
|
719
|
-
$('<input/>', { class: 'node-input-manual-id', type: 'number', placeholder: 'ID', style: 'width:80px;' })
|
|
720
|
-
.val(data.id || '')
|
|
721
|
-
.appendTo(row);
|
|
722
|
-
},
|
|
723
|
-
removable: true,
|
|
724
|
-
header: $('<div></div>').append(
|
|
725
|
-
$.parseHTML('<div style="display:flex; gap:5px; padding-left:5px;"><div style="flex:1;">Name (String)</div><div style="width:80px;">ID (Int)</div></div>')
|
|
726
|
-
),
|
|
727
|
-
addButton: 'Add Mapping'
|
|
728
|
-
});
|
|
729
|
-
|
|
730
|
-
// Populate Table
|
|
731
|
-
const currentManual = $manualHidden.val() || '';
|
|
732
|
-
if (currentManual) {
|
|
733
|
-
currentManual.split(',').forEach(entry => {
|
|
734
|
-
const parts = entry.split(':');
|
|
735
|
-
if (parts.length === 2) {
|
|
736
|
-
const n = parts[0].trim();
|
|
737
|
-
const i = parts[1].trim();
|
|
738
|
-
if (n && i) $manualList.editableList('addItem', { name: n, id: i });
|
|
739
|
-
}
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
},
|
|
744
|
-
oneditsave: function () {
|
|
745
|
-
const $manualList = $('#node-input-manual-def-list');
|
|
746
|
-
const items = [];
|
|
747
|
-
$manualList.editableList('items').each(function () {
|
|
748
|
-
const name = $(this).find('.node-input-manual-name').val().trim();
|
|
749
|
-
const id = $(this).find('.node-input-manual-id').val().trim();
|
|
750
|
-
if (name && id) {
|
|
751
|
-
items.push(`${name}:${id}`);
|
|
752
|
-
}
|
|
753
|
-
});
|
|
754
|
-
$('#node-input-manualVariables').val(items.join(','));
|
|
755
|
-
}
|
|
425
|
+
</script>
|
package/nodes/datahub-input.js
CHANGED
|
@@ -27,9 +27,9 @@ module.exports = function (RED) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
this.providerId = config.providerId || 'sampleprovider';
|
|
30
|
-
this.providerId = config.providerId || 'sampleprovider';
|
|
31
|
-
this.pollingInterval = parseInt(config.pollingInterval, 10) || 0; // ms
|
|
32
30
|
this.mode = config.mode || 'auto';
|
|
31
|
+
this.triggerMode = config.triggerMode || 'event';
|
|
32
|
+
this.pollingInterval = this.triggerMode === 'poll' ? (parseInt(config.pollingInterval, 10) || 1000) : 0;
|
|
33
33
|
|
|
34
34
|
const text = config.variablesText || '';
|
|
35
35
|
const manualText = config.manualVariables || '';
|