solidstats 2.0.0 → 3.0.0
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 +4 -4
- data/CHANGELOG.md +12 -63
- data/README.md +27 -0
- data/Rakefile +3 -3
- data/app/assets/javascripts/solidstats/dashboard.js +0 -46
- data/app/assets/stylesheets/solidstats/dashboard.css +48 -0
- data/app/controllers/solidstats/dashboard_controller.rb +73 -61
- data/app/controllers/solidstats/logs_controller.rb +72 -0
- data/app/controllers/solidstats/performance_controller.rb +25 -0
- data/app/controllers/solidstats/productivity_controller.rb +39 -0
- data/app/controllers/solidstats/quality_controller.rb +152 -0
- data/app/controllers/solidstats/securities_controller.rb +30 -0
- data/app/helpers/solidstats/application_helper.rb +124 -11
- data/app/helpers/solidstats/performance_helper.rb +87 -0
- data/app/helpers/solidstats/productivity_helper.rb +38 -0
- data/app/services/solidstats/bundler_audit_service.rb +206 -0
- data/app/services/solidstats/coverage_compass_service.rb +335 -0
- data/app/services/solidstats/load_lens_service.rb +474 -0
- data/app/services/solidstats/log_size_monitor_service.rb +197 -66
- data/app/services/solidstats/my_todo_service.rb +242 -0
- data/app/services/solidstats/style_patrol_service.rb +319 -0
- data/app/views/layouts/solidstats/application.html.erb +8 -2
- data/app/views/layouts/solidstats/dashboard.html.erb +84 -0
- data/app/views/solidstats/dashboard/dashboard.html.erb +39 -0
- data/app/views/solidstats/logs/logs_size.html.erb +409 -0
- data/app/views/solidstats/performance/load_lens.html.erb +158 -0
- data/app/views/solidstats/productivity/_todo_list.html.erb +49 -0
- data/app/views/solidstats/productivity/my_todos.html.erb +84 -0
- data/app/views/solidstats/quality/coverage_compass.html.erb +420 -0
- data/app/views/solidstats/quality/style_patrol.html.erb +463 -0
- data/app/views/solidstats/securities/bundler_audit.html.erb +345 -0
- data/app/views/solidstats/shared/_dashboard_card.html.erb +160 -0
- data/app/views/solidstats/shared/_quick_actions.html.erb +26 -0
- data/config/routes.rb +31 -6
- data/lib/generators/solidstats/clean/clean_generator.rb +24 -0
- data/lib/generators/solidstats/clean/templates/README +8 -0
- data/lib/generators/solidstats/install/install_generator.rb +51 -10
- data/lib/generators/solidstats/install/templates/README +7 -0
- data/lib/solidstats/engine.rb +6 -71
- data/lib/solidstats/version.rb +1 -1
- data/lib/solidstats.rb +19 -303
- data/lib/tasks/solidstats.rake +67 -0
- data/lib/tasks/solidstats_performance.rake +61 -0
- data/lib/tasks/solidstats_tasks.rake +16 -4
- metadata +33 -95
- data/app/assets/javascripts/solidstats/gem_metadata.js +0 -554
- data/app/assets/stylesheets/solidstats/components/action_button.css +0 -99
- data/app/assets/stylesheets/solidstats/components/dashboard.css +0 -151
- data/app/assets/stylesheets/solidstats/components/dashboard_header.css +0 -93
- data/app/assets/stylesheets/solidstats/components/dashboard_layout.css +0 -97
- data/app/assets/stylesheets/solidstats/components/gem_metadata.css +0 -1403
- data/app/assets/stylesheets/solidstats/components/navigation.css +0 -80
- data/app/assets/stylesheets/solidstats/components/quick_navigation.css +0 -54
- data/app/assets/stylesheets/solidstats/components/security.css +0 -332
- data/app/assets/stylesheets/solidstats/components/status_badge.css +0 -58
- data/app/assets/stylesheets/solidstats/components/summary_card.css +0 -66
- data/app/assets/stylesheets/solidstats/components/tab_navigation.css +0 -95
- data/app/components/solidstats/base_component.rb +0 -88
- data/app/components/solidstats/code_quality/code_quality_section_component.html.erb +0 -0
- data/app/components/solidstats/code_quality/code_quality_section_component.rb +0 -0
- data/app/components/solidstats/code_quality/section_component.html.erb +0 -45
- data/app/components/solidstats/code_quality/section_component.rb +0 -34
- data/app/components/solidstats/dashboard_header_component.html.erb +0 -39
- data/app/components/solidstats/dashboard_header_component.rb +0 -33
- data/app/components/solidstats/previews/action_button_component_preview/button_vs_link.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/sizes.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/variants.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview/with_icons.html.erb +0 -6
- data/app/components/solidstats/previews/action_button_component_preview.rb +0 -64
- data/app/components/solidstats/previews/navigation_component_preview.rb +0 -74
- data/app/components/solidstats/previews/stats_overview_component_preview.rb +0 -100
- data/app/components/solidstats/previews/status_badge_component_preview/sizes.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview/statuses.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview/with_icons.html.erb +0 -6
- data/app/components/solidstats/previews/status_badge_component_preview.rb +0 -49
- data/app/components/solidstats/previews/summary_card_component_preview/clickable.html.erb +0 -9
- data/app/components/solidstats/previews/summary_card_component_preview/dashboard_layout.html.erb +0 -9
- data/app/components/solidstats/previews/summary_card_component_preview/statuses.html.erb +0 -6
- data/app/components/solidstats/previews/summary_card_component_preview/value_formats.html.erb +0 -6
- data/app/components/solidstats/previews/summary_card_component_preview.rb +0 -67
- data/app/components/solidstats/quick_navigation_component.html.erb +0 -8
- data/app/components/solidstats/quick_navigation_component.rb +0 -21
- data/app/components/solidstats/security/gem_impact_analysis_component.html.erb +0 -44
- data/app/components/solidstats/security/gem_impact_analysis_component.rb +0 -45
- data/app/components/solidstats/security/overview_component.html.erb +0 -21
- data/app/components/solidstats/security/overview_component.rb +0 -104
- data/app/components/solidstats/security/section_component.html.erb +0 -26
- data/app/components/solidstats/security/section_component.rb +0 -52
- data/app/components/solidstats/security/timeline_component.html.erb +0 -39
- data/app/components/solidstats/security/timeline_component.rb +0 -43
- data/app/components/solidstats/tasks_section_component.html.erb +0 -17
- data/app/components/solidstats/tasks_section_component.rb +0 -22
- data/app/components/solidstats/ui/action_button_component.html.erb +0 -6
- data/app/components/solidstats/ui/action_button_component.rb +0 -71
- data/app/components/solidstats/ui/dashboard_layout_component.html.erb +0 -19
- data/app/components/solidstats/ui/dashboard_layout_component.rb +0 -85
- data/app/components/solidstats/ui/navigation_component.html.erb +0 -34
- data/app/components/solidstats/ui/navigation_component.rb +0 -72
- data/app/components/solidstats/ui/stats_overview_component.html.erb +0 -14
- data/app/components/solidstats/ui/stats_overview_component.rb +0 -78
- data/app/components/solidstats/ui/status_badge_component.html.erb +0 -6
- data/app/components/solidstats/ui/status_badge_component.rb +0 -42
- data/app/components/solidstats/ui/summary_card_component.html.erb +0 -12
- data/app/components/solidstats/ui/summary_card_component.rb +0 -63
- data/app/components/solidstats/ui/tab_navigation_component.html.erb +0 -22
- data/app/components/solidstats/ui/tab_navigation_component.rb +0 -79
- data/app/services/solidstats/audit_service.rb +0 -56
- data/app/services/solidstats/data_collector_service.rb +0 -83
- data/app/services/solidstats/gem_metadata/fetcher_service.rb +0 -136
- data/app/services/solidstats/todo_service.rb +0 -114
- data/app/views/solidstats/dashboard/_log_monitor.html.erb +0 -759
- data/app/views/solidstats/dashboard/_todos.html.erb +0 -151
- data/app/views/solidstats/dashboard/audit/_additional_styles.css +0 -22
- data/app/views/solidstats/dashboard/audit/_audit_badge.html.erb +0 -5
- data/app/views/solidstats/dashboard/audit/_audit_details.html.erb +0 -495
- data/app/views/solidstats/dashboard/audit/_audit_summary.html.erb +0 -26
- data/app/views/solidstats/dashboard/audit/_no_vulnerabilities.html.erb +0 -3
- data/app/views/solidstats/dashboard/audit/_security_audit.html.erb +0 -14
- data/app/views/solidstats/dashboard/audit/_vulnerabilities_table.html.erb +0 -1120
- data/app/views/solidstats/dashboard/audit/_vulnerability_details.html.erb +0 -63
- data/app/views/solidstats/dashboard/index.html.erb +0 -81
- data/app/views/solidstats/gem_metadata/_panel.html.erb +0 -419
- data/lib/generators/solidstats/feature/feature_generator.rb +0 -170
- data/lib/generators/solidstats/feature/templates/component.html.erb +0 -84
- data/lib/generators/solidstats/feature/templates/component.rb.erb +0 -103
- data/lib/generators/solidstats/feature/templates/component.scss +0 -243
- data/lib/generators/solidstats/feature/templates/component_test.rb.erb +0 -183
- data/lib/generators/solidstats/feature/templates/controller.rb.erb +0 -44
- data/lib/generators/solidstats/feature/templates/controller_test.rb.erb +0 -111
- data/lib/generators/solidstats/feature/templates/detail_view.html.erb +0 -755
- data/lib/generators/solidstats/feature/templates/preview.rb.erb +0 -107
- data/lib/generators/solidstats/feature/templates/service.rb.erb +0 -132
- data/lib/generators/solidstats/feature/templates/service_test.rb.erb +0 -109
- data/lib/generators/solidstats/install_generator.rb +0 -109
- data/lib/tasks/solidstats_install.rake +0 -133
@@ -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>
|