drupal :: order complete hook and upgrade user permission/roles - drupal

I want to be able to upgrade user's permission after the order status shows complete.
I figured out that I should use hook_order hook in order to achieve that. But how do I get to know which user has created that order and how do go about updating the permissions as well as setting up the expire time for that role automatically.
I want this hook to be called as soon as the payment is made and the order is completed.
Any pointers will be valuable.

In the hook_order, 3 parameters are passed. Third parameter depends on the first one. When the first parameter is 'update', third parameter is the status to which the order is going.
hook_order($op, &$order, $arg2){
switch($op){
case 'update':
if($arg2 === 'completed'){
// This order got marked completed
}
}
}
$order->uid will give you the user that created the order. You can do something like the following
$user = user_load(array('uid' => $order->uid));
// update the roles assigned to user
user_save($user);
For expiring the role, you will need to write a module that will keep track of the duration and will do something like above when the time expires. Or you can use role_expire module and see if that helps.

Related

I can't get "Find personal time entry in progress" using clockify API

I will try to get those users whose time tracking start currently in clockify
and I'm trying to use the following API endpoint to get the user:
How to get user list using this endpoint?
I have made custom logic for check user is currently working or not
I have made a loop that checks the user is in progress or not.
e.g
public getClockifyBaseWorkerStatus(clokifyApiKey: string) {
let headers = new HttpHeaders().set('X-Api-Key', clokifyApiKey ? clokifyApiKey : environment.clokifyApiKey);
return this.http.get<any>(`https://api.clockify.me/api/workspaces/${environment.clockifyWorkSpace}/timeEntries/inProgress`, { headers })
.pipe(map((data) => { return data; }));
}
so, in this function, I have pass different clokifyApiKey and check the status of the user is currently working or not.
I hope this answer will help other people in the future.
The GET /workspaces/{workspaceId}/timeEntries/inProgress only returns your own currently running timer, not the entire workspaces, per the API docs (https://clockify.github.io/clockify_api_docs/#tag-Time-entry). So you can't get a list of active timers in the workspace other than for yourself. From what I can tell it is not possible to get a list of users with active timers.

Loading datastore based on boolean flag

I want to make a purchase order manager, where a queue is created from a database and then assembled into an accordion. Then, the user can look at requests, and then check the request when it is done. The task will then move to a "completed purchases" list.
I've been using a "notPurchased" datastore with the following server script:
query.filters.purchased._equals = false;
return query.run();
And then when the "submit" button is pressed, I call datastore.load();. However, this doesn't seem to refresh the purchase queue immediately. I have to completely refresh the page in order to see purchase request moved to 'completed'. How do I make this change instantaneous?
I figured out a solution that reduced any lag. Instead of filtering the database with a query, I bound the 'visibility' property to the proper boolean flag. Now items move instantly!

Reactively show number of unread comments in a thread?

I'm making a forum type app with Threads and Comments within a Thread. I'm trying to figure out how to show the total number of unread comments within a thread to each user.
I considered publishing all the Comments for every Thread, but this seems like excessive data to be publishing to the client when all I want is a single number showing the unread Comments. But if I start adding metadata to the Thread collection (such as numComments, numCommentsUnread...), this adds extra moving parts to the app (i.e. I have to track every time a different user adds a Comment to a Thread, etc...).
What are some of the best practices for dealing with this?
I would recommend using the Publish-Counts package (https://github.com/percolatestudio/publish-counts) if all you need is the count. If you need the actual related comments take a look at the meteor-composite-publish (https://github.com/englue/meteor-publish-composite) package.
This sounds like a database design problem.
You will have to keep a collection of UserThreads, which tracks when the last time the user checked the thread. It has the userId, the threadId, and the lastViewed date(or whatever sensible alternatives you might use).
IF the user has never checked the thread then do not have an object in the UserThreads then the unread count would be the comment count.
WHEN the user views the thread for the first time, create a UserThread object for him.
UPDATE the lastViewed on the UserThread whenever he views the thread.
The UnreadCommentCount will be calculated reactively. It is the sum of comments on the thread where the comment's createdAt is newer than the lastViewed on the UserThread. This can be a template helper function that is executed in the view on an as needed basis. For example, when listing Threads in a subforum view, then it would only calculate for the Threads being viewed in that list at that time.
Alternatively, you could keep an unreadCommentCount attribute on the UserThread. Every time a comment is posted to the thread, then you would iterate through that Thread's UserThreads, updating the unreadCommentCount. When the user later visits that thread, you then reset the unreadCommentCount to zero and updated the lastViewed. The user would then subscribe to a publication of his own UserThreads, which would update reactively.
It seems that in building a forum type site that UserThread object would be indispensable for tracking how a User interacts with Threads. If he had viewed it, ignored it, has commented in it, wants to subscribe to it but has not commented yet, etc.
Based on #datacarl answer, you can modify your thread publication to integrate additional data, such as a count of your unread comments. Here is how you can achieve it, using Cursor.observe().
var self = this;
// Modify the document we are sending to the client.
function filter(doc) {
var length = doc.item.length;
// White list the fields you want to publish.
var docToPublish = _.pick(doc, [
'someOtherField'
]);
// Add your custom fields.
docToPublish.itemLength = length;
return docToPublish;
}
var handle = myCollection.find({}, {fields: {item:1, someOtherField:1}})
// Use observe since it gives us the the old and new document when something is changing.
// If this becomes a performance issue then consider using observeChanges,
// but its usually a lot simpler to use observe in cases like this.
.observe({
added: function(doc) {
self.added("myCollection", doc._id, filter(doc));
},
changed: function(newDocument, oldDocument)
// When the item count is changing, send update to client.
if (newDocument.item.length !== oldDocument.item.length)
self.changed("myCollection", newDocument._id, filter(newDocument));
},
removed: function(doc) {
self.removed("myCollection", doc._id);
});
self.ready();
self.onStop(function () {
handle.stop();
});
I guess you can adapt this example to your case. You can remove the white list part if you need to. The count part will be covered using a request such as post.find({"unread":true, "thread_id": doc._id}).count()
Another way to achieve that is to use collection hooks. Each time you insert a comment, you hook on after the insert and you update a dedicated field "unread comments count" in your related thread document. Each time, the user read a post, you update the value.

Meteor, Iron Router and collection state in the client/server

This is my code:
Router.route "/", ->
users = Meteor.users.find().fetch().length
if users > 0
#render 'header'
else
#render 'register'
And the problem is simple: the route is called 2 time, first in the find() and later in the find.fetch().
I only want to know the number of user to determinate what template render, but in the client side is necessary fetch first, and in the server I can do it, but I don't know how to say that render the template from the client....
I need something like callback after find to know the result and do an action. How do it? Only determinate the length and take a decision, it's simple!
The reason your route is being called twice is that there is some latency before the data from your server arrives client, so when you first call it,
Meteor.users.find().fetch()
is just an empty array. Only after a fraction of second it becomes populated with some data. In general there is little you can do about, but in your particular case - since you only need to know if a user is logged in or not - you can use Meteor.userId() function instead.
If by some reason, you prefer to have the collection data being fetched prior to your route's action, then you should probably use waitOn hook with a custom subscription which is responsible for fetching the set of data you're interested in.

Find out all the Queries listening on a Meteor.js Collection

In Meteor 0.7.0.1, is it possible to count/find out the all the queries that are currently listening to a particular Collection?
I am trying to create a function which does: Whenever the number of users listening on a particular query (eg: myCollection.find({color:'red'}) becomes non-zero, execute a function whenever documents are changed/added to a second Collection anotherCollection.
When/how is the find method called? If it's called when someone hits a button on the page, for instance, simply increase a serverside variable that will increase when that happens. To decrease this variable when the user leaves the page, listen to the window.onbeforeunload event and decrease the count when it happens.
Alternately, if you have a login system, assign a boolean value such as online to each user. When they log in, make their online status true with the following code. if(Meteor.user()){Meteor.user().online=true;}. Make sure an onbeforeunload sets their online status to false when they leave. Then, do something like Meteor.users.find({online:true}).size() to get the amount of users online.
Basically, rather than update when myCollection.find({color:'red'}) is called, put that in a function. For instance:
if(Meteor.isClient){
Session.set('browsing', false);
function findColor(c){//Alerts the server when the user attempts to get a color.
//This is presuming they don't use the plain MongoDB command.
//Your button/however you're finding the color should use this command
if(!Session.get('browsing'))//if it's already true, don't increase the count
{
Meteor.call('incBrowsing');
Session.set('browsing', true);
}
return myCollection.find({color:c});
}
window.onbeforeunload = function(){Meteor.call('decBrowsing');};
}
if(Meteor.isServer){
var browsing = 0;
Meteor.methods({
incBrowsing: function(){browsing++;},
decBrowsing: function(){browsing++;}
});
}
I haven't tested this, but I hope it works for you. You didn't provide too many details on your problem, so feel free to comment below if you or I need to clarify something.

Resources