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 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">&#8203;</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,4 @@
1
+ <!-- GET / <%#= request.path %> <%= RUBY_VERSION %> -->
2
+
3
+ <span>GET <%= request.path %></span>
4
+ <span class="ml-2"><%= format_time(@data[:duration]) %></span>
@@ -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>