roda-debug_bar 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/roda/debug_bar/current.rb +110 -0
- data/lib/roda/debug_bar/instance.rb +186 -0
- data/lib/roda/debug_bar/views/debug_bar/models.erb +37 -0
- data/lib/roda/debug_bar/views/debug_bar/queries.erb +30 -0
- data/lib/roda/debug_bar/views/debug_bar/request.erb +39 -0
- data/lib/roda/debug_bar/views/debug_bar/right_bar.erb +4 -0
- data/lib/roda/debug_bar/views/debug_bar/route.erb +17 -0
- data/lib/roda/debug_bar/views/debug_bar/views.erb +19 -0
- data/lib/roda/debug_bar/views/debug_bar.erb +196 -0
- data/lib/roda/plugins/debug_bar.rb +299 -0
- data/lib/sequel/extensions/debug_bar.rb +39 -0
- data/lib/sequel/main.rb +36 -0
- data/lib/sequel/plugins/debug_bar.rb +50 -0
- data/lib/version.rb +3 -0
- data/public/out.css +1000 -0
- data/public/ruby.png +0 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 579c3658131b0cbcf37b4eb150bac95328b6fd03f6fcce27a2470dbb8549f232
|
4
|
+
data.tar.gz: ef1819c9640e2df2575bb1f5c11a5dc934e951ea57adc03a24c6bedbab7ca27a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 839359c83b959a366d8eaf8d6b181ec30288b9ee6c13c8020e34287be24cf9b8d3074d7296e343e4e2eea3119de43359b27f3db09d57b30f9902e2db70ca9698
|
7
|
+
data.tar.gz: 8707fa854cf92383fa8e76adf3045212be52807496e0b749776c777ad29d3c3c4003d6084dca2120a4e2c5f57a594bfcb0e6e3462721e5077cc08e8c1c80af76
|
@@ -0,0 +1,110 @@
|
|
1
|
+
class Roda
|
2
|
+
module DebugBar
|
3
|
+
module Current
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Increment the accrued database time
|
7
|
+
# @param value [Numeric]
|
8
|
+
# the value to increment
|
9
|
+
# @return [Numeric]
|
10
|
+
# the updated value
|
11
|
+
def increment_accrued_database_time(value)
|
12
|
+
Thread.current[:accrued_database_time] ||= 0
|
13
|
+
Thread.current[:accrued_database_time] += value
|
14
|
+
end
|
15
|
+
|
16
|
+
# The accrued database time
|
17
|
+
# @return [Numeric]
|
18
|
+
def accrued_database_time
|
19
|
+
Thread.current[:accrued_database_time]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Set accrued database time
|
23
|
+
# @param value [Numeric]
|
24
|
+
# the value to set
|
25
|
+
# @return [Numeric]
|
26
|
+
# the new value
|
27
|
+
def accrued_database_time=(value)
|
28
|
+
Thread.current[:accrued_database_time] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
def increment_database_query_count(value = 1)
|
32
|
+
Thread.current[:database_query_count] ||= 0
|
33
|
+
Thread.current[:database_query_count] += value
|
34
|
+
end
|
35
|
+
|
36
|
+
def database_query_count
|
37
|
+
Thread.current[:database_query_count]
|
38
|
+
end
|
39
|
+
|
40
|
+
def database_query_count=(value)
|
41
|
+
Thread.current[:database_query_count] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_database_query(message, duration)
|
45
|
+
Thread.current[:database_queries] ||= []
|
46
|
+
Thread.current[:database_queries] << {query: message, duration: duration}
|
47
|
+
end
|
48
|
+
|
49
|
+
def database_queries
|
50
|
+
Thread.current[:database_queries]
|
51
|
+
end
|
52
|
+
|
53
|
+
def database_queries=(value)
|
54
|
+
Thread.current[:database_queries] = value
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_model(model, values)
|
58
|
+
Thread.current[:models] ||= {}
|
59
|
+
Thread.current[:models][model.to_s] ||= []
|
60
|
+
Thread.current[:models][model.to_s] << values
|
61
|
+
# Thread.current[:models] << {name: model, values: values}
|
62
|
+
end
|
63
|
+
|
64
|
+
def models
|
65
|
+
Thread.current[:models]
|
66
|
+
end
|
67
|
+
|
68
|
+
def models=(value)
|
69
|
+
Thread.current[:models] = value
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_view(view)
|
73
|
+
Thread.current[:view] ||= []
|
74
|
+
Thread.current[:view] << view
|
75
|
+
end
|
76
|
+
|
77
|
+
def views
|
78
|
+
Thread.current[:view]
|
79
|
+
end
|
80
|
+
|
81
|
+
def views=(value)
|
82
|
+
Thread.current[:view] = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_route(handler, path)
|
86
|
+
Thread.current[:routes] ||= []
|
87
|
+
Thread.current[:routes] << {handler: handler, path: path}
|
88
|
+
end
|
89
|
+
|
90
|
+
def routes
|
91
|
+
Thread.current[:routes]
|
92
|
+
end
|
93
|
+
|
94
|
+
def routes=(value)
|
95
|
+
Thread.current[:routes] = value
|
96
|
+
end
|
97
|
+
|
98
|
+
# Reset the counters
|
99
|
+
def reset
|
100
|
+
self.accrued_database_time = nil
|
101
|
+
self.database_query_count = nil
|
102
|
+
self.database_queries = nil
|
103
|
+
self.models = nil
|
104
|
+
self.views = nil
|
105
|
+
self.routes = nil
|
106
|
+
true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
require "roda"
|
3
|
+
|
4
|
+
class Roda
|
5
|
+
module DebugBar
|
6
|
+
##
|
7
|
+
# Logger instance for this application
|
8
|
+
class Instance
|
9
|
+
|
10
|
+
# Application root
|
11
|
+
attr_reader :root
|
12
|
+
|
13
|
+
# Log entries generated during request
|
14
|
+
attr_reader :log_entries
|
15
|
+
|
16
|
+
# Logger instance
|
17
|
+
attr_reader :logger
|
18
|
+
|
19
|
+
# Route matches during request
|
20
|
+
attr_reader :matches
|
21
|
+
|
22
|
+
attr_reader :timer
|
23
|
+
private :timer
|
24
|
+
|
25
|
+
# Callable object to filter log entries
|
26
|
+
attr_reader :filter
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
### added
|
31
|
+
attr_accessor :debug_data
|
32
|
+
|
33
|
+
# attr_reader :views
|
34
|
+
###
|
35
|
+
|
36
|
+
|
37
|
+
def initialize(logger, env, instance_id, root, filter)
|
38
|
+
@logger = logger
|
39
|
+
@root = root
|
40
|
+
@log_entries = []
|
41
|
+
# @views = []
|
42
|
+
@matches = []
|
43
|
+
@timer = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
44
|
+
@filter = filter || proc { false }
|
45
|
+
if env["debug_bar_id"].nil?
|
46
|
+
@primary = true
|
47
|
+
env["debug_bar"] = instance_id
|
48
|
+
else
|
49
|
+
@primary = false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add a matched route handler
|
54
|
+
def add_match(caller)
|
55
|
+
@matches << caller
|
56
|
+
end
|
57
|
+
|
58
|
+
# Add log entry for request
|
59
|
+
# @param status [Integer]
|
60
|
+
# status code for the response
|
61
|
+
# @param request [Roda::RodaRequest]
|
62
|
+
# request object
|
63
|
+
# @param trace [Boolean]
|
64
|
+
# tracing was enabled
|
65
|
+
def add(status, request, trace = false)
|
66
|
+
if (last_matched_caller = matches.last)
|
67
|
+
handler = format("%s:%d",
|
68
|
+
Pathname(last_matched_caller.path).relative_path_from(root),
|
69
|
+
last_matched_caller.lineno)
|
70
|
+
end
|
71
|
+
|
72
|
+
if handler.nil?
|
73
|
+
handler = 'nilString'
|
74
|
+
end
|
75
|
+
|
76
|
+
meth =
|
77
|
+
case status
|
78
|
+
when 400..499
|
79
|
+
:warn
|
80
|
+
when 500..599
|
81
|
+
:error
|
82
|
+
else
|
83
|
+
:info
|
84
|
+
end
|
85
|
+
|
86
|
+
data = {
|
87
|
+
duration: (Process.clock_gettime(Process::CLOCK_MONOTONIC) - timer).round(4),
|
88
|
+
status: status,
|
89
|
+
verb: request.request_method,
|
90
|
+
path: request.path,
|
91
|
+
remaining_path: request.remaining_path,
|
92
|
+
handler: handler,
|
93
|
+
params: request.params
|
94
|
+
}
|
95
|
+
|
96
|
+
if (db = Roda::DebugBar::Current.accrued_database_time)
|
97
|
+
data[:db] = db.round(6)
|
98
|
+
else
|
99
|
+
data[:db] = false
|
100
|
+
end
|
101
|
+
|
102
|
+
if (query_count = Roda::DebugBar::Current.database_query_count)
|
103
|
+
data[:db_queries] = query_count
|
104
|
+
end
|
105
|
+
|
106
|
+
if (queries = Roda::DebugBar::Current.database_queries)
|
107
|
+
data[:db_messages] = queries
|
108
|
+
end
|
109
|
+
|
110
|
+
if (models = Roda::DebugBar::Current.models)
|
111
|
+
data[:models] = models
|
112
|
+
end
|
113
|
+
|
114
|
+
if (views = Roda::DebugBar::Current.views)
|
115
|
+
data[:views] = views
|
116
|
+
end
|
117
|
+
|
118
|
+
data[:request] = request
|
119
|
+
|
120
|
+
# data[:request_inspect] = request.env
|
121
|
+
|
122
|
+
# data[:views] = @views
|
123
|
+
|
124
|
+
if trace
|
125
|
+
p "matches: #{matches}"
|
126
|
+
matches.each do |match|
|
127
|
+
add_log_entry([meth, format(" %s (%s:%s)",
|
128
|
+
File.readlines(match.path)[match.lineno - 1].strip.sub(" do", ""),
|
129
|
+
Pathname(match.path).relative_path_from(root),
|
130
|
+
match.lineno)])
|
131
|
+
|
132
|
+
|
133
|
+
handler = File.readlines(match.path)[match.lineno - 1].strip.sub(" do", "")
|
134
|
+
path = "#{Pathname(match.path).relative_path_from(root)}:#{match.lineno}"
|
135
|
+
Roda::DebugBar::Current.add_route(handler, path)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if (routes = Roda::DebugBar::Current.routes)
|
140
|
+
data[:routes] = routes
|
141
|
+
end
|
142
|
+
|
143
|
+
return if filter.call(request.path)
|
144
|
+
|
145
|
+
@debug_data = data
|
146
|
+
add_log_entry([meth, "#{request.request_method} #{request.path}", data])
|
147
|
+
end
|
148
|
+
|
149
|
+
# This instance is the primary logger
|
150
|
+
# @return [Boolean]
|
151
|
+
def primary?
|
152
|
+
@primary
|
153
|
+
end
|
154
|
+
|
155
|
+
# Drain the log entry queue, writing each to the logger at their respective level
|
156
|
+
# @return [Boolean]
|
157
|
+
def drain
|
158
|
+
return unless primary?
|
159
|
+
|
160
|
+
log_entries.each do |args|
|
161
|
+
logger.public_send(*args)
|
162
|
+
end
|
163
|
+
|
164
|
+
true
|
165
|
+
end
|
166
|
+
|
167
|
+
# Reset the counters for this thread
|
168
|
+
# @return [Boolean]
|
169
|
+
def reset
|
170
|
+
Roda::DebugBar::Current.reset
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
# def add_view(view)
|
176
|
+
# raise "Error: @views is nil" if @views.nil?
|
177
|
+
# @views << view
|
178
|
+
# puts @views
|
179
|
+
# end
|
180
|
+
|
181
|
+
def add_log_entry(record)
|
182
|
+
@log_entries << record
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<% if @data[:models] %>
|
2
|
+
<div class="max-w mx-auto space-y-1">
|
3
|
+
<% @data[:models].each do |model_name, models_list| %>
|
4
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">
|
5
|
+
|
6
|
+
<!-- <pretty-json> <%= {model_name => models_list}.to_json %></pretty-json> -->
|
7
|
+
|
8
|
+
<!--
|
9
|
+
<json-viewer> <%= {model_name => models_list}.to_json %><json-viewer>
|
10
|
+
|
11
|
+
<json-viewer>
|
12
|
+
{ "quiz": { "sport": { "q1": { "question": "Which one is correct team name in NBA?", "options": [ "New York Bulls",
|
13
|
+
"Los Angeles Kings", "Golden State Warriros", "Huston Rocket" ], "answer": "Huston Rocket" } }, "maths": { "q1": {
|
14
|
+
"question": "5 + 7 = ?", "options": [ "10", "11", "12", "13" ], "answer": "12" }, "q2": { "question": "12 - 8 = ?",
|
15
|
+
"options": [ "1", "2", "3", "4" ], "answer": "4" } } } }
|
16
|
+
</json-viewer>
|
17
|
+
-->
|
18
|
+
|
19
|
+
<div x-data="{open: false}">
|
20
|
+
<!-- <span><%= model_name %> x<%= models_list.size %> </span> -->
|
21
|
+
<span class="font-mono"><%= model_name %></span>
|
22
|
+
<span @click="open = !open" x-text="open? '[-]': '[+]'" class="text-blue-500 hover:cursor-pointer hover:text-blue-700 active:text-blue-400"></span>
|
23
|
+
<span class="ml-1 px-2 py-[0.125rem] bg-ruby-600 text-white rounded-full text-xs"><%= models_list.size %></span>
|
24
|
+
<ul x-show="open" class="font-mono">
|
25
|
+
<% models_list.each do |values| %>
|
26
|
+
<!-- <li class="ml-6 highlight">{ <%= highlight_ruby_hash(values.map { |k, v| "#{k}: #{v}" }.join(', ')) %> }</li> -->
|
27
|
+
<li class="ml-6 highlight ruby"><%= highlight_ruby_hash(values.to_s) %></li>
|
28
|
+
<% end %>
|
29
|
+
</ul>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<% end %>
|
34
|
+
</div>
|
35
|
+
<% else %>
|
36
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">No models</div>
|
37
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% if @data[:db_messages] %>
|
2
|
+
<div class="max-w mx-auto bg-gray-400">
|
3
|
+
<% def foo v
|
4
|
+
'bar'
|
5
|
+
end
|
6
|
+
%>
|
7
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50 font-mono flex justify-between">
|
8
|
+
<span class="italic"><%= @data[:db_queries] == 1? "1 statement was executed": "#{@data[:db_queries]} statements were executed" %></span>
|
9
|
+
<span class="text-gray-900"><%= format_time(@data[:db]) %></span>
|
10
|
+
|
11
|
+
</div>
|
12
|
+
<% @data[:db_messages].each do |query| %>
|
13
|
+
<div class="highlight px-4 py-2 odd:bg-white even:bg-ruby-50 font-mono flex justify-between">
|
14
|
+
<span><%= sql_highlight(query[:query]).downcase %></span>
|
15
|
+
<span class="text-gray-500"><%= format_time(query[:duration]) %></span>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div id="foo"></div>
|
20
|
+
|
21
|
+
<!-- Fill up 5 rows minimum -->
|
22
|
+
<!-- <% (6-@data[:db_messages].size).times do %> <div class="px-4 py-2 odd:bg-white even:bg-ruby-50 font-mono">​</div> <% end %> -->
|
23
|
+
<!-- -->
|
24
|
+
|
25
|
+
<% else %>
|
26
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">No queries</div>
|
27
|
+
<% end %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<%# grid_component(@data[:db_messages], ) %>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
hash = [
|
4
|
+
{ name: 'request_method', value: request.request_method },
|
5
|
+
{ name: 'request_path', value: request.path },
|
6
|
+
{ name: 'request_params', value: request.params }
|
7
|
+
]
|
8
|
+
|
9
|
+
request.env.each do |key, value|
|
10
|
+
hash << {name: key.downcase, value: value} if key.start_with?('HTTP_')
|
11
|
+
end
|
12
|
+
|
13
|
+
# hash << { name: 'request_headers', value: request.env.filter {|k, v| k.to_s.start_with? 'HTTP_' } }
|
14
|
+
hash << { name: 'request_headers', value: request.env.to_json }
|
15
|
+
|
16
|
+
hash << { name: 'response_headers', value: response.headers }
|
17
|
+
|
18
|
+
%>
|
19
|
+
|
20
|
+
<div class="max-w mx-auto space-y-1 font-mono">
|
21
|
+
<% hash.each do |elem| %>
|
22
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">
|
23
|
+
<span class="inline-block w-64"><%= elem[:name] %></span><span class=""><%= elem[:value] %></span>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<!--
|
29
|
+
<div class="grid grid-cols-2 gap-4 p-4 border border-gray-300 rounded-md">
|
30
|
+
<div class="font-bold">request_method</div>
|
31
|
+
<div>GET</div>
|
32
|
+
<div class="font-bold">request_path</div>
|
33
|
+
<div>/</div>
|
34
|
+
<div class="font-bold">request_params</div>
|
35
|
+
<div>{}</div>
|
36
|
+
<div class="font-bold">http_host</div>
|
37
|
+
<div>localhost:9292</div>
|
38
|
+
</div>
|
39
|
+
-->
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<% @app_root ||= __dir__ %>
|
2
|
+
<% @data[:handler] ||= 'nilString' %>
|
3
|
+
<% @data[:routes] ||= {} %>
|
4
|
+
|
5
|
+
|
6
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">
|
7
|
+
<a class="text-blue-500 hover:underline hover:cursor-pointer" href="vscode://file/<%= File.join(@app_root, @data[:handler]) %>">
|
8
|
+
<%= @data[:handler] %>
|
9
|
+
</a>
|
10
|
+
</div>
|
11
|
+
<% @data[:routes].each do |route| %>
|
12
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50">
|
13
|
+
<a class="text-blue-500 hover:underline hover:cursor-pointer" href="vscode://file/<%= File.join(@app_root, route[:path]) %>">
|
14
|
+
<%= route[:handler] %>
|
15
|
+
</a>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<% @app_root ||= __dir__ %>
|
2
|
+
|
3
|
+
<% if @data[:views] %>
|
4
|
+
<div class="max-w mx-auto">
|
5
|
+
<% views = @data[:views].tally; views.each do |view, count| %>
|
6
|
+
<div class="px-4 py-2 odd:bg-white even:bg-ruby-50 flex justify-between">
|
7
|
+
<!-- <span><%= view %> x<%= count %></span> -->
|
8
|
+
<span>
|
9
|
+
<%= view %>
|
10
|
+
<span class="ml-1 px-2 py-[0.125rem] bg-ruby-600 text-white rounded-full text-xs"><%= count %></span>
|
11
|
+
</span>
|
12
|
+
<!-- Make dynamic to engine and views directory -->
|
13
|
+
<a href="<%= "vscode://file/#{File.join(@app_root, "views/#{view}.erb")}" %>" class="text-blue-500 hover:underline hover:cursor-pointer"><%= "views/#{view}.erb" %></a>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
<% else %>
|
17
|
+
<div class="p-4 odd:bg-white even:bg-ruby-50">No views</div>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
@@ -0,0 +1,196 @@
|
|
1
|
+
|
2
|
+
<style>
|
3
|
+
<%#= Rouge::Themes::Colorful.render(scope: '.highlight') %>
|
4
|
+
<%#= Rouge::Themes::Github.mode(:light).render(scope: '.highlight') %>
|
5
|
+
|
6
|
+
/* SQL syntax highlight */
|
7
|
+
|
8
|
+
/* keywords */
|
9
|
+
.highlight .k {
|
10
|
+
font-weight: bold;
|
11
|
+
color: #912520; /* ruby-700 */
|
12
|
+
}
|
13
|
+
|
14
|
+
/* strings */
|
15
|
+
.highlight .nv {
|
16
|
+
color: #009999;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* integers */
|
20
|
+
.highlight .mi {
|
21
|
+
font-weight: bold;
|
22
|
+
color: #0086B3;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* punctuation */
|
26
|
+
.highlight .p {
|
27
|
+
color: #9ca3af;
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
/****** ruby hash ******/
|
33
|
+
|
34
|
+
/* strings */
|
35
|
+
.highlight.ruby .ss {
|
36
|
+
font-weight: bold;
|
37
|
+
color: #912520;
|
38
|
+
}
|
39
|
+
|
40
|
+
.highlight.ruby .s2 {
|
41
|
+
color: #009999;
|
42
|
+
}
|
43
|
+
|
44
|
+
/* integers */
|
45
|
+
.highlight.ruby .mi {
|
46
|
+
font-weight: normal;
|
47
|
+
color: #0086B3;
|
48
|
+
}
|
49
|
+
|
50
|
+
/* punctuation */
|
51
|
+
.highlight.ruby .p {
|
52
|
+
color: #9ca3af;
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
/*
|
57
|
+
.reset {
|
58
|
+
all: initial;
|
59
|
+
}
|
60
|
+
|
61
|
+
.reset * {
|
62
|
+
all: unset;
|
63
|
+
}
|
64
|
+
*/
|
65
|
+
/*
|
66
|
+
.normalize * {
|
67
|
+
/* @apply @tailwind base;
|
68
|
+
all: unset;
|
69
|
+
display: block;
|
70
|
+
}
|
71
|
+
*/
|
72
|
+
|
73
|
+
|
74
|
+
</style>
|
75
|
+
|
76
|
+
<!-- -->
|
77
|
+
<link rel="stylesheet" href="/debug_bar/out.css">
|
78
|
+
<!-- -->
|
79
|
+
|
80
|
+
<div class="reset">
|
81
|
+
<div x-data="debugBarComponent()" x-init="init()" class="debug-bar">
|
82
|
+
<!-- Ruby logo in lower lefthand side -->
|
83
|
+
<div>
|
84
|
+
<div x-show="openState == 'hidden'" class="fixed bottom-0 left-0 pb-2 pt-2 pl-2 pr-3 text-center hover:cursor-pointer border-t-4 border-ruby-600 bg-gray-200" @click="setOpenState('open')">
|
85
|
+
<img src="/debug_bar/ruby.png" alt="Ruby" class="h-7 w-auto">
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
<section x-show="openState != 'hidden'" class="fixed bottom-0 left-0 w-full bg-gray-200 border-t border-gray-300">
|
89
|
+
<!-- Debug Bar -->
|
90
|
+
<div class="w-full bg-gray-200 border-t border-gray-300">
|
91
|
+
<!-- Tabs -->
|
92
|
+
<div class="flex items-center bg-gray-200 justify-between">
|
93
|
+
<div class="w-8/12 flex items-center">
|
94
|
+
<!-- Clickable Ruby logo to hide debug bar -->
|
95
|
+
<div class="px-2 text-center hover:cursor-pointer" @click="setOpenState('hidden')">
|
96
|
+
<img src="/debug_bar/ruby.png" alt="Ruby" class="h-7 w-auto">
|
97
|
+
</div>
|
98
|
+
<!-- Tab group for request/models/queries... -->
|
99
|
+
<template x-for="(tab, index) in tabs" :key="index">
|
100
|
+
<div
|
101
|
+
@click="selectTab(index)"
|
102
|
+
class="flex-1 py-2 text-center cursor-pointer text-sm border-t-4 transition-all"
|
103
|
+
:class="selectedTab === index
|
104
|
+
? 'bg-gray-300 border-ruby-600 font-bold'
|
105
|
+
: 'bg-gray-200 border-transparent text-gray-800'"
|
106
|
+
x-text="tab.label">
|
107
|
+
</div>
|
108
|
+
</template>
|
109
|
+
</div>
|
110
|
+
<!--
|
111
|
+
<div class="w-16">
|
112
|
+
</div>
|
113
|
+
-->
|
114
|
+
|
115
|
+
<div class="flex">
|
116
|
+
<!-- Make right bar left aligned instead -->
|
117
|
+
<div class="flex-1 py-2 text-center text-sm border-t-4 border-transparent text-gray-800 font-mono">
|
118
|
+
<%= relative_render('debug_bar/right_bar') %>
|
119
|
+
</div>
|
120
|
+
|
121
|
+
<div class="flex justify-center items-center mr-2 ml-4">
|
122
|
+
<!-- <img src="" alt="foo" srcset="" @click="setOpenState('minimized')" class="hover:cursor-pointer"> -->
|
123
|
+
|
124
|
+
|
125
|
+
<a href="/debug_bar/last/1" class="hover:cursor-pointer">
|
126
|
+
<svg width="24px" height="24px" viewBox="0 0 76 76" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" enable-background="new 0 0 76.00 76.00" xml:space="preserve" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill="#000000" fill-opacity="1" stroke-linejoin="round" d="M 46.5,19C 47.8807,19 49,20.1193 49,21.5C 49,22.8807 47.8807,24 46.5,24L 45.8641,23.9184L 43.5566,26.8718C 45.1489,28.0176 46.5309,29.6405 47.6023,31.6025C 44.8701,32.4842 41.563,33 38,33C 34.4369,33 31.1299,32.4842 28.3977,31.6025C 29.4333,29.7061 30.7591,28.1265 32.2844,26.9882L 29.9221,23.9646C 29.7849,23.9879 29.6438,24 29.5,24C 28.1193,24 27,22.8808 27,21.5C 27,20.1193 28.1193,19 29.5,19C 30.8807,19 32,20.1193 32,21.5C 32,22.0018 31.8521,22.4691 31.5976,22.8607L 34.0019,25.938C 35.2525,25.3305 36.5982,25 38,25C 39.3339,25 40.617,25.2993 41.8156,25.8516L 44.2947,22.6786C 44.1066,22.3274 44,21.9262 44,21.5C 44,20.1193 45.1193,19 46.5,19 Z M 54.5,40C 55.3284,40 56,40.6716 56,41.5C 56,42.3284 55.3284,43 54.5,43L 49.9511,43C 49.88,44.0847 49.7325,45.1391 49.5162,46.1531L 54.8059,48.6197C 55.5567,48.9698 55.8815,49.8623 55.5314,50.6131C 55.1813,51.3639 54.2889,51.6887 53.5381,51.3386L 48.6665,49.067C 46.8161,53.9883 43.2172,57.4651 39,57.9435L 39,34.9864C 42.541,34.8897 45.7913,34.283 48.4239,33.3201L 48.6187,33.8074L 53.73,31.8454C 54.5034,31.5485 55.371,31.9348 55.6679,32.7082C 55.9648,33.4816 55.5785,34.3492 54.8051,34.6461L 49.482,36.6895C 49.717,37.7515 49.8763,38.859 49.9511,40L 54.5,40 Z M 21.5,40L 26.0489,40C 26.1237,38.859 26.2829,37.7516 26.518,36.6895L 21.1949,34.6461C 20.4215,34.3492 20.0352,33.4816 20.332,32.7082C 20.6289,31.9348 21.4966,31.5485 22.27,31.8454L 27.3812,33.8074L 27.5761,33.3201C 30.2087,34.283 33.4589,34.8897 37,34.9864L 37,57.9435C 32.7827,57.4651 29.1838,53.9883 27.3335,49.067L 22.4618,51.3387C 21.711,51.6888 20.8186,51.3639 20.4685,50.6131C 20.1184,49.8623 20.4432,48.9699 21.194,48.6198L 26.4838,46.1531C 26.2674,45.1392 26.12,44.0847 26.0489,43L 21.5,43C 20.6716,43 20,42.3285 20,41.5C 20,40.6716 20.6716,40 21.5,40 Z "></path> </g></svg>
|
127
|
+
</a>
|
128
|
+
|
129
|
+
<svg @click="toggleMinimized()" class="hover:cursor-pointer size-5" :class="openState == 'minimized' ? 'rotate-180': ''"
|
130
|
+
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
131
|
+
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
132
|
+
</svg>
|
133
|
+
<svg @click="setOpenState('hidden')" class="hover:cursor-pointer size-5"
|
134
|
+
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
135
|
+
<path d="M6.28 5.22a.75.75 0 0 0-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 1 0 1.06 1.06L10 11.06l3.72 3.72a.75.75 0 1 0 1.06-1.06L11.06 10l3.72-3.72a.75.75 0 0 0-1.06-1.06L10 8.94 6.28 5.22Z" />
|
136
|
+
</svg>
|
137
|
+
</div>
|
138
|
+
</div>
|
139
|
+
</div>
|
140
|
+
<!-- Tab Content -->
|
141
|
+
<!-- <div class="p-8 bg-gray-100 text-sm text-gray-800"> -->
|
142
|
+
<!-- <div class="bg-gray-100 text-sm text-gray-800 h-48 overflow-y-auto"> -->
|
143
|
+
<%#= @data.inspect %>
|
144
|
+
<%#= @data[:request].request_method %>
|
145
|
+
<%#= @data[:request].path %>
|
146
|
+
<div class="bg-white text-sm text-gray-800 h-56 overflow-y-auto" x-show="openState == 'open'">
|
147
|
+
<template x-for="(tab, index) in tabs" :key="index">
|
148
|
+
<div x-show="selectedTab === index" x-html="tab.content"></div>
|
149
|
+
</template>
|
150
|
+
</div>
|
151
|
+
</div>
|
152
|
+
</section>
|
153
|
+
</div>
|
154
|
+
</div>
|
155
|
+
|
156
|
+
<script>
|
157
|
+
function debugBarComponent() {
|
158
|
+
return {
|
159
|
+
selectedTab: 0,
|
160
|
+
openState: 'open',
|
161
|
+
tabs: [
|
162
|
+
// Can't comment out lines with backticks or it doesn't render
|
163
|
+
{ label: 'Request', content: `<%= relative_render('debug_bar/request') %>` },
|
164
|
+
{ label: 'Models', content: `<%= relative_render('debug_bar/models') %>` },
|
165
|
+
{ label: 'Queries', content: `<%= relative_render('debug_bar/queries') %>` },
|
166
|
+
{ label: 'Messages', content: 'Debug Info for Tab 1' },
|
167
|
+
// { label: 'Timeline', content: 'Debug Info for Tab 2' },
|
168
|
+
// { label: 'Exceptions', content: 'Debug Info for Tab 3' },
|
169
|
+
{ label: 'Views', content: `<%= relative_render('debug_bar/views') %>` },
|
170
|
+
{ label: 'Route', content: `<%= relative_render('debug_bar/route') %>` },
|
171
|
+
// { label: 'Mails', content: 'Debug Info for Tab 4' },
|
172
|
+
// { label: 'Gate', content: 'Debug Info for Tab 4' },
|
173
|
+
{ label: 'Session', content: 'Debug Info for Tab 4' },
|
174
|
+
],
|
175
|
+
|
176
|
+
init() {
|
177
|
+
this.selectedTab = parseInt(sessionStorage.getItem('debugBar.selectedTab')) || this.selectedTab;
|
178
|
+
this.openState = sessionStorage.getItem('debugBar.openState') || this.openState;
|
179
|
+
},
|
180
|
+
|
181
|
+
toggleMinimized() {
|
182
|
+
this.setOpenState(this.openState == 'minimized'? 'open': 'minimized');
|
183
|
+
},
|
184
|
+
|
185
|
+
setOpenState(openState) {
|
186
|
+
this.openState = openState;
|
187
|
+
sessionStorage.setItem('debugBar.openState', openState);
|
188
|
+
},
|
189
|
+
|
190
|
+
selectTab(index) {
|
191
|
+
this.selectedTab = index;
|
192
|
+
sessionStorage.setItem('debugBar.selectedTab', index);
|
193
|
+
}
|
194
|
+
};
|
195
|
+
}
|
196
|
+
</script>
|