View Source Phoenix.LiveDashboard.PageBuilder behaviour (LiveDashboard v0.7.2)
Page builder is the default mechanism for building custom dashboard pages.
Each dashboard page is a LiveView with additional callbacks for
customizing the menu appearance. One notable difference, however,
is that a page implements a render_page/1
callback, which must
return one or more page builder components, instead of a render/1
callback that returns ~H
or ~L
(deprecated).
A simple and straight-forward example of a custom page is the
Phoenix.LiveDashboard.EtsPage
that ships with the dashboard:
defmodule Phoenix.LiveDashboard.EtsPage do
@moduledoc false
use Phoenix.LiveDashboard.PageBuilder
@impl true
def menu_link(_, _) do
{:ok, "ETS"}
end
@impl true
def render_page(_assigns) do
table(
columns: table_columns(),
id: :ets_table,
row_attrs: &row_attrs/1,
row_fetcher: &fetch_ets/2,
rows_name: "tables",
title: "ETS"
)
end
defp fetch_ets(params, node) do
%{search: search, sort_by: sort_by, sort_dir: sort_dir, limit: limit} = params
# Here goes the code that goes through all ETS tables, searches
# (if not nil), sorts, and limits them.
#
# It must return a tuple where the first element is list with
# the current entries (up to limit) and an integer with the
# total amount of entries.
# ...
end
defp table_columns() do
[
%{
field: :name,
header: "Name or module",
},
%{
field: :protection
},
%{
field: :type
},
%{
field: :size,
cell_attrs: [class: "text-right"],
sortable: :desc
},
%{
field: :memory,
format: &format_words/1,
sortable: :desc
},
%{
field: :owner,
format: &encode_pid/1
}
]
end
defp row_attrs(table) do
[
{"phx-click", "show_info"},
{"phx-value-info", encode_ets(table[:id])},
{"phx-page-loading", true}
]
end
end
Once a page is defined, it must be declared in your live_dashboard
route as follows:
live_dashboard "/dashboard",
additional_pages: [
route_name: MyAppWeb.MyCustomPage
]
Or alternatively:
live_dashboard "/dashboard",
additional_pages: [
route_name: {MyAppWeb.MyCustomPage, some_option: ...}
]
The second argument of the tuple will be given to the init/1
callback. If not tuple is given, init/1
will receive an empty
list.
components
Components
A page can only have the components listed with this page.
We currently support card/1
, columns/1
, fields_card/1
,
layered_graph/1
, nav_bar/1
, row/1
, shared_usage_card/1
, table/1
,
and usage_card/1
.
helpers
Helpers
Some helpers are available for page building. The supported
helpers are: live_dashboard_path/2
, live_dashboard_path/3
,
encode_app/1
, encode_ets/1
, encode_pid/1
, encode_port/1
,
and encode_socket/1
.
Link to this section Summary
Callbacks
Callback invoked when an event is called.
Callback invoked when a page is declared in the router.
Callback invoked when a page is declared in the router.
Functions
Renders a card component.
Renders a column component.
Encodes an application for URLs.
Encodes ETSs references for URLs.
Encodes PIDs for URLs.
Encodes Port for URLs.
Encodes Sockets for URLs.
Renders a fields card component.
A component for drawing layered graphs.
Computes a router path to the current page.
Computes a router path to the current page with merged params.
Renders a nav bar.
Renders a row component.
Renders a shared usage card component.
Renders a table component.
Renders a usage card component.
Link to this section Types
Link to this section Callbacks
@callback handle_event(event :: binary(), unsigned_params(), socket :: Socket.t()) :: {:noreply, Socket.t()} | {:reply, map(), Socket.t()}
Callback invoked when an event is called.
Note that show_info
event is handled automatically by
Phoenix.LiveDashboard.PageBuilder
,
but the info
parameter (phx-value-info
) needs to be encoded with
one of the encode_*
helper functions.
For more details, see Phoenix.LiveView bindings
@callback handle_info(msg :: term(), socket :: Socket.t()) :: {:noreply, Socket.t()}
@callback handle_params(unsigned_params(), uri :: String.t(), socket :: Socket.t()) :: {:noreply, Socket.t()}
@callback handle_refresh(socket :: Socket.t()) :: {:noreply, Socket.t()}
@callback init(term()) :: {:ok, session()} | {:ok, session(), requirements()}
Callback invoked when a page is declared in the router.
It receives the router options and it must return the
tuple {:ok, session, requirements}
.
The page session will be serialized to the client and
received on mount
.
The requirements is an optional keyword to detect the state of the node.
The result of this detection will be passed as second
argument in the menu_link/2
callback.
The possible values are:
:applications
list of applications that are running or not.:modules
list of modules that are loaded or not.:pids
list of processes that alive or not.
@callback mount(unsigned_params(), session(), socket :: Socket.t()) :: {:ok, Socket.t()} | {:ok, Socket.t(), keyword()}
@callback render_page(assigns :: Socket.assigns()) :: component()
Link to this section Functions
Renders a card component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
card(
title: "Run queues",
inner_title: "Total",
class: ["additional-class"],
value: 1.5
)
end
You can see it in use the Home and OS Data pages.
Options
These are the options supported by the component:
:value
- Required. The value that the card will show.:title
- The title above the card. Default:nil
.:inner_title
- The title inside the card. Default:nil
.:hint
- A textual hint to show close to the title. Default:nil
.:inner_hint
- A textual hint to show close to the inner title. Default:nil
.:class
- A list of additional css classes that will be added along banner-card class. Default:[]
.
Renders a column component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
columns(
components: [
card(...),
card_usage(...)
]
)
end
You can see it in use the Home page and OS Data pages.
Options
These are the options supported by the component:
:components
- Required. A list of components. It can receive up to 3 components. Each element will be one column.
Encodes an application for URLs.
example
Example
This function can be used to encode an application for an event value:
<button phx-click="show-info" phx-value-info=<%= encode_app(@my_app) %>/>
Encodes ETSs references for URLs.
example
Example
This function can be used to encode an ETS reference for an event value:
<button phx-click="show-info" phx-value-info=<%= encode_ets(@reference) %>/>
Encodes PIDs for URLs.
example
Example
This function can be used to encode a PID for an event value:
<button phx-click="show-info" phx-value-info=<%= encode_pid(@pid) %>/>
Encodes Port for URLs.
example
Example
This function can be used to encode a Port for an event value:
<button phx-click="show-info" phx-value-info=<%= encode_port(@port) %>/>
Encodes Sockets for URLs.
example
Example
This function can be used to encode @socket
for an event value:
<button phx-click="show-info" phx-value-info=<%= encode_socket(@socket) %>/>
Renders a fields card component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
fields_card(
title: "Run queues",
inner_title: "Total",
fields: ["USER": "...", "ROOTDIR": "..."]
)
end
You can see it in use the Home page in the Environment section.
Options
These are the options supported by the component:
:fields
- Required. A list of key-value elements that will be shown inside the card.:title
- The title above the card. Default:nil
.:inner_title
- The title inside the card. Default:nil
.:hint
- A textual hint to show close to the title. Default:nil
.:inner_hint
- A textual hint to show close to the inner title. Default:nil
.
A component for drawing layered graphs.
This is useful to represent pipelines like we have on BroadwayDashboard where each layer points to nodes of the layer below. It draws the layers from top to bottom.
The calculation of layers and positions is done automatically based on options.
options
Options
:title
- The title of the component. Default:nil
.:hint
- A textual hint to show close to the title. Default:nil
.:layers
- A graph of layers with nodes. They represent our graph structure (see example). Each layer is a list of nodes, where each node has the following fields::id
- The ID of the given node.:children
- The IDs of children nodes.:data
- A string or a map. If it's a map, the required fields aredetail
andlabel
.
:show_grid?
- Enable or disable the display of a grid. This is useful for development. Default:false
.:y_label_offset
- The "y" offset of label position relative to the center of its circle. Default:5
.:y_detail_offset
- The "y" offset of detail position relative to the center of its circle. Default:18
.:background
- A function that calculates the background for a node based on it's data. Default:fn _node_data -> "gray" end
.:format_label
- A function that formats the label. Defaults to a function that returns the label or data if data is binary.:format_detail
- A function that formats the detail field. This is only going to be called if data is a map. Default:fn node_data -> node_data.detail end
.
examples
Examples
iex> layers = [
...> [
...> %{
...> id: "a1",
...> data: "a1",
...> children: ["b1"]
...> }
...> ],
...> [
...> %{
...> id: "b1"
...> data: %{
...> detail: 0,
...> label: "b1"
...> },
...> children: []
...> }
...> ]
...> ]
iex> layered_graph(layers: layers, title: "My Graph", hint: "A simple graph")
@spec live_dashboard_path( Socket.t(), page :: %Phoenix.LiveDashboard.PageBuilder{ allow_destructive_actions: term(), info: term(), module: term(), node: term(), params: term(), route: term(), tick: term() } ) :: binary()
Computes a router path to the current page.
@spec live_dashboard_path( Socket.t(), page :: %Phoenix.LiveDashboard.PageBuilder{ allow_destructive_actions: term(), info: term(), module: term(), node: term(), params: term(), route: term(), tick: term() }, map() | Keyword.t() ) :: binary()
Computes a router path to the current page with merged params.
Renders a row component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
row(
components: [
card(...),
columns(...)
]
)
end
You can see it in use the Home page and OS Data pages.
Options
These are the options supported by the component:
:components
- Required. A list of components. It can receive up to 3 components. Each element will be one column.
Renders a table component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
table(
columns: table_columns(),
id: @table_id,
row_attrs: &row_attrs/1,
row_fetcher: &fetch_applications/2,
title: "Applications"
)
end
You can see it in use the applications, processes, sockets pages and many others.
Options
These are the options supported by the component:
:id
- Required. Because is a statefulPhoenix.LiveComponent
an unique id is needed.:columns
- Required. AKeyword
list with the following keys::field
- Required. An identifier for the column.:sortable
- Required for at least one column. Either:asc
or:desc
with the default sorting. When set, the column header is clickable and it fetches again rows with the new order. Default:nil
.:header
- Label to show in the current column. Default value is calculated from:field
.:header_attrs
- A list with HTML attributes for the column header. Default:[]
.:format
- Function which receives the value and returns the cell information. Default is the field value itself.:cell_attrs
- A list with HTML attributes for the table cell. Default:[]
.
:row_fetcher
- Required. A function which receives the params and the node and returns a tuple with the rows and the total number:(params(), node() -> {list(), integer() | binary()})
. Optionally, if the function needs to keep a state, it can be defined as a tuple where the first element is a function and the second is the initial state. In this case, the function will receive the state as third argument and must return a tuple with the rows, the total number, and the new state for the following call:{(params(), node(), term() -> {list(), integer() | binary(), term()}), term()}
:rows_name
- A string to name the representation of the rows. Default is calculated from the current page.:row_attrs
- A function that return a list with HTML attributes for the table row. It receive the row as argument and return a list of 2 element tuple with HTML attribute name and value. The default function returns an empty list[]
.:default_sort_by
- The default columnt to sort by to. Defaults to the first sortable column.:title
- Required. The title of the table.:limit
- A list of integers to limit the number of rows to show. Default:[50, 100, 500, 1000, 5000]
. May be set tofalse
to disable thelimit
.:search
- A boolean indicating if the search functionality is enabled. Default:true
.:hint
- A textual hint to show close to the title. Default:nil
.
Renders a usage card component.
It can be rendered in any dashboard page via the render_page/1
function:
def render_page(assigns) do
usage_card(
usages: [
%{
current: 10,
limit: 150,
dom_sub_id: "1",
title: "Memory",
percent: "13"
}
],
dom_id: "memory"
)
end
You can see it in use the Home page and OS Data pages.
Options
These are the options supported by the component:
:usages
- Required. A list ofMap
with the following keys::current
- Required. The current value of the usage.:limit
- Required. The max value of usage.:dom_sub_id
- Required. An unique identifier for the usage that will be concatenated todom_id
.:percent
- The used percent if the usage. Default:nil
.:title
- Required. The title of the usage.:hint
- A textual hint to show close to the usage title. Default:nil
.
:dom_id
- Required. A unique identifier for all usages in this card.:title
- The title of the card. Default:nil
.:hint
- A textual hint to show close to the card title. Default:nil
.