Page MenuHomePhabricator

Add "Contributions" tab to EventDetails special page (table view)
Closed, ResolvedPublic

Description

User story:

As an event organizer and/or participant, I want to see what everyone did during an event so that I can understand the overall output and impact.

Background information

We will be adding a new tab to EventDetails, which will be called "Contributions." For the MVP, it will have 2 sections: a table view and a summary view. This ticket represents the work to add the table view. The summary view is in a separate ticket: T402211.

The table view is sort of like a basic activity feed, in which users can see what contributions people made during an event. It is meant to give a complete picture and focus on the contributions rather than who did the "best" (i.e., it is not a leaderboard, though we may create a separate leaderboard view after we release the MVP).

This tab will be visible to everyone. However, the contributions made by private participants will only be shared with those who are allowed to see them. The contributions made by public participants will be displayed to everyone.

More notes:

  • The Contributions tab must always be visible, regardless of whether the event has associated edits or not.
  • We will always load the data, regardless of whether the user clicks the Contributions tab or not.
  • We will represent bytes as one number for the MVP. So, for example, if someone removed 1000 bytes and added 100 bytes, we will show that they removed 900 bytes.
  • Characters are out of scope for the MVP.
Acceptance criteria:
  • Given that a user is on EventDetails,
    • They should be able to see a new tab with the name "Contributions."
  • Given that a user is viewing the Contributions tab,
    • And there is contribution data associated with the event,
      • They should see a table with contribution data in the tab.
  • Given the user can see private participants for the event (e.g., they are an organizer or admin)
    • Then they should see edits for each participant who has them
  • Given the user cannot see private participants for the event
    • Then they should see edits for public participants only, and also for themself (regardless of whether they registered privately)
  • Given that they are viewing the contributions table,
    • Then each row should display the following fields:
      • Article edited (with link to article page)
      • Wiki
      • Username
      • Timestamp (with link to the diff)
      • Bytes
  • Given that a user is viewing an article listed in the table,
    • And the article was created during the event,
      • Then cdxIconArticleAdd icon should appear next to the article name
        • And when hovered, a tooltip should appear with the text: “This article was created during the event
  • Given that a user is viewing the "Article edited" column,
    • Then each article title should link to that article's page
  • Given that a user is viewing the "Wiki" column,
    • Then the content should be the localised name of the wiki (e.g., "Spanish Wiktionary") if available, and the wiki ID (e.g., "eswiktionary") otherwise, for example locally
  • Given that a user is viewing the "Timestamp" column,
    • Then each timestamp should link to the diff of that specific edit
  • Given that a user is viewing the contributions table,
    • Then all columns should be sortable
    • And the default sorting should be by timestamp
    • And for non-unique values (such as usernames and articles), the timestamp is also used as secondary sort key
  • Given that a user is viewing the contributions table,
    • Then pagination should be available at the bottom of the table allowing navigation between pages
  • Given the event has no entries in ce_event_edit_association
    • When the user opens the "Collaboration" tab on the Special:EventDetails page
      • Then the summary is shown with all values set to 0
  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • Then no query is made to fetch edit association data

Design

Desktop:

table (7).png (682×984 px, 61 KB)

tooltip (1) (1).png (84×244 px, 5 KB)

Mobile:

Make the cards in the summary scrollable horizontally. The table should also be scrollable horizontally per the component's breakpoint for mobile.

mobile (5).png (568×320 px, 24 KB)

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
JFernandez-WMF renamed this task from Draft: Add "Contributions" tab to Event Details special page to Add "Contributions" tab to Event Details special page.Aug 6 2025, 10:44 PM

Reminder to add visibility to the AC: who can view what on this page? And how does that change for private participants? And should private participants be visually distinct in the table?

Ah yes, good point, @Daimona!

Perhaps that can be handled in a separate ticket, so design is not a blocker for this work. I will create a design ticket for @JFernandez-WMF on this.

And I will update AC on who can view this page.

ifried updated the task description. (Show Details)
ifried renamed this task from Add "Contributions" tab to Event Details special page to Add "Contributions" tab to EventDetails special page (table view).Aug 20 2025, 3:49 PM
ifried updated the task description. (Show Details)
ifried updated the task description. (Show Details)

Question: what would be the default ordering? Timestamp?


  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • Then no query is made to fetch edit association data

It's the first time I'm hearing of this, I'm not sure where it comes from. I think it might be doable, but it would work such that when you click the tab, the page does a full reload (unlike for the other tabs). Otherwise we'd need to implement pagination from scratch either in JS or in a REST endpoint, either way a decent amount of work. But I'm also generally curious to hear if there are specific reasons for this. If the answer is just "performance", it's worth noting that the queries done within that tab should be efficient anyway, so they shouldn't make a huge difference overall.

Question: what would be the default ordering? Timestamp?

And more generally: what is the default secondary sorting? None of the fields (page, username, timestamp, etc.) are unique, so if we are sorting say by page, then: within a given page, how do we sort the edits? By timestamp?

[Note, the timestamp isn't unique either, but that should be rarer in practice and we can just add the unique contribution ID to disambiguate]

Question: what would be the default ordering? Timestamp?


  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • Then no query is made to fetch edit association data

It's the first time I'm hearing of this, I'm not sure where it comes from. I think it might be doable, but it would work such that when you click the tab, the page does a full reload (unlike for the other tabs). Otherwise we'd need to implement pagination from scratch either in JS or in a REST endpoint, either way a decent amount of work. But I'm also generally curious to hear if there are specific reasons for this. If the answer is just "performance", it's worth noting that the queries done within that tab should be efficient anyway, so they shouldn't make a huge difference overall.

@Daimona, Ah sorry, I copy/pasted this over from some earlier AC text that I believe @cmelo wrote. I personally do not have a preference on this topic, to be clear. I just thought there was a technical reason to implement in such a way. If there is not, I can remove it from the AC.

And good question about default sorting! Since we are considering this tab to be like an "activity feed" of recent event activity, I think it should be sorted by timestamp by default. Do you agree, @JFernandez-WMF?

Change #1182589 had a related patch set uploaded (by Mhorsey; author: Mhorsey):

[mediawiki/extensions/CampaignEvents@master] Add new contributions tab with no content

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

Change #1182615 had a related patch set uploaded (by Mhorsey; author: Mhorsey):

[mediawiki/extensions/CampaignEvents@master] Add empty table to contributions tab

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

  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • Then no query is made to fetch edit association data

It's the first time I'm hearing of this, I'm not sure where it comes from. I think it might be doable, but it would work such that when you click the tab, the page does a full reload (unlike for the other tabs). Otherwise we'd need to implement pagination from scratch either in JS or in a REST endpoint, either way a decent amount of work. But I'm also generally curious to hear if there are specific reasons for this. If the answer is just "performance", it's worth noting that the queries done within that tab should be efficient anyway, so they shouldn't make a huge difference overall.

@Daimona, Ah sorry, I copy/pasted this over from some earlier AC text that I believe @cmelo wrote. I personally do not have a preference on this topic, to be clear. I just thought there was a technical reason to implement in such a way. If there is not, I can remove it from the AC.

@cmelo Do you have more context on this?

And good question about default sorting! Since we are considering this tab to be like an "activity feed" of recent event activity, I think it should be sorted by timestamp by default. Do you agree, @JFernandez-WMF?

For default sorting makes sense to me, but there's also the question of secondary sort key from above. Note that, due to how the pager hierarchy works, all the fields that are part of the sort key would need to use the same sorting direction. So, for example, if you sort by username ascending, then for each users the edits would be sorted by timestamp ascending. If you sorted by username descending, then edits for the same user would be sorted by timestamp descending. That is, we can't sort by username descending and timestamp ascending at the same time (or vice versa). I hope this is fine.

@Daimona, I'm not sure I understand what you're saying about the secondary sort key. Are you saying that we can't apply two sorting rules at the same time - just one? If that is what you're saying, that is fine with me. However, if there's more to this, then maybe you can share an example (and apologies for any confusion on my part!).

Are you saying that we can't apply two sorting rules at the same time - just one?

This is not what I meant, but it is indeed true and maybe worth mentioning. For example, if you click the header to sort by wiki, and then you click the other header to sort by timestamp, the original ordering by wiki is lost. That is, you can only choose to sort on one thing at a time.

However, my point was slightly different. None of the columns in this table uniquely identify an edit: for example, there are going to be multiple edits for the same wiki, or from the same user, etc. So, if say you sort edits by user, you will see all the edits of User:Alice before those of User:Bob, but we still need to determine how Alice's and Bob's edit are sorted within the respective groups. My proposal is that we use the timestamp. The other thing is that all the "properties" that we sort by must use the same ordering. So, if we sort by username ascending (first Alice, then Bob), edits for each user would also be in ascending order (from oldest to newest). And if you sort by username descending (first Bob, then Alice), edit times would also be in descending order (from newest to oldest).

Simplified example, where I'm just using ordinals in lieu of timestamps:

Default sorting (timestamp asc)Sort by timestamp descSort by user ascSort by user desc
- Alice T_1
- Bob T_2
- Alice T_3
- Bob T_4
- Bob T_4
- Alice T_3
- Bob T_2
- Alice T_1
- Alice T_1
- Alice T_3
- Bob T_2
- Bob T_4
- Bob T_4
- Bob T_2
- Alice T_3
- Alice T_1

And this would work the same way for the other sortable properties other than user: the timestamp is always used as the secondary sort key.

@Daimona, aaaah, yes, I understand what you're asking. Thanks for patiently breaking it down with an example :)

Yes, I think timestamp makes sense as the secondary sorting logic, especially since it is the default sorting we have when someone views the page.

So, if we sort by username ascending (first Alice, then Bob), edits for each user would also be in ascending order (from oldest to newest). And if you sort by username descending (first Bob, then Alice), edit times would also be in descending order (from newest to oldest).

I think this behavior could seem kind-of weird, from a user perspective. I think it would be more common to expect that the sorting order for edit timestamp would remain the same in these two examples. BUT, if that is just how things work, then I think it's probably okay and I wouldn't want to over-complicate things by trying to bend how things naturally work, especially for the MVP & prior to user feedback on the first testable version.

So, in summary: Yes, this should be fine.

I think this behavior could seem kind-of weird, from a user perspective. I think it would be more common to expect that the sorting order for edit timestamp would remain the same in these two examples. BUT, if that is just how things work, then I think it's probably okay and I wouldn't want to over-complicate things by trying to bend how things naturally work, especially for the MVP & prior to user feedback on the first testable version.

I agree, it is a bit weird. After the initial version we can maybe look into this and see how difficult it'd be to change.

I agree, it is a bit weird. After the initial version we can maybe look into this and see how difficult it'd be to change.

Yup, works for me. Thank you, @Daimona!

Change #1182589 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] Add new contributions tab with no content

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

  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • Then no query is made to fetch edit association data

It's the first time I'm hearing of this, I'm not sure where it comes from. I think it might be doable, but it would work such that when you click the tab, the page does a full reload (unlike for the other tabs). Otherwise we'd need to implement pagination from scratch either in JS or in a REST endpoint, either way a decent amount of work. But I'm also generally curious to hear if there are specific reasons for this. If the answer is just "performance", it's worth noting that the queries done within that tab should be efficient anyway, so they shouldn't make a huge difference overall.

@Daimona, Ah sorry, I copy/pasted this over from some earlier AC text that I believe @cmelo wrote. I personally do not have a preference on this topic, to be clear. I just thought there was a technical reason to implement in such a way. If there is not, I can remove it from the AC.

@cmelo Do you have more context on this?

And good question about default sorting! Since we are considering this tab to be like an "activity feed" of recent event activity, I think it should be sorted by timestamp by default. Do you agree, @JFernandez-WMF?

For default sorting makes sense to me, but there's also the question of secondary sort key from above. Note that, due to how the pager hierarchy works, all the fields that are part of the sort key would need to use the same sorting direction. So, for example, if you sort by username ascending, then for each users the edits would be sorted by timestamp ascending. If you sorted by username descending, then edits for the same user would be sorted by timestamp descending. That is, we can't sort by username descending and timestamp ascending at the same time (or vice versa). I hope this is fine.

We decided not to implement lazy loading for the Contributions tab. While the initial idea was to only fetch the data when the user clicks the tab, in practice the queries are lightweight and won’t significantly affect performance. On the other hand, implementing lazy loading would require considerable effort without bringing much benefit in this case. Therefore, we opted to always load the data regardless of whether the user clicks the Contributions tab or not.
cc: @ifried @MHorsey-WMF @Daimona

Thank you, @cmelo!

FYI, I have updated the description in the ticket to no longer state that we should try to do lazy loading and instead: "We will always load the data, regardless of whether the user clicks the Contributions tab or not."

Test wiki created on Patch demo by CMelo (WMF) using patch(es) linked to this task:
https://554fabc3ca.catalyst.wmcloud.org/w/

Test wiki created on Patch demo by CMelo (WMF) using patch(es) linked to this task:
https://27a4ec2259.catalyst.wmcloud.org/w/

Test wiki on Patch demo by CMelo (WMF) using patch(es) linked to this task was deleted:

https://554fabc3ca.catalyst.wmcloud.org/w/

Test wiki created on Patch demo by CMelo (WMF) using patch(es) linked to this task:
https://ce2d28a2bc.catalyst.wmcloud.org/w/

Test wiki created on Patch demo by CMelo (WMF) using patch(es) linked to this task:
https://2b7ac98b54.catalyst.wmcloud.org/w/

Test wiki on [[ | Patch demo ]] by CMelo (WMF) using patch(es) linked to this task was deleted:

https://2b7ac98b54.catalyst.wmcloud.org/w/

Test wiki created on Patch demo by CMelo (WMF) using patch(es) linked to this task:
https://c55106d465.catalyst.wmcloud.org/w/

Test wiki on Patch demo by CMelo (WMF) using patch(es) linked to this task was deleted:

https://c55106d465.catalyst.wmcloud.org/w/

@ifried @JFernandez-WMF question that came up in code review: for the "wiki" column, what are we showing? Options are:

  • URL: es.wikipedia.org
  • ID: eswiki
  • Localised: Spanish Wikipedia

@Daimona, ty for this question! I think the localized name makes sense and it's pretty self-explanatory for both organizers and participants. we also use localized names in Special:AllEvents, so also better for consistency on language. @ifried what do you think?

Yes, localized name is the way to go! The most intuitive and clear. Thank you!

Change #1182615 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] Add contributions table to contributions tab

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

Change #1193442 had a related patch set uploaded (by Daimona Eaytoy; author: Daimona Eaytoy):

[mediawiki/extensions/CampaignEvents@master] EventContributionsPager: add cec_id to queries for uniqueness

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

Change #1193442 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] EventContributionsPager: add cec_id to queries for uniqueness

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

Acceptance criteria:
  • Given that a user is on EventDetails,
    • ✅ They should be able to see a new tab with the name "Contributions."
  • Given that a user is viewing the Contributions tab,
    • ✅ And there is contribution data associated with the event,
      • ✅ They should see a table with contribution data in the tab.
  • Given the user can see private participants for the event (e.g., they are an organizer or admin)
    • ✅ Then they should see edits for each participant who has them
  • Given the user cannot see private participants for the event
    • ✅ Then they should see edits for public participants only, and also for themself (regardless of whether they registered privately)
  • Given that they are viewing the contributions table,
    • Then each row should display the following fields:
      • ✅ Article edited (with link to article page)
      • ✅ Wiki
      • ✅ Username
      • ✅ Timestamp (with link to the diff)
      • ✅ Bytes
      • Screenshot 2025-10-23 at 4.05.29 PM.png (328×2 px, 87 KB)
  • Given that a user is viewing an article listed in the table,
    • And the article was created during the event,
      • ✅ Then cdxIconArticleAdd icon should appear next to the article name
        • ✅ And when hovered, a tooltip should appear with the text: “This article was created during the event
  • Given that a user is viewing the "Article edited" column,
    • ✅ Then each article title should link to that article's page
  • Given that a user is viewing the "Wiki" column,
    • Then the content should be the localised name of the wiki (e.g., "Spanish Wiktionary") if available, and the wiki ID (e.g., "eswiktionary") otherwise, for example locally
    • QA note - I will want to check this further when this is on betacluster
  • Given that a user is viewing the "Timestamp" column,
    • ✅ Then each timestamp should link to the diff of that specific edit
  • Given that a user is viewing the contributions table,
    • ✅ Then all columns should be sortable
    • ✅ And the default sorting should be by timestamp
    • ❓ And for non-unique values (such as usernames and articles), the timestamp is also used as secondary sort key
    • QA note - the timestamp is correctly used as a secondary sort key, but it is currently used as a secondary sort key in ascending order, whereas when timestamp is used as the default, it is used in descending order. I feel this secondary timestamp sort key should also be descending, as it is when the default view for the contributions tab is viewed. This would make the experience more consistent, IMO. Thoughts @cmelo? see current behavior below
default view, sorted by descending timestamp valuessecondary sort, timestamp is in ascending order
Screenshot 2025-10-23 at 4.16.16 PM.png (538×1 px, 88 KB)
Screenshot 2025-10-23 at 4.19.04 PM.png (578×1 px, 113 KB)
  • Given that a user is viewing the contributions table,
    • ❌ Then pagination should be available at the bottom of the table allowing navigation between pages
    • QA Note - this definitely was working, but now the pager is not appearing on any of my events' contributions tabs. This table shown below has 22 edits, and before I believe the pager should start displaying at 20 edits. Maybe I am doing something wrong here?
      Screen Recording 2025-10-23 at 7.56.21 PM.gif (1×1 px, 2 MB)
  • Given the event has no entries in ce_event_edit_association
    • When the user opens the "Collaboration" tab on the Special:EventDetails page
      • ✅ Then the summary is shown with all values set to 0
  • Given the user visits the Special:EventDetails page
    • When the "Collaboration" tab is not yet clicked
      • ❓ Then no query is made to fetch edit association data
      • QA Note - I am not seeing any requests happen in the chrome network tab nor in the logs when I click on the Contributions tab, but the data is already there when I click the tab, so I am not sure how to test that is happening using an api call at the time of the click on the contributions tab, and not on page load. How can I best test that this query is not being made until the Collaboration tab is clicked?

Thanks @vaughnwalters!

For:

Given the user visits the Special:EventDetails page
When the "Collaboration" tab is not yet clicked
❓ Then no query is made to fetch edit association data
QA Note - I am not seeing any requests happen in the chrome network tab nor in the logs when I click on the Contributions tab, but the data is already there when I click the tab, so I am not sure how to test that is happening using an api call at the time of the click on the contributions tab, and not on page load. How can I best test that this query is not being made until the Collaboration tab is clicked?

I will update the AC, we decided to load all the data when the page is open instead of just when the tab is clicked, in terms of performance there is not much difference, and implement this new behavior of loading the data only when the tab is clicked is not supported by default and would require a big effort to implement it properly.

Given that a user is viewing the contributions table,
❌ Then pagination should be available at the bottom of the table allowing navigation between pages
QA Note - this definitely was working, but now the pager is not appearing on any of my events' contributions tabs. This table shown below has 22 edits, and before I believe the pager should start displaying at 20 >> edits. Maybe I am doing something wrong here?

This should work, I will take a look, thanks!

QA note - the timestamp is correctly used as a secondary sort key, but it is currently used as a secondary sort key in ascending order, whereas when timestamp is used as the default, it is used in descending order. I >>feel this secondary timestamp sort key should also be descending, as it is when the default view for the contributions tab is viewed. This would make the experience more consistent, IMO. Thoughts @cmelo? see >>current behavior below

I agree, I will take a look to understand the reason why, thanks!

Thanks @vaughnwalters!

For:

Given the user visits the Special:EventDetails page
When the "Collaboration" tab is not yet clicked
❓ Then no query is made to fetch edit association data
QA Note - I am not seeing any requests happen in the chrome network tab nor in the logs when I click on the Contributions tab, but the data is already there when I click the tab, so I am not sure how to test that is happening using an api call at the time of the click on the contributions tab, and not on page load. How can I best test that this query is not being made until the Collaboration tab is clicked?

I will update the AC, we decided to load all the data when the page is open instead of just when the tab is clicked, in terms of performance there is not much difference, and implement this new behavior of loading the data only when the tab is clicked is not supported by default and would require a big effort to implement it properly.

Okay thank you for the update!

Given that a user is viewing the contributions table,
❌ Then pagination should be available at the bottom of the table allowing navigation between pages
QA Note - this definitely was working, but now the pager is not appearing on any of my events' contributions tabs. This table shown below has 22 edits, and before I believe the pager should start displaying at 20 >> edits. Maybe I am doing something wrong here?

This should work, I will take a look, thanks!

Ah, okay yes thank you for letting me know that it is now 50 edits before pagination works. This is working as expected when I added more edits now! 🎉

QA note - the timestamp is correctly used as a secondary sort key, but it is currently used as a secondary sort key in ascending order, whereas when timestamp is used as the default, it is used in descending order. I >>feel this secondary timestamp sort key should also be descending, as it is when the default view for the contributions tab is viewed. This would make the experience more consistent, IMO. Thoughts @cmelo? see >>current behavior below

I agree, I will take a look to understand the reason why, thanks!

Okay thanks @cmelo. I can create a new ticket too if that is easier.

QA note - the timestamp is correctly used as a secondary sort key, but it is currently used as a secondary sort key in ascending order, whereas when timestamp is used as the default, it is used in descending order. I >>feel this secondary timestamp sort key should also be descending, as it is when the default view for the contributions tab is viewed. This would make the experience more consistent, IMO. Thoughts @cmelo? see >>current behavior below

I agree, I will take a look to understand the reason why, thanks!

Okay thanks @cmelo. I can create a new ticket too if that is easier.

Thanks @vaughnwalters, yes another ticket would be good, thanks!!!

QA note - the timestamp is correctly used as a secondary sort key, but it is currently used as a secondary sort key in ascending order, whereas when timestamp is used as the default, it is used in descending order. I >>feel this secondary timestamp sort key should also be descending, as it is when the default view for the contributions tab is viewed. This would make the experience more consistent, IMO. Thoughts @cmelo? see >>current behavior below

I agree, I will take a look to understand the reason why, thanks!

Okay thanks @cmelo. I can create a new ticket too if that is easier.

Thanks @vaughnwalters, yes another ticket would be good, thanks!!!

Okay, sounds good @cmelo I created T408923 to work on this.

With that, all of the AC has been met or has follow up tasks. I'm sending this to design sign off. @JFernandez-WMF here are some screencaps of the most current version:

fullmobile
Screenshot 2025-10-31 at 11.08.04 AM.png (1×1 px, 330 KB)
Screen Recording 2025-10-31 at 3.20.48 PM.gif (1×592 px, 3 MB)

thank you! @cmelo, one question: is the pagination going to be at the bottom? is there a task for this?

thank you! @cmelo, one question: is the pagination going to be at the bottom? is there a task for this?

Heya @JFernandez-WMF yes the pagination is at the bottom, but it won't appear unless there are are over 50 rows:

Screen Recording 2025-11-05 at 10.00.14 AM.gif (1×3 px, 1 MB)