# `MishkaBlogWeb.Live.Admin.Dashboard.VersionsModal`
[🔗](https://github.com/mishka-group/mishka_blog/blob/v0.0.1/lib/mishka_blog_web/live/admin/dashboard/versions_modal.ex#L5)

The version history of a dashboard list page: a modal that lists one record's versions a page at a
time, previews one of them, and restores one. The page keeps the template, its `:versions_modal`
and the one-line event handlers; everything they do is here.

Every function takes the page's socket and returns it, with the assigns the template reads:
`:versions`, `:versions_record_id`, `:versions_record_name`, `:versions_loading`,
`:versions_page`, `:versions_per_page`, `:versions_total`, `:version_masters` and
`:preview_version_id`.

    @versions [
      resource: MishkaBlog.Blogger,
      name: :display_name,
      modal: "blogger-versions-modal",
      not_found: gettext_noop("Blogger not found or access denied")
    ]

    def mount(_params, _session, socket) do
      {:ok, VersionsModal.assign_defaults(socket)}
    end

    def handle_event("restore_version", %{"version-id" => id}, socket),
      do: {:noreply, VersionsModal.restore(socket, @versions, id)}

    def handle_info({:row_action, "show_versions", %{"id" => id}}, socket),
      do: {:noreply, VersionsModal.show(socket, @versions, id)}

    def handle_async(:load_versions, result, socket),
      do: {:noreply, VersionsModal.loaded(socket, @versions, result)}

The versions are read, and a version is restored, as the signed-in user in `:current_user`: a
master through the master actions and every site, a site's admin through the site's own.

## Options

* `:resource` - Required. The record's resource. It needs the `:get_with_versions` and
  `:master_get_with_versions` reads, a `Version` resource beside it, and the
  `:restore_version_api` and `:master_restore_version_api` actions.
* `:name` - Required. The attribute shown as the modal's subtitle.
* `:modal` - Required. The DOM id of the versions modal.
* `:not_found` - Required. The flash for a record that cannot be read.
* `:load` - What else the read loads, as `[master: [...], site: [...]]`.
* `:loaded` - A `(socket, record)` function run once the versions are in, to assign more.

# `assign_defaults`

```elixir
@spec assign_defaults(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
```

The assigns a page starts with, no record selected and the modal empty.

# `close_modal`

```elixir
@spec close_modal(Phoenix.LiveView.Socket.t(), String.t()) ::
  Phoenix.LiveView.Socket.t()
```

Hides the modal `id`, the way `open_modal/2` shows it.

# `load`

```elixir
@spec load(Phoenix.LiveView.Socket.t(), keyword()) :: Phoenix.LiveView.Socket.t()
```

Reads the current page of the selected record's versions in the background.

# `loaded`

```elixir
@spec loaded(Phoenix.LiveView.Socket.t(), keyword(), term()) ::
  Phoenix.LiveView.Socket.t()
```

Takes the result of the `:load_versions` async started by `load/2`: the versions on success, a
flash on a failure, and the modal closed when the record cannot be read.

# `next_page`

```elixir
@spec next_page(Phoenix.LiveView.Socket.t(), keyword()) :: Phoenix.LiveView.Socket.t()
```

Goes to the next page of versions; on the last page the socket is left as it is.

# `open_modal`

```elixir
@spec open_modal(Phoenix.LiveView.Socket.t(), String.t()) ::
  Phoenix.LiveView.Socket.t()
```

Shows the modal `id`. A modal opened by `:if` snaps in and out, gone from the DOM before its own
transition can run, so the modals stay rendered and are driven by the `gervaz:exec-js` bridge the
Gervaz form uses.

# `previous_page`

```elixir
@spec previous_page(Phoenix.LiveView.Socket.t(), keyword()) ::
  Phoenix.LiveView.Socket.t()
```

Goes to the previous page of versions; on the first page the socket is left as it is.

# `reset`

```elixir
@spec reset(Phoenix.LiveView.Socket.t()) :: Phoenix.LiveView.Socket.t()
```

Forgets the record and its versions, as when the modal is dismissed.

# `restore`

```elixir
@spec restore(Phoenix.LiveView.Socket.t(), keyword(), String.t()) ::
  Phoenix.LiveView.Socket.t()
```

Restores the selected record to the version `version_id`. On success the modal closes and a flash
says so; otherwise the modal stays and the flash is the refusal.

# `show`

```elixir
@spec show(Phoenix.LiveView.Socket.t(), keyword(), String.t()) ::
  Phoenix.LiveView.Socket.t()
```

Opens the modal for the record `record_id` and starts reading its first page of versions.

# `toggle_preview`

```elixir
@spec toggle_preview(Phoenix.LiveView.Socket.t(), String.t()) ::
  Phoenix.LiveView.Socket.t()
```

Opens the preview of the version `version_id`, or closes it when it is already open.

---

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