node-red-contrib-questdb 0.6.9 → 0.6.23

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.
Binary file
@@ -0,0 +1,45 @@
1
+ <style>
2
+ .questdb-white-text { fill: #ffffff !important; }
3
+ .red-ui-palette-node[data-palette-type="questdb-flatten"] .red-ui-palette-label { color: #ffffff !important; }
4
+ .red-ui-palette-node[data-palette-type="questdb-flatten"] .red-ui-palette-icon-container { background-color: #f0f0f0 !important; }
5
+ </style>
6
+
7
+ <script type="text/javascript">
8
+ RED.nodes.registerType('questdb-flatten', {
9
+ category: 'questdb',
10
+ color: '#a23154',
11
+ defaults: {
12
+ name: { value: "" }
13
+ },
14
+ inputs: 1,
15
+ outputs: 1,
16
+ icon: "questdb-logo.png",
17
+ paletteLabel: "Flatten",
18
+ label: function () { return this.name || "Flatten"; },
19
+ labelStyle: function () { return (this.name ? "node_label_italic" : "") + " questdb-white-text"; }
20
+ });
21
+ </script>
22
+
23
+ <script type="text/html" data-template-name="questdb-flatten">
24
+ <div class="form-row">
25
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
26
+ <input type="text" id="node-input-name" placeholder="Name">
27
+ </div>
28
+ </script>
29
+
30
+ <script type="text/html" data-help-name="questdb-flatten">
31
+ <p>Flattens <code>msg.payload</code> into the top-level message object.</p>
32
+
33
+ <h3>Behaviour</h3>
34
+ <p>Spreads all properties of <code>msg.payload</code> directly onto <code>msg</code>, then removes <code>msg.payload</code>.</p>
35
+
36
+ <h3>Example</h3>
37
+ <pre>// Input
38
+ msg.payload = { topic: "temp", symbols: { ... }, columns: { ... } }
39
+
40
+ // Output
41
+ msg.topic = "temp"
42
+ msg.symbols = { ... }
43
+ msg.columns = { ... }
44
+ // msg.payload is removed</pre>
45
+ </script>
@@ -0,0 +1,15 @@
1
+ module.exports = function (RED) {
2
+ function FlattenNode(config) {
3
+ RED.nodes.createNode(this, config);
4
+ var node = this;
5
+
6
+ node.on('input', function (msg) {
7
+ var payload = msg.payload;
8
+ delete msg.payload;
9
+ Object.assign(msg, payload);
10
+ node.send(msg);
11
+ });
12
+ }
13
+
14
+ RED.nodes.registerType('questdb-flatten', FlattenNode);
15
+ };
@@ -1,277 +1,281 @@
1
- <script type="text/javascript">
2
- RED.nodes.registerType('questdb-mapper', {
3
- category: 'questdb',
4
- color: '#a23154',
5
- defaults: {
6
- name: {value: ""},
7
- tableName: {value: ""},
8
- timestampField: {value: "timestamp"},
9
- timestampFieldType: {value: "msg"},
10
- symbolMappings: {value: []},
11
- columnMappings: {value: []}
12
- },
13
- inputs: 1,
14
- outputs: 1,
15
- icon: "font-awesome/fa-exchange",
16
- label: function() {
17
- return this.name || "Mapper";
18
- },
19
- paletteLabel: "Mapper",
20
- labelStyle: function() {
21
- return this.name ? "node_label_italic questdb-white-text" : "questdb-white-text";
22
- },
23
- oneditprepare: function() {
24
- const node = this;
25
-
26
- // Initialize TypedInput for timestamp field
27
- $("#node-input-timestampField").typedInput({
28
- type: node.timestampFieldType || "msg",
29
- types: ["msg", "flow", "global", "str", "jsonata"],
30
- typeField: "#node-input-timestampFieldType"
31
- });
32
-
33
- // Symbol mappings list
34
- const symbolList = $("#node-input-symbol-list").css({
35
- 'min-height': '100px',
36
- 'min-width': '400px'
37
- }).editableList({
38
- addItem: function(container, i, data) {
39
- const row = $('<div/>').css({display: 'flex', alignItems: 'center'}).appendTo(container);
40
-
41
- // Source field with TypedInput
42
- const sourceInput = $('<input/>', {type: "text", class: "symbol-source"})
43
- .css({width: "45%", marginRight: "5px"})
44
- .appendTo(row);
45
-
46
- $(sourceInput).typedInput({
47
- default: 'msg',
48
- types: ['msg', 'flow', 'global', 'jsonata']
49
- });
50
-
51
- if (data.source) {
52
- $(sourceInput).typedInput('type', data.sourceType || 'msg');
53
- $(sourceInput).typedInput('value', data.source);
54
- }
55
-
56
- $('<span/>').text(" → ").css({margin: "0 5px"}).appendTo(row);
57
-
58
- // Target field (plain text)
59
- $('<input/>', {type: "text", placeholder: "symbol name", class: "symbol-target"})
60
- .css({width: "40%"})
61
- .val(data.target || "")
62
- .appendTo(row);
63
- },
64
- removable: true,
65
- sortable: true
66
- });
67
-
68
- // Column mappings list
69
- const columnList = $("#node-input-column-list").css({
70
- 'min-height': '100px',
71
- 'min-width': '400px'
72
- }).editableList({
73
- addItem: function(container, i, data) {
74
- const row = $('<div/>').css({display: 'flex', alignItems: 'center'}).appendTo(container);
75
-
76
- // Source field with TypedInput
77
- const sourceInput = $('<input/>', {type: "text", class: "column-source"})
78
- .css({width: "35%", marginRight: "5px"})
79
- .appendTo(row);
80
-
81
- $(sourceInput).typedInput({
82
- default: 'msg',
83
- types: ['msg', 'flow', 'global', 'jsonata']
84
- });
85
-
86
- if (data.source) {
87
- $(sourceInput).typedInput('type', data.sourceType || 'msg');
88
- $(sourceInput).typedInput('value', data.source);
89
- }
90
-
91
- $('<span/>').text(" → ").css({margin: "0 5px"}).appendTo(row);
92
-
93
- // Target field (plain text)
94
- $('<input/>', {type: "text", placeholder: "column name", class: "column-target"})
95
- .css({width: "25%", marginRight: "5px"})
96
- .val(data.target || "")
97
- .appendTo(row);
98
-
99
- // Type selector
100
- const typeSelect = $('<select/>', {class: "column-type"})
101
- .css({width: "20%"})
102
- .appendTo(row);
103
- ['auto', 'float', 'double', 'integer', 'long', 'decimal', 'varchar', 'string', 'boolean', 'timestamp', 'array'].forEach(function(t) {
104
- $('<option/>').val(t).text(t).appendTo(typeSelect);
105
- });
106
- typeSelect.val(data.type || "auto");
107
- },
108
- removable: true,
109
- sortable: true
110
- });
111
-
112
- // Load existing mappings
113
- if (node.symbolMappings) {
114
- node.symbolMappings.forEach(function(m) {
115
- symbolList.editableList('addItem', m);
116
- });
117
- }
118
- if (node.columnMappings) {
119
- node.columnMappings.forEach(function(m) {
120
- columnList.editableList('addItem', m);
121
- });
122
- }
123
- },
124
- oneditresize: function(size) {
125
- // Resize editable lists if needed
126
- },
127
- oneditsave: function() {
128
- const node = this;
129
-
130
- // Save symbol mappings
131
- node.symbolMappings = [];
132
- $("#node-input-symbol-list").editableList('items').each(function() {
133
- const sourceInput = $(this).find(".symbol-source");
134
- const source = sourceInput.typedInput('value');
135
- const sourceType = sourceInput.typedInput('type');
136
- const target = $(this).find(".symbol-target").val().trim();
137
- if (source && target) {
138
- node.symbolMappings.push({
139
- source: source,
140
- sourceType: sourceType,
141
- target: target
142
- });
143
- }
144
- });
145
-
146
- // Save column mappings
147
- node.columnMappings = [];
148
- $("#node-input-column-list").editableList('items').each(function() {
149
- const sourceInput = $(this).find(".column-source");
150
- const source = sourceInput.typedInput('value');
151
- const sourceType = sourceInput.typedInput('type');
152
- const target = $(this).find(".column-target").val().trim();
153
- const type = $(this).find(".column-type").val();
154
- if (source && target) {
155
- node.columnMappings.push({
156
- source: source,
157
- sourceType: sourceType,
158
- target: target,
159
- type: type
160
- });
161
- }
162
- });
163
- }
164
- });
165
- </script>
166
-
167
- <script type="text/html" data-template-name="questdb-mapper">
168
- <div class="form-row">
169
- <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
170
- <input type="text" id="node-input-name" placeholder="Name">
171
- </div>
172
- <div class="form-row">
173
- <label for="node-input-tableName"><i class="fa fa-table"></i> Table Name</label>
174
- <input type="text" id="node-input-tableName" placeholder="Leave empty to use msg.topic">
175
- </div>
176
- <div class="form-row">
177
- <label for="node-input-timestampField"><i class="fa fa-clock-o"></i> Timestamp Field</label>
178
- <input type="hidden" id="node-input-timestampFieldType">
179
- <input type="text" id="node-input-timestampField" placeholder="timestamp">
180
- </div>
181
- <div class="form-row">
182
- <label style="width:100%;"><i class="fa fa-bookmark"></i> Symbol Mappings (indexed tags)</label>
183
- <ol id="node-input-symbol-list"></ol>
184
- </div>
185
- <div class="form-row">
186
- <label style="width:100%;"><i class="fa fa-columns"></i> Column Mappings (values)</label>
187
- <ol id="node-input-column-list"></ol>
188
- </div>
189
- </script>
190
-
191
- <script type="text/html" data-help-name="questdb-mapper">
192
- <p>Maps message fields to QuestDB ILP structure for use with the Write node.</p>
193
-
194
- <h3>Properties</h3>
195
- <dl class="message-properties">
196
- <dt>Table Name</dt>
197
- <dd>Target table name. If empty, uses <code>msg.topic</code></dd>
198
- <dt>Timestamp Field</dt>
199
- <dd>Path to timestamp field (e.g. <code>payload.ts</code>)</dd>
200
- <dt>Symbol Mappings</dt>
201
- <dd>Map msg fields to QuestDB symbols (indexed string columns)</dd>
202
- <dt>Column Mappings</dt>
203
- <dd>Map msg fields to QuestDB columns with type conversion</dd>
204
- </dl>
205
-
206
- <h3>Column Types</h3>
207
- <ul>
208
- <li><b>auto</b> - Auto-detect type from value</li>
209
- <li><b>float</b> - 32-bit floating point</li>
210
- <li><b>double</b> - 64-bit floating point (higher precision)</li>
211
- <li><b>integer</b> - 32-bit signed integer</li>
212
- <li><b>long</b> - 64-bit signed integer</li>
213
- <li><b>decimal</b> - Arbitrary precision decimal</li>
214
- <li><b>varchar</b> - Variable-length text (QuestDB native type, preferred over string)</li>
215
- <li><b>string</b> - Text value (alias for varchar)</li>
216
- <li><b>boolean</b> - true/false</li>
217
- <li><b>timestamp</b> - Date/time value</li>
218
- <li><b>array</b> - Array of doubles (double[])</li>
219
- </ul>
220
-
221
- <h3>Field Path Syntax</h3>
222
- <p>Use dot notation: <code>payload.sensor.value</code></p>
223
- <p>Array access: <code>payload.readings[0]</code></p>
224
-
225
- <h3>Output</h3>
226
- <p>Produces a message ready for the QuestDB Write node:</p>
227
- <pre>{
228
- topic: "table_name",
229
- payload: {
230
- symbols: { ... },
231
- columns: { ... },
232
- timestamp: ...
233
- }
234
- }</pre>
235
-
236
- <h3>Example</h3>
237
- <p>Input message:</p>
238
- <pre>{
239
- topic: "sensors",
240
- payload: {
241
- device: "sensor1",
242
- temp: 23.5,
243
- readings: [1.1, 2.2, 3.3],
244
- ts: 1699999999000
245
- }
246
- }</pre>
247
- <p>With mappings:</p>
248
- <ul>
249
- <li>Symbol: <code>payload.device</code> → <code>device_id</code></li>
250
- <li>Column: <code>payload.temp</code> → <code>temperature</code> (double)</li>
251
- <li>Column: <code>payload.readings</code> → <code>values</code> (array)</li>
252
- <li>Timestamp: <code>payload.ts</code></li>
253
- </ul>
254
- <p>Output:</p>
255
- <pre>{
256
- topic: "sensors",
257
- payload: {
258
- symbols: { device_id: "sensor1" },
259
- columns: {
260
- temperature: { value: 23.5, type: "double" },
261
- values: { value: [1.1, 2.2, 3.3], type: "array" }
262
- },
263
- timestamp: 1699999999000
264
- }
265
- }</pre>
266
- </script>
267
-
268
- <style>
269
- /* White text on flow canvas */
270
- .questdb-white-text {
271
- fill: #ffffff !important;
272
- }
273
- /* White text in palette */
274
- .red-ui-palette-node[data-palette-type="questdb-mapper"] .red-ui-palette-label {
275
- color: #ffffff !important;
276
- }
277
- </style>
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('questdb-mapper', {
3
+ category: 'questdb',
4
+ color: '#a23154',
5
+ defaults: {
6
+ name: {value: ""},
7
+ tableName: {value: ""},
8
+ timestampField: {value: "timestamp"},
9
+ timestampFieldType: {value: "msg"},
10
+ symbolMappings: {value: []},
11
+ columnMappings: {value: []}
12
+ },
13
+ inputs: 1,
14
+ outputs: 1,
15
+ icon: "questdb-logo.png",
16
+ label: function() {
17
+ return this.name || "Mapper";
18
+ },
19
+ paletteLabel: "Mapper",
20
+ labelStyle: function() {
21
+ return this.name ? "node_label_italic questdb-white-text" : "questdb-white-text";
22
+ },
23
+ oneditprepare: function() {
24
+ const node = this;
25
+
26
+ // Initialize TypedInput for timestamp field
27
+ $("#node-input-timestampField").typedInput({
28
+ type: node.timestampFieldType || "msg",
29
+ types: ["msg", "flow", "global", "str", "jsonata"],
30
+ typeField: "#node-input-timestampFieldType"
31
+ });
32
+
33
+ // Symbol mappings list
34
+ const symbolList = $("#node-input-symbol-list").css({
35
+ 'min-height': '100px',
36
+ 'min-width': '400px'
37
+ }).editableList({
38
+ addItem: function(container, i, data) {
39
+ const row = $('<div/>').css({display: 'flex', alignItems: 'center'}).appendTo(container);
40
+
41
+ // Source field with TypedInput
42
+ const sourceInput = $('<input/>', {type: "text", class: "symbol-source"})
43
+ .css({width: "45%", marginRight: "5px"})
44
+ .appendTo(row);
45
+
46
+ $(sourceInput).typedInput({
47
+ default: 'msg',
48
+ types: ['msg', 'flow', 'global', 'jsonata']
49
+ });
50
+
51
+ if (data.source) {
52
+ $(sourceInput).typedInput('type', data.sourceType || 'msg');
53
+ $(sourceInput).typedInput('value', data.source);
54
+ }
55
+
56
+ $('<span/>').text(" → ").css({margin: "0 5px"}).appendTo(row);
57
+
58
+ // Target field (plain text)
59
+ $('<input/>', {type: "text", placeholder: "symbol name", class: "symbol-target"})
60
+ .css({width: "40%"})
61
+ .val(data.target || "")
62
+ .appendTo(row);
63
+ },
64
+ removable: true,
65
+ sortable: true
66
+ });
67
+
68
+ // Column mappings list
69
+ const columnList = $("#node-input-column-list").css({
70
+ 'min-height': '100px',
71
+ 'min-width': '400px'
72
+ }).editableList({
73
+ addItem: function(container, i, data) {
74
+ const row = $('<div/>').css({display: 'flex', alignItems: 'center'}).appendTo(container);
75
+
76
+ // Source field with TypedInput
77
+ const sourceInput = $('<input/>', {type: "text", class: "column-source"})
78
+ .css({width: "35%", marginRight: "5px"})
79
+ .appendTo(row);
80
+
81
+ $(sourceInput).typedInput({
82
+ default: 'msg',
83
+ types: ['msg', 'flow', 'global', 'jsonata']
84
+ });
85
+
86
+ if (data.source) {
87
+ $(sourceInput).typedInput('type', data.sourceType || 'msg');
88
+ $(sourceInput).typedInput('value', data.source);
89
+ }
90
+
91
+ $('<span/>').text(" → ").css({margin: "0 5px"}).appendTo(row);
92
+
93
+ // Target field (plain text)
94
+ $('<input/>', {type: "text", placeholder: "column name", class: "column-target"})
95
+ .css({width: "25%", marginRight: "5px"})
96
+ .val(data.target || "")
97
+ .appendTo(row);
98
+
99
+ // Type selector
100
+ const typeSelect = $('<select/>', {class: "column-type"})
101
+ .css({width: "20%"})
102
+ .appendTo(row);
103
+ ['auto', 'float', 'double', 'integer', 'long', 'decimal', 'varchar', 'string', 'boolean', 'timestamp', 'array'].forEach(function(t) {
104
+ $('<option/>').val(t).text(t).appendTo(typeSelect);
105
+ });
106
+ typeSelect.val(data.type || "auto");
107
+ },
108
+ removable: true,
109
+ sortable: true
110
+ });
111
+
112
+ // Load existing mappings
113
+ if (node.symbolMappings) {
114
+ node.symbolMappings.forEach(function(m) {
115
+ symbolList.editableList('addItem', m);
116
+ });
117
+ }
118
+ if (node.columnMappings) {
119
+ node.columnMappings.forEach(function(m) {
120
+ columnList.editableList('addItem', m);
121
+ });
122
+ }
123
+ },
124
+ oneditresize: function(size) {
125
+ // Resize editable lists if needed
126
+ },
127
+ oneditsave: function() {
128
+ const node = this;
129
+
130
+ // Save symbol mappings
131
+ node.symbolMappings = [];
132
+ $("#node-input-symbol-list").editableList('items').each(function() {
133
+ const sourceInput = $(this).find(".symbol-source");
134
+ const source = sourceInput.typedInput('value');
135
+ const sourceType = sourceInput.typedInput('type');
136
+ const target = $(this).find(".symbol-target").val().trim();
137
+ if (source && target) {
138
+ node.symbolMappings.push({
139
+ source: source,
140
+ sourceType: sourceType,
141
+ target: target
142
+ });
143
+ }
144
+ });
145
+
146
+ // Save column mappings
147
+ node.columnMappings = [];
148
+ $("#node-input-column-list").editableList('items').each(function() {
149
+ const sourceInput = $(this).find(".column-source");
150
+ const source = sourceInput.typedInput('value');
151
+ const sourceType = sourceInput.typedInput('type');
152
+ const target = $(this).find(".column-target").val().trim();
153
+ const type = $(this).find(".column-type").val();
154
+ if (source && target) {
155
+ node.columnMappings.push({
156
+ source: source,
157
+ sourceType: sourceType,
158
+ target: target,
159
+ type: type
160
+ });
161
+ }
162
+ });
163
+ }
164
+ });
165
+ </script>
166
+
167
+ <script type="text/html" data-template-name="questdb-mapper">
168
+ <div class="form-row">
169
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
170
+ <input type="text" id="node-input-name" placeholder="Name">
171
+ </div>
172
+ <div class="form-row">
173
+ <label for="node-input-tableName"><i class="fa fa-table"></i> Table Name</label>
174
+ <input type="text" id="node-input-tableName" placeholder="Leave empty to use msg.topic">
175
+ </div>
176
+ <div class="form-row">
177
+ <label for="node-input-timestampField"><i class="fa fa-clock-o"></i> Timestamp Field</label>
178
+ <input type="hidden" id="node-input-timestampFieldType">
179
+ <input type="text" id="node-input-timestampField" placeholder="timestamp">
180
+ </div>
181
+ <div class="form-row">
182
+ <label style="width:100%;"><i class="fa fa-bookmark"></i> Symbol Mappings (indexed tags)</label>
183
+ <ol id="node-input-symbol-list"></ol>
184
+ </div>
185
+ <div class="form-row">
186
+ <label style="width:100%;"><i class="fa fa-columns"></i> Column Mappings (values)</label>
187
+ <ol id="node-input-column-list"></ol>
188
+ </div>
189
+ </script>
190
+
191
+ <script type="text/html" data-help-name="questdb-mapper">
192
+ <p>Maps message fields to QuestDB ILP structure for use with the Write node.</p>
193
+
194
+ <h3>Properties</h3>
195
+ <dl class="message-properties">
196
+ <dt>Table Name</dt>
197
+ <dd>Target table name. If empty, uses <code>msg.topic</code></dd>
198
+ <dt>Timestamp Field</dt>
199
+ <dd>Path to timestamp field (e.g. <code>payload.ts</code>)</dd>
200
+ <dt>Symbol Mappings</dt>
201
+ <dd>Map msg fields to QuestDB symbols (indexed string columns)</dd>
202
+ <dt>Column Mappings</dt>
203
+ <dd>Map msg fields to QuestDB columns with type conversion</dd>
204
+ </dl>
205
+
206
+ <h3>Column Types</h3>
207
+ <ul>
208
+ <li><b>auto</b> - Auto-detect type from value</li>
209
+ <li><b>float</b> - 32-bit floating point</li>
210
+ <li><b>double</b> - 64-bit floating point (higher precision)</li>
211
+ <li><b>integer</b> - 32-bit signed integer</li>
212
+ <li><b>long</b> - 64-bit signed integer</li>
213
+ <li><b>decimal</b> - Arbitrary precision decimal</li>
214
+ <li><b>varchar</b> - Variable-length text (QuestDB native type, preferred over string)</li>
215
+ <li><b>string</b> - Text value (alias for varchar)</li>
216
+ <li><b>boolean</b> - true/false</li>
217
+ <li><b>timestamp</b> - Date/time value</li>
218
+ <li><b>array</b> - Array of doubles (double[])</li>
219
+ </ul>
220
+
221
+ <h3>Field Path Syntax</h3>
222
+ <p>Use dot notation: <code>payload.sensor.value</code></p>
223
+ <p>Array access: <code>payload.readings[0]</code></p>
224
+
225
+ <h3>Output</h3>
226
+ <p>Produces a message ready for the QuestDB Write node:</p>
227
+ <pre>{
228
+ topic: "table_name",
229
+ payload: {
230
+ symbols: { ... },
231
+ columns: { ... },
232
+ timestamp: ...
233
+ }
234
+ }</pre>
235
+
236
+ <h3>Example</h3>
237
+ <p>Input message:</p>
238
+ <pre>{
239
+ topic: "sensors",
240
+ payload: {
241
+ device: "sensor1",
242
+ temp: 23.5,
243
+ readings: [1.1, 2.2, 3.3],
244
+ ts: 1699999999000
245
+ }
246
+ }</pre>
247
+ <p>With mappings:</p>
248
+ <ul>
249
+ <li>Symbol: <code>payload.device</code> → <code>device_id</code></li>
250
+ <li>Column: <code>payload.temp</code> → <code>temperature</code> (double)</li>
251
+ <li>Column: <code>payload.readings</code> → <code>values</code> (array)</li>
252
+ <li>Timestamp: <code>payload.ts</code></li>
253
+ </ul>
254
+ <p>Output:</p>
255
+ <pre>{
256
+ topic: "sensors",
257
+ payload: {
258
+ symbols: { device_id: "sensor1" },
259
+ columns: {
260
+ temperature: { value: 23.5, type: "double" },
261
+ values: { value: [1.1, 2.2, 3.3], type: "array" }
262
+ },
263
+ timestamp: 1699999999000
264
+ }
265
+ }</pre>
266
+ </script>
267
+
268
+ <style>
269
+ /* White text on flow canvas */
270
+ .questdb-white-text {
271
+ fill: #ffffff !important;
272
+ }
273
+ /* White text in palette */
274
+ .red-ui-palette-node[data-palette-type="questdb-mapper"] .red-ui-palette-label {
275
+ color: #ffffff !important;
276
+ }
277
+ /* Light grey icon background */
278
+ .red-ui-palette-node[data-palette-type="questdb-mapper"] .red-ui-palette-icon-container {
279
+ background-color: #f0f0f0 !important;
280
+ }
281
+ </style>
@@ -1,6 +1,7 @@
1
1
  <style>
2
2
  .questdb-white-text { fill: #ffffff !important; }
3
3
  .red-ui-palette-node[data-palette-type="questdb-type-router"] .red-ui-palette-label { color: #ffffff !important; }
4
+ .red-ui-palette-node[data-palette-type="questdb-type-router"] .red-ui-palette-icon-container { background-color: #f0f0f0 !important; }
4
5
  </style>
5
6
 
6
7
  <script type="text/javascript">
@@ -13,7 +14,7 @@
13
14
  inputs:1,
14
15
  outputs:5,
15
16
  outputLabels: ["long", "double", "bool", "string", "unresolvable"],
16
- icon: "font-awesome/fa-random",
17
+ icon: "questdb-logo.png",
17
18
  paletteLabel: "Type Router",
18
19
  label: function() { return this.name || "Type Router"; },
19
20
  labelStyle: function() { return (this.name ? "node_label_italic" : "") + " questdb-white-text"; }