Page MenuHomePhabricator

Wikimedia-native pager component in Codex
Open, Needs TriagePublicFeature

Description

Feature summary

A Codex "pager" component that can display two-dimensional data structures (i.e. data tables) in batches from a data source. The pager should be trivial to connect to the Action API endpoints that provide paged data (i.e. anything that supports continue and a batch size, anything that can be a generator), either natively or through integration with a mw.api module (the latter might be desirable for users wanting a different pager / data table component for whatever reason).

Use case(s)

A larger number of the MW Action API endpoints deliver lists of things (often pages or revisions, sometimes users) in batches. The endpoints exist in the first place because these are the things that are useful to expose to non-core clients (read: user scripts and Gadgets). Each list can be requested to include additional properties (e.g. rvprop for extra information on revisions), that would fit neatly into additional columns of a data table.

Currently this requires loading a third-party data table and pager library and then writing a shim to connect the Action API to whatever the data table and pager expect as a data source. All in client-side JS, with no TypeScript, LESS, and limited support for ES6 (still "at your own risk", I believe, although now possible at least).

Concrete use case 1

One concrete use case would be: while waiting for T41510 to be resolved (possibly through T34151, filed by @brion in 2011 and still open) I would like to build my own "Watchlist Editor" as a user script and possibly as a Gadget if other users want it. I'd like a low-effort way to pop a design system-compliant data table on screen, that's essentially backed by ?list=watchlistraw, and which doesn't fall over with large lists (cf. T41510) or kneel the user's web browser. I'd like to enrich the displayed data with custom styling (e.g. nowrap some columns' contents), decorations (icons, say), and interactivity (e.g. some kind of UI widget to remove a page from the watchlist, or a date picker to set a Watchlist expiry for a previously permanently watched page).

Concrete use case 2

Another would be a mass delete Gadget. Wikisource uses Proofread Page to manage their main workflow, which generates a ton of wikipages for what on something like Wikipedia would be a single wikipage. A typical enWP mainspace artefact that might come up for deletion is "an article" (a single ns:0 wikipage), that might have an associated talk page, which in turn might have a few tens of subpages (todo, talk archives, etc.). An enWP artefact would be "a book", consisting of one top-level mainspace wikipage, several tens (novel with 30 chapters) to hundreds (poetry collection) to several thousand subpages (think biographical dictionaries, encyclopedias, etc.), one wikipage in the Index: namespace (Proofread Page metadata), several thousand wikipages in the Page: namespace (one for each physical page in the scanned book), several hundred files and file description pages in the File: namespace (the PDF/DjVu of the book scan, and extracted PNG/JPEGs of individual illustrations from the book).

While working as an administrator the wikipages to delete can come from different sources. Often a copyvio or deletion discussion pointing at the top level wikipage in mainspace. Sometimes it'll be the Index: wikipage (e.g. because none of the artefacts have been transcluded to mainspace yet), and sometimes it's the File: file description page. Sometimes it's all wikipages in a category.

I'd like to apply my knowledge of the workflow of administrators and the local factors of Wikisource to make a Gadget that knows in what contexts admins may want to "delete all these" (i.e. where to expose UI) and what wikipages should end up on the list as a result (i.e. project-specific logic), and then display the result in a generic (but design system-compliant and accessible) data table. I want the data table to be both performant and show a reasonable number of entries to the user. And I want to provide UI for selecting or deselecting subsets of the rows in case some wikipages should not be deleted.

This would also apply at a smaller scale to deleting something like a template on enWP, where Template:Foo has associated Template:Foo/doc, Template:Foo/styles.css, Template:Foo/sandbox, Template:Foo/sandbox/styles.css, and possibly a Scribunto module that implements it and associated Lua .loadData() data pseudo-modules.

Concrete use case 3

Similar to #2, moving a mainspace artefact on Wikisource might involve moving a very large number of wikipages (for example when a file is renamed on Commons, or there was a typo in the initial top-level page, or because disambiguation is needed).

I'd like to write a Gadget that allows administrators to see an overview of all pages that will need to be moved, provide transformation rules for the page names to control what the destination page names will be (e.g. because the subpages were named "/Chapter XII" with roman numerals but current policy is to use "/Chapter 12" in arabic numerals). This implies that I will need to dynamically populate one column of the table with page names after a set of transformation rules have been applied, for example a custom function that changes roman numerals into arabic numerals (the algorithm is somewhat involved). Because wikipage content contains references to page names, it'd also need to modify page content while moving.

Concrete use case 4

"Moving" a category. Commons and enWP have a huge and complex category system, where it's often necessary to eith rename a single category, or move wikipages to a different category based on some rule, or diffuse a large category into subcategories based on a set of rules (e.g. intersections of category X and Y go to subcategory A, but intersections of X and Z go to B, unless also members of M or N).

Benefits

Having a data table + pager component in Codex that is trivial to connect to any generator module in the Action API would ensure all such use cases have a consistent presentation and are by default accessible (pagers are notoriously poor to use in screen readers because the non-displayed rows are not present in the DOM, cf. eg. Superset's use of React Virtualized). It would also reduce the effort volunteers like me would need to spend on reinventing data table and pager components, or, more likely, grabbing them from an external source and shimming them into the Action API. Reinventing foundational and generic components like this for every Gadget is a very poor use of volunteer resources, and results in suboptimal solutions for design consistency, UI consistency, and accessibility.

The above use cases are all things that require local project and workflow knowledge and each benefit a relatively small subset of users (from the global Wikimedia perspective), and are thus extremely unlikely to ever get resource allocation from WMF for an in-core feature, but which still all need certain generic components. Having this thus enables the long tail of on-wiki volunteers to cover locally-important gaps in functionality while still remaining consistent, accessible, and secure (no sneaking third party libraries onto the projects, whether from third-party CDN or cut&paste of minified code or copying them onto Toolforge or ...). It would also leverage and enhance the existing investment into the Action API (and, obviously, in Codex), and, if implemented that way, the mw.api client framework.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript
CCiufo-WMF subscribed.

Thank you for the request. Design-System-Team is already considering adding a table and pagination component as part of T303320: Table: Add Table component to Codex, perhaps these use cases can be added to the inventory there? Note however that Codex components are meant to be MediaWiki agnostic, so direct integration with any specific APIs is unlikely. With the table component, we're aiming for something that can be used more generally with any data source, which you could then build on top of for re-use with specific use cases. So maybe that gets you at least 50% of the way there.

It also sounds like you'd need T313945: [EPIC] Enable gadget and user-script developers to use Vue and Codex, which is on our radar and these are great supporting use cases for.

Note however that Codex components are meant to be MediaWiki agnostic, so direct integration with any specific APIs is unlikely.

That's a design parameter for Codex components, but not for "the Wikimedia UI and design system". Each Codex component need not necessarily have any MediaWiki-specific knowledge, but should be easy to connect to some kind of middleware that does have such knowledge (in mediawiki.api maybe?). And whatever that middleware component is it should exist and know how to talk to the Action API so that for Gadget and user script developers to use it is just a matter of a small handful of boilerplate code. And it should have relatively standardized hooks and extension points for things like transforming data on its way from the Action API to the relevant Codex component.

Note however that Codex components are meant to be MediaWiki agnostic, so direct integration with any specific APIs is unlikely.

That's a design parameter for Codex components, but not for "the Wikimedia UI and design system". Each Codex component need not necessarily have any MediaWiki-specific knowledge, but should be easy to connect to some kind of middleware that does have such knowledge (in mediawiki.api maybe?). And whatever that middleware component is it should exist and know how to talk to the Action API so that for Gadget and user script developers to use it is just a matter of a small handful of boilerplate code. And it should have relatively standardized hooks and extension points for things like transforming data on its way from the Action API to the relevant Codex component.

I can see such a middleware being useful but it's not something we (the design system team) would be prioritizing any time soon. The actual pager / pagination component is something we will look at as part of T303320 as mentioned before. I'm going to backlog this for now, but I wonder if it would be good to split apart the "middleware" request (mw-aware) from the "page component" (mw-agnostic).