Visualize.Chart.Builder.Boards (Visualize v0.6.0)

Copy Markdown View Source

The board mode's editor (spec/14 §22, D-152): the pure writes of a board — a cell placed, a field read from a control — and the inspector panel that makes them.

A board chart holds a %Visualize.Board{}, not a stack of uses. Every write goes through a function here that builds the board it would make, and the mode validates that board alone before it keeps it (Visualize.Board.validate/1), so the board the builder holds always reads and a client can never place a cell over another or off the grid (§22.2, §22.3). Each cell previews alone through Visualize.Board.realise/4 (preview/3, §22.6).

This module compiles only when Phoenix.Component is loaded (spec/10 §1.1, D-45, D-85).

Summary

Functions

The variables a component declares, from its flattened design, sorted (spec/14 §22.4): the names a cell's variables may take. [] for a component the store does not hold, or one that reaches itself.

The first place in reading order — the first row, then the first column — where a w-by-h rectangle overlaps no cell of the board (spec/14 §22.3).

The inspector of the board mode (spec/14 §22.4): the selected cell — its title, its component, whether it joins the sync group, its variables, Edit component and Remove — then add a cell, the board's name, its window and zone, its sync group and staleness, its layout, its variables, and its faults given the store (§22.5).

The board with a cell at a rectangle, {:ok, board}, or {:error, errors}: every fault of the board the placement would make, alone — {:off_grid, 12} for a cell that runs past the grid, {:overlap, other} for one that shares a square, a type fault for a key that is not an integer of the right sign (spec/14 §22.3, spec/15 §3.1). The board is the server's: whatever rectangle a client sends, this is the one place it is written.

Each cell realised alone (spec/14 §22.6): Visualize.Board.realise/4 of a board holding that one cell and the board's shared state, at a container width of 1200, so one cell that cannot apply leaves every other drawn. %{cell => {:ok, svg} | {:error, lines}}, the chart a responsive root titled with the cell's title, the faults in Visualize.Board.format_error/1's words.

Sixty rows made from a schema, for a preview where the host gave none of a feed's (spec/14 §22.6): a :time field a second apart and ending at now, a :number window field (window: true, D-154) its row's place, 0 to 59, as a tick counts, any other :number field a slow sine, a :category field its order in turn — else "a", "b" and "c" — and a :text field its own name. The rows are shaped like the feed's, not its values.

Functions

declared(ref, fetch)

@spec declared(term(), (term() -> {:ok, map()} | :error)) :: [atom()]

The variables a component declares, from its flattened design, sorted (spec/14 §22.4): the names a cell's variables may take. [] for a component the store does not hold, or one that reaches itself.

iex> fetch = fn {:composite, 1} -> {:ok, %{vars: %{unit: %{default: "%"}, host: %{}}}} end
iex> Visualize.Chart.Builder.Boards.declared({:composite, 1}, fetch)
[:host, :unit]

free(board, w, h)

The first place in reading order — the first row, then the first column — where a w-by-h rectangle overlaps no cell of the board (spec/14 §22.3).

iex> board = Visualize.Board.from_map!(%{cells: %{
...>   a: %{x: 0, y: 0, w: 8, h: 2, ref: {:composite, 1}}
...> }})
iex> Visualize.Chart.Builder.Boards.free(board, 4, 2)
{8, 0}
iex> Visualize.Chart.Builder.Boards.free(board, 6, 1)
{0, 2}

panel(assigns)

The inspector of the board mode (spec/14 §22.4): the selected cell — its title, its component, whether it joins the sync group, its variables, Edit component and Remove — then add a cell, the board's name, its window and zone, its sync group and staleness, its layout, its variables, and its faults given the store (§22.5).

Attributes

  • id (:string) (required) - the panel's id.
  • mode (:map) (required) - the board mode's assigns, as the builder derives them for the open board (spec/14 §22).
  • target (:any) - the phx-target of every control. Defaults to nil.

place(board, cell, rect)

@spec place(Visualize.Board.t(), atom(), Visualize.Board.rect()) ::
  {:ok, Visualize.Board.t()} | {:error, [Visualize.Board.error()]}

The board with a cell at a rectangle, {:ok, board}, or {:error, errors}: every fault of the board the placement would make, alone — {:off_grid, 12} for a cell that runs past the grid, {:overlap, other} for one that shares a square, a type fault for a key that is not an integer of the right sign (spec/14 §22.3, spec/15 §3.1). The board is the server's: whatever rectangle a client sends, this is the one place it is written.

iex> board = Visualize.Board.from_map!(%{cells: %{
...>   a: %{x: 0, y: 0, w: 6, h: 2, ref: {:composite, 1}},
...>   b: %{x: 6, y: 0, w: 6, h: 2, ref: {:composite, 1}}
...> }})
iex> {:ok, moved} = Visualize.Chart.Builder.Boards.place(board, :b, %{x: 6, y: 2, w: 6, h: 3})
iex> Map.take(moved.cells.b, [:x, :y, :w, :h])
%{x: 6, y: 2, w: 6, h: 3}
iex> Visualize.Chart.Builder.Boards.place(board, :b, %{x: 4, y: 0, w: 6, h: 2})
{:error, [{[:cells, :b], {:overlap, :a}}]}
iex> Visualize.Chart.Builder.Boards.place(board, :b, %{x: 8, y: 4, w: 6, h: 2})
{:error, [{[:cells, :b], {:off_grid, 12}}]}

preview(board, fetch, opts)

@spec preview(Visualize.Board.t(), Visualize.Board.store(), keyword()) :: %{
  required(atom()) =>
    {:ok, String.t()}
    | {:error, [String.t()]}
    | {:fault, String.t(), [String.t()]}
}

Each cell realised alone (spec/14 §22.6): Visualize.Board.realise/4 of a board holding that one cell and the board's shared state, at a container width of 1200, so one cell that cannot apply leaves every other drawn. %{cell => {:ok, svg} | {:error, lines}}, the chart a responsive root titled with the cell's title, the faults in Visualize.Board.format_error/1's words.

Options

  • :pools - each cell's pool, by its name (default none)
  • :theme - as Visualize.Chart.apply/2 takes it
  • :describe - ({cell, slot} -> {:ok, schema} | {:error, reason}), as Visualize.Board.realise/4 takes it: the schema of a slot's feed

  • :refused - each cell the binding's type check refused, by its name, with its faults (D-153): it is not realised, and is drawn as the fault panel

A cell whose binding has the wrong type — refused, or reporting a {:type_mismatch, …} from application — is {:fault, svg, lines}: the board runtime's cell-state panel of {:invalid, errors} and every fault's words (spec/14 §18.4, §22.6).

sample(schema, now)

@spec sample(Visualize.Data.Schema.t(), DateTime.t()) :: [map()]

Sixty rows made from a schema, for a preview where the host gave none of a feed's (spec/14 §22.6): a :time field a second apart and ending at now, a :number window field (window: true, D-154) its row's place, 0 to 59, as a tick counts, any other :number field a slow sine, a :category field its order in turn — else "a", "b" and "c" — and a :text field its own name. The rows are shaped like the feed's, not its values.

iex> schema = Visualize.Data.Schema.new!(%{t: %{type: :time}, v: %{type: :number},
...>   state: %{type: :category, order: ["ok", "warn"]}})
iex> rows = Visualize.Chart.Builder.Boards.sample(schema, ~U[2026-10-11 12:00:00Z])
iex> {length(rows), List.last(rows).t, Enum.map(Enum.take(rows, 3), & &1.state)}
{60, ~U[2026-10-11 12:00:00Z], ["ok", "warn", "ok"]}