Page MenuHomePhabricator

Change Special:EditWatchlist layout to a table
Closed, ResolvedPublic

Assigned To
Authored By
Cparle
Dec 3 2025, 10:44 AM
Referenced Files
F71774398: Edit watchlist_V3.jpg
Feb 9 2026, 4:05 PM
F71710718: 2026-02-06_10-33-27.webm
Feb 6 2026, 8:06 PM
F71711145: 2026-02-06_10-07-19.png
Feb 6 2026, 8:06 PM
F71710637: 2026-02-06_10-24-39.png
Feb 6 2026, 8:06 PM
F71710633: 2026-02-06_10-19-08.png
Feb 6 2026, 8:06 PM
Restricted File
Jan 28 2026, 8:30 PM
F71619044: Edit watchlist_V3.jpg
Jan 28 2026, 1:05 PM
F71598121: 2026-01-23_10-15-36.png
Jan 23 2026, 7:12 PM

Description

Update the layout of Special:EditWatchlist so that pages from each namespace are in their own table. Create the table using CodexPHP

Edit watchlist_V3.jpg (1,440×1,054 px, 354 KB)

Columns are:

  • checkbox
  • page title
  • expiry (if it exists)

The design has sorting, but we do not want sorting - we can only sort by page title, and with pagination clicking to go to the last page is functionally equivalent to reverse-sorting by title

We can't implement the "Page x-y of z" part shown in the design on the backend, so that will be missing

Don't change the buttons in this ticket - we need to talk to design first

Don't put this behind our WatchlistLabels feature flag

If there's refactoring on Special:EditWatchlist to be done (and there is), do it under this ticket


Derived Requirements

  1. Special:EditWatchlist must be updated to use a table-based layout, with pages grouped into separate tables per namespace.
  2. Each namespace table must be implemented using CodexPHP components.
  3. Each table must include the following columns only:
    • Selection checkbox
    • Page title
    • Expiry, displayed only when an expiry exists
  4. Page title ordering must follow the existing behavior and must not introduce new sorting controls or sortable headers.
  5. No additional sorting mechanisms beyond the current page title ordering may be introduced.
  6. Pagination behavior must remain unchanged, and no pagination controls may imply or introduce sorting functionality.
  7. Existing action buttons on Special:EditWatchlist must remain unchanged in placement, behavior, and appearance.
  8. The table-based layout must not be gated behind the WatchlistLabels feature flag.
  9. Any required refactoring of Special:EditWatchlist necessary to support the new layout must be included as part of this change without altering user-facing behavior beyond the layout update.
Test Steps

Test Case 1: Namespace-Based Table Layout

Preconditions

  • The user is logged in.
  • The watchlist contains pages from multiple namespaces.
  1. Navigate to Special:EditWatchlist.
  2. Observe the overall page layout.
  3. Identify how watchlist items are grouped.
  4. ✅❓❌⬜ AC1: Verify that watchlist items are displayed in separate tables per namespace and that each table clearly corresponds to a single namespace.

Test Case 2: Table Structure and Columns

Preconditions

  • Same as Test Case 1.
  • At least one watchlist item has an expiry set.
  1. Inspect any namespace table on Special:EditWatchlist.
  2. Review the column headers and row structure.
  3. Locate a row with an expiry and one without.
  4. ✅❓❌⬜ AC2: Verify that each table contains only the checkbox, page title, and expiry columns, and that the expiry column displays values only when an expiry exists.

Test Case 3: No Sorting Controls Introduced

Preconditions

  • Same as Test Case 1.
  1. Inspect table headers for interactive elements.
  2. Attempt to click on column headers.
  3. Observe page behavior.
  4. ✅❓❌⬜ AC3: Verify that no sortable headers or sorting controls are present and that clicking column headers does not change item order.

Test Case 4: Pagination Behavior Remains Unchanged

Preconditions

  • The watchlist contains enough items to trigger pagination.
  1. Navigate to the first page of Special:EditWatchlist.
  2. Use pagination controls to move between pages.
  3. Navigate to the last page using pagination.
  4. ✅❓❌⬜ AC4: Verify that pagination behaves as before, with no new sorting implications and that navigating to the last page functions equivalently to existing behavior.

QA Results - Meta Beta

Event Timeline

Cparle changed the task status from Open to In Progress.Dec 3 2025, 5:21 PM
Cparle claimed this task.
Cparle moved this task from Ready for Dev to In Development on the Community-Tech (Fox Squad) board.

Change #1214483 had a related patch set uploaded (by Pppery; author: Shivaansh Singh):

[mediawiki/core@master] Update EditWatchlist to display pages in Codex tables per namespace

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

Change #1217764 had a related patch set uploaded (by Cparle; author: Cparle):

[mediawiki/core@master] Display watchlist items in a table in Special:EditWatchlist

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

Change #1217764 merged by jenkins-bot:

[mediawiki/core@master] Display watchlist items in a table in Special:EditWatchlist

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

Change #1214483 abandoned by Shivaansh Singh:

[mediawiki/core@master] Update EditWatchlist to display pages in Codex tables per namespace

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

@Cparle Please review AC1, AC2 and AC4, thanks!

Test Result - Beta

Status: ✅ PASS / ❓ Need More Info / ❌ FAIL
Environment: Beta
OS: macOS Tahoe 26.1
Browser: Chrome 143
Device: MBA
Emulated Device: NA

Test Artifact(s):

Test Steps

Test Case 1: Namespace-Based Table Layout

Preconditions

  • The user is logged in.
  • The watchlist contains pages from multiple namespaces.
  1. Navigate to Special:EditWatchlist.
  2. Observe the overall page layout.
  3. Identify how watchlist items are grouped.
  4. AC1: Verify that watchlist items are displayed in separate tables per namespace and that each table clearly corresponds to a single namespace.

Do you have the latest Figma design for this? I don't see how I can test Expiry since there are no options. If it's not ready, can you update the task description?

2026-01-14_16-36-24.png (1,603×1,141 px, 215 KB)

Test Case 2: Table Structure and Columns

Preconditions

  • Same as Test Case 1.
  • At least one watchlist item has an expiry set.
  1. Inspect any namespace table on Special:EditWatchlist.
  2. Review the column headers and row structure.
  3. Locate a row with an expiry and one without.
  4. AC2: Verify that each table contains only the checkbox, page title, and expiry columns, and that the expiry column displays values only when an expiry exists.

How can I test Expiry if there are no options?

Test Case 3: No Sorting Controls Introduced

Preconditions

  • Same as Test Case 1.
  1. Inspect table headers for interactive elements.
  2. Attempt to click on column headers.
  3. Observe page behavior.
  4. AC3: Verify that no sortable headers or sorting controls are present and that clicking column headers does not change item order.

Test Case 4: Pagination Behavior Remains Unchanged

Preconditions

  • The watchlist contains enough items to trigger pagination.
  1. Navigate to the first page of Special:EditWatchlist.
  2. Use pagination controls to move between pages.
  3. Navigate to the last page using pagination.
  4. AC4: Verify that pagination behaves as before, with no new sorting implications and that navigating to the last page functions equivalently to existing behavior.

When you click on the next page arrow and previous page arrow, they seem to work fine. When you click on the last page arrow, it displays the incorrect amount. The first page changes from 20 being shown to 13, and vice versa, on the next page.

@GMikesell-WMF

Test case 1:
We agreed not to separate the namespaces into different tables, but it seems like the figma hasn't been updated. I pinged @JSengupta-WMF on slack about this

Test case 2:
In order to see the expiry you need to add an expiry when you're watching a page

Test case 4:
Can't see the video, but if what you're describing is something like this:

  1. You have 55 items in your watchlist, so you see 50 items on your first page, click the "next page" arrow and you see 5 items
  2. Click the "previous page" arrow you get back to the first page, and you see 50 items
  3. Click the "last page" arrow and you see the last 50 items
  4. Click the "previous page" arrow from there and you see the first 5 items

... then I think this is how pagination has always worked? Could be wrong though, maybe @tstarling or @Samwilson can verify?

@GMikesell-WMF please use this updated version of the design for validation. We discussed this in a planning meeting sometime ago.

Edit watchlist_V3.jpg (1,440×1,054 px, 354 KB)

@Cparle does the story description need to be changed?

Cparle updated the task description. (Show Details)

@Cparle Can you please review AC2 (which is based off the screenshot from T411596#11545161) and AC4 (another question), thanks!

Test Result - Beta

Status: ✅ PASS / ❓ Need More Info / ❌ FAIL
Environment: Beta
OS: macOS Tahoe 26.1
Browser: Chrome 143
Device: MBA
Emulated Device: NA

Test Artifact(s):

Test Steps

Test Case 1: Namespace-Based Table Layout

Preconditions

  • The user is logged in.
  • The watchlist contains pages from multiple namespaces.
  1. Navigate to Special:EditWatchlist.
  2. Observe the overall page layout.
  3. Identify how watchlist items are grouped.
  4. ⬜  AC1: Verify that watchlist items are displayed in separate tables per namespace and that each table clearly corresponds to a single namespace.

We agreed not to separate the namespaces into different tables per T411596#11544755

Test Case 2: Table Structure and Columns

Preconditions

  • Same as Test Case 1.
  • At least one watchlist item has an expiry set.
  1. Inspect any namespace table on Special:EditWatchlist.
  2. Review the column headers and row structure.
  3. Locate a row with an expiry and one without.
  4. AC2: Verify that each table contains only the checkbox, page title, and expiry columns, and that the expiry column displays values only when an expiry exists.

Based off the updated screenshot from T411596#11545161

  • Permanent does not show in Expiry when I select Permanent, it just shows as a blank
  • 1 week and 3 months show the correct days but 1 month and 6 month shows 31 and 181 days
  • Expiry shows days left in your watchlist, besides just days
  • The header shows Expiry, besides Expires in
  • The labels shows Unwatch, Assign labels, Remove labels and in that order besides Assign label, Remove label, Remove title
  • For example, at the top and bottom, it does not have Showing rows 1-10 of 92, it currently has nothing.
  • Currently says # items besides # rows
  • Currently says all, besides All
  • In dark mode, it does not display the dropdown arrow
❌Permanent✅ 1 week❌1 Month✅ 3 Month❌ 6 Month
2026-01-23_10-15-01.png (1,508×1,031 px, 195 KB)
2026-01-23_10-15-01.png (1,508×1,031 px, 195 KB)
2026-01-23_10-16-14.png (1,515×890 px, 179 KB)
2026-01-23_10-15-56.png (1,515×901 px, 179 KB)
2026-01-23_10-15-36.png (1,509×975 px, 191 KB)

Test Case 3: No Sorting Controls Introduced

Preconditions

  • Same as Test Case 1.
  1. Inspect table headers for interactive elements.
  2. Attempt to click on column headers.
  3. Observe page behavior.
  4. AC3: Verify that no sortable headers or sorting controls are present and that clicking column headers does not change item order.

Test Case 4: Pagination Behavior Remains Unchanged

Preconditions

  • The watchlist contains enough items to trigger pagination.
  1. Navigate to the first page of Special:EditWatchlist.
  2. Use pagination controls to move between pages.
  3. Navigate to the last page using pagination.
  4. AC4: Verify that pagination behaves as before, with no new sorting implications and that navigating to the last page functions equivalently to existing behavior.

Click the "last page" arrow and you see the last 50 items
Click the "previous page" arrow from there and you see the first 5 items

@Cparle Oh I see now. If that is the case though, shouldn't we have the option to revert and have the first page available so we can have it back to what it was? The only way I can get it back to what it was is if I change the Namespace then back. This is regarding having 20 items to be back on the first page besides 13 since my total is 33

Test case 4

@Cparle Oh I see now. If that is the case though, shouldn't we have the option to revert and have the first page available so we can have it back to what it was? The only way I can get it back to what it was is if I change the Namespace then back. This is regarding having 20 items to be back on the first page besides 13 since my total is 33

Maybe we should, but this is the way the pager component works and changing it is outside the scope of this ticket.

Test case 2 functionality

1 week and 3 months show the correct days but 1 month and 6 month shows 31 and 181 days

When you watch an item via the watch-star and say you want it to expire in 1 month, the expiry is set to 31 days from now. When you say you want it to expire in 6 months, the expiry is set to 181 days from now. We haven't touched any of that code, so afaict this is the way it has always worked, and changing it is outside the scope of this ticket

For example, at the top and bottom, it does not have Showing rows 1-10 of 92, it currently has nothing.

The pager cannot tell how many rows there are in total, nor where we are in the dataset, so we can't display this. It's called out in the ticket description

Test case 2 design/copy

Permanent does not show in Expiry when I select Permanent, it just shows as a blank

To me this makes sense. "Expiry == permanent" is kinda weird, no? For permanently-watched items there is no expiry

Expiry shows days left in your watchlist, besides just days

Yeah the piece of code that displays this is used also in Special:RecentChanges ... I don't feel like I can change this in Special:RecentChanges, and to split the display of the two into separate functions feels unnecessarily hacky for such a tiny change
... and that means that

The header shows Expiry, besides Expires in

makes sense - we can't really say "Expires in: 7 days left in your watchlist"

Currently says all, besides All

The lowercase "all" comes from the Codex component, and I can't really change it

Currently says # items besides # rows

There's a long email (or maybe slack?) thread where we discussed this that I can't find now ...

The labels shows Unwatch, Assign labels, Remove labels and in that order besides Assign label, Remove label, Remove title

We had a lot of discussion back and forth on this since, and I think what we have is what we decided.

@JSengupta-WMF can you sign off on (or disagree with!) the points under the heading Test case 2 design/copy

I had a look at case 2 and based on the confusion in column header and value related to permanent items, will propose the following change.

Column name: Expires, Value: in 1..29 days/1..11 months/years/never

e.g. Expires: in 7 days, Expires: in 1 month 29 days, Expires: in 3 years, Expires: never

Here is the updated design

Edit watchlist_V3.jpg (1,440×1,054 px, 357 KB)

Change #1234460 had a related patch set uploaded (by Cparle; author: Cparle):

[mediawiki/core@master] Change display of expiry on Special:EditWatchlist

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

@JSengupta-WMF did you intend the 5th row down to say "in 11 months X days"?

The existing code we have to display stuff like this uses an "and" e.g. "in 11 months and 3 days" or "in 1 year, 2 months and 4 days", so that's what I've pushed in the latest patch. Maybe you could update the design to show that just to avoid confusion?

... and while you're at it please remove the text "Showing rows 1-10 of 92" because we can't display that

I updated it with "and". Sorry it was a typo in the design. So to reconfirm
we are dropping the week. Day, Month and Year stays. Have removed the row
counter too. Here's the updated design

{F71620671}

Hi! Visiting from Wikipedia. The previous version of the "edit watchlist" page was sorted by expiry, not alphabetically, and this was a feature I used very heavily. With the updated table design this has changed and now the only option appears to be an alphabetical list. A column for expiry exists but isn't sortable. Now I have to manually scan over my whole watchlist by sight to see if anything is about to slide off which I intended to swing back around to and hope I didn't miss anything before it disappears.

Are there any future plans to update the "edit watchlist" table further to allow for sorting by expiry, restoring the original behaviour at the editor's choice? I saw in the posts above that a contributor emphatically said the "design has sorting, but we do not want sorting". I hope this isn't true. If there are indeed no plans for sorting in the future, is it possible to ask the developers involved to reconsider? The quiet change from listing by expiry to the new default alphabetical order is not just a cosmetic change, but one which shredded my workflow for managing my watchlist after it was implemented.

I'm new to Phabricator, so if this isn't the appropriate place for this please point me in the right direction. If implementing sorting by expiry would require opening a new task on Phabricator, I'd appreciate some assistance in doing that.

I need to be able to show my whole watchlist on one page so that I can use my browser's Find command. Is there a secret switch for power users to go above 1,000 items per page? Please add an "All" option, or at least a "5,000" option, which is the secret limit on most other pages that list things (e.g. What links here, Contributions)

Removal of sorting is a misfeature. Sorting by expiry, labels, and other columns is useful. Please add/restore it.

Do we need to put 'never' in every cell of the table when there's no expiry? When there are no labels we leave it blank. It feels like it's more common to leave cells blank when there's no data, but I'm not really sure if there's a rule about that. If we are putting 'never', should we also put 'no labels' or something in the labels' column?

Pagination solves a real problem with performance, so I'm not sure that we're going to roll this change back. However, I understand the problems this change has caused. I wonder if T416172: Allow users to search by page title in Special:EditWatchlist would solve them?

@Scyrme and @Jonesey95 - we removed sort-by-expiry because the database queries underlying it are approximately 100 times slower. Slow database queries clog up the database connections and make the wikis slower for all logged-in users, so we try really hard to minimise them.

We have a wish on the community wishlist for re-enabling it - if this is important to you please support the wish. We can't just re-enable sort-by-expiry as it was because the queries were just too slow, but we might be able to figure out some alternative way of doing it instead.

Also @Scyrme we're just finishing off some work on allowing user to label watchlist items, which might allow you to do what you need with a modified workflow. First iteration should be deployed in the next couple of weeks, and the next by the end of March

@Cparle Unfortunately manually labelling watchlist items does not replace what I need because labels don't automatically update themselves as time passes. My workflow relied on the expiry date updating itself with the passing of time.

An equivalent based on labelling would only provide a substitute for my previous workflow if labels could expire and I could sort based on that. This could look something like adding an option for "remove label after: [3 months]" when adding a label, paired with a way to sort based on when the label expires.

Another way might be automated labelling based on rules like "apply label "[label]" if [expires in:] [less than] [3 months]" etc. paired with a way to filter the "edit watchlist" list to show only items which have a selected label. If filtering by label were implemented, it would also help to include a filter for unlabelled watchlist items.

I don't know whether these approaches would depend on the same database queries though.

Change #1234460 merged by jenkins-bot:

[mediawiki/core@master] Change display of expiry on Special:EditWatchlist

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

@Cparle Sorry, I know this task is getting a little crazy and out of scope for this task specifically. I did get different answers, though of 31 days if you can review my findings below. For all the options that I selected, I just did the same thing as in the video. Also, if there are any things I mentioned earlier that you want me to create a task for, just let me know, and I can create them.

@JSengupta-WMF - Since there are a lot of minor issues that go with the design, besides what is currently in Beta. Also, so we don't have to go over each one, can you please review the design of my screenshots below? If you say that all looks good, then I'll pass it from the design pov. Is Figma up to date with everything?

@Samwilson - If you have any extra input on any of the below

Test Result - Beta

Status: ✅ PASS / ❓ Need More Info / ❌ FAIL
Environment: Beta
OS: macOS Tahoe 26.1
Browser: Chrome 143
Device: MBA
Emulated Device: NA

Test Artifact(s):

https://en.wikipedia.beta.wmcloud.org/wiki/Special:EditWatchlist

Test Steps

Test case 2 functionality
1 week and 3 months show the correct days but 1 month and 6 month shows 31 and 181 days

When you watch an item via the watch-star and say you want it to expire in 1 month, the expiry is set to 31 days from now. When you say you want it to expire in 6 months, the expiry is set to 181 days from now. We haven't touched any of that code, so afaict this is the way it has always worked, and changing it is outside the scope of this ticket

Ok I get the 31 days for the month part. So the following were all set to permanent, which it will have an expires as "never". I get that part. I redid the whole 1 week, 1 month, 3 months, 6 months, as seen below, but now I got 6 days, 27 days, 2months and 29 days, 5 months and 30 days.. It looks like it took the current month of February, which has only 28 days besides a set amount of 31 days for a month, unless that's how you want the design to be? Also, if you want days or years, shouldn't we have that option when we click Watch on the page? Should there be a custom open text box that we can enter whatever we want?

Edit Watchlist: Expire dates for all optionsOptions to select when Watching a pageFigma
2026-02-06_10-19-08.png (1,603×693 px, 141 KB)
2026-02-06_10-24-39.png (1,782×660 px, 307 KB)
2026-02-06_10-07-19.png (1,446×1,066 px, 191 KB)

Video of Article entering as Watch for 1 month

Looks good to me @GMikesell-WMF. Yes the design in Figma is up to date. I see that the screenshot you have shows the row numbers but that has been removed as per discussion with @Cparle. The implementation is correct.

Edit watchlist_V3.jpg (1,440×1,054 px, 348 KB)

@GMikesell-WMF when I said this

When you watch an item via the watch-star and say you want it to expire in 1 month, the expiry is set to 31 days from now. When you say you want it to expire in 6 months, the expiry is set to 181 days from now

... turns out I was wrong - it looks like the code actually takes account of the current time and sets the expiry accordingly. So what you're describing here

I redid the whole 1 week, 1 month, 3 months, 6 months, as seen below, but now I got 6 days, 27 days, 2months and 29 days, 5 months and 30 days

... is I think correct? If I set expiry to one week from now and then look in Special:EditWatchlist the expiry time is days but rounded down, so 6 days is what I expect. Similar for a month - Feb has 28 days, so if I set expiry to one month from now and then go to Special:EditWatchlist it'll round down to 27 days. If I select 3 months from today that's May 18, so minus one day (because I'm rounding down) that's 2 months (getting me to April 18) plus 29 days (because April has 30 days)

So I think this is correct, so I'm closing it