@node-red/editor-client 4.1.5 → 4.1.6
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/package.json +1 -1
- package/public/red/about +11 -0
- package/public/red/red.js +287 -139
- package/public/red/red.min.js +3 -3
- package/public/vendor/mermaid/mermaid.min.js +727 -543
package/package.json
CHANGED
package/public/red/about
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
#### 4.1.6: Maintenance Release
|
|
2
|
+
|
|
3
|
+
- Allow palette.theme to be set via theme plugin and include icons (#5500) @knolleary
|
|
4
|
+
- Ensure config sidebar tooltip handles html content (#5501) @knolleary
|
|
5
|
+
- Allow node-red integrator access to available updates (#5499) @Steve-Mcl
|
|
6
|
+
- Add frontend pre and post debug message hooks (#5495) @Steve-Mcl
|
|
7
|
+
- Fix: allow middle-click panning over links and ports (#5496) @lklivingstone
|
|
8
|
+
- Support ctrl key to select configuration nodes (#5486) @kazuhitoyokoi
|
|
9
|
+
- Add § as shortcut meta-key (#5482) @gorenje
|
|
10
|
+
- Update dependencies (#5502) @knolleary
|
|
11
|
+
|
|
1
12
|
#### 4.1.5: Maintenance Release
|
|
2
13
|
|
|
3
14
|
- chore: bump tar to 7.5.7 (#5472) @bryopsida
|
package/public/red/red.js
CHANGED
|
@@ -1079,138 +1079,209 @@ var RED = (function() {
|
|
|
1079
1079
|
emit: emit
|
|
1080
1080
|
}
|
|
1081
1081
|
})();
|
|
1082
|
-
;RED.hooks = (function() {
|
|
1082
|
+
;RED.hooks = (function () {
|
|
1083
|
+
// At the time of writing this PR, VALID_HOOKS were not enforced. There may be a good reason for this
|
|
1084
|
+
// so the below flag has been added to permit this behaviour. If desired, this can be set to false to
|
|
1085
|
+
// enforce that only known hooks can be added/triggered.
|
|
1086
|
+
const knownHooksOnly = false
|
|
1087
|
+
|
|
1088
|
+
const VALID_HOOKS = Object.freeze({
|
|
1089
|
+
viewRemoveNode: true,
|
|
1090
|
+
viewAddNode: true,
|
|
1091
|
+
viewRemovePort: true,
|
|
1092
|
+
viewAddPort: true,
|
|
1093
|
+
viewRedrawNode: true,
|
|
1094
|
+
debugPreProcessMessage: true,
|
|
1095
|
+
debugPostProcessMessage: true
|
|
1096
|
+
})
|
|
1083
1097
|
|
|
1084
|
-
|
|
1098
|
+
/**
|
|
1099
|
+
* @typedef {keyof typeof VALID_HOOKS} HookId - A string literal type representing a hook identifier (sans label).
|
|
1100
|
+
*
|
|
1101
|
+
* @typedef {Object} HookItem - An item in the linked list of hooks for a given HookId
|
|
1102
|
+
* @property {function} cb - The callback function to be called when the hook is triggered
|
|
1103
|
+
* @property {HookItem|null} previousHook - The previous hook in the linked list
|
|
1104
|
+
* @property {HookItem|null} nextHook - The next hook in the linked list
|
|
1105
|
+
* @property {boolean} removed - Flag indicating if the hook has been removed
|
|
1106
|
+
*
|
|
1107
|
+
* @typedef {Record<HookId, HookItem|null>} Hooks - A mapping of HookIds to the head of their linked list of HookItems
|
|
1108
|
+
*/
|
|
1085
1109
|
|
|
1086
|
-
]
|
|
1087
1110
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1111
|
+
/** @type {Hooks} - A mapping of HookIds to the head of their linked list of HookItems */
|
|
1112
|
+
let hooks = {}
|
|
1113
|
+
|
|
1114
|
+
/** @type {Record<string, Record<HookId, HookItem>>} - A mapping of labels to their hooks */
|
|
1115
|
+
let labelledHooks = {}
|
|
1090
1116
|
|
|
1091
1117
|
function add(hookId, callback) {
|
|
1092
|
-
|
|
1093
|
-
var id = parts[0], label = parts[1];
|
|
1118
|
+
const { label, id } = parseLabelledHook(hookId)
|
|
1094
1119
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1120
|
+
if (knownHooksOnly && !isKnownHook(id)) {
|
|
1121
|
+
throw new Error("Invalid hook '" + id + "'")
|
|
1122
|
+
}
|
|
1098
1123
|
if (label && labelledHooks[label] && labelledHooks[label][id]) {
|
|
1099
|
-
throw new Error("Hook "+hookId+" already registered")
|
|
1124
|
+
throw new Error("Hook " + hookId + " already registered")
|
|
1100
1125
|
}
|
|
1101
|
-
|
|
1126
|
+
if (typeof callback !== "function") {
|
|
1127
|
+
throw new Error("Invalid hook '" + hookId + "'. Callback must be a function")
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
/** @type {HookItem} */
|
|
1131
|
+
const hookItem = { cb: callback, previousHook: null, nextHook: null }
|
|
1102
1132
|
|
|
1103
|
-
|
|
1133
|
+
let tailItem = hooks[id]
|
|
1104
1134
|
if (tailItem === undefined) {
|
|
1105
|
-
hooks[id] = hookItem
|
|
1135
|
+
hooks[id] = hookItem
|
|
1106
1136
|
} else {
|
|
1107
|
-
while(tailItem.nextHook !== null) {
|
|
1137
|
+
while (tailItem.nextHook !== null) {
|
|
1108
1138
|
tailItem = tailItem.nextHook
|
|
1109
1139
|
}
|
|
1110
|
-
tailItem.nextHook = hookItem
|
|
1111
|
-
hookItem.previousHook = tailItem
|
|
1140
|
+
tailItem.nextHook = hookItem
|
|
1141
|
+
hookItem.previousHook = tailItem
|
|
1112
1142
|
}
|
|
1113
1143
|
|
|
1114
1144
|
if (label) {
|
|
1115
|
-
labelledHooks[label] = labelledHooks[label]||{}
|
|
1116
|
-
labelledHooks[label][id] = hookItem
|
|
1145
|
+
labelledHooks[label] = labelledHooks[label] || {}
|
|
1146
|
+
labelledHooks[label][id] = hookItem
|
|
1117
1147
|
}
|
|
1118
1148
|
}
|
|
1149
|
+
|
|
1119
1150
|
function remove(hookId) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
throw new Error("Cannot remove hook without label: "+hookId)
|
|
1151
|
+
const { label, id } = parseLabelledHook(hookId)
|
|
1152
|
+
if (!label) {
|
|
1153
|
+
throw new Error("Cannot remove hook without label: " + hookId)
|
|
1124
1154
|
}
|
|
1125
1155
|
if (labelledHooks[label]) {
|
|
1126
1156
|
if (id === "*") {
|
|
1127
1157
|
// Remove all hooks for this label
|
|
1128
|
-
|
|
1129
|
-
for (
|
|
1130
|
-
removeHook(hookList[i],labelledHooks[label][hookList[i]])
|
|
1158
|
+
const hookList = Object.keys(labelledHooks[label])
|
|
1159
|
+
for (let i = 0; i < hookList.length; i++) {
|
|
1160
|
+
removeHook(hookList[i], labelledHooks[label][hookList[i]])
|
|
1131
1161
|
}
|
|
1132
|
-
delete labelledHooks[label]
|
|
1162
|
+
delete labelledHooks[label]
|
|
1133
1163
|
} else if (labelledHooks[label][id]) {
|
|
1134
|
-
removeHook(id,labelledHooks[label][id])
|
|
1135
|
-
delete labelledHooks[label][id]
|
|
1136
|
-
if (Object.keys(labelledHooks[label]).length === 0){
|
|
1137
|
-
delete labelledHooks[label]
|
|
1164
|
+
removeHook(id, labelledHooks[label][id])
|
|
1165
|
+
delete labelledHooks[label][id]
|
|
1166
|
+
if (Object.keys(labelledHooks[label]).length === 0) {
|
|
1167
|
+
delete labelledHooks[label]
|
|
1138
1168
|
}
|
|
1139
1169
|
}
|
|
1140
1170
|
}
|
|
1141
1171
|
}
|
|
1142
1172
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1173
|
+
/**
|
|
1174
|
+
* Remove a hook from the linked list of hooks for a given id
|
|
1175
|
+
* @param {HookId} id
|
|
1176
|
+
* @param {HookItem} hookItem
|
|
1177
|
+
* @private
|
|
1178
|
+
*/
|
|
1179
|
+
function removeHook(id, hookItem) {
|
|
1180
|
+
let previousHook = hookItem.previousHook
|
|
1181
|
+
let nextHook = hookItem.nextHook
|
|
1146
1182
|
|
|
1147
1183
|
if (previousHook) {
|
|
1148
|
-
previousHook.nextHook = nextHook
|
|
1184
|
+
previousHook.nextHook = nextHook
|
|
1149
1185
|
} else {
|
|
1150
|
-
hooks[id] = nextHook
|
|
1186
|
+
hooks[id] = nextHook
|
|
1151
1187
|
}
|
|
1152
1188
|
if (nextHook) {
|
|
1153
|
-
nextHook.previousHook = previousHook
|
|
1189
|
+
nextHook.previousHook = previousHook
|
|
1154
1190
|
}
|
|
1155
|
-
hookItem.removed = true
|
|
1191
|
+
hookItem.removed = true
|
|
1156
1192
|
if (!previousHook && !nextHook) {
|
|
1157
|
-
delete hooks[id]
|
|
1193
|
+
delete hooks[id]
|
|
1158
1194
|
}
|
|
1159
1195
|
}
|
|
1160
1196
|
|
|
1161
|
-
|
|
1162
|
-
|
|
1197
|
+
/**
|
|
1198
|
+
* Trigger a hook, calling all registered callbacks in sequence.
|
|
1199
|
+
* If any callback returns false, the flow is halted and no further hooks are called.
|
|
1200
|
+
* @param {HookId} id The id of the hook to trigger (should not include a label - e.g. "viewAddNode", not "viewAddNode.myLabel")
|
|
1201
|
+
* @param {*} payload The payload to be passed to each hook callback
|
|
1202
|
+
* @param {function(?Error=):void} [done] Optional callback. If not provided, a Promise will be returned.
|
|
1203
|
+
* @return {Promise|undefined} Returns a Promise if the done callback is not provided, otherwise undefined
|
|
1204
|
+
*/
|
|
1205
|
+
function trigger(id, payload, done) {
|
|
1206
|
+
let hookItem = hooks[id]
|
|
1163
1207
|
if (!hookItem) {
|
|
1164
1208
|
if (done) {
|
|
1165
|
-
done()
|
|
1209
|
+
done()
|
|
1210
|
+
return
|
|
1211
|
+
} else {
|
|
1212
|
+
return Promise.resolve()
|
|
1166
1213
|
}
|
|
1167
|
-
return;
|
|
1168
1214
|
}
|
|
1215
|
+
if (!done) {
|
|
1216
|
+
return new Promise((resolve, reject) => {
|
|
1217
|
+
invokeStack(hookItem, payload, function (err) {
|
|
1218
|
+
if (err !== undefined && err !== false) {
|
|
1219
|
+
if (!(err instanceof Error)) {
|
|
1220
|
+
err = new Error(err)
|
|
1221
|
+
}
|
|
1222
|
+
err.hook = id
|
|
1223
|
+
reject(err)
|
|
1224
|
+
} else {
|
|
1225
|
+
resolve(err)
|
|
1226
|
+
}
|
|
1227
|
+
})
|
|
1228
|
+
})
|
|
1229
|
+
} else {
|
|
1230
|
+
invokeStack(hookItem, payload, done)
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/**
|
|
1235
|
+
* @private
|
|
1236
|
+
*/
|
|
1237
|
+
function invokeStack(hookItem, payload, done) {
|
|
1169
1238
|
function callNextHook(err) {
|
|
1170
1239
|
if (!hookItem || err) {
|
|
1171
|
-
|
|
1172
|
-
return
|
|
1240
|
+
done(err)
|
|
1241
|
+
return
|
|
1173
1242
|
}
|
|
1174
1243
|
if (hookItem.removed) {
|
|
1175
|
-
hookItem = hookItem.nextHook
|
|
1176
|
-
|
|
1244
|
+
hookItem = hookItem.nextHook
|
|
1245
|
+
callNextHook()
|
|
1246
|
+
return
|
|
1177
1247
|
}
|
|
1178
|
-
|
|
1248
|
+
const callback = hookItem.cb
|
|
1179
1249
|
if (callback.length === 1) {
|
|
1180
1250
|
try {
|
|
1181
|
-
let result = callback(payload)
|
|
1251
|
+
let result = callback(payload)
|
|
1182
1252
|
if (result === false) {
|
|
1183
1253
|
// Halting the flow
|
|
1184
|
-
|
|
1185
|
-
return
|
|
1254
|
+
done(false)
|
|
1255
|
+
return
|
|
1186
1256
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1257
|
+
if (result && typeof result.then === 'function') {
|
|
1258
|
+
result.then(handleResolve, callNextHook)
|
|
1259
|
+
return
|
|
1260
|
+
}
|
|
1261
|
+
hookItem = hookItem.nextHook
|
|
1262
|
+
callNextHook()
|
|
1263
|
+
} catch (e) {
|
|
1264
|
+
done(e)
|
|
1265
|
+
return
|
|
1193
1266
|
}
|
|
1194
1267
|
} else {
|
|
1195
|
-
// There is a done callback
|
|
1196
1268
|
try {
|
|
1197
|
-
callback(payload,
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
} else {
|
|
1202
|
-
if (done) { done(result)}
|
|
1203
|
-
}
|
|
1204
|
-
})
|
|
1205
|
-
} catch(e) {
|
|
1206
|
-
console.warn(e);
|
|
1207
|
-
if (done) { done(e) }
|
|
1208
|
-
return e;
|
|
1269
|
+
callback(payload, handleResolve)
|
|
1270
|
+
} catch (e) {
|
|
1271
|
+
done(e)
|
|
1272
|
+
return
|
|
1209
1273
|
}
|
|
1210
1274
|
}
|
|
1211
1275
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1276
|
+
function handleResolve(result) {
|
|
1277
|
+
if (result === undefined) {
|
|
1278
|
+
hookItem = hookItem.nextHook
|
|
1279
|
+
callNextHook()
|
|
1280
|
+
} else {
|
|
1281
|
+
done(result)
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
callNextHook()
|
|
1214
1285
|
}
|
|
1215
1286
|
|
|
1216
1287
|
function clear() {
|
|
@@ -1218,23 +1289,51 @@ var RED = (function() {
|
|
|
1218
1289
|
labelledHooks = {}
|
|
1219
1290
|
}
|
|
1220
1291
|
|
|
1292
|
+
/**
|
|
1293
|
+
* Check if a hook with the given id exists
|
|
1294
|
+
* @param {string} hookId The hook identifier, which may include a label (e.g. "viewAddNode.myLabel")
|
|
1295
|
+
* @returns {boolean}
|
|
1296
|
+
*/
|
|
1221
1297
|
function has(hookId) {
|
|
1222
|
-
|
|
1223
|
-
var id = parts[0], label = parts[1];
|
|
1298
|
+
const { label, id } = parseLabelledHook(hookId)
|
|
1224
1299
|
if (label) {
|
|
1225
1300
|
return !!(labelledHooks[label] && labelledHooks[label][id])
|
|
1226
1301
|
}
|
|
1227
1302
|
return !!hooks[id]
|
|
1228
1303
|
}
|
|
1229
1304
|
|
|
1305
|
+
function isKnownHook(hookId) {
|
|
1306
|
+
const { id } = parseLabelledHook(hookId)
|
|
1307
|
+
return !!VALID_HOOKS[id]
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* Split a hook identifier into its id and label components.
|
|
1312
|
+
* @param {*} hookId A hook identifier, which may include a label (e.g. "viewAddNode.myLabel")
|
|
1313
|
+
* @returns {{label: string, id: HookId}}
|
|
1314
|
+
* @private
|
|
1315
|
+
*/
|
|
1316
|
+
function parseLabelledHook(hookId) {
|
|
1317
|
+
if (typeof hookId !== "string") {
|
|
1318
|
+
return { label: '', id: '' }
|
|
1319
|
+
}
|
|
1320
|
+
const parts = hookId.split(".")
|
|
1321
|
+
const id = parts[0]
|
|
1322
|
+
const label = parts[1]
|
|
1323
|
+
return { label, id }
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
VALID_HOOKS['all'] = true // Special wildcard to allow hooks to indicate they should be triggered for all ids
|
|
1327
|
+
|
|
1230
1328
|
return {
|
|
1231
|
-
has
|
|
1232
|
-
clear
|
|
1233
|
-
add
|
|
1234
|
-
remove
|
|
1235
|
-
trigger
|
|
1329
|
+
has,
|
|
1330
|
+
clear,
|
|
1331
|
+
add,
|
|
1332
|
+
remove,
|
|
1333
|
+
trigger,
|
|
1334
|
+
isKnownHook
|
|
1236
1335
|
}
|
|
1237
|
-
})()
|
|
1336
|
+
})()
|
|
1238
1337
|
;/**
|
|
1239
1338
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
1240
1339
|
*
|
|
@@ -10892,20 +10991,36 @@ RED.utils = (function() {
|
|
|
10892
10991
|
return result;
|
|
10893
10992
|
}
|
|
10894
10993
|
|
|
10994
|
+
/**
|
|
10995
|
+
* Get the default icon for a given node based on its definition.
|
|
10996
|
+
* @param {*} def
|
|
10997
|
+
* @param {*} node
|
|
10998
|
+
* @returns
|
|
10999
|
+
*/
|
|
10895
11000
|
function getDefaultNodeIcon(def,node) {
|
|
10896
11001
|
def = def || {};
|
|
10897
11002
|
var icon_url;
|
|
10898
11003
|
if (node && node.type === "subflow") {
|
|
10899
11004
|
icon_url = "node-red/subflow.svg";
|
|
10900
|
-
} else if (typeof def.icon === "function") {
|
|
10901
|
-
try {
|
|
10902
|
-
icon_url = def.icon.call(node);
|
|
10903
|
-
} catch(err) {
|
|
10904
|
-
console.log("Definition error: "+def.type+".icon",err);
|
|
10905
|
-
icon_url = "arrow-in.svg";
|
|
10906
|
-
}
|
|
10907
11005
|
} else {
|
|
10908
|
-
|
|
11006
|
+
let themeRule = nodeIconCache[def.type]
|
|
11007
|
+
if (themeRule === undefined) {
|
|
11008
|
+
// If undefined, we've not checked the theme yet
|
|
11009
|
+
nodeIconCache[def.type] = getThemeOverrideForNode(def, 'icon') || null;
|
|
11010
|
+
themeRule = nodeIconCache[def.type];
|
|
11011
|
+
}
|
|
11012
|
+
if (themeRule) {
|
|
11013
|
+
icon_url = themeRule.icon;
|
|
11014
|
+
} else if (typeof def.icon === "function") {
|
|
11015
|
+
try {
|
|
11016
|
+
icon_url = def.icon.call(node);
|
|
11017
|
+
} catch(err) {
|
|
11018
|
+
console.log("Definition error: "+def.type+".icon",err);
|
|
11019
|
+
icon_url = "arrow-in.svg";
|
|
11020
|
+
}
|
|
11021
|
+
} else {
|
|
11022
|
+
icon_url = def.icon;
|
|
11023
|
+
}
|
|
10909
11024
|
}
|
|
10910
11025
|
|
|
10911
11026
|
var iconPath = separateIconPath(icon_url);
|
|
@@ -11031,48 +11146,60 @@ RED.utils = (function() {
|
|
|
11031
11146
|
return label
|
|
11032
11147
|
}
|
|
11033
11148
|
|
|
11034
|
-
|
|
11149
|
+
let nodeColorCache = {};
|
|
11150
|
+
let nodeIconCache = {}
|
|
11035
11151
|
function clearNodeColorCache() {
|
|
11036
11152
|
nodeColorCache = {};
|
|
11037
11153
|
}
|
|
11038
11154
|
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11155
|
+
/**
|
|
11156
|
+
* Checks if there is a theme override for the given node definition and property
|
|
11157
|
+
* @param {*} def node definition
|
|
11158
|
+
* @param {*} property either 'color' or 'icon'
|
|
11159
|
+
* @returns the theme override value if there is a match, otherwise null
|
|
11160
|
+
*/
|
|
11161
|
+
function getThemeOverrideForNode(def, property) {
|
|
11162
|
+
const paletteTheme = RED.settings.theme('palette.theme') || [];
|
|
11043
11163
|
if (paletteTheme.length > 0) {
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
if (themeRule.hasOwnProperty('category')) {
|
|
11050
|
-
if (!themeRule.hasOwnProperty('_category')) {
|
|
11051
|
-
themeRule._category = new RegExp(themeRule.category);
|
|
11052
|
-
}
|
|
11053
|
-
if (!themeRule._category.test(def.category)) {
|
|
11054
|
-
continue;
|
|
11055
|
-
}
|
|
11164
|
+
for (let i = 0; i < paletteTheme.length; i++ ){
|
|
11165
|
+
const themeRule = paletteTheme[i];
|
|
11166
|
+
if (themeRule.hasOwnProperty('category')) {
|
|
11167
|
+
if (!themeRule.hasOwnProperty('_category')) {
|
|
11168
|
+
themeRule._category = new RegExp(themeRule.category);
|
|
11056
11169
|
}
|
|
11057
|
-
if (themeRule.
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11170
|
+
if (!themeRule._category.test(def.category)) {
|
|
11171
|
+
continue;
|
|
11172
|
+
}
|
|
11173
|
+
}
|
|
11174
|
+
if (themeRule.hasOwnProperty('type')) {
|
|
11175
|
+
if (!themeRule.hasOwnProperty('_type')) {
|
|
11176
|
+
themeRule._type = new RegExp(themeRule.type);
|
|
11177
|
+
}
|
|
11178
|
+
if (!themeRule._type.test(def.type)) {
|
|
11179
|
+
continue;
|
|
11064
11180
|
}
|
|
11065
|
-
|
|
11066
|
-
|
|
11181
|
+
}
|
|
11182
|
+
// We have found a rule that matches - now see if it provides the requested property
|
|
11183
|
+
if (themeRule.hasOwnProperty(property)) {
|
|
11184
|
+
return themeRule;
|
|
11067
11185
|
}
|
|
11068
11186
|
}
|
|
11069
|
-
result = nodeColorCache[type];
|
|
11070
11187
|
}
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11188
|
+
return null;
|
|
11189
|
+
}
|
|
11190
|
+
|
|
11191
|
+
function getNodeColor(type, def) {
|
|
11192
|
+
def = def || {};
|
|
11193
|
+
if (!nodeColorCache.hasOwnProperty(type)) {
|
|
11194
|
+
const paletteTheme = RED.settings.theme('palette.theme') || [];
|
|
11195
|
+
if (paletteTheme.length > 0) {
|
|
11196
|
+
const themeRule = getThemeOverrideForNode(def, 'color');
|
|
11197
|
+
nodeColorCache[type] = themeRule?.color || def.color;
|
|
11198
|
+
} else {
|
|
11199
|
+
nodeColorCache[type] = def.color;
|
|
11200
|
+
}
|
|
11075
11201
|
}
|
|
11202
|
+
return nodeColorCache[type] || "#ddd";
|
|
11076
11203
|
}
|
|
11077
11204
|
|
|
11078
11205
|
function addSpinnerOverlay(container,contain) {
|
|
@@ -20790,6 +20917,7 @@ RED.keyboard = (function() {
|
|
|
20790
20917
|
"-":189,
|
|
20791
20918
|
".":190,
|
|
20792
20919
|
"/":191,
|
|
20920
|
+
"§":192, // <- top left key MacOS
|
|
20793
20921
|
"\\":220,
|
|
20794
20922
|
"'":222,
|
|
20795
20923
|
"?":191, // <- QWERTY specific
|
|
@@ -25892,7 +26020,7 @@ RED.view = (function() {
|
|
|
25892
26020
|
clearSuggestedFlow();
|
|
25893
26021
|
RED.contextMenu.hide();
|
|
25894
26022
|
evt = evt || d3.event;
|
|
25895
|
-
if (evt
|
|
26023
|
+
if (evt.button !== 0) {
|
|
25896
26024
|
return;
|
|
25897
26025
|
}
|
|
25898
26026
|
if (mouse_mode === RED.state.SELECTING_NODE) {
|
|
@@ -26748,7 +26876,7 @@ RED.view = (function() {
|
|
|
26748
26876
|
d3.event.stopPropagation();
|
|
26749
26877
|
return;
|
|
26750
26878
|
}
|
|
26751
|
-
if (d3.event.button
|
|
26879
|
+
if (d3.event.button !== 0) {
|
|
26752
26880
|
return
|
|
26753
26881
|
}
|
|
26754
26882
|
mousedown_link = d;
|
|
@@ -34636,7 +34764,7 @@ RED.sidebar.config = (function() {
|
|
|
34636
34764
|
nodeDiv.addClass("red-ui-palette-node-config-invalid");
|
|
34637
34765
|
RED.popover.tooltip(nodeDivAnnotations, function () {
|
|
34638
34766
|
if (node.validationErrors && node.validationErrors.length > 0) {
|
|
34639
|
-
return RED._("editor.errors.invalidProperties") + "<br> - " + node.validationErrors.join("<br> - ");
|
|
34767
|
+
return $('<span>' + RED._("editor.errors.invalidProperties") + "<br> - " + node.validationErrors.join("<br> - ") + '</span>');
|
|
34640
34768
|
}
|
|
34641
34769
|
})
|
|
34642
34770
|
}
|
|
@@ -34644,7 +34772,7 @@ RED.sidebar.config = (function() {
|
|
|
34644
34772
|
nodeDiv.on('click',function(e) {
|
|
34645
34773
|
e.stopPropagation();
|
|
34646
34774
|
RED.view.select(false);
|
|
34647
|
-
if (e.metaKey) {
|
|
34775
|
+
if (e.metaKey || e.ctrlKey) {
|
|
34648
34776
|
$(this).toggleClass("selected");
|
|
34649
34777
|
} else {
|
|
34650
34778
|
$(content).find(".red-ui-palette-node").removeClass("selected");
|
|
@@ -35294,6 +35422,12 @@ RED.palette.editor = (function() {
|
|
|
35294
35422
|
// Install tab - search input
|
|
35295
35423
|
let searchInput;
|
|
35296
35424
|
|
|
35425
|
+
// Core and Package Updates
|
|
35426
|
+
/** @type {Array<{package: string, current: string, available: string}>} */
|
|
35427
|
+
const moduleUpdates = []
|
|
35428
|
+
const updateStatusState = { version: null, moduleCount: 0 }
|
|
35429
|
+
|
|
35430
|
+
|
|
35297
35431
|
const SMALL_CATALOGUE_SIZE = 40
|
|
35298
35432
|
|
|
35299
35433
|
const typesInUse = {};
|
|
@@ -37079,8 +37213,6 @@ RED.palette.editor = (function() {
|
|
|
37079
37213
|
|
|
37080
37214
|
const updateStatusWidget = $('<button type="button" class="red-ui-footer-button red-ui-update-status"></button>');
|
|
37081
37215
|
let updateStatusWidgetPopover;
|
|
37082
|
-
const updateStatusState = { moduleCount: 0 }
|
|
37083
|
-
let updateAvailable = [];
|
|
37084
37216
|
|
|
37085
37217
|
function addUpdateInfoToStatusBar() {
|
|
37086
37218
|
updateStatusWidgetPopover = RED.popover.create({
|
|
@@ -37089,7 +37221,7 @@ RED.palette.editor = (function() {
|
|
|
37089
37221
|
interactive: true,
|
|
37090
37222
|
direction: "bottom",
|
|
37091
37223
|
content: function () {
|
|
37092
|
-
const count =
|
|
37224
|
+
const count = moduleUpdates.length || 0
|
|
37093
37225
|
const content = $('<div style="display: flex; flex-direction: column; gap: 5px;"></div>');
|
|
37094
37226
|
if (updateStatusState.version) {
|
|
37095
37227
|
$(`<a class='red-ui-button' href="https://github.com/node-red/node-red/releases/tag/${updateStatusState.version}" target="_blank">${RED._("telemetry.updateAvailableDesc", updateStatusState)}</a>`).appendTo(content)
|
|
@@ -37099,7 +37231,7 @@ RED.palette.editor = (function() {
|
|
|
37099
37231
|
updateStatusWidgetPopover.close()
|
|
37100
37232
|
RED.actions.invoke("core:manage-palette", {
|
|
37101
37233
|
view: "nodes",
|
|
37102
|
-
filter: '"' +
|
|
37234
|
+
filter: '"' + moduleUpdates.map(u => u.package).join('", "') + '"'
|
|
37103
37235
|
});
|
|
37104
37236
|
}).appendTo(content)
|
|
37105
37237
|
}
|
|
@@ -37121,7 +37253,7 @@ RED.palette.editor = (function() {
|
|
|
37121
37253
|
function refreshUpdateStatus() {
|
|
37122
37254
|
clearTimeout(pendingRefreshTimeout)
|
|
37123
37255
|
pendingRefreshTimeout = setTimeout(() => {
|
|
37124
|
-
|
|
37256
|
+
moduleUpdates.length = 0
|
|
37125
37257
|
for (const module of Object.keys(nodeEntries)) {
|
|
37126
37258
|
if (loadedIndex.hasOwnProperty(module)) {
|
|
37127
37259
|
const moduleInfo = nodeEntries[module].info;
|
|
@@ -37129,36 +37261,52 @@ RED.palette.editor = (function() {
|
|
|
37129
37261
|
// Module updated
|
|
37130
37262
|
continue;
|
|
37131
37263
|
}
|
|
37264
|
+
const current = moduleInfo.version
|
|
37265
|
+
const latest = loadedIndex[module].version
|
|
37132
37266
|
if (updateAllowed &&
|
|
37133
|
-
semVerCompare(
|
|
37267
|
+
semVerCompare(latest, current) > 0 &&
|
|
37134
37268
|
RED.utils.checkModuleAllowed(module, null, updateAllowList, updateDenyList)
|
|
37135
37269
|
) {
|
|
37136
|
-
|
|
37270
|
+
moduleUpdates.push({ package: module, current, latest })
|
|
37137
37271
|
}
|
|
37138
37272
|
}
|
|
37139
37273
|
}
|
|
37140
|
-
updateStatusState.moduleCount =
|
|
37274
|
+
updateStatusState.moduleCount = moduleUpdates.length
|
|
37141
37275
|
updateStatus();
|
|
37142
37276
|
}, 200)
|
|
37143
37277
|
}
|
|
37144
37278
|
|
|
37145
37279
|
function updateStatus() {
|
|
37146
|
-
|
|
37280
|
+
const updates = RED.palette.editor.getAvailableUpdates()
|
|
37281
|
+
if (updates.count > 0) {
|
|
37147
37282
|
updateStatusWidget.empty();
|
|
37148
|
-
|
|
37149
|
-
if (updateStatusState.version) {
|
|
37150
|
-
count ++
|
|
37151
|
-
}
|
|
37152
|
-
$(`<span><i class="fa fa-cube"></i> ${RED._("telemetry.updateAvailable", { count: count })}</span>`).appendTo(updateStatusWidget);
|
|
37283
|
+
$(`<span><i class="fa fa-cube"></i> ${RED._("telemetry.updateAvailable", { count: updates.count })}</span>`).appendTo(updateStatusWidget);
|
|
37153
37284
|
RED.statusBar.show("red-ui-status-package-update");
|
|
37154
37285
|
} else {
|
|
37155
37286
|
RED.statusBar.hide("red-ui-status-package-update");
|
|
37156
37287
|
}
|
|
37288
|
+
RED.events.emit("registry:updates-available", updates)
|
|
37289
|
+
}
|
|
37290
|
+
|
|
37291
|
+
function getAvailableUpdates () {
|
|
37292
|
+
const palette = [...moduleUpdates]
|
|
37293
|
+
let core = null
|
|
37294
|
+
let count = palette.length
|
|
37295
|
+
if (updateStatusState.version) {
|
|
37296
|
+
core = { current: RED.settings.version, latest: updateStatusState.version }
|
|
37297
|
+
count ++
|
|
37298
|
+
}
|
|
37299
|
+
return {
|
|
37300
|
+
count,
|
|
37301
|
+
core,
|
|
37302
|
+
palette
|
|
37303
|
+
}
|
|
37157
37304
|
}
|
|
37158
37305
|
|
|
37159
37306
|
return {
|
|
37160
|
-
init
|
|
37161
|
-
install
|
|
37307
|
+
init,
|
|
37308
|
+
install,
|
|
37309
|
+
getAvailableUpdates
|
|
37162
37310
|
}
|
|
37163
37311
|
})();
|
|
37164
37312
|
;/**
|