Page MenuHomePhabricator

Load the voting Vue app on wishes and focus areas
Open, Needs TriagePublic5 Estimated Story Points

Description

The wish and focus area view pages will have the HTML generated by the server. This would also include the voting button.

User story

As a wishlist participant, I want to be able to show my support to a wish so that the WMF knows which wish is important to me.

Enable supporting individual wishes. User should be able to support a wish with or without adding a comment and remove a support.

Acceptance criteria

  • Add any necessary config settings, including one to control whether voting is enabled
  • If enabled, add the voting button to the renderWish output
  • In the BeforePageDisplay hook, load the voting module (if voting is enabled and we're on a wish or focus area page)

Designs:

https://www.figma.com/design/JcTMFwbEJPpCKBiZ16Jkel/Future-of-the-Wishlist?node-id=3797-150914&t=H8DqOupKYrNx1LOk-1

Event Timeline

Cparle renamed this task from New focus-area-votes parser function to New ((#focus-area-votes}} parser function.Mar 7 2025, 11:55 AM
MusikAnimal renamed this task from New ((#focus-area-votes}} parser function to New {{#focus-area-votes}} parser function.Mar 10 2025, 6:26 PM

I think this should be {{#community-requests-vote}}

We intentionally are leaving room for the possibility of voting on wishes some day. In the community_requests_votes table, there's a crv_request field (foreign key to the wish ID aka "request"), and crv_focus_area (foreign key to focus area ID), and just one of them would be filled. Maybe not the best schema for this (as one column will always be NULL), but it shouldn't matter too much performance-wise or in terms of storage.

So, {{#community-requests-vote}} would live in vote template, and store the data directly in the database. Then we don't need a dedicated API at all (T388220).


after writing, and on page load, trigger an api call to update the number of votes (by counting the templates on the subpage)

Not necessary per above.

Or I guess <community-requests-vote> to keep it consistent as the others are parser tags and not parser functions.

The focus areas index page will be built with PHP (T388216). This task is about when viewing a single focus area, which will use the existing Focus area template and styles for display purposes (not Vue or PHP).

after writing, and on page load, trigger an api call to update the number of votes (by counting the templates on the subpage)

I say we keep with the existing system, which has JavaScript increment the number at the /Vote count subpage (example) and it transcludes that in the focus area template. So in other words, no changes needed. If we want a cleaner solution, I think a new parser function/tag for fetching votes will do just fine, that way it can be cached by Varnish like other parser content. It's the extraneous API request (T388220) that concerns me, because that data should be available already without the need for another roundtrip to the server.

We do want to store the votes though, so the need for <community-requests-vote> remains.


If the above sounds correct, I think we only need a separate task i.e. "Vue application for voting on a focus area". This would essentially be the same app that we use now, just moved to the extension.

I think the idea with {{#focus-area-votes}} was that there's no need to actually store the votes themselves in the database, but just the total count of support votes (which can go in the focus_areas table). The votes would still be stored on a /Votes subpage using {{support}} etc. but the /Vote_count page wouldn't be needed any more. So the parser function would be (as you say) a Vue app that basically does what the current one does with a button and dialog and appending the vote to the subpage — the difference would be that it'd use an API call to store the vote count rather than a wiki page. The parser function would also perhaps count and store the votes (when the focus area page is rendered, so making it possible to handle manual votes). Having the count and store functionality server-side means it wouldn't need to be duplicated client-side (and we can't only have it client side because then manual votes wouldn't be counted until someone else votes).

Regarding parser function vs tag, I'm not sure it matters which here as it doesn't take any params and is outputting a bare div to hang the Vue app on. With the others, we've gone with a parser function where it's about storing data (because we need to wrap translate tags around param values, and that doesn't work for parser function attributes), and a tag when it's about displaying data (i.e. can output full HTML).

Do you think there's a need to store all the individual votes in the DB? Do they get queried other than to count them? I guess it'd be nice to show people a list of all of their own votes.

Ahh, I see. Sorry. I was going off of the schema we already have, which is meant to support voting on wishes too, and also different types of votes – necessitating its own table. I understand if we're now trying to trim the fat and just do a MVP.

Also, the storage happening in the Vote template could get tricky with bulk updates, and in particular deletions (say from vandalism). Perhaps solvable by putting the preexisting vote results in the process cache and comparing against it as each {{#community-requests-vote}} (or what have you) is processed. Nonetheless I can foresee that being tricky! So yeah, storing the total votes somewhere sounds pretty good.

Do you think there's a need to store all the individual votes in the DB? Do they get queried other than to count them? I guess it'd be nice to show people a list of all of their own votes.

We have repeatedly wanted to reach out to voters of a wish/focus area, but it's not that hard to run some regex on the /Votes subpage and accomplish the same.


Alright, so we want to store only the total vote count. What if we made that a parser function, i.e. {{#focus-area-vote-count|<focus-area>}}? Then it gets cached, and we don't need to build an API. We'd only need the Vue app to trigger a purge, which it needs to do anyway to ensure we get the updated /Votes page.

The part I don't like is:

… on page load, trigger an api call to update the number of votes (by counting the templates on the subpage)

Reads should be idempotent and not change any data. But also, there could be a network hiccup, runtime JS error, or some other reason that our vote count doesn't update. I'm thinking it should be more foolproof than that.

Another idea is to add a hook to listen to changes to pages starting with i.e. $wgCommunityRequestsFocusAreaPagePrefix, and do the vote counting and storage then. That seems pretty straightforward.

Hmm yeah that does sound more straightforward. Is this an existing pattern? Like are there other extensions that (for example) do a title check on onpagesavecomplete?

Updated T388220 to use the hook rather than an api call ... @Samwilson does this seem ok to you?

Very good points. I like the idea of triggering on changes to the /Votes page — could we avoid the config var because we already know if a page is a focus area (based on the presence of {{#focus-area}}) and I guess the subpage name will need to be set to something static anyway? One of the ideas I like with what we've got so far is that we're not enforcing any particular subpage structures for any of this, which I think keeps it simpler.

i.e. when a Foo/Bar/Votes subpage is edited, we count the votes and update any focus area row with a page title that matches the parent page's. Which I think could perhaps be done with something along the lines of update community_requests_focus_areas set crfa_vote_count = 3 where crfa_page = ( select page_id from page where page_title = 'Foo/Bar' LIMIT 1 ) — so if the parent isn't already a focus area, nothing happens.

We already have {{#focus-area}} (T388207) which will be used in Template:Community_Wishlist/Focus_area (or one of its sub-templates). Do we need an additional parser function just to indicate where the Vue app should add the support button, or could that container div just be part of the {{#focus-area}} output?

It could all be done in the one parser function, but I was thinking that they'd both be called in the Template:Community_Wishlist/Focus_area/Full template, and that template would then handle all the other bits like description (not short description), created and updated times, list of wishes (T387962), owners and volunteers, and transcluding the list of votes from /Votes.

{{#focus-area}} will just save the three fields that are needed to be displayed elsewhere (title, short description, and status), and not output anything. The /Full template will handle the actual display of everything (as it already does, so not much change will be needed).

Or does that sound like it splits things up too much between on-wiki and in the extension?

If they are meant to be in the same template, maybe we can just place {{#focus-area}} where we want the empty <div> to go? We'd want both wrapped in a <noinclude>, anyway, so it seems easier for both template editors and for us as engineers to have one fewer parser function.

Ok so after talking this through last night we think we're going to have 2 templates - {{focus-area-header}} and {{focus-area-footer}}, and this one will be used in the footer

This parser function doesn't have to do the wish table and transclusion, those are pretty much just <community-requests focus-area="Lorem ipsum" /> and {{:{{PAGENAME}}/Votes}} and can go in the {{focus-area-footer}}.

So perhaps this should be called {{#focus-area-vote-button}} or just {{#support-button}} or something?

Ok updated - it's kind of a tiny task now really

Cparle renamed this task from New {{#focus-area-votes}} parser function to New {{#focus-area-support}} parser function.Apr 9 2025, 9:54 AM
JWheeler-WMF set the point value for this task to 5.Apr 29 2025, 4:53 PM
HMonroy renamed this task from New {{#focus-area-support}} parser function to New <voting-button> parser tag.May 29 2025, 1:00 AM
HMonroy updated the task description. (Show Details)

Change #1151820 had a related patch set uploaded (by HMonroy; author: HMonroy):

[mediawiki/extensions/CommunityRequests@master] WIP: new voting-button parser tag

https://gerrit.wikimedia.org/r/1151820

Change #1161615 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CommunityRequests@master] WishHookHandler: add voting button and transclude /Votes

https://gerrit.wikimedia.org/r/1161615

MusikAnimal renamed this task from New <voting-button> parser tag to Load the voting Vue app on wishes and focus areas.Thu, Jun 19, 8:18 PM
MusikAnimal updated the task description. (Show Details)

Change #1163497 had a related patch set uploaded (by HMonroy; author: HMonroy):

[mediawiki/extensions/CommunityRequests@master] Add frontend functionaly to voting button

https://gerrit.wikimedia.org/r/1163497

Change #1151820 abandoned by HMonroy:

[mediawiki/extensions/CommunityRequests@master] WIP: new voting-button parser tag

Reason:

replacing it with a cleaner patch https://gerrit.wikimedia.org/r/c/mediawiki/extensions/CommunityRequests/+/1163497

https://gerrit.wikimedia.org/r/1151820

Change #1163497 merged by jenkins-bot:

[mediawiki/extensions/CommunityRequests@master] Add frontend functionaly to voting button

https://gerrit.wikimedia.org/r/1163497

I don't think there's a way to QA this yet.

Change #1165637 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CommunityRequests@master] Add SpecialEditFocusArea and focus area detail page; add voting sections

https://gerrit.wikimedia.org/r/1165637

Change #1161615 abandoned by MusikAnimal:

[mediawiki/extensions/CommunityRequests@master] WishHookHandler: add voting button and transclude /Votes

Reason:

superseded by I15ea8f39853a43af144b48605d69b0676922e386

https://gerrit.wikimedia.org/r/1161615

Change #1167294 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CommunityRequests@master] CommunityRequestsHooks: load voting RL module when applicable

https://gerrit.wikimedia.org/r/1167294

Change #1165637 merged by jenkins-bot:

[mediawiki/extensions/CommunityRequests@master] Add SpecialEditFocusArea and focus area detail page; add voting sections

https://gerrit.wikimedia.org/r/1165637

Change #1167294 merged by jenkins-bot:

[mediawiki/extensions/CommunityRequests@master] CommunityRequestsHooks: load voting RL module when applicable

https://gerrit.wikimedia.org/r/1167294

Change #1167937 had a related patch set uploaded (by HMonroy; author: HMonroy):

[mediawiki/extensions/CommunityRequests@master] Set up `wish` or `focus-area` text according to page

https://gerrit.wikimedia.org/r/1167937