# `MishkaCmsCoreWeb.Templates.VersionHistory`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core_web/templates/version_history.ex#L5)

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"` with `phx-value-version-id`
  * `"restore_version"` with `phx-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.

# `action_color`

```elixir
@spec action_color(atom()) :: String.t()
```

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.

# `action_label`

```elixir
@spec action_label(atom()) :: String.t() | atom()
```

The word a version's chip shows for the action that wrote it. An action this does not name shows
as it is stored.

# `author`

```elixir
@spec author(map(), MapSet.t()) :: String.t()
```

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.

# `change_value`

```elixir
@spec change_value(term()) :: String.t()
```

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.

# `changed_fields`

```elixir
@spec changed_fields(map() | nil) :: String.t() | nil
```

Which fields a version touched, as one line.

# `last_page`

```elixir
@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.

# `master_ids`

```elixir
@spec master_ids([map()]) :: MapSet.t()
```

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.

# `panel`

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 to `nil`.
* `master_ids` (`:any`) - `master_ids/1` of `:versions`, so a master's version reads "Master" to a site user. Defaults to `MapSet.new([])`.
* `empty_title` (`:string`) - Defaults to `nil`.
* `empty_hint` (`:string`) - Defaults to `nil`.
* `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"`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
