@vsoch Ok, I’m going to first lay out some administrative stuff about working with Discourse and contributing to the plugin, then give you some pointers on what you’ll need to do to achieve this. I’m available to asnwer questions on any question, issue or blocker, so don’t hestiate to reach out.
Working with the plugin.
Generally speaking, the Discourse Development Contribution Guidelines apply to working with our plugins. In terms of working with us:
- Work on a branch of your fork of the repo.
- Commit as you go to make it easier for me to help you out if you get stuck.
- When you’re ready, make a PR and I’ll give your work a full review at that stage.
What you’ll need to look at for this task.
Within Discourse the general pattern for limiting user actions is to have seperate limits for each trust level. If you do a search for “tl1” or “tl2” in the config/site_settings.yml you’ll see a number of examples. At a high level, what we’ll be doing here is adding four new site settings:
Adding the settings
Add the settings in the plugin’s config/settings.yml file. They should follow the same format as the other numerical settings in there. Every site setting also needs description text in config/locales/server.en.yml. Copy the format of the other settings for adding that.
Integrating the settings
There are a few places you need to focus on.
ensure_can_act method in the VotesController. This gets run whenever a create or destroy vote action is sent from the client to the server.
The voted method of the TopicSerializer edit.
The vote method in the
qa-post widget on the client.
If you take a look at each of these you’ll see that there is a ‘voted’ property of the topic model that gets determined by the
voted class method of
Topic on the server. Essentially we need to replace this boolean check with two new properties / methods:
vote_count. A count of how many votes a user has made in a topic; and
can_vote. A comparison of how many votes a user has against the limit for their trust level
There are a number of ways you could do this. Looking at my code now (months / years on) I cringe a little at some of the ways I set this up. However, I think for our purposes now, it’s best if we follow the existing pattern / logic of the plugin, rather than re-think the structure itself.
So that means you’ll need to:
Add two new class methods for
can_vote to the Topic model on the server. Like the
voted method, use a PostCustomField query to count the user’s existing votes.
Update the serializer to serialize these new properties to the client.
Update the checks in the
vote method on the client.
Depending on how you go, with 3, you may be able to also improve on it’s current structure. Currently the client
voted check is updated optimistically prior to the vote actually getting sent down to the server (one of those things that now makes me cringe).
You could follow that pattern and make a count / limit comparison at this point to determine the
can_vote property straight afer the user has voted. However, ideally, you would disable the vote button while the data is being sent down to the server then let the server send back a ‘can_vote’ state which is then used to update the client.
If you want to tackle that structural improvement happy to give you more pointers on how to do things like disable the button while ‘loading’.
That should be enough to start you off, but let me know if you get stuck or need more context / explaination.