mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge pull request #4797 from GogoVega/config-node-history
Add config node to `RED.history` and handle `changed` prop
This commit is contained in:
commit
93102837dd
@ -808,6 +808,17 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldCreds = {};
|
||||||
|
if (editing_node._def.credentials) {
|
||||||
|
for (const prop in editing_node._def.credentials) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(editing_node._def.credentials, prop)) {
|
||||||
|
if (prop in editing_node.credentials) {
|
||||||
|
oldCreds[prop] = editing_node.credentials[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const rc = editing_node._def.oneditsave.call(editing_node);
|
const rc = editing_node._def.oneditsave.call(editing_node);
|
||||||
if (rc === true) {
|
if (rc === true) {
|
||||||
@ -839,6 +850,21 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editing_node._def.credentials) {
|
||||||
|
for (const prop in editing_node._def.credentials) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(editing_node._def.credentials, prop)) {
|
||||||
|
if (oldCreds[prop] !== editing_node.credentials[prop]) {
|
||||||
|
if (editing_node.credentials[prop] === '__PWRD__') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
editState.changes.credentials = editState.changes.credentials || {};
|
||||||
|
editState.changes.credentials[prop] = oldCreds[prop];
|
||||||
|
editState.changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1481,134 +1507,181 @@ RED.editor = (function() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "node-config-dialog-ok",
|
id: "node-config-dialog-ok",
|
||||||
text: adding?RED._("editor.configAdd"):RED._("editor.configUpdate"),
|
text: adding ? RED._("editor.configAdd") : RED._("editor.configUpdate"),
|
||||||
class: "primary",
|
class: "primary",
|
||||||
click: function() {
|
click: function() {
|
||||||
var editState = {
|
// TODO: Already defined
|
||||||
|
const configProperty = name;
|
||||||
|
const configType = type;
|
||||||
|
const configTypeDef = RED.nodes.getType(configType);
|
||||||
|
|
||||||
|
const wasChanged = editing_config_node.changed;
|
||||||
|
const editState = {
|
||||||
changes: {},
|
changes: {},
|
||||||
changed: false,
|
changed: false,
|
||||||
outputMap: null
|
outputMap: null
|
||||||
};
|
};
|
||||||
var configProperty = name;
|
|
||||||
var configId = editing_config_node.id;
|
// Call `oneditsave` and search for changes
|
||||||
var configType = type;
|
handleEditSave(editing_config_node, editState);
|
||||||
var configAdding = adding;
|
|
||||||
var configTypeDef = RED.nodes.getType(configType);
|
|
||||||
var d;
|
|
||||||
var input;
|
|
||||||
|
|
||||||
if (configTypeDef.oneditsave) {
|
// Search for changes in the edit box (panes)
|
||||||
try {
|
activeEditPanes.forEach(function (pane) {
|
||||||
configTypeDef.oneditsave.call(editing_config_node);
|
|
||||||
} catch(err) {
|
|
||||||
console.warn("oneditsave",editing_config_node.id,editing_config_node.type,err.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (d in configTypeDef.defaults) {
|
|
||||||
if (configTypeDef.defaults.hasOwnProperty(d)) {
|
|
||||||
var newValue;
|
|
||||||
input = $("#node-config-input-"+d);
|
|
||||||
if (input.attr('type') === "checkbox") {
|
|
||||||
newValue = input.prop('checked');
|
|
||||||
} else if ("format" in configTypeDef.defaults[d] && configTypeDef.defaults[d].format !== "" && input[0].nodeName === "DIV") {
|
|
||||||
newValue = input.text();
|
|
||||||
} else {
|
|
||||||
newValue = input.val();
|
|
||||||
}
|
|
||||||
if (newValue != null && newValue !== editing_config_node[d]) {
|
|
||||||
if (editing_config_node._def.defaults[d].type) {
|
|
||||||
if (newValue == "_ADD_") {
|
|
||||||
newValue = "";
|
|
||||||
}
|
|
||||||
// Change to a related config node
|
|
||||||
var configNode = RED.nodes.node(editing_config_node[d]);
|
|
||||||
if (configNode) {
|
|
||||||
var users = configNode.users;
|
|
||||||
users.splice(users.indexOf(editing_config_node),1);
|
|
||||||
RED.events.emit("nodes:change",configNode);
|
|
||||||
}
|
|
||||||
configNode = RED.nodes.node(newValue);
|
|
||||||
if (configNode) {
|
|
||||||
configNode.users.push(editing_config_node);
|
|
||||||
RED.events.emit("nodes:change",configNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
editing_config_node[d] = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activeEditPanes.forEach(function(pane) {
|
|
||||||
if (pane.apply) {
|
if (pane.apply) {
|
||||||
pane.apply.call(pane, editState);
|
pane.apply.call(pane, editState);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
editing_config_node.label = configTypeDef.label;
|
// TODO: Why?
|
||||||
|
editing_config_node.label = configTypeDef.label
|
||||||
var scope = $("#red-ui-editor-config-scope").val();
|
|
||||||
editing_config_node.z = scope;
|
|
||||||
|
|
||||||
|
// Check if disabled has changed
|
||||||
if ($("#node-config-input-node-disabled").prop('checked')) {
|
if ($("#node-config-input-node-disabled").prop('checked')) {
|
||||||
if (editing_config_node.d !== true) {
|
if (editing_config_node.d !== true) {
|
||||||
|
editState.changes.d = editing_config_node.d;
|
||||||
|
editState.changed = true;
|
||||||
editing_config_node.d = true;
|
editing_config_node.d = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (editing_config_node.d === true) {
|
if (editing_config_node.d === true) {
|
||||||
|
editState.changes.d = editing_config_node.d;
|
||||||
|
editState.changed = true;
|
||||||
delete editing_config_node.d;
|
delete editing_config_node.d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: must be undefined if no scope used
|
||||||
|
const scope = $("#red-ui-editor-config-scope").val() || undefined;
|
||||||
|
|
||||||
|
// Check if the scope has changed
|
||||||
|
if (editing_config_node.z !== scope) {
|
||||||
|
editState.changes.z = editing_config_node.z;
|
||||||
|
editState.changed = true;
|
||||||
|
editing_config_node.z = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for nodes that use this config node that are no longer
|
||||||
|
// in scope, so must be removed
|
||||||
|
const historyEvents = [];
|
||||||
if (scope) {
|
if (scope) {
|
||||||
// Search for nodes that use this one that are no longer
|
const newUsers = editing_config_node.users.filter(function (node) {
|
||||||
// in scope, so must be removed
|
let keepNode = false;
|
||||||
editing_config_node.users = editing_config_node.users.filter(function(n) {
|
let nodeModified = null;
|
||||||
var keep = true;
|
|
||||||
for (var d in n._def.defaults) {
|
for (const d in node._def.defaults) {
|
||||||
if (n._def.defaults.hasOwnProperty(d)) {
|
if (node._def.defaults.hasOwnProperty(d)) {
|
||||||
if (n._def.defaults[d].type === editing_config_node.type &&
|
if (node._def.defaults[d].type === editing_config_node.type) {
|
||||||
n[d] === editing_config_node.id &&
|
if (node[d] === editing_config_node.id) {
|
||||||
n.z !== scope) {
|
if (node.z === editing_config_node.z) {
|
||||||
keep = false;
|
// The node is kept only if at least one property uses
|
||||||
// Remove the reference to this node
|
// this config node in the correct scope.
|
||||||
// and revalidate
|
keepNode = true;
|
||||||
n[d] = null;
|
} else {
|
||||||
n.dirty = true;
|
if (!nodeModified) {
|
||||||
n.changed = true;
|
nodeModified = {
|
||||||
validateNode(n);
|
t: "edit",
|
||||||
|
node: node,
|
||||||
|
changes: { [d]: node[d] },
|
||||||
|
changed: node.changed,
|
||||||
|
dirty: node.dirty
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
nodeModified.changes[d] = node[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the reference to the config node
|
||||||
|
node[d] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return keep;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configAdding) {
|
// Add the node modified to the history
|
||||||
RED.nodes.add(editing_config_node);
|
if (nodeModified) {
|
||||||
}
|
historyEvents.push(nodeModified);
|
||||||
|
|
||||||
validateNode(editing_config_node);
|
|
||||||
var validatedNodes = {};
|
|
||||||
validatedNodes[editing_config_node.id] = true;
|
|
||||||
|
|
||||||
var userStack = editing_config_node.users.slice();
|
|
||||||
while(userStack.length > 0) {
|
|
||||||
var user = userStack.pop();
|
|
||||||
if (!validatedNodes[user.id]) {
|
|
||||||
validatedNodes[user.id] = true;
|
|
||||||
if (user.users) {
|
|
||||||
userStack = userStack.concat(user.users);
|
|
||||||
}
|
}
|
||||||
validateNode(user);
|
|
||||||
|
// Mark as changed and revalidate this node
|
||||||
|
if (!keepNode) {
|
||||||
|
node.changed = true;
|
||||||
|
node.dirty = true;
|
||||||
|
validateNode(node);
|
||||||
|
RED.events.emit("nodes:change", node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keepNode;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if users are changed
|
||||||
|
if (editing_config_node.users.length !== newUsers.length) {
|
||||||
|
editState.changes.users = editing_config_node.users;
|
||||||
|
editState.changed = true;
|
||||||
|
editing_config_node.users = newUsers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RED.nodes.dirty(true);
|
|
||||||
RED.view.redraw(true);
|
if (editState.changed) {
|
||||||
if (!configAdding) {
|
// Set the congig node as changed
|
||||||
RED.events.emit("editor:save",editing_config_node);
|
editing_config_node.changed = true;
|
||||||
RED.events.emit("nodes:change",editing_config_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now, validate the config node
|
||||||
|
validateNode(editing_config_node);
|
||||||
|
|
||||||
|
// And validate nodes using this config node too
|
||||||
|
const validatedNodes = new Set();
|
||||||
|
const userStack = editing_config_node.users.slice();
|
||||||
|
|
||||||
|
validatedNodes.add(editing_config_node.id);
|
||||||
|
while (userStack.length) {
|
||||||
|
const node = userStack.pop();
|
||||||
|
if (!validatedNodes.has(node.id)) {
|
||||||
|
validatedNodes.add(node.id);
|
||||||
|
if (node.users) {
|
||||||
|
userStack.push(...node.users);
|
||||||
|
}
|
||||||
|
validateNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let historyEvent = {
|
||||||
|
t: "edit",
|
||||||
|
node: editing_config_node,
|
||||||
|
changes: editState.changes,
|
||||||
|
changed: wasChanged,
|
||||||
|
dirty: RED.nodes.dirty()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (historyEvents.length) {
|
||||||
|
// Need a multi events
|
||||||
|
historyEvent = {
|
||||||
|
t: "multi",
|
||||||
|
events: [historyEvent].concat(historyEvents),
|
||||||
|
dirty: historyEvent.dirty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adding) {
|
||||||
|
// This event is triggered when the edit box is saved,
|
||||||
|
// regardless of whether there are any modifications.
|
||||||
|
RED.events.emit("editor:save", editing_config_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editState.changed) {
|
||||||
|
if (adding) {
|
||||||
|
RED.history.push({ t: "add", nodes: [editing_config_node.id], dirty: RED.nodes.dirty() });
|
||||||
|
// Add the new config node and trigger the `nodes:add` event
|
||||||
|
RED.nodes.add(editing_config_node);
|
||||||
|
} else {
|
||||||
|
RED.history.push(historyEvent);
|
||||||
|
RED.events.emit("nodes:change", editing_config_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
|
||||||
RED.tray.close(function() {
|
RED.tray.close(function() {
|
||||||
var filter = null;
|
var filter = null;
|
||||||
// when editing a config via subflow edit panel, the `configProperty` will not
|
// when editing a config via subflow edit panel, the `configProperty` will not
|
||||||
|
Loading…
x
Reference in New Issue
Block a user