Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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
3 changes: 3 additions & 0 deletions assets/app/styles/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,8 @@
--diff-pulse-text: var(--gray-900);
--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);
--monitored-pid-text: var(--slate-900);
}
}
3 changes: 3 additions & 0 deletions assets/app/styles/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,7 @@
--diff-pulse-text: var(--slate-900);
--diff-negative-bg: var(--red-300);
--diff-positive-bg: var(--swm-green-60);

--monitored-pid-bg: var(--swm-green-40);
--monitored-pid-text: var(--slate-900);
}
2 changes: 2 additions & 0 deletions assets/app/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ 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)',
'monitored-pid-text': 'var(--monitored-pid-text)',
},
screens: { xs: '380px' },
fontFamily: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,28 @@ defmodule LiveDebugger.App.Debugger.CallbackTracing.Web.GlobalTracesLive do
alias LiveDebugger.Bus
alias LiveDebugger.App.Debugger.Events.DeadViewModeEntered

alias LiveDebugger.App.Debugger.Web.Components.NavigationMenu
alias LiveDebugger.App.Debugger.Web.HookComponents, as: DebuggerHookComponents

@live_stream_limit 128
@page_size 25

attr(:socket, Phoenix.LiveView.Socket, required: true)
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, default: false)
attr(:return_link, :string)

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 +66,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 +92,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 +119,90 @@ 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">
<NavigationMenu.sidebar
class="flex w-full border-b"
current_url={@url}
return_link={@return_link}
>
<:inspect_button>
<DebuggerHookComponents.InspectButton.render
inspect_mode?={@inspect_mode?}
lv_process={@lv_process}
/>
</:inspect_button>
</NavigationMenu.sidebar>
<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 +228,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 @@ -73,7 +73,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
96 changes: 62 additions & 34 deletions lib/live_debugger/app/debugger/web/components/navigation_menu.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ defmodule LiveDebugger.App.Debugger.Web.Components.NavigationMenu do

attr(:class, :any, default: nil, doc: "Additional classes to add to the navigation bar.")
attr(:current_url, :any, required: true)
attr(:return_link, :any, required: true, doc: "Link to navigate to.")
slot(:inspect_button)

def sidebar(assigns) do
assigns =
Expand All @@ -21,24 +23,39 @@ defmodule LiveDebugger.App.Debugger.Web.Components.NavigationMenu do

~H"""
<div class={[
"flex flex-col gap-3 bg-sidebar-bg shadow-custom h-full p-2 border-r border-default-border"
"flex flex-row gap-3 bg-sidebar-bg shadow-custom w-full h-max px-2 border-default-border items-center"
| List.wrap(@class)
]}>
<.tooltip id="node-inspector-tooltip" position="right" content="Node Inspector">
<.link patch={RoutesHelper.debugger_node_inspector(@pid)}>
<.nav_icon icon="icon-info" selected?={@current_view == "node_inspector"} />
</.link>
</.tooltip>
<.tooltip id="global-traces-tooltip" position="right" content="Global Callbacks">
<.link patch={RoutesHelper.debugger_global_traces(@pid)}>
<.nav_icon icon="icon-globe" selected?={@current_view == "global_traces"} />
</.link>
</.tooltip>
<.tooltip id="resources-tooltip" position="right" content="Resources">
<.link patch={RoutesHelper.debugger_resources(@pid)}>
<.nav_icon icon="icon-chart-line" selected?={@current_view == "resources"} />
</.link>
</.tooltip>
<%= render_slot(@inspect_button) %>
<div id="visible-items" class="flex flex-row gap-3">
<.sidebar_item
id="node-inspector-sidebar-item"
content="Node Inspector"
patch={RoutesHelper.debugger_node_inspector(@pid)}
icon="icon-info"
selected?={@current_view == "node_inspector"}
/>

<.sidebar_item
id="global-traces-sidebar-item"
content="Global Callbacks"
patch={RoutesHelper.debugger_global_traces(@pid)}
icon="icon-globe"
selected?={@current_view == "global_traces"}
/>
</div>

<.dropdown return_link={@return_link} current_url={@current_url} class="sm:hidden" />

<div id="hidden-items" class="hidden sm:flex flex-row gap-3">
<.sidebar_item
id="resources-sidebar-item"
content="Resources"
patch={RoutesHelper.debugger_resources(@pid)}
icon="icon-chart-line"
selected?={@current_view == "resources"}
/>
</div>
</div>
"""
end
Expand All @@ -55,27 +72,16 @@ defmodule LiveDebugger.App.Debugger.Web.Components.NavigationMenu do
)

~H"""
<.live_component module={LiveDropdown} id="navigation-bar-dropdown" class={@class}>
<.live_component
module={LiveDropdown}
id="navigation-bar-dropdown"
class={@class}
direction={:bottom_left}
>
<:button>
<.nav_icon icon="icon-menu-hamburger" />
<.nav_icon icon="icon-chevrons-right" icon_class="w-5! h-5!" />
</:button>
<div class="min-w-44 flex flex-col p-1">
<.link patch={@return_link}>
<.dropdown_item icon="icon-arrow-left" label="Back to Home" />
</.link>
<span class="w-full border-b border-default-border my-1"></span>
<.dropdown_item
icon="icon-info"
label="Node Inspector"
selected?={@current_view == "node_inspector"}
phx-click={dropdown_item_click(RoutesHelper.debugger_node_inspector(@pid))}
/>
<.dropdown_item
icon="icon-globe"
label="Global Callbacks"
selected?={@current_view == "global_traces"}
phx-click={dropdown_item_click(RoutesHelper.debugger_global_traces(@pid))}
/>
<.dropdown_item
icon="icon-chart-line"
label="Resources"
Expand Down Expand Up @@ -114,6 +120,28 @@ defmodule LiveDebugger.App.Debugger.Web.Components.NavigationMenu do
|> JS.push("close", target: "#navigation-bar-dropdown-live-dropdown-container")
end

attr(:id, :string, required: true)
attr(:patch, :string, required: true)
attr(:icon, :string, required: true)
attr(:selected?, :boolean, default: false)
attr(:content, :string, required: true)

def sidebar_item(assigns) do
~H"""
<div id={@id} class={["w-max pb-0.5 pt-2", @selected? && "border-b-2"]}>
<.link patch={@patch}>
<div class="flex flex-row items-center justify-center w-full mt-1 mb-2">
<.icon name={@icon} class="h-4 w-4" />

<span class="text-xs font-medium text-center pl-1">
{@content}
</span>
</div>
</.link>
</div>
"""
end

defp get_current_view(url) do
URL.take_nth_segment(url, 3) || "node_inspector"
end
Expand Down
Loading