@node-red/editor-client 4.1.5 → 4.1.7
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 +22 -0
- package/public/red/red.js +292 -139
- package/public/red/red.min.js +3 -3
- package/public/red/style.min.css +1 -1
- package/public/vendor/mermaid/mermaid.min.js +727 -543
- package/public/vendor/vendor.js +1 -1
package/package.json
CHANGED
package/public/red/about
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
#### 4.1.7: Maintenance Release
|
|
2
|
+
|
|
3
|
+
- Do not block touch events on ports (#5527) @knolleary
|
|
4
|
+
- Allow palette.categories to be set via theme plugin (#5526) @knolleary
|
|
5
|
+
- Bump i18next version (#5519) @knolleary
|
|
6
|
+
- Suppress i18n notice in frontend (#5528) @knolleary
|
|
7
|
+
- Set showSupportNotice option on i18n (#5520) @knolleary
|
|
8
|
+
- Do not cache subflow colors as each subflow can have its own (#5518) @knolleary
|
|
9
|
+
- Update tar/multer deps (#5515) @knolleary
|
|
10
|
+
- Remove IE7 CSS hacks (#5511) @bonanitech
|
|
11
|
+
|
|
12
|
+
#### 4.1.6: Maintenance Release
|
|
13
|
+
|
|
14
|
+
- Allow palette.theme to be set via theme plugin and include icons (#5500) @knolleary
|
|
15
|
+
- Ensure config sidebar tooltip handles html content (#5501) @knolleary
|
|
16
|
+
- Allow node-red integrator access to available updates (#5499) @Steve-Mcl
|
|
17
|
+
- Add frontend pre and post debug message hooks (#5495) @Steve-Mcl
|
|
18
|
+
- Fix: allow middle-click panning over links and ports (#5496) @lklivingstone
|
|
19
|
+
- Support ctrl key to select configuration nodes (#5486) @kazuhitoyokoi
|
|
20
|
+
- Add § as shortcut meta-key (#5482) @gorenje
|
|
21
|
+
- Update dependencies (#5502) @knolleary
|
|
22
|
+
|
|
1
23
|
#### 4.1.5: Maintenance Release
|
|
2
24
|
|
|
3
25
|
- 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
|
+
})
|
|
1097
|
+
|
|
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
|
+
*/
|
|
1083
1109
|
|
|
1084
|
-
var VALID_HOOKS = [
|
|
1085
1110
|
|
|
1086
|
-
|
|
1111
|
+
/** @type {Hooks} - A mapping of HookIds to the head of their linked list of HookItems */
|
|
1112
|
+
let hooks = {}
|
|
1087
1113
|
|
|
1088
|
-
|
|
1089
|
-
|
|
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")
|
|
1125
|
+
}
|
|
1126
|
+
if (typeof callback !== "function") {
|
|
1127
|
+
throw new Error("Invalid hook '" + hookId + "'. Callback must be a function")
|
|
1100
1128
|
}
|
|
1101
|
-
var hookItem = {cb:callback, previousHook: null, nextHook: null }
|
|
1102
1129
|
|
|
1103
|
-
|
|
1130
|
+
/** @type {HookItem} */
|
|
1131
|
+
const hookItem = { cb: callback, previousHook: null, nextHook: null }
|
|
1132
|
+
|
|
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
|
|
1256
|
+
}
|
|
1257
|
+
if (result && typeof result.then === 'function') {
|
|
1258
|
+
result.then(handleResolve, callNextHook)
|
|
1259
|
+
return
|
|
1186
1260
|
}
|
|
1187
|
-
hookItem = hookItem.nextHook
|
|
1188
|
-
|
|
1189
|
-
} catch(e) {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
return e;
|
|
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
|
*
|
|
@@ -1264,6 +1363,7 @@ RED.i18n = (function() {
|
|
|
1264
1363
|
apiRootUrl = options.apiRootUrl||"";
|
|
1265
1364
|
var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage();
|
|
1266
1365
|
var opts = {
|
|
1366
|
+
showSupportNotice: false,
|
|
1267
1367
|
backend: {
|
|
1268
1368
|
loadPath: apiRootUrl+'locales/__ns__?lng=__lng__',
|
|
1269
1369
|
},
|
|
@@ -10892,20 +10992,36 @@ RED.utils = (function() {
|
|
|
10892
10992
|
return result;
|
|
10893
10993
|
}
|
|
10894
10994
|
|
|
10995
|
+
/**
|
|
10996
|
+
* Get the default icon for a given node based on its definition.
|
|
10997
|
+
* @param {*} def
|
|
10998
|
+
* @param {*} node
|
|
10999
|
+
* @returns
|
|
11000
|
+
*/
|
|
10895
11001
|
function getDefaultNodeIcon(def,node) {
|
|
10896
11002
|
def = def || {};
|
|
10897
11003
|
var icon_url;
|
|
10898
11004
|
if (node && node.type === "subflow") {
|
|
10899
11005
|
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
11006
|
} else {
|
|
10908
|
-
|
|
11007
|
+
let themeRule = nodeIconCache[def.type]
|
|
11008
|
+
if (themeRule === undefined) {
|
|
11009
|
+
// If undefined, we've not checked the theme yet
|
|
11010
|
+
nodeIconCache[def.type] = getThemeOverrideForNode(def, 'icon') || null;
|
|
11011
|
+
themeRule = nodeIconCache[def.type];
|
|
11012
|
+
}
|
|
11013
|
+
if (themeRule) {
|
|
11014
|
+
icon_url = themeRule.icon;
|
|
11015
|
+
} else if (typeof def.icon === "function") {
|
|
11016
|
+
try {
|
|
11017
|
+
icon_url = def.icon.call(node);
|
|
11018
|
+
} catch(err) {
|
|
11019
|
+
console.log("Definition error: "+def.type+".icon",err);
|
|
11020
|
+
icon_url = "arrow-in.svg";
|
|
11021
|
+
}
|
|
11022
|
+
} else {
|
|
11023
|
+
icon_url = def.icon;
|
|
11024
|
+
}
|
|
10909
11025
|
}
|
|
10910
11026
|
|
|
10911
11027
|
var iconPath = separateIconPath(icon_url);
|
|
@@ -11031,48 +11147,63 @@ RED.utils = (function() {
|
|
|
11031
11147
|
return label
|
|
11032
11148
|
}
|
|
11033
11149
|
|
|
11034
|
-
|
|
11150
|
+
let nodeColorCache = {};
|
|
11151
|
+
let nodeIconCache = {}
|
|
11035
11152
|
function clearNodeColorCache() {
|
|
11036
11153
|
nodeColorCache = {};
|
|
11037
11154
|
}
|
|
11038
11155
|
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11156
|
+
/**
|
|
11157
|
+
* Checks if there is a theme override for the given node definition and property
|
|
11158
|
+
* @param {*} def node definition
|
|
11159
|
+
* @param {*} property either 'color' or 'icon'
|
|
11160
|
+
* @returns the theme override value if there is a match, otherwise null
|
|
11161
|
+
*/
|
|
11162
|
+
function getThemeOverrideForNode(def, property) {
|
|
11163
|
+
const paletteTheme = RED.settings.theme('palette.theme') || [];
|
|
11043
11164
|
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
|
-
}
|
|
11165
|
+
for (let i = 0; i < paletteTheme.length; i++ ){
|
|
11166
|
+
const themeRule = paletteTheme[i];
|
|
11167
|
+
if (themeRule.hasOwnProperty('category')) {
|
|
11168
|
+
if (!themeRule.hasOwnProperty('_category')) {
|
|
11169
|
+
themeRule._category = new RegExp(themeRule.category);
|
|
11056
11170
|
}
|
|
11057
|
-
if (themeRule.
|
|
11058
|
-
|
|
11059
|
-
themeRule._type = new RegExp(themeRule.type);
|
|
11060
|
-
}
|
|
11061
|
-
if (!themeRule._type.test(type)) {
|
|
11062
|
-
continue;
|
|
11063
|
-
}
|
|
11171
|
+
if (!themeRule._category.test(def.category)) {
|
|
11172
|
+
continue;
|
|
11064
11173
|
}
|
|
11065
|
-
|
|
11066
|
-
|
|
11174
|
+
}
|
|
11175
|
+
if (themeRule.hasOwnProperty('type')) {
|
|
11176
|
+
if (!themeRule.hasOwnProperty('_type')) {
|
|
11177
|
+
themeRule._type = new RegExp(themeRule.type);
|
|
11178
|
+
}
|
|
11179
|
+
if (!themeRule._type.test(def.type)) {
|
|
11180
|
+
continue;
|
|
11181
|
+
}
|
|
11182
|
+
}
|
|
11183
|
+
// We have found a rule that matches - now see if it provides the requested property
|
|
11184
|
+
if (themeRule.hasOwnProperty(property)) {
|
|
11185
|
+
return themeRule;
|
|
11067
11186
|
}
|
|
11068
11187
|
}
|
|
11069
|
-
result = nodeColorCache[type];
|
|
11070
11188
|
}
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11189
|
+
return null;
|
|
11190
|
+
}
|
|
11191
|
+
|
|
11192
|
+
function getNodeColor(type, def) {
|
|
11193
|
+
def = def || {};
|
|
11194
|
+
if (type === 'subflow') {
|
|
11195
|
+
return def.color
|
|
11196
|
+
}
|
|
11197
|
+
if (!nodeColorCache.hasOwnProperty(type)) {
|
|
11198
|
+
const paletteTheme = RED.settings.theme('palette.theme') || [];
|
|
11199
|
+
if (paletteTheme.length > 0) {
|
|
11200
|
+
const themeRule = getThemeOverrideForNode(def, 'color');
|
|
11201
|
+
nodeColorCache[type] = themeRule?.color || def.color;
|
|
11202
|
+
} else {
|
|
11203
|
+
nodeColorCache[type] = def.color;
|
|
11204
|
+
}
|
|
11075
11205
|
}
|
|
11206
|
+
return nodeColorCache[type] || "#ddd";
|
|
11076
11207
|
}
|
|
11077
11208
|
|
|
11078
11209
|
function addSpinnerOverlay(container,contain) {
|
|
@@ -20790,6 +20921,7 @@ RED.keyboard = (function() {
|
|
|
20790
20921
|
"-":189,
|
|
20791
20922
|
".":190,
|
|
20792
20923
|
"/":191,
|
|
20924
|
+
"§":192, // <- top left key MacOS
|
|
20793
20925
|
"\\":220,
|
|
20794
20926
|
"'":222,
|
|
20795
20927
|
"?":191, // <- QWERTY specific
|
|
@@ -25892,7 +26024,8 @@ RED.view = (function() {
|
|
|
25892
26024
|
clearSuggestedFlow();
|
|
25893
26025
|
RED.contextMenu.hide();
|
|
25894
26026
|
evt = evt || d3.event;
|
|
25895
|
-
|
|
26027
|
+
|
|
26028
|
+
if (!evt.touches && evt.button !== 0) {
|
|
25896
26029
|
return;
|
|
25897
26030
|
}
|
|
25898
26031
|
if (mouse_mode === RED.state.SELECTING_NODE) {
|
|
@@ -26748,7 +26881,7 @@ RED.view = (function() {
|
|
|
26748
26881
|
d3.event.stopPropagation();
|
|
26749
26882
|
return;
|
|
26750
26883
|
}
|
|
26751
|
-
if (d3.event.button
|
|
26884
|
+
if (!d3.event.touches && d3.event.button !== 0) {
|
|
26752
26885
|
return
|
|
26753
26886
|
}
|
|
26754
26887
|
mousedown_link = d;
|
|
@@ -34636,7 +34769,7 @@ RED.sidebar.config = (function() {
|
|
|
34636
34769
|
nodeDiv.addClass("red-ui-palette-node-config-invalid");
|
|
34637
34770
|
RED.popover.tooltip(nodeDivAnnotations, function () {
|
|
34638
34771
|
if (node.validationErrors && node.validationErrors.length > 0) {
|
|
34639
|
-
return RED._("editor.errors.invalidProperties") + "<br> - " + node.validationErrors.join("<br> - ");
|
|
34772
|
+
return $('<span>' + RED._("editor.errors.invalidProperties") + "<br> - " + node.validationErrors.join("<br> - ") + '</span>');
|
|
34640
34773
|
}
|
|
34641
34774
|
})
|
|
34642
34775
|
}
|
|
@@ -34644,7 +34777,7 @@ RED.sidebar.config = (function() {
|
|
|
34644
34777
|
nodeDiv.on('click',function(e) {
|
|
34645
34778
|
e.stopPropagation();
|
|
34646
34779
|
RED.view.select(false);
|
|
34647
|
-
if (e.metaKey) {
|
|
34780
|
+
if (e.metaKey || e.ctrlKey) {
|
|
34648
34781
|
$(this).toggleClass("selected");
|
|
34649
34782
|
} else {
|
|
34650
34783
|
$(content).find(".red-ui-palette-node").removeClass("selected");
|
|
@@ -35294,6 +35427,12 @@ RED.palette.editor = (function() {
|
|
|
35294
35427
|
// Install tab - search input
|
|
35295
35428
|
let searchInput;
|
|
35296
35429
|
|
|
35430
|
+
// Core and Package Updates
|
|
35431
|
+
/** @type {Array<{package: string, current: string, available: string}>} */
|
|
35432
|
+
const moduleUpdates = []
|
|
35433
|
+
const updateStatusState = { version: null, moduleCount: 0 }
|
|
35434
|
+
|
|
35435
|
+
|
|
35297
35436
|
const SMALL_CATALOGUE_SIZE = 40
|
|
35298
35437
|
|
|
35299
35438
|
const typesInUse = {};
|
|
@@ -37079,8 +37218,6 @@ RED.palette.editor = (function() {
|
|
|
37079
37218
|
|
|
37080
37219
|
const updateStatusWidget = $('<button type="button" class="red-ui-footer-button red-ui-update-status"></button>');
|
|
37081
37220
|
let updateStatusWidgetPopover;
|
|
37082
|
-
const updateStatusState = { moduleCount: 0 }
|
|
37083
|
-
let updateAvailable = [];
|
|
37084
37221
|
|
|
37085
37222
|
function addUpdateInfoToStatusBar() {
|
|
37086
37223
|
updateStatusWidgetPopover = RED.popover.create({
|
|
@@ -37089,7 +37226,7 @@ RED.palette.editor = (function() {
|
|
|
37089
37226
|
interactive: true,
|
|
37090
37227
|
direction: "bottom",
|
|
37091
37228
|
content: function () {
|
|
37092
|
-
const count =
|
|
37229
|
+
const count = moduleUpdates.length || 0
|
|
37093
37230
|
const content = $('<div style="display: flex; flex-direction: column; gap: 5px;"></div>');
|
|
37094
37231
|
if (updateStatusState.version) {
|
|
37095
37232
|
$(`<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 +37236,7 @@ RED.palette.editor = (function() {
|
|
|
37099
37236
|
updateStatusWidgetPopover.close()
|
|
37100
37237
|
RED.actions.invoke("core:manage-palette", {
|
|
37101
37238
|
view: "nodes",
|
|
37102
|
-
filter: '"' +
|
|
37239
|
+
filter: '"' + moduleUpdates.map(u => u.package).join('", "') + '"'
|
|
37103
37240
|
});
|
|
37104
37241
|
}).appendTo(content)
|
|
37105
37242
|
}
|
|
@@ -37121,7 +37258,7 @@ RED.palette.editor = (function() {
|
|
|
37121
37258
|
function refreshUpdateStatus() {
|
|
37122
37259
|
clearTimeout(pendingRefreshTimeout)
|
|
37123
37260
|
pendingRefreshTimeout = setTimeout(() => {
|
|
37124
|
-
|
|
37261
|
+
moduleUpdates.length = 0
|
|
37125
37262
|
for (const module of Object.keys(nodeEntries)) {
|
|
37126
37263
|
if (loadedIndex.hasOwnProperty(module)) {
|
|
37127
37264
|
const moduleInfo = nodeEntries[module].info;
|
|
@@ -37129,36 +37266,52 @@ RED.palette.editor = (function() {
|
|
|
37129
37266
|
// Module updated
|
|
37130
37267
|
continue;
|
|
37131
37268
|
}
|
|
37269
|
+
const current = moduleInfo.version
|
|
37270
|
+
const latest = loadedIndex[module].version
|
|
37132
37271
|
if (updateAllowed &&
|
|
37133
|
-
semVerCompare(
|
|
37272
|
+
semVerCompare(latest, current) > 0 &&
|
|
37134
37273
|
RED.utils.checkModuleAllowed(module, null, updateAllowList, updateDenyList)
|
|
37135
37274
|
) {
|
|
37136
|
-
|
|
37275
|
+
moduleUpdates.push({ package: module, current, latest })
|
|
37137
37276
|
}
|
|
37138
37277
|
}
|
|
37139
37278
|
}
|
|
37140
|
-
updateStatusState.moduleCount =
|
|
37279
|
+
updateStatusState.moduleCount = moduleUpdates.length
|
|
37141
37280
|
updateStatus();
|
|
37142
37281
|
}, 200)
|
|
37143
37282
|
}
|
|
37144
37283
|
|
|
37145
37284
|
function updateStatus() {
|
|
37146
|
-
|
|
37285
|
+
const updates = RED.palette.editor.getAvailableUpdates()
|
|
37286
|
+
if (updates.count > 0) {
|
|
37147
37287
|
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);
|
|
37288
|
+
$(`<span><i class="fa fa-cube"></i> ${RED._("telemetry.updateAvailable", { count: updates.count })}</span>`).appendTo(updateStatusWidget);
|
|
37153
37289
|
RED.statusBar.show("red-ui-status-package-update");
|
|
37154
37290
|
} else {
|
|
37155
37291
|
RED.statusBar.hide("red-ui-status-package-update");
|
|
37156
37292
|
}
|
|
37293
|
+
RED.events.emit("registry:updates-available", updates)
|
|
37294
|
+
}
|
|
37295
|
+
|
|
37296
|
+
function getAvailableUpdates () {
|
|
37297
|
+
const palette = [...moduleUpdates]
|
|
37298
|
+
let core = null
|
|
37299
|
+
let count = palette.length
|
|
37300
|
+
if (updateStatusState.version) {
|
|
37301
|
+
core = { current: RED.settings.version, latest: updateStatusState.version }
|
|
37302
|
+
count ++
|
|
37303
|
+
}
|
|
37304
|
+
return {
|
|
37305
|
+
count,
|
|
37306
|
+
core,
|
|
37307
|
+
palette
|
|
37308
|
+
}
|
|
37157
37309
|
}
|
|
37158
37310
|
|
|
37159
37311
|
return {
|
|
37160
|
-
init
|
|
37161
|
-
install
|
|
37312
|
+
init,
|
|
37313
|
+
install,
|
|
37314
|
+
getAvailableUpdates
|
|
37162
37315
|
}
|
|
37163
37316
|
})();
|
|
37164
37317
|
;/**
|