defmodule Observer.Web.Components.Core do @moduledoc """ Provides core UI components. """ use Observer.Web, :html alias Phoenix.HTML.Form @doc ~S""" Renders a table with generic metric log styling. ## Examples <.table_tracing id="users" rows={@users}> <:col :let={user} label="id"><%= user.id %> <:col :let={user} label="username"><%= user.username %> """ attr :id, :string, required: true attr :rows, :list, required: true attr :row_id, :any, default: nil, doc: "the function for generating the row id" attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row" attr :transition, :boolean, default: false attr :row_item, :any, default: &Function.identity/1, doc: "the function for mapping each row before calling the :col slots" slot :col, required: true do attr :label, :string end def table_tracing(assigns) do assigns = with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end) end ~H"""
{col[:label]}
{render_slot(col, @row_item.(row))}
""" end @doc ~S""" Renders a value that stays plain text while it is short and collapses behind a click-to-expand summary when it exceeds `max_chars`, following the same pattern as the tracing results content. ## Examples <.truncated value={row.name} /> <.truncated value={table.owner_label} max_chars={30} /> """ attr :value, :string, required: true attr :max_chars, :integer, default: 40 def truncated(assigns) do ~H""" {@value}
@max_chars}> {String.slice(@value, 0, @max_chars)}…
{@value}
""" end @doc ~S""" Renders a disclosure row: a single truncated line preceded by a triangle marker that is filled when there is more content to expand and hollow (and non-interactive) when the line is all there is - so a list of rows reads at a glance which entries hide detail. Used by the Logs pillar; any table listing collapsible rows can adopt it. ## Examples <.disclosure id="log-entry-1" expandable?={entry.expandable?} title={entry.summary}> <:summary>{entry.summary}
{entry.content}
""" attr :id, :string, required: true attr :expandable?, :boolean, default: true attr :summary_class, :any, default: nil attr :title, :string, default: nil slot :summary, required: true slot :inner_block def disclosure(assigns) do ~H"""
{render_slot(@summary)}
{render_slot(@summary)}
{render_slot(@inner_block)}
""" end @doc ~S""" Renders a table with process styling. ## Examples <.table id="users" rows={@users}> <:col :let={user} label="id"><%= user.id %> <:col :let={user} label="username"><%= user.username %> """ attr :id, :string, required: true attr :title, :string, required: true attr :rows, :list, required: true attr :row_id, :any, default: nil, doc: "the function for generating the row id" attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row" attr :transition, :boolean, default: false attr :title_bg_color, :string, default: "standard" attr :row_item, :any, default: &Function.identity/1, doc: "the function for mapping each row before calling the :col slots" slot :col, required: true do attr :label, :string end def table_process(assigns) do assigns = with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end) end ~H"""
{@title}
{render_slot(col, @row_item.(row))}
""" end defp title_bg_color("liveview"), do: "bg-green-200 dark:bg-green-900" defp title_bg_color(_any), do: "bg-zinc-200 dark:bg-zinc-500" @doc ~S""" Renders a table with generic metrics styling. ## Examples <.table id="users" rows={@users}> <:col :let={user} label="id"><%= user.id %> <:col :let={user} label="username"><%= user.username %> """ attr :id, :string, required: true attr :rows, :list, required: true attr :row_id, :any, default: nil, doc: "the function for generating the row id" attr :row_click, :any, default: nil, doc: "the function for handling phx-click on each row" attr :transition, :boolean, default: false attr :h_max_size, :string, default: "h-64" attr :row_item, :any, default: &Function.identity/1, doc: "the function for mapping each row before calling the :col and :action slots" slot :col, required: true do attr :label, :string end def table_metrics(assigns) do assigns = with %{rows: %Phoenix.LiveView.LiveStream{}} <- assigns do assign(assigns, row_id: assigns.row_id || fn {id, _item} -> id end) end ~H"""
{col[:label]}
{render_slot(col, @row_item.(row))}
""" end @doc """ Renders an input with label and error messages. A `Phoenix.HTML.FormField` may be passed as argument, which is used to retrieve the input name, id, and values. Otherwise all attributes may be passed explicitly. ## Types This function accepts all HTML input types, considering that: * You may also set `type="select"` to render a ` {@label} """ end def input(%{type: "select"} = assigns) do ~H"""
<.label for={@id}>{@label}
""" end def input(%{type: "select-undefined-class"} = assigns) do ~H"""
<.label for={@id}>{@label}
""" end def input(%{type: "textarea"} = assigns) do ~H"""
<.label for={@id}>{@label}
""" end def input(%{type: "text-custom-search"} = assigns) do ~H"""
<.label for={@id}>{@label}
""" end # All other inputs text, datetime-local, url, password, etc. are handled here... def input(assigns) do ~H"""
<.label for={@id}>{@label}
""" end @doc """ Translates an error message using gettext. """ def translate_error({msg, _opts}) do msg end @doc """ Translates the errors for a field from a keyword list of errors. """ def translate_errors(errors, field) when is_list(errors) do for {^field, {msg, opts}} <- errors, do: translate_error({msg, opts}) end @doc """ Renders a label. """ attr :for, :string, default: nil slot :inner_block, required: true def label(assigns) do ~H""" """ end end