MishkaCmsCoreWeb.Templates.ActivityTimeline (Mishka CMS Core v0.0.1)

Copy Markdown View Source

A MishkaGervaz custom table template: an activity log drawn as a vertical timeline — a rail with a severity-tinted node per event, day headings across it — rather than a table.

A template owns the whole table, so the chrome is here: the filter bar (render_filters/1) and the footer (render_pagination/1). The bar is generic — a :select with few options becomes a segmented switch, a long one a dropdown, a :text filter the search box and a :date_range a pair of date inputs — so the resource stays the single source of truth and no filter is named here.

Row content comes from each column's render, mapped by position: 0 the event (message + badge), 1 the actor, 2 the date, 3+ inline badges.

What a resource has to give it

Columns and filters are read off the resource, but three things come from the record itself:

  • :severity — an atom field (:info, :warn, :error) tinting the node and the actor avatar of a row that carries no :tone; an unknown or unloaded one renders the :info tint.
  • :tone — an optional atom field (:created, :updated, :destroyed) a content-change row carries. When present it tints the node and the actor avatar by action rather than severity, so a create reads green, an update blue and a destroy red; a row without one (a job, a compile, a draft) is nil and falls back to :severity.
  • __metadata__.first_of_day? / __metadata__.day_count — the day heading. A LiveView stream never hands a row its predecessor, so the READ decides which row opens a day and how many events that day holds; a row without them simply gets no heading.
  • a timestamp field, named by the :timestamp template option.

Template options

  • :timestamp — the record's timestamp field (default :inserted_at).
  • :max_cap — the read's scan ceiling, when it has one. A count that reaches it is only a floor, so it reads 10,000+ rather than claiming an exact total. Default nil — counts are exact.

Used by MishkaCmsCore.Activity.ActivityEntry (the unified log at /admin/dashboard/runtime/activity) and MishkaDocument.EventLog (the document event log at /admin/dashboard/document/event-logs).

See MishkaCmsCore.Activity.Query and MishkaCmsCoreWeb.Live.Admin.Dashboard.Activity.Index.

Summary

Functions

The bg-/text- pair an actor avatar carries for a row of this palette value — the same tint the node beside it uses, so the two always agree. Takes the row's tone-or-severity, not the actor: the name already says who that was.

The dot colour for one palette value — a :severity (:info/:warn/:error), a content-change :tone (:created/:updated/:destroyed), or an action filter's raw value (create/update/ destroy, which resolve to their tone's colour). The node is a tinted disc (node_class/1) around this solid dot; the filter switch reuses it for its per-option dots. An unknown value renders no dot rather than guess. Accepts the atom or its string form.

The tinted-disc background the node draws around its dot_class/1 dot, for a :severity or a content-change :tone. An unknown or nil value reads as the :info/:created green. Accepts the atom or its string form.

The filter bar: a short :select renders as a segmented switch, a long one as a dropdown, a :text filter as the search box and a :date_range as a pair of date inputs. The phx-change="filter" form and the input names are Gervaz's contract — only the look is ours.

The footer: a centred load-more, driven straight from the ui_adapter so it can carry the design's classes (Shared.render_pagination/1 hardcodes its own).

Functions

avatar_tone_class(value)

@spec avatar_tone_class(atom() | String.t() | nil) :: String.t()

The bg-/text- pair an actor avatar carries for a row of this palette value — the same tint the node beside it uses, so the two always agree. Takes the row's tone-or-severity, not the actor: the name already says who that was.

For a resource's :actor column render; a content-change :tone (:created/:updated/ :destroyed) colours by action, any other value by severity, and an unknown one reads green. Accepts the atom or its string form.

dot_class(value)

@spec dot_class(atom() | String.t() | nil) :: String.t() | nil

The dot colour for one palette value — a :severity (:info/:warn/:error), a content-change :tone (:created/:updated/:destroyed), or an action filter's raw value (create/update/ destroy, which resolve to their tone's colour). The node is a tinted disc (node_class/1) around this solid dot; the filter switch reuses it for its per-option dots. An unknown value renders no dot rather than guess. Accepts the atom or its string form.

node_class(value)

@spec node_class(atom() | String.t() | nil) :: String.t()

The tinted-disc background the node draws around its dot_class/1 dot, for a :severity or a content-change :tone. An unknown or nil value reads as the :info/:created green. Accepts the atom or its string form.

render_bulk_actions(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_bulk_actions/1.

render_empty(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_empty/1.

render_error(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_error/1.

render_filters(assigns)

The filter bar: a short :select renders as a segmented switch, a long one as a dropdown, a :text filter as the search box and a :date_range as a pair of date inputs. The phx-change="filter" form and the input names are Gervaz's contract — only the look is ours.

render_header(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_header/1.

render_loading(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_loading/1.

render_pagination(assigns)

The footer: a centred load-more, driven straight from the ui_adapter so it can carry the design's classes (Shared.render_pagination/1 hardcodes its own).

render_template_switcher(assigns)

Callback implementation for MishkaGervaz.Table.Behaviours.Template.render_template_switcher/1.