Adding participants in a group chat - meteor

I am trying to add participants in a group chat but I am not getting any error but nothing is happening here is my code:
Meteor.methods({
addMember: function(groupId,email){
Groups.update({_id:groupId},
{$addToSet: {participants:{"emails":email}}}
);
}
});
My event:
Template.editGroup.events({
'click .add': function() {
var id = this._id;
swal({
title: "An input!",
text: "Add an email address:",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
animation: "slide-from-top",
inputPlaceholder: "Add email address"
},
function(email) {
if (email === false) return false;
if (email === "") {
swal.showInputError("You need to add email address!");
return false
}
Meteor.call("addMember",id,email)
})
}
})

The id is the first parameter of a meteor collection update.
See in: https://docs.meteor.com/api/collections.html#Mongo-Collection-update
try it
Meteor.methods({
addMember: function(groupId,email){
Groups.update(groupId,
{$addToSet: {participants:{"emails":email}}}
);
}
});

You should be using dot notation to update the emails field inside participants.
https://docs.mongodb.com/v3.2/core/document/#document-dot-notation
Just replace {$addToSet: {participants:{"emails":email}}} with
{$addToSet: {"participants.emails":email}}

Related

Ionic 4, Firebase-x and FCM Push notification with action buttons

I am trying to add action buttons to the push notifications sent via the firebase admin SDK to my Ionic 4 app using the Firebase-X native plugin to handle push notifications. My app is running on android and ios.
Here's my current script that sends me successfully a push notification:
exports.sendDebugPush = functions.pubsub.schedule('* * * * *').onRun((context) => {
let promises: Promise<any>[] = [];
return admin.database().ref('/users/******').once("value")
.then( user => {
let todos = [];
for(let key in user.val().nextActions) {
if(user.val().nextActions[key].active != false) {
let todo = user.val().nextActions[key]
todo['todoid'] = key;
todos.push(todo);
}
}
if(todos.length > 0) {
//currently we pick a random todo, later on the one with the highest priority
//todos.sort((a, b) => (a.priority/1 < b.priority/1) ? 1 : -1);
let randomTodo = todos[Math.floor(Math.random()*todos.length)]
let payload: any = {
notification: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString()
},
data: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString(),
target: 'todo',
todoid: randomTodo.todoid
}
};
Object.values(user.val().devices).forEach( (device) => {
promises.push(admin.messaging().sendToDevice(String(device), payload));
});
}
return Promise.all(promises)
.then( () => {
console.log('success!');
})
.catch( error => {
console.log('failed :(');
console.log(error);
});
});
});
Of course, without action buttons. And this function handles the push notifications in my app (this.firebase = FirebaseX plugin imported from 'import { FirebaseX } from "#ionic-native/firebase-x/ngx";'):
initPushNotifications() {
this.firebase.getToken().then(token => {
this.db.saveDeviceToken(this.auth.userid, token);
});
this.firebase.onMessageReceived().subscribe(data => {
if(!data.target) {
let title = '';
if(data.title) {
title = data.title;
} else if(data.notification && data.notification.title) {
title = data.notification.title;
} else if(data.aps && data.aps.alert && data.aps.alert.title) {
title = data.aps.alert.title;
}
let body = '';
if(data.body){
body = data.body;
} else if(data.notification && data.notification.body){
body = data.notification.body;
} else if(data.aps && data.aps.alert && data.aps.alert.body){
body = data.aps.alert.body;
}
this.alertCtrl.create({
message: title + ' ' + body,
buttons: [
{
text: "Ok"
}
]
}).then( alert => {
alert.present();
});
} else {
this.goToToDoPage(data.todoid);
}
});
}
It does this also successfully. I achieved to handle the click on the push notification such that it redirects to my To-Do page for this kind of push notification (one with a 'target' property). But now I'd like to add two action buttons 'Start' and 'Skip' on the push notification to start or skip the corresponding to-do. To be clear, I am talking about a background push notification, so the app is not open. The user then gets a standard push notification on his phone and there I'd like two action buttons to take an action without opening the app itself.
I tried various things with the payload to first even show me action buttons, but didn't achieve it. For example, the following is not working for me:
let payload: any = {
notification: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString()
},
data: {
title: "Gossik",
body: "Hoiiiii " + new Date().toISOString(),
target: 'todo',
todoid: randomTodo.todoid,
"actions": [
{ "icon": "approve_icon", "title": "APPROVE", "callback": "AppComponent.approve", "foreground": true},
{ "icon": "reject_icon", "title": "REJECT", "callback": "AppComponent.reject", "foreground": true}
]
}
};
Thanks a lot in advance for your help and let me know if something is still unclear. :)

Handlebars + passport js

I'm using handlebars as a view engine.
For routes :
app.get('/', function(req, res) {
if(req.user) {res.render('user'), {name:req.user.username, id:req.user.id}}
else
if(!req.user) {res.render('index')};
});
For passport.js
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
connection.query("SELECT * FROM users WHERE id = ? ",[id], function(err, rows){
done(err, rows[0]);
});
});
passport.use(
'local-signup',
new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done) {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
connection.query("SELECT * FROM users WHERE username = ?",[username], function(err, rows) {
if (err)
return done(err);
if (rows.length) {
return done(null, false, {message: 'That username is already taken'});
} else {
var newUserMysql = {
username: username,
password: bcrypt.hashSync(password, null, null) // use the generateHash function in our user model
};
var insertQuery = "INSERT INTO users ( username, password ) values (?,?)";
connection.query(insertQuery,[newUserMysql.username, newUserMysql.password],function(err, rows) {
newUserMysql.id = rows.insertId;
return done(null, newUserMysql);
});
}
});
})
);
I'm trying to find a solution, but it doesn't work. Whenever I try to use this, handlebars won't show anything up.. I know that ejs uses something like <%= user.username %> that does work, but can't convert that to handlebars..
if(req.user) {res.render('user'), {name:req.user.username, id:req.user.id}}
I figured it out till the end, my object {} was outside the (), not inside like it was supposed to be. This is the right code:
if(req.user) {res.render('user', {name:req.user.username, id:req.user.id})}

How to validate an update against SimpleSchema before updating a document in collection

I'm trying to validate my data against a SimpleSchema before it gets submitted to the collection but for some reason I'm not able to do so with this error.
Exception while invoking method 'createVendorCategory' { stack: 'TypeError: Cannot call method \'simpleSchema\' of undefined
I have one collections with two SimpleSchemas as follows.
Vendors = new Mongo.Collection('vendors'); //Define the collection.
VendorCategoriesSchema = new SimpleSchema({
name: {
type: String,
label: "Category"
},
slug: {
type: String,
label: "Slug"
},
createdAt : {
type: Date,
label: "Created At",
autoValue: function(){
return new Date()//return the current date timestamp to the schema
}
}
});
VendorSchema = new SimpleSchema({
name: {
type: String,
label: "Name"
},
phone: {
type: String,
label: "Phone"
},
vendorCategories:{
type: [VendorCategoriesSchema],
optional: true
}
});
Vendors.attachSchema(VendorSchema);
The vendorCategory will be added after the Vendor document is created by the user.
Here is what my client side looks like.
Template.addCategory.events({
'click #app-vendor-category-submit': function(e,t){
var category = {
vendorID: Session.get("currentViewingVendor"),
name: $.trim(t.find('#app-cat-name').value),
slug: $.trim(t.find('#app-cat-slug').value),
};
Meteor.call('createVendorCategory', category, function(error) {
//Server-side validation
if (error) {
alert(error);
}
});
}
});
And here is what my server side Meteor.methods look like
createVendorCategory: function(category)
{
var vendorID = Vendors.findOne(category.vendorID);
if(!vendorID){
throw new Meteor.Error(403, 'This Vendor is not found!');
}
//build the arr to be passed to collection
var vendorCategories = {
name: category.name,
slug: category.slug
}
var isValid = check( vendorCategories, VendorSchema.vendorCategories.simpleSchema());//This is not working?
if(isValid){
Vendors.update(VendorID, vendorCategories);
// return vendorReview;
console.log(vendorCategories);
}
else{
throw new Meteor.Error(403, 'Data is not valid');
}
}
I'm guessing this is where the error is coming from.
var isValid = check( vendorCategories, VendorSchema.vendorCategories.simpleSchema());//This is not working?
Any help would be greatly appreciated.
Since you've already defined a sub-schema for the sub-object you can directly check against that:
check(vendorCategories,VendorCategoriesSchema)

Subcribe gets more records than server publishes

I am trying to publish all admin users from server
on server something like this:
Meteor.publish("users_with_roles", function (options, role) {
//{fields: {emails: 1, profile: 1}}
Counts.publish(this, 'numberOfUsers', Meteor.users.find({$and:[
{'roles.tripro': {$exists: true}},
{'roles.tripro': role}
]}),
{ noReady: true });
return Meteor.users.find({
$and:[
{'roles.tripro': {$exists: true}},
{'roles.tripro': role}
]
}, options);
});
Then on client side, I am trying to subscribe this:
$meteor.autorun($scope, function() {
$meteor.subscribe('users_with_roles', {
limit: parseInt($scope.getReactively('perPage')),
skip: (parseInt($scope.getReactively('page')) - 1) * parseInt($scope.getReactively('perPage')),
sort: $scope.getReactively('sort'),
fields: {emails: 1, profile: 1}
},'admin').then(function() {
$scope.usersCount = $meteor.object(Counts ,'numberOfUsers', false);
console.log('user counter:' + $scope.usersCount.count);
$scope.users.forEach( function (user) {
// user.onClicked = function () {
// //$state.go('userProfile', {userId: user._id});
// };
console.log(user._id);
});
},
function(error)
{
console.log(error);
}
);
});
$scope.users = $meteor.collection(function() {
console.log('looking for role: ' + role);
return Meteor.users.find({}, {
//sort : $scope.getReactively('sort')
});
});
However, from the logging, it appears that the client side received all users , but from the logging on server side, it does give correct result.
What am I missing here?
A couple things to think about here.
When you request users you will always have "you". So if the user you are logged into is not an admin, it will still show up in the collection.
Because you are using $meteor.subscribe instead of $scope.$meteorSubscribe you are not clearing the subscription when the scope is destroyed so it's possible that it's mixing with other subscriptions on the client side from other scopes.

Client filter does not work in alethes:meteor-pages

I set auth function:
UsersPagination = new Meteor.Pagination(Meteor.users, {
templateName: "usersPaginate",
itemTemplate: "userListItem",
router: "iron-router",
homeRoute: "/userlist/",
route: "/userlist/",
routerTemplate: "userListPage",
routerLayout: "indexLayout",
perPage: 50,
sort: {createdAt: -1},
auth: function(skip, sub){
//use alanning:roles
if(Roles.userIsInRole(sub.userId, ['admin'])) { // see all users
return Meteor.users.find({roles: 'user', user_status: {$in: [1,2,3,4,5]}}, {fields: {services: 0}});
} else if(Roles.userIsInRole(sub.userId, ['manager'])) { // see own users
return Meteor.users.find({manager_id: sub.userId, roles: 'user', user_status: {$in: [1,2,3,4,5]}}, {fields: {services: 0}});
} else {
console.log('whaa?');
return false ;
}
},
divWrapper: false,
fastRender: true,
availableSettings: {
filters: true,
settings: true
}
});
and if i set filter "user_status" in template:
Template.usersPaginate.events({
'change #user_status': function(event, template){ //select input
var status_id = parseInt(event.currentTarget.value) ;
var filter = {} ;
if(status_id !== 0) {
filter.user_status = status_id ;
}
//....
UsersPagination.set({
filters: filter
});
}
});
it's not working, template refresh, but filter not working. Displays all users.
Please tell me what I'm doing wrong.
Sorry my bad english :)
The combination auth and filter seems bugged or not clearly documented. Make your own pagination. You will spend less time in the end.

Resources