liqd / adhocracy-plus

adhocracy+ is a SaaS platform to make digital democracy easy for everyone
https://adhocracy.plus/
GNU Affero General Public License v3.0
75 stars 20 forks source link

Need help in adding a new module without start-time and end-time #2538

Closed erelsgl closed 5 days ago

erelsgl commented 10 months ago

Hi all. We want to add a new module, in which users can both add ideas and rank them at the same time, without any time-limit. It is similar to the "idea challenge" module, except that adding and ranking occurs simultaneously, and there are no start-time and end-time.

We looked at the "idea challenge" module to get an idea what to do, but got stuck. Particularly, we did not see any reference to "start-time" or "end-time" in apps.ideas.phases.

We are new to this project, so any explanations or references to the right locations in the code are welcome. Thanks!

goapunk commented 10 months ago

Hi @erelsgl , thanks for your interest in a+. Creating a module which allows you to add and rank ideas at the same time should be fairly easy. We already have a phase which allows that (see here), so all you need to do is to create a blueprint which uses this phase, see blueprints. In fact, for testing you can even create a module with that features already without any modifications if you are a bit familiar with Django and its admin interface. To do so these are the steps roughly:

  1. Create a project in the dashboard
  2. Go to the module pane in the django admin interface (e.g. http://127.0.0.1:8004/django-admin/a4modules/module/)
  3. Click Add Module
  4. Fill in all fields, for weight choose 1, for project choose the project you created in step 2. For the phases part, fill in all fields and for type choose CollectFeedbackPhase.
  5. Go back to dashboard and publish your project

Regarding the time-limit, creating a phase without time constraints might unfortunately be more complicated as a lot of the logic in the code relies on the dates being present. A trivial workaround which doesn't require any code modifications would be to just set the end-date in the very far future, which would effectively be the same as without a time-limit. If you want to have a look into changing the code I recommend looking at adhocracy4, our library which is the base for a+ and our other projects. This is also where the phases are defined, see here. If you have any more questions feel free to ask.

Cheers, Julian

oriyalperin commented 10 months ago

Thanks for your response, @goapunk.

@erelsgl and I have tried the CollectFeedbackPhase, and it works great. Now, we would like to add a new functionality, and will be happy to get some guidance.

We illustrate the need with an example. Suppose 60% of the site users are interested in health issues, and 40% are interested in education issues. So the 60% will suggest and up-vote only health issues, and the 40% will suggest and up-vote only education issues. When the ideas are sorted by "most popular", all the health issues will appear first, and the education issues will be pushed to the bottom of the list. We think this may be unfair to the minority, who may feel that their opinions are neglected.

There are new algorithms that generate fair rankings - rankings that guarantee each group of users a proportional representation for the issues important to them, among the top issues. Here is a paper that presents some such algorithms: https://arxiv.org/abs/2105.08043 . We would like to implement one of these algorithms (particularly, the "Sequential Phragmen" algorithm), and allow to sort the ideas by "fair ranking" rather than just "most popular". The ranking should be dynamic: when an issue is "accepted", the people who did not vote for that issue should get a higher priority in the new ranking, so that their opinion receives the attention it deserves.

Practically, we would like to add a new module similar to CollectFeedbackPhase, but with several changes:

We have a few questions:

  1. What is the most efficient and appropriate way to add the coins attribute to the users?
  2. Where should we implement the logic (including all calculations and algorithms that use user and rating data)?
  3. What can help us in managing this on the frontend (displaying coins and idea values)?

We would greatly appreciate any information and best practices on this matter.

Thank you!

goapunk commented 10 months ago

Hi @oriyalperin, the proposed sorting sounds really interesting. I sadly don't have any capacities to look into it in detail or provide a lot of help implementing it. I can try to answer questions as far as possible though.

  1. That depends on whether the coins are project-specific (e.g. a user has x coins in each project, or even in each module of each project, ...) or if they are global (i.e. a user has 5 coins to vote in total). For the former case, I think a new django app with a Coin Model which has a foreign key on the user and the project (or module) would be the way to go. For the latter case you could just add it to the user model (see here)
  2. I'm not completely sure where the best place would be. For the sorting, you could probably implement a custom filter which does it (for an example see the daily custom filter here). The coin logic would probably live in the ideas app (e.g. calculating if a user has coins left to rate, resetting coins if an idea is accepted, etc...)
  3. Not sure what you mean here. I guess what would help is knowledge of django templates and react, as the frontend uses a mix of both. You'd need to make changes to the idea templates and also in the react components.

In general you could maybe also get some inspiration from meinBerlin, it's a project which is based on the same code as a+. It has a module "participatory budgeting which allows users who received a token to vote on 5 proposals/ideas with that token. So it's a bit similar, there is also only upvoting/supporting a proposal and no downvoting.

Cheers, Julian

oriyalperin commented 8 months ago

Hi @goapunk,

We've added a new model to store the number of coins for each idea. Now, we're looking to display the coin amount for each idea in the idea list. We noticed that you use queryset annotations for sorting and displaying data (like positive rating count and comments count). Should we also use annotate to display the idea coins amount? Is it necessary only for calculated values? If so, do we need to create a React component that calls API methods? Thanks!

goapunk commented 8 months ago

Hi @oriyalperin, you probably don't need annotate here, it's as you said used to calculate / count things on the database level. If your coins model has a foreign key for the idea it should be very simple, just add it to the IdeaSerializer in the same way it was done for the content_type.

oriyalperin commented 8 months ago

Thank you @goapunk, I added coins to the serializer as you suggested, but it's not showing up in the idea list/details. I also attempted to display other serializer fields like creator, but instead of the username, I got the email (user as str). Any ideas on what might be missing?

goapunk commented 8 months ago

I added coins to the serializer as you suggested, but it's not showing up in the idea list/details.

Ah, sorry! I thought the idea list was in react already (it is in other projects) but it appears it isn't in . So instead of using the serializer you probably just need to add it in https://github.com/liqd/adhocracy-plus/blob/main/apps/ideas/templates/a4_candy_ideas/includes/idea_list_item.html. If your foreign_key has a related_name defined I think you can get it like object.<related_name> (e.g. object.coins).

oriyalperin commented 8 months ago

Thanks! I have another question: What is the common approach for accessing idea annotations, such as positive_rating_count, within an api method? (can't get it by idea_obj.positive_rating_count)

oriyalperin commented 7 months ago

Hi @goapunk, I have another question. I would like to create a separate tab specifically for displaying accepted ideas, essentially duplicating the existing 'Participation' tab but with a filtered list. I noticed that the 'Participation' tab includes a 'phase content' block, but I'm unsure how to customize it to show a filtered list of accepted ideas.

Thanks! I have another question: What is the common approach for accessing idea annotations, such as positive_rating_count, within an api method? (can't get it by idea_obj.positive_rating_count)

goapunk commented 7 months ago

Thanks! I have another question: What is the common approach for accessing idea annotations, such as positive_rating_count, within an api method? (can't get it by idea_obj.positive_rating_count)

It depends, maybe you have to add the annotation in the get_queryset method of the api if not done already. I will have a look later

TeaJayyy commented 5 days ago

Closing this issue since its part of https://github.com/liqd/adhocracy-plus/pull/2555.