@node-red/editor-client 4.0.0-beta.2 → 4.0.0-beta.3
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/locales/en-US/editor.json +7 -1
- package/locales/fr/editor.json +9 -2
- package/locales/ja/editor.json +8 -1
- package/package.json +1 -1
- package/public/red/about +40 -0
- package/public/red/red.js +893 -369
- package/public/red/red.min.js +3 -3
- package/public/red/style.min.css +2 -2
- package/public/red/tours/images/nr4-background-deploy.png +0 -0
- package/public/red/tours/images/nr4-diff-update.png +0 -0
- package/public/red/tours/images/nr4-multiplayer-location.png +0 -0
- package/public/red/tours/welcome.js +87 -26
- package/public/types/node-red/util.d.ts +1 -1
package/public/red/red.js
CHANGED
|
@@ -389,6 +389,7 @@ var RED = (function() {
|
|
|
389
389
|
RED.workspaces.show(workspaces[0]);
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
|
+
RED.events.emit('flows:loaded')
|
|
392
393
|
} catch(err) {
|
|
393
394
|
console.warn(err);
|
|
394
395
|
RED.notify(
|
|
@@ -1877,6 +1878,8 @@ RED.user = (function() {
|
|
|
1877
1878
|
|
|
1878
1879
|
function updateUserMenu() {
|
|
1879
1880
|
$("#red-ui-header-button-user-submenu li").remove();
|
|
1881
|
+
const userMenu = $("#red-ui-header-button-user")
|
|
1882
|
+
userMenu.empty()
|
|
1880
1883
|
if (RED.settings.user.anonymous) {
|
|
1881
1884
|
RED.menu.addItem("red-ui-header-button-user",{
|
|
1882
1885
|
id:"usermenu-item-login",
|
|
@@ -1891,7 +1894,6 @@ RED.user = (function() {
|
|
|
1891
1894
|
});
|
|
1892
1895
|
}
|
|
1893
1896
|
});
|
|
1894
|
-
$('<i class="fa fa-user"></i>').appendTo("#red-ui-header-button-user");
|
|
1895
1897
|
} else {
|
|
1896
1898
|
RED.menu.addItem("red-ui-header-button-user",{
|
|
1897
1899
|
id:"usermenu-item-username",
|
|
@@ -1904,17 +1906,9 @@ RED.user = (function() {
|
|
|
1904
1906
|
RED.user.logout();
|
|
1905
1907
|
}
|
|
1906
1908
|
});
|
|
1907
|
-
const userMenu = $("#red-ui-header-button-user")
|
|
1908
|
-
userMenu.empty()
|
|
1909
|
-
if (RED.settings.user.image) {
|
|
1910
|
-
$('<span class="user-profile"></span>').css({
|
|
1911
|
-
backgroundImage: "url("+RED.settings.user.image+")",
|
|
1912
|
-
}).appendTo(userMenu);
|
|
1913
|
-
} else {
|
|
1914
|
-
$('<i class="fa fa-user"></i>').appendTo(userMenu);
|
|
1915
|
-
}
|
|
1916
1909
|
}
|
|
1917
|
-
|
|
1910
|
+
const userIcon = generateUserIcon(RED.settings.user)
|
|
1911
|
+
userIcon.appendTo(userMenu);
|
|
1918
1912
|
}
|
|
1919
1913
|
|
|
1920
1914
|
function init() {
|
|
@@ -1985,12 +1979,30 @@ RED.user = (function() {
|
|
|
1985
1979
|
return false;
|
|
1986
1980
|
}
|
|
1987
1981
|
|
|
1982
|
+
function generateUserIcon(user) {
|
|
1983
|
+
const userIcon = $('<span class="red-ui-user-profile"></span>')
|
|
1984
|
+
if (user.image) {
|
|
1985
|
+
userIcon.addClass('has_profile_image')
|
|
1986
|
+
userIcon.css({
|
|
1987
|
+
backgroundImage: "url("+user.image+")",
|
|
1988
|
+
})
|
|
1989
|
+
} else if (user.anonymous) {
|
|
1990
|
+
$('<i class="fa fa-user"></i>').appendTo(userIcon);
|
|
1991
|
+
} else {
|
|
1992
|
+
$('<span>').text(user.username.substring(0,2)).appendTo(userIcon);
|
|
1993
|
+
}
|
|
1994
|
+
if (user.profileColor !== undefined) {
|
|
1995
|
+
userIcon.addClass('red-ui-user-profile-color-' + user.profileColor)
|
|
1996
|
+
}
|
|
1997
|
+
return userIcon
|
|
1998
|
+
}
|
|
1988
1999
|
|
|
1989
2000
|
return {
|
|
1990
2001
|
init: init,
|
|
1991
2002
|
login: login,
|
|
1992
2003
|
logout: logout,
|
|
1993
|
-
hasPermission: hasPermission
|
|
2004
|
+
hasPermission: hasPermission,
|
|
2005
|
+
generateUserIcon
|
|
1994
2006
|
}
|
|
1995
2007
|
|
|
1996
2008
|
})();
|
|
@@ -2274,115 +2286,93 @@ RED.comms = (function() {
|
|
|
2274
2286
|
})()
|
|
2275
2287
|
;RED.multiplayer = (function () {
|
|
2276
2288
|
|
|
2277
|
-
//
|
|
2278
|
-
let
|
|
2289
|
+
// activeSessionId - used to identify sessions across websocket reconnects
|
|
2290
|
+
let activeSessionId
|
|
2279
2291
|
|
|
2280
2292
|
let headerWidget
|
|
2281
2293
|
// Map of session id to { session:'', user:{}, location:{}}
|
|
2282
|
-
let
|
|
2283
|
-
// Map of username to { user:{},
|
|
2294
|
+
let sessions = {}
|
|
2295
|
+
// Map of username to { user:{}, sessions:[] }
|
|
2284
2296
|
let users = {}
|
|
2285
2297
|
|
|
2286
|
-
function
|
|
2287
|
-
if (
|
|
2298
|
+
function addUserSession (session) {
|
|
2299
|
+
if (sessions[session.session]) {
|
|
2288
2300
|
// This is an existing connection that has been authenticated
|
|
2289
|
-
const
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2301
|
+
const existingSession = sessions[session.session]
|
|
2302
|
+
if (existingSession.user.username !== session.user.username) {
|
|
2303
|
+
removeUserHeaderButton(users[existingSession.user.username])
|
|
2292
2304
|
}
|
|
2293
2305
|
}
|
|
2294
|
-
|
|
2295
|
-
const user = users[
|
|
2296
|
-
user:
|
|
2297
|
-
|
|
2306
|
+
sessions[session.session] = session
|
|
2307
|
+
const user = users[session.user.username] = users[session.user.username] || {
|
|
2308
|
+
user: session.user,
|
|
2309
|
+
sessions: []
|
|
2310
|
+
}
|
|
2311
|
+
if (session.user.profileColor === undefined) {
|
|
2312
|
+
session.user.profileColor = (1 + Math.floor(Math.random() * 5))
|
|
2298
2313
|
}
|
|
2299
|
-
|
|
2300
|
-
user.
|
|
2314
|
+
session.location = session.location || {}
|
|
2315
|
+
user.sessions.push(session)
|
|
2301
2316
|
|
|
2302
|
-
if (
|
|
2303
|
-
|
|
2304
|
-
) {
|
|
2305
|
-
// This is the current user - do not add a extra button for them
|
|
2317
|
+
if (session.session === activeSessionId) {
|
|
2318
|
+
// This is the current user session - do not add a extra button for them
|
|
2306
2319
|
} else {
|
|
2307
|
-
if (user.
|
|
2320
|
+
if (user.sessions.length === 1) {
|
|
2308
2321
|
if (user.button) {
|
|
2309
2322
|
clearTimeout(user.inactiveTimeout)
|
|
2310
2323
|
clearTimeout(user.removeTimeout)
|
|
2311
2324
|
user.button.removeClass('inactive')
|
|
2312
2325
|
} else {
|
|
2313
|
-
|
|
2326
|
+
addUserHeaderButton(user)
|
|
2314
2327
|
}
|
|
2315
2328
|
}
|
|
2329
|
+
sessions[session.session].location = session.location
|
|
2330
|
+
updateUserLocation(session.session)
|
|
2316
2331
|
}
|
|
2317
2332
|
}
|
|
2318
2333
|
|
|
2319
|
-
function
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
const
|
|
2324
|
-
user.
|
|
2334
|
+
function removeUserSession (sessionId, isDisconnected) {
|
|
2335
|
+
removeUserLocation(sessionId)
|
|
2336
|
+
const session = sessions[sessionId]
|
|
2337
|
+
delete sessions[sessionId]
|
|
2338
|
+
const user = users[session.user.username]
|
|
2339
|
+
const i = user.sessions.indexOf(session)
|
|
2340
|
+
user.sessions.splice(i, 1)
|
|
2325
2341
|
if (isDisconnected) {
|
|
2326
|
-
|
|
2342
|
+
removeUserHeaderButton(user)
|
|
2327
2343
|
} else {
|
|
2328
|
-
if (user.
|
|
2344
|
+
if (user.sessions.length === 0) {
|
|
2329
2345
|
// Give the user 5s to reconnect before marking inactive
|
|
2330
2346
|
user.inactiveTimeout = setTimeout(() => {
|
|
2331
2347
|
user.button.addClass('inactive')
|
|
2332
2348
|
// Give the user further 20 seconds to reconnect before removing them
|
|
2333
2349
|
// from the user toolbar entirely
|
|
2334
2350
|
user.removeTimeout = setTimeout(() => {
|
|
2335
|
-
|
|
2351
|
+
removeUserHeaderButton(user)
|
|
2336
2352
|
}, 20000)
|
|
2337
2353
|
}, 5000)
|
|
2338
2354
|
}
|
|
2339
2355
|
}
|
|
2340
2356
|
}
|
|
2341
2357
|
|
|
2342
|
-
function
|
|
2343
|
-
user.button = $('<li class="red-ui-multiplayer-user"><button type="button" class="red-ui-multiplayer-user-icon"
|
|
2358
|
+
function addUserHeaderButton (user) {
|
|
2359
|
+
user.button = $('<li class="red-ui-multiplayer-user"><button type="button" class="red-ui-multiplayer-user-icon"></button></li>')
|
|
2344
2360
|
.attr('data-username', user.user.username)
|
|
2345
2361
|
.prependTo("#red-ui-multiplayer-user-list");
|
|
2346
2362
|
var button = user.button.find("button")
|
|
2363
|
+
RED.popover.tooltip(button, user.user.username)
|
|
2347
2364
|
button.on('click', function () {
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
trigger: 'modal',
|
|
2351
|
-
interactive: true,
|
|
2352
|
-
width: "250px",
|
|
2353
|
-
direction: 'bottom',
|
|
2354
|
-
content: () => {
|
|
2355
|
-
const content = $('<div>')
|
|
2356
|
-
$('<div style="text-align: center">').text(user.user.username).appendTo(content)
|
|
2357
|
-
|
|
2358
|
-
const location = user.connections[0].location
|
|
2359
|
-
if (location.workspace) {
|
|
2360
|
-
const ws = RED.nodes.workspace(location.workspace) || RED.nodes.subflow(location.workspace)
|
|
2361
|
-
if (ws) {
|
|
2362
|
-
$('<div>').text(`${ws.type}: ${ws.label||ws.name||ws.id}`).appendTo(content)
|
|
2363
|
-
} else {
|
|
2364
|
-
$('<div>').text(`tab: unknown`).appendTo(content)
|
|
2365
|
-
}
|
|
2366
|
-
}
|
|
2367
|
-
if (location.node) {
|
|
2368
|
-
const node = RED.nodes.node(location.node)
|
|
2369
|
-
if (node) {
|
|
2370
|
-
$('<div>').text(`node: ${node.id}`).appendTo(content)
|
|
2371
|
-
} else {
|
|
2372
|
-
$('<div>').text(`node: unknown`).appendTo(content)
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
return content
|
|
2376
|
-
},
|
|
2377
|
-
}).open()
|
|
2365
|
+
const location = user.sessions[0].location
|
|
2366
|
+
revealUser(location)
|
|
2378
2367
|
})
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2368
|
+
|
|
2369
|
+
const userProfile = RED.user.generateUserIcon(user.user)
|
|
2370
|
+
userProfile.appendTo(button)
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
function removeUserHeaderButton (user) {
|
|
2374
|
+
user.button.remove()
|
|
2375
|
+
delete user.button
|
|
2386
2376
|
}
|
|
2387
2377
|
|
|
2388
2378
|
function getLocation () {
|
|
@@ -2398,7 +2388,7 @@ RED.comms = (function() {
|
|
|
2398
2388
|
}
|
|
2399
2389
|
return location
|
|
2400
2390
|
}
|
|
2401
|
-
function
|
|
2391
|
+
function publishLocation () {
|
|
2402
2392
|
const location = getLocation()
|
|
2403
2393
|
if (location.workspace !== 0) {
|
|
2404
2394
|
log('send', 'multiplayer/location', location)
|
|
@@ -2406,31 +2396,314 @@ RED.comms = (function() {
|
|
|
2406
2396
|
}
|
|
2407
2397
|
}
|
|
2408
2398
|
|
|
2409
|
-
function
|
|
2410
|
-
|
|
2411
|
-
|
|
2399
|
+
function revealUser(location, skipWorkspace) {
|
|
2400
|
+
if (location.node) {
|
|
2401
|
+
// Need to check if this is a known node, so we can fall back to revealing
|
|
2402
|
+
// the workspace instead
|
|
2403
|
+
const node = RED.nodes.node(location.node)
|
|
2404
|
+
if (node) {
|
|
2405
|
+
RED.view.reveal(location.node)
|
|
2406
|
+
} else if (!skipWorkspace && location.workspace) {
|
|
2407
|
+
RED.view.reveal(location.workspace)
|
|
2408
|
+
}
|
|
2409
|
+
} else if (!skipWorkspace && location.workspace) {
|
|
2410
|
+
RED.view.reveal(location.workspace)
|
|
2411
|
+
}
|
|
2412
2412
|
}
|
|
2413
2413
|
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2414
|
+
const workspaceTrays = {}
|
|
2415
|
+
function getWorkspaceTray(workspaceId) {
|
|
2416
|
+
// console.log('get tray for',workspaceId)
|
|
2417
|
+
if (!workspaceTrays[workspaceId]) {
|
|
2418
|
+
const tray = $('<div class="red-ui-multiplayer-users-tray"></div>')
|
|
2419
|
+
const users = []
|
|
2420
|
+
const userIcons = {}
|
|
2421
|
+
|
|
2422
|
+
const userCountIcon = $(`<div class="red-ui-multiplayer-user-location"><span class="red-ui-user-profile red-ui-multiplayer-user-count"><span></span></span></div>`)
|
|
2423
|
+
const userCountSpan = userCountIcon.find('span span')
|
|
2424
|
+
userCountIcon.hide()
|
|
2425
|
+
userCountSpan.text('')
|
|
2426
|
+
userCountIcon.appendTo(tray)
|
|
2427
|
+
const userCountTooltip = RED.popover.tooltip(userCountIcon, function () {
|
|
2428
|
+
const content = $('<div>')
|
|
2429
|
+
users.forEach(sessionId => {
|
|
2430
|
+
$('<div>').append($('<a href="#">').text(sessions[sessionId].user.username).on('click', function (evt) {
|
|
2431
|
+
evt.preventDefault()
|
|
2432
|
+
revealUser(sessions[sessionId].location, true)
|
|
2433
|
+
userCountTooltip.close()
|
|
2434
|
+
})).appendTo(content)
|
|
2435
|
+
})
|
|
2436
|
+
return content
|
|
2437
|
+
},
|
|
2438
|
+
null,
|
|
2439
|
+
true
|
|
2440
|
+
)
|
|
2441
|
+
|
|
2442
|
+
const updateUserCount = function () {
|
|
2443
|
+
const maxShown = 2
|
|
2444
|
+
const children = tray.children()
|
|
2445
|
+
children.each(function (index, element) {
|
|
2446
|
+
const i = users.length - index
|
|
2447
|
+
if (i > maxShown) {
|
|
2448
|
+
$(this).hide()
|
|
2449
|
+
} else if (i >= 0) {
|
|
2450
|
+
$(this).show()
|
|
2451
|
+
}
|
|
2452
|
+
})
|
|
2453
|
+
if (users.length < maxShown + 1) {
|
|
2454
|
+
userCountIcon.hide()
|
|
2455
|
+
} else {
|
|
2456
|
+
userCountSpan.text('+'+(users.length - maxShown))
|
|
2457
|
+
userCountIcon.show()
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
workspaceTrays[workspaceId] = {
|
|
2461
|
+
attached: false,
|
|
2462
|
+
tray,
|
|
2463
|
+
users,
|
|
2464
|
+
userIcons,
|
|
2465
|
+
addUser: function (sessionId) {
|
|
2466
|
+
if (users.indexOf(sessionId) === -1) {
|
|
2467
|
+
// console.log(`addUser ws:${workspaceId} session:${sessionId}`)
|
|
2468
|
+
users.push(sessionId)
|
|
2469
|
+
const userLocationId = `red-ui-multiplayer-user-location-${sessionId}`
|
|
2470
|
+
const userLocationIcon = $(`<div class="red-ui-multiplayer-user-location" id="${userLocationId}"></div>`)
|
|
2471
|
+
RED.user.generateUserIcon(sessions[sessionId].user).appendTo(userLocationIcon)
|
|
2472
|
+
userLocationIcon.prependTo(tray)
|
|
2473
|
+
RED.popover.tooltip(userLocationIcon, sessions[sessionId].user.username)
|
|
2474
|
+
userIcons[sessionId] = userLocationIcon
|
|
2475
|
+
updateUserCount()
|
|
2476
|
+
}
|
|
2477
|
+
},
|
|
2478
|
+
removeUser: function (sessionId) {
|
|
2479
|
+
// console.log(`removeUser ws:${workspaceId} session:${sessionId}`)
|
|
2480
|
+
const userLocationId = `red-ui-multiplayer-user-location-${sessionId}`
|
|
2481
|
+
const index = users.indexOf(sessionId)
|
|
2482
|
+
if (index > -1) {
|
|
2483
|
+
users.splice(index, 1)
|
|
2484
|
+
userIcons[sessionId].remove()
|
|
2485
|
+
delete userIcons[sessionId]
|
|
2486
|
+
}
|
|
2487
|
+
updateUserCount()
|
|
2488
|
+
},
|
|
2489
|
+
updateUserCount
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
const trayDef = workspaceTrays[workspaceId]
|
|
2493
|
+
if (!trayDef.attached) {
|
|
2494
|
+
const workspaceTab = $(`#red-ui-tab-${workspaceId}`)
|
|
2495
|
+
if (workspaceTab.length > 0) {
|
|
2496
|
+
trayDef.attached = true
|
|
2497
|
+
trayDef.tray.appendTo(workspaceTab)
|
|
2498
|
+
trayDef.users.forEach(sessionId => {
|
|
2499
|
+
trayDef.userIcons[sessionId].on('click', function (evt) {
|
|
2500
|
+
revealUser(sessions[sessionId].location, true)
|
|
2501
|
+
})
|
|
2502
|
+
})
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
return workspaceTrays[workspaceId]
|
|
2506
|
+
}
|
|
2507
|
+
function attachWorkspaceTrays () {
|
|
2508
|
+
let viewTouched = false
|
|
2509
|
+
for (let sessionId of Object.keys(sessions)) {
|
|
2510
|
+
const location = sessions[sessionId].location
|
|
2511
|
+
if (location) {
|
|
2512
|
+
if (location.workspace) {
|
|
2513
|
+
getWorkspaceTray(location.workspace).updateUserCount()
|
|
2514
|
+
}
|
|
2515
|
+
if (location.node) {
|
|
2516
|
+
addUserToNode(sessionId, location.node)
|
|
2517
|
+
viewTouched = true
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
if (viewTouched) {
|
|
2522
|
+
RED.view.redraw()
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
function addUserToNode(sessionId, nodeId) {
|
|
2527
|
+
const node = RED.nodes.node(nodeId)
|
|
2528
|
+
if (node) {
|
|
2529
|
+
if (!node._multiplayer) {
|
|
2530
|
+
node._multiplayer = {
|
|
2531
|
+
users: [sessionId]
|
|
2532
|
+
}
|
|
2533
|
+
node._multiplayer_refresh = true
|
|
2534
|
+
} else {
|
|
2535
|
+
if (node._multiplayer.users.indexOf(sessionId) === -1) {
|
|
2536
|
+
node._multiplayer.users.push(sessionId)
|
|
2537
|
+
node._multiplayer_refresh = true
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
function removeUserFromNode(sessionId, nodeId) {
|
|
2543
|
+
const node = RED.nodes.node(nodeId)
|
|
2544
|
+
if (node && node._multiplayer) {
|
|
2545
|
+
const i = node._multiplayer.users.indexOf(sessionId)
|
|
2546
|
+
if (i > -1) {
|
|
2547
|
+
node._multiplayer.users.splice(i, 1)
|
|
2548
|
+
}
|
|
2549
|
+
if (node._multiplayer.users.length === 0) {
|
|
2550
|
+
delete node._multiplayer
|
|
2551
|
+
} else {
|
|
2552
|
+
node._multiplayer_refresh = true
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
function removeUserLocation (sessionId) {
|
|
2559
|
+
updateUserLocation(sessionId, {})
|
|
2560
|
+
}
|
|
2561
|
+
function updateUserLocation (sessionId, location) {
|
|
2562
|
+
let viewTouched = false
|
|
2563
|
+
const oldLocation = sessions[sessionId].location
|
|
2564
|
+
if (location) {
|
|
2565
|
+
if (oldLocation.workspace !== location.workspace) {
|
|
2566
|
+
// console.log('removing', sessionId, oldLocation.workspace)
|
|
2567
|
+
workspaceTrays[oldLocation.workspace]?.removeUser(sessionId)
|
|
2568
|
+
}
|
|
2569
|
+
if (oldLocation.node !== location.node) {
|
|
2570
|
+
removeUserFromNode(sessionId, oldLocation.node)
|
|
2571
|
+
viewTouched = true
|
|
2572
|
+
}
|
|
2573
|
+
sessions[sessionId].location = location
|
|
2574
|
+
} else {
|
|
2575
|
+
location = sessions[sessionId].location
|
|
2576
|
+
}
|
|
2577
|
+
// console.log(`updateUserLocation sessionId:${sessionId} oldWS:${oldLocation?.workspace} newWS:${location.workspace}`)
|
|
2578
|
+
if (location.workspace) {
|
|
2579
|
+
getWorkspaceTray(location.workspace).addUser(sessionId)
|
|
2580
|
+
}
|
|
2581
|
+
if (location.node) {
|
|
2582
|
+
addUserToNode(sessionId, location.node)
|
|
2583
|
+
viewTouched = true
|
|
2584
|
+
}
|
|
2585
|
+
if (viewTouched) {
|
|
2586
|
+
RED.view.redraw()
|
|
2587
|
+
}
|
|
2417
2588
|
}
|
|
2589
|
+
|
|
2590
|
+
// function refreshUserLocations () {
|
|
2591
|
+
// for (const session of Object.keys(sessions)) {
|
|
2592
|
+
// if (session !== activeSessionId) {
|
|
2593
|
+
// updateUserLocation(session)
|
|
2594
|
+
// }
|
|
2595
|
+
// }
|
|
2596
|
+
// }
|
|
2597
|
+
|
|
2418
2598
|
return {
|
|
2419
2599
|
init: function () {
|
|
2420
|
-
|
|
2421
2600
|
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2601
|
+
function createAnnotationUser(user) {
|
|
2602
|
+
|
|
2603
|
+
const group = document.createElementNS("http://www.w3.org/2000/svg","g");
|
|
2604
|
+
const badge = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
|
2605
|
+
const radius = 20
|
|
2606
|
+
badge.setAttribute("cx",radius/2);
|
|
2607
|
+
badge.setAttribute("cy",radius/2);
|
|
2608
|
+
badge.setAttribute("r",radius/2);
|
|
2609
|
+
badge.setAttribute("class", "red-ui-multiplayer-annotation-background")
|
|
2610
|
+
group.appendChild(badge)
|
|
2611
|
+
if (user && user.profileColor !== undefined) {
|
|
2612
|
+
badge.setAttribute("class", "red-ui-multiplayer-annotation-background red-ui-user-profile-color-" + user.profileColor)
|
|
2613
|
+
}
|
|
2614
|
+
if (user && user.image) {
|
|
2615
|
+
const image = document.createElementNS("http://www.w3.org/2000/svg","image");
|
|
2616
|
+
image.setAttribute("width", radius)
|
|
2617
|
+
image.setAttribute("height", radius)
|
|
2618
|
+
image.setAttribute("href", user.image)
|
|
2619
|
+
image.setAttribute("clip-path", "circle("+Math.floor(radius/2)+")")
|
|
2620
|
+
group.appendChild(image)
|
|
2621
|
+
} else if (user && user.anonymous) {
|
|
2622
|
+
const anonIconHead = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
|
2623
|
+
anonIconHead.setAttribute("cx", radius/2)
|
|
2624
|
+
anonIconHead.setAttribute("cy", radius/2 - 2)
|
|
2625
|
+
anonIconHead.setAttribute("r", 2.4)
|
|
2626
|
+
anonIconHead.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
|
2627
|
+
group.appendChild(anonIconHead)
|
|
2628
|
+
const anonIconBody = document.createElementNS("http://www.w3.org/2000/svg","path");
|
|
2629
|
+
anonIconBody.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
|
|
2630
|
+
// anonIconBody.setAttribute("d",`M ${radius/2 - 4} ${radius/2 + 1} h 8 v4 h -8 z`);
|
|
2631
|
+
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
|
2632
|
+
group.appendChild(anonIconBody)
|
|
2633
|
+
} else {
|
|
2634
|
+
const labelText = user.username ? user.username.substring(0,2) : user
|
|
2635
|
+
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
|
2636
|
+
if (user.username) {
|
|
2637
|
+
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
|
2638
|
+
label.textContent = user.username.substring(0,2)
|
|
2639
|
+
} else {
|
|
2640
|
+
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
|
2641
|
+
label.textContent = user
|
|
2642
|
+
}
|
|
2643
|
+
label.setAttribute("text-anchor", "middle")
|
|
2644
|
+
label.setAttribute("x",radius/2);
|
|
2645
|
+
label.setAttribute("y",radius/2 + 3);
|
|
2646
|
+
group.appendChild(label)
|
|
2647
|
+
}
|
|
2648
|
+
const border = document.createElementNS("http://www.w3.org/2000/svg","circle");
|
|
2649
|
+
border.setAttribute("cx",radius/2);
|
|
2650
|
+
border.setAttribute("cy",radius/2);
|
|
2651
|
+
border.setAttribute("r",radius/2);
|
|
2652
|
+
border.setAttribute("class", "red-ui-multiplayer-annotation-border")
|
|
2653
|
+
group.appendChild(border)
|
|
2654
|
+
|
|
2655
|
+
|
|
2656
|
+
|
|
2657
|
+
return group
|
|
2426
2658
|
}
|
|
2427
2659
|
|
|
2660
|
+
RED.view.annotations.register("red-ui-multiplayer",{
|
|
2661
|
+
type: 'badge',
|
|
2662
|
+
align: 'left',
|
|
2663
|
+
class: "red-ui-multiplayer-annotation",
|
|
2664
|
+
show: "_multiplayer",
|
|
2665
|
+
refresh: "_multiplayer_refresh",
|
|
2666
|
+
element: function(node) {
|
|
2667
|
+
const containerGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
|
|
2668
|
+
containerGroup.setAttribute("transform","translate(0,-4)")
|
|
2669
|
+
if (node._multiplayer) {
|
|
2670
|
+
let y = 0
|
|
2671
|
+
for (let i = Math.min(1, node._multiplayer.users.length - 1); i >= 0; i--) {
|
|
2672
|
+
const user = sessions[node._multiplayer.users[i]].user
|
|
2673
|
+
const group = createAnnotationUser(user)
|
|
2674
|
+
group.setAttribute("transform","translate("+y+",0)")
|
|
2675
|
+
y += 15
|
|
2676
|
+
containerGroup.appendChild(group)
|
|
2677
|
+
}
|
|
2678
|
+
if (node._multiplayer.users.length > 2) {
|
|
2679
|
+
const group = createAnnotationUser('+'+(node._multiplayer.users.length - 2))
|
|
2680
|
+
group.setAttribute("transform","translate("+y+",0)")
|
|
2681
|
+
y += 12
|
|
2682
|
+
containerGroup.appendChild(group)
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
}
|
|
2686
|
+
return containerGroup;
|
|
2687
|
+
},
|
|
2688
|
+
tooltip: node => { return node._multiplayer.users.map(u => sessions[u].user.username).join('\n') }
|
|
2689
|
+
});
|
|
2690
|
+
|
|
2691
|
+
|
|
2692
|
+
// activeSessionId = RED.settings.getLocal('multiplayer:sessionId')
|
|
2693
|
+
// if (!activeSessionId) {
|
|
2694
|
+
activeSessionId = RED.nodes.id()
|
|
2695
|
+
// RED.settings.setLocal('multiplayer:sessionId', activeSessionId)
|
|
2696
|
+
// log('Session ID (new)', activeSessionId)
|
|
2697
|
+
// } else {
|
|
2698
|
+
log('Session ID', activeSessionId)
|
|
2699
|
+
// }
|
|
2700
|
+
|
|
2428
2701
|
headerWidget = $('<li><ul id="red-ui-multiplayer-user-list"></ul></li>').prependTo('.red-ui-header-toolbar')
|
|
2429
2702
|
|
|
2430
2703
|
RED.comms.on('connect', () => {
|
|
2431
2704
|
const location = getLocation()
|
|
2432
2705
|
const connectInfo = {
|
|
2433
|
-
session:
|
|
2706
|
+
session: activeSessionId
|
|
2434
2707
|
}
|
|
2435
2708
|
if (location.workspace !== 0) {
|
|
2436
2709
|
connectInfo.location = location
|
|
@@ -2442,40 +2715,52 @@ RED.comms = (function() {
|
|
|
2442
2715
|
if (topic === 'multiplayer/init') {
|
|
2443
2716
|
// We have just reconnected, runtime has sent state to
|
|
2444
2717
|
// initialise the world
|
|
2445
|
-
|
|
2718
|
+
sessions = {}
|
|
2446
2719
|
users = {}
|
|
2447
2720
|
$('#red-ui-multiplayer-user-list').empty()
|
|
2448
2721
|
|
|
2449
|
-
msg.forEach(
|
|
2450
|
-
|
|
2722
|
+
msg.sessions.forEach(session => {
|
|
2723
|
+
addUserSession(session)
|
|
2451
2724
|
})
|
|
2452
2725
|
} else if (topic === 'multiplayer/connection-added') {
|
|
2453
|
-
|
|
2726
|
+
addUserSession(msg)
|
|
2454
2727
|
} else if (topic === 'multiplayer/connection-removed') {
|
|
2455
|
-
|
|
2728
|
+
removeUserSession(msg.session, msg.disconnected)
|
|
2456
2729
|
} else if (topic === 'multiplayer/location') {
|
|
2457
|
-
|
|
2730
|
+
const session = msg.session
|
|
2731
|
+
delete msg.session
|
|
2732
|
+
updateUserLocation(session, msg)
|
|
2458
2733
|
}
|
|
2459
2734
|
})
|
|
2460
2735
|
|
|
2461
2736
|
RED.events.on('workspace:change', (event) => {
|
|
2462
|
-
|
|
2737
|
+
getWorkspaceTray(event.workspace)
|
|
2738
|
+
publishLocation()
|
|
2463
2739
|
})
|
|
2464
2740
|
RED.events.on('editor:open', () => {
|
|
2465
|
-
|
|
2741
|
+
publishLocation()
|
|
2466
2742
|
})
|
|
2467
2743
|
RED.events.on('editor:close', () => {
|
|
2468
|
-
|
|
2744
|
+
publishLocation()
|
|
2469
2745
|
})
|
|
2470
2746
|
RED.events.on('editor:change', () => {
|
|
2471
|
-
|
|
2747
|
+
publishLocation()
|
|
2472
2748
|
})
|
|
2473
2749
|
RED.events.on('login', () => {
|
|
2474
|
-
|
|
2750
|
+
publishLocation()
|
|
2751
|
+
})
|
|
2752
|
+
RED.events.on('flows:loaded', () => {
|
|
2753
|
+
attachWorkspaceTrays()
|
|
2754
|
+
})
|
|
2755
|
+
RED.events.on('workspace:close', (event) => {
|
|
2756
|
+
// A subflow tab has been closed. Need to mark its tray as detached
|
|
2757
|
+
if (workspaceTrays[event.workspace]) {
|
|
2758
|
+
workspaceTrays[event.workspace].attached = false
|
|
2759
|
+
}
|
|
2475
2760
|
})
|
|
2476
2761
|
RED.events.on('logout', () => {
|
|
2477
2762
|
const disconnectInfo = {
|
|
2478
|
-
session:
|
|
2763
|
+
session: activeSessionId
|
|
2479
2764
|
}
|
|
2480
2765
|
RED.comms.send('multiplayer/disconnect', disconnectInfo)
|
|
2481
2766
|
RED.settings.removeLocal('multiplayer:sessionId')
|
|
@@ -8086,7 +8371,14 @@ RED.history = (function() {
|
|
|
8086
8371
|
}
|
|
8087
8372
|
return RED.nodes.junction(id);
|
|
8088
8373
|
}
|
|
8089
|
-
|
|
8374
|
+
function ensureUnlocked(id, flowsToLock) {
|
|
8375
|
+
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
|
|
8376
|
+
const isLocked = flow ? flow.locked : false;
|
|
8377
|
+
if (flow && isLocked) {
|
|
8378
|
+
flow.locked = false;
|
|
8379
|
+
flowsToLock.add(flow)
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8090
8382
|
function undoEvent(ev) {
|
|
8091
8383
|
var i;
|
|
8092
8384
|
var len;
|
|
@@ -8116,18 +8408,46 @@ RED.history = (function() {
|
|
|
8116
8408
|
t: 'replace',
|
|
8117
8409
|
config: RED.nodes.createCompleteNodeSet(),
|
|
8118
8410
|
changed: {},
|
|
8119
|
-
|
|
8411
|
+
moved: {},
|
|
8412
|
+
complete: true,
|
|
8413
|
+
rev: RED.nodes.version(),
|
|
8414
|
+
dirty: RED.nodes.dirty()
|
|
8120
8415
|
};
|
|
8416
|
+
var selectedTab = RED.workspaces.active();
|
|
8417
|
+
inverseEv.config.forEach(n => {
|
|
8418
|
+
const node = RED.nodes.node(n.id)
|
|
8419
|
+
if (node) {
|
|
8420
|
+
inverseEv.changed[n.id] = node.changed
|
|
8421
|
+
inverseEv.moved[n.id] = node.moved
|
|
8422
|
+
}
|
|
8423
|
+
})
|
|
8121
8424
|
RED.nodes.clear();
|
|
8122
8425
|
var imported = RED.nodes.import(ev.config);
|
|
8426
|
+
// Clear all change flags from the import
|
|
8427
|
+
RED.nodes.dirty(false);
|
|
8428
|
+
|
|
8429
|
+
const flowsToLock = new Set()
|
|
8430
|
+
|
|
8123
8431
|
imported.nodes.forEach(function(n) {
|
|
8124
8432
|
if (ev.changed[n.id]) {
|
|
8433
|
+
ensureUnlocked(n.z, flowsToLock)
|
|
8125
8434
|
n.changed = true;
|
|
8126
|
-
|
|
8435
|
+
}
|
|
8436
|
+
if (ev.moved[n.id]) {
|
|
8437
|
+
ensureUnlocked(n.z, flowsToLock)
|
|
8438
|
+
n.moved = true;
|
|
8127
8439
|
}
|
|
8128
8440
|
})
|
|
8441
|
+
flowsToLock.forEach(flow => {
|
|
8442
|
+
flow.locked = true
|
|
8443
|
+
})
|
|
8129
8444
|
|
|
8130
8445
|
RED.nodes.version(ev.rev);
|
|
8446
|
+
RED.view.redraw(true);
|
|
8447
|
+
RED.palette.refresh();
|
|
8448
|
+
RED.workspaces.refresh();
|
|
8449
|
+
RED.workspaces.show(selectedTab, true);
|
|
8450
|
+
RED.sidebar.config.refresh();
|
|
8131
8451
|
} else {
|
|
8132
8452
|
var importMap = {};
|
|
8133
8453
|
ev.config.forEach(function(n) {
|
|
@@ -12913,9 +13233,12 @@ RED.popover = (function() {
|
|
|
12913
13233
|
|
|
12914
13234
|
return {
|
|
12915
13235
|
create: createPopover,
|
|
12916
|
-
tooltip: function(target,content, action) {
|
|
13236
|
+
tooltip: function(target,content, action, interactive) {
|
|
12917
13237
|
var label = function() {
|
|
12918
13238
|
var label = content;
|
|
13239
|
+
if (typeof content === 'function') {
|
|
13240
|
+
label = content()
|
|
13241
|
+
}
|
|
12919
13242
|
if (action) {
|
|
12920
13243
|
var shortcut = RED.keyboard.getShortcut(action);
|
|
12921
13244
|
if (shortcut && shortcut.key) {
|
|
@@ -12931,6 +13254,7 @@ RED.popover = (function() {
|
|
|
12931
13254
|
size: "small",
|
|
12932
13255
|
direction: "bottom",
|
|
12933
13256
|
content: label,
|
|
13257
|
+
interactive,
|
|
12934
13258
|
delay: { show: 750, hide: 50 }
|
|
12935
13259
|
});
|
|
12936
13260
|
popover.setContent = function(newContent) {
|
|
@@ -13689,7 +14013,10 @@ RED.tabs = (function() {
|
|
|
13689
14013
|
|
|
13690
14014
|
var thisTabA = thisTab.find("a");
|
|
13691
14015
|
if (options.onclick) {
|
|
13692
|
-
options.onclick(tabs[thisTabA.attr('href').slice(1)]);
|
|
14016
|
+
options.onclick(tabs[thisTabA.attr('href').slice(1)], evt);
|
|
14017
|
+
if (evt.isDefaultPrevented() && evt.isPropagationStopped()) {
|
|
14018
|
+
return false
|
|
14019
|
+
}
|
|
13693
14020
|
}
|
|
13694
14021
|
activateTab(thisTabA);
|
|
13695
14022
|
if (fireSelectionChanged) {
|
|
@@ -13872,6 +14199,8 @@ RED.tabs = (function() {
|
|
|
13872
14199
|
ul.find("li.red-ui-tab a")
|
|
13873
14200
|
.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
|
|
13874
14201
|
.on("mouseup",onTabClick)
|
|
14202
|
+
// prevent browser-default middle-click behaviour
|
|
14203
|
+
.on("auxclick", function(evt) { evt.preventDefault() })
|
|
13875
14204
|
.on("click", function(evt) {evt.preventDefault(); })
|
|
13876
14205
|
.on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); })
|
|
13877
14206
|
|
|
@@ -14140,6 +14469,8 @@ RED.tabs = (function() {
|
|
|
14140
14469
|
}
|
|
14141
14470
|
link.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
|
|
14142
14471
|
link.on("mouseup",onTabClick);
|
|
14472
|
+
// prevent browser-default middle-click behaviour
|
|
14473
|
+
link.on("auxclick", function(evt) { evt.preventDefault() })
|
|
14143
14474
|
link.on("click", function(evt) { evt.preventDefault(); })
|
|
14144
14475
|
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
|
|
14145
14476
|
|
|
@@ -16507,6 +16838,8 @@ RED.deploy = (function() {
|
|
|
16507
16838
|
|
|
16508
16839
|
var currentDiff = null;
|
|
16509
16840
|
|
|
16841
|
+
var activeBackgroundDeployNotification;
|
|
16842
|
+
|
|
16510
16843
|
function changeDeploymentType(type) {
|
|
16511
16844
|
deploymentType = type;
|
|
16512
16845
|
$("#red-ui-header-button-deploy-icon").attr("src",deploymentTypes[type].img);
|
|
@@ -16585,51 +16918,59 @@ RED.deploy = (function() {
|
|
|
16585
16918
|
RED.actions.add("core:set-deploy-type-to-modified-nodes",function() { RED.menu.setSelected("deploymenu-item-node",true); });
|
|
16586
16919
|
}
|
|
16587
16920
|
|
|
16588
|
-
|
|
16921
|
+
window.addEventListener('beforeunload', function (event) {
|
|
16922
|
+
if (RED.nodes.dirty()) {
|
|
16923
|
+
event.preventDefault();
|
|
16924
|
+
event.stopImmediatePropagation()
|
|
16925
|
+
event.returnValue = RED._("deploy.confirm.undeployedChanges");
|
|
16926
|
+
return
|
|
16927
|
+
}
|
|
16928
|
+
})
|
|
16589
16929
|
|
|
16590
16930
|
RED.events.on('workspace:dirty',function(state) {
|
|
16591
16931
|
if (state.dirty) {
|
|
16592
|
-
window.onbeforeunload = function() {
|
|
16593
|
-
|
|
16594
|
-
}
|
|
16932
|
+
// window.onbeforeunload = function() {
|
|
16933
|
+
// return
|
|
16934
|
+
// }
|
|
16595
16935
|
$("#red-ui-header-button-deploy").removeClass("disabled");
|
|
16596
16936
|
} else {
|
|
16597
|
-
window.onbeforeunload = null;
|
|
16937
|
+
// window.onbeforeunload = null;
|
|
16598
16938
|
$("#red-ui-header-button-deploy").addClass("disabled");
|
|
16599
16939
|
}
|
|
16600
16940
|
});
|
|
16601
16941
|
|
|
16602
|
-
var activeNotifyMessage;
|
|
16603
16942
|
RED.comms.subscribe("notification/runtime-deploy",function(topic,msg) {
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16627
|
-
resolveConflict(nns,false);
|
|
16628
|
-
activeNotifyMessage = null;
|
|
16629
|
-
}
|
|
16943
|
+
var currentRev = RED.nodes.version();
|
|
16944
|
+
if (currentRev === null || deployInflight || currentRev === msg.revision) {
|
|
16945
|
+
return;
|
|
16946
|
+
}
|
|
16947
|
+
if (activeBackgroundDeployNotification?.hidden && !activeBackgroundDeployNotification?.closed) {
|
|
16948
|
+
activeBackgroundDeployNotification.showNotification()
|
|
16949
|
+
return
|
|
16950
|
+
}
|
|
16951
|
+
const message = $('<p>').text(RED._('deploy.confirm.backgroundUpdate'));
|
|
16952
|
+
const options = {
|
|
16953
|
+
id: 'background-update',
|
|
16954
|
+
type: 'compact',
|
|
16955
|
+
modal: false,
|
|
16956
|
+
fixed: true,
|
|
16957
|
+
timeout: 10000,
|
|
16958
|
+
buttons: [
|
|
16959
|
+
{
|
|
16960
|
+
text: RED._('deploy.confirm.button.review'),
|
|
16961
|
+
class: "primary",
|
|
16962
|
+
click: function() {
|
|
16963
|
+
activeBackgroundDeployNotification.hideNotification();
|
|
16964
|
+
var nns = RED.nodes.createCompleteNodeSet();
|
|
16965
|
+
resolveConflict(nns,false);
|
|
16630
16966
|
}
|
|
16631
|
-
|
|
16632
|
-
|
|
16967
|
+
}
|
|
16968
|
+
]
|
|
16969
|
+
}
|
|
16970
|
+
if (!activeBackgroundDeployNotification || activeBackgroundDeployNotification.closed) {
|
|
16971
|
+
activeBackgroundDeployNotification = RED.notify(message, options)
|
|
16972
|
+
} else {
|
|
16973
|
+
activeBackgroundDeployNotification.update(message, options)
|
|
16633
16974
|
}
|
|
16634
16975
|
});
|
|
16635
16976
|
}
|
|
@@ -16686,7 +17027,11 @@ RED.deploy = (function() {
|
|
|
16686
17027
|
class: "primary disabled",
|
|
16687
17028
|
click: function() {
|
|
16688
17029
|
if (!$("#red-ui-deploy-dialog-confirm-deploy-review").hasClass('disabled')) {
|
|
16689
|
-
RED.diff.showRemoteDiff(
|
|
17030
|
+
RED.diff.showRemoteDiff(null, {
|
|
17031
|
+
onmerge: function () {
|
|
17032
|
+
activeBackgroundDeployNotification.close()
|
|
17033
|
+
}
|
|
17034
|
+
});
|
|
16690
17035
|
conflictNotification.close();
|
|
16691
17036
|
}
|
|
16692
17037
|
}
|
|
@@ -16699,6 +17044,7 @@ RED.deploy = (function() {
|
|
|
16699
17044
|
if (!$("#red-ui-deploy-dialog-confirm-deploy-merge").hasClass('disabled')) {
|
|
16700
17045
|
RED.diff.mergeDiff(currentDiff);
|
|
16701
17046
|
conflictNotification.close();
|
|
17047
|
+
activeBackgroundDeployNotification.close()
|
|
16702
17048
|
}
|
|
16703
17049
|
}
|
|
16704
17050
|
}
|
|
@@ -16711,6 +17057,7 @@ RED.deploy = (function() {
|
|
|
16711
17057
|
click: function() {
|
|
16712
17058
|
save(true,activeDeploy);
|
|
16713
17059
|
conflictNotification.close();
|
|
17060
|
+
activeBackgroundDeployNotification.close()
|
|
16714
17061
|
}
|
|
16715
17062
|
})
|
|
16716
17063
|
}
|
|
@@ -16721,21 +17068,17 @@ RED.deploy = (function() {
|
|
|
16721
17068
|
buttons: buttons
|
|
16722
17069
|
});
|
|
16723
17070
|
|
|
16724
|
-
var now = Date.now();
|
|
16725
17071
|
RED.diff.getRemoteDiff(function(diff) {
|
|
16726
|
-
var ellapsed = Math.max(1000 - (Date.now()-now), 0);
|
|
16727
17072
|
currentDiff = diff;
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
$("#red-ui-deploy-dialog-confirm-deploy-review").removeClass('disabled')
|
|
16738
|
-
},ellapsed);
|
|
17073
|
+
conflictCheck.hide();
|
|
17074
|
+
var d = Object.keys(diff.conflicts);
|
|
17075
|
+
if (d.length === 0) {
|
|
17076
|
+
conflictAutoMerge.show();
|
|
17077
|
+
$("#red-ui-deploy-dialog-confirm-deploy-merge").removeClass('disabled')
|
|
17078
|
+
} else {
|
|
17079
|
+
conflictManualMerge.show();
|
|
17080
|
+
}
|
|
17081
|
+
$("#red-ui-deploy-dialog-confirm-deploy-review").removeClass('disabled')
|
|
16739
17082
|
})
|
|
16740
17083
|
}
|
|
16741
17084
|
function cropList(list) {
|
|
@@ -17085,7 +17428,10 @@ RED.deploy = (function() {
|
|
|
17085
17428
|
}
|
|
17086
17429
|
});
|
|
17087
17430
|
RED.nodes.eachSubflow(function (subflow) {
|
|
17088
|
-
subflow.changed
|
|
17431
|
+
if (subflow.changed) {
|
|
17432
|
+
subflow.changed = false;
|
|
17433
|
+
RED.events.emit("subflows:change", subflow);
|
|
17434
|
+
}
|
|
17089
17435
|
});
|
|
17090
17436
|
RED.nodes.eachWorkspace(function (ws) {
|
|
17091
17437
|
if (ws.changed || ws.added) {
|
|
@@ -17193,7 +17539,6 @@ RED.diagnostics = (function () {
|
|
|
17193
17539
|
};
|
|
17194
17540
|
})();
|
|
17195
17541
|
;RED.diff = (function() {
|
|
17196
|
-
|
|
17197
17542
|
var currentDiff = {};
|
|
17198
17543
|
var diffVisible = false;
|
|
17199
17544
|
var diffList;
|
|
@@ -17256,12 +17601,14 @@ RED.diagnostics = (function () {
|
|
|
17256
17601
|
addedCount:0,
|
|
17257
17602
|
deletedCount:0,
|
|
17258
17603
|
changedCount:0,
|
|
17604
|
+
movedCount:0,
|
|
17259
17605
|
unchangedCount: 0
|
|
17260
17606
|
},
|
|
17261
17607
|
remote: {
|
|
17262
17608
|
addedCount:0,
|
|
17263
17609
|
deletedCount:0,
|
|
17264
17610
|
changedCount:0,
|
|
17611
|
+
movedCount:0,
|
|
17265
17612
|
unchangedCount: 0
|
|
17266
17613
|
},
|
|
17267
17614
|
conflicts: 0
|
|
@@ -17332,7 +17679,7 @@ RED.diagnostics = (function () {
|
|
|
17332
17679
|
$(this).parent().toggleClass('collapsed');
|
|
17333
17680
|
});
|
|
17334
17681
|
|
|
17335
|
-
createNodePropertiesTable(def,tab,localTabNode,remoteTabNode
|
|
17682
|
+
createNodePropertiesTable(def,tab,localTabNode,remoteTabNode).appendTo(div);
|
|
17336
17683
|
selectState = "";
|
|
17337
17684
|
if (conflicts[tab.id]) {
|
|
17338
17685
|
flowStats.conflicts++;
|
|
@@ -17402,19 +17749,26 @@ RED.diagnostics = (function () {
|
|
|
17402
17749
|
var localStats = $('<span>',{class:"red-ui-diff-list-flow-stats"}).appendTo(localCell);
|
|
17403
17750
|
$('<span class="red-ui-diff-status"></span>').text(RED._('diff.nodeCount',{count:localNodeCount})).appendTo(localStats);
|
|
17404
17751
|
|
|
17405
|
-
if (flowStats.conflicts + flowStats.local.addedCount + flowStats.local.changedCount + flowStats.local.deletedCount > 0) {
|
|
17752
|
+
if (flowStats.conflicts + flowStats.local.addedCount + flowStats.local.changedCount + flowStats.local.movedCount + flowStats.local.deletedCount > 0) {
|
|
17406
17753
|
$('<span class="red-ui-diff-status"> [ </span>').appendTo(localStats);
|
|
17407
17754
|
if (flowStats.conflicts > 0) {
|
|
17408
17755
|
$('<span class="red-ui-diff-status-conflict"><span class="red-ui-diff-status"><i class="fa fa-exclamation"></i> '+flowStats.conflicts+'</span></span>').appendTo(localStats);
|
|
17409
17756
|
}
|
|
17410
17757
|
if (flowStats.local.addedCount > 0) {
|
|
17411
|
-
$('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.local.addedCount+'</span></span>').appendTo(localStats);
|
|
17758
|
+
const cell = $('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.local.addedCount+'</span></span>').appendTo(localStats);
|
|
17759
|
+
RED.popover.tooltip(cell, RED._('diff.type.added'))
|
|
17412
17760
|
}
|
|
17413
17761
|
if (flowStats.local.changedCount > 0) {
|
|
17414
|
-
$('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.changedCount+'</span></span>').appendTo(localStats);
|
|
17762
|
+
const cell = $('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.changedCount+'</span></span>').appendTo(localStats);
|
|
17763
|
+
RED.popover.tooltip(cell, RED._('diff.type.changed'))
|
|
17764
|
+
}
|
|
17765
|
+
if (flowStats.local.movedCount > 0) {
|
|
17766
|
+
const cell = $('<span class="red-ui-diff-status-moved"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.movedCount+'</span></span>').appendTo(localStats);
|
|
17767
|
+
RED.popover.tooltip(cell, RED._('diff.type.moved'))
|
|
17415
17768
|
}
|
|
17416
17769
|
if (flowStats.local.deletedCount > 0) {
|
|
17417
|
-
$('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.local.deletedCount+'</span></span>').appendTo(localStats);
|
|
17770
|
+
const cell = $('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.local.deletedCount+'</span></span>').appendTo(localStats);
|
|
17771
|
+
RED.popover.tooltip(cell, RED._('diff.type.deleted'))
|
|
17418
17772
|
}
|
|
17419
17773
|
$('<span class="red-ui-diff-status"> ] </span>').appendTo(localStats);
|
|
17420
17774
|
}
|
|
@@ -17440,19 +17794,26 @@ RED.diagnostics = (function () {
|
|
|
17440
17794
|
}
|
|
17441
17795
|
var remoteStats = $('<span>',{class:"red-ui-diff-list-flow-stats"}).appendTo(remoteCell);
|
|
17442
17796
|
$('<span class="red-ui-diff-status"></span>').text(RED._('diff.nodeCount',{count:remoteNodeCount})).appendTo(remoteStats);
|
|
17443
|
-
if (flowStats.conflicts + flowStats.remote.addedCount + flowStats.remote.changedCount + flowStats.remote.deletedCount > 0) {
|
|
17797
|
+
if (flowStats.conflicts + flowStats.remote.addedCount + flowStats.remote.changedCount + flowStats.remote.movedCount + flowStats.remote.deletedCount > 0) {
|
|
17444
17798
|
$('<span class="red-ui-diff-status"> [ </span>').appendTo(remoteStats);
|
|
17445
17799
|
if (flowStats.conflicts > 0) {
|
|
17446
17800
|
$('<span class="red-ui-diff-status-conflict"><span class="red-ui-diff-status"><i class="fa fa-exclamation"></i> '+flowStats.conflicts+'</span></span>').appendTo(remoteStats);
|
|
17447
17801
|
}
|
|
17448
17802
|
if (flowStats.remote.addedCount > 0) {
|
|
17449
|
-
$('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.remote.addedCount+'</span></span>').appendTo(remoteStats);
|
|
17803
|
+
const cell = $('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.remote.addedCount+'</span></span>').appendTo(remoteStats);
|
|
17804
|
+
RED.popover.tooltip(cell, RED._('diff.type.added'))
|
|
17450
17805
|
}
|
|
17451
17806
|
if (flowStats.remote.changedCount > 0) {
|
|
17452
|
-
$('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.changedCount+'</span></span>').appendTo(remoteStats);
|
|
17807
|
+
const cell = $('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.changedCount+'</span></span>').appendTo(remoteStats);
|
|
17808
|
+
RED.popover.tooltip(cell, RED._('diff.type.changed'))
|
|
17809
|
+
}
|
|
17810
|
+
if (flowStats.remote.movedCount > 0) {
|
|
17811
|
+
const cell = $('<span class="red-ui-diff-status-moved"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.movedCount+'</span></span>').appendTo(remoteStats);
|
|
17812
|
+
RED.popover.tooltip(cell, RED._('diff.type.moved'))
|
|
17453
17813
|
}
|
|
17454
17814
|
if (flowStats.remote.deletedCount > 0) {
|
|
17455
|
-
$('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.remote.deletedCount+'</span></span>').appendTo(remoteStats);
|
|
17815
|
+
const cell = $('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.remote.deletedCount+'</span></span>').appendTo(remoteStats);
|
|
17816
|
+
RED.popover.tooltip(cell, RED._('diff.type.deleted'))
|
|
17456
17817
|
}
|
|
17457
17818
|
$('<span class="red-ui-diff-status"> ] </span>').appendTo(remoteStats);
|
|
17458
17819
|
}
|
|
@@ -17487,7 +17848,7 @@ RED.diagnostics = (function () {
|
|
|
17487
17848
|
if (options.mode === "merge") {
|
|
17488
17849
|
diffPanel.addClass("red-ui-diff-panel-merge");
|
|
17489
17850
|
}
|
|
17490
|
-
var diffList = createDiffTable(diffPanel, diff);
|
|
17851
|
+
var diffList = createDiffTable(diffPanel, diff, options);
|
|
17491
17852
|
|
|
17492
17853
|
var localDiff = diff.localDiff;
|
|
17493
17854
|
var remoteDiff = diff.remoteDiff;
|
|
@@ -17710,7 +18071,6 @@ RED.diagnostics = (function () {
|
|
|
17710
18071
|
|
|
17711
18072
|
var hasChanges = false; // exists in original and local/remote but with changes
|
|
17712
18073
|
var unChanged = true; // existing in original,local,remote unchanged
|
|
17713
|
-
var localChanged = false;
|
|
17714
18074
|
|
|
17715
18075
|
if (localDiff.added[node.id]) {
|
|
17716
18076
|
stats.local.addedCount++;
|
|
@@ -17729,12 +18089,20 @@ RED.diagnostics = (function () {
|
|
|
17729
18089
|
unChanged = false;
|
|
17730
18090
|
}
|
|
17731
18091
|
if (localDiff.changed[node.id]) {
|
|
17732
|
-
|
|
18092
|
+
if (localDiff.positionChanged[node.id]) {
|
|
18093
|
+
stats.local.movedCount++
|
|
18094
|
+
} else {
|
|
18095
|
+
stats.local.changedCount++;
|
|
18096
|
+
}
|
|
17733
18097
|
hasChanges = true;
|
|
17734
18098
|
unChanged = false;
|
|
17735
18099
|
}
|
|
17736
18100
|
if (remoteDiff && remoteDiff.changed[node.id]) {
|
|
17737
|
-
|
|
18101
|
+
if (remoteDiff.positionChanged[node.id]) {
|
|
18102
|
+
stats.remote.movedCount++
|
|
18103
|
+
} else {
|
|
18104
|
+
stats.remote.changedCount++;
|
|
18105
|
+
}
|
|
17738
18106
|
hasChanges = true;
|
|
17739
18107
|
unChanged = false;
|
|
17740
18108
|
}
|
|
@@ -17799,27 +18167,32 @@ RED.diagnostics = (function () {
|
|
|
17799
18167
|
localNodeDiv.addClass("red-ui-diff-status-moved");
|
|
17800
18168
|
var localMovedMessage = "";
|
|
17801
18169
|
if (node.z === localN.z) {
|
|
17802
|
-
|
|
18170
|
+
const movedFromNodeTab = localDiff.currentConfig.all[localDiff.currentConfig.all[node.id].z]
|
|
18171
|
+
const movedFromLabel = `'${movedFromNodeTab ? (movedFromNodeTab.label || movedFromNodeTab.id) : 'global'}'`
|
|
18172
|
+
localMovedMessage = RED._("diff.type.movedFrom",{id: movedFromLabel});
|
|
17803
18173
|
} else {
|
|
17804
|
-
|
|
18174
|
+
const movedToNodeTab = localDiff.newConfig.all[localN.z]
|
|
18175
|
+
const movedToLabel = `'${movedToNodeTab ? (movedToNodeTab.label || movedToNodeTab.id) : 'global'}'`
|
|
18176
|
+
localMovedMessage = RED._("diff.type.movedTo",{id:movedToLabel});
|
|
17805
18177
|
}
|
|
17806
18178
|
$('<span class="red-ui-diff-status"><i class="fa fa-caret-square-o-right"></i> '+localMovedMessage+'</span>').appendTo(localNodeDiv);
|
|
17807
18179
|
}
|
|
17808
|
-
localChanged = true;
|
|
17809
18180
|
} else if (localDiff.deleted[node.z]) {
|
|
17810
18181
|
localNodeDiv.addClass("red-ui-diff-empty");
|
|
17811
|
-
localChanged = true;
|
|
17812
18182
|
} else if (localDiff.deleted[node.id]) {
|
|
17813
18183
|
localNodeDiv.addClass("red-ui-diff-status-deleted");
|
|
17814
18184
|
$('<span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> <span data-i18n="diff.type.deleted"></span></span>').appendTo(localNodeDiv);
|
|
17815
|
-
localChanged = true;
|
|
17816
18185
|
} else if (localDiff.changed[node.id]) {
|
|
17817
18186
|
if (localDiff.newConfig.all[node.id].z !== node.z) {
|
|
17818
18187
|
localNodeDiv.addClass("red-ui-diff-empty");
|
|
17819
18188
|
} else {
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
|
|
18189
|
+
if (localDiff.positionChanged[node.id]) {
|
|
18190
|
+
localNodeDiv.addClass("red-ui-diff-status-moved");
|
|
18191
|
+
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.moved"></span></span>').appendTo(localNodeDiv);
|
|
18192
|
+
} else {
|
|
18193
|
+
localNodeDiv.addClass("red-ui-diff-status-changed");
|
|
18194
|
+
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(localNodeDiv);
|
|
18195
|
+
}
|
|
17823
18196
|
}
|
|
17824
18197
|
} else {
|
|
17825
18198
|
if (localDiff.newConfig.all[node.id].z !== node.z) {
|
|
@@ -17840,9 +18213,13 @@ RED.diagnostics = (function () {
|
|
|
17840
18213
|
remoteNodeDiv.addClass("red-ui-diff-status-moved");
|
|
17841
18214
|
var remoteMovedMessage = "";
|
|
17842
18215
|
if (node.z === remoteN.z) {
|
|
17843
|
-
|
|
18216
|
+
const movedFromNodeTab = remoteDiff.currentConfig.all[remoteDiff.currentConfig.all[node.id].z]
|
|
18217
|
+
const movedFromLabel = `'${movedFromNodeTab ? (movedFromNodeTab.label || movedFromNodeTab.id) : 'global'}'`
|
|
18218
|
+
remoteMovedMessage = RED._("diff.type.movedFrom",{id:movedFromLabel});
|
|
17844
18219
|
} else {
|
|
17845
|
-
|
|
18220
|
+
const movedToNodeTab = remoteDiff.newConfig.all[remoteN.z]
|
|
18221
|
+
const movedToLabel = `'${movedToNodeTab ? (movedToNodeTab.label || movedToNodeTab.id) : 'global'}'`
|
|
18222
|
+
remoteMovedMessage = RED._("diff.type.movedTo",{id:movedToLabel});
|
|
17846
18223
|
}
|
|
17847
18224
|
$('<span class="red-ui-diff-status"><i class="fa fa-caret-square-o-right"></i> '+remoteMovedMessage+'</span>').appendTo(remoteNodeDiv);
|
|
17848
18225
|
}
|
|
@@ -17855,8 +18232,13 @@ RED.diagnostics = (function () {
|
|
|
17855
18232
|
if (remoteDiff.newConfig.all[node.id].z !== node.z) {
|
|
17856
18233
|
remoteNodeDiv.addClass("red-ui-diff-empty");
|
|
17857
18234
|
} else {
|
|
17858
|
-
|
|
17859
|
-
|
|
18235
|
+
if (remoteDiff.positionChanged[node.id]) {
|
|
18236
|
+
remoteNodeDiv.addClass("red-ui-diff-status-moved");
|
|
18237
|
+
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.moved"></span></span>').appendTo(remoteNodeDiv);
|
|
18238
|
+
} else {
|
|
18239
|
+
remoteNodeDiv.addClass("red-ui-diff-status-changed");
|
|
18240
|
+
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(remoteNodeDiv);
|
|
18241
|
+
}
|
|
17860
18242
|
}
|
|
17861
18243
|
} else {
|
|
17862
18244
|
if (remoteDiff.newConfig.all[node.id].z !== node.z) {
|
|
@@ -17982,7 +18364,7 @@ RED.diagnostics = (function () {
|
|
|
17982
18364
|
$("<td>",{class:"red-ui-diff-list-cell-label"}).text("position").appendTo(row);
|
|
17983
18365
|
localCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-local"}).appendTo(row);
|
|
17984
18366
|
if (localNode) {
|
|
17985
|
-
localCell.addClass("red-ui-diff-status-"+(localChanged?"
|
|
18367
|
+
localCell.addClass("red-ui-diff-status-"+(localChanged?"moved":"unchanged"));
|
|
17986
18368
|
$('<span class="red-ui-diff-status">'+(localChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(localCell);
|
|
17987
18369
|
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(localCell);
|
|
17988
18370
|
var localPosition = {x:localNode.x,y:localNode.y};
|
|
@@ -18007,7 +18389,7 @@ RED.diagnostics = (function () {
|
|
|
18007
18389
|
|
|
18008
18390
|
if (remoteNode !== undefined) {
|
|
18009
18391
|
remoteCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-remote"}).appendTo(row);
|
|
18010
|
-
remoteCell.addClass("red-ui-diff-status-"+(remoteChanged?"
|
|
18392
|
+
remoteCell.addClass("red-ui-diff-status-"+(remoteChanged?"moved":"unchanged"));
|
|
18011
18393
|
if (remoteNode) {
|
|
18012
18394
|
$('<span class="red-ui-diff-status">'+(remoteChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(remoteCell);
|
|
18013
18395
|
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(remoteCell);
|
|
@@ -18293,11 +18675,11 @@ RED.diagnostics = (function () {
|
|
|
18293
18675
|
// var diff = generateDiff(originalFlow,nns);
|
|
18294
18676
|
// showDiff(diff);
|
|
18295
18677
|
// }
|
|
18296
|
-
function showRemoteDiff(diff) {
|
|
18297
|
-
if (diff
|
|
18298
|
-
getRemoteDiff(showRemoteDiff);
|
|
18678
|
+
function showRemoteDiff(diff, options = {}) {
|
|
18679
|
+
if (!diff) {
|
|
18680
|
+
getRemoteDiff((remoteDiff) => showRemoteDiff(remoteDiff, options));
|
|
18299
18681
|
} else {
|
|
18300
|
-
showDiff(diff,{mode:'merge'});
|
|
18682
|
+
showDiff(diff,{...options, mode:'merge'});
|
|
18301
18683
|
}
|
|
18302
18684
|
}
|
|
18303
18685
|
function parseNodes(nodeList) {
|
|
@@ -18338,23 +18720,53 @@ RED.diagnostics = (function () {
|
|
|
18338
18720
|
}
|
|
18339
18721
|
}
|
|
18340
18722
|
function generateDiff(currentNodes,newNodes) {
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
|
|
18723
|
+
const currentConfig = parseNodes(currentNodes);
|
|
18724
|
+
const newConfig = parseNodes(newNodes);
|
|
18725
|
+
const added = {};
|
|
18726
|
+
const deleted = {};
|
|
18727
|
+
const changed = {};
|
|
18728
|
+
const positionChanged = {};
|
|
18729
|
+
const moved = {};
|
|
18347
18730
|
|
|
18348
18731
|
Object.keys(currentConfig.all).forEach(function(id) {
|
|
18349
|
-
|
|
18732
|
+
const node = RED.nodes.workspace(id)||RED.nodes.subflow(id)||RED.nodes.node(id);
|
|
18350
18733
|
if (!newConfig.all.hasOwnProperty(id)) {
|
|
18351
18734
|
deleted[id] = true;
|
|
18352
|
-
|
|
18735
|
+
return
|
|
18736
|
+
}
|
|
18737
|
+
const currentConfigJSON = JSON.stringify(currentConfig.all[id])
|
|
18738
|
+
const newConfigJSON = JSON.stringify(newConfig.all[id])
|
|
18739
|
+
|
|
18740
|
+
if (currentConfigJSON !== newConfigJSON) {
|
|
18353
18741
|
changed[id] = true;
|
|
18354
|
-
|
|
18355
18742
|
if (currentConfig.all[id].z !== newConfig.all[id].z) {
|
|
18356
18743
|
moved[id] = true;
|
|
18744
|
+
} else if (
|
|
18745
|
+
currentConfig.all[id].x !== newConfig.all[id].x ||
|
|
18746
|
+
currentConfig.all[id].y !== newConfig.all[id].y ||
|
|
18747
|
+
currentConfig.all[id].w !== newConfig.all[id].w ||
|
|
18748
|
+
currentConfig.all[id].h !== newConfig.all[id].h
|
|
18749
|
+
) {
|
|
18750
|
+
// This node's position on its parent has changed. We want to
|
|
18751
|
+
// check if this is the *only* change for this given node
|
|
18752
|
+
const currentNodeClone = JSON.parse(currentConfigJSON)
|
|
18753
|
+
const newNodeClone = JSON.parse(newConfigJSON)
|
|
18754
|
+
|
|
18755
|
+
delete currentNodeClone.x
|
|
18756
|
+
delete currentNodeClone.y
|
|
18757
|
+
delete currentNodeClone.w
|
|
18758
|
+
delete currentNodeClone.h
|
|
18759
|
+
delete newNodeClone.x
|
|
18760
|
+
delete newNodeClone.y
|
|
18761
|
+
delete newNodeClone.w
|
|
18762
|
+
delete newNodeClone.h
|
|
18763
|
+
|
|
18764
|
+
if (JSON.stringify(currentNodeClone) === JSON.stringify(newNodeClone)) {
|
|
18765
|
+
// Only the position has changed - everything else is the same
|
|
18766
|
+
positionChanged[id] = true
|
|
18767
|
+
}
|
|
18357
18768
|
}
|
|
18769
|
+
|
|
18358
18770
|
}
|
|
18359
18771
|
});
|
|
18360
18772
|
Object.keys(newConfig.all).forEach(function(id) {
|
|
@@ -18363,13 +18775,14 @@ RED.diagnostics = (function () {
|
|
|
18363
18775
|
}
|
|
18364
18776
|
});
|
|
18365
18777
|
|
|
18366
|
-
|
|
18367
|
-
currentConfig
|
|
18368
|
-
newConfig
|
|
18369
|
-
added
|
|
18370
|
-
deleted
|
|
18371
|
-
changed
|
|
18372
|
-
|
|
18778
|
+
const diff = {
|
|
18779
|
+
currentConfig,
|
|
18780
|
+
newConfig,
|
|
18781
|
+
added,
|
|
18782
|
+
deleted,
|
|
18783
|
+
changed,
|
|
18784
|
+
positionChanged,
|
|
18785
|
+
moved
|
|
18373
18786
|
};
|
|
18374
18787
|
return diff;
|
|
18375
18788
|
}
|
|
@@ -18434,12 +18847,14 @@ RED.diagnostics = (function () {
|
|
|
18434
18847
|
return diff;
|
|
18435
18848
|
}
|
|
18436
18849
|
|
|
18437
|
-
function showDiff(diff,options) {
|
|
18850
|
+
function showDiff(diff, options) {
|
|
18438
18851
|
if (diffVisible) {
|
|
18439
18852
|
return;
|
|
18440
18853
|
}
|
|
18441
18854
|
options = options || {};
|
|
18442
18855
|
var mode = options.mode || 'merge';
|
|
18856
|
+
|
|
18857
|
+
options.hidePositionChanges = true
|
|
18443
18858
|
|
|
18444
18859
|
var localDiff = diff.localDiff;
|
|
18445
18860
|
var remoteDiff = diff.remoteDiff;
|
|
@@ -18509,6 +18924,9 @@ RED.diagnostics = (function () {
|
|
|
18509
18924
|
if (!$("#red-ui-diff-view-diff-merge").hasClass('disabled')) {
|
|
18510
18925
|
refreshConflictHeader(diff);
|
|
18511
18926
|
mergeDiff(diff);
|
|
18927
|
+
if (options.onmerge) {
|
|
18928
|
+
options.onmerge()
|
|
18929
|
+
}
|
|
18512
18930
|
RED.tray.close();
|
|
18513
18931
|
}
|
|
18514
18932
|
}
|
|
@@ -18539,6 +18957,7 @@ RED.diagnostics = (function () {
|
|
|
18539
18957
|
var newConfig = [];
|
|
18540
18958
|
var node;
|
|
18541
18959
|
var nodeChangedStates = {};
|
|
18960
|
+
var nodeMovedStates = {};
|
|
18542
18961
|
var localChangedStates = {};
|
|
18543
18962
|
for (id in localDiff.newConfig.all) {
|
|
18544
18963
|
if (localDiff.newConfig.all.hasOwnProperty(id)) {
|
|
@@ -18546,12 +18965,14 @@ RED.diagnostics = (function () {
|
|
|
18546
18965
|
if (resolutions[id] === 'local') {
|
|
18547
18966
|
if (node) {
|
|
18548
18967
|
nodeChangedStates[id] = node.changed;
|
|
18968
|
+
nodeMovedStates[id] = node.moved;
|
|
18549
18969
|
}
|
|
18550
18970
|
newConfig.push(localDiff.newConfig.all[id]);
|
|
18551
18971
|
} else if (resolutions[id] === 'remote') {
|
|
18552
18972
|
if (!remoteDiff.deleted[id] && remoteDiff.newConfig.all.hasOwnProperty(id)) {
|
|
18553
18973
|
if (node) {
|
|
18554
18974
|
nodeChangedStates[id] = node.changed;
|
|
18975
|
+
nodeMovedStates[id] = node.moved;
|
|
18555
18976
|
}
|
|
18556
18977
|
localChangedStates[id] = 1;
|
|
18557
18978
|
newConfig.push(remoteDiff.newConfig.all[id]);
|
|
@@ -18575,8 +18996,9 @@ RED.diagnostics = (function () {
|
|
|
18575
18996
|
}
|
|
18576
18997
|
return {
|
|
18577
18998
|
config: newConfig,
|
|
18578
|
-
nodeChangedStates
|
|
18579
|
-
|
|
18999
|
+
nodeChangedStates,
|
|
19000
|
+
nodeMovedStates,
|
|
19001
|
+
localChangedStates
|
|
18580
19002
|
}
|
|
18581
19003
|
}
|
|
18582
19004
|
|
|
@@ -18587,6 +19009,7 @@ RED.diagnostics = (function () {
|
|
|
18587
19009
|
|
|
18588
19010
|
var newConfig = appliedDiff.config;
|
|
18589
19011
|
var nodeChangedStates = appliedDiff.nodeChangedStates;
|
|
19012
|
+
var nodeMovedStates = appliedDiff.nodeMovedStates;
|
|
18590
19013
|
var localChangedStates = appliedDiff.localChangedStates;
|
|
18591
19014
|
|
|
18592
19015
|
var isDirty = RED.nodes.dirty();
|
|
@@ -18595,33 +19018,56 @@ RED.diagnostics = (function () {
|
|
|
18595
19018
|
t:"replace",
|
|
18596
19019
|
config: RED.nodes.createCompleteNodeSet(),
|
|
18597
19020
|
changed: nodeChangedStates,
|
|
19021
|
+
moved: nodeMovedStates,
|
|
19022
|
+
complete: true,
|
|
18598
19023
|
dirty: isDirty,
|
|
18599
19024
|
rev: RED.nodes.version()
|
|
18600
19025
|
}
|
|
18601
19026
|
|
|
18602
19027
|
RED.history.push(historyEvent);
|
|
18603
19028
|
|
|
18604
|
-
var originalFlow = RED.nodes.originalFlow();
|
|
18605
|
-
// originalFlow is what the editor
|
|
18606
|
-
// - add any newly added nodes from remote diff as they are now part of the record
|
|
18607
|
-
for (var id in diff.remoteDiff.added) {
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
|
|
18612
|
-
|
|
18613
|
-
}
|
|
19029
|
+
// var originalFlow = RED.nodes.originalFlow();
|
|
19030
|
+
// // originalFlow is what the editor thinks it loaded
|
|
19031
|
+
// // - add any newly added nodes from remote diff as they are now part of the record
|
|
19032
|
+
// for (var id in diff.remoteDiff.added) {
|
|
19033
|
+
// if (diff.remoteDiff.added.hasOwnProperty(id)) {
|
|
19034
|
+
// if (diff.remoteDiff.newConfig.all.hasOwnProperty(id)) {
|
|
19035
|
+
// originalFlow.push(JSON.parse(JSON.stringify(diff.remoteDiff.newConfig.all[id])));
|
|
19036
|
+
// }
|
|
19037
|
+
// }
|
|
19038
|
+
// }
|
|
18614
19039
|
|
|
18615
19040
|
RED.nodes.clear();
|
|
18616
19041
|
var imported = RED.nodes.import(newConfig);
|
|
18617
19042
|
|
|
18618
|
-
// Restore the original flow so subsequent merge resolutions can properly
|
|
18619
|
-
// identify new-vs-old
|
|
18620
|
-
RED.nodes.originalFlow(originalFlow);
|
|
19043
|
+
// // Restore the original flow so subsequent merge resolutions can properly
|
|
19044
|
+
// // identify new-vs-old
|
|
19045
|
+
// RED.nodes.originalFlow(originalFlow);
|
|
19046
|
+
|
|
19047
|
+
// Clear all change flags from the import
|
|
19048
|
+
RED.nodes.dirty(false);
|
|
19049
|
+
|
|
19050
|
+
const flowsToLock = new Set()
|
|
19051
|
+
function ensureUnlocked(id) {
|
|
19052
|
+
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
|
|
19053
|
+
const isLocked = flow ? flow.locked : false;
|
|
19054
|
+
if (flow && isLocked) {
|
|
19055
|
+
flow.locked = false;
|
|
19056
|
+
flowsToLock.add(flow)
|
|
19057
|
+
}
|
|
19058
|
+
}
|
|
18621
19059
|
imported.nodes.forEach(function(n) {
|
|
18622
|
-
if (nodeChangedStates[n.id]
|
|
19060
|
+
if (nodeChangedStates[n.id]) {
|
|
19061
|
+
ensureUnlocked(n.z)
|
|
18623
19062
|
n.changed = true;
|
|
18624
19063
|
}
|
|
19064
|
+
if (nodeMovedStates[n.id]) {
|
|
19065
|
+
ensureUnlocked(n.z)
|
|
19066
|
+
n.moved = true;
|
|
19067
|
+
}
|
|
19068
|
+
})
|
|
19069
|
+
flowsToLock.forEach(flow => {
|
|
19070
|
+
flow.locked = true
|
|
18625
19071
|
})
|
|
18626
19072
|
|
|
18627
19073
|
RED.nodes.version(diff.remoteDiff.rev);
|
|
@@ -20681,11 +21127,17 @@ RED.workspaces = (function() {
|
|
|
20681
21127
|
RED.sidebar.config.refresh();
|
|
20682
21128
|
RED.view.focus();
|
|
20683
21129
|
},
|
|
20684
|
-
onclick: function(tab) {
|
|
20685
|
-
if
|
|
20686
|
-
|
|
21130
|
+
onclick: function(tab, evt) {
|
|
21131
|
+
if(evt.which === 2) {
|
|
21132
|
+
evt.preventDefault();
|
|
21133
|
+
evt.stopPropagation();
|
|
21134
|
+
RED.actions.invoke("core:hide-flow", tab)
|
|
21135
|
+
} else {
|
|
21136
|
+
if (tab.id !== activeWorkspace) {
|
|
21137
|
+
addToViewStack(activeWorkspace);
|
|
21138
|
+
}
|
|
21139
|
+
RED.view.focus();
|
|
20687
21140
|
}
|
|
20688
|
-
RED.view.focus();
|
|
20689
21141
|
},
|
|
20690
21142
|
ondblclick: function(tab) {
|
|
20691
21143
|
if (tab.type != "subflow") {
|
|
@@ -20723,6 +21175,7 @@ RED.workspaces = (function() {
|
|
|
20723
21175
|
if (tab.type === "tab") {
|
|
20724
21176
|
workspaceTabCount--;
|
|
20725
21177
|
} else {
|
|
21178
|
+
RED.events.emit("workspace:close",{workspace: tab.id})
|
|
20726
21179
|
hideStack.push(tab.id);
|
|
20727
21180
|
}
|
|
20728
21181
|
RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
|
|
@@ -21938,120 +22391,128 @@ RED.view = (function() {
|
|
|
21938
22391
|
}
|
|
21939
22392
|
d3.event = event;
|
|
21940
22393
|
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
|
|
21941
|
-
|
|
21942
|
-
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
22394
|
+
try {
|
|
22395
|
+
var result = createNode(selected_tool);
|
|
22396
|
+
if (!result) {
|
|
22397
|
+
return;
|
|
22398
|
+
}
|
|
22399
|
+
var historyEvent = result.historyEvent;
|
|
22400
|
+
var nn = RED.nodes.add(result.node);
|
|
21947
22401
|
|
|
21948
|
-
|
|
21949
|
-
|
|
21950
|
-
|
|
21951
|
-
|
|
22402
|
+
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
|
|
22403
|
+
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
|
|
22404
|
+
nn.l = showLabel;
|
|
22405
|
+
}
|
|
21952
22406
|
|
|
21953
|
-
|
|
21954
|
-
|
|
21955
|
-
|
|
21956
|
-
|
|
22407
|
+
var helperOffset = d3.touches(ui.helper.get(0))[0]||d3.mouse(ui.helper.get(0));
|
|
22408
|
+
var helperWidth = ui.helper.width();
|
|
22409
|
+
var helperHeight = ui.helper.height();
|
|
22410
|
+
var mousePos = d3.touches(this)[0]||d3.mouse(this);
|
|
21957
22411
|
|
|
21958
|
-
|
|
21959
|
-
|
|
21960
|
-
|
|
21961
|
-
|
|
21962
|
-
var label = RED.utils.getNodeLabel(nn, nn.type);
|
|
21963
|
-
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
|
|
21964
|
-
if (hideLabel) {
|
|
21965
|
-
nn.w = node_height;
|
|
21966
|
-
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
|
|
21967
|
-
} else {
|
|
21968
|
-
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
|
|
21969
|
-
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
|
|
21970
|
-
}
|
|
21971
|
-
} catch(err) {
|
|
21972
|
-
}
|
|
22412
|
+
try {
|
|
22413
|
+
var isLink = (nn.type === "link in" || nn.type === "link out")
|
|
22414
|
+
var hideLabel = nn.hasOwnProperty('l')?!nn.l : isLink;
|
|
21973
22415
|
|
|
21974
|
-
|
|
21975
|
-
|
|
21976
|
-
|
|
21977
|
-
|
|
22416
|
+
var label = RED.utils.getNodeLabel(nn, nn.type);
|
|
22417
|
+
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
|
|
22418
|
+
if (hideLabel) {
|
|
22419
|
+
nn.w = node_height;
|
|
22420
|
+
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
|
|
22421
|
+
} else {
|
|
22422
|
+
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
|
|
22423
|
+
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
|
|
22424
|
+
}
|
|
22425
|
+
} catch(err) {
|
|
22426
|
+
}
|
|
21978
22427
|
|
|
21979
|
-
|
|
21980
|
-
|
|
22428
|
+
mousePos[1] += this.scrollTop + ((helperHeight/2)-helperOffset[1]);
|
|
22429
|
+
mousePos[0] += this.scrollLeft + ((helperWidth/2)-helperOffset[0]);
|
|
22430
|
+
mousePos[1] /= scaleFactor;
|
|
22431
|
+
mousePos[0] /= scaleFactor;
|
|
21981
22432
|
|
|
21982
|
-
|
|
21983
|
-
|
|
21984
|
-
nn.x = minX;
|
|
21985
|
-
}
|
|
21986
|
-
var minY = nn.h/2 -5;
|
|
21987
|
-
if (nn.y < minY) {
|
|
21988
|
-
nn.y = minY;
|
|
21989
|
-
}
|
|
21990
|
-
var maxX = space_width -nn.w/2 +5;
|
|
21991
|
-
if (nn.x > maxX) {
|
|
21992
|
-
nn.x = maxX;
|
|
21993
|
-
}
|
|
21994
|
-
var maxY = space_height -nn.h +5;
|
|
21995
|
-
if (nn.y > maxY) {
|
|
21996
|
-
nn.y = maxY;
|
|
21997
|
-
}
|
|
22433
|
+
nn.x = mousePos[0];
|
|
22434
|
+
nn.y = mousePos[1];
|
|
21998
22435
|
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
22002
|
-
|
|
22003
|
-
|
|
22436
|
+
var minX = nn.w/2 -5;
|
|
22437
|
+
if (nn.x < minX) {
|
|
22438
|
+
nn.x = minX;
|
|
22439
|
+
}
|
|
22440
|
+
var minY = nn.h/2 -5;
|
|
22441
|
+
if (nn.y < minY) {
|
|
22442
|
+
nn.y = minY;
|
|
22443
|
+
}
|
|
22444
|
+
var maxX = space_width -nn.w/2 +5;
|
|
22445
|
+
if (nn.x > maxX) {
|
|
22446
|
+
nn.x = maxX;
|
|
22447
|
+
}
|
|
22448
|
+
var maxY = space_height -nn.h +5;
|
|
22449
|
+
if (nn.y > maxY) {
|
|
22450
|
+
nn.y = maxY;
|
|
22451
|
+
}
|
|
22004
22452
|
|
|
22005
|
-
|
|
22006
|
-
|
|
22007
|
-
|
|
22008
|
-
|
|
22453
|
+
if (snapGrid) {
|
|
22454
|
+
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
|
|
22455
|
+
nn.x -= gridOffset.x;
|
|
22456
|
+
nn.y -= gridOffset.y;
|
|
22457
|
+
}
|
|
22009
22458
|
|
|
22010
|
-
|
|
22011
|
-
|
|
22012
|
-
|
|
22013
|
-
var oldY = group.y;
|
|
22014
|
-
RED.group.addToGroup(group, nn);
|
|
22015
|
-
var moveEvent = null;
|
|
22016
|
-
if ((group.x !== oldX) ||
|
|
22017
|
-
(group.y !== oldY)) {
|
|
22018
|
-
moveEvent = {
|
|
22019
|
-
t: "move",
|
|
22020
|
-
nodes: [{n: group,
|
|
22021
|
-
ox: oldX, oy: oldY,
|
|
22022
|
-
dx: group.x -oldX,
|
|
22023
|
-
dy: group.y -oldY}],
|
|
22024
|
-
dirty: true
|
|
22025
|
-
};
|
|
22459
|
+
var linkToSplice = $(ui.helper).data("splice");
|
|
22460
|
+
if (linkToSplice) {
|
|
22461
|
+
spliceLink(linkToSplice, nn, historyEvent)
|
|
22026
22462
|
}
|
|
22027
|
-
historyEvent = {
|
|
22028
|
-
t: 'multi',
|
|
22029
|
-
events: [historyEvent],
|
|
22030
22463
|
|
|
22031
|
-
|
|
22032
|
-
if (
|
|
22033
|
-
|
|
22464
|
+
var group = $(ui.helper).data("group");
|
|
22465
|
+
if (group) {
|
|
22466
|
+
var oldX = group.x;
|
|
22467
|
+
var oldY = group.y;
|
|
22468
|
+
RED.group.addToGroup(group, nn);
|
|
22469
|
+
var moveEvent = null;
|
|
22470
|
+
if ((group.x !== oldX) ||
|
|
22471
|
+
(group.y !== oldY)) {
|
|
22472
|
+
moveEvent = {
|
|
22473
|
+
t: "move",
|
|
22474
|
+
nodes: [{n: group,
|
|
22475
|
+
ox: oldX, oy: oldY,
|
|
22476
|
+
dx: group.x -oldX,
|
|
22477
|
+
dy: group.y -oldY}],
|
|
22478
|
+
dirty: true
|
|
22479
|
+
};
|
|
22480
|
+
}
|
|
22481
|
+
historyEvent = {
|
|
22482
|
+
t: 'multi',
|
|
22483
|
+
events: [historyEvent],
|
|
22484
|
+
|
|
22485
|
+
};
|
|
22486
|
+
if (moveEvent) {
|
|
22487
|
+
historyEvent.events.push(moveEvent)
|
|
22488
|
+
}
|
|
22489
|
+
historyEvent.events.push({
|
|
22490
|
+
t: "addToGroup",
|
|
22491
|
+
group: group,
|
|
22492
|
+
nodes: nn
|
|
22493
|
+
})
|
|
22034
22494
|
}
|
|
22035
|
-
historyEvent.events.push({
|
|
22036
|
-
t: "addToGroup",
|
|
22037
|
-
group: group,
|
|
22038
|
-
nodes: nn
|
|
22039
|
-
})
|
|
22040
|
-
}
|
|
22041
22495
|
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22496
|
+
RED.history.push(historyEvent);
|
|
22497
|
+
RED.editor.validateNode(nn);
|
|
22498
|
+
RED.nodes.dirty(true);
|
|
22499
|
+
// auto select dropped node - so info shows (if visible)
|
|
22500
|
+
clearSelection();
|
|
22501
|
+
nn.selected = true;
|
|
22502
|
+
movingSet.add(nn);
|
|
22503
|
+
updateActiveNodes();
|
|
22504
|
+
updateSelection();
|
|
22505
|
+
redraw();
|
|
22052
22506
|
|
|
22053
|
-
|
|
22054
|
-
|
|
22507
|
+
if (nn._def.autoedit) {
|
|
22508
|
+
RED.editor.edit(nn);
|
|
22509
|
+
}
|
|
22510
|
+
} catch (error) {
|
|
22511
|
+
if (error.code != "NODE_RED") {
|
|
22512
|
+
RED.notify(RED._("notification.error",{message:error.toString()}),"error");
|
|
22513
|
+
} else {
|
|
22514
|
+
RED.notify(RED._("notification.error",{message:error.message}),"error");
|
|
22515
|
+
}
|
|
22055
22516
|
}
|
|
22056
22517
|
}
|
|
22057
22518
|
});
|
|
@@ -27355,14 +27816,19 @@ RED.view = (function() {
|
|
|
27355
27816
|
function createNode(type, x, y, z) {
|
|
27356
27817
|
const wasDirty = RED.nodes.dirty()
|
|
27357
27818
|
var m = /^subflow:(.+)$/.exec(type);
|
|
27358
|
-
var activeSubflow = z ? RED.nodes.subflow(z) : null;
|
|
27819
|
+
var activeSubflow = (z || RED.workspaces.active()) ? RED.nodes.subflow(z || RED.workspaces.active()) : null;
|
|
27820
|
+
|
|
27359
27821
|
if (activeSubflow && m) {
|
|
27360
27822
|
var subflowId = m[1];
|
|
27823
|
+
let err
|
|
27361
27824
|
if (subflowId === activeSubflow.id) {
|
|
27362
|
-
|
|
27825
|
+
err = new Error(RED._("notification.errors.cannotAddSubflowToItself"))
|
|
27826
|
+
} else if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
|
|
27827
|
+
err = new Error(RED._("notification.errors.cannotAddCircularReference"))
|
|
27363
27828
|
}
|
|
27364
|
-
if (
|
|
27365
|
-
|
|
27829
|
+
if (err) {
|
|
27830
|
+
err.code = 'NODE_RED'
|
|
27831
|
+
throw err
|
|
27366
27832
|
}
|
|
27367
27833
|
}
|
|
27368
27834
|
|
|
@@ -27751,14 +28217,27 @@ RED.view = (function() {
|
|
|
27751
28217
|
addAnnotation(evt.node.__pendingAnnotation__,evt);
|
|
27752
28218
|
delete evt.node.__pendingAnnotation__;
|
|
27753
28219
|
}
|
|
27754
|
-
|
|
27755
|
-
|
|
27756
|
-
|
|
27757
|
-
|
|
28220
|
+
let badgeRDX = 0;
|
|
28221
|
+
let badgeLDX = 0;
|
|
28222
|
+
|
|
28223
|
+
for (let i=0,l=evt.el.__annotations__.length;i<l;i++) {
|
|
28224
|
+
const annotation = evt.el.__annotations__[i];
|
|
27758
28225
|
if (annotations.hasOwnProperty(annotation.id)) {
|
|
27759
|
-
|
|
27760
|
-
|
|
27761
|
-
|
|
28226
|
+
const opts = annotations[annotation.id];
|
|
28227
|
+
let showAnnotation = true;
|
|
28228
|
+
const isBadge = opts.type === 'badge';
|
|
28229
|
+
if (opts.refresh !== undefined) {
|
|
28230
|
+
let refreshAnnotation = false
|
|
28231
|
+
if (typeof opts.refresh === "string") {
|
|
28232
|
+
refreshAnnotation = !!evt.node[opts.refresh]
|
|
28233
|
+
delete evt.node[opts.refresh]
|
|
28234
|
+
} else if (typeof opts.refresh === "function") {
|
|
28235
|
+
refreshAnnotation = opts.refresh(evnt.node)
|
|
28236
|
+
}
|
|
28237
|
+
if (refreshAnnotation) {
|
|
28238
|
+
refreshAnnotationElement(annotation.id, annotation.node, annotation.element)
|
|
28239
|
+
}
|
|
28240
|
+
}
|
|
27762
28241
|
if (opts.show !== undefined) {
|
|
27763
28242
|
if (typeof opts.show === "string") {
|
|
27764
28243
|
showAnnotation = !!evt.node[opts.show]
|
|
@@ -27771,17 +28250,24 @@ RED.view = (function() {
|
|
|
27771
28250
|
}
|
|
27772
28251
|
if (isBadge) {
|
|
27773
28252
|
if (showAnnotation) {
|
|
27774
|
-
|
|
27775
|
-
|
|
27776
|
-
|
|
27777
|
-
|
|
27778
|
-
|
|
27779
|
-
|
|
27780
|
-
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
|
|
28253
|
+
const rect = annotation.element.getBoundingClientRect();
|
|
28254
|
+
let annotationX
|
|
28255
|
+
if (!opts.align || opts.align === 'right') {
|
|
28256
|
+
annotationX = evt.node.w - 3 - badgeRDX - rect.width
|
|
28257
|
+
badgeRDX += rect.width + 4;
|
|
28258
|
+
|
|
28259
|
+
} else if (opts.align === 'left') {
|
|
28260
|
+
annotationX = 3 + badgeLDX
|
|
28261
|
+
badgeLDX += rect.width + 4;
|
|
28262
|
+
}
|
|
28263
|
+
annotation.element.setAttribute("transform", "translate("+annotationX+", -8)");
|
|
27784
28264
|
}
|
|
28265
|
+
// } else {
|
|
28266
|
+
// if (showAnnotation) {
|
|
28267
|
+
// var rect = annotation.element.getBoundingClientRect();
|
|
28268
|
+
// annotation.element.setAttribute("transform", "translate("+(3+controlDX)+", -12)");
|
|
28269
|
+
// controlDX += rect.width + 4;
|
|
28270
|
+
// }
|
|
27785
28271
|
}
|
|
27786
28272
|
} else {
|
|
27787
28273
|
annotation.element.parentNode.removeChild(annotation.element);
|
|
@@ -27837,15 +28323,25 @@ RED.view = (function() {
|
|
|
27837
28323
|
annotationGroup.setAttribute("class",opts.class || "");
|
|
27838
28324
|
evt.el.__annotations__.push({
|
|
27839
28325
|
id:id,
|
|
28326
|
+
node: evt.node,
|
|
27840
28327
|
element: annotationGroup
|
|
27841
28328
|
});
|
|
27842
|
-
|
|
28329
|
+
refreshAnnotationElement(id, evt.node, annotationGroup)
|
|
28330
|
+
evt.el.appendChild(annotationGroup);
|
|
28331
|
+
}
|
|
28332
|
+
|
|
28333
|
+
function refreshAnnotationElement(id, node, annotationGroup) {
|
|
28334
|
+
const opts = annotations[id];
|
|
28335
|
+
const annotation = opts.element(node);
|
|
27843
28336
|
if (opts.tooltip) {
|
|
27844
|
-
annotation.addEventListener("mouseenter", getAnnotationMouseEnter(annotation,
|
|
28337
|
+
annotation.addEventListener("mouseenter", getAnnotationMouseEnter(annotation, node, opts.tooltip));
|
|
27845
28338
|
annotation.addEventListener("mouseleave", annotationMouseLeave);
|
|
27846
28339
|
}
|
|
28340
|
+
if (annotationGroup.hasChildNodes()) {
|
|
28341
|
+
annotationGroup.removeChild(annotationGroup.firstChild)
|
|
28342
|
+
}
|
|
27847
28343
|
annotationGroup.appendChild(annotation);
|
|
27848
|
-
|
|
28344
|
+
|
|
27849
28345
|
}
|
|
27850
28346
|
|
|
27851
28347
|
|
|
@@ -33287,7 +33783,7 @@ RED.palette.editor = (function() {
|
|
|
33287
33783
|
}).done(function(data,textStatus,xhr) {
|
|
33288
33784
|
callback();
|
|
33289
33785
|
}).fail(function(xhr,textStatus,err) {
|
|
33290
|
-
callback(xhr);
|
|
33786
|
+
callback(xhr,textStatus,err);
|
|
33291
33787
|
});
|
|
33292
33788
|
}
|
|
33293
33789
|
function removeNodeModule(id,callback) {
|
|
@@ -34500,13 +34996,13 @@ RED.palette.editor = (function() {
|
|
|
34500
34996
|
});
|
|
34501
34997
|
|
|
34502
34998
|
if (!found_onremove) {
|
|
34503
|
-
let removeNotify = RED.notify(
|
|
34999
|
+
let removeNotify = RED.notify(RED._("palette.editor.confirm.removePlugin.body",{module:entry.name}),{
|
|
34504
35000
|
modal: true,
|
|
34505
35001
|
fixed: true,
|
|
34506
35002
|
type: 'warning',
|
|
34507
35003
|
buttons: [
|
|
34508
35004
|
{
|
|
34509
|
-
text: "
|
|
35005
|
+
text: RED._("palette.editor.confirm.button.understood"),
|
|
34510
35006
|
class:"primary",
|
|
34511
35007
|
click: function(e) {
|
|
34512
35008
|
removeNotify.close();
|
|
@@ -34559,9 +35055,28 @@ RED.palette.editor = (function() {
|
|
|
34559
35055
|
RED.actions.invoke("core:show-event-log");
|
|
34560
35056
|
});
|
|
34561
35057
|
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.id+" "+entry.version);
|
|
34562
|
-
installNodeModule(entry.id,entry.version,entry.pkg_url,function(xhr) {
|
|
35058
|
+
installNodeModule(entry.id,entry.version,entry.pkg_url,function(xhr, textStatus,err) {
|
|
34563
35059
|
spinner.remove();
|
|
34564
|
-
if (xhr) {
|
|
35060
|
+
if (err && xhr.status === 504) {
|
|
35061
|
+
var notification = RED.notify(RED._("palette.editor.errors.installTimeout"), {
|
|
35062
|
+
modal: true,
|
|
35063
|
+
fixed: true,
|
|
35064
|
+
buttons: [
|
|
35065
|
+
{
|
|
35066
|
+
text: RED._("common.label.close"),
|
|
35067
|
+
click: function() {
|
|
35068
|
+
notification.close();
|
|
35069
|
+
}
|
|
35070
|
+
},{
|
|
35071
|
+
text: RED._("eventLog.view"),
|
|
35072
|
+
click: function() {
|
|
35073
|
+
notification.close();
|
|
35074
|
+
RED.actions.invoke("core:show-event-log");
|
|
35075
|
+
}
|
|
35076
|
+
}
|
|
35077
|
+
]
|
|
35078
|
+
})
|
|
35079
|
+
} else if (xhr) {
|
|
34565
35080
|
if (xhr.responseJSON) {
|
|
34566
35081
|
var notification = RED.notify(RED._('palette.editor.errors.installFailed',{module: entry.id,message:xhr.responseJSON.message}),{
|
|
34567
35082
|
type: 'error',
|
|
@@ -36325,8 +36840,8 @@ RED.editor = (function() {
|
|
|
36325
36840
|
}
|
|
36326
36841
|
|
|
36327
36842
|
if (!isSameObj(old_env, new_env)) {
|
|
36328
|
-
editing_node.env = new_env;
|
|
36329
36843
|
editState.changes.env = editing_node.env;
|
|
36844
|
+
editing_node.env = new_env;
|
|
36330
36845
|
editState.changed = true;
|
|
36331
36846
|
}
|
|
36332
36847
|
|
|
@@ -41569,7 +42084,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
41569
42084
|
_monaco.languages.json.jsonDefaults.setDiagnosticsOptions(diagnosticOptions);
|
|
41570
42085
|
if(modeConfiguration) { _monaco.languages.json.jsonDefaults.setModeConfiguration(modeConfiguration); }
|
|
41571
42086
|
} catch (error) {
|
|
41572
|
-
console.warn("monaco - Error setting up json options",
|
|
42087
|
+
console.warn("monaco - Error setting up json options", error)
|
|
41573
42088
|
}
|
|
41574
42089
|
}
|
|
41575
42090
|
|
|
@@ -41581,7 +42096,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
41581
42096
|
if(htmlDefaults) { _monaco.languages.html.htmlDefaults.setOptions(htmlDefaults); }
|
|
41582
42097
|
if(handlebarDefaults) { _monaco.languages.html.handlebarDefaults.setOptions(handlebarDefaults); }
|
|
41583
42098
|
} catch (error) {
|
|
41584
|
-
console.warn("monaco - Error setting up html options",
|
|
42099
|
+
console.warn("monaco - Error setting up html options", error)
|
|
41585
42100
|
}
|
|
41586
42101
|
}
|
|
41587
42102
|
|
|
@@ -41601,7 +42116,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
41601
42116
|
if(lessDefaults_modeConfiguration) { _monaco.languages.css.cssDefaults.setDiagnosticsOptions(lessDefaults_modeConfiguration); }
|
|
41602
42117
|
if(scssDefaults_modeConfiguration) { _monaco.languages.css.cssDefaults.setDiagnosticsOptions(scssDefaults_modeConfiguration); }
|
|
41603
42118
|
} catch (error) {
|
|
41604
|
-
console.warn("monaco - Error setting up CSS/SCSS/LESS options",
|
|
42119
|
+
console.warn("monaco - Error setting up CSS/SCSS/LESS options", error)
|
|
41605
42120
|
}
|
|
41606
42121
|
}
|
|
41607
42122
|
|
|
@@ -45419,12 +45934,12 @@ RED.notifications = (function() {
|
|
|
45419
45934
|
if (newType) {
|
|
45420
45935
|
n.className = "red-ui-notification red-ui-notification-"+newType;
|
|
45421
45936
|
}
|
|
45422
|
-
|
|
45937
|
+
newTimeout = newOptions.hasOwnProperty('timeout')?newOptions.timeout:timeout
|
|
45423
45938
|
if (!fixed || newOptions.fixed === false) {
|
|
45424
|
-
newTimeout =
|
|
45939
|
+
newTimeout = newTimeout || 5000
|
|
45425
45940
|
}
|
|
45426
45941
|
if (newOptions.buttons) {
|
|
45427
|
-
var buttonSet = $('<div
|
|
45942
|
+
var buttonSet = $('<div class="ui-dialog-buttonset"></div>').appendTo(nn)
|
|
45428
45943
|
newOptions.buttons.forEach(function(buttonDef) {
|
|
45429
45944
|
var b = $('<button>').text(buttonDef.text).on("click", buttonDef.click).appendTo(buttonSet);
|
|
45430
45945
|
if (buttonDef.id) {
|
|
@@ -45470,6 +45985,15 @@ RED.notifications = (function() {
|
|
|
45470
45985
|
};
|
|
45471
45986
|
})());
|
|
45472
45987
|
n.timeoutid = window.setTimeout(n.close,timeout||5000);
|
|
45988
|
+
} else if (timeout) {
|
|
45989
|
+
$(n).on("click.red-ui-notification-close", (function() {
|
|
45990
|
+
var nn = n;
|
|
45991
|
+
return function() {
|
|
45992
|
+
nn.hideNotification();
|
|
45993
|
+
window.clearTimeout(nn.timeoutid);
|
|
45994
|
+
};
|
|
45995
|
+
})());
|
|
45996
|
+
n.timeoutid = window.setTimeout(n.hideNotification,timeout||5000);
|
|
45473
45997
|
}
|
|
45474
45998
|
currentNotifications.push(n);
|
|
45475
45999
|
if (options.id) {
|
|
@@ -48502,7 +49026,7 @@ RED.subflow = (function() {
|
|
|
48502
49026
|
break;
|
|
48503
49027
|
case "conf-types":
|
|
48504
49028
|
item.value = input.val()
|
|
48505
|
-
item.type =
|
|
49029
|
+
item.type = "conf-type"
|
|
48506
49030
|
}
|
|
48507
49031
|
if (ui.type === "cred" || item.type !== data.parent.type || item.value !== data.parent.value) {
|
|
48508
49032
|
env.push(item);
|
|
@@ -52355,7 +52879,7 @@ RED.projects.settings = (function() {
|
|
|
52355
52879
|
var notInstalledCount = 0;
|
|
52356
52880
|
|
|
52357
52881
|
for (var m in modulesInUse) {
|
|
52358
|
-
if (modulesInUse.hasOwnProperty(m)) {
|
|
52882
|
+
if (modulesInUse.hasOwnProperty(m) && !activeProject.dependencies.hasOwnProperty(m)) {
|
|
52359
52883
|
depsList.editableList('addItem',{
|
|
52360
52884
|
id: modulesInUse[m].module,
|
|
52361
52885
|
version: modulesInUse[m].version,
|
|
@@ -52375,8 +52899,8 @@ RED.projects.settings = (function() {
|
|
|
52375
52899
|
|
|
52376
52900
|
if (activeProject.dependencies) {
|
|
52377
52901
|
for (var m in activeProject.dependencies) {
|
|
52378
|
-
if (activeProject.dependencies.hasOwnProperty(m)
|
|
52379
|
-
var installed = !!RED.nodes.registry.getModule(m);
|
|
52902
|
+
if (activeProject.dependencies.hasOwnProperty(m)) {
|
|
52903
|
+
var installed = !!RED.nodes.registry.getModule(m) && activeProject.dependencies[m] === modulesInUse[m].version;
|
|
52380
52904
|
depsList.editableList('addItem',{
|
|
52381
52905
|
id: m,
|
|
52382
52906
|
version: activeProject.dependencies[m], //RED.nodes.registry.getModule(module).version,
|