Want to acces object in requests array of profile in users collection - javascript

i want to create a event in which by clicking on accept in the
termplate i want to get that respective object of requests array in
profile of users collection
this profile section of my users collection (accounts-password)
{
"profile": {
"name": {
"first_name": "Vibhor",
"last_name": "Yadav"
},
"college_name": "ssit",
"gender": "MALE",
"friends": [],
"requests": [{
"id": "z6rDkvayDA5Ckoeab",
"name": "Nitin Gupta"
}],
"requested": [{
"id": "M6edD427rG9WwhfNh",
"name": "suraj Kumar"
}]
}
template to print requests
<template name = "notification">
<div id="req-main-div">
<ul>
{{# each username in reqList}}
<li>
<div id="req-user-name" value={{username.name}}>{{username.name}}</div>
<div id="accept">accept</div>
<div id="delete">delete</div>
</li>
{{/each}}
</ul>
</div>
</template>
helper to the template
Template.notification.helpers({
reqList:function () {
var User = Meteor.user();
return User.profile.requests;
}
});
the method i tried
Template.notification.events({
'click #accept':function(){
console.log(document.getElementById('req-user-name').value);
Meteor.call('accept_request',this);
}
});
i am not able to access DOM too
accept_request:function(accept){
if(!Meteor.userId())
{
throw new Meteor.Error('not-authorized','you are not signed in');
}
var user = Meteor.user();
console.log(accept);
}
iam getting this on console
undefined//for DOM of # accept
Object// for accept in accept_request method
main: ()
__proto__: Object

Related

Sendgrid API: How to send bulk emails with individual template data?

Requested behaviour:
I would like to send out bulk emails using Sendgrid and Firestore Cloud functions together. The email should display some individual user data depending on the recipient (e.g. user id and user name).
Current State
I created a working cloud function. It gets the user data from firestore and sends out emails by using the sendgrid API to the given email addresses.
Issue
However, it sends the ids of all users to every email address, instead of only sending the id belonging to a certain subscriber. Example:
There are 3 subscribers with 3 ids in my firestore collection:
"abc", "pqr", "xyz"
The function should deliver three emails including the id belonging to the email adress. Instead, the function sends "abcpqrxyz" to every address right now.
My cloud function:
export const sendAllEmails = functions.https.onCall(async (event) => {
const subscriberSnapshots = await admin.firestore().collection('subscribers').get();
const emails = subscriberSnapshots.docs.map(snap => snap.data().email);
const ids = subscriberSnapshots.docs.map(snap => snap.id);
const individualMail = {
to: emails,
from: senderEmail,
templateId: TEMPLATE_ID,
dynamic_template_data: {
subject: event.subject,
text: event.text,
id: ids // sends all ids to everyone instead of a single id in every mail
}
await sendGridMail.send(individualMail);
return {success: true};
});
Do I need to loop over emails and IDs or does the SendGrid API have a smarter implementation for this behaviour?
You have to read over each one of these elements to get the value and construct the object.
Maybe the parameters are not being included correctly in the body of the request. Please note that the personalizations object contains the data provided for each one of these mails.
https://sendgrid.com/docs/ui/sending-email/how-to-send-an-email-with-dynamic-transactional-templates/#send-a-transactional-email
var data = JSON.stringify({
"personalizations": [
{
"to": [
{
"email": "john.doe#example.com",
"name": "John Doe"
}
],
"dynamic_template_data": {
"verb": "",
"adjective": "",
"noun": "",
"currentDayofWeek": ""
},
"subject": "Hello, World!"
}
],
"from": {
"email": "noreply#johndoe.com",
"name": "John Doe"
},
"reply_to": {
"email": "noreply#johndoe.com",
"name": "John Doe"
},
"template_id": "<<YOUR_TEMPLATE_ID>>"
});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://api.sendgrid.com/v3/mail/send");
xhr.setRequestHeader("authorization", "Bearer <<YOUR_API_KEY_HERE>>");
xhr.setRequestHeader("content-type", "application/json");
xhr.send(data);
You need to make multiple "personalizations" objects within the data. I'm not sure what the limitations are with the maximum amount of emails in one request. You might need to research that and check. However I tested with the following json data, and it worked for me:
let data = JSON.stringify({
"from": {
"email": senderEmail
},
"personalizations": [
{ //first individual starts here
"to": [
{
"email": "john.doe.1#example.com"
}
],
"dynamic_template_data": {
"subject": "The subject",
"text": "Event Text goes here",
"id": "abc" // the individual id you need goes here
}
},
{ //next individual starts here
"to": [
{
"email": "john.doe.2#example.com"
}
],
"dynamic_template_data": {
"subject": "The subject",
"text": "Event Text goes here",
"id": "pqr" // the individual id you need goes here
}
} //end - but one can add more indivuals
],
"template_id": "[your_template_id]" //add your template id here
});

Link two objects in angular

I've got 2 data sets
posts
[
{
"postId": 1,
"postContent": "Lorem Ipsum",
"user": 1
},
{
"postId": 2,
"postContent": "Lorem Ipsum",
"user": 2
},
]
and users
[
{
"user": 1,
"firstName": "John",
"lastName": "Doe"
},
{
"user": 2,
"firstName": "Johny",
"lastName": "Doey"
}
]
I am repeating all the posts and i would like to access a user data throught the $scope.post.user.firstName etc.
how should i aproach it?
You can implement a method like getUserById() with the use of Array.prototype.find() to use it when iterating over your posts.
Code in AngularJS:
angular
.module('App', [])
.controller('AppController', ['$scope', function ($scope) {
$scope.posts = [{"postId": 1,"postContent": "Lorem Ipsum","user": 1},{"postId": 2,"postContent": "Lorem Ipsum","user": 2}];
$scope.users = [{"user": 1, "firstName": "John", "lastName": "Doe"},{ "user": 2, "firstName": "Johny", "lastName": "Doey"}];
$scope.getUserById = function (id) {
return $scope.users.find(function (user) {
return id === user.user;
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<div ng-repeat="p in posts">
<p>{{p.postContent}} <i>by {{getUserById(p.user).firstName}}</i></p>
</div>
</div>
find() the matching user for each post.
Note that if you are not using ES6 features, you will need a polyfill for Object.assign() and should use regular function() {}s instead array functions.
var posts = [{"postId":1,"postContent":"LoremIpsum","user":1},{"postId":2,"postContent":"LoremIpsum","user":2}];
var users = [{"user":1,"firstName":"John","lastName":"Doe"},{"user":2,"firstName":"Johny","lastName":"Doey"}];
var out = posts.map(post => Object.assign({}, post, {
user: users.find(user => user.user === post.user)
}));
console.log(out);
You can create a function that maps each user object to your post object. Then you can access user details as $scope.post.user.first_name; Here is simple code that will make you an new object with users.
var new_object = [];
function mapUsersToPosts(users, posts){
angular.forEach(posts, function(post){
angular.forEach(users, function(user){
if(post.user_id == user.user_id){
new_object.push({
'post' : post,
'user' : user
});
}
});
});
}
Now you can loop new_object and use user data and post data in same object.

compare 2 array of objects. match by ids, push object property into array

I have 2 arrays. users and posts. posts contain a property "post_by" which is the id of one of the users. I need to match the user and push the first & last name into the post object as a new property. Goal is I need to display the name of the user that made the post in a table.
note* I can use javascript, jquery, linq.js or lodash.
fiddle with json
fiddle
var users = [
{
"id": "15e640c1-a481-4997-96a7-be2d7b3fcabb",
"first_name": "Kul",
"last_name": "Srivastva",
},
{
"id": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd",
"first_name": "Rudy",
"last_name": "Sanchez",
},
{
"id": "636f9c2a-9e19-44e2-be88-9dc71d705322",
"first_name": "Todd",
"last_name": "Brothers"
},
{
"id": "79823c6d-de52-4464-aa7e-a15949fb25fb",
"first_name": "Mike",
"last_name": "Piehota"
},
{
"id": "e2ecd88e-c616-499c-8087-f7315c9bf470",
"first_name": "Nick",
"last_name": "Broadhurst"
}
]
var posts = [
{
"id": 1,
"status": "Active",
"post_title": "test title",
"post_body": "test body",
"post_by": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd"
},
{
"id": 2,
"status": "Fixed",
"post_title": "test title two",
"post_body": "test body two",
"post_by": "79823c6d-de52-4464-aa7e-a15949fb25fb"
}
]
https://jsfiddle.net/zy5oe25n/7/
console.log($.map(posts, function(post){
var user = $.grep(users, function(user){
return user.id === post.post_by;
})[0];
post.first_name = user.first_name;
post.last_name = user.last_name;
return post;
}));
Here's a lodash approach:
_.map(posts, function(item) {
return _.assign(
_.pick(_.find(users, { id: item.post_by }),
'first_name', 'last_name'),
item
);
});
It's using map() to map the posts array to a new array of new objects (immutable data). It's then using find() to locate the user object, and uses pick() to get the properties we need. Finally, assign() adds the post properties to the new object that pick() created.
For good measure, using linq.js.
var userMap = Enumerable.From(users).ToObject("$.id");
posts.forEach(function (post) {
var user = userMap[post.post_by];
if (user) {
post.first_name = user.first_name;
post.last_name = user.last_name;
}
});
Note, we're using the builtin forEach() for arrays, linq.js is not needed for that part.

Mapping and binding nested objects and arrays

I have an object and within this object I have items and one of the items is an array which also contains objects. A sample of the data is shown below.
I am using knockout to bind this data to the view so I think I need to implement a double loop for returning the objects and the objects within the child array to be able to bind them in the view.
Sample data:
"singers": {
"ijiyt6ih": {
"id": ObjectId('ijiyt6ih'),
"name": "John",
"songs": [
{
"id": ObjectId('okoiu8yi'),
"songName": "Hello There",
"year": "1980"
},
{
"id": ObjectId('sewfd323'),
"songName": "No More",
"year": "1983"
}
]
},
"98usd96w": {
"id": ObjectId('98usd96w'),
"name": "Jack",
"songs": [
{
"id": ObjectId('iew342o3'),
"songName": "Hurry Up",
"year": "1985"
}
]
}
}
I need to find a way to appropriately loop through this so that I can modify the returned data to bind it to the viewModel using knockout.
Here is how my viewModel looks like:
singersViewModel = function(data) {
var self = {
singerId: ko.observable(data.id),
singerName: ko.observable(data.name),
songName: ko.observable(...),
songYear: ko.observable(...)
};
I am not sure if I will have to return two different sets of data or not.
As for the looping. I was able to loop and return the list of singers to display on the page but I am not able to get the list of songs displayed within each singer.
Here is my loop so far:
var self = {},
singer,
tempSingers = [];
self.singers = ko.observableArray([]);
for (singer in singers) {
if (singers.hasOwnProperty(singer)) {
tempSingers.push(new singersViewModel(singers[singer]));
}
}
self.singers(tempSingers);
I tried to duplicate the same type of loop for songs within this loop but i would get an error using hasOwnProperty because songs is an array.
In the included snippet you can see how you can map the original data to a viewmodel that can be bound to a view.
I've left the ids as regular properties, and converted the names into observables, so thatthey can be edited. At the bottom you can see the current viewmodel state.
There is also a sample view which iterates the list of singers, and also the list of song within each singer.
As you can see I'm implementing the solution using mapping. For mapping you need to implement a callback that receives each original object and returns a new one with a new structure. For example this part of the code
_.map(_singers, function(singer) {
return {
id: singer.id,
name: ko.observable(singer.name),
// ... songs:
})
iterates over each singer (the sample data in the question), and for each one creates a new object with the id, an observable which includes the name (and the mapping of songs, which I don't show in this fragment).
NOTE: I'm using lodash, but many browsers support map natively as an array function
var ObjectId = function (id) { return id; }
var singers = {
"ijiyt6ih": {
"id": ObjectId('ijiyt6ih'),
"name": "John",
"songs": [
{
"id": ObjectId('okoiu8yi'),
"songName": "Hello There",
"year": "1980"
},
{
"id": ObjectId('sewfd323'),
"songName": "No More",
"year": "1983"
}
]
},
"98usd96w": {
"id": ObjectId('98usd96w'),
"name": "Jack",
"songs": [
{
"id": ObjectId('iew342o3'),
"songName": "Hurry Up",
"year": "1985"
}
]
}
};
var SingersVm = function(_singers) {
var self = this;
self.singers = _.map(_singers, function(singer) {
return {
id: singer.id,
name: ko.observable(singer.name),
songs: _.map(singer.songs, function(song) {
return {
name: ko.observable(song.songName),
id: song.id
};
})
};
});
return self;
};
var vm = new SingersVm(singers);
//console.log(vm);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-bind="foreach: singers">
<div>
<input data-bind="value: name"/> (<span data-bind="text: id"></span>)
<ul data-bind="foreach:songs">
<li>
<input data-bind="value: name"/> (<span data-bind="text: id"></span>)
</li>
</ul>
</div>
</div>
<pre data-bind="html: ko.toJSON($root,null,2)">
</pre>

Angular ng-repeat this JSON structure for user to user messaging

Very simple user to user messaging piece that I'm struggling with the interface in an app to use ng-repeat on the items.
Here is the data:
{
"ID": 4118,
"CreatedDate": "2015-08-20T03:12:50.397",
"recipient": [
{
"ID": 13,
"FirstName": "Heather",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/13"
}
],
"sender": [
{
"ID": 1046,
"FirstName": "Brad",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/1046"
}
],
"messages": [
{
"ID": 4137,
"ConversationID": 4118,
"UserID": 1046,
"Body": "hey",
"CreatedDate": "2015-08-20T14:34:42.4716233+00:00"
}
]
}
In the controller I get the conversations out of LS, one conversation is one record in LocalStorage, the JSON above will represent one conversation.
$scope.convo = JSON.parse(localStorage.getItem("convo-" + $stateParams.chatId));
Here is the structure I am trying to achieve (again, very simple, nothing fancy).
<ul>
<li class="item-avatar-left" ng-repeat="c in convo track by $index">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech">
{{c.messages[0].Body}}
</p>
</li>
</ul>
I've tried multiple variations on the ng-repeat directive.
Essentially what I'd like to achieve is just showing one <li> per each message.
Current result:
Console output of a conversation from LS:
You can try normally by ng-repeat
In controller like:
$scope.convo = [
{
"ID": 4118,
"CreatedDate": '2015-08-20T03:12:50.397',
//...... as your info
}
];
In HTML:
<ul>
<li class="item-avatar-left" ng-repeat="c in convo">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech" ng-repeat="m in c.messages">
{{m.Body}}
</p>
</li>
</ul>
NB: your $scope.convo need to be an array

Categories

Resources