Page MenuHomePhabricator

Allow uncollapsing grouped results
Open, LowPublic30 Estimated Story PointsFeature

Description

Something that is possible in core, but not yet available
Fairly straightforward to implement in Vue imo, not quite sure how to do it in the jQuery display

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript
DannyS712 changed the subtype of this task from "Task" to "Feature Request".
DannyS712 moved this task from Unsorted to Later on the User-DannyS712 board.
DannyS712 set the point value for this task to 8.

Okay, so I started looking into how to show this as an option. In core's enhanced changes list the line goes roughly

* > x   mb 01:23 Title (9 changes | history ) .. (-100) .. [Editor1; Editor2; Editor3 (2x)]

where * is the bullet point from the <li>, and > is the collapse marker (its a filled in arrow pointing right, but there isn't a character for that), and mb are minor and bot flags
once you expand the group, the only difference to that singe line is that the arrow is pointing down
Both of those arrows are accomplished by using the background image css property, see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/8217a1a253c7f3b52ee0ef99c8baa41552a48b28/resources/src/mediawiki.icon/ for the icons

For the non-Vue display, I anticipate using the same thing, including the background icons. Our line entry order is a bit different, but it'll go between the timestamp and the edit flags (we should probably consider always adding some space there to align the start of the title regardless of flags and whether there is a collapse toggle or not)

For the Vue display, it'll go in the same place but using the <wvui-icon> which can thankfully include different svg paths for RTL and LTR (will copy from the svg paths in the core icons).

Once expanded, there will be a row for each of the grouped changes - probably using their own dedicated <ul> for the group so we can indent it together. Rather than manipulating the DOM to add and remove those, it'll just be hidden with CSS if the toggle is not triggered (this is for the non-Vue display, for Vue is really easy to only show if the toggle is triggered, and so we probably won't include it unless we should)

The link to unwatch should only be included for the overall grouped entry, to align with core's only showing the x to unwatch for the overall grouped entry (maybe we should switch to x and + in the same location, instead of "unwatch"/"watch" links? Something to consider later...)

We should also consider what else should not be duplicated. In core, there is

  • (diff | history) if there is only one edit
  • (3 changes | history) if there is multiple, for the overall entry
  • (cur | prev) for the individual edits in a grouped entry, once uncollapsed

Additionally, the title isn't shown for each individual edit in a grouped entry

Finally, in the grouped entries the timestamps of the individual edits work as links to the state after that edit (cf T262768)

For the internals, we currently have the data for entry rows represented as plain javascript objects - I'll probably create a dedicated class (object, not css) for this that will hold the data and, for grouped entries, also the inner objects)

DannyS712 changed the point value for this task from 8 to 30.Jul 28 2021, 11:06 PM

Okay, thinking about the class structure more, we will want something like the following. Properties are public instead of using getters because this code should only be used within the extension. Syntax here is just for documenting, not for valid javascript. Does not include which properties are optional for fast mode.

abstract class EntryBase {
	constructor( object with at least the properties that are common )

	properties:
		* type (edit or log)
		* timestamp
		* watchlist expiry
		* flags
		* page link and display text
		* user display
		* comment display
		* tags display
}

class EntryLog {
	constructor( object with all the common properties, plus the log ones, calls the parent constructor )

	properties:
		* log type
		* log action
		* page logs link
		* specific log entry link
}

// Used for all edit entries, single or grouped
class EntryEditGroup {
	constructor( object with all the common properties, plus the edit ones, calls the parent constructor )

	properties:
		* diff link target and message
		* history link target
		* [NEW FEATURE] array with EntryEditSingle objects for each grouped edit
}

// Represents a single edit that is part of a group. Properties are accessed directly for the Vue display, the `getRow()` method is called for the jQuery/OOUI display
class EntryEditSingle {
	constructor( object with all properties that we need )

	properties:
		* flags
		* timestamp
		* user display
		* comment display
		* tags display

	method:
		* getRow() - returns jQuery object for the row
}

Showing / hiding:

jQuery/OOUI: will check if there are multiple edits grouped, if so add a control button / trigger. The icon shown will be controlled by a CSS class that changes when toggled (using background-image property). The individual entry rows will all be added to the DOM at the beginning, and shown/hidden based on the CSS class. This matches how the core watchlist works. Watch/unwatch will still only be handled by the overall grouped entry, but upon unwatching the strikethrough will apply to all nested edits too.

Vue: will check if there are multiple edits grouped, if so add a control <wvui-icon>. The SVG path will be controlled by the current state (enabled/disabled). Vue makes it a whole lot easier to add/remove elements from the DOM, so we might use v-if, or do the same CSS hiding. Watch/unwatch is the same as jQuery/OOUI. Rendering will use a new component, <entry-edit-single> that produces a similar output to the getRow() method.

Roadmap:

  • add EntryBase/EntryLog/EntryEditGroup and use them in the current code, without EntryEditSingle
  • add EntryEditSingle and use that

this will also help with T286268

Bumping up estimated story points to reflect that this is much bigger than I initially guessed and also prompted work in multiple other tickets. Its probably the biggest single feature request since the functionality was deployed.

Change 714147 had a related patch set uploaded (by DannyS712; author: DannyS712):

[mediawiki/extensions/GlobalWatchlist@master] Handle rendering edits and log entries separately

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