Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events #1360

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Events #1360

wants to merge 4 commits into from

Conversation

peteryates
Copy link
Member

@peteryates peteryates commented May 9, 2024

Context

User research has shown repeatedly that admins in both ECF and NPQ have struggled to piece together what happened chonologically. This meant time had to be spent by devs piecing things together using the audit log. A disadvantage of using record-level audit data for events is that events are often related to multiple records.

For example, when a participant registers for an NPQ, we might want to see that event when looking at the participant, the school, the course, etc.

This PR proposes a new, better way of recording that information.

The record at the centre is an Event. Events are linked by foreign keys to all the 'domain' models in the app but the foreign keys default to NULL. As we will be organising all of our business logic in the service layer, we will have objects that perform the creation/update/deletion. The intended use is that we wrap the operation in a transaction and write an event at the same time.

The foreign keys are all set to on_delete: :nullify so objects in the application can be deleted at will. The events will no longer be linked to any object so at that point we'd be reliant on the title/description for context. Really deletion should also happen through a service object so we can record a deletion event (that won't be accessible through the originating object but will be through the other related ones).

# pseudocode in app/services/widgets/create_widget.rb
class Widgets::CreateWidget
  def create_widget
    Widget.transaction do
      widget = Widget.create(widget_params)

      Events::WidgetCreation.new(widget:, author: current_user, title: "Widget #{widget.name} was created by #{current_user}")

      # or

      Events::WidgetCreation.create_from_widget(widget, title: "Widget #{widget.name} was created by #{current_user}")
    end
  end
end

In addition to the foreign key colums the event has:

  • title - (required) a short string of text describing what happened. It should make sense regardless of where it's displayed in the admin UI
  • description - (optional) more text if required, this might be useful in some circumstances but I'm not sure exactly how yet

I decided not to add any metadata columns to events yet, but dropping in a hstore or jsonb is an option.

Changes proposed in this pull request

  • Add events model with validation and relationships
  • Add sample event creation service

Overview/preview of how the UI might look

image

Remaining tasks

  • work out how to mark the importance of an event type - this will vary by context (an application raised by a participant is important and should be given prominence but when looking at it from the course's point of view it's less important)
    I think the solution here is to not try and predict how we want to display events, just make sure they're easy to identify and categorise. I've switched over the event_type column validation from presence/length to inclusion and defined a list of event types in the Event model. I think it's sufficient for now.

  • add a timeline component based on MoJ's timeline or HMRC's timeline that takes and displays an array of events. Here's a preview of how it looks, note that the data is all smoke and mirrors at the moment:

    Screenshot from 2024-05-14 14-40-03

Copy link

github-actions bot commented May 9, 2024

t.integer :private_childcare_provider_id, index: true
t.integer :statement_id, index: true
t.integer :statement_item_id, index: true
t.integer :lead_provider_id, index: true
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lead_provider is probably low cardinality tbh.

The timeline component accepts an array of events which are
ViewComponent slots (meaning it can be constructed manually too via
`with_item(event)`) although I don't see us using that.

It's intended to display a chronological list of events that happened to
a thing.
There's only one in it so far, ApplicationAcceptance. The idea is that
if we can reliably identify the events by type we can show them with
more or less prominence (or not at all) depending on the context.

So, an application creation might be important from a user's point of
view, but less so from a course's.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant