Undo and redo for a GanttEx.Store.
The history keeps snapshots of the store (cheap, thanks to immutable data
structures). Undoing returns the previous snapshot together with the
changes that lead to it (see GanttEx.Store.diff/2), so they can be
persisted like any other change.
iex> store = GanttEx.Store.new!([%{id: 1, text: "A", start_date: ~D[2025-01-01]}])
iex> history = GanttEx.History.new()
iex> {:ok, changed, _} = GanttEx.Store.update_task(store, 1, %{text: "B"})
iex> history = GanttEx.History.record(history, store)
iex> {:ok, history, restored, [{:task_updated, task, %{changes: changes}}]} = GanttEx.History.undo(history, changed)
iex> {task.text, changes, GanttEx.History.can_redo?(history)}
{"A", %{text: "A"}, true}
iex> {:ok, _history, _store, [{:task_updated, %{text: "B"}, _}]} = GanttEx.History.redo(history, restored)
iex> GanttEx.History.undo(GanttEx.History.new(), store)
:empty
Summary
Functions
Returns true when there is something to redo.
Returns true when there is something to undo.
Creates an empty history.
Records store as the state before a change. Clears the redo steps.
Goes forward one step from current, or returns :empty.
Goes back one step from current. Returns the restored store and the
changes from current to it, or :empty.
Types
@type t() :: %GanttEx.History{ future: [GanttEx.Store.t()], limit: pos_integer(), past: [GanttEx.Store.t()] }
Functions
Returns true when there is something to redo.
Returns true when there is something to undo.
Creates an empty history.
Options
:limit- how many steps are kept. Defaults to50.
@spec record(t(), GanttEx.Store.t()) :: t()
Records store as the state before a change. Clears the redo steps.
@spec redo(t(), GanttEx.Store.t()) :: {:ok, t(), GanttEx.Store.t(), [GanttEx.Store.change()]} | :empty
Goes forward one step from current, or returns :empty.
@spec undo(t(), GanttEx.Store.t()) :: {:ok, t(), GanttEx.Store.t(), [GanttEx.Store.change()]} | :empty
Goes back one step from current. Returns the restored store and the
changes from current to it, or :empty.