Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6e8fac9
change monitored pid style
srzeszut Nov 20, 2025
18a0052
Update dead_view_mode.ex
srzeszut Nov 20, 2025
4e8c335
Update dead_view_mode.ex
srzeszut Nov 20, 2025
e0a4335
layout updates
srzeszut Nov 24, 2025
b527c71
change sidebar orientation
srzeszut Nov 24, 2025
6e9bd4f
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Nov 24, 2025
cf9c945
fix
srzeszut Nov 24, 2025
fc298e8
fix sidebar margin
srzeszut Nov 24, 2025
a6150b8
update sidebar menu
srzeszut Nov 24, 2025
ec2669a
move node basic info
srzeszut Nov 24, 2025
c0a1259
move dropdown to new sidebar
srzeszut Nov 25, 2025
29d0e72
fix e2e tests
srzeszut Nov 25, 2025
b37033b
small ui changes
srzeszut Nov 27, 2025
c4974ce
change disconnected state indicator
srzeszut Nov 27, 2025
953eb8b
fix basic info ui
srzeszut Nov 27, 2025
a576be6
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Nov 27, 2025
36556e5
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Nov 27, 2025
ab9ecf9
update layout
srzeszut Nov 28, 2025
3628b4c
update app.css
srzeszut Nov 28, 2025
c707501
ui changes
srzeszut Nov 28, 2025
6458231
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Nov 28, 2025
9671570
move parent pid section
srzeszut Nov 28, 2025
498168e
update parent live view link and fix e2e tests
srzeszut Dec 1, 2025
0d20e79
remove unused alias
srzeszut Dec 1, 2025
d4fa4f7
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Dec 1, 2025
bc71369
remove no parent liveview from basic info
srzeszut Dec 1, 2025
a89a544
fix ui
srzeszut Dec 1, 2025
27fca8a
Merge remote-tracking branch 'origin/main' into 827-update-layout-of-…
srzeszut Dec 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions assets/app/styles/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,14 @@
--diff-negative-bg: var(--red-900);
--diff-positive-bg: rgb(from var(--swm-green-100) r g b / 0.3);

--monitored-pid-bg: var(--swm-green-60);
--disconnected-bg: var(--swm-pink-60);
--disconnected-text: var(--slate-900);

--status-dot-success-bg: var(--swm-green-100);
--status-dot-warning-bg: var(--swm-yellow-100);
--status-dot-error-bg: var(--swm-pink-100);

--navbar-selected-bg: var(--swm-sea-blue-60);
}
}
6 changes: 6 additions & 0 deletions assets/app/styles/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,13 @@
--diff-negative-bg: var(--red-300);
--diff-positive-bg: var(--swm-green-60);

--monitored-pid-bg: var(--swm-green-40);
--disconnected-bg: var(--swm-pink-40);
--disconnected-text: var(--slate-900);

--status-dot-success-bg: var(--swm-green-100);
--status-dot-warning-bg: var(--swm-yellow-100);
--status-dot-error-bg: var(--swm-pink-100);

--navbar-selected-bg: var(--swm-brand);
}
4 changes: 4 additions & 0 deletions assets/app/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ module.exports = {
'diff-border': 'var(--diff-border)',
'diff-negative-bg': 'var(--diff-negative-bg)',
'diff-positive-bg': 'var(--diff-positive-bg)',
'monitored-pid-bg': 'var(--monitored-pid-bg)',
'disconnected-bg': 'var(--disconnected-bg)',
'disconnected-text': 'var(--disconnected-text)',
'status-dot-success-bg': 'var(--status-dot-success-bg)',
'status-dot-warning-bg': 'var(--status-dot-warning-bg)',
'status-dot-error-bg': 'var(--status-dot-error-bg)',
'navbar-selected-bg': 'var(--navbar-selected-bg)',
},
screens: { xs: '380px' },
fontFamily: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
alias LiveDebugger.Structs.LvProcess
alias LiveDebugger.Bus
alias LiveDebugger.App.Debugger.Events.DeadViewModeEntered
alias LiveDebugger.App.Debugger.Web.Components.Pages

@live_stream_limit 128
@page_size 25
Expand All @@ -35,12 +36,18 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
attr(:id, :string, required: true)
attr(:lv_process, LvProcess, required: true)
attr(:class, :string, default: "", doc: "CSS class for the container")
attr(:url, :string, required: true)
attr(:inspect_mode?, :boolean, required: true)
attr(:return_link, :string, required: true)

def live_render(assigns) do
session = %{
"id" => assigns.id,
"lv_process" => assigns.lv_process,
"parent_pid" => self()
"url" => assigns.url,
"parent_pid" => self(),
"inspect_mode?" => assigns.inspect_mode?,
"return_link" => assigns.return_link
}

assigns = assign(assigns, session: session)
Expand All @@ -57,7 +64,14 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
@impl true
def mount(
_params,
%{"parent_pid" => parent_pid, "lv_process" => lv_process, "id" => id},
%{
"parent_pid" => parent_pid,
"lv_process" => lv_process,
"id" => id,
"url" => url,
"inspect_mode?" => inspect_mode?,
"return_link" => return_link
},
socket
) do
if connected?(socket) do
Expand All @@ -76,7 +90,10 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
traces_continuation: nil,
sidebar_hidden?: true,
trace_search_phrase: "",
node_id: nil
node_id: nil,
url: url,
inspect_mode?: inspect_mode?,
return_link: return_link
)
|> stream(:existing_traces, [], reset: true)
|> put_private(:page_size, @page_size)
Expand All @@ -100,76 +117,84 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
@impl true
def render(assigns) do
~H"""
<div class="grow p-8 overflow-y-auto scrollbar-main">
<div class="w-full min-w-[25rem] max-w-screen-2xl mx-auto">
<div class="flex flex-col gap-1.5 pb-6 px-0.5">
<.h1>Global Callback Traces</.h1>
<span class="text-secondary-text">
This view lists all callbacks inside debugged LiveView and its LiveComponents
</span>
</div>
<div class="@container/traces w-full min-w-[20rem] flex flex-col pt-2 shadow-custom rounded-sm bg-surface-0-bg border border-default-border">
<div class="w-full flex justify-between items-center border-b border-default-border pb-2">
<div class="ml-2">
<HookComponents.SearchInput.render
disabled?={@tracing_started?}
trace_search_phrase={@trace_search_phrase}
/>
</div>
<div class="flex gap-2 items-center h-8 px-2">
<HookComponents.ToggleTracingButton.render
tracing_started?={@tracing_started?}
lv_process_alive?={@lv_process.alive?}
/>
<%= if not @tracing_started? do %>
<.global_traces_dropdown_menu class="@[30rem]/traces:hidden" />

<div class="hidden @[30rem]/traces:flex gap-2">
<HookComponents.RefreshButton.render display_mode={:normal} />
<HookComponents.ClearButton.render display_mode={:normal} />
</div>
<% end %>
</div>
<div class="flex flex-col h-full overflow-x-auto w-full">
<Pages.navbar_menu
url={@url}
return_link={@return_link}
inspect_mode?={@inspect_mode?}
lv_process={@lv_process}
/>
<div class="grow p-8 overflow-y-auto scrollbar-main">
<div class="w-full min-w-[25rem] max-w-screen-2xl mx-auto">
<div class="flex flex-col gap-1.5 pb-6 px-0.5">
<.h1>Global Callback Traces</.h1>
<span class="text-secondary-text">
This view lists all callbacks inside debugged LiveView and its LiveComponents
</span>
</div>
<div class="flex flex-1 overflow-auto rounded-sm bg-surface-0-bg p-4">
<div class="w-full h-full flex flex-col gap-4">
<HookComponents.Stream.render
id={@id}
existing_traces_status={@existing_traces_status}
existing_traces={@streams.existing_traces}
>
<:trace :let={{id, trace_display}}>
<HookComponents.TraceWrapper.render id={id} trace_display={trace_display}>
<:label>
<.trace_label
id={id <> "-label"}
trace_display={trace_display}
search_phrase={@trace_search_phrase}
short_content_full?={true}
show_subtitle?={true}
/>
</:label>

<:body>
<.trace_body
id={id <> "-body"}
trace_display={trace_display}
search_phrase={@trace_search_phrase}
/>
</:body>
</HookComponents.TraceWrapper.render>
</:trace>
</HookComponents.Stream.render>
<HookComponents.LoadMoreButton.render
:if={not @tracing_started? and not @traces_empty?}
traces_continuation={@traces_continuation}
/>
<.trace_fullscreen
:if={@displayed_trace}
id="trace-fullscreen"
displayed_trace={@displayed_trace}
search_phrase={@trace_search_phrase}
/>
<div class="@container/traces w-full min-w-[20rem] flex flex-col pt-2 shadow-custom rounded-sm bg-surface-0-bg border border-default-border">
<div class="w-full flex justify-between items-center border-b border-default-border pb-2">
<div class="ml-2">
<HookComponents.SearchInput.render
disabled?={@tracing_started?}
trace_search_phrase={@trace_search_phrase}
/>
</div>
<div class="flex gap-2 items-center h-8 px-2">
<HookComponents.ToggleTracingButton.render
tracing_started?={@tracing_started?}
lv_process_alive?={@lv_process.alive?}
/>
<%= if not @tracing_started? do %>
<.global_traces_dropdown_menu class="@[30rem]/traces:hidden" />

<div class="hidden @[30rem]/traces:flex gap-2">
<HookComponents.RefreshButton.render display_mode={:normal} />
<HookComponents.ClearButton.render display_mode={:normal} />
</div>
<% end %>
</div>
</div>
<div class="flex flex-1 overflow-auto rounded-sm bg-surface-0-bg p-4">
<div class="w-full h-full flex flex-col gap-4">
<HookComponents.Stream.render
id={@id}
existing_traces_status={@existing_traces_status}
existing_traces={@streams.existing_traces}
>
<:trace :let={{id, trace_display}}>
<HookComponents.TraceWrapper.render id={id} trace_display={trace_display}>
<:label>
<.trace_label
id={id <> "-label"}
trace_display={trace_display}
search_phrase={@trace_search_phrase}
short_content_full?={true}
show_subtitle?={true}
/>
</:label>

<:body>
<.trace_body
id={id <> "-body"}
trace_display={trace_display}
search_phrase={@trace_search_phrase}
/>
</:body>
</HookComponents.TraceWrapper.render>
</:trace>
</HookComponents.Stream.render>
<HookComponents.LoadMoreButton.render
:if={not @tracing_started? and not @traces_empty?}
traces_continuation={@traces_continuation}
/>
<.trace_fullscreen
:if={@displayed_trace}
id="trace-fullscreen"
displayed_trace={@displayed_trace}
search_phrase={@trace_search_phrase}
/>
</div>
</div>
</div>
</div>
Expand All @@ -195,4 +220,13 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
end

def handle_info(_, socket), do: {:noreply, socket}

@impl true
def handle_event("switch-inspect-mode", _, socket) do
send(socket.assigns.parent_pid, :switch_inspect_mode)

socket
|> assign(:inspect_mode?, !socket.assigns.inspect_mode?)
|> noreply()
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ defmodule LiveDebugger.App.Debugger.NestedLiveViewLinks.Web.NestedLiveViewLinksL

use LiveDebugger.App.Web, :live_view

alias Phoenix.LiveView.AsyncResult

alias LiveDebugger.Structs.LvProcess
alias LiveDebugger.API.LiveViewDiscovery
alias LiveDebugger.App.Debugger.Web.Components, as: DebuggerComponents

alias LiveDebugger.App.Debugger.NestedLiveViewLinks.Queries,
as: NestedLiveViewLinksQueries

alias LiveDebugger.App.Debugger.Queries.LvProcess, as: LvProcessQueries

alias LiveDebugger.Bus
alias LiveDebugger.Services.ProcessMonitor.Events.LiveViewDied
alias LiveDebugger.Services.ProcessMonitor.Events.LiveViewBorn
Expand Down Expand Up @@ -56,18 +60,30 @@ defmodule LiveDebugger.App.Debugger.NestedLiveViewLinks.Web.NestedLiveViewLinksL
socket
|> assign(lv_process: lv_process)
|> assign_async_nested_lv_processes()
|> assign_async_parent_lv_process()
|> ok()
end

@impl true
def render(assigns) do
~H"""
<div class="w-full px-4 py-3 gap-3 flex flex-col border-b border-default-border">
<div class="w-full px-4 pt-4 pb-5 gap-3 flex flex-col border-b border-default-border mt-1 z">
<.async_result :let={parent_lv_process} assign={@parent_lv_process}>
<p :if={parent_lv_process} class="pl-2 shrink-0 font-medium text-secondary-text pb-1 pt-1">
Parent LiveView
</p>
<div :if={parent_lv_process} class="pl-2 flex flex-col gap-1">
<DebuggerComponents.live_view_link
lv_process={parent_lv_process}
id="parent-live-view-link"
/>
</div>
</.async_result>
<.async_result :let={nested_lv_processes} assign={@nested_lv_processes}>
<:loading>
<.spinner size="sm" class="m-auto" />
</:loading>
<p class="pl-2 shrink-0 font-medium text-secondary-text">
<p class="pl-2 shrink-0 font-medium text-secondary-text pb-1 pt-1">
<%= if Enum.empty?(nested_lv_processes), do: "No nested LiveViews", else: "Nested LiveViews" %>
</p>
<%= if not Enum.empty?(nested_lv_processes) do %>
Expand Down Expand Up @@ -114,6 +130,20 @@ defmodule LiveDebugger.App.Debugger.NestedLiveViewLinks.Web.NestedLiveViewLinksL
)
end

defp assign_async_parent_lv_process(socket) do
parent_pid = socket.assigns.lv_process.parent_pid

case parent_pid do
nil ->
assign(socket, :parent_lv_process, AsyncResult.ok(nil))

pid ->
assign_async(socket, :parent_lv_process, fn ->
{:ok, %{parent_lv_process: LvProcessQueries.get_lv_process_with_retries(pid)}}
end)
end
end

defp known_child_lv_process?(socket, pid) do
case socket.assigns.nested_lv_processes.result do
nil -> false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ defmodule LiveDebugger.App.Debugger.NodeState.Web.NodeStateLive do
@impl true
def render(assigns) do
~H"""
<div class="flex-1 max-w-full flex flex-col gap-4">
<div class="flex-1 w-full flex flex-col gap-4">
<.async_result :let={{_node_assigns, term_node, copy_string}} assign={@node_assigns_info}>
<:loading>
<NodeStateComponents.loading />
Expand Down
Loading
Loading