-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathcomponents.ex
More file actions
210 lines (188 loc) · 6.32 KB
/
components.ex
File metadata and controls
210 lines (188 loc) · 6.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
defmodule LiveDebugger.App.Debugger.Streams.Web.Components do
@moduledoc """
UI components used in the Streams.
"""
use LiveDebugger.App.Web, :component
alias LiveDebugger.App.Debugger.Web.Components.ElixirDisplay
alias LiveDebugger.App.Utils.TermParser
alias Phoenix.LiveView.JS
def loading(assigns) do
~H"""
<div class="w-full flex items-center justify-center p-4">
<.spinner size="sm" />
</div>
"""
end
def failed(assigns) do
~H"""
<div class="w-full flex items-center justify-center p-4">
<.alert class="w-full" with_icon heading="Error while fetching stream from render traces">
Check logs for more
</.alert>
</div>
"""
end
attr(:id, :string, required: true)
slot(:display, required: true)
def streams_section(assigns) do
~H"""
<.collapsible_section
id={@id}
class="h-max overflow-y-hidden"
title="Streams"
save_state_in_browser={true}
title_class="flex flex-row justify-between min-w-max gap-2"
>
<:title_sub_panel>
<.section_info_tooltip
id="stream-info"
content="Streams are reconstructed from render traces. If traces are garbage collected, the stream may be incomplete."
/>
</:title_sub_panel>
<%= render_slot(@display) %>
</.collapsible_section>
"""
end
attr(:stream_names, :list, required: true)
attr(:existing_streams, :map, required: true)
def streams_display_container(assigns) do
~H"""
<div id="streams-display-container" class="flex flex-col gap-2 w-full h-max p-4 overflow-y-auto">
<div :for={stream_name <- @stream_names} id={"#{stream_name}-display"}>
<.stream_name_wrapper
id={"#{stream_name}-collapsible"}
stream_name={stream_name}
existing_stream={Map.get(@existing_streams, stream_name, [])}
/>
</div>
</div>
"""
end
attr(:id, :string, required: true)
attr(:stream_name, :atom, required: true)
attr(:existing_stream, Phoenix.LiveView.LiveStream, required: true)
def stream_name_wrapper(assigns) do
~H"""
<.collapsible
id={@id}
icon="icon-chevron-right"
chevron_class="w-5 h-5 text-accent-icon"
class="max-w-full border rounded border-default-border"
label_class="font-semibold bg-surface-1-bg p-2 py-3 rounded"
>
<:label>
<%= @stream_name %>
</:label>
<div class="overflow-x-auto max-w-full max-h-[30vh] overflow-y-auto p-3">
<div id={"#{@stream_name}-stream"} phx-update="stream" class="flex flex-col gap-2">
<%= for {dom_id, stream_element} <-@existing_stream do %>
<.stream_element_wrapper dom_id={dom_id} stream_element={stream_element} />
<% end %>
</div>
</div>
</.collapsible>
"""
end
attr(:stream_element, :any, required: true)
attr(:dom_id, :string, required: true)
def stream_element_wrapper(assigns) do
~H"""
<.collapsible
id={@dom_id}
icon="icon-chevron-right"
chevron_class="w-5 h-5 text-accent-icon"
class="max-w-full border rounded last:mb-1 border-default-border"
label_class="font-semibold bg-surface-1-bg p-1 py-1 rounded"
phx-hook="Highlight"
phx-value-search-attribute="id"
phx-value-search-value={@dom_id}
phx-value-type="StreamItem"
phx-value-id={@dom_id}
>
<:label>
<p class="font-semibold whitespace-nowrap break-keep grow-0 shrink-0">
<%= @dom_id %>
</p>
<div class="grow min-w-0 text-secondary-text font-code font-normal text-3xs truncate pl-2">
<p
id={@dom_id <> "-short-content"}
class="hide-on-open mt-0.5 overflow-hidden whitespace-nowrap"
>
<%= inspect(@stream_element) %>
</p>
</div>
</:label>
<div class="flex flex-col gap-4 w-full overflow-auto p-2">
<.stream_element_body stream_element={@stream_element} dom_id={@dom_id} />
<.stream_element_fullscreen stream_element={@stream_element} dom_id={@dom_id} />
</div>
</.collapsible>
"""
end
@doc """
Displays the fullscreen of the stream element.
"""
attr(:stream_element, :any, required: true)
attr(:dom_id, :string, required: true)
def stream_element_fullscreen(assigns) do
~H"""
<.fullscreen id={@dom_id <> "-fullscreen"} title={@dom_id}>
<:header>
<div class="w-full h-12 py-auto px-3 flex justify-between items-center border-b border-default-border">
<div class="flex justify-between items-center w-full font-semibold text-primary-text text-base">
<%= @dom_id %>
</div>
<div class="flex flex-row gap-2">
<.copy_button
id={"#{@dom_id}-copy-button"}
variant="icon-button"
value={TermParser.term_to_copy_string(@stream_element)}
fullscreen?={true}
/>
<.icon_button
id={"#{@dom_id}-close"}
phx-click={JS.dispatch("close", to: "##{@dom_id}-fullscreen")}
icon="icon-cross"
variant="secondary"
/>
</div>
</div>
</:header>
<div class="p-4 flex flex-col gap-4 items-start justify-center [&_.absolute_>_:last-child]:hidden">
<.stream_element_body stream_element={@stream_element} dom_id={@dom_id} in_fullscreen={true} />
</div>
</.fullscreen>
"""
end
@doc """
Displays the body of the stream element.
"""
attr(:stream_element, :any, required: true)
attr(:dom_id, :string, required: true)
attr(:in_fullscreen, :boolean, default: false)
def stream_element_body(assigns) do
~H"""
<div class="relative w-full group">
<div class="absolute top-0 right-0 z-10 flex gap-2">
<.copy_button
:if={!@in_fullscreen}
id={"#{@dom_id}-copy-button"}
variant="icon-button"
value={TermParser.term_to_copy_string(@stream_element)}
/>
<.fullscreen_button
id={@dom_id <> "-fullscreen-button"}
phx-click="open-stream_element"
phx-value-dom_id={@dom_id}
/>
</div>
<div class="w-full overflow-x-auto pt-1 pr-12">
<ElixirDisplay.term
id={"#{@dom_id}-term"}
node={TermParser.term_to_display_tree(@stream_element)}
/>
</div>
</div>
"""
end
end