Page MenuHomePhabricator

Community updates module: dismiss module
Open, HighPublic

Description

User story & summary:

As a new editor visiting my Newcomer homepage, I want to dismiss the community updates notice, because I've read it and decided it's not relevant to me.

Designs:

Community updates: Figma designs for Homepage module.

Community updates: Figma designs for the configuration form.

NOTE: Figma designs show the end state of the MVP release. This task only covers adding a x to dismiss the module, the "undo" option, and the associated logic.

v.2 CX banner (5).png (183×330 px, 12 KB)

Message (1).png (54×328 px, 2 KB)

Acceptance Criteria:

Given I'm viewing Special:Homepage,
When the Community Updates module is displayed,
Then I'm able to discuss the module and that preference is preserved until a new Community Update is added

  • This will follow the logic of a temporary undo.
  • By clicking on the Close icon the user will get a message that informs the banner was dismissed with an option to Undo that action (for example if they dismissed it by accident).
  • This message will be dismissible only manually (not automatically), so that the action does not expire.
  • After the banner is effectively dismissed, we will only show the module again when it is about another event/initiative. The action is to dismiss the specific banner, but not the module in itself.

Open questions

  • What kind of storage should we use for storing the dismissed flag?
  • What should be stored to identify the update that was dismissed?

Event Timeline

KStoller-WMF renamed this task from Community updates module: dismissing module to Community updates module: dismiss module.May 24 2024, 11:25 PM
KStoller-WMF moved this task from Backlog to Up Next (estimated tasks) on the Growth-Team board.
KStoller-WMF raised the priority of this task from Medium to High.Aug 20 2024, 3:56 PM

Team discussion notes:

What kind of storage should we use for storing the dismissed flag?

Mh, two options come to mind: LocalStorage (per-device) and UserOptions (server-side). I'm not fully sure what the tradeoffs for User Options are in terms of database space (maybe @Urbanecm_WMF can provide more insight), but for LocalStorage it seems straight forward: The storage is per-device only and on-device only, but it is immediate.

What should be stored to identify the update that was dismissed?
How to decide what determines a "new" Community Update

That's the trickier question. Some possible options:

  • store the title
    • PRO: the title is probably going change if it is a new Community Update, and is probably going to stay the same while the description copy and logo might be more likely to be adjusted for the same campaign
    • CON: but minor wording changes to the title, including typo-fixes would still cause a new update to be shown
  • add a new field to the config form: "Update id" or "Update key" or something, with a placeholder/example like 2024-09-WomenInRed-01 and explain that changing this triggers the update to be shown to all users again
    • PRO: an explicit mechanism, and this might scale better to a future where we have multiple updates
    • CON: it is an additional field in the form that needs to be explained and validated and so on

Sorry, I should have posted an update. I discussed this task briefly with @Etonkovidova and @JFernandez-WMF, because I've been wondering if we should consider rethinking this task.

We've always wanted to allow newcomers to have more control over their homepage, and enable or disable modules based on their preferences. I wonder if we should consider working on that rather than logic and UI that only relates to this one module. (Essentially individual editors could decide they want to permanently stop showing the Community Updates module if they don't find it useful, but perhaps not dismiss an individual update).

Also, I should note that this is a "nice to have" feature but I don't think this task blocks our release or initial pilot testing.

What kind of storage should we use for storing the dismissed flag?

Mh, two options come to mind: LocalStorage (per-device) and UserOptions (server-side). I'm not fully sure what the tradeoffs for User Options are in terms of database space (maybe @Urbanecm_WMF can provide more insight), but for LocalStorage it seems straight forward: The storage is per-device only and on-device only, but it is immediate.

Thanks for the ping! Happy to cover that. In short, the problem with user options is the newer an user is, the more user options it needs on average (even when the user is inactive). This mostly happened thanks to extensions manipulating with user options within the onLocalUserCreated hook (or similar place). That is an antipattern, as it creates a new user options row for every new user, even when that new user never does anything (let alone changes its preferences).

Previously, we were forced to do this, as there was no other way to say "user option has value X for all users who registered up to now, and value Y for all users who register from now on". In this case, we're unlikely to need something like that. Even if we need to support that use case, MediaWiki Core now supports it natively.

That being said, I'm not sure user options are a good tool in this case, even if they are appropriate from a strictly DB usage standpoint. User options are meant to be permanent, while our need here appears to be merely ephemeral (we only need to store the data as long as the community update is posted). Leaving now-useless data in localstorage might not be that big of a deal, but leaving such data in user_properties feels like wasting our resources. If we are able to determine when a new notice was posted and implement some sort of purging mechanism, this would likely be acceptable, but I'm unsure whether investing in that would be an appropriate use of team resources.

Do you have any opinion on this, @Michael? If you want me to clarify anything further, please do feel free to let me know.

What should be stored to identify the update that was dismissed?
How to decide what determines a "new" Community Update

That's the trickier question. Some possible options:

  • store the title
    • PRO: the title is probably going change if it is a new Community Update, and is probably going to stay the same while the description copy and logo might be more likely to be adjusted for the same campaign
    • CON: but minor wording changes to the title, including typo-fixes would still cause a new update to be shown
  • add a new field to the config form: "Update id" or "Update key" or something, with a placeholder/example like 2024-09-WomenInRed-01 and explain that changing this triggers the update to be shown to all users again
    • PRO: an explicit mechanism, and this might scale better to a future where we have multiple updates
    • CON: it is an additional field in the form that needs to be explained and validated and so on

Hmm... Can we make use of the identifier we already have – the revision ID? With CC2.0, CommunityUpdates have its own configuration page, so changes of the latest revision ID should more-or-less correspond to changes between user options. Of course, this is not precise (I might make just a very minor change like deleting a space, or I might change the "minimum edits" requirement without changing the wording). However, it is the closest approximation we have available. This would need some changes to CommunityConfiguration itself, to make the revision ID retrievable. However, that should be fairly reasonable to do.

  • PRO: transparent for the admin
  • CON: users might see one update twice (either genuinely, or because an admin made a very minor edit)

@Michael Do you have any thoughts on this third approach?

What kind of storage should we use for storing the dismissed flag?

Mh, two options come to mind: LocalStorage (per-device) and UserOptions (server-side). I'm not fully sure what the tradeoffs for User Options are in terms of database space (maybe @Urbanecm_WMF can provide more insight), but for LocalStorage it seems straight forward: The storage is per-device only and on-device only, but it is immediate.

Thanks for the ping! Happy to cover that. In short, the problem with user options is the newer an user is, the more user options it needs on average (even when the user is inactive). This mostly happened thanks to extensions manipulating with user options within the onLocalUserCreated hook (or similar place). That is an antipattern, as it creates a new user options row for every new user, even when that new user never does anything (let alone changes its preferences).

Previously, we were forced to do this, as there was no other way to say "user option has value X for all users who registered up to now, and value Y for all users who register from now on". In this case, we're unlikely to need something like that. Even if we need to support that use case, MediaWiki Core now supports it natively.

That being said, I'm not sure user options are a good tool in this case, even if they are appropriate from a strictly DB usage standpoint. User options are meant to be permanent, while our need here appears to be merely ephemeral (we only need to store the data as long as the community update is posted). Leaving now-useless data in localstorage might not be that big of a deal, but leaving such data in user_properties feels like wasting our resources. If we are able to determine when a new notice was posted and implement some sort of purging mechanism, this would likely be acceptable, but I'm unsure whether investing in that would be an appropriate use of team resources.

Do you have any opinion on this, @Michael? If you want me to clarify anything further, please do feel free to let me know.

Thank you for sharing your thoughts 🙏. The main advantage for UserOptions in my mind would be that it is cross-device. If that is not required, then LocalStorage seems indeed the straight-forwardly better choice. Maybe we can start with LocalStorage, and if people complain about still seeing community updates on their phone after dismissing them on desktop, then we can think about whether UserOption is worth the added complexity of explicit invalidation.

What should be stored to identify the update that was dismissed?
How to decide what determines a "new" Community Update

That's the trickier question. Some possible options:

  • store the title
    • PRO: the title is probably going change if it is a new Community Update, and is probably going to stay the same while the description copy and logo might be more likely to be adjusted for the same campaign
    • CON: but minor wording changes to the title, including typo-fixes would still cause a new update to be shown
  • add a new field to the config form: "Update id" or "Update key" or something, with a placeholder/example like 2024-09-WomenInRed-01 and explain that changing this triggers the update to be shown to all users again
    • PRO: an explicit mechanism, and this might scale better to a future where we have multiple updates
    • CON: it is an additional field in the form that needs to be explained and validated and so on

Hmm... Can we make use of the identifier we already have – the revision ID? With CC2.0, CommunityUpdates have its own configuration page, so changes of the latest revision ID should more-or-less correspond to changes between user options. Of course, this is not precise (I might make just a very minor change like deleting a space, or I might change the "minimum edits" requirement without changing the wording). However, it is the closest approximation we have available. This would need some changes to CommunityConfiguration itself, to make the revision ID retrievable. However, that should be fairly reasonable to do.

  • PRO: transparent for the admin
  • CON: users might see one update twice (either genuinely, or because an admin made a very minor edit)

@Michael Do you have any thoughts on this third approach?

Mh, my main motivation behind my suggested approaches was to limit how the dismissal is invalidated by trivial changes. Your approach, while otherwise the simplest, would indeed dismiss it on any change. But maybe trivial changes are not made that often days after a banner has been published, so this doesn't matter?

Either way, given @KStoller-WMF's comment above (T365894#10107684), it seems this functionality is not strictly required for the MVP anyway. It might make sense to revisit this task for "CommunityUpdates v2" when we maybe have multiple + scheduled updates configured, because that will change the requirements that we have for the dismiss-behavior.