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.
@@ -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
- const rowStyle = "display:grid; grid-template-columns: 60px 1fr 80px 80px; align-items:center; padding:4px 0; border-bottom:1px solid #eee; font-family:'Helvetica Neue', Arial, sans-serif; font-size:12px; cursor:pointer;";
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
- const safeType = v.dataType || v.type || '-';
58
- const safeAccess = v.access || v.accessType || '-';
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(idCol).append(keyCol).append(typeCol).append(accessCol);
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
- $(this).css('background', '#dcefff'); // Highlight selection
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(2)').text().toLowerCase(); // Key is 2nd column
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 (User Request)
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 (User Request: "tiefste Zahl zuoberst")
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
- updateSelectionDisplay(node.variableId, node.variableKey);
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, inputs are handled automatically
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 80px 80px; background:#eee; font-size:11px; font-weight:bold; padding:4px 0; border-bottom:1px solid #ccc;">
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.102",
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",