mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3156 from node-red/change-clone
Add option to deep-clone properties in Change node
This commit is contained in:
commit
81a278dd8c
@ -109,9 +109,41 @@
|
|||||||
var del = this._("change.action.delete");
|
var del = this._("change.action.delete");
|
||||||
var move = this._("change.action.move");
|
var move = this._("change.action.move");
|
||||||
var to = this._("change.action.to");
|
var to = this._("change.action.to");
|
||||||
|
var toValueLabel = this._("change.action.toValue",to);
|
||||||
var search = this._("change.action.search");
|
var search = this._("change.action.search");
|
||||||
var replace = this._("change.action.replace");
|
var replace = this._("change.action.replace");
|
||||||
var regex = this._("change.label.regex");
|
var regex = this._("change.label.regex");
|
||||||
|
var deepCopyLabel = this._("change.label.deepCopy");
|
||||||
|
|
||||||
|
function createPropertyValue(row2_1,row2_2) {
|
||||||
|
var propValInput = $('<input/>',{class:"node-input-rule-property-value",type:"text"})
|
||||||
|
.appendTo(row2_1)
|
||||||
|
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env']});
|
||||||
|
|
||||||
|
var dcLabel = $('<label style="padding-left: 130px; display: flex; align-items: center "></label>').appendTo(row2_2);
|
||||||
|
var deepCopy = $('<input type="checkbox" class="node-input-rule-property-deepCopy" style="width: auto; margin: 0 6px 0 0">').appendTo(dcLabel)
|
||||||
|
$('<span>').text(deepCopyLabel).appendTo(dcLabel)
|
||||||
|
|
||||||
|
propValInput.on("change", function(evt,type,val) {
|
||||||
|
row2_2.toggle(type === "msg" || type === "flow" || type === "global" || type === "env");
|
||||||
|
})
|
||||||
|
return [propValInput, deepCopy];
|
||||||
|
}
|
||||||
|
function createFromValue(row3_1) {
|
||||||
|
return $('<input/>',{class:"node-input-rule-property-search-value",type:"text"})
|
||||||
|
.appendTo(row3_1)
|
||||||
|
.typedInput({default:'str',types:['msg','flow','global','str','re','num','bool','env']});
|
||||||
|
}
|
||||||
|
function createToValue(row3_2) {
|
||||||
|
return $('<input/>',{class:"node-input-rule-property-replace-value",type:"text"})
|
||||||
|
.appendTo(row3_2)
|
||||||
|
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','env']});
|
||||||
|
}
|
||||||
|
function createMoveValue(row4) {
|
||||||
|
return $('<input/>',{class:"node-input-rule-property-move-value",type:"text"})
|
||||||
|
.appendTo(row4)
|
||||||
|
.typedInput({default:'msg',types:['msg','flow','global']});
|
||||||
|
}
|
||||||
|
|
||||||
$('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({
|
$('#node-input-rule-container').css('min-height','150px').css('min-width','450px').editableList({
|
||||||
addItem: function(container,i,opt) {
|
addItem: function(container,i,opt) {
|
||||||
@ -139,10 +171,10 @@
|
|||||||
whiteSpace: 'nowrap'
|
whiteSpace: 'nowrap'
|
||||||
});
|
});
|
||||||
let fragment = document.createDocumentFragment();
|
let fragment = document.createDocumentFragment();
|
||||||
var row1 = $('<div/>',{style:"display:flex;"}).appendTo(fragment);
|
var row1 = $('<div/>',{style:"display:flex; align-items: baseline"}).appendTo(fragment);
|
||||||
var row2 = $('<div/>',{style:"display:flex;margin-top:8px;"}).appendTo(fragment);
|
var row2 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
|
||||||
var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
|
var row3 = $('<div/>',{style:"margin-top:8px;"}).appendTo(fragment);
|
||||||
var row4 = $('<div/>',{style:"display:flex;margin-top:8px;"}).appendTo(fragment);
|
var row4 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(fragment);
|
||||||
|
|
||||||
var selectField = $('<select/>',{class:"node-input-rule-type",style:"width:110px; margin-right:10px;"}).appendTo(row1);
|
var selectField = $('<select/>',{class:"node-input-rule-type",style:"width:110px; margin-right:10px;"}).appendTo(row1);
|
||||||
var selectOptions = [{v:"set",l:set},{v:"change",l:change},{v:"delete",l:del},{v:"move",l:move}];
|
var selectOptions = [{v:"set",l:set},{v:"change",l:change},{v:"delete",l:del},{v:"move",l:move}];
|
||||||
@ -154,48 +186,27 @@
|
|||||||
.appendTo(row1)
|
.appendTo(row1)
|
||||||
.typedInput({types:['msg','flow','global']});
|
.typedInput({types:['msg','flow','global']});
|
||||||
|
|
||||||
|
var row2_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row2);
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
||||||
.text(to)
|
.text(toValueLabel)
|
||||||
.appendTo(row2);
|
.appendTo(row2_1);
|
||||||
|
|
||||||
function createPropertyValue() {
|
var row2_2 = $('<div/>', {style:"margin-top: 4px;"}).appendTo(row2);
|
||||||
return $('<input/>',{class:"node-input-rule-property-value",type:"text"})
|
|
||||||
.appendTo(row2)
|
|
||||||
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','date','jsonata','env']});
|
|
||||||
}
|
|
||||||
|
|
||||||
var row3_1 = $('<div/>', {style:"display:flex;"}).appendTo(row3);
|
var row3_1 = $('<div/>', {style:"display:flex;align-items: baseline"}).appendTo(row3);
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
||||||
.text(search)
|
.text(search)
|
||||||
.appendTo(row3_1);
|
.appendTo(row3_1);
|
||||||
|
|
||||||
function createFromValue() {
|
var row3_2 = $('<div/>',{style:"display:flex;margin-top:8px;align-items: baseline"}).appendTo(row3);
|
||||||
return $('<input/>',{class:"node-input-rule-property-search-value",type:"text"})
|
|
||||||
.appendTo(row3_1)
|
|
||||||
.typedInput({default:'str',types:['msg','flow','global','str','re','num','bool','env']});
|
|
||||||
}
|
|
||||||
|
|
||||||
var row3_2 = $('<div/>',{style:"display:flex;margin-top:8px;"}).appendTo(row3);
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
||||||
.text(replace)
|
.text(replace)
|
||||||
.appendTo(row3_2);
|
.appendTo(row3_2);
|
||||||
|
|
||||||
function createToValue() {
|
|
||||||
return $('<input/>',{class:"node-input-rule-property-replace-value",type:"text"})
|
|
||||||
.appendTo(row3_2)
|
|
||||||
.typedInput({default:'str',types:['msg','flow','global','str','num','bool','json','bin','env']});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
$('<div/>',{style:"display:inline-block;text-align:right; width:120px; padding-right:10px; box-sizing:border-box;"})
|
||||||
.text(to)
|
.text(to)
|
||||||
.appendTo(row4);
|
.appendTo(row4);
|
||||||
|
|
||||||
function createMoveValue() {
|
|
||||||
return $('<input/>',{class:"node-input-rule-property-move-value",type:"text"})
|
|
||||||
.appendTo(row4)
|
|
||||||
.typedInput({default:'msg',types:['msg','flow','global']});
|
|
||||||
}
|
|
||||||
|
|
||||||
let propertyValue = null;
|
let propertyValue = null;
|
||||||
let fromValue = null;
|
let fromValue = null;
|
||||||
let toValue = null;
|
let toValue = null;
|
||||||
@ -218,7 +229,9 @@
|
|||||||
|
|
||||||
if (type == "set") {
|
if (type == "set") {
|
||||||
if(!propertyValue) {
|
if(!propertyValue) {
|
||||||
propertyValue = createPropertyValue();
|
var parts = createPropertyValue(row2_1, row2_2);
|
||||||
|
propertyValue = parts[0];
|
||||||
|
deepCopy = parts[1];
|
||||||
}
|
}
|
||||||
propertyValue.typedInput('show');
|
propertyValue.typedInput('show');
|
||||||
row2.show();
|
row2.show();
|
||||||
@ -226,11 +239,11 @@
|
|||||||
row4.hide();
|
row4.hide();
|
||||||
} else if (type == "change") {
|
} else if (type == "change") {
|
||||||
if(!fromValue) {
|
if(!fromValue) {
|
||||||
fromValue = createFromValue();
|
fromValue = createFromValue(row3_1);
|
||||||
}
|
}
|
||||||
fromValue.typedInput('show');
|
fromValue.typedInput('show');
|
||||||
if(!toValue) {
|
if(!toValue) {
|
||||||
toValue = createToValue();
|
toValue = createToValue(row3_2);
|
||||||
}
|
}
|
||||||
toValue.typedInput('show');
|
toValue.typedInput('show');
|
||||||
row2.hide();
|
row2.hide();
|
||||||
@ -242,7 +255,7 @@
|
|||||||
row4.hide();
|
row4.hide();
|
||||||
} else if (type == "move") {
|
} else if (type == "move") {
|
||||||
if(!moveValue) {
|
if(!moveValue) {
|
||||||
moveValue = createMoveValue();
|
moveValue = createMoveValue(row4);
|
||||||
}
|
}
|
||||||
moveValue.typedInput('show');
|
moveValue.typedInput('show');
|
||||||
row2.hide();
|
row2.hide();
|
||||||
@ -256,26 +269,29 @@
|
|||||||
propertyName.typedInput('type',rule.pt);
|
propertyName.typedInput('type',rule.pt);
|
||||||
if (rule.t == "set") {
|
if (rule.t == "set") {
|
||||||
if(!propertyValue) {
|
if(!propertyValue) {
|
||||||
propertyValue = createPropertyValue();
|
var parts = createPropertyValue(row2_1, row2_2);
|
||||||
|
propertyValue = parts[0];
|
||||||
|
deepCopy = parts[1];
|
||||||
}
|
}
|
||||||
propertyValue.typedInput('value',rule.to);
|
propertyValue.typedInput('value',rule.to);
|
||||||
propertyValue.typedInput('type',rule.tot);
|
propertyValue.typedInput('type',rule.tot);
|
||||||
|
deepCopy.prop("checked", !!rule.dc);
|
||||||
}
|
}
|
||||||
if (rule.t == "move") {
|
if (rule.t == "move") {
|
||||||
if(!moveValue) {
|
if(!moveValue) {
|
||||||
moveValue = createMoveValue();
|
moveValue = createMoveValue(row4);
|
||||||
}
|
}
|
||||||
moveValue.typedInput('value',rule.to);
|
moveValue.typedInput('value',rule.to);
|
||||||
moveValue.typedInput('type',rule.tot);
|
moveValue.typedInput('type',rule.tot);
|
||||||
}
|
}
|
||||||
if (rule.t == "change") {
|
if (rule.t == "change") {
|
||||||
if(!fromValue) {
|
if(!fromValue) {
|
||||||
fromValue = createFromValue();
|
fromValue = createFromValue(row3_1);
|
||||||
}
|
}
|
||||||
fromValue.typedInput('value',rule.from);
|
fromValue.typedInput('value',rule.from);
|
||||||
fromValue.typedInput('type',rule.fromt);
|
fromValue.typedInput('type',rule.fromt);
|
||||||
if (!toValue) {
|
if (!toValue) {
|
||||||
toValue = createToValue();
|
toValue = createToValue(row3_2);
|
||||||
}
|
}
|
||||||
toValue.typedInput('value',rule.to);
|
toValue.typedInput('value',rule.to);
|
||||||
toValue.typedInput('type',rule.tot);
|
toValue.typedInput('type',rule.tot);
|
||||||
@ -331,6 +347,9 @@
|
|||||||
if (type === "set") {
|
if (type === "set") {
|
||||||
r.to = rule.find(".node-input-rule-property-value").typedInput('value');
|
r.to = rule.find(".node-input-rule-property-value").typedInput('value');
|
||||||
r.tot = rule.find(".node-input-rule-property-value").typedInput('type');
|
r.tot = rule.find(".node-input-rule-property-value").typedInput('type');
|
||||||
|
if (rule.find(".node-input-rule-property-deepCopy").prop("checked")) {
|
||||||
|
r.dc = true;
|
||||||
|
}
|
||||||
} else if (type === "move") {
|
} else if (type === "move") {
|
||||||
r.to = rule.find(".node-input-rule-property-move-value").typedInput('value');
|
r.to = rule.find(".node-input-rule-property-move-value").typedInput('value');
|
||||||
r.tot = rule.find(".node-input-rule-property-move-value").typedInput('type');
|
r.tot = rule.find(".node-input-rule-property-move-value").typedInput('type');
|
||||||
|
@ -206,6 +206,9 @@ module.exports = function(RED) {
|
|||||||
node.error(err, msg);
|
node.error(err, msg);
|
||||||
return done(undefined,null);
|
return done(undefined,null);
|
||||||
} else {
|
} else {
|
||||||
|
if (rule.dc) {
|
||||||
|
value = RED.util.cloneMessage(value);
|
||||||
|
}
|
||||||
getFromValue(msg,rule,(err,fromParts) => {
|
getFromValue(msg,rule,(err,fromParts) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
node.error(err, msg);
|
node.error(err, msg);
|
||||||
|
@ -713,13 +713,15 @@
|
|||||||
"delete": "delete __property__",
|
"delete": "delete __property__",
|
||||||
"move": "move __property__",
|
"move": "move __property__",
|
||||||
"changeCount": "change: __count__ rules",
|
"changeCount": "change: __count__ rules",
|
||||||
"regex": "Use regular expressions"
|
"regex": "Use regular expressions",
|
||||||
|
"deepCopy": "Deep copy value"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"set": "Set",
|
"set": "Set",
|
||||||
"change": "Change",
|
"change": "Change",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"move": "Move",
|
"move": "Move",
|
||||||
|
"toValue": "to the value",
|
||||||
"to": "to",
|
"to": "to",
|
||||||
"search": "Search for",
|
"search": "Search for",
|
||||||
"replace": "Replace with"
|
"replace": "Replace with"
|
||||||
|
@ -615,7 +615,6 @@ describe('change Node', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('changes the value using jsonata', function(done) {
|
it('changes the value using jsonata', function(done) {
|
||||||
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$length(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]},
|
var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$length(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
@ -847,7 +846,36 @@ describe('change Node', function() {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('deep copies the property if selected', function(done) {
|
||||||
|
|
||||||
|
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"set","p":"payload","pt":"msg","to":"source","tot":"msg","dc":true}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||||
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
|
helper.load(changeNode, flow, function() {
|
||||||
|
var changeNode1 = helper.getNode("changeNode1");
|
||||||
|
var helperNode1 = helper.getNode("helperNode1");
|
||||||
|
helperNode1.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
// Check payload has been set to a clone of original object
|
||||||
|
// - the JSON should match
|
||||||
|
JSON.stringify(msg.payload).should.equal(JSON.stringify(originalObject))
|
||||||
|
// - but they must be different objects
|
||||||
|
msg.payload.should.not.equal(originalObject);
|
||||||
|
|
||||||
|
// Modify nested property of original object
|
||||||
|
originalObject.a.c = 3;
|
||||||
|
// Check that modification hasn't happened on cloned prop
|
||||||
|
msg.payload.a.should.not.have.property('c');
|
||||||
|
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var originalObject = { a: { b: 2 } }
|
||||||
|
changeNode1.receive({source:originalObject});
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
});
|
});
|
||||||
describe('#change', function() {
|
describe('#change', function() {
|
||||||
it('changes the value of the message property', function(done) {
|
it('changes the value of the message property', function(done) {
|
||||||
|
Loading…
Reference in New Issue
Block a user