Create a new Checklist config entity type

Created on 13 September 2024, 2 months ago
Updated 18 September 2024, 2 months ago

Problem/Motivation

Let's define a new config entity type for checklists.

They'll have the following:

  • A label
  • A description
  • A set of task groups
  • A set of tasks, which are represented as value objects with the following properties:
    • name
    • description
    • a set of condition plugin configurations that would fulfill the task
    • weight
    • a set of links
✨ Feature request
Status

RTBC

Version

3.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @phenaproxima
  • First commit to issue fork.
  • πŸ‡ͺπŸ‡ΈSpain penyaskito Seville πŸ’ƒ, Spain πŸ‡ͺπŸ‡Έ, UTC+2 πŸ‡ͺπŸ‡Ί

    I've created a new branch based on @phenaproxima's as I plan to work on this during the weekend, but don't want to disrupt any work he might have on his local or maybe we had different understandings on how to do this.

  • πŸ‡ͺπŸ‡ΈSpain penyaskito Seville πŸ’ƒ, Spain πŸ‡ͺπŸ‡Έ, UTC+2 πŸ‡ͺπŸ‡Ί

    I've got to a point where even the previous UI is mostly kept using the config actions.
    I'd need to discuss with Adam to continue, as I'm not sure how he intents to use the existing conditions.

    Also is not clear if we want to keep the existing task help texts/links, or if description should be a rich text. If that's the case, the api or modules implementing the api might need to include text formats?

    For completion, I like the idea that we could have a "CompletionPlugin" (e.g. one of them being a checkbox), but not sure how that could be/extend the condition api. Also the 2.x branch allow to store that in config or state if I read the code correctly, and that might be a feature we want to implement in the future.

    I added some @todos on places that might need discussion, and lots of hacky code will need to be edited/remove, but if the scope of this was the config entity, I'm pretty satisfied with what I got to. Just needed to get a bit further to ensure that the existing implementation could be achieved with the new one.

  • πŸ‡ͺπŸ‡ΈSpain penyaskito Seville πŸ’ƒ, Spain πŸ‡ͺπŸ‡Έ, UTC+2 πŸ‡ͺπŸ‡Ί

    In the meantime did some progress on providing blocks on the checklist-dashboard-block branch (might be in a different computer next week, had to push it somewhere)

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    Here's what I've come up with so far in https://git.drupalcode.org/issue/checklistapi-3474237/-/tree/3474237-cre... -- it's only sketched in, and by no means ready to commit, but I thought I'd explain the design choices here.

    Long story short is that this MR adopts very well-established patterns for modern Drupal development: config entities, and plugins.

    In my view, Checklist API has two "pillars": storing checklist definitions (i.e., what are the tasks in this checklist? How are they grouped? etc.) and managing checklist state (which tasks are completed?). The first pillar is implemented using a config entity; the second pillar is implemented with plugins.

    The config entity is called Checklist, and has a corresponding ChecklistInterface. Like all config entities, it is exportable, importable, and translatable. Checklist entities have absolutely nothing to do with state storage; they simply are lists of tasks and task groups. Checklist entities do not define specific routes by which they can be accessed, because that's a pain in the butt and introduces caching-related weirdness; there will be only one canonical route for a checklist, probably something like /checklist/CHECKLIST_ID. (A standard path alias could be created to visit a checklist via an alternate path.)

    The tasks are represented with a simple value object, called Task. Tasks contain a runtime reference to their defining checklist, a basic string identifier, a human-readable title and description, an identifier of which group they're in (if any), and an optional set of conditions under which they are considered fulfilled. (More on that in a bit.) Tasks also don't know what state they're in.

    That brings us to state management. This is done with plugins, which implement a new ProgressInterface. Progress plugins are responsible for storing the state of tasks in a checklist. They can tell you whether a task is complete, explicitly mark a task as complete or incomplete, or reset the progress of a whole checklist. The only link between the Checklist entities and the progress plugins is that the checklist will specify which progress plugin it wants to use. (This is a very common pattern in core -- MediaType and Workflow entities are two examples that leap to mind.)

    Out of the box, there are two progress plugins: State and Config. The only real difference between these two is that State is environment-specific, and Config persists across environments. External code could implement more types of progress plugins if they wanted.

    Code that wants to interrogate the progress of a checklist can use the plugin manager for the progress plugins, which is called ProgressManager. It contains methods to report how many tasks in a checklist are completed (either as an integer or a percentage). ProgressManager is the intersection between checklists (which don't know their state), and the progress plugins (which know about the state of checklist tasks, but don't know anything else about the checklist itself). Plugin managers having type-specific superpowers is also a common pattern (for example, BreakpointManagerInterface, MailManagerInterface, BlockManagerInterface, and others). I did NOT create an interface for ProgressManager because it felt superfluous, but I'm not against adding one if that's desirable.

    Now let's talk about those conditions I mentioned. Drupal has the concept of a "condition plugin", which is essentially just a way to dynamically get a boolean value based on...some conditions in the system. I know that they are used in core by the block system, but I'm not sure where else; nevertheless, they are an established and supported core API. I think it makes sense for Task objects to be able to optionally define a set of conditions that, if all of them are fulfilled, mean that the task itself is considered complete. I implemented this in a basic way. Tasks that don't define any conditions must be manually marked as complete, but tasks that do define conditions can be automatically determined to be complete. ProgressManager has an explicit method to facilitate this.

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    phenaproxima β†’ changed the visibility of the branch 3474237-entity-type to hidden.

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    phenaproxima β†’ changed the visibility of the branch 3474237-entity-type to active.

  • Pipeline finished with Canceled
    2 months ago
    Total: 83s
    #285532
  • Pipeline finished with Failed
    2 months ago
    Total: 175s
    #285533
  • Pipeline finished with Failed
    2 months ago
    #285534
  • Pipeline finished with Failed
    2 months ago
    Total: 159s
    #285539
  • Pipeline finished with Failed
    2 months ago
    Total: 235s
    #285550
  • Pipeline finished with Failed
    2 months ago
    #285579
  • Pipeline finished with Failed
    2 months ago
    Total: 190s
    #285585
  • Pipeline finished with Canceled
    2 months ago
    Total: 67s
    #285612
  • Pipeline finished with Canceled
    2 months ago
    Total: 93s
    #285615
  • Pipeline finished with Failed
    2 months ago
    #285616
  • Pipeline finished with Canceled
    2 months ago
    Total: 75s
    #285622
  • Pipeline finished with Success
    2 months ago
    Total: 159s
    #285624
  • Pipeline finished with Success
    2 months ago
    Total: 235s
    #285681
  • Pipeline finished with Success
    2 months ago
    Total: 145s
    #285709
  • Pipeline finished with Success
    2 months ago
    Total: 356s
    #285832
  • Pipeline finished with Success
    2 months ago
    #285835
  • Pipeline finished with Canceled
    2 months ago
    Total: 243s
    #285840
  • Pipeline finished with Success
    2 months ago
    Total: 297s
    #285844
  • Pipeline finished with Failed
    2 months ago
    Total: 150s
    #285858
  • Pipeline finished with Failed
    2 months ago
    Total: 153s
    #285859
  • Pipeline finished with Canceled
    2 months ago
    Total: 87s
    #285870
  • Pipeline finished with Failed
    2 months ago
    Total: 151s
    #285871
  • Pipeline finished with Success
    2 months ago
    Total: 155s
    #286183
  • Pipeline finished with Success
    2 months ago
    Total: 142s
    #286185
  • Pipeline finished with Canceled
    2 months ago
    Total: 85s
    #286199
  • Pipeline finished with Success
    2 months ago
    Total: 154s
    #286201
  • Pipeline finished with Failed
    2 months ago
    Total: 143s
    #286341
  • Pipeline finished with Success
    2 months ago
    Total: 145s
    #286357
  • Pipeline finished with Success
    2 months ago
    #286374
  • Pipeline finished with Success
    2 months ago
    Total: 159s
    #286376
  • Pipeline finished with Success
    2 months ago
    Total: 175s
    #286398
  • Pipeline finished with Success
    2 months ago
    Total: 161s
    #286407
  • Pipeline finished with Canceled
    2 months ago
    Total: 81s
    #286415
  • Pipeline finished with Success
    2 months ago
    Total: 154s
    #286417
  • Pipeline finished with Success
    2 months ago
    Total: 140s
    #286442
  • Pipeline finished with Success
    2 months ago
    #286451
  • Pipeline finished with Success
    2 months ago
    Total: 134s
    #286464
  • Pipeline finished with Success
    2 months ago
    Total: 146s
    #286474
  • Pipeline finished with Success
    2 months ago
    Total: 181s
    #286479
  • Issue was unassigned.
  • Status changed to Needs review 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    OK - I think I'm happy with this.

    This MR only sets up the data model. It has nothing to do with state management or progress storage. We'll do that in subsequent issues.

    This sets up a pretty standard config entity, called Checklist, which generally follows the structure defined by hook_checklistapi_checklist_info() and callback_checklistapi_checklist_items(). Tasks and links are represented by immutable value objects that can be upcast from, and downcast to, arrays for export and storage purposes. There is a very basic API to modify the config entity -- you can add task groups and tasks, but currently there is no way to remove any of those things. (We can add those in other issues, if needed.) Config actions are also natively supported, with the trade-off being that support for Drupal older than 10.3 is dropped.

    Virtually all of these changes have kernel test coverage, too!

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    phenaproxima β†’ changed the visibility of the branch 3474237-create-a-new to hidden.

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    phenaproxima β†’ changed the visibility of the branch checklist-dashboard-block to hidden.

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    phenaproxima β†’ changed the visibility of the branch 3474237-config-entity-with-test to hidden.

  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts
  • Pipeline finished with Success
    2 months ago
    Total: 145s
    #286533
  • Pipeline finished with Success
    2 months ago
    Total: 143s
    #286541
  • Status changed to RTBC 2 months ago
  • πŸ‡ͺπŸ‡ΈSpain penyaskito Seville πŸ’ƒ, Spain πŸ‡ͺπŸ‡Έ, UTC+2 πŸ‡ͺπŸ‡Ί

    Love this kick-off for the 3.0.x branch.

  • Status changed to Needs review 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts
  • Pipeline finished with Success
    2 months ago
    Total: 156s
    #286567
  • Status changed to RTBC 2 months ago
  • πŸ‡ΊπŸ‡ΈUnited States phenaproxima Massachusetts

    Thanks @penyaskito for the sharp thinking on the string|\Stringable stuff. After a cursory search, I can't find any precedent in core so I think we should just do string for now. I've made that change and therefore I'm restoring RTBC!

  • Pipeline finished with Success
    2 months ago
    Total: 278s
    #286573
  • Pipeline finished with Canceled
    2 months ago
    Total: 116s
    #288272
  • Pipeline finished with Success
    2 months ago
    #288274
  • Pipeline finished with Success
    about 2 months ago
    #290448
  • Pipeline finished with Success
    about 2 months ago
    Total: 204s
    #290458
  • First commit to issue fork.
  • Pipeline finished with Skipped
    about 2 months ago
    #290515
  • πŸ‡ΊπŸ‡ΈUnited States traviscarden

    Nice! Merged. Good work, guys; this is exciting. πŸ™‚

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024