The version-history modal's body and footer, shared by every admin page that has one.
A collection, a post, a blogger, a team and a tag all keep AshPaperTrail history and all show it the same way: a list of versions, each with when it happened, which action wrote it, who by, and which fields it touched — plus a preview that opens the changes in place and a Restore beside it. Only the record differs, so only the record's page owns the modal shell and the head; everything inside it is this module.
The event contract
panel/1 renders buttons, not callbacks — the page must handle four events, which is the set the
existing pages already implement:
"toggle_version_preview"withphx-value-version-id"restore_version"withphx-value-version-id"versions_prev_page"and"versions_next_page"
Pair it with MishkaCmsCore.CoreComponents.modal/1 given padding_class="p-0" and
MishkaCmsCoreWeb.Templates.CardChrome.modal_head/1, the way
MishkaBlogWeb.Live.Admin.Dashboard.Post.Index does.
Summary
Functions
Chip colours for the action a version came from.
The word a version's chip shows for the action that wrote it. An action this does not name shows as it is stored.
Who wrote version, for the reader whose read loaded its :user.
One changed value, formatted for the preview box.
Which fields a version touched, as one line.
The last page of history, so the pager never offers a page that does not exist.
The ids among versions' authors that are masters, for panel/1's :master_ids.
The scrolling list of versions and the pager under it.
Functions
Chip colours for the action a version came from.
PaperTrail stores the resource's own action name, so a master's edit arrives as :master_update
and a publish as :publish. Anything unrecognised reads neutral rather than colourless — the
earlier version of this map covered only :create/:update/:destroy, which left most real
badges unstyled.
The word a version's chip shows for the action that wrote it. An action this does not name shows as it is stored.
Who wrote version, for the reader whose read loaded its :user.
The email the reader may read, "Master" when master_ids holds the version's user_id, "System"
for a version with no user, and "Unknown" for a user the reader's read did not return.
One changed value, formatted for the preview box.
Maps and lists are pretty-printed, a string is shown as written, and anything else falls back to
inspect/1. Formatting here rather than in the template keeps the value off its own line — under
whitespace-pre-wrap the template's own indentation would otherwise render as part of the value.
Which fields a version touched, as one line.
@spec last_page(non_neg_integer(), pos_integer()) :: pos_integer()
The last page of history, so the pager never offers a page that does not exist.
The ids among versions' authors that are masters, for panel/1's :master_ids.
Reads once, off the render: call it where the versions are loaded. An empty set when the read fails, so a master's version reads "Unknown" rather than breaking the modal.
The scrolling list of versions and the pager under it.
:preview_id is the one version whose changes are open; the list is an accordion, so at most one
is. The "Current" badge is only correct on the first page — it marks the newest version, and page
two's first row is not that.
Attributes
id(:string) (required)versions(:list) (required)loading(:boolean) (required)page(:integer) (required)per_page(:integer) (required)total(:integer) (required)preview_id(:any) - Defaults tonil.master_ids(:any) -master_ids/1of:versions, so a master's version reads "Master" to a site user. Defaults toMapSet.new([]).empty_title(:string) - Defaults tonil.empty_hint(:string) - Defaults tonil.toggle_event(:string) - Defaults to"toggle_version_preview".restore_event(:string) - Defaults to"restore_version".prev_event(:string) - Defaults to"versions_prev_page".next_event(:string) - Defaults to"versions_next_page".