rails_error_dashboard 0.1.15 → 0.1.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da18321511a53167fa248ae72974c6c15807a725396aabd27af1059296ecbc46
4
- data.tar.gz: 84f348d386b6b07375797275dedf97e5a9504522270447bebd6b56307f5e4a7d
3
+ metadata.gz: 2bb87db0ac566c74592758f0bb11c4e16f3caff7464d7c428436083adc13edb5
4
+ data.tar.gz: ccead510cbc1f57d1197aafa34e4c43f3f74a59f7b4d56e53ea0b8ebb4fa73e2
5
5
  SHA512:
6
- metadata.gz: b5b3d045f7a0b7bcae61823aa57e373111b6dab59e5a651ae5a33df9a3f043598e6469195b9cb508e79ad6bda62182877572888dba3cea37a4039715eee79349
7
- data.tar.gz: 460491a0614445e91f098dbb792d86d9d7c8616f0456ad88cd6b14fdf27aba4d87990b080bd6c289eafe03befccceec94b6b23dcce29d850fd05b3bda946d39d
6
+ metadata.gz: 330ec515a3f833517c66926f1c77a3bd9c6cf7db23a5d9e63d2ae796c1fb2fd672dba56839cb7e70cd055e8d6ec46ff8d0974f56af4580463d0bcfa6f3c5b9c5
7
+ data.tar.gz: f19ea45f7eadce30679c0cf0e0e8f117f603fa2d06158783477ad2a6e0451e91a09cb6913eb6ec2a4798ea57d655622d496adce5a4f8cf378a74304ae92cf19c
@@ -2,6 +2,12 @@ module RailsErrorDashboard
2
2
  class ApplicationController < ActionController::Base
3
3
  include Pagy::Backend
4
4
 
5
+ # Enable features that are disabled in API-only mode
6
+ # These are ONLY enabled for Error Dashboard routes, not the entire app
7
+ include ActionController::Cookies
8
+ include ActionController::Flash
9
+ include ActionController::RequestForgeryProtection
10
+
5
11
  layout "rails_error_dashboard"
6
12
 
7
13
  protect_from_forgery with: :exception
@@ -3,8 +3,12 @@
3
3
  <head>
4
4
  <title><%= content_for?(:page_title) ? "#{content_for(:page_title)} | " : "" %><%= Rails.application.class.module_parent_name %> - Error Dashboard</title>
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
- <%= csrf_meta_tags %>
7
- <%= csp_meta_tag %>
6
+ <% if respond_to?(:csrf_meta_tags) %>
7
+ <%= csrf_meta_tags %>
8
+ <% end %>
9
+ <% if respond_to?(:csp_meta_tag) %>
10
+ <%= csp_meta_tag %>
11
+ <% end %>
8
12
 
9
13
  <!-- Bootstrap CSS -->
10
14
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
@@ -1170,17 +1174,19 @@
1170
1174
  };
1171
1175
 
1172
1176
  // Show flash messages as toasts
1173
- <% if flash[:notice] %>
1174
- showToast('<%= j flash[:notice] %>', 'success');
1175
- <% end %>
1176
- <% if flash[:alert] %>
1177
- showToast('<%= j flash[:alert] %>', 'danger');
1178
- <% end %>
1179
- <% if flash[:success] %>
1180
- showToast('<%= j flash[:success] %>', 'success');
1181
- <% end %>
1182
- <% if flash[:error] %>
1183
- showToast('<%= j flash[:error] %>', 'danger');
1177
+ <% if defined?(flash) && flash.present? %>
1178
+ <% if flash[:notice] %>
1179
+ showToast('<%= j flash[:notice] %>', 'success');
1180
+ <% end %>
1181
+ <% if flash[:alert] %>
1182
+ showToast('<%= j flash[:alert] %>', 'danger');
1183
+ <% end %>
1184
+ <% if flash[:success] %>
1185
+ showToast('<%= j flash[:success] %>', 'success');
1186
+ <% end %>
1187
+ <% if flash[:error] %>
1188
+ showToast('<%= j flash[:error] %>', 'danger');
1189
+ <% end %>
1184
1190
  <% end %>
1185
1191
  });
1186
1192
  </script>
@@ -131,14 +131,29 @@
131
131
  <script>
132
132
  document.addEventListener('DOMContentLoaded', function() {
133
133
  const colors = window.getChartColors();
134
+ // Distinct, accessible colors for 5 platforms with good contrast
135
+ const platformColors = [
136
+ "#2563EB", // Blue - API
137
+ "#10B981", // Green - Android
138
+ "#F59E0B", // Amber - Background Jobs
139
+ "#8B5CF6", // Purple - Web
140
+ "#EF4444" // Red - iOS
141
+ ];
142
+
134
143
  new Chartkick.PieChart("errors-by-platform-chart", <%= raw @errors_by_platform.to_json %>, {
135
- colors: ["#000000", "#3DDC84", "#3B82F6"],
144
+ colors: platformColors,
136
145
  height: "300px",
137
146
  legend: "bottom",
138
147
  donut: true,
139
148
  library: {
140
149
  plugins: {
141
- legend: { labels: { color: colors.textColor } }
150
+ legend: {
151
+ labels: {
152
+ color: colors.textColor,
153
+ font: { size: 12, weight: 'bold' }
154
+ }
155
+ }
156
+ // Tooltip uses global theme-aware defaults from layout
142
157
  }
143
158
  }
144
159
  });
@@ -291,6 +291,19 @@
291
291
  </div>
292
292
 
293
293
  <script>
294
+ // Platform color mapping - consistent with analytics page
295
+ const platformColorMap = {
296
+ 'api': '#2563EB', // Blue
297
+ 'android': '#10B981', // Green
298
+ 'background_jobs': '#F59E0B', // Amber
299
+ 'web': '#8B5CF6', // Purple
300
+ 'ios': '#EF4444' // Red
301
+ };
302
+
303
+ function getPlatformColor(platform) {
304
+ return platformColorMap[platform.toLowerCase()] || '#6B7280'; // Gray fallback
305
+ }
306
+
294
307
  // Error Rate Chart
295
308
  const errorRateCtx = document.getElementById('errorRateChart');
296
309
  if (errorRateCtx) {
@@ -301,16 +314,8 @@
301
314
  datasets: [{
302
315
  label: 'Total Errors',
303
316
  data: <%= raw @error_rate_by_platform.values.to_json %>,
304
- backgroundColor: (function() {
305
- const isDark = document.body.classList.contains('dark-mode');
306
- const config = getCatppuccinChartConfig(isDark);
307
- return config.colors.blue.replace('rgb', 'rgba').replace(')', ', 0.5)');
308
- })(),
309
- borderColor: (function() {
310
- const isDark = document.body.classList.contains('dark-mode');
311
- const config = getCatppuccinChartConfig(isDark);
312
- return config.colors.blue;
313
- })(),
317
+ backgroundColor: 'rgba(37, 99, 235, 0.5)', // Blue with transparency
318
+ borderColor: '#2563EB', // Blue
314
319
  borderWidth: 1
315
320
  }]
316
321
  },
@@ -330,9 +335,6 @@
330
335
  // Daily Trend Chart
331
336
  const dailyTrendCtx = document.getElementById('dailyTrendChart');
332
337
  if (dailyTrendCtx) {
333
- // Use Catppuccin colors from global theme config
334
- const isDark = document.body.classList.contains('dark-mode');
335
-
336
338
  const datasets = <%= raw @daily_trends.map { |platform, data|
337
339
  {
338
340
  label: platform.to_s.capitalize,
@@ -342,12 +344,12 @@
342
344
  }
343
345
  }.to_json %>;
344
346
 
345
- // Apply Catppuccin platform colors
347
+ // Apply platform-specific colors
346
348
  datasets.forEach(ds => {
347
- const color = getPlatformColor(ds.platform, isDark);
349
+ const color = getPlatformColor(ds.platform);
348
350
  ds.borderColor = color;
349
351
  // Add transparency for background
350
- ds.backgroundColor = color.replace('rgb', 'rgba').replace(')', ', 0.1)');
352
+ ds.backgroundColor = color + '1A'; // Add 10% alpha in hex
351
353
  });
352
354
 
353
355
  new Chart(dailyTrendCtx, {
@@ -382,16 +384,8 @@
382
384
  datasets: [{
383
385
  label: 'Hours to Resolve',
384
386
  data: times,
385
- backgroundColor: (function() {
386
- const isDark = document.body.classList.contains('dark-mode');
387
- const config = getCatppuccinChartConfig(isDark);
388
- return config.colors.orange.replace('rgb', 'rgba').replace(')', ', 0.5)');
389
- })(),
390
- borderColor: (function() {
391
- const isDark = document.body.classList.contains('dark-mode');
392
- const config = getCatppuccinChartConfig(isDark);
393
- return config.colors.orange;
394
- })(),
387
+ backgroundColor: 'rgba(245, 158, 11, 0.5)', // Amber with transparency
388
+ borderColor: '#F59E0B', // Amber
395
389
  borderWidth: 1
396
390
  }]
397
391
  },
@@ -30,9 +30,6 @@
30
30
  <button type="button" class="btn btn-outline-secondary" onclick="downloadErrorJSON()" title="Download error details as JSON">
31
31
  <i class="bi bi-download"></i> Export JSON
32
32
  </button>
33
- <button type="button" class="btn btn-outline-primary" onclick="copyErrorURL()" title="Copy shareable link to this error">
34
- <i class="bi bi-share"></i> Share
35
- </button>
36
33
  <% if @error.resolved? %>
37
34
  <span class="badge bg-success fs-6">
38
35
  <i class="bi bi-check-circle"></i> Resolved
@@ -46,26 +43,6 @@
46
43
  </div>
47
44
 
48
45
  <script>
49
- function copyErrorURL() {
50
- const url = window.location.href;
51
- navigator.clipboard.writeText(url).then(() => {
52
- // Change button text temporarily
53
- const button = event.currentTarget;
54
- const originalHTML = button.innerHTML;
55
- button.innerHTML = '<i class="bi bi-check"></i> Copied!';
56
- button.classList.remove('btn-outline-primary');
57
- button.classList.add('btn-success');
58
-
59
- setTimeout(() => {
60
- button.innerHTML = originalHTML;
61
- button.classList.remove('btn-success');
62
- button.classList.add('btn-outline-primary');
63
- }, 2000);
64
- }).catch(err => {
65
- alert('Failed to copy URL: ' + err);
66
- });
67
- }
68
-
69
46
  function downloadErrorJSON() {
70
47
  const errorData = {
71
48
  id: <%= @error.id %>,
@@ -4,6 +4,15 @@ module RailsErrorDashboard
4
4
 
5
5
  # Initialize the engine
6
6
  initializer "rails_error_dashboard.middleware" do |app|
7
+ # Enable Flash middleware for Error Dashboard routes in API-only apps
8
+ # This ensures flash messages work even when config.api_only = true
9
+ if app.config.api_only
10
+ # Insert Flash middleware ONLY for Error Dashboard routes
11
+ app.middleware.use ActionDispatch::Flash
12
+ app.middleware.use ActionDispatch::Cookies
13
+ app.middleware.use ActionDispatch::Session::CookieStore
14
+ end
15
+
7
16
  # Add error catching middleware if enabled
8
17
  if RailsErrorDashboard.configuration.enable_middleware
9
18
  app.config.middleware.insert_before 0, RailsErrorDashboard::Middleware::ErrorCatcher
@@ -46,7 +46,16 @@ module RailsErrorDashboard
46
46
  end
47
47
 
48
48
  def build_request_url
49
- return @context[:request]&.fullpath if @context[:request]
49
+ # Handle both full Rails requests and API-only requests
50
+ if @context[:request]
51
+ begin
52
+ return @context[:request].fullpath
53
+ rescue NoMethodError
54
+ # Fallback for minimal request objects
55
+ return @context[:request].path rescue nil
56
+ end
57
+ end
58
+
50
59
  return @context[:request_url] if @context[:request_url]
51
60
  return "Background Job: #{@context[:job]&.class}" if @context[:job]
52
61
  return "Sidekiq: #{@context[:job_class]}" if @context[:job_class]
@@ -114,10 +123,17 @@ module RailsErrorDashboard
114
123
  def detect_platform
115
124
  # Check if it's from a mobile request
116
125
  user_agent = extract_user_agent
117
- return Services::PlatformDetector.detect(user_agent) if @context[:request]
118
126
 
119
- # Everything else is API/backend
120
- "API"
127
+ return "API" unless user_agent.present? && @context[:request]
128
+
129
+ # Only detect platform if we have a valid user agent
130
+ begin
131
+ Services::PlatformDetector.detect(user_agent)
132
+ rescue => e
133
+ # Fallback to API if platform detection fails
134
+ Rails.logger.debug("[RailsErrorDashboard] Platform detection failed: #{e.message}")
135
+ "API"
136
+ end
121
137
  end
122
138
 
123
139
  def extract_controller_name
@@ -161,8 +177,8 @@ module RailsErrorDashboard
161
177
  end
162
178
 
163
179
  def extract_session_id
164
- # From Rails session
165
- return @context[:request]&.session&.id if @context[:request]&.session
180
+ # Session is only available in full Rails mode, not API-only
181
+ return @context[:request]&.session&.id if @context[:request]&.respond_to?(:session) && @context[:request]&.session
166
182
 
167
183
  # From explicit context
168
184
  return @context[:session_id] if @context[:session_id]
@@ -1,3 +1,3 @@
1
1
  module RailsErrorDashboard
2
- VERSION = "0.1.15"
2
+ VERSION = "0.1.16"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_error_dashboard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.15
4
+ version: 0.1.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anjan Jagirdar
@@ -379,7 +379,7 @@ metadata:
379
379
  source_code_uri: https://github.com/AnjanJ/rails_error_dashboard
380
380
  changelog_uri: https://github.com/AnjanJ/rails_error_dashboard/blob/main/CHANGELOG.md
381
381
  post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
382
- \ Rails Error Dashboard v0.1.15\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
382
+ \ Rails Error Dashboard v0.1.16\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
383
383
  First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
384
384
  db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
385
385
  => '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n