Closed oliverbarnes closed 3 years ago
this can easily become an umbrella issue as well. Once we have individual tasks, let's toss it
I've added a list of steps in 1st comment. I'll convert these to individual issues.
Probably better if I ask for comments / thoughts before converting to individual issues. Any suggestions / comments?
It's pretty good, here's what I noticed:
To implement "either supports or endorsements, at the Proposal level", you'll need database support, so add a migration for proposals.delegation_subject (:support, :endorsement), as well as the rake task for copying local migrations. Also, this should reuse the same delegations controller, but rename ProposalVoteDelegationsController
to ProposalDelegationsController
. Also create a helper for the views to ask a helpful question like if delegating_supports|endorsements
.
I think it's worth copying/adapting the specs for endorsements, and using a red spec to drive the implementation...it's pretty good for focus since it's implementing outside-in, and when it's green you're done with happy path.
I like your leaving the admin UI for the end. You can also defer the database work, and just hardcode a value that you can alter during dev.
Also create a helper for the views to ask a helpful question like
if delegating_supports|endorsements
.
@davefrey Not sure I understand the delegating
part. Why not just if supports|endorsements
?
The proposed config point, as I understand it, is used to decide "are we enabling delegation for Proposal Supports or Proposal Endorsements (or neither)?", for ex in the view where we're rendering the components.
The view could have if supports?
but it's a little unclear to someone reading the code fresh.
Also if we want to handle all three cases, I think it reads better
if delegating_support?
...
else if delegating_endorsements?
...
else
... classic decidim UI w/o delegation elements
Ahh, I see. I had assumed we were changing core Decidim Proposals functionality to totally either Supports or Proposals. i.e. You either see Supports + delegations, OR Endorsements + delegations.
I like your version better though.
So, we could have something like: delegation_mode
, with 3 possible values: null / "supports" / "endorsements"
.
Maybe an explicit "off"
is better than null
?
I propose reorganizing the plan to be:
if delegating_supports|endorsements
By starting with creating the admin mode switch, this would enable me to keep the specs for the current 'supports' implementation, (by using a factory that includes the new mode), and thus ensure I don't break what already works as I develop the endorsements stuff. Thoughts?
I think the admin switch should be later, because we still haven't had oliver input on our approach. I'd just hardcode it (you can just put your helpers in the controller and hardcode a boolean return)
I think the admin switch should be later, because we still haven't had oliver input on our approach. I'd just hardcode it (you can just put your helpers in the controller and hardcode a boolean return)
Boolean? We are proposing 3 states, no? Off, Supports, or Endorsements.
How do I write specs that use the controller hardcoding? How can I, for example, test that the 'Support' button does not get disabled when an Endorsements delegation is made.
If it were me, I'd set off in this order:
there are indeed three states. I propose the helper methods be boolean questions because it reads better in the (already semantically heavy) views. See code snippet above
I'm happy with sticking to the original plan order, but so far I haven't found a way to emulate different 'modes' when testing, as the hardcoded controller value seems always to override anything set in an rspec let
or before
statement.
So, here's my take: it's a safe to assume a user delegating their support for a proposal to a given person would also delegate their endorsement to them, or at least a vast majority of users would. And if we have the delegation simply work for both supports and endorsements, we avoid the whole admin configuration bit, and what's left to implement will be very similar to what was done for supports.
I think this would be a good-enough first version. If in the future we find that users actually have a strong demand for separating their delegations for support and endorsements, then we bite the bullet and implement that choice.
What do you think?
Summarizing conversations from slack and pairing:
proposal_url
to include support/endorse (propose adding a &LV_voting_method=ā[support|endorse]ā
param, or an additional url segment)proposal_url
. Withdrawing a delegation removes both from LVcreate_vote
to LV with the extended url. The returned votingResult
has data specific to the Support or Endorsement, and the controller updates either proposals.proposal_vote_count
or proposals.endorsements_count
.Endorsement
model and Proposal#endorsements
association are abandoned, just like ProposalVote
Extending the proposal_url
is hacking around a data model mismatch between Decidim and Liquidvoting: Decidim conceptually has both a voteable thing (Proposal), and a vote method (Support, Endorse), but Liquidvoting has only a voteable thing (today this is explicitly a proposal_url
). Our hack is to collapse the two Decidim things into the single LV thing.
Going through all the Decidim kinds of voting will be a nice test for our model, and that might be the right time to take what we learn to a LV refactoring. In any case, proposal_url
as a name in LV is taking a beating :-)
I like where this is going :)
The issue of different voting methods was going to come up sooner or later, it was expected: down the line we'll have to tackle things like quadratic voting, for example. Endorsements vs supports for a given same proposal lets us start on this abstraction incrementally, since we simply need to distinguish between them, without changing any other mechanics on the API. We basically need separate tallies for each.
Instead of using a url hack, though, I'd go ahead and add a new voting_method
graphql field to vote mutations and queries, and to voting results, on the API. A string field mapping to entries in a new voting_methods
db table there, that gets upserted so we avoid the need for pre-seed or for an admin interface to manage it.
As for the delegations, I don't see the need for separate ones for each voting method at this point, for the reasons I explained on my last comment. I think it's Good Enough to have a single delegation for both supports and endorsements for a given proposal, and the user will be able to override that with their own support or endorsement. If the need for separate delegations arises, we can implement this later.
... A string field mapping to entries in a new
voting_methods
db table there, that gets upserted so we avoid the need for pre-seed or for an admin interface to manage it.
So, we would have a new voting_methods
table on our LV api. This would map a vote.uuid
to a method (support vs. endorse, for example). Would also map a voting_result.uuid
to a method. Is this what you mean?
As for the delegations, I don't see the need for separate ones for each voting method at this point...
Agree.
~I think we're still not aligned (which is normal), and we can discuss in person as three in our meeting tomorrow.~ (old text, I think this is cleared up now)
And I think stepping up to voting_method
does simplify back to a single delegation. There is just one voteable thing, so one delegation. We'll need to change votingResult
to either be a list, or include a count (etc) per voting method, counts will be different for Support and Endorse
.... new
voting_method
graphql field to vote mutations and queries, and to voting results, on the API
And this field would be optional? To allow our api to still work in it's purest, no voting method specified, way, as (for example) in the api readme examples. So we could use a create_vote
api function, for example, that picks up the voting_method
field if present and does the voting_method
table stuff, and if no voting_method
is specified the votes/results etc. are processed as they are now (without considering any voting_method
.
@jinjagit:
So, we would have a new
voting_methods
table on our LV api. This would map avote.uuid
to a method (support vs. endorse, for example). Would also map avoting_result.uuid
to a method. Is this what you mean?
Well, it would map to an association, perhaps like this on the Vote
schema:
defmodule LiquidVoting.Voting.Vote do
schema "votes" do
belongs_to :voting_methods, VotingMethods
Same for VotingResult
.
And this field would be optional? To allow our api to still work in it's purest, no voting method specified, way, as (for example) in the api readme examples. So we could use a create_vote api function, for example, that picks up the voting_method field if present and does the voting_method table stuff, and if no voting_method is specified the votes/results etc. are processed as they are now (without considering any voting_method.
š agreed, it should be optional. To avoid splitting db queries we can just have an empty entry in the db - but this is an implementation detail we can figure out during, well, implementation
@davefrey:
or include a count (etc) per voting method, counts will be different for Support and Endorse
This one. One VotingResult
per VotingMethod
, through an association.
I'll include all of this in an issue I'll open next, on the api
repo.
Well, it would map to an association, perhaps like this on the
Vote
schema:
Ahh, I see. And this table would list the different voting methods, which makes it easier to add more / see what they are / use them in other ways. :+1:
exactly :)
We should probably use "Decidim_proposal_supports" & "Decidim_proposal_endorsements", or something like that, as naming schemes for the voting_method
then, to be really clear.
That's something to think about... though remember this would also be restricted by organization, like everything else. So entries wouldn't be shared between orgs that use different platforms, for instance. And within Decidim itself, afaik both supports
and endorsements
only exist in the context of a proposal
.
Good point. I keep forgetting about the org level thing.
So, new plan is something like this:
voting_method
via createVote
, deleteVote
and calculateVotingResult
GraphQl queries/mutations, including extension of all involved functions as appropriate / necessary (and adding new upsert_voting_method
functionality).voting_method
, and update Decidim support count using the LV voting_result for this voting_method
.voting_method
for supports. (i.e. the 'correct' voting_result is updated accurately, when/if delegate supports/unsupports)voting_method
, and update Decidim endorsement count using the LV voting_result for this voting_method
.voting_method
for endorsements. (i.e. the 'correct' voting_result is updated accurately, when/if delegate endorses/unendorses)All TDD, of course ;-) [I'll update the issues related to the proposed steps, if/when this agreed as OK]
- [ ] Extend LV api to accept and use (optional)
voting_method
viacreateVote
,deleteVote
andcalculateVotingResult
GraphQl queries/mutations, including extension of all involved functions as appropriate / necessary (and adding newupsert_voting_method
functionality).
š https://github.com/liquidvotingio/api/issues/225
- [ ] Use LV api to record Decidim proposal supports as associated with respective
voting_method
, and update Decidim support count using the LV voting_result for thisvoting_method
.
Covered by https://github.com/liquidvotingio/api/issues/225 as well
- [ ] Ensure delegation/undelegation on Decidim proposals works smoothly with new LV
voting_method
for supports. (i.e. the 'correct' voting_result is updated accurately, when/if delegate supports/unsupports)
I don't foresee any change on the delegation part of things, but definitely on the results calculation. Also part of https://github.com/liquidvotingio/api/issues/225
- [ ] Use LV api to record Decidim proposal endorsements as associated with respective
voting_method
, and update Decidim endorsement count using the LV voting_result for thisvoting_method
.
š we need an issue for this here on the module repo
- [ ] Ensure delegation/undelegation on Decidim proposals works smoothly with new LV
voting_method
for endorsements. (i.e. the 'correct' voting_result is updated accurately, when/if delegate endorses/unendorses)
same issue as above
All TDD, of course ;-)
As long as it doesn't block things :) it's ok to come up with code before tests when TDD is too slow.
This can be closed now that tasks have been hashed out.
Update by @jinjagit
EDIT: - plan revised after discussions below. Plasn is now:
voting_method
viacreateVote
,deleteVote
andcalculateVotingResult
GraphQl queries/mutations, including extension of all involved functions as appropriate / necessary (and adding newupsert_voting_method
functionality). See #225voting_method
, and update Decidim support count using the LV voting_result for thisvoting_method
. See #225voting_method
, and update Decidim endorsement count using the LV voting_result for thisvoting_method
.voting_result
(s) is/are updated accurately (on LV api & then to Decidim), when/if delegate endorses/unendorses)