How can I create a list of online/active users? - meteor

I'm using the package mizzao:user-status to add online/active statuses to my users. Using this, I'm able to run a query to get all online users.
The problem I'm facing is, keeping a list of users up to date with users that are logged in.
I believe I would need to use Accounts.onLogin to update the list, which I think is used on the server side. So, how would I keep a list of users up to date with users that are connected on the client side?

Like mizzao point on the README.
First Do the Publish.
Meteor.publish("userStatus", function() {
return Meteor.users.find({ "status.online": true });
});
and the subscribe,
Meteor.subscribe('userStatus')
Second do a helper to return the users online.
Javascript
Template.example.helpers({
usersOnline:function(){
return Meteor.users.find({ "status.online": true })
},
usersOnlineCount:function(){
//event a count of users online too.
return Meteor.users.find({ "status.online": true }).count();
}
})
HTML
<template name="example">
There are currently {{usersOnlineCount}} users online.
<h1>List of Users online </h1>
<ul>
{{#each usersOnline}}
<li> {{username}}</li>
{{/each}}
</ul>
</template>

Related

Iterating through user accounts in meteor accounts UI

I wanted to display all the user information in a tabular format as a part of an admin page. I used meteor accounts ui package for the same.
The HTML code is:
{{#each userList}}
<tbody>
<tr>
<th scope="row">*</th>
<td>{{infofullname}}</td>
<td>{{infosurname}}</td>
<td>{{infoemail}}</td>
</tr>
</tbody>
{{/each}}
The problem is that the information for the current user is getting displayed and not all the enrolled users. The iteration does happen but for the current logged in user. Also the email address is not getting displayed.
The helper code is:
Template.students.helpers({
userList: function(){
return Meteor.users.find({});
},
infofullname: function(){
return Meteor.user().profile.fullname;
},
infosurname: function(){
return Meteor.user().profile.surname;
},
infoemails: function(){
return Meteor.user().emails.[0].address;
}
});
Im facing the following problems:
1) The email address is not getting displayed.
2)The information of all the users is not getting displayed.
Thank You.
Publish all users with the following on the server:
Meteor.publish('allUsers',function(){
return Meteor.users.find({},{fields: {emails: 1, profile: 1}});
this.ready();
});
Then subscribe on the client with:
Meteor.subscribe('allUsers');
Your helpers will need some slight modifications as #Sudhanshu suggested however since you're looping over a cursor of users you can take advantage of this being an individual user object inside the loop.
Template.students.helpers({
userList() {
return Meteor.users.find({});
},
infofullname() {
return this.profile.fullname;
},
infosurname() {
return this.profile.surname;
},
infoemails: function(){
return this.emails.[0].address;
}
});
You can also access nested properties directly in blaze, avoiding the need for three of your helpers, ex:
{{#each userList}}
<tbody>
<tr>
<th scope="row">*</th>
<td>{{profile.fullname}}</td>
<td>{{profile.surname}}</td>
<td>{{emails.[0].address}}</td>
</tr>
</tbody>
{{/each}}
Multiple things are wrong:
Meteor.users() will give you multiple users only if you publish them (or you use autopublish).
Meteor.user() will always give you only the currently logged in user. So all your helpers will not work as per your plan. Modify them to use Meteor.users.findOne({_id: id)}). You can always use helpers with parameters.
Meteor publishes only the profile by default and not the emails. So you will have to publish the emails field in your publication.

How do I control two subscriptions to display within a single template?

Sorry kind of new to the Meteor framework!
I Subscribed to two Publish functions. Even if both publish functions target the same Collection, they both have different functions, that I would like to display in one template. How do I achieve this. I have done allot of research but there doesn't seem to be sufficient information on how to achieve.
Following are the two publish functions in code that I subscribe to:
.server/main.js:
Meteor.publish('MerchantTrending', function (categoryMan){
var currentUser = this.userId;
return buyList.find({ who:"Merchant", ownerId:currentUser, itemCategory: { $in: categoryMan } }, {skip: 0, limit: 3});
});
.server/main.js:
Meteor.publish('myTopViews', function (){
var currentUser = this.userId;
return buyList.find({ newArrivalsExpiryDate : {'$lte': new Date()}}, {ownerId:currentUser }, {skip: 0, limit: 3});
});
Following is the subscription function in code
.client/main.js:
Router.route('/MerchantLandingPage', {
subscriptions: function(){
var categoryMan = Session.get('category');
return Meteor.subscribe('MerchantTrending', categoryMan, 'merchantTopViews')
}
});
Now the helper function in code:
Template.MerchantLandingPage.helpers({
'top3Trending' : function () {
return buyList.find({}).fetch();
},
'myTopViews' : function () {
return buyList.find({}).fetch();
}
});
And now the template in code:
<template name="MerchantLandingPage">
##### *** Top three trending items *** ########
{{#each top3Trending}}
ItemName:: <b>{{itemName}}</b> <br>
Item Category:: <b>{{itemCategory}}</b> <br>
Discription:: <b>{{descriptions}}</b> <br>
Image:: {{this.photo._id}} <br>
Date Created:: {{createdDate}} <br>
{{/each}}
<br><br>
############ *** My top Views *** #############
{{#each myTopViews}}
ItemName:: <b>{{itemName}}</b> <br>
Item Category:: <b>{{itemCategory}}</b> <br>
Discription:: <b>{{descriptions}}</b> <br>
Image:: {{this.photo._id}} <br>
Date Created:: {{createdDate}} <br>
{{/each}}
</template>
Both {{#each myTopViews}} and {{#each top3Trending}} successfully display but not correctly. When the variable categoryMan in
Meteor.subscribe('MerchantTrending', categoryMan, 'merchantTopViews')
changes value, it affects both both the outcome of both {{#each myTopViews}} and {{#each top3Trending}}, when its only supposed to affect {{#each top3Trending}}.
How can I get the subscriptions to NOT have an affect on both {{#each myTopViews}} and {{#each top3Trending}}, but only {{#each myTopViews}} in my template?
Thanks for the help!
Welcome to Meteor!
The solution is straight forward once you understand that:
Subscription is just a stream of your DB documents from server into your client's MiniMongoDB. So your 2 subscriptions (it is perfectly fine having several subs on the same Collection) just fill in your client's buyList local collection.
Use of Collections client side is generally independent from how you subscribe the data. So you should simply use a similar selector and possibly options in your top3Trending and myTopViews helpers as you have done for your publication server side (not the same between the 2 helpers, obviously).
As a side note, you do not even need to fetch() the Collection cursor returned by find(), Blaze knows how to handle it directly.
I see a few problems with your code, first of all - your second subscription isn't going to work because your query is wrong:
Meteor.publish('myTopViews', function (){
var currentUser = this.userId;
return buyList.find(
{ ownerId:currentUser, newArrivalsExpiryDate : {'$lte': new Date()}},
{skip: 0, limit: 3}
);
});
You had ownerId: currentUser wrapped in curly braces, it is fixed above.
The way publications/subscriptions work is, if you have two publications sending different data, the template doesn't 'know' the data is coming from two different subscriptions. It will just have access to all of the data being sent by all subscriptions.
For that reason, your two helpers top3trending and myTopViews are returning exactly the same thing. You can delete one of them!
You should move your subscriptions out of the router and in to the Template itself. Here's an article that will help you with that!
There is a package percolate:find-from-publication that permits to filter the data from publications.

Display list of user email addresses in Meteor

I'm trying to get a list of all users in meteor using Metor.methods
This is my code :
server/main.js
Meteor.methods({
'createUser': function(){
if (Meteor.users.find({}).count()===0) {
for (i = 0; i <= 5; i++){
let id = Accounts.createUser({
email: Meteor.settings.ADMIN_USE,
password: Meteor.settings.ADMIN_PASSWORD,
profile: { firstName: Meteor.settings.ADMIN_FIRSTNAME, lastName: Meteor.settings.ADMIN_LASTNAME }
});
}
}
},
'returnmail': function(){
return Meteor.users.findOne().emails[0].address;
}
});
then i call this function in another file called Listusers.js:
Template.ListUsers.helpers({
email: function(){
Meteor.call('returnmail');
},
});
I'm trying to display the value of email using this code but it doesn't work
Client/ListUsers.html
<Template name="ListUsers">
<input id="mail" type="text" value="{{email}}" />
</Template>
Several problems. I strongly recommend you go through the tutorial at least. The Discover Meteor ebook is also invaluable. One of the first steps in understanding Meteor is moving from a traditional XHR request-response model to publish-subscribe.
Your email helper needs to return a value.
Meteor.call() doesn't return anything. Normally you use it with a callback that gives you an error status and the result. However you can't use that in a helper unless you use a Session variable or a promise because the return value from the call is at the wrong context level.
Your returnmail method is only returning a single email address from findOne() and not any specific one either, just a quasi-random one (you can't guarantee which document findOne() is going to return!)
You're creating 5 identical users with the same email address and password. 2-5 are going to fail because of a uniqueness constraint on the email field.
Now on to the solution.
On the server, publish the Users collection including only the emails field (which is an array of objects)
On the client, subscribe to that publication.
On the client, iterate over the users collection and get the email address from a helper.
server:
Meteor.publish('allEmails',function(){
// you should restrict this publication to only be available to admin users
return Meteor.users.find({},{fields: { emails: 1 }});
});
client js:
Meteor.subscribe('allEmails');
Template.ListUsers.helpers({
allUsers(){ return Meteor.users.find({}); },
email(){ return this.emails[0].address; }
});
client html:
<Template name="ListUsers">
{{#each allUsers}}
<input id="mail" type="text" value="{{email}}" />
{{/each}}
</Template>

Publishing all Meteor.users doesn't work

I'm trying to publish all the usernames to the clients, even if not signed in. For that, on the server I have:
Meteor.publish("users", function() {
return Meteor.users.find({}, {fields : { username : 1 } });
});
And on the client:
Meteor.subscribe("users");
However, when I try to access the Meteor.users collection, I find nothing there.
(This is essentially the same as the question here: Listing of all users in the users collection not working first time with meteor js, only without checking the roles for admin first. Still doesn't seem to work..)
I'm probably missing something silly..
I find the same issue, and after doing a research i find this package, i think it may should help you.
Take a look and hope it help you
Update
First move the subscription to the /lib folder, just to make sure its the first thing meteor do when start, also change a little bit the subscription like this on the /lib, folder.
Tracker.autorun(function() {
if(Meteor.isClient) {
if (!Meteor.user()) {
console.log("sorry you need to be logged in to subscribe this collection")
}else{
Meteor.subscribe('users');
}
}
});
For better security we just subscribe to the users collection when the client its logged in
This code outputs all the usernames to the clients, even if not signed in (in this case on /users page):
server/publications.js:
Meteor.publish("userlist", function () {
return Meteor.users.find({},{fields:{username:1}});
});
client/users_list.js:
Template.usersList.helpers({
users: function () {
return Meteor.users.find();
}
});
client/users_list.html:
<template name="usersList">
{{#each users}}
{{username}}
{{/each}}
</template>
lib/router.js (using iron:router package):
Router.route('/users', {
name: 'usersList',
waitOn: function(){
return Meteor.subscribe("userlist");
}
});
Hope it helps.

sending information through events in meteor

Ok so I'm working with meteor! Woo hoo I love it so far, but I've actually run into an architecture problem (or maybe its super simple and i just dont know it yet).
I have a list of names that belong to a user. And a delete button that is aligned next to the name
name - x
name - x
name - x
and I want a functionality to click the 'x', and then proceed to clearing the name from the database using the meteor event handler. I'm finding trouble thinking about how I'm going to pass the name along with the click to proceed to delete it from the database.
I can't use a unique id in the template to call a document.getElementById() (unless I came up with an integer system that followed the database.)
Does anyone have a good thought on this?
Here is a complete working example:
html
<body>
{{> userEdit}}
</body>
<template name="nameChoice">
<p>
<span>{{name}}</span>
x
</p>
</template>
<template name="userEdit">
{{#each nameChoices}}
{{> nameChoice name=this}}
{{/each}}
</template>
js
Users = new Meteor.Collection(null);
if (Meteor.isClient) {
Meteor.startup(function () {
Users.insert({nameChoices: ['foo', 'bar', 'baz']});
});
Template.userEdit.nameChoices = function () {
return Users.findOne() && Users.findOne().nameChoices;
};
Template.nameChoice.events({
'click .remove': function () {
_id = Users.findOne()._id;
Users.update(_id, {$pull: {'nameChoices': this.name}});
}
});
}
This actually does a bunch of stuff you wouldn't do in a real application (defined a client-only Users collection, assumes there is only one user, etc). But the main takeaway is that you can use the data context in each nameChoice template to respond to the remove event. This approach can nearly always replace the need for coming up with your own artificial id system. Feel free to ask questions if any of this is unclear.

Resources