Current section
Files
Jump to
Current section
Files
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]).
-export([app/0]).
-export_type([model/0, msg/0]).
-type model() :: {model,
gleam@option:option(gleam@erlang@process:subject(msg())),
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("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 36).
-spec emit_after(
integer(),
msg(),
gleam@option:option(gleam@erlang@process:subject(msg()))
) -> lustre@effect:effect(msg()).
emit_after(Delay, Msg, Subject) ->
case Subject of
{some, Self} ->
lustre@effect:from(
fun(_) ->
_ = gleam@erlang@process:send_after(Self, Delay, Msg),
nil
end
);
none ->
lustre@server_component:select(
fun(Dispatch, Subject@1) ->
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:selecting(
_pipe,
Subject@1,
fun(Msg@1) -> Msg@1 end
)
end,
_ = gleam@erlang@process:send_after(Subject@1, Delay, Msg),
Dispatch({created_subject, Subject@1}),
Selector
end
)
end.
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 58).
-spec init(gleam@option:option(binary())) -> {model(),
lustre@effect:effect(msg())}.
init(Initial_selection) ->
Info = spectator@internal@api:get_port_list(),
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 Initial_selection of
none ->
none;
{some, 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(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(erlang:element(2, Ap)) of
{ok, Details} ->
{some, Details};
{error, _} ->
none
end
end,
{{model,
none,
Sorted,
Default_sort_criteria,
Default_sort_direction,
Active_port,
Details@1},
emit_after(500, refresh, none)}.
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 104).
-spec do_refresh(model()) -> model().
do_refresh(Model) ->
Info = spectator@internal@api:get_port_list(),
Sorted = spectator@internal@api:sort_port_list(
Info,
erlang:element(4, Model),
erlang:element(5, Model)
),
Active_port@1 = case erlang:element(6, Model) of
none ->
none;
{some, Active_port} ->
case spectator_ffi:get_port_info(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, Ap)) of
{ok, Details} ->
{some, Details};
{error, _} ->
none
end
end,
erlang:setelement(
7,
erlang:setelement(3, erlang:setelement(6, Model, Active_port@1), Sorted),
Details@1
).
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 133).
-spec update(model(), msg()) -> {model(), lustre@effect:effect(msg())}.
update(Model, Msg) ->
case Msg of
refresh ->
{do_refresh(Model),
emit_after(500, refresh, erlang:element(2, Model))};
{created_subject, Subject} ->
{erlang:setelement(2, Model, {some, Subject}), lustre@effect:none()};
{port_clicked, P} ->
New_model = begin
_pipe = erlang:setelement(6, Model, {some, P}),
do_refresh(_pipe)
end,
{New_model, lustre@effect:none()};
{heading_clicked, Criteria} ->
case Criteria of
C when C =:= erlang:element(4, Model) ->
New_model@1 = erlang:setelement(
5,
Model,
spectator@internal@api:invert_sort_direction(
erlang:element(5, Model)
)
),
{do_refresh(New_model@1), lustre@effect:none()};
C@1 ->
New_model@2 = erlang:setelement(4, Model, C@1),
{do_refresh(New_model@2), lustre@effect:none()}
end
end.
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 299).
-spec render_name(spectator@internal@api:port_item()) -> lustre@internals@vdom: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("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 306).
-spec render_primitive_list(list(spectator@internal@api:system_primitive())) -> list(lustre@internals@vdom:element(any())).
render_primitive_list(Primitives) ->
_pipe = gleam@list:map(
Primitives,
fun spectator@internal@views@display:system_primitive/1
),
gleam@list:intersperse(_pipe, lustre@element@html:text(<<", "/utf8>>)).
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 311).
-spec render_details(
gleam@option:option(spectator@internal@api:port_item()),
gleam@option:option(spectator@internal@api:port_details())
) -> lustre@internals@vdom:element(any()).
render_details(P, D) ->
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)
)
)]
)]
),
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)
)
)]
),
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)
)
)]
),
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)
)
)]
)]
);
{_, _} ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"footer-placeholder"/utf8>>)],
[lustre@element@html:text(
<<"Click a process to see details"/utf8>>
)]
)
end.
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 172).
-spec view(model()) -> lustre@internals@vdom: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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, 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(4, Model),
erlang:element(5, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
)]
)]
),
lustre@element@html:tbody(
[],
spectator@internal@views@table:map_rows(
erlang:element(3, Model),
fun(Port) ->
lustre@element@html:tr(
[lustre@attribute:role(<<"button"/utf8>>),
case erlang:element(6, 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(
[],
[spectator@internal@views@display:system_primitive(
erlang:element(
4,
erlang:element(3, Port)
)
)]
),
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(6, Model),
erlang:element(7, Model)
)]
)]
)]
)]
).
-file("/Users/jonas/Projects/spectator/src/spectator/internal/components/ports_live.gleam", 19).
-spec app() -> lustre:app(gleam@option:option(binary()), model(), msg()).
app() ->
lustre:application(fun init/1, fun update/2, fun view/1).