Masu.Sheet (Masu v0.7.0)

Copy Markdown View Source

A grid outside the LiveView: its rows, and its writes, for a job, a test, or an agent (Masu.Issho). The writes go the grid's way: its changeset or its on_update, its read-only rules, the compare of a cell someone changed meanwhile, its history, and its live topic, so the people who have the grid open see each change as it lands.

Define a grid once, as the attributes of Masu.Components.data_grid/1, and use it in both places:

defmodule MyApp.Grids do
  def tasks(scope) do
    [
      id: "tasks",
      source: MyApp.Tasks.query(scope),
      repo: MyApp.Repo,
      changeset: &MyApp.Tasks.Task.changeset/2,
      struct: %MyApp.Tasks.Task{},
      create_with: %{account_id: scope.account.id},
      deletable: true,
      history: MyApp.GridHistory,
      live: {MyApp.PubSub, "tasks:#{scope.account.id}"},
      columns: [
        [field: :title],
        [field: :status, type: :enum],
        [field: :due, type: :date]
      ]
    ]
  end
end
<.data_grid {MyApp.Grids.tasks(@current_scope)} scope={@current_scope} user={@user} />
sheet = Masu.Sheet.new(MyApp.Grids.tasks(scope))
Masu.Sheet.rows(sheet, filters: [{"status", :eq, "open"}], limit: 20)
Masu.Sheet.update(sheet, [%{"id" => 7, "key" => "status", "value" => "done"}],
  scope: scope, user: %{id: "agent:1", name: "Assistant"})

The columns of a sheet are those of columns, or its source's: a :col slot is of the HEEx that renders the grid, and a sheet has none. A grid given rows (a list) is a sheet of that list, which its writes do not change.

Summary

Functions

Whether the sheet edits cells, adds rows, deletes rows.

The columns of the sheet.

New rows, each the values of its cells by key: for each, {:ok, row} or {:error, errors} ([key, message], a key of nil for the row). Options as update/3.

Deletes rows, by their ids: the rows deleted, and the errors, each [id, message]. Options as update/3.

The rows of these ids that the sheet has (its source may show).

A row's id, as update/3 and delete/3 take it.

A sheet of a grid's attributes (a keyword list or a map, as data_grid/1 takes them). The attributes of the LiveView alone (issho, views, url...) are left out.

Rows of the sheet, in an order, filtered and searched as a person would (Masu.Query.new/2: sort, filters, search), from offset, at most limit (50 unless given, 500 at most): {:ok, %{rows:, total:}}, or what is wrong with the query. total is how many rows the query has, or {:at_least, n} for a count the source caps.

A row as a person reads it in the grid: each column's key and value, with the row's "id".

Edits cells, as a person types in them: each %{"id" => id, "key" => key, "value" => value}, with "before", the value seen, to refuse an edit of a cell someone changed since. Options: scope (in the Masu.Write), user (who, for the history and the people who see the rows change: %{id:, name:}), by (who, as the write's by says them; user unless given), and origin (:edit, :paste...).

Types

error()

@type error() :: [term()]

t()

@type t() :: %Masu.Sheet{
  attrs: map(),
  columns: [Masu.Column.t()],
  id: String.t(),
  source: Masu.Source.t()
}

Functions

can(sheet)

@spec can(t()) :: %{edit: boolean(), create: boolean(), delete: boolean()}

Whether the sheet edits cells, adds rows, deletes rows.

columns(sheet)

@spec columns(t()) :: [Masu.Column.t()]

The columns of the sheet.

create(sheet, drafts, opts \\ [])

@spec create(t(), [map()], keyword()) :: [ok: term(), error: [list()]]

New rows, each the values of its cells by key: for each, {:ok, row} or {:error, errors} ([key, message], a key of nil for the row). Options as update/3.

delete(sheet, ids, opts \\ [])

@spec delete(t(), [term()], keyword()) :: %{deleted: [term()], errors: [list()]}

Deletes rows, by their ids: the rows deleted, and the errors, each [id, message]. Options as update/3.

fetch(sheet, ids)

@spec fetch(t(), [term()]) :: [term()]

The rows of these ids that the sheet has (its source may show).

id(sheet, row)

@spec id(t(), term()) :: term()

A row's id, as update/3 and delete/3 take it.

new(attrs)

@spec new(keyword() | map()) :: t()

A sheet of a grid's attributes (a keyword list or a map, as data_grid/1 takes them). The attributes of the LiveView alone (issho, views, url...) are left out.

rows(sheet, opts \\ [])

@spec rows(t(), keyword()) ::
  {:ok, %{rows: [term()], total: term()}} | {:error, String.t()}

Rows of the sheet, in an order, filtered and searched as a person would (Masu.Query.new/2: sort, filters, search), from offset, at most limit (50 unless given, 500 at most): {:ok, %{rows:, total:}}, or what is wrong with the query. total is how many rows the query has, or {:at_least, n} for a count the source caps.

to_map(sheet, row)

@spec to_map(t(), term()) :: map()

A row as a person reads it in the grid: each column's key and value, with the row's "id".

update(sheet, edits, opts \\ [])

@spec update(t(), [map()], keyword()) :: %{
  saved: [term()],
  errors: [error()],
  saving: [list()]
}

Edits cells, as a person types in them: each %{"id" => id, "key" => key, "value" => value}, with "before", the value seen, to refuse an edit of a cell someone changed since. Options: scope (in the Masu.Write), user (who, for the history and the people who see the rows change: %{id:, name:}), by (who, as the write's by says them; user unless given), and origin (:edit, :paste...).

Gives the rows saved, and the errors, each [id, key, message] or, for a cell changed meanwhile, [id, key, message, value].