Current section
Files
Jump to
Current section
Files
src/spectator@internal@components@processes_live.erl
-module(spectator@internal@components@processes_live).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/spectator/internal/components/processes_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:process_item()),
spectator@internal@api:process_sort_criteria(),
spectator@internal@api:sort_direction(),
gleam@option:option(spectator@internal@api:process_item()),
gleam@option:option(spectator@internal@api:process_details()),
gleam@option:option(spectator@internal@api:process_otp_status()),
gleam@option:option(gleam@dynamic:dynamic_())}.
-opaque msg() :: refresh |
{received_otp_details, spectator@internal@api:otp_details()} |
{created_subject, gleam@erlang@process:subject(msg())} |
{process_clicked, spectator@internal@api:process_item()} |
{heading_clicked, spectator@internal@api:process_sort_criteria()} |
{otp_state_clicked,
spectator@internal@api:process_item(),
spectator@internal@api:sys_state()} |
{pid_clicked, gleam@erlang@process:pid_()} |
{kill_clicked, spectator@internal@api:process_item()}.
-file("src/spectator/internal/components/processes_live.gleam", 42).
?DOC(false).
-spec emit_message(msg()) -> lustre@effect:effect(msg()).
emit_message(Msg) ->
lustre@effect:from(fun(Dispatch) -> Dispatch(Msg) end).
-file("src/spectator/internal/components/processes_live.gleam", 46).
?DOC(false).
-spec request_otp_details(
gleam@option:option(gleam@erlang@atom:atom_()),
gleam@erlang@process:pid_()
) -> lustre@effect:effect(msg()).
request_otp_details(Node, Pid) ->
lustre@effect:from(
fun(Dispatch) ->
spectator@internal@api:request_otp_data(
Node,
Pid,
fun(Details) -> Dispatch({received_otp_details, Details}) end
),
nil
end
).
-file("src/spectator/internal/components/processes_live.gleam", 59).
?DOC(false).
-spec init(list({binary(), binary()})) -> {model(), lustre@effect:effect(msg())}.
init(Params) ->
Node = spectator@internal@api:node_from_params(Params),
Default_sort_criteria = sort_by_reductions,
Default_sort_direction = descending,
Refresh_interval = spectator@internal@common:get_refresh_interval(Params),
{{model,
Node,
spectator@internal@common:sanitize_params(Params),
none,
Refresh_interval,
[],
Default_sort_criteria,
Default_sort_direction,
none,
none,
none,
none},
lustre@effect:batch(
[emit_message(refresh),
case spectator@internal@common:get_param(
Params,
<<"selected"/utf8>>
) of
{error, _} ->
lustre@effect:none();
{ok, Potential_pid} ->
case spectator@internal@api:decode_pid(Potential_pid) of
{ok, Pid} ->
emit_message({pid_clicked, Pid});
{error, _} ->
lustre@effect:none()
end
end]
)}.
-file("src/spectator/internal/components/processes_live.gleam", 110).
?DOC(false).
-spec do_refresh(model()) -> model().
do_refresh(Model) ->
Info = spectator@internal@api:get_process_list(erlang:element(2, Model)),
Sorted = spectator@internal@api:sort_process_list(
Info,
erlang:element(7, Model),
erlang:element(8, Model)
),
Active_process@1 = case erlang:element(9, Model) of
none ->
none;
{some, Active_process} ->
case spectator_ffi:get_process_info(
erlang:element(2, Model),
erlang:element(2, Active_process)
) of
{ok, Info@1} ->
{some,
{process_item,
erlang:element(2, Active_process),
Info@1}};
{error, _} ->
none
end
end,
Details@1 = case Active_process@1 of
none ->
none;
{some, Ap} ->
case spectator_ffi:get_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_process@1,
Details@1,
erlang:element(11, Model),
erlang:element(12, Model)}.
-file("src/spectator/internal/components/processes_live.gleam", 139).
?DOC(false).
-spec update(model(), msg()) -> {model(), lustre@effect:effect(msg())}.
update(Model, Msg) ->
case Msg of
refresh ->
New_model = do_refresh(Model),
case erlang:element(9, New_model) of
{some, P} when erlang:element(6, erlang:element(3, P)) < 10 ->
{New_model,
lustre@effect:batch(
[request_otp_details(
erlang:element(2, Model),
erlang:element(2, P)
),
spectator@internal@common:emit_after(
erlang:element(5, Model),
refresh,
erlang:element(4, Model),
fun(Field@0) -> {created_subject, Field@0} end
)]
)};
_ ->
{New_model,
spectator@internal@common:emit_after(
erlang:element(5, Model),
refresh,
erlang:element(4, Model),
fun(Field@0) -> {created_subject, Field@0} end
)}
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),
erlang:element(11, Model),
erlang:element(12, Model)},
lustre@effect:none()};
{process_clicked, P@1} ->
New_model@1 = 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@1},
erlang:element(10, Model),
none,
none},
do_refresh(_pipe)
end,
{New_model@1,
request_otp_details(
erlang:element(2, Model),
erlang:element(2, P@1)
)};
{heading_clicked, Criteria} ->
case Criteria of
C when C =:= erlang:element(7, Model) ->
New_model@2 = {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),
erlang:element(11, Model),
erlang:element(12, Model)},
{do_refresh(New_model@2), lustre@effect:none()};
C@1 ->
New_model@3 = {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),
erlang:element(11, Model),
erlang:element(12, Model)},
{do_refresh(New_model@3), lustre@effect:none()}
end;
{received_otp_details, Details} ->
case erlang:element(9, Model) of
{some, P@2} when erlang:element(2, P@2) =:= erlang:element(
2,
Details
) ->
{{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),
erlang:element(9, Model),
erlang:element(10, Model),
{some, erlang:element(3, Details)},
{some, erlang:element(4, Details)}},
lustre@effect:none()};
_ ->
{Model, lustre@effect:none()}
end;
{otp_state_clicked, P@3, Target_sys_state} ->
case Target_sys_state of
process_suspended ->
_ = spectator_ffi:sys_resume(
erlang:element(2, Model),
erlang:element(2, P@3)
),
{do_refresh(Model),
request_otp_details(
erlang:element(2, Model),
erlang:element(2, P@3)
)};
process_running ->
_ = spectator_ffi:sys_suspend(
erlang:element(2, Model),
erlang:element(2, P@3)
),
{do_refresh(Model),
request_otp_details(
erlang:element(2, Model),
erlang:element(2, P@3)
)}
end;
{pid_clicked, Pid} ->
case spectator_ffi:get_process_info(erlang:element(2, Model), Pid) of
{ok, Info} ->
P@4 = {process_item, Pid, Info},
New_model@4 = begin
_pipe@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),
erlang:element(8, Model),
{some, P@4},
erlang:element(10, Model),
none,
none},
do_refresh(_pipe@1)
end,
{New_model@4,
request_otp_details(
erlang:element(2, Model),
erlang:element(2, P@4)
)};
{error, _} ->
{Model, lustre@effect:none()}
end;
{kill_clicked, P@5} ->
_ = spectator_ffi:kill_process(
erlang:element(2, Model),
erlang:element(2, P@5)
),
{do_refresh(Model), lustre@effect:none()}
end.
-file("src/spectator/internal/components/processes_live.gleam", 354).
?DOC(false).
-spec render_name(spectator@internal@api:process_item()) -> lustre@vdom@vnode:element(any()).
render_name(Process) ->
case erlang:element(4, erlang:element(3, Process)) of
none ->
spectator@internal@views@display:pid(erlang:element(2, Process));
{some, Name} ->
lustre@element@html:text(erlang:atom_to_binary(Name))
end.
-file("src/spectator/internal/components/processes_live.gleam", 361).
?DOC(false).
-spec render_tag(spectator@internal@api:process_item()) -> lustre@vdom@vnode:element(any()).
render_tag(Process) ->
case erlang:element(8, erlang:element(3, Process)) of
none ->
spectator@internal@views@display:function(
erlang:element(3, erlang:element(3, Process))
);
{some, <<"__spectator_internal "/utf8, Rest/binary>>} ->
lustre@element@html:text(<<"🔍 "/utf8, Rest/binary>>);
{some, Tag} ->
lustre@element@html:text(<<"🔖 "/utf8, Tag/binary>>)
end.
-file("src/spectator/internal/components/processes_live.gleam", 369).
?DOC(false).
-spec render_primitive_list(
list(spectator@internal@api:system_primitive()),
fun((gleam@erlang@process:pid_()) -> msg()),
list({binary(), binary()})
) -> list(lustre@vdom@vnode:element(msg())).
render_primitive_list(Primitives, On_primitive_click, Params) ->
_pipe = gleam@list:map(
Primitives,
fun(_capture) ->
spectator@internal@views@display:system_primitive_interactive(
_capture,
On_primitive_click,
Params
)
end
),
gleam@list:intersperse(_pipe, lustre@element@html:text(<<", "/utf8>>)).
-file("src/spectator/internal/components/processes_live.gleam", 382).
?DOC(false).
-spec render_details(
gleam@option:option(spectator@internal@api:process_item()),
gleam@option:option(spectator@internal@api:process_details()),
gleam@option:option(spectator@internal@api:process_otp_status()),
gleam@option:option(gleam@dynamic:dynamic_()),
fun((spectator@internal@api:process_item(), spectator@internal@api:sys_state()) -> msg()),
list({binary(), binary()})
) -> lustre@vdom@vnode:element(msg()).
render_details(P, D, Status, State, Handle_otp_state_click, Params) ->
case {P, D} of
{{some, Proc}, {some, Details}} ->
lustre@element@html:'div'(
[lustre@attribute:class(<<"details"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(<<"general"/utf8>>)],
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-heading"/utf8>>
)],
[case {erlang:element(
8,
erlang:element(3, Proc)
),
erlang:element(
4,
erlang:element(3, Proc)
)} of
{{some,
<<"__spectator_internal "/utf8, Rest/binary>>},
_} ->
lustre@element@html:text(
<<"🔍 Spectator "/utf8,
Rest/binary>>
);
{{some, Tag}, none} ->
lustre@element@html:text(
<<<<<<"🔖 "/utf8,
(spectator_ffi:format_pid(
erlang:element(
2,
Proc
)
))/binary>>/binary,
" "/utf8>>/binary,
Tag/binary>>
);
{{some, Tag@1}, {some, Name}} ->
lustre@element@html:text(
<<<<<<<<<<"🔖 "/utf8,
(spectator_ffi:format_pid(
erlang:element(
2,
Proc
)
))/binary>>/binary,
" "/utf8>>/binary,
Tag@1/binary>>/binary,
" registered as "/utf8>>/binary,
(erlang:atom_to_binary(Name))/binary>>
);
{none, none} ->
lustre@element@html:text(
<<<<"🎛️ "/utf8,
(spectator_ffi:format_pid(
erlang:element(
2,
Proc
)
))/binary>>/binary,
" Process"/utf8>>
);
{none, {some, Name@1}} ->
lustre@element@html:text(
<<<<<<"📠 "/utf8,
(spectator_ffi:format_pid(
erlang:element(
2,
Proc
)
))/binary>>/binary,
" "/utf8>>/binary,
(erlang:atom_to_binary(
Name@1
))/binary>>
)
end,
lustre@element@html:button(
[lustre@attribute:class(
<<"panel-action suspend"/utf8>>
),
lustre@event:on_click(
{kill_clicked, Proc}
)],
[lustre@element@html:text(
<<"🗡️ Kill"/utf8>>
)]
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-content"/utf8>>
)],
[lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Links"/utf8>>
)]
),
lustre@element@html:dd(
[],
render_primitive_list(
erlang:element(3, Details),
fun(Field@0) -> {pid_clicked, Field@0} end,
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(4, Details),
fun(Field@0) -> {pid_clicked, Field@0} end,
Params
)
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Monitors"/utf8>>
)]
),
lustre@element@html:dd(
[],
render_primitive_list(
erlang:element(5, Details),
fun(Field@0) -> {pid_clicked, Field@0} end,
Params
)
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Parent"/utf8>>
)]
),
lustre@element@html:dd(
[],
[case erlang:element(7, Details) of
none ->
lustre@element@html:text(
<<"None"/utf8>>
);
{some, Parent} ->
spectator@internal@views@display:system_primitive_interactive(
Parent,
fun(Field@0) -> {pid_clicked, Field@0} end,
Params
)
end]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Status"/utf8>>
)]
),
lustre@element@html:dd(
[],
[lustre@element@html:text(
erlang:atom_to_binary(
erlang:element(
9,
erlang:element(
3,
Proc
)
)
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Trap Exit"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:bool(
erlang:element(
6,
Details
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Initial Call"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:function(
erlang:element(
3,
erlang:element(
3,
Proc
)
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Current Function"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:function(
erlang:element(
2,
erlang:element(
3,
Proc
)
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Reductions"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:number(
erlang:element(
7,
erlang:element(
3,
Proc
)
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Memory"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:storage_detailed(
erlang:element(
5,
erlang:element(
3,
Proc
)
)
)]
)]
),
lustre@element@html:dl(
[],
[lustre@element@html:dt(
[],
[lustre@element@html:text(
<<"Message Queue Length"/utf8>>
)]
),
lustre@element@html:dd(
[],
[spectator@internal@views@display:number(
erlang:element(
6,
erlang:element(
3,
Proc
)
)
)]
)]
)]
)]
),
lustre@element@html:'div'(
[lustre@attribute:class(<<"otp"/utf8>>)],
case {Status, State} of
{{some, Status@1}, {some, State@1}} ->
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-heading"/utf8>>
)],
[lustre@element@html:strong(
[],
[lustre@element@html:text(
<<"☎️ OTP Process: "/utf8>>
)]
),
spectator@internal@views@display:atom(
erlang:element(3, Status@1)
),
case erlang:element(5, Status@1) of
process_suspended ->
lustre@element@html:button(
[lustre@event:on_click(
Handle_otp_state_click(
Proc,
erlang:element(
5,
Status@1
)
)
),
lustre@attribute:class(
<<"panel-action resume"/utf8>>
)],
[lustre@element@html:text(
<<"🏃♀️➡️ Resume"/utf8>>
)]
);
process_running ->
lustre@element@html:button(
[lustre@event:on_click(
Handle_otp_state_click(
Proc,
erlang:element(
5,
Status@1
)
)
),
lustre@attribute:class(
<<"panel-action suspend"/utf8>>
)],
[lustre@element@html:text(
<<"✋ Suspend"/utf8>>
)]
)
end]
),
lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-content"/utf8>>
)],
[lustre@element@html:pre(
[],
[lustre@element@html:text(
pprint:format(State@1)
)]
)]
)];
{_, _} when erlang:element(
6,
erlang:element(3, Proc)
) >= 10 ->
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-content"/utf8>>
)],
[lustre@element@html:strong(
[],
[lustre@element@html:text(
<<"⚠️ Spectator has stopped trying to inspect the OTP state of this process"/utf8>>
)]
),
lustre@element@html:p(
[],
[lustre@element@html:text(
<<"The message queue length is above the threshold of "/utf8>>
),
spectator@internal@views@display:number(
10
),
lustre@element@html:text(
<<"."/utf8>>
),
lustre@element@html:br([]),
lustre@element@html:text(
<<"Spectator will not send it any more system messages to avoid filling the message queue."/utf8>>
)]
)]
)];
{_, _} ->
[lustre@element@html:'div'(
[lustre@attribute:class(
<<"panel-content"/utf8>>
)],
[lustre@element@html:text(
<<"This process does not appear to be OTP-compliant"/utf8>>
)]
)]
end
)]
);
{_, _} ->
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/processes_live.gleam", 563).
?DOC(false).
-spec classify_selected(
spectator@internal@api:process_item(),
gleam@option:option(spectator@internal@api:process_item())
) -> lustre@vdom@vattr:attribute(any()).
classify_selected(Process, Active) ->
Selection_status = case Active of
{some, Active@1} when erlang:element(2, Active@1) =:= erlang:element(
2,
Process
) ->
<<"selected"/utf8>>;
_ ->
<<""/utf8>>
end,
case erlang:element(8, erlang:element(3, Process)) of
none ->
lustre@attribute:class(Selection_status);
{some, <<"__spectator_internal "/utf8, _/binary>>} ->
lustre@attribute:class(
<<Selection_status/binary, " spectator-tagged"/utf8>>
);
{some, _} ->
lustre@attribute:class(<<Selection_status/binary, " tagged"/utf8>>)
end.
-file("src/spectator/internal/components/processes_live.gleam", 241).
?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>>,
<<"Process PID or registered name"/utf8>>,
sort_by_process_name,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Tag"/utf8>>,
<<"Spectator tag or initial call"/utf8>>,
sort_by_tag,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Current"/utf8>>,
<<"Current function"/utf8>>,
sort_by_current_function,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Reductions"/utf8>>,
<<"Number of reductions"/utf8>>,
sort_by_reductions,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
false
),
spectator@internal@views@table:heading(
<<"Memory"/utf8>>,
<<"Memory usage"/utf8>>,
sort_by_process_memory,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
),
spectator@internal@views@table:heading(
<<"Msgs"/utf8>>,
<<"Message queue size"/utf8>>,
sort_by_message_queue,
erlang:element(7, Model),
erlang:element(8, Model),
fun(Field@0) -> {heading_clicked, Field@0} end,
true
),
spectator@internal@views@table:heading(
<<"Status"/utf8>>,
<<"Process Status"/utf8>>,
sort_by_process_status,
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(Process) ->
lustre@element@html:tr(
[lustre@attribute:role(<<"button"/utf8>>),
classify_selected(
Process,
erlang:element(9, Model)
),
lustre@event:on_click(
{process_clicked, Process}
)],
[lustre@element@html:td([], [render_name(Process)]),
lustre@element@html:td(
[],
[render_tag(Process)]
),
lustre@element@html:td(
[],
[spectator@internal@views@display:function(
erlang:element(
2,
erlang:element(3, Process)
)
)]
),
lustre@element@html:td(
[],
[spectator@internal@views@display:number(
erlang:element(
7,
erlang:element(3, Process)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:storage(
erlang:element(
5,
erlang:element(3, Process)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:number(
erlang:element(
6,
erlang:element(3, Process)
)
)]
),
lustre@element@html:td(
[lustre@attribute:class(
<<"cell-right"/utf8>>
)],
[spectator@internal@views@display:atom(
erlang:element(
9,
erlang:element(3, Process)
)
)]
)]
)
end
)
),
lustre@element@html:tfoot(
[],
[lustre@element@html:tr(
[],
[lustre@element@html:td(
[lustre@attribute:attribute(
<<"colspan"/utf8>>,
<<"7"/utf8>>
)],
[render_details(
erlang:element(9, Model),
erlang:element(10, Model),
erlang:element(11, Model),
erlang:element(12, Model),
fun(Field@0, Field@1) -> {otp_state_clicked, Field@0, Field@1} end,
erlang:element(3, Model)
)]
)]
)]
)]
).
-file("src/spectator/internal/components/processes_live.gleam", 20).
?DOC(false).
-spec app() -> lustre@runtime@app:app(list({binary(), binary()}), model(), msg()).
app() ->
lustre:application(fun init/1, fun update/2, fun view/1).