Object.assign make duplicate when post a request - javascript

I create a ticket using zendesk but I didn't know why this happens
here is node js code:
config.js
baseTicketObject: {
'comment': {
'body': null,
},
'requester': {
'name': null,
'email': null,
},
'custom_fields': [],
},
create ticket api
function createTicketObjectFromRequest(req) {
const requestBody = req.body;
console.log('requestBody', requestBody);
console.log('config.baseTicketObject', config.baseTicketObject);
const ticket = Object.assign(config.baseTicketObject, {});
//console.log('ticket', ticket);
const {
messageBody, email, name, customFields,
} = requestBody;
//console.log('ticket.custom_fields', ticket.custom_fields);
// Request must contain a name, email and body
ticket.requester.name = name;
ticket.requester.email = email;
ticket.comment.body = messageBody;
if (req.user && req.user.id) {
ticket.custom_fields.push(createCustomFieldObject(config.customFieldNameToZendeskFieldIdMapping['userId'], Number(req.user.id)));
}
Object.keys(config.customFieldNameToZendeskFieldIdMapping).forEach((fieldName) => {
if (config.customFieldNameToZendeskFieldIdMapping[fieldName] === config.customFieldNameToZendeskFieldIdMapping.userId) {
return;
}
//console.log('fieldName', fieldName);
const mappedCustomFieldId = config.customFieldNameToZendeskFieldIdMapping[fieldName];
if (mappedCustomFieldId) {
ticket.custom_fields.push(createCustomFieldObject(mappedCustomFieldId, !customFields[fieldName] ? '' : customFields[fieldName]));
}
});
return { ticket: ticket };
}
whenever I post a request the config.baseTicketObject will keep all items i pushed before like this
config.baseTicketObject { comment: { body: null },
requester: { name: null, email: null },
custom_fields: [] }
-------------------------------------
config.baseTicketObject { comment: { body: 'dgfhdgfhdgfh dgfhdfghdfg' },
requester: { name: 'test other', email: 'tranthiphuonghue96#yopmail.com' },
custom_fields:
[ { id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' } ] }
---------------------------------------------------------
config.baseTicketObject { comment: { body: 'dgfhdgfhdgfh dgfhdfghdfg' },
requester: { name: 'test other', email: 'tranthiphuonghue96#yopmail.com' },
custom_fields:
[ { id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' },
{ id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' } ] }
I don't know why the config.baseTicketObject like that, please help.

Reverse parameters order in Object.assing.
You have
Object.assign(config.baseTicketObject, {});
but should be
Object.assign({}, config.baseTicketObject);
Object.assign syntax
Object.assign(target, ...sources)
In your case
const ticket = Object.assign({}, config.baseTicketObject);
Edit:
Add
ticket.custom_fields = [];
after
const ticket = Object.assign({}, config.baseTicketObject);
because Object.assign create shallow copy, witch mean that ticket.custom_fields still holds reference to original array object from config.baseTicketObject.custom_fields

Related

How to construct an array of object to unique array of object

I have an array of object like this
let data =
[
{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
]
and my expect array of objects
let result =
[
{
label: 'book',
username: 'john',
category: 'education'
},
{
label: 'car',
username: 'doe',
category: 'automotive'
},
{
label: 'shoes',
username: 'cena',
category: 'fashion'
},
]
Just a simple for loop is probably the clearest. Here storing each object in a temp variable to avoid having to access the end of the result array every iteration, and abstracting the size into a variable.
let data = [{ text: 'label' }, { text: 'username' }, { text: 'category' }, { text: 'book' }, { text: 'john' }, { text: 'education' }, { text: 'car' }, { text: 'doe' }, { text: 'automotive' }, { text: 'shoes' }, { text: 'cena' }, { text: 'fashion' },];
const size = 3;
const result = [];
for (let temp, i = size; i < data.length; i++) {
if (i % size === 0) {
result.push(temp = {});
}
temp[data[i % size].text] = data[i].text;
}
console.log(result)
How about a switch-case with a modulo % operator to check for the current key:
const transformData = (data) => {
let result = [];
let tmpObj = {};
data.forEach((element, idx) => {
switch (idx % 3) {
case 0:
tmpObj["label"] = element.text;
break;
case 1:
tmpObj["username"] = element.text;
break;
case 2:
result.push({ ...tmpObj,
category: element.text
});
tmpObj = {};
break;
default:
break;
}
});
return result;
};
console.log(transformData(getSampleData()));
function getSampleData() {
return [{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
];
}
According to your data,the top 3 records are property name,others are data,so we can use Array.slice() to get the property names
Then we can use Array.reduce() to convert the left data
let keys = data.slice(0,3).map(v => v.text)
let result = data.slice(3).reduce((a,c,i) =>{
let key = keys[i%3]
if(i%keys.length ==0){
let obj = {}
obj[key] = c.text
a.push(obj)
}else{
a.at(-1)[key]=c.text
}
return a
},[])
console.log(result)
let data =
[
{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
]
let keys = Object.values(data.slice(0,3)).map(v => v.text)
let result = data.slice(3).reduce((a,c,i) =>{
let key = keys[i%3]
if(i%keys.length ==0){
let obj = {}
obj[key] = c.text
a.push(obj)
}else{
a.at(-1)[key]=c.text
}
return a
},[])
console.log(result)

Unable update the nested state

I am trying to update the state, but the state is not getting updated as expected. Partially gets updated.
I need help in updating the updatedData data.
My state is as below.
this.state = {
userData: {
accounts: { '82345': 'Data 1' },
jobTitle: { '79438': 'Data 2' },
state: { '82099': 'Data 3' },
country: { '82008': 'Data 4' },
},
updatedData: {
firstName: ‘Parul’,
lastName: ‘Rathod’,
mail: parulRathod#gmail.com,
accounts: '',
jobTitle: '',
state: '',
country: '',
},
};
}
I need the data to be saved as
accounts: { label: 'Data 1', value: '82345' },
jobTitle: { label: 'Data 2', value: '79438' },
state: { label: 'Data 3', value: '82099' },
country: { label: 'Data 4', value: '82008' },
I have tried using the below method to do the required steps, but only country gets updated, and the rest remains as the previous state.
setUserData = () => {
for (const key of Object.keys(this.state.userData)) {
if(typeof (this.state.userData[key]) === 'object') {
const seperator = this.state.userData[key];
if(seperator) {
const values = Object.values(seperator);
const keys = Object.keys(seperator);
const data = { label: values[0], value: keys[0] };
if (key === 'country') {
this.setState({
updatedData: {
...this.state.updatedData,
country: data,
},
});
} else if (key === 'accounts') {
this.setState({
updatedData: {
...this.state.updatedData,
accounts: data,
},
});
} else if (key === 'state') {
this.setState({
updatedData: {
...this.state.updatedData,
state: data,
},
});
} else if (key === 'jobTitle') {
this.setState({
updatedData: {
...this.state.updatedData,
jobTitle: data,
},
});
}
}
}
}
}

How to remove TextRow and add a string to JSON in NodeJs

I want to remove TextRow and add a string(true) to JSON in NodeJs. I have added below my code.
NodeJs Code:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
let key = obj[property]
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
}
group data :
[
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
TextRow { name: '/sales', email: '111#gmail.com' },
TextRow { name: '/sales', email: '222#gmail.com' },
TextRow { name: '/sales', email: '333#gmail.com' },
TextRow { name: '/sales', email: '444#gmail.com' },
TextRow { name: '/finance', email: '333#gmail.com' },
TextRow { name: '/finance', email: '444#gmail.com' },
]
My output:
{
'/products': [
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
],
'/sales': [
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
TextRow { name: '/products', email: '333#gmail.com' },
TextRow { name: '/products', email: '444#gmail.com' },
],
'/products': [
TextRow { name: '/products', email: '333#gmail.com' },
TextRow { name: '/products', email: '444#gmail.com' },
],
}
Output Should be:
{
'/products': [
{
'111#gmail.com': true,
'222#gmail.com': true,
}
],
'/sales': [
{
'111#gmail.com': true,
'222#gmail.com': true,
'333#gmail.com': true,
'444#gmail.com': true,
}
],
'/finance': [
{
'333#gmail.com': true,
'444#gmail.com': true,
}
]
}
Instead of pushing the entire row, you want to create a new object. I'm not quite sure why your final output is an array with a single object though or why there is a true for each email.
const key = obj[property];
if (!acc[key]) {
acc[key] = [{}];
}
acc[key][0][obj.email] = true;
return acc;
Doing something like this will result in an object whose keys are the name and the values are each an array with a single object whose keys are the email addresses.
Here is an example on how you should do it. It will give you the expected result
const list = [{
TextRow: {
name: '/products',
email: '111#gmail.com'
}
},
{
TextRow: {
name: '/products',
email: '222#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '111#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '222#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '333#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '444#gmail.com'
}
}, {
TextRow: {
name: '/finance',
email: '333#gmail.com'
}
}, {
TextRow: {
name: '/finance',
email: '444#gmail.com'
}
},
]
const result = list.reduce((acc, x) => {
const name = x['TextRow']['name'];
const obj = {
[x['TextRow'].email]: true
};
if (acc[name]) {
acc[name].push(obj)
} else {
acc[name] = [obj];
}
return acc;
}, [])
console.log(result)

Search object in array and update if exist or add

This is what my array of logged in users looks like:
const connectedUsers = [{
user: {
uuid: 'b62-2dw',
points: 1,
},
id: "1234567"
}];
I will concat this table when a new user logs in to my system:
this.connectedUsers = [
...this.connectedUsers,
{
...payload,
id: client.id
},
];
Then my array looks like this: (I give this to better understand)
const connectedUsers = [{
user: {
uuid: 'b62-2dw',
points: 1,
},
id: "1234567"
},
{
user: {
uuid: '663-dda',
points: 5,
},
id: "33332"
}
];
If the user with the uuid like 663-dda updates his point, I perform this method again.
When I leave it as it is, something like this will be done:
const connectedUsers = [{
user: {
uuid: 'b62-2dw',
points: 1,
},
id: "1234567"
},
{
user: {
uuid: '663-dda',
points: 5,
},
id: "33332"
},
{
user: {
uuid: '663-dda',
points: 6,
},
id: "33332"
}
];
I want to write a very nice (use ES6+) algorithm that first checks if such an object exists in this array (check by id or by user.uuid). If so, update. If not, add a new object. So it should be like this:
const connectedUsers = [{
user: {
uuid: 'b62-2dw',
points: 1,
},
id: "1234567"
},
{
user: {
uuid: '663-dda',
points: 6,
},
id: "33332"
}
];
In the code where you're updating the array when a user logs in, you could do like this:
if (!this.connectedUsers.find(user => user.user.uuid === payload.user.uuid) {
this.connectedUsers = [
...this.connectedUsers,
{ ...payload, id: client.id },
];
}
const connectedUsers = [{
user: {
uuid: 'b62-2dw',
points: 1,
},
id: "1234567"
},
{
user: {
uuid: '663-dda',
points: 5,
},
id: "33332"
},
{
user: {
uuid: '663-dda',
points: 6,
},
id: "33332"
}];
//let take some sample object
const newObDuplicateUuid = {
user: {
uuid: '663-dda',
points: 6,
},
id: "3333290"
}
const newObDuplicateId = {
user: {
uuid: '756-dda',
points: 6,
},
id: "33332"
}
const newObFresh = {
user: {
uuid: '756-dda',
points: 6,
},
id: "3333290"
}
let checkRule = connectedUsers.every(item => item.user.uuid != newObDuplicateUuid.user.uuid && item.id != newObDuplicateUuid.id)
//return false for same uuid
checkRule = connectedUsers.every(item => item.user.uuid != newObDuplicateId.user.uuid && item.id != newObDuplicateId.id)
//return false for same id
checkRule = connectedUsers.every(item => item.user.uuid != newObFresh.user.uuid && item.id != newObFresh.id)
//return true
console.log('Passed validation :'+checkRule);
const result = checkRule ? [...connectedUsers,newObFresh] : 'There is duplicate value';
console.log(result);
This is my approach. One function that covers both cases. Just pass the array and the new entry and it will return the updated list
function updateOrAddUser(listOfUsers, newEntry) {
let found = false;
const updatedUserList = listOfUsers.map(entry => {
if (entry.user.uuid === newEntry.user.uuid) {
found = true;
return newEntry;
}
return entry;
});
if (!found) {
updatedUserList.push(newUser);
}
return updatedUserList;
}

Merge objects in array without overriding different value properties

I'm trying to merge objects in an array with the same id without overriding different value properties.
var arr = [{
Messages: { count: 1 },
Account: { key: 'TEST' },
id: 179,
Contact:
{
firstName: 'The Postman',
lastName: 'Team'
},
Tags: { name: 'forums', color: '#0091EA' }
},
{
Messages: { count: 1 },
Account: { key: 'TEST' },
id: 179,
Contact:
{
firstName: 'The Postman',
lastName: 'Team'
},
Tags: { name: 'defective', color: '#0091EA' }
}];
var tags = [];
for(var i=0; i<arr.length; i++){
tags = tags.concat(arr[i].Tags);
}
var result = arr[0];
result.Tags = tags;
console.log(result);
My goal is is to have the following object:
var obj =
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: [{ name: "forums", color: "#0091EA" }, { name: "defective", color: "#0091EA" }]
};
I've created a fiddle where I managed to get the desired output, but I'm sure there is a better way to do it.
http://jsfiddle.net/18mLhx7j/1/
UPDATE
Based on the answer posted by #Harun Yilmaz I was able to accomplish the same result using Lodash reduce.
I just wonder if it's a valid alternative to what he posted.
var arr = [
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "defective", color: "#0091EA" } }
];
var interactions =_.reduce(arr, function(acc, cur) {
for (let i =0; i < Object.keys(cur).length; i++) {
let key = Object.keys(cur)[i];
if (!acc[key]) {
acc[key] = cur[key];
} else if (acc[key] && !_.isArray(acc[key]) && !_.isEqual(acc[key], cur[key])) {
var obj = [];
obj.push(acc[key]);
obj.push(cur[key]);
acc[key] = obj;
} else if (acc[key] && _.isArray(acc[key])) {
acc[key].push(cur[key]);
}
}
return acc;
}, {});
console.log(interactions);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
You can use Array.reduce() to have a final object and spread operator as following
var arr = [
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "defective", color: "#0091EA" } }
];
const finalArr = arr.reduce((acc, cur) => {
const {Tags,...Rest} = cur;
acc.Tags.push(Tags);
acc = {
...Rest,
Tags: acc.Tags
};
return acc;
},{Tags:[]});
// ^^ initial object
console.log(finalArr);

Categories