How do you save two values in a user field using angularjs? - angularjs

I've got a requirement where I need to assign a SharePoint task to two users. Code below assigns it to one user but not the second when creating a task.
first user value _spPageContextInfo.userId second user value taskcase.Caseownername,
$scope.createTask = function() {
var item = $scope.taskDetails;
var taskcase = $scope.caseDetails;
var updates = angular.extend({}, {
Title: item.Title,
DueDate: item.DueDate ? moment(item.DueDate, 'DD/MM/YYYY').format() : null,
Status: item.Status,
AssignedTo: _spPageContextInfo.userId && taskcase.Caseownername,
RelatedCase: $routeParams.id
});
ModalDialog.showWaitScreen({
message: 'Creating task for case ' + updates.Title
}).then(function (waitScreen) {
return CaseManagementService.createTask({
updates: updates
}).then(function (task) {
$log.info('task created', task);
$scope.taskDetails = {
Status: 'Not Started'
};
$scope.loadRelatedTasks();
return ModalDialog.delayClose(waitScreen, 200);
}, function(e){
console.error(e);
});
});
};

You need get the userid from the taskcase.Caseownername object, and then pass the data like below.
AssignedToId: {'results':[_spPageContextInfo.userId,user2Id]}
Refer to: How to update Person field with multiple values using REST API

_spPageContextInfo.userId sounds like an integer value and taskcase.Caseownername sounds like a string value
Is AssignedTo a string? Then just do:
AssignedTo: _spPageContextInfo.userId + taskcase.Caseownername,
This will save both values as 1 string
Is it an integer? You can't save two values in 1 property...

Related

Mongoose stops to $push to array if the field already exists in a document

I am using Node and Mongoose, and trying to set an array of ISODate elements:
"visitLog" : [
ISODate("2017-10-22T22:43:49.571Z"),
ISODate("2017-10-22T22:44:39.572Z"),
ISODate("2017-10-22T23:35:36.111Z"),
ISODate("2017-10-22T23:48:26.516Z"),
ISODate("2017-10-22T23:50:33.378Z"),
ISODate("2017-10-22T23:53:56.227Z"),
ISODate("2017-10-22T23:57:20.986Z")
]
So I had an existing schema where visitLog field did not existed, added new field to a schema - visitLog: [ {type: Date, default: '' }],and it worked - the result is what you see above.
But when I created a new document with updated schema that already has an empty array in it - "visitLog" : [ ] , $push just stopped working.
Here is mongoose query, if needed:
// conditions is a ternary operator that checks whether req.body username
// is an email or not, and puts needed condition to a query
var conditions = (!/^[a-zA-Z0-9\-\_\.\+]+#[a-zA-Z0-9\-\_\.]+\.[a-zA-Z0-9\-\_]+$/.test(req.body.username)) ? ' {email: req.body.username } ' : ' {username: req.body.username } ';
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { upsert: true };
User.findOneAndUpdate(conditions, fieldsToSet, options, function(err, user) { ...
The working document was created in mongo console, while the second was generated on a server, but I can't how can this make any difference.
Using $push shuld work with empty arrays. Can someone explain what's wrong here?
Thank you.
Edit
It figures that using findByIdAndUpdate without conditions works for both documents:
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { new: true };
req.app.db.models.User
.findByIdAndUpdate(req.user.id, fieldsToSet, options, function(err, user) {
You can do with the following query.
User.findOne(condiitons, (err, user) => {
if (user) {
var date = new Date().toISOString();
user.visitLog.push(date);
user.save();
...
}
});

Construct array in nodejs through for loop

I am using sails (0.11.0) running on nodejs (6.9.1). I am trying to construct an array by filling it through for loop. I would send this completed array in response to the client. I have tried various methods as suggested by people here on Stack Overflow, for example
the discussion here suggested
for (var i = yearStart; i < yearEnd+1; i++) {
arr.push(i);
}
On this discussion, it is suggested to use:
var array = calendars.map(function(item) {
return item.id;
});
console.log(array);
Similarly I tried many methods but I am coming across the same issue that during the loop, the array gets filled but as soon as the loop is completed, the array gets empty because of asynchronous process and therefore I can not send the response. To tackle with this I tried checking the index inside the loop body and send response from inside the loop body itself through
var userArray = [];
_.each(users, function(user, index){
MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){
if(err){
return res.json({"status":"some_error"});
}else{
userID = user.id
userImageID = userImage[0][0].id;
var userInfo = {
userID: userID,
userImageID: userImageID
}
userArray.push(userInfo)
if(index == users.length - 1){
res.json({selectedUsers: userArray});
}
}
});
});
I am initiating an empty userArray and then iterate through users object where each element of the object is characterized by name user and an index. Through a MySQL query I am fetching the userImage object and in each iteration, I am creating an object called userInfo that consists of userID and userImageID. I am pushing this object into userArray. And after each iteratio of the for loop (_.each), I check if last index is reached. Once last index is reached, the final array is sent as response before loop body is complete.
Here too I have an issue that the array body is not always completely filled. The reason is due to asynchronous process, the index does not always follow the order 0,1,2,3,4,.... and it can start with any number and can jump to any index in the next iteration, for example the first index to start would be 4, the second would be 0, third would be 2 and so on. This sequence would be different for every time we run this for loop. For a user, it will appear to be a total random process. Therefore if users.length is 8, and current index is randomly 7 at third iteration, the condition index == users.length - 1 will be met and response will be sent just with an array consisting of 3 elements rather than 8.
Can someone suggest me a better and robust way to fill an array through the for loop in nodejs and send that array in response, so that all items are included in the array in their original order?
As you are using node js , it is better to use any promises library like bluebird or async to handle Async requests.
The reason your loop is not working as expected is because as you've pointed out, due to async requests taking time to resolve for which _.each loop is not waiting.
Using bluebird, it can be done with Promise.map method which works as explained below from the documentaion :
Given an Iterable(arrays are Iterable), or a promise of an Iterable,
which produces promises (or a mix of promises and values), iterate
over all the values in the Iterable into an array and map the array to
another using the given mapper function.
Promises returned by the mapper function are awaited for and the
returned promise doesn't fulfill until all mapped promises have
fulfilled as well. If any promise in the array is rejected, or any
promise returned by the mapper function is rejected, the returned
promise is rejected as well.
Hence, Using Promise.map your code can be updated like below :
var Promise = require("bluebird");
return Promise.map(users, function(user, index){
return MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){
if(err){
return Promise.reject({"status":"some_error"});
}else{
userID = user.id
userImageID = userImage[0][0].id;
var userInfo = {
userID: userID,
userImageID: userImageID
}
return userInfo;
}
});
})
.then(function (usersArray){
res.json({selectedUsers: usersArray});
})
.catch(function (err){
res.json(err);
});
You can execute loops with functions with callbacks synchronously using SynJS:
var SynJS = require('synjs');
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'tracker',
password : 'tracker123',
database : 'tracker'
});
function myFunction1(modules,connection,users) {
var ret=[];
for(var i=0; i<users.length; i++) {
connection.query("SELECT CONCAT('some image of user #',?) AS userImage", [users[i]], function(err, rows, fields) {
if (err) throw err;
ret.push({
id: users[i],
image: rows[0].userImage
});
modules.SynJS.resume(_synjsContext); // <-- indicate that callback is finished
});
SynJS.wait(); // <-- wait for callback to finish
}
return ret;
};
var modules = {
SynJS: SynJS,
mysql: mysql,
};
var users = [1,5,7,9,20,21];
SynJS.run(myFunction1,null,modules,connection,users,function (ret) {
console.log('done. result is:');
console.log(ret);
});
Result would be following:
done. result is:
[ { id: 1, image: 'some image of user #1' },
{ id: 5, image: 'some image of user #5' },
{ id: 7, image: 'some image of user #7' },
{ id: 9, image: 'some image of user #9' },
{ id: 20, image: 'some image of user #20' },
{ id: 21, image: 'some image of user #21' } ]

Output all documents in mongoose

I am using mongoose ODM and have a schema which looks like this:
var banSchema = new Schema({
userid: { type: String, required: true, unique: true },
name: String,
groupid: String,
reason: String,
timestamp: Date
});
I want to output every single user id from all documents in the collection. I am using this query to obtain the userid objects. However I cannot seem to get the full list automatically. I have to manually enter the object number as seeen below:
bot.onText(/\/sync/i, function (msg) {
var fromId = msg.from.id;
var chatId = msg.chat.id;
if (fromId == config.sudo) {
console.log('Sudo Confirmed And Authorized!');
Ban.find({}, function (err, obj) {
console.log(obj[0].userid); // Returns A Single ID
console.log(obj[1].toObject().userid); // Returns a different ID
bot.sendMessage(chatId, obj[1].toObject().useridid);
});
} else {
console.log('Someone Is Trying To Act Like Sudo! *sigh*');
bot.sendMessage(chatId, 'You Are Not A Mod!');
}
});
This however does not return a full list of id's as I want. How could I solve this issue?
The code above is for a telegram bot which on a /sync command it should return a message with all ids from the collection.
Telegram bot API Limits
Due to the API limits, the entire output should be in a single message.
var query = Ban.find({}).select({
"userid": 1,
//Add more column fields here
"_id": 0 //Ensures _id is not displayed
});
var arr = [];
query.exec(function (err, results) {
if (err) throw err;
results.forEach(function (result) {
arr.push(result.userid);
// Add more column fields here;
});
var fixedJoin =arr.join("\n");
console.log(fixed);
bot.sendMessage(chatId, 'List\n\n' + fixedJoin);
});
The easiest way to get all values of a particular field across all docs in the collection is to use distinct:
Ban.distinct('userid', function (err, userids) {
// userids is an array containing all userid values in the collection.
// string.join into a single string for the message.
bot.sendMessage(chatId, 'USER IDs\n\n' + userids.join('\n'));
});
Use this syntax
Ban.find({}).
select('userid').
exec(function(err, result) {
//result is array of userid of all document
});
You can use this syntax:
Ban.find({}, 'userid', function(err, users) {
users.forEach(function(user) {
console.log(user);
bot.sendMessage(chatId, 'users \n' + user);
});
})

Ember array serialization

I'm adding objects to an array property of a model, then saving it. When I look at the outgoing request, the property in question is always an empty array.
My custom serializer (extending Ember.RESTSerializer) has this:
DS.ArrayTransform = DS.Transform.extend(
{
deserialize: function(serialized)
{
return (Ember.typeOf(serialized) == "array") ? serialized : [];
},
serialize: function(deserialized)
{
var type = Ember.typeOf(deserialized);
if (type == 'array')
{
return [{foo:'bar'}];
// return deserialized;
}
else if (type == 'string')
{
return deserialized.split(',').map(function(item)
{
return item.trim();
});
}
else
{
return [];
}
}
});
App.register("transform:array", DS.ArrayTransform);
As you can see I've tried passing back an arbitrary array with an object in it, but even then the array always comes out as empty. In the app I create the record like this:
var post = this.store.createRecord('explorePost', {
title: content.get('title'),
text: content.get('text'),
postDate: content.get('postdate'),
publishDate: content.get('publishDate'),
published: content.get('published'),
postType: content.get('postType'),
link: content.get('link,'),
projectDownloads: [],
// projectDownloads: this.model.get('projectDownloads'),
projectLinks: content.get('projectLinks'),
});
then add the objects like this:
this.model.get('projectDownloads').forEach(function (_download) {
console.log('pushing download', _download);
post.get('projectDownloads').pushObject(_download);
});
I can confirm that at time of saving, the post object has a projectDownloads array with one object in it. No matter what I do I can't seem to get it to spit out the contents when it saves. It's definitely going into the custom serializer, and detects it as an array, but you can see something else seems to be overriding it.
Can anyone tell me what I'm doing wrong? My model setup is below:
App.ExplorePost = DS.Model.extend(
{
title: DS.attr('string'),
text: DS.attr('string'),
link: DS.attr('string'),
postDate: DS.attr('momentdate'),
publishDate: DS.attr('momentdate'),
user: DS.belongsTo('user',{async:true}),
postType: DS.attr('string'),
activity: DS.belongsTo('activity',{ inverse: 'explorePost', async:true}),
comments: DS.hasMany('comment',{ inverse: 'explorePost', async: true }),
// projectDownloads: DS.hasMany('projectDownload',{ inverse: 'explorePost'}),
projectDownloads: DS.attr('array'),
// projectLinks: DS.hasMany('projectLink',{ inverse: 'explorePost'}),
projectLinks: DS.attr('string'),
published: DS.attr('boolean', {defaultValue: true}),
// tags: DS.hasMany('tag')
sortdate: function()
{
var datestr = Ember.isEmpty(this.get('postDate')) ? '' : moment(this.get('postDate')).format('YYYYMMDDHHmm');
var fn = (datestr + '____________').slice(0, 12);
return fn;
}.property('postDate')
});
There's no built in DS.attr('array') and a naive implementation would probably not know how to serialize ember-data objects found inside. Did you intend to leave that in there? If you swap it back to the relationships you've commented out and change projectDownloads to work with the promise:
this.model.get('projectDownloads').then(function(downloads) {
downloads.forEach(function(_download){
post.get('projectDownloads').pushObject(_download);
});
});
This should work jsut fine. I put together something nearly identical the other day. http://emberjs.jsbin.com/zolani/3/edit?html,css,js,output
if you array not contain complex object, like array of string, you can use DS.attr(), it will work.

mongodb updateOne value in an array

So I have an update one function going i just need to know how to update one of the elements in an array rather than wipe and replace the whole thing.
labelRelease = function(db, callback){
db.collection($$showName).updateOne(
{'showName' : $$showName},
{
$set: {'episode[2]' : data + label}
}, function(err, results){
callback();
});
}
Is a stripped down version of the code I am using to update, obviously the episode[2] does not work to select only one array element how can i achieve this?
relevant part of the database
episode:[episode1, episode2, episode3.....]
You can update an array element by position by using dot notation:
labelRelease = function(db, callback){
db.collection($$showName).updateOne(
{'showName' : $$showName},
{
$set: {'episode.2' : data + label}
},
function(err, results){
callback();
});
};
If the index of 2 is in a variable, you need to build up your $set value in a couple steps:
var index = 2;
var setValue = {};
setValue['episode.' + index] = data + label;
labelRelease = function(db, callback){
db.collection($$showName).updateOne(
{'showName' : $$showName},
{
$set: setValue
},
function(err, results){
callback();
});
};
The correct syntax for the set operation is:
$set: { 'episode.2' : ... } }
Note that episode.2 refers to the 3rd element of the episode array.

Resources