solidstats 2.0.0 → 3.0.0.beta.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.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -63
  3. data/README.md +27 -33
  4. data/Rakefile +3 -3
  5. data/app/assets/stylesheets/solidstats/application.css +1 -6
  6. data/app/assets/stylesheets/solidstats/dashboard.css +48 -0
  7. data/app/controllers/solidstats/dashboard_controller.rb +81 -62
  8. data/app/controllers/solidstats/logs_controller.rb +72 -0
  9. data/app/controllers/solidstats/performance_controller.rb +25 -0
  10. data/app/controllers/solidstats/productivity_controller.rb +39 -0
  11. data/app/controllers/solidstats/quality_controller.rb +152 -0
  12. data/app/controllers/solidstats/securities_controller.rb +30 -0
  13. data/app/helpers/solidstats/application_helper.rb +124 -11
  14. data/app/helpers/solidstats/performance_helper.rb +87 -0
  15. data/app/helpers/solidstats/productivity_helper.rb +38 -0
  16. data/app/services/solidstats/bundler_audit_service.rb +206 -0
  17. data/app/services/solidstats/coverage_compass_service.rb +335 -0
  18. data/app/services/solidstats/load_lens_service.rb +454 -0
  19. data/app/services/solidstats/log_size_monitor_service.rb +207 -76
  20. data/app/services/solidstats/my_todo_service.rb +242 -0
  21. data/app/services/solidstats/style_patrol_service.rb +319 -0
  22. data/app/views/layouts/solidstats/application.html.erb +8 -2
  23. data/app/views/layouts/solidstats/dashboard.html.erb +84 -0
  24. data/app/views/solidstats/dashboard/dashboard.html.erb +39 -0
  25. data/app/views/solidstats/logs/logs_size.html.erb +409 -0
  26. data/app/views/solidstats/performance/load_lens.html.erb +158 -0
  27. data/app/views/solidstats/productivity/_todo_list.html.erb +49 -0
  28. data/app/views/solidstats/productivity/my_todos.html.erb +84 -0
  29. data/app/views/solidstats/quality/coverage_compass.html.erb +420 -0
  30. data/app/views/solidstats/quality/style_patrol.html.erb +463 -0
  31. data/app/views/solidstats/securities/bundler_audit.html.erb +345 -0
  32. data/app/views/solidstats/shared/_dashboard_card.html.erb +160 -0
  33. data/app/views/solidstats/shared/_quick_actions.html.erb +26 -0
  34. data/config/routes.rb +32 -7
  35. data/lib/generators/solidstats/install/install_generator.rb +28 -2
  36. data/lib/generators/solidstats/install/templates/README +7 -0
  37. data/lib/solidstats/engine.rb +9 -114
  38. data/lib/solidstats/version.rb +1 -1
  39. data/lib/solidstats.rb +2 -299
  40. data/lib/tasks/solidstats_install.rake +2 -122
  41. data/lib/tasks/solidstats_performance.rake +84 -0
  42. metadata +32 -103
  43. data/app/assets/javascripts/solidstats/application.js +0 -257
  44. data/app/assets/javascripts/solidstats/dashboard.js +0 -225
  45. data/app/assets/javascripts/solidstats/gem_metadata.js +0 -554
  46. data/app/assets/stylesheets/solidstats/components/action_button.css +0 -99
  47. data/app/assets/stylesheets/solidstats/components/dashboard.css +0 -151
  48. data/app/assets/stylesheets/solidstats/components/dashboard_header.css +0 -93
  49. data/app/assets/stylesheets/solidstats/components/dashboard_layout.css +0 -97
  50. data/app/assets/stylesheets/solidstats/components/gem_metadata.css +0 -1403
  51. data/app/assets/stylesheets/solidstats/components/navigation.css +0 -80
  52. data/app/assets/stylesheets/solidstats/components/quick_navigation.css +0 -54
  53. data/app/assets/stylesheets/solidstats/components/security.css +0 -332
  54. data/app/assets/stylesheets/solidstats/components/status_badge.css +0 -58
  55. data/app/assets/stylesheets/solidstats/components/summary_card.css +0 -66
  56. data/app/assets/stylesheets/solidstats/components/tab_navigation.css +0 -95
  57. data/app/components/solidstats/base_component.rb +0 -88
  58. data/app/components/solidstats/code_quality/code_quality_section_component.html.erb +0 -0
  59. data/app/components/solidstats/code_quality/code_quality_section_component.rb +0 -0
  60. data/app/components/solidstats/code_quality/section_component.html.erb +0 -45
  61. data/app/components/solidstats/code_quality/section_component.rb +0 -34
  62. data/app/components/solidstats/dashboard_header_component.html.erb +0 -39
  63. data/app/components/solidstats/dashboard_header_component.rb +0 -33
  64. data/app/components/solidstats/previews/action_button_component_preview/button_vs_link.html.erb +0 -6
  65. data/app/components/solidstats/previews/action_button_component_preview/sizes.html.erb +0 -6
  66. data/app/components/solidstats/previews/action_button_component_preview/variants.html.erb +0 -6
  67. data/app/components/solidstats/previews/action_button_component_preview/with_icons.html.erb +0 -6
  68. data/app/components/solidstats/previews/action_button_component_preview.rb +0 -64
  69. data/app/components/solidstats/previews/navigation_component_preview.rb +0 -74
  70. data/app/components/solidstats/previews/stats_overview_component_preview.rb +0 -100
  71. data/app/components/solidstats/previews/status_badge_component_preview/sizes.html.erb +0 -6
  72. data/app/components/solidstats/previews/status_badge_component_preview/statuses.html.erb +0 -6
  73. data/app/components/solidstats/previews/status_badge_component_preview/with_icons.html.erb +0 -6
  74. data/app/components/solidstats/previews/status_badge_component_preview.rb +0 -49
  75. data/app/components/solidstats/previews/summary_card_component_preview/clickable.html.erb +0 -9
  76. data/app/components/solidstats/previews/summary_card_component_preview/dashboard_layout.html.erb +0 -9
  77. data/app/components/solidstats/previews/summary_card_component_preview/statuses.html.erb +0 -6
  78. data/app/components/solidstats/previews/summary_card_component_preview/value_formats.html.erb +0 -6
  79. data/app/components/solidstats/previews/summary_card_component_preview.rb +0 -67
  80. data/app/components/solidstats/quick_navigation_component.html.erb +0 -8
  81. data/app/components/solidstats/quick_navigation_component.rb +0 -21
  82. data/app/components/solidstats/security/gem_impact_analysis_component.html.erb +0 -44
  83. data/app/components/solidstats/security/gem_impact_analysis_component.rb +0 -45
  84. data/app/components/solidstats/security/overview_component.html.erb +0 -21
  85. data/app/components/solidstats/security/overview_component.rb +0 -104
  86. data/app/components/solidstats/security/section_component.html.erb +0 -26
  87. data/app/components/solidstats/security/section_component.rb +0 -52
  88. data/app/components/solidstats/security/timeline_component.html.erb +0 -39
  89. data/app/components/solidstats/security/timeline_component.rb +0 -43
  90. data/app/components/solidstats/tasks_section_component.html.erb +0 -17
  91. data/app/components/solidstats/tasks_section_component.rb +0 -22
  92. data/app/components/solidstats/ui/action_button_component.html.erb +0 -6
  93. data/app/components/solidstats/ui/action_button_component.rb +0 -71
  94. data/app/components/solidstats/ui/dashboard_layout_component.html.erb +0 -19
  95. data/app/components/solidstats/ui/dashboard_layout_component.rb +0 -85
  96. data/app/components/solidstats/ui/navigation_component.html.erb +0 -34
  97. data/app/components/solidstats/ui/navigation_component.rb +0 -72
  98. data/app/components/solidstats/ui/stats_overview_component.html.erb +0 -14
  99. data/app/components/solidstats/ui/stats_overview_component.rb +0 -78
  100. data/app/components/solidstats/ui/status_badge_component.html.erb +0 -6
  101. data/app/components/solidstats/ui/status_badge_component.rb +0 -42
  102. data/app/components/solidstats/ui/summary_card_component.html.erb +0 -12
  103. data/app/components/solidstats/ui/summary_card_component.rb +0 -63
  104. data/app/components/solidstats/ui/tab_navigation_component.html.erb +0 -22
  105. data/app/components/solidstats/ui/tab_navigation_component.rb +0 -79
  106. data/app/controllers/solidstats/gem_metadata_controller.rb +0 -12
  107. data/app/services/solidstats/audit_service.rb +0 -56
  108. data/app/services/solidstats/data_collector_service.rb +0 -83
  109. data/app/services/solidstats/gem_metadata/fetcher_service.rb +0 -136
  110. data/app/services/solidstats/todo_service.rb +0 -114
  111. data/app/views/solidstats/dashboard/_log_monitor.html.erb +0 -759
  112. data/app/views/solidstats/dashboard/_todos.html.erb +0 -151
  113. data/app/views/solidstats/dashboard/audit/_additional_styles.css +0 -22
  114. data/app/views/solidstats/dashboard/audit/_audit_badge.html.erb +0 -5
  115. data/app/views/solidstats/dashboard/audit/_audit_details.html.erb +0 -495
  116. data/app/views/solidstats/dashboard/audit/_audit_summary.html.erb +0 -26
  117. data/app/views/solidstats/dashboard/audit/_no_vulnerabilities.html.erb +0 -3
  118. data/app/views/solidstats/dashboard/audit/_security_audit.html.erb +0 -14
  119. data/app/views/solidstats/dashboard/audit/_vulnerabilities_table.html.erb +0 -1120
  120. data/app/views/solidstats/dashboard/audit/_vulnerability_details.html.erb +0 -63
  121. data/app/views/solidstats/dashboard/index.html.erb +0 -81
  122. data/app/views/solidstats/gem_metadata/_panel.html.erb +0 -419
  123. data/lib/generators/solidstats/feature/feature_generator.rb +0 -170
  124. data/lib/generators/solidstats/feature/templates/component.html.erb +0 -84
  125. data/lib/generators/solidstats/feature/templates/component.rb.erb +0 -103
  126. data/lib/generators/solidstats/feature/templates/component.scss +0 -243
  127. data/lib/generators/solidstats/feature/templates/component_test.rb.erb +0 -183
  128. data/lib/generators/solidstats/feature/templates/controller.rb.erb +0 -44
  129. data/lib/generators/solidstats/feature/templates/controller_test.rb.erb +0 -111
  130. data/lib/generators/solidstats/feature/templates/detail_view.html.erb +0 -755
  131. data/lib/generators/solidstats/feature/templates/preview.rb.erb +0 -107
  132. data/lib/generators/solidstats/feature/templates/service.rb.erb +0 -132
  133. data/lib/generators/solidstats/feature/templates/service_test.rb.erb +0 -109
  134. data/lib/generators/solidstats/install_generator.rb +0 -109
  135. data/lib/generators/solidstats/templates/initializer.rb +0 -112
  136. data/lib/solidstats/asset_compatibility.rb +0 -238
  137. data/lib/solidstats/asset_manifest.rb +0 -205
  138. data/lib/tasks/solidstats_tasks.rake +0 -4
@@ -1,63 +0,0 @@
1
- <% # results should be passed as a local variable %>
2
- <div class="vulnerabilities-details-section">
3
- <h3>
4
- <span>Vulnerability Details</span>
5
- <button class="toggle-details-btn" aria-expanded="true">Hide Details</button>
6
- </h3>
7
- <%# TODO: Render Markdown in .erb using Redcarpet with sanitize for safe HTML output %>
8
- <div class="md-container">
9
- <% results.each_with_index do |result, index| %>
10
- <%
11
- gem = result.dig("gem") || {}
12
- advisory = result.dig("advisory") || {}
13
- criticality = advisory["criticality"] || "unknown"
14
- is_high = %w[high critical].include?(criticality.to_s.downcase)
15
- %>
16
- <% if advisory["description"].present? %>
17
- <div id="vulnerability-<%= index %>" class="md-entry <%= is_high ? 'high-severity' : '' %>">
18
- <h2 class="md-heading">
19
- <%= gem["name"] %> <%= gem["version"] %> - <%= advisory["title"] %>
20
- </h2>
21
-
22
- <div class="md-metadata">
23
- <% if advisory["cve"].present? %>
24
- <div class="md-tag cve">CVE-<%= advisory["cve"] %></div>
25
- <% elsif advisory["ghsa"].present? %>
26
- <div class="md-tag ghsa">GHSA-<%= advisory["ghsa"] %></div>
27
- <% end %>
28
- <div class="md-tag severity <%= criticality.to_s.downcase %>"><%= criticality %></div>
29
- <% if advisory["date"].present? %>
30
- <div class="md-date"><%= advisory["date"] %></div>
31
- <% end %>
32
- </div>
33
-
34
- <div class="md-divider"></div>
35
-
36
- <div class="md-content">
37
- <%= simple_format(advisory["description"]) %>
38
- </div>
39
-
40
- <% if advisory["patched_versions"].present? %>
41
- <div class="md-code-block">
42
- <div class="md-code-header">Patched Versions</div>
43
- <pre class="md-code"><%= advisory["patched_versions"].join(", ") %></pre>
44
- </div>
45
- <% end %>
46
-
47
- <% if advisory["url"].present? %>
48
- <div class="md-link">
49
- <span class="md-link-icon">🔗</span>
50
- <a href="<%= advisory["url"] %>" target="_blank" rel="noopener">More information</a>
51
- </div>
52
- <% end %>
53
-
54
- <div class="md-back">
55
- <a href="#" class="back-to-top" onclick="window.scrollTo({top: document.querySelector('.vulnerabilities-table').offsetTop - 20, behavior: 'smooth'}); return false;">
56
- ↑ Back to vulnerabilities table
57
- </a>
58
- </div>
59
- </div>
60
- <% end %>
61
- <% end %>
62
- </div>
63
- </div>
@@ -1,81 +0,0 @@
1
- <%# Modern Component-Based Dashboard %>
2
- <%# Refactored from 1,368-line monolithic file to clean ViewComponent architecture %>
3
-
4
- <div class="solidstats-dashboard">
5
- <%# Dashboard Header with Navigation and Actions %>
6
- <%= render Solidstats::DashboardHeaderComponent.new(audit_output: @audit_output) %>
7
-
8
- <%# Overview Section with Key Metrics Summary Cards %>
9
- <section id="overview" class="dashboard-section active">
10
- <h2 class="section-title">Overview</h2>
11
-
12
- <div class="stats-summary">
13
- <%# Security Issues Summary Card %>
14
- <%= render Solidstats::Ui::SummaryCardComponent.new(
15
- title: "Security Issues",
16
- value: @audit_output.dig('results')&.size || 0,
17
- status: :warning,
18
- icon: "🔒",
19
- section: "security",
20
- tab: "security-overview"
21
- ) %>
22
-
23
- <%# Gem Count Summary Card %>
24
- <%= render Solidstats::Ui::SummaryCardComponent.new(
25
- title: "Total Gems",
26
- value: (Solidstats::GemMetadata::FetcherService.call.size rescue 0),
27
- status: :info,
28
- icon: "💎",
29
- section: "gem-metadata"
30
- ) %>
31
-
32
- <%# TODO Items Summary Card %>
33
- <%= render Solidstats::Ui::SummaryCardComponent.new(
34
- title: "TODO Items",
35
- value: @todo_items&.count || 0,
36
- status: ((@todo_items&.count || 0) > 10 ? :warning : :ok),
37
- icon: "📝",
38
- section: "tasks",
39
- tab: "todos"
40
- ) %>
41
-
42
- <%# Test Coverage Summary Card %>
43
- <%= render Solidstats::Ui::SummaryCardComponent.new(
44
- title: "Test Coverage",
45
- value: "#{@coverage.to_f.round(1)}%",
46
- status: (@coverage.to_f >= 80 ? :ok : :warning),
47
- icon: "📊",
48
- section: "code-quality",
49
- tab: "test-coverage"
50
- ) %>
51
-
52
- <%# Log Size Summary Card %>
53
- <%= render Solidstats::Ui::SummaryCardComponent.new(
54
- title: "Log Size",
55
- value: "#{@log_data[:total_size_mb]} MB",
56
- status: @log_data[:status]&.to_sym || :ok,
57
- icon: "📋",
58
- section: "code-quality",
59
- tab: "log-monitor"
60
- ) %>
61
- </div>
62
- </section>
63
-
64
- <%# Security Section - Component-Based Architecture %>
65
- <%= render Solidstats::Security::SectionComponent.new(audit_output: @audit_output) %>
66
-
67
- <%# Code Quality Section - Component-Based Architecture %>
68
- <%= render Solidstats::CodeQuality::SectionComponent.new(coverage: @coverage, log_data: @log_data) %>
69
-
70
- <%# Gem Metadata Section %>
71
- <section id="gem-metadata" class="dashboard-section">
72
- <h2 class="section-title">Gem Dependencies</h2>
73
- <%= render partial: 'solidstats/gem_metadata/panel' %>
74
- </section>
75
-
76
- <%# Tasks Section - Component-Based Architecture %>
77
- <%= render Solidstats::TasksSectionComponent.new(todo_items: @todo_items) %>
78
-
79
- <%# Quick Navigation - Component-Based Architecture %>
80
- <%= render Solidstats::QuickNavigationComponent.new %>
81
- </div>
@@ -1,419 +0,0 @@
1
- <%= stylesheet_link_tag 'solidstats/components/gem_metadata' %>
2
- <%= javascript_include_tag 'solidstats/gem_metadata' %>
3
-
4
- <%# Enhanced Gem Metadata Index with Modern UI/UX %>
5
- <div class="gem-metadata-index">
6
- <!-- Page Header -->
7
- <div class="page-header">
8
- <div class="header-content">
9
- <div class="header-title-section">
10
- <h1 class="page-title">
11
- <span class="page-icon">💎</span>
12
- Gem Dependencies
13
- </h1>
14
- <div class="page-subtitle">
15
- Complete overview of your project's gem dependencies
16
- </div>
17
- </div>
18
- <div class="header-actions">
19
- <%= button_to refresh_gem_metadata_path,
20
- method: :post,
21
- class: "action-btn refresh-btn",
22
- title: "Refresh gem metadata",
23
- form: { style: "display: inline-block;" },
24
- data: { confirm: 'This will fetch the latest gem information. Continue?' } do %>
25
- <i class="fas fa-sync-alt"></i>
26
- <span class="btn-text">Refresh All</span>
27
- <% end %>
28
- </div>
29
- </div>
30
- </div>
31
-
32
- <!-- Stats Overview -->
33
- <div class="stats-overview">
34
- <% total_gems = @gems.size %>
35
- <% outdated_gems = @gems.count { |gem| gem.current_version && gem.version && gem.version != gem.current_version } %>
36
- <% up_to_date_gems = @gems.count { |gem| gem.current_version && gem.version && gem.version == gem.current_version } %>
37
- <% unavailable_gems = @gems.count { |gem| gem.info == '(API unavailable)' } %>
38
-
39
- <div class="stat-card total">
40
- <div class="stat-icon">📦</div>
41
- <div class="stat-content">
42
- <div class="stat-number"><%= total_gems %></div>
43
- <div class="stat-label">Total Gems</div>
44
- </div>
45
- </div>
46
-
47
- <div class="stat-card outdated">
48
- <div class="stat-icon">⚠️</div>
49
- <div class="stat-content">
50
- <div class="stat-number"><%= outdated_gems %></div>
51
- <div class="stat-label">Need Updates</div>
52
- </div>
53
- </div>
54
-
55
- <div class="stat-card up-to-date">
56
- <div class="stat-icon">✅</div>
57
- <div class="stat-content">
58
- <div class="stat-number"><%= up_to_date_gems %></div>
59
- <div class="stat-label">Up to Date</div>
60
- </div>
61
- </div>
62
-
63
- <div class="stat-card unavailable">
64
- <div class="stat-icon">❓</div>
65
- <div class="stat-content">
66
- <div class="stat-number"><%= unavailable_gems %></div>
67
- <div class="stat-label">Unavailable</div>
68
- </div>
69
- </div>
70
- </div>
71
-
72
- <!-- Search and Filters -->
73
- <div class="search-filters">
74
- <div class="search-section">
75
- <div class="search-input-wrapper">
76
- <i class="fas fa-search search-icon"></i>
77
- <input type="search"
78
- class="search-input"
79
- id="gem-search"
80
- placeholder="Search gems by name..."
81
- aria-label="Search gems">
82
- <button class="clear-search" id="clear-search" style="display: none;">
83
- <i class="fas fa-times"></i>
84
- </button>
85
- </div>
86
- </div>
87
-
88
- <div class="filters-section">
89
- <div class="filter-group">
90
- <label class="filter-label">Status:</label>
91
- <select class="filter-select" id="status-filter">
92
- <option value="">All</option>
93
- <option value="outdated">Need Updates</option>
94
- <option value="up-to-date">Up to Date</option>
95
- <option value="unavailable">Unavailable</option>
96
- </select>
97
- </div>
98
-
99
- <div class="filter-group">
100
- <label class="filter-label">Sort by:</label>
101
- <select class="filter-select" id="sort-filter">
102
- <option value="name-asc">Name (A-Z)</option>
103
- <option value="name-desc">Name (Z-A)</option>
104
- <option value="status-desc">Status (Updates First)</option>
105
- <option value="release-desc">Release Date (Newest)</option>
106
- <option value="release-asc">Release Date (Oldest)</option>
107
- </select>
108
- </div>
109
-
110
- <div class="filter-group view-toggle-group">
111
- <label class="filter-label">View:</label>
112
- <div class="view-toggle">
113
- <button class="view-toggle-btn active" id="grid-view-btn" title="Grid View" aria-label="Switch to grid view">
114
- <i class="fas fa-th"></i>
115
- </button>
116
- <button class="view-toggle-btn" id="table-view-btn" title="Table View" aria-label="Switch to table view">
117
- <i class="fas fa-table"></i>
118
- </button>
119
- </div>
120
- </div>
121
-
122
- <div class="filter-group export-group" id="export-group" style="display: none;">
123
- <button class="export-btn" id="export-table-btn" title="Export table data to CSV">
124
- <i class="fas fa-download"></i>
125
- Export CSV
126
- </button>
127
- </div>
128
-
129
- <button class="reset-filters" id="reset-filters">
130
- <i class="fas fa-undo"></i>
131
- Reset
132
- </button>
133
- </div>
134
- </div>
135
-
136
- <!-- Loading State -->
137
- <div class="loading-overlay" id="loading-overlay" style="display: none;">
138
- <div class="loading-content">
139
- <div class="loading-spinner"></div>
140
- <div class="loading-text">Loading gem metadata...</div>
141
- </div>
142
- </div>
143
-
144
- <!-- Gems Grid -->
145
- <div class="gems-container">
146
- <% if @gems.any? %>
147
- <div class="gems-grid" id="gems-grid">
148
- <% @gems.each_with_index do |gem, index| %>
149
- <div class="gem-card-full <%= 'unavailable' if gem.info == '(API unavailable)' %>"
150
- data-gem-name="<%= gem.name.downcase %>"
151
- data-status="<%= gem.current_version && gem.version && gem.version != gem.current_version ? 'outdated' : (gem.current_version && gem.version && gem.version == gem.current_version ? 'up-to-date' : 'unavailable') %>"
152
- data-release-date="<%= gem.released&.to_i || 0 %>"
153
- style="animation-delay: <%= (index * 0.05).round(2) %>s">
154
-
155
- <div class="gem-card-header">
156
- <div class="gem-title-section">
157
- <h3 class="gem-name"><%= gem.name %></h3>
158
- <div class="gem-status-badges">
159
- <% if gem.current_version && gem.version && gem.version != gem.current_version %>
160
- <span class="status-badge upgrade-available" title="Upgrade available">
161
- <i class="fas fa-arrow-up"></i>
162
- Update Available
163
- </span>
164
- <% elsif gem.current_version && gem.version && gem.version == gem.current_version %>
165
- <span class="status-badge up-to-date" title="Up to date">
166
- <i class="fas fa-check"></i>
167
- Latest
168
- </span>
169
- <% elsif gem.info == '(API unavailable)' %>
170
- <span class="status-badge unavailable" title="API unavailable">
171
- <i class="fas fa-exclamation-triangle"></i>
172
- Unavailable
173
- </span>
174
- <% end %>
175
- </div>
176
- </div>
177
- </div>
178
-
179
- <div class="gem-card-body">
180
- <div class="versions-section">
181
- <div class="version-group">
182
- <div class="version-item">
183
- <span class="version-label">Current</span>
184
- <% if gem.current_version %>
185
- <span class="version-badge current" title="Current version">
186
- <%= gem.current_version %>
187
- </span>
188
- <% else %>
189
- <span class="version-badge unknown">N/A</span>
190
- <% end %>
191
- </div>
192
-
193
- <div class="version-item">
194
- <span class="version-label">Latest</span>
195
- <% if gem.version %>
196
- <span class="version-badge latest" title="Latest version">
197
- <%= gem.version %>
198
- </span>
199
- <% else %>
200
- <span class="version-badge unknown">N/A</span>
201
- <% end %>
202
- </div>
203
- </div>
204
- </div>
205
-
206
- <div class="gem-info-section">
207
- <div class="release-info">
208
- <i class="fas fa-calendar-alt"></i>
209
- <% if gem.released %>
210
- <span title="<%= gem.released.strftime('%Y-%m-%d %H:%M') %>">
211
- <%= time_ago_in_words(gem.released) %> ago
212
- </span>
213
- <% else %>
214
- <span>Unknown release date</span>
215
- <% end %>
216
- </div>
217
-
218
- <% if gem.info && gem.info != '(API unavailable)' %>
219
- <div class="gem-description">
220
- <i class="fas fa-info-circle"></i>
221
- <span title="<%= gem.info %>"><%= truncate(gem.info, length: 120) %></span>
222
- </div>
223
- <% end %>
224
- </div>
225
-
226
- <% if gem.runtime&.any? %>
227
- <div class="dependencies-section">
228
- <div class="deps-header">
229
- <i class="fas fa-cubes"></i>
230
- <span>Dependencies (<%= gem.runtime.size %>)</span>
231
- </div>
232
- <div class="deps-grid">
233
- <% gem.runtime.first(6).each do |dep| %>
234
- <span class="dep-badge <%= 'rails-dep' if dep['name'] == 'rails' %>"
235
- title="<%= dep['name'] %> <%= dep['requirements'] %>">
236
- <%= dep['name'] %>
237
- <span class="dep-version"><%= dep['requirements'] %></span>
238
- </span>
239
- <% end %>
240
- <% if gem.runtime.size > 6 %>
241
- <span class="dep-more"
242
- title="<%= gem.runtime.drop(6).map { |d| "#{d['name']} #{d['requirements']}" }.join(', ') %>">
243
- +<%= gem.runtime.size - 6 %> more
244
- </span>
245
- <% end %>
246
- </div>
247
- </div>
248
- <% end %>
249
- </div>
250
- </div>
251
- <% end %>
252
- </div>
253
-
254
- <!-- Table View (Hidden by default) -->
255
- <div class="gems-table-container" id="gems-table-container" style="display: none;">
256
- <div class="table-wrapper">
257
- <table class="gems-table" id="gems-table">
258
- <thead>
259
- <tr>
260
- <th class="sortable" data-sort="name">
261
- <span>Gem Name</span>
262
- <i class="fas fa-sort sort-icon"></i>
263
- </th>
264
- <th class="sortable" data-sort="status">
265
- <span>Status</span>
266
- <i class="fas fa-sort sort-icon"></i>
267
- </th>
268
- <th class="sortable" data-sort="current">
269
- <span>Current</span>
270
- <i class="fas fa-sort sort-icon"></i>
271
- </th>
272
- <th class="sortable" data-sort="latest">
273
- <span>Latest</span>
274
- <i class="fas fa-sort sort-icon"></i>
275
- </th>
276
- <th class="sortable" data-sort="released">
277
- <span>Released</span>
278
- <i class="fas fa-sort sort-icon"></i>
279
- </th>
280
- <th>Description</th>
281
- <th>Dependencies</th>
282
- </tr>
283
- </thead>
284
- <tbody id="gems-table-body">
285
- <% @gems.each do |gem| %>
286
- <tr class="gem-table-row <%= 'unavailable' if gem.info == '(API unavailable)' %>"
287
- data-gem-name="<%= gem.name.downcase %>"
288
- data-status="<%= gem.current_version && gem.version && gem.version != gem.current_version ? 'outdated' : (gem.current_version && gem.version && gem.version == gem.current_version ? 'up-to-date' : 'unavailable') %>"
289
- data-release-date="<%= gem.released&.to_i || 0 %>">
290
-
291
- <td class="gem-name-cell">
292
- <strong class="gem-name-table"><%= gem.name %></strong>
293
- </td>
294
-
295
- <td class="status-cell">
296
- <% if gem.current_version && gem.version && gem.version != gem.current_version %>
297
- <span class="status-badge-table upgrade-available" title="Upgrade available">
298
- <i class="fas fa-arrow-up"></i>
299
- Update Available
300
- </span>
301
- <% elsif gem.current_version && gem.version && gem.version == gem.current_version %>
302
- <span class="status-badge-table up-to-date" title="Up to date">
303
- <i class="fas fa-check"></i>
304
- Latest
305
- </span>
306
- <% elsif gem.info == '(API unavailable)' %>
307
- <span class="status-badge-table unavailable" title="API unavailable">
308
- <i class="fas fa-exclamation-triangle"></i>
309
- Unavailable
310
- </span>
311
- <% else %>
312
- <span class="status-badge-table unknown">
313
- Unknown
314
- </span>
315
- <% end %>
316
- </td>
317
-
318
- <td class="version-cell">
319
- <% if gem.current_version %>
320
- <span class="version-badge-table current" title="Current version">
321
- <%= gem.current_version %>
322
- </span>
323
- <% else %>
324
- <span class="version-badge-table unknown">N/A</span>
325
- <% end %>
326
- </td>
327
-
328
- <td class="version-cell">
329
- <% if gem.version %>
330
- <span class="version-badge-table latest" title="Latest version">
331
- <%= gem.version %>
332
- </span>
333
- <% else %>
334
- <span class="version-badge-table unknown">N/A</span>
335
- <% end %>
336
- </td>
337
-
338
- <td class="release-cell">
339
- <% if gem.released %>
340
- <span title="<%= gem.released.strftime('%Y-%m-%d %H:%M') %>">
341
- <%= time_ago_in_words(gem.released) %> ago
342
- </span>
343
- <% else %>
344
- <span class="text-muted">Unknown</span>
345
- <% end %>
346
- </td>
347
-
348
- <td class="description-cell">
349
- <% if gem.info && gem.info != '(API unavailable)' %>
350
- <span title="<%= gem.info %>"><%= truncate(gem.info, length: 80) %></span>
351
- <% else %>
352
- <span class="text-muted">No description available</span>
353
- <% end %>
354
- </td>
355
-
356
- <td class="dependencies-cell">
357
- <% if gem.runtime&.any? %>
358
- <div class="table-deps">
359
- <% gem.runtime.first(3).each do |dep| %>
360
- <span class="dep-badge-table <%= 'rails-dep' if dep['name'] == 'rails' %>"
361
- title="<%= dep['name'] %> <%= dep['requirements'] %>">
362
- <%= dep['name'] %>
363
- </span>
364
- <% end %>
365
- <% if gem.runtime.size > 3 %>
366
- <span class="dep-more-table"
367
- title="<%= gem.runtime.drop(3).map { |d| "#{d['name']} #{d['requirements']}" }.join(', ') %>">
368
- +<%= gem.runtime.size - 3 %>
369
- </span>
370
- <% end %>
371
- </div>
372
- <% else %>
373
- <span class="text-muted">None</span>
374
- <% end %>
375
- </td>
376
- </tr>
377
- <% end %>
378
- </tbody>
379
- </table>
380
- </div>
381
- </div>
382
- <% else %>
383
- <div class="empty-state">
384
- <div class="empty-icon">🔍</div>
385
- <div class="empty-title">No Gem Data Found</div>
386
- <div class="empty-description">
387
- It looks like we couldn't find any gem metadata. This could happen if your Gemfile.lock is missing or the API is unavailable.
388
- </div>
389
- <div class="empty-actions">
390
- <%= button_to refresh_gem_metadata_path,
391
- method: :post,
392
- class: "action-btn refresh-btn primary",
393
- form: { style: "display: inline-block;" } do %>
394
- <i class="fas fa-sync-alt"></i>
395
- Try Refreshing
396
- <% end %>
397
- </div>
398
- </div>
399
- <% end %>
400
- </div>
401
-
402
- <!-- Footer -->
403
- <div class="page-footer">
404
- <div class="footer-content">
405
- <div class="footer-links">
406
- <%= link_to "https://railsbump.org",
407
- class: "footer-link external",
408
- target: "_blank",
409
- rel: "noopener" do %>
410
- <i class="fas fa-external-link-alt"></i>
411
- Run full Rails compatibility scan on RailsBump
412
- <% end %>
413
- </div>
414
- <div class="footer-stats">
415
- Last updated: <span id="last-updated">just now</span>
416
- </div>
417
- </div>
418
- </div>
419
- </div>