From b476c3eb2019d54bb77466d5fff881738cae4330 Mon Sep 17 00:00:00 2001 From: Dan Loman Date: Fri, 9 Jan 2026 16:19:27 -0800 Subject: [PATCH] Add application/full backtrace filtering via toggle --- .../layouts/solid_errors/application.html.erb | 65 +++++++++++++++++ .../occurrences/_occurrence.html.erb | 73 +++++++++++++++---- 2 files changed, 124 insertions(+), 14 deletions(-) diff --git a/app/views/layouts/solid_errors/application.html.erb b/app/views/layouts/solid_errors/application.html.erb index 1c353bc..b93ca12 100644 --- a/app/views/layouts/solid_errors/application.html.erb +++ b/app/views/layouts/solid_errors/application.html.erb @@ -51,6 +51,71 @@ document.querySelectorAll('[data-controller="fade"]').forEach(element => { fadeOut(element); }); + + // Backtrace filter toggle functionality + (function() { + const STORAGE_KEY = 'solid_errors_backtrace_filter'; + + function toggleBacktrace(button) { + const filter = button.getAttribute('data-backtrace-toggle'); + const occurrenceId = button.getAttribute('data-occurrence-id'); + + // Toggle visibility + const appTrace = document.getElementById(`backtrace-application-${occurrenceId}`); + const fullTrace = document.getElementById(`backtrace-full-${occurrenceId}`); + + if (filter === 'application') { + appTrace.removeAttribute('hidden'); + fullTrace.setAttribute('hidden', ''); + } else { + appTrace.setAttribute('hidden', ''); + fullTrace.removeAttribute('hidden'); + } + + // Update button states for this occurrence + const occurrenceButtons = document.querySelectorAll(`[data-occurrence-id="${occurrenceId}"][data-backtrace-toggle]`); + occurrenceButtons.forEach(btn => { + if (btn === button) { + btn.classList.add('border-blue-500', 'text-blue-500'); + btn.classList.remove('border-transparent', 'text-gray-500'); + } else { + btn.classList.remove('border-blue-500', 'text-blue-500'); + btn.classList.add('border-transparent', 'text-gray-500'); + } + }); + + // Save preference + sessionStorage.setItem(STORAGE_KEY, filter); + } + + // Initialize on page load + const savedFilter = sessionStorage.getItem(STORAGE_KEY) || 'application'; + + // Apply saved filter to all occurrences + if (savedFilter === 'full') { + document.querySelectorAll('[id^="backtrace-application-"]').forEach(el => el.setAttribute('hidden', '')); + document.querySelectorAll('[id^="backtrace-full-"]').forEach(el => el.removeAttribute('hidden')); + + // Update button states + document.querySelectorAll('[data-backtrace-toggle]').forEach(btn => { + const filter = btn.getAttribute('data-backtrace-toggle'); + if (filter === savedFilter) { + btn.classList.add('border-blue-500', 'text-blue-500'); + btn.classList.remove('border-transparent', 'text-gray-500'); + } else { + btn.classList.remove('border-blue-500', 'text-blue-500'); + btn.classList.add('border-transparent', 'text-gray-500'); + } + }); + } + + // Attach event listeners + document.querySelectorAll('[data-backtrace-toggle]').forEach(button => { + button.addEventListener('click', function() { + toggleBacktrace(this); + }); + }); + })(); diff --git a/app/views/solid_errors/occurrences/_occurrence.html.erb b/app/views/solid_errors/occurrences/_occurrence.html.erb index 722da96..75e41f0 100644 --- a/app/views/solid_errors/occurrences/_occurrence.html.erb +++ b/app/views/solid_errors/occurrences/_occurrence.html.erb @@ -25,22 +25,67 @@ <%= SolidErrors::Occurrence.human_attribute_name(:backtrace) %>
- <% backtrace.lines.each_with_index do |line, i| %> - <%= tag.details open: line.application? || i.zero? do %> - - <% if line.filtered_file %> - <%= File.dirname(line.filtered_file) %>/<%= File.basename(line.filtered_file) %>:<%= line.filtered_number %> - in - <%= line.filtered_method %> - <% else %> - <%= line.unparsed_line %> +
+ + +
+ +
+ <% if backtrace.application_lines.empty? %> +

+ No application code in backtrace. + +

+ <% else %> + <% backtrace.application_lines.each_with_index do |line, i| %> + <%= tag.details open: line.application? || i.zero? do %> + + <% if line.filtered_file %> + <%= File.dirname(line.filtered_file) %>/<%= File.basename(line.filtered_file) %>:<%= line.filtered_number %> + in + <%= line.filtered_method %> + <% else %> + <%= line.unparsed_line %> + <% end %> + +
<% line.source.each do |n, code| %>
+                        
<%= n %><%= code %>
+ <% end %>
<% end %> -
-
<% line.source.each do |n, code| %>
-                    
<%= n %><%= code %>
- <% end %>
+ <% end %> + <% end %> + + +