Current section

Files

Jump to
spectator src spectator@internal@components@ports_live.erl
Raw

src/spectator@internal@components@ports_live.erl

-module(spectator@internal@components@ports_live).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/spectator/internal/components/ports_live.gleam").
-export([app/0]).
-export_type([model/0, msg/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type model() :: {model,
gleam@option:option(gleam@erlang@atom:atom_()),
list({binary(), binary()}),
gleam@option:option(gleam@erlang@process:subject(msg())),
integer(),
list(spectator@internal@api:port_item()),
spectator@internal@api:port_sort_criteria(),
spectator@internal@api:sort_direction(),
gleam@option:option(spectator@internal@api:port_item()),
gleam@option:option(spectator@internal@api:port_details())}.
-opaque msg() :: refresh |
{created_subject, gleam@erlang@process:subject(msg())} |
{port_clicked, spectator@internal@api:port_item()} |
{heading_clicked, spectator@internal@api:port_sort_criteria()}.
-file("src/spectator/internal/components/ports_live.gleam", 38).
?DOC(false).
-spec init(list({binary(), binary()})) -> {model(), lustre@effect:effect(msg())}.
init(Params) ->
Node = spectator@internal@api:node_from_params(Params),
Info = spectator@internal@api:get_port_list(Node),
Refresh_interval = spectator@internal@common:get_refresh_interval(Params),
Default_sort_criteria = sort_by_port_input,
Default_sort_direction = descending,
Sorted = spectator@internal@api:sort_port_list(
Info,
Default_sort_criteria,
descending
),
Active_port = case spectator@internal@common:get_param(
Params,
<<"selected"/utf8>>
) of
{error, _} ->
none;
{ok, Raw_port_id} ->
gleam@option:then(
begin
_pipe = spectator@internal@api:decode_port(Raw_port_id),
gleam@option:from_result(_pipe)
end,
fun(Port_id) ->
gleam@option:then(
begin
_pipe@1 = spectator_ffi:get_port_info(Node, Port_id),
gleam@option:from_result(_pipe@1)
end,
fun(Info@1) -> {some, {port_item, Port_id, Info@1}} end
)
end
)
end,
Details@1 = case Active_port of
none ->
none;
{some, Ap} ->
case spectator_ffi:get_port_details(Node, erlang:element(2, Ap)) of
{ok, Details} ->
{some, Details};
{error, _} ->
none
end
end,
{{model,
Node,
spectator@internal@common:sanitize_params(Params),
none,
Refresh_interval,
Sorted,
Default_sort_criteria,
Default_sort_direction,
Active_port,
Details@1},
spectator@internal@common:emit_after(
Refresh_interval,
refresh,
none,
fun(Field@0) -> {created_subject, Field@0} end
)}.
-file("src/spectator/internal/components/ports_live.gleam", 92).
?DOC(false).
-spec do_refresh(model()) -> model().
do_refresh(Model) ->
Info = spectator@internal@api:get_port_list(erlang:element(2, Model)),
Sorted = spectator@internal@api:sort_port_list(
Info,
erlang:element(7, Model),
erlang:element(8, Model)
),
Active_port@1 = case erlang:element(9, Model) of
none ->
none;
{some, Active_port} ->
case spectator_ffi:get_port_info(
erlang:element(2, Model),
erlang:element(2, Active_port)
) of
{ok, Info@1} ->
{some, {port_item, erlang:element(2, Active_port), Info@1}};
{error, _} ->
none
end
end,
Details@1 = case Active_port@1 of
none ->
none;
{some, Ap} ->
case spectator_ffi:get_port_details(
erlang:element(2, Model),
erlang:element(2, Ap)
) of
{ok, Details} ->
{some, Details};
{error, _} ->
none
end
end,
{model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
Sorted,
erlang:element(7, Model),
erlang:element(8, Model),
Active_port@1,
Details@1}.
-file("src/spectator/internal/components/ports_live.gleam", 121).
?DOC(false).
-spec update(model(), msg()) -> {model(), lustre@effect:effect(msg())}.
update(Model, Msg) ->
case Msg of
refresh ->
{do_refresh(Model),
spectator@internal@common:emit_after(
erlang:element(5, Model),
refresh,
erlang:element(4, Model),
fun(Field@0) -> {created_subject, Field@0} end
)};
{created_subject, Subject} ->
{{model,
erlang:element(2, Model),
erlang:element(3, Model),
{some, Subject},
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
lustre@effect:none()};
{port_clicked, P} ->
New_model = begin
_pipe = {model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
erlang:element(8, Model),
{some, P},
erlang:element(10, Model)},
do_refresh(_pipe)
end,
{New_model, lustre@effect:none()};
{heading_clicked, Criteria} ->
case Criteria of
C when C =:= erlang:element(7, Model) ->
New_model@1 = {model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
erlang:element(7, Model),
spectator@internal@api:invert_sort_direction(
erlang:element(8, Model)
),
erlang:element(9, Model),
erlang:element(10, Model)},
{do_refresh(New_model@1), lustre@effect:none()};
C@1 ->
New_model@2 = {model,
erlang:element(2, Model),
erlang:element(3, Model),
erlang:element(4, Model),
erlang:element(5, Model),
erlang:element(6, Model),
C@1,
erlang:element(8, Model),
erlang:element(9, Model),
erlang:element(10, Model)},
{do_refresh(New_model@2), lustre@effect:none()}
end
end.
-file("src/spectator/internal/components/ports_live.gleam", 297).
?DOC(false).
-spec render_name(spectator@internal@api:port_item()) -> lustre@vdom@vnode:element(any()).
render_name(Process) ->
case erlang:element(3, erlang:element(3, Process)) of
none ->
spectator@internal@views@display:port(erlang:element(2, Process));
{some, Name} ->
lustre@element@html:text(erlang:atom_to_binary(Name))
end.
-file("src/spectator/internal/components/ports_live.gleam", 304).
?DOC(false).
-spec render_primitive_list(
list(spectator@internal@api:system_primitive()),
list({binary(), binary()})
) -> list(lustre@vdom@vnode:element(any())).
render_primitive_list(Primitives, Params) ->
_pipe = gleam@list:map(
Primitives,
fun(_capture) ->
spectator@internal@views@display:system_primitive(_capture, Params)
end
),
gleam@list:intersperse(_pipe, lustre@element@html:text(<<", "/utf8>>)).
-file("src/spectator/internal/components/ports_live.gleam", 312).
?DOC(false).
-spec render_details(
gleam@option:option(spectator@internal@api:port_item()),
gleam@option:option(spectator@internal@api:port_details()),
list({binary(), binary()})
) -> lustre@vdom@vnode:element(any()).
render_details(P, D, Params) ->
case {P, D} of
{{some, Port}, {some, Details}} ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"details compact"/utf8>>)],
[lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Connected Process"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:system_primitive(
erlang:element(
4,
erlang:element(3, Port)
),
Params
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(<<"Links"/utf8>>)]
),
lustre@element@html:dd(
[],
render_primitive_list(
erlang:element(2, Details),
Params
)
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Monitored By"/utf8>>
)]
),
lustre@element@html:dd(
[],
render_primitive_list(
erlang:element(3, Details),
Params
)
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(<<"Monitors"/utf8>>)]
),
lustre@element@html:dd(
[],
render_primitive_list(
erlang:element(4, Details),
Params
)
)]
)]
);
{_, _} ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"footer-placeholder"/utf8>>)],
[lustre@element@html:text(
<<"Click a process to see details"/utf8>>
)]
)
end.
-file("src/spectator/internal/components/ports_live.gleam", 165).
?DOC(false).
-spec view(model()) -> lustre@vdom@vnode:element(msg()).
view(Model) ->
lustre@element@html:table(
[],
[lustre@element@html:thead(
[],
[lustre@element@html:tr(
[],
[spectator@internal@views@table:heading(
<<"Name"/utf8>>,
<<"Port ID or registered name"/utf8>>,
sort_by_port_name,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Command"/utf8>>,
<<"Command name that started the port"/utf8>>,
sort_by_port_command,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Process"/utf8>>,
<<"Process connected to the port"/utf8>>,
sort_by_port_connected_process,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"OS PID"/utf8>>,
<<"Operating system process ID"/utf8>>,
sort_by_port_os_pid,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Input"/utf8>>,
<<"Input: Number of bytes read from the port"/utf8>>,
sort_by_port_input,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
),
spectator@internal@views@table:heading(
<<"Output"/utf8>>,
<<"Output: Number of bytes written to the port"/utf8>>,
sort_by_port_output,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
),
spectator@internal@views@table:heading(
<<"Memory"/utf8>>,
<<"Memory allocated for this port by the runtime system"/utf8>>,
sort_by_port_memory,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
),
spectator@internal@views@table:heading(
<<"Queue"/utf8>>,
<<"Queue Size"/utf8>>,
sort_by_port_queue_size,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
)]
)]
),
lustre@element@html:tbody(
[],
spectator@internal@views@table:map_rows(
erlang:element(6, Model),
fun(Port) ->
lustre@element@html:tr(
[lustre@attribute:role(<<"button"/utf8>>),
case erlang:element(9, Model) of
{some, Active} when erlang:element(
2,
Active
) =:= erlang:element(2, Port) ->
lustre@attribute:class(
<<"selected"/utf8>>
);
_ ->
lustre@attribute:none()
end,
lustre@event:on_click({port_clicked, Port})],
[lustre@element@html:td([], [render_name(Port)]),
lustre@element@html:td(
[],
[lustre@element@html:text(
erlang:element(
2,
erlang:element(3, Port)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"link-cell"/utf8>>
)],
[spectator@internal@views@display:system_primitive(
erlang:element(
4,
erlang:element(3, Port)
),
erlang:element(3, Model)
)]
),
lustre@element@html:td(
[],
[case erlang:element(
5,
erlang:element(3, Port)
) of
{some, Pid} ->
spectator@internal@views@display:number(
Pid
);
none ->
lustre@element@html:text(
<<"N/A"/utf8>>
)
end]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:storage(
erlang:element(
6,
erlang:element(3, Port)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:storage(
erlang:element(
7,
erlang:element(3, Port)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:storage(
erlang:element(
8,
erlang:element(3, Port)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:number(
erlang:element(
9,
erlang:element(3, Port)
)
)]
)]
)
end
)
),
lustre@element@html:tfoot(
[],
[lustre@element@html:tr(
[],
[lustre@element@html:td(
[lustre@attribute:attribute(
<<"colspan"/utf8>>,
<<"8"/utf8>>
)],
[render_details(
erlang:element(9, Model),
erlang:element(10, Model),
erlang:element(3, Model)
)]
)]
)]
)]
).
-file("src/spectator/internal/components/ports_live.gleam", 18).
?DOC(false).
-spec app() -> lustre:app(list({binary(), binary()}), model(), msg()).
app() ->
lustre:application(fun init/1, fun update/2, fun view/1).