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:
Masu.History.Ecto, a table of any Ecto repo: the grid's own, or another database (use Masu.History.Ecto, repo: MyApp.HistoryRepo, andmix masu.gen.historyfor its migration);Masu.History.Memory, in memory, for development and tests.
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
@callback batch(grid :: String.t(), batch :: String.t()) :: [Masu.History.Entry.t()]
The entries of a batch (one write), as recorded.
@callback entry(grid :: String.t(), id :: String.t()) :: Masu.History.Entry.t() | nil
An entry by its id, or nil.
@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.
@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.
@callback recent(grid :: String.t(), opts :: keyword()) :: [Masu.History.Entry.t()]
The latest entries of the grid, newest first. Options: :limit.
@callback record(entries :: [Masu.History.Entry.t()]) :: :ok
Keeps entries.
@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
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}
])