node-red-contrib-uos-nats 0.2.102 → 0.2.103
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-write.html +36 -40
- package/package.json +1 -1
package/nodes/datahub-write.html
CHANGED
|
@@ -22,28 +22,22 @@
|
|
|
22
22
|
const $listContainer = $('#variable-list-container');
|
|
23
23
|
const $statusMsg = $('#fetch-status');
|
|
24
24
|
const $searchInput = $('#node-input-var-search');
|
|
25
|
-
const $selectionDisplay = $('#selected-variable-display');
|
|
25
|
+
const $selectionDisplay = $('#selected-variable-display'); // Will be removed in HTML, but reference might exist in legacy code if not careful. Removed from logic below.
|
|
26
26
|
|
|
27
27
|
// Raw Inputs (Hidden)
|
|
28
28
|
const $inputId = $('#node-input-variableId');
|
|
29
29
|
const $inputKey = $('#node-input-variableKey');
|
|
30
30
|
|
|
31
|
-
// Styles matching Read Node
|
|
32
|
-
|
|
31
|
+
// Styles matching Read Node (Simplified: Icon, ID, Name)
|
|
32
|
+
// Was: 60px 1fr 80px 80px
|
|
33
|
+
// New: 30px 60px 1fr
|
|
34
|
+
const rowStyle = "display:grid; grid-template-columns: 30px 60px 1fr; align-items:center; padding:4px 0; border-bottom:1px solid #eee; font-family:'Helvetica Neue', Arial, sans-serif; font-size:12px; cursor:pointer;";
|
|
33
35
|
const idStyle = "background:#eee; color:#555; padding:1px 4px; border-radius:3px; font-family:monospace; text-align:center; font-size:11px;";
|
|
34
36
|
const keyStyle = "overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding-left:10px;";
|
|
37
|
+
const iconStyle = "text-align:center; color:#ccc;";
|
|
35
38
|
|
|
36
39
|
let currentVariables = [];
|
|
37
40
|
|
|
38
|
-
// Helper to update display
|
|
39
|
-
const updateSelectionDisplay = (id, key) => {
|
|
40
|
-
if (id || key) {
|
|
41
|
-
$selectionDisplay.html(`<b>${key || '?'}</b> <span style="color:#666; font-family:monospace; margin-left:10px;">(ID: ${id || '?'})</span>`);
|
|
42
|
-
} else {
|
|
43
|
-
$selectionDisplay.html('<span style="color:#888; font-style:italic;">None selected</span>');
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
41
|
// Render List Function
|
|
48
42
|
const renderList = (vars) => {
|
|
49
43
|
$listContainer.empty();
|
|
@@ -54,32 +48,38 @@
|
|
|
54
48
|
|
|
55
49
|
vars.forEach(v => {
|
|
56
50
|
const safeId = (v.id !== undefined) ? v.id : (v.Id !== undefined ? v.Id : 'ERR');
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
// Type/Access removed from display as per request
|
|
52
|
+
|
|
53
|
+
const isSelected = String(safeId) === String($inputId.val());
|
|
59
54
|
|
|
60
55
|
const row = $('<div>', { class: 'var-row', style: rowStyle });
|
|
56
|
+
if (isSelected) {
|
|
57
|
+
row.css('background', '#dcefff');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Icon (Selection Indicator)
|
|
61
|
+
const iconCol = $('<div>', { style: iconStyle }).html(isSelected ? '<i class="fa fa-dot-circle-o" style="color:#2196f3; font-size:14px;"></i>' : '<i class="fa fa-circle-o"></i>');
|
|
61
62
|
|
|
62
63
|
// ID
|
|
63
64
|
const idCol = $('<div>', { style: 'text-align:center;' }).append($('<span>', { style: idStyle }).text(safeId));
|
|
64
65
|
// Key
|
|
65
66
|
const keyCol = $('<div>', { style: keyStyle, title: v.key }).text(v.key);
|
|
66
|
-
// Type
|
|
67
|
-
const typeCol = $('<div>', { style: 'font-size:10px; color:#666; padding-left:5px;' }).text(safeType);
|
|
68
|
-
// Access
|
|
69
|
-
const accessCol = $('<div>', { style: 'font-size:10px; color:#666; padding-left:5px;' }).text(safeAccess);
|
|
70
67
|
|
|
71
|
-
row.append(
|
|
68
|
+
row.append(iconCol).append(idCol).append(keyCol);
|
|
72
69
|
|
|
73
70
|
// Click Handler - Fill Inputs
|
|
74
71
|
row.on('click', function () {
|
|
72
|
+
// Reset all rows
|
|
75
73
|
$('.var-row').css('background', 'transparent');
|
|
76
|
-
$(
|
|
74
|
+
$('.var-row i.fa').removeClass('fa-dot-circle-o').addClass('fa-circle-o').css('color', '#ccc');
|
|
75
|
+
|
|
76
|
+
// Highlight this one
|
|
77
|
+
$(this).css('background', '#dcefff');
|
|
78
|
+
$(this).find('i.fa').removeClass('fa-circle-o').addClass('fa-dot-circle-o').css('color', '#2196f3');
|
|
77
79
|
|
|
78
80
|
$inputId.val(safeId !== 'ERR' ? safeId : '');
|
|
79
81
|
$inputKey.val(v.key);
|
|
80
82
|
|
|
81
|
-
updateSelectionDisplay(safeId, v.key);
|
|
82
|
-
|
|
83
83
|
// Trigger validation visual update if needed
|
|
84
84
|
$inputId.trigger('change');
|
|
85
85
|
});
|
|
@@ -90,13 +90,19 @@
|
|
|
90
90
|
|
|
91
91
|
$listContainer.append(row);
|
|
92
92
|
});
|
|
93
|
+
|
|
94
|
+
// Scroll to selection if possible
|
|
95
|
+
const selectedRow = $listContainer.find('.var-row').filter(function () { return $(this).css('background-color') === 'rgb(220, 239, 255)'; });
|
|
96
|
+
if (selectedRow.length) {
|
|
97
|
+
$listContainer.scrollTop(selectedRow.offset().top - $listContainer.offset().top + $listContainer.scrollTop() - 40);
|
|
98
|
+
}
|
|
93
99
|
};
|
|
94
100
|
|
|
95
101
|
// Filter Logic
|
|
96
102
|
$searchInput.on('keyup', function () {
|
|
97
103
|
const term = $(this).val().toLowerCase();
|
|
98
104
|
$listContainer.find('.var-row').each(function () {
|
|
99
|
-
const text = $(this).find('div:nth-child(
|
|
105
|
+
const text = $(this).find('div:nth-child(3)').text().toLowerCase(); // Key is 3rd column now
|
|
100
106
|
$(this).toggle(text.indexOf(term) > -1);
|
|
101
107
|
});
|
|
102
108
|
});
|
|
@@ -123,15 +129,13 @@
|
|
|
123
129
|
$fetchBtn.prop('disabled', false);
|
|
124
130
|
$statusMsg.text('');
|
|
125
131
|
|
|
126
|
-
// Filter: Only writable variables
|
|
127
|
-
// If access is missing (fallback mode), we SHOW it to be safe (let user try).
|
|
132
|
+
// Filter: Only writable variables
|
|
128
133
|
const writableVars = data.filter(v => {
|
|
129
134
|
const acc = (v.access || v.accessType || '').toUpperCase();
|
|
130
|
-
// Show if explicitly Writable OR if access info is missing entirely
|
|
131
135
|
return acc.includes('WRITE') || acc === '';
|
|
132
136
|
});
|
|
133
137
|
|
|
134
|
-
// Sort: ID ascending
|
|
138
|
+
// Sort: ID ascending
|
|
135
139
|
currentVariables = writableVars.sort((a, b) => {
|
|
136
140
|
const idA = (a.id !== undefined) ? parseInt(a.id) : (a.Id !== undefined ? parseInt(a.Id) : Infinity);
|
|
137
141
|
const idB = (b.id !== undefined) ? parseInt(b.id) : (b.Id !== undefined ? parseInt(b.Id) : Infinity);
|
|
@@ -150,15 +154,13 @@
|
|
|
150
154
|
// Initial state
|
|
151
155
|
$listContainer.html('<div style="padding:20px; text-align:center; color:#999;">Click <b>Load Variables</b> to browse.</div>');
|
|
152
156
|
|
|
153
|
-
// Set initial display
|
|
154
|
-
|
|
157
|
+
// Set initial display (Removed updateSelectionDisplay call)
|
|
158
|
+
// But we might want to manually populate inputs if they are empty? No, defaults handle that.
|
|
155
159
|
|
|
156
160
|
const validateVar = () => {
|
|
157
161
|
const hasId = $inputId.val();
|
|
158
162
|
const hasKey = $inputKey.val();
|
|
159
163
|
if (!hasId && !hasKey) {
|
|
160
|
-
// Valid in Batch Mode?
|
|
161
|
-
// We can show a hint that batch mode is active if nothing selected.
|
|
162
164
|
$('#var-validation-error').hide();
|
|
163
165
|
$('#batch-mode-hint').show();
|
|
164
166
|
} else {
|
|
@@ -172,7 +174,7 @@
|
|
|
172
174
|
validateVar();
|
|
173
175
|
},
|
|
174
176
|
oneditsave: function () {
|
|
175
|
-
// Nothing special to save
|
|
177
|
+
// Nothing special to save
|
|
176
178
|
}
|
|
177
179
|
});
|
|
178
180
|
</script>
|
|
@@ -204,21 +206,15 @@
|
|
|
204
206
|
<input type="text" id="node-input-var-search" placeholder="Filter..." style="width:120px; font-size:11px; padding:2px;">
|
|
205
207
|
</div>
|
|
206
208
|
|
|
207
|
-
<div style="display:grid; grid-template-columns: 60px 1fr
|
|
209
|
+
<div style="display:grid; grid-template-columns: 30px 60px 1fr; background:#eee; font-size:11px; font-weight:bold; padding:4px 0; border-bottom:1px solid #ccc;">
|
|
210
|
+
<div style="text-align:center;"></div>
|
|
208
211
|
<div style="text-align:center;">ID</div>
|
|
209
212
|
<div style="padding-left:10px;">Name</div>
|
|
210
|
-
<div style="padding-left:5px;">Type</div>
|
|
211
|
-
<div style="padding-left:5px;">Access</div>
|
|
212
213
|
</div>
|
|
213
214
|
|
|
214
215
|
<div id="variable-list-container" style="height:200px; overflow-y:auto; background:white;">
|
|
215
216
|
<!-- Variables -->
|
|
216
217
|
</div>
|
|
217
|
-
|
|
218
|
-
<div style="background:#f7f7f7; padding:10px; border-top:1px solid #ddd; font-size:12px; display:flex; align-items:center;">
|
|
219
|
-
<span style="font-weight:bold; margin-right:10px;">Currently Selected:</span>
|
|
220
|
-
<span id="selected-variable-display"></span>
|
|
221
|
-
</div>
|
|
222
218
|
</div>
|
|
223
219
|
|
|
224
220
|
<!-- Hidden Inputs (Required by Node-RED to save state) -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-uos-nats",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.103",
|
|
4
4
|
"description": "Node-RED nodes for Weidmüller u-OS Data Hub. Read, write, and provide variables via NATS protocol with OAuth2 authentication. Features: Variable Key resolution, custom icons, example flows, and provider definition caching.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "IoTUeli",
|