Masu.History behaviour (Masu v0.7.0)

Copy Markdown View Source

Where a grid keeps the history of its cells: who changed a cell, when, from what to what; and a value of the history brought back.

<.data_grid id="orders" source={Order} repo={Repo} changeset={&Order.changeset/2}
  history={MyApp.GridHistory} user={@user}>

history is a module of this behaviour. Masu has two:

A store of your own implements the callbacks below over what your app already keeps (an audit table, PaperTrail, a service).

What is recorded

Every write of the grid (see Masu.Write) that saves: a cell edited, pasted, filled, undone or restored is an entry of its cell, with its value before and after, as the browser gets them; a new row and a row deleted are an entry of the row. The entries of one write (a paste of 200 cells) share a batch. Who is the grid's user (:id and :name); when, the time of the record.

The grid records what its writes save, the grid's own and your on_update's alike. What your app changes another way (an action's Repo.update_all, a job) it records with record/2.

In the row's transaction, or after it

When the store keeps the history in the grid's own repo (repo/0), the grid's own way of saving (Masu.Write.save/1) records a change in the transaction that saves it: the change and its record are saved together, or neither. In another repo (a SQLite file next to a PostgreSQL app, say), no transaction spans both: a change is recorded just after it is saved, and a node that stops between the two leaves it unrecorded; a change that was not saved is never recorded. Keep the history in the main repo when every change must have its record.

An on_update of yours that saves in a transaction of its own records in it with Masu.Write.record/3.

Summary

Callbacks

The entries of a batch (one write), as recorded.

An entry by its id, or nil.

The entries of a cell of the grid, newest first. Options: :limit.

The entries of a row of the grid (of its cells, and of the row), newest first. Options: :limit.

The latest entries of the grid, newest first. Options: :limit.

Keeps entries.

The Ecto repo that keeps the entries, or nil: when it is the grid's own, the grid records a change in the transaction that saves it.

Functions

Records entries in store: what your app changed another way than the grid's writes. fields of each: :grid, :row_id, :key, :before, :after (as the browser gets them), and :op, :origin, :batch, :user (a map of :id and :name), which the entry takes as they are.

Callbacks

batch(grid, batch)

@callback batch(grid :: String.t(), batch :: String.t()) :: [Masu.History.Entry.t()]

The entries of a batch (one write), as recorded.

entry(grid, id)

@callback entry(grid :: String.t(), id :: String.t()) :: Masu.History.Entry.t() | nil

An entry by its id, or nil.

for_cell(grid, row_id, key, opts)

@callback for_cell(
  grid :: String.t(),
  row_id :: term(),
  key :: String.t(),
  opts :: keyword()
) :: [
  Masu.History.Entry.t()
]

The entries of a cell of the grid, newest first. Options: :limit.

for_row(grid, row_id, opts)

@callback for_row(grid :: String.t(), row_id :: term(), opts :: keyword()) :: [
  Masu.History.Entry.t()
]

The entries of a row of the grid (of its cells, and of the row), newest first. Options: :limit.

recent(grid, opts)

@callback recent(grid :: String.t(), opts :: keyword()) :: [Masu.History.Entry.t()]

The latest entries of the grid, newest first. Options: :limit.

record(entries)

@callback record(entries :: [Masu.History.Entry.t()]) :: :ok

Keeps entries.

repo()

(optional)
@callback repo() :: module() | nil

The Ecto repo that keeps the entries, or nil: when it is the grid's own, the grid records a change in the transaction that saves it.

Functions

record(store, entries)

@spec record(module(), [map()]) :: :ok

Records entries in store: what your app changed another way than the grid's writes. fields of each: :grid, :row_id, :key, :before, :after (as the browser gets them), and :op, :origin, :batch, :user (a map of :id and :name), which the entry takes as they are.

Masu.History.record(MyApp.GridHistory, [
  %{grid: "orders", row_id: order.id, key: "status", before: "paid", after: "archived",
    origin: :archive, user: user}
])