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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -63
- data/README.md +27 -33
- data/Rakefile +3 -3
- data/app/assets/stylesheets/solidstats/application.css +1 -6
- data/app/assets/stylesheets/solidstats/dashboard.css +48 -0
- data/app/controllers/solidstats/dashboard_controller.rb +81 -62
- 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 +454 -0
- data/app/services/solidstats/log_size_monitor_service.rb +207 -76
- 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 +32 -7
- data/lib/generators/solidstats/install/install_generator.rb +28 -2
- data/lib/generators/solidstats/install/templates/README +7 -0
- data/lib/solidstats/engine.rb +9 -114
- data/lib/solidstats/version.rb +1 -1
- data/lib/solidstats.rb +2 -299
- data/lib/tasks/solidstats_install.rake +2 -122
- data/lib/tasks/solidstats_performance.rake +84 -0
- metadata +32 -103
- data/app/assets/javascripts/solidstats/application.js +0 -257
- data/app/assets/javascripts/solidstats/dashboard.js +0 -225
- 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/controllers/solidstats/gem_metadata_controller.rb +0 -12
- 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/generators/solidstats/templates/initializer.rb +0 -112
- data/lib/solidstats/asset_compatibility.rb +0 -238
- data/lib/solidstats/asset_manifest.rb +0 -205
- data/lib/tasks/solidstats_tasks.rake +0 -4
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Previews
|
5
|
-
# Preview for SummaryCardComponent
|
6
|
-
class SummaryCardComponentPreview < ViewComponent::Preview
|
7
|
-
# Default summary card
|
8
|
-
def default
|
9
|
-
render(Solidstats::Ui::SummaryCardComponent.new(
|
10
|
-
title: "Total Gems",
|
11
|
-
value: 127,
|
12
|
-
status: :ok
|
13
|
-
))
|
14
|
-
end
|
15
|
-
|
16
|
-
# Different statuses
|
17
|
-
def statuses
|
18
|
-
render_with_template(locals: {
|
19
|
-
cards: [
|
20
|
-
{ title: "Secure Gems", value: 95, status: :ok, icon: "🔒" },
|
21
|
-
{ title: "Minor Issues", value: 12, status: :warning, icon: "⚠" },
|
22
|
-
{ title: "Vulnerabilities", value: 3, status: :error, icon: "🚨" },
|
23
|
-
{ title: "Outdated", value: 8, status: :info, icon: "📅" },
|
24
|
-
{ title: "Critical Issues", value: 1, status: :critical, icon: "💥" }
|
25
|
-
]
|
26
|
-
})
|
27
|
-
end
|
28
|
-
|
29
|
-
# Clickable cards
|
30
|
-
def clickable
|
31
|
-
render_with_template(locals: {
|
32
|
-
cards: [
|
33
|
-
{ title: "Security Issues", value: 3, status: :error, href: "/security", section: "security" },
|
34
|
-
{ title: "Code Quality", value: 85, status: :ok, href: "/quality", section: "quality" },
|
35
|
-
{ title: "Dependencies", value: 127, status: :warning, href: "/deps", section: "dependencies" }
|
36
|
-
]
|
37
|
-
})
|
38
|
-
end
|
39
|
-
|
40
|
-
# With different value formats
|
41
|
-
def value_formats
|
42
|
-
render_with_template(locals: {
|
43
|
-
cards: [
|
44
|
-
{ title: "Lines of Code", value: 15420, status: :info },
|
45
|
-
{ title: "Test Coverage", value: "92%", status: :ok },
|
46
|
-
{ title: "Build Time", value: "2.3s", status: :ok },
|
47
|
-
{ title: "Bundle Size", value: "1.2MB", status: :warning }
|
48
|
-
]
|
49
|
-
})
|
50
|
-
end
|
51
|
-
|
52
|
-
# Dashboard layout example
|
53
|
-
def dashboard_layout
|
54
|
-
render_with_template(locals: {
|
55
|
-
metrics: [
|
56
|
-
{ title: "Total Gems", value: 127, status: :ok, icon: "💎" },
|
57
|
-
{ title: "Vulnerabilities", value: 0, status: :ok, icon: "🔒" },
|
58
|
-
{ title: "Outdated", value: 8, status: :warning, icon: "📅" },
|
59
|
-
{ title: "Code Quality", value: "A+", status: :ok, icon: "⭐" },
|
60
|
-
{ title: "Test Coverage", value: "94%", status: :ok, icon: "🧪" },
|
61
|
-
{ title: "Build Status", value: "Passing", status: :ok, icon: "✅" }
|
62
|
-
]
|
63
|
-
})
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
class QuickNavigationComponent < BaseComponent
|
5
|
-
def initialize
|
6
|
-
super()
|
7
|
-
end
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
def navigation_items
|
12
|
-
[
|
13
|
-
{ href: "#overview", label: "Overview" },
|
14
|
-
{ href: "#security", label: "Security" },
|
15
|
-
{ href: "#code-quality", label: "Code Quality" },
|
16
|
-
{ href: "#gem-metadata", label: "Gem Metadata" },
|
17
|
-
{ href: "#tasks", label: "Tasks" }
|
18
|
-
]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
<div class="gem-impact-analysis">
|
2
|
-
<h3>Gem Impact Analysis</h3>
|
3
|
-
<% if has_affected_gems? %>
|
4
|
-
<div class="gems-container">
|
5
|
-
<% affected_gems.each do |gem| %>
|
6
|
-
<div class="gem-card <%= gem[:severity_class] %>">
|
7
|
-
<div class="gem-header">
|
8
|
-
<div class="gem-name"><%= gem[:name] %></div>
|
9
|
-
<div class="gem-severity <%= gem[:severity] %>"><%= gem[:severity].capitalize %></div>
|
10
|
-
</div>
|
11
|
-
<div class="gem-details">
|
12
|
-
<div class="gem-versions">
|
13
|
-
<div class="current-version">
|
14
|
-
<span class="version-label">Current:</span>
|
15
|
-
<span class="version-value"><%= gem[:current_version] %></span>
|
16
|
-
</div>
|
17
|
-
<div class="target-version">
|
18
|
-
<span class="version-label">Target:</span>
|
19
|
-
<span class="version-value"><%= gem[:target_version] %></span>
|
20
|
-
</div>
|
21
|
-
</div>
|
22
|
-
<div class="gem-vulnerabilities-count">
|
23
|
-
<%= gem[:vulnerability_count] %> <%= "vulnerability".pluralize(gem[:vulnerability_count]) %> found
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
<div class="gem-actions">
|
27
|
-
<%= render Solidstats::Ui::ActionButtonComponent.new(
|
28
|
-
text: "Update Gem",
|
29
|
-
icon: "↑",
|
30
|
-
variant: :primary,
|
31
|
-
size: :sm
|
32
|
-
) %>
|
33
|
-
</div>
|
34
|
-
</div>
|
35
|
-
<% end %>
|
36
|
-
</div>
|
37
|
-
<% else %>
|
38
|
-
<div class="empty-state">
|
39
|
-
<div class="empty-icon">✅</div>
|
40
|
-
<div class="empty-message">No vulnerable gems found</div>
|
41
|
-
<div class="empty-description">Your application is secure. Keep up with regular security audits!</div>
|
42
|
-
</div>
|
43
|
-
<% end %>
|
44
|
-
</div>
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Security
|
5
|
-
class GemImpactAnalysisComponent < BaseComponent
|
6
|
-
def initialize(results:)
|
7
|
-
@results = results
|
8
|
-
super()
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
attr_reader :results
|
14
|
-
|
15
|
-
def affected_gems
|
16
|
-
return [] unless results.any?
|
17
|
-
|
18
|
-
results.map { |r| r.dig("gem", "name") }.uniq.map do |gem_name|
|
19
|
-
gem_vulns = results.select { |r| r.dig("gem", "name") == gem_name }
|
20
|
-
highest_severity = calculate_highest_severity(gem_vulns)
|
21
|
-
|
22
|
-
{
|
23
|
-
name: gem_name,
|
24
|
-
vulnerabilities: gem_vulns,
|
25
|
-
vulnerability_count: gem_vulns.size,
|
26
|
-
current_version: gem_vulns.first.dig("gem", "version") || "Unknown",
|
27
|
-
target_version: gem_vulns.first.dig("advisory", "patched_versions")&.first || "N/A",
|
28
|
-
severity: highest_severity,
|
29
|
-
severity_class: "severity-#{highest_severity}"
|
30
|
-
}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def calculate_highest_severity(gem_vulns)
|
35
|
-
severities = gem_vulns.map { |v| v.dig("advisory", "criticality").to_s.downcase }
|
36
|
-
valid_severities = severities.select { |s| %w[critical high medium low].include?(s) }
|
37
|
-
valid_severities.min_by { |s| %w[critical high medium low].index(s) || 999 } || "unknown"
|
38
|
-
end
|
39
|
-
|
40
|
-
def has_affected_gems?
|
41
|
-
results.any?
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
<%# filepath: /Users/mezbah/microstartup/infolily_organizer/gems/solidstats/security/security_overview_component.html.erb %>
|
2
|
-
<%= tag.div(**overview_attributes) do %>
|
3
|
-
<%= tag.div(class: score_container_classes) do %>
|
4
|
-
<%= tag.div(class: score_classes) do %>
|
5
|
-
<div class="score-value"><%= security_score %></div>
|
6
|
-
<div class="score-label">Security<br>Rating</div>
|
7
|
-
<% end %>
|
8
|
-
|
9
|
-
<div class="security-metrics">
|
10
|
-
<% metrics_data.each do |metric| %>
|
11
|
-
<div class="metric-item <%= metric[:class] %>">
|
12
|
-
<div class="metric-icon"><%= metric[:icon] %></div>
|
13
|
-
<div class="metric-data">
|
14
|
-
<div class="metric-value"><%= metric[:value] %></div>
|
15
|
-
<div class="metric-label"><%= metric[:label] %></div>
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
<% end %>
|
19
|
-
</div>
|
20
|
-
<% end %>
|
21
|
-
<% end %>
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Security
|
5
|
-
# Security overview component showing security score and key metrics
|
6
|
-
class OverviewComponent < Solidstats::BaseComponent
|
7
|
-
def initialize(vulnerabilities: [], **options)
|
8
|
-
@vulnerabilities = vulnerabilities
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
attr_reader :vulnerabilities, :options
|
15
|
-
|
16
|
-
def overview_classes
|
17
|
-
css_classes("security-overview", options[:class])
|
18
|
-
end
|
19
|
-
|
20
|
-
def overview_attributes
|
21
|
-
{ class: overview_classes }.merge(options.except(:class))
|
22
|
-
end
|
23
|
-
|
24
|
-
def vulnerabilities_count
|
25
|
-
vulnerabilities.size
|
26
|
-
end
|
27
|
-
|
28
|
-
def high_severity_count
|
29
|
-
vulnerabilities.count do |vuln|
|
30
|
-
severity = vuln.dig("advisory", "criticality").to_s.downcase
|
31
|
-
%w[high critical].include?(severity)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def affected_gems_count
|
36
|
-
vulnerabilities.map { |vuln| vuln.dig("gem", "name") }.uniq.size
|
37
|
-
end
|
38
|
-
|
39
|
-
def security_score
|
40
|
-
if vulnerabilities_count == 0
|
41
|
-
"A+"
|
42
|
-
elsif high_severity_count > 0
|
43
|
-
"C"
|
44
|
-
else
|
45
|
-
"B"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def security_score_class
|
50
|
-
if vulnerabilities_count == 0
|
51
|
-
"score-excellent"
|
52
|
-
elsif high_severity_count > 0
|
53
|
-
"score-critical"
|
54
|
-
else
|
55
|
-
"score-warning"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def score_container_classes
|
60
|
-
css_classes("security-score-container")
|
61
|
-
end
|
62
|
-
|
63
|
-
def score_classes
|
64
|
-
css_classes("security-score", security_score_class)
|
65
|
-
end
|
66
|
-
|
67
|
-
def metric_class(count, type = :warning)
|
68
|
-
return "" if count == 0
|
69
|
-
|
70
|
-
case type
|
71
|
-
when :critical
|
72
|
-
"metric-critical"
|
73
|
-
when :warning
|
74
|
-
"metric-warning"
|
75
|
-
else
|
76
|
-
""
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def metrics_data
|
81
|
-
[
|
82
|
-
{
|
83
|
-
icon: "⚠️",
|
84
|
-
value: high_severity_count,
|
85
|
-
label: "Critical Issues",
|
86
|
-
class: metric_class(high_severity_count, :critical)
|
87
|
-
},
|
88
|
-
{
|
89
|
-
icon: "🔍",
|
90
|
-
value: vulnerabilities_count,
|
91
|
-
label: "Total Vulnerabilities",
|
92
|
-
class: metric_class(vulnerabilities_count, :warning)
|
93
|
-
},
|
94
|
-
{
|
95
|
-
icon: "💎",
|
96
|
-
value: affected_gems_count,
|
97
|
-
label: "Affected Gems",
|
98
|
-
class: metric_class(affected_gems_count, :warning)
|
99
|
-
}
|
100
|
-
]
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
<section id="security" class="dashboard-section">
|
2
|
-
<h2 class="section-title">Security</h2>
|
3
|
-
|
4
|
-
<%= render Solidstats::Security::OverviewComponent.new(
|
5
|
-
vulnerabilities: results
|
6
|
-
) %>
|
7
|
-
|
8
|
-
<%= render Solidstats::Ui::TabNavigationComponent.new(
|
9
|
-
container_class: "security-tabs",
|
10
|
-
tabs: tab_items
|
11
|
-
) %>
|
12
|
-
|
13
|
-
<div class="tabs-content">
|
14
|
-
<div class="tab-content active" id="security-overview">
|
15
|
-
<%= render partial: 'solidstats/dashboard/audit/security_audit', locals: { results: results } %>
|
16
|
-
</div>
|
17
|
-
|
18
|
-
<div class="tab-content" id="security-gems">
|
19
|
-
<%= render Solidstats::Security::GemImpactAnalysisComponent.new(results: results) %>
|
20
|
-
</div>
|
21
|
-
|
22
|
-
<div class="tab-content" id="security-timeline">
|
23
|
-
<%= render Solidstats::Security::TimelineComponent.new %>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
</section>
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Security
|
5
|
-
class SectionComponent < BaseComponent
|
6
|
-
def initialize(audit_output:)
|
7
|
-
@audit_output = audit_output
|
8
|
-
super()
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
attr_reader :audit_output
|
14
|
-
|
15
|
-
def results
|
16
|
-
@results ||= audit_output.dig("results") || []
|
17
|
-
end
|
18
|
-
|
19
|
-
def vulnerabilities_count
|
20
|
-
results.size
|
21
|
-
end
|
22
|
-
|
23
|
-
def high_severity_count
|
24
|
-
results.count { |r| %w[high critical].include?(r.dig("advisory", "criticality").to_s.downcase) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def affected_gems_count
|
28
|
-
results.map { |r| r.dig("gem", "name") }.uniq.size
|
29
|
-
end
|
30
|
-
|
31
|
-
def security_rating
|
32
|
-
return "A+" if vulnerabilities_count.zero?
|
33
|
-
return "C" if high_severity_count > 0
|
34
|
-
"B"
|
35
|
-
end
|
36
|
-
|
37
|
-
def security_score_class
|
38
|
-
return "score-excellent" if vulnerabilities_count.zero?
|
39
|
-
return "score-critical" if high_severity_count > 0
|
40
|
-
"score-warning"
|
41
|
-
end
|
42
|
-
|
43
|
-
def tab_items
|
44
|
-
[
|
45
|
-
{ id: "security-overview", label: "Overview", icon: "📊", active: true },
|
46
|
-
{ id: "security-gems", label: "Affected Gems", icon: "💎" },
|
47
|
-
{ id: "security-timeline", label: "Timeline", icon: "📈" }
|
48
|
-
]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
<div class="security-timeline-container">
|
2
|
-
<h3>Security Timeline</h3>
|
3
|
-
<div class="timeline-chart-placeholder">
|
4
|
-
<div class="chart-header">
|
5
|
-
<div class="chart-title">Vulnerability History</div>
|
6
|
-
<div class="chart-legend">
|
7
|
-
<% legend_items.each do |item| %>
|
8
|
-
<div class="legend-item">
|
9
|
-
<span class="legend-color" style="background-color: <%= item[:color] %>;"></span>
|
10
|
-
<span class="legend-label"><%= item[:label] %></span>
|
11
|
-
</div>
|
12
|
-
<% end %>
|
13
|
-
</div>
|
14
|
-
</div>
|
15
|
-
<div class="chart-visualization">
|
16
|
-
<div class="chart-timeline">
|
17
|
-
<% timeline_points.each do |point| %>
|
18
|
-
<div class="timeline-point" style="left: <%= point[:position] %>;">
|
19
|
-
<div class="timeline-marker <%= point[:severity] %>"></div>
|
20
|
-
<div class="timeline-date"><%= point[:date] %></div>
|
21
|
-
</div>
|
22
|
-
<% end %>
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
<div class="timeline-insights">
|
27
|
-
<div class="insight-card">
|
28
|
-
<div class="insight-header">Key Insights</div>
|
29
|
-
<div class="insight-content">
|
30
|
-
<% insights.each do |insight| %>
|
31
|
-
<div class="insight-item">
|
32
|
-
<div class="insight-title"><%= insight[:title] %></div>
|
33
|
-
<div class="insight-description"><%= insight[:description] %></div>
|
34
|
-
</div>
|
35
|
-
<% end %>
|
36
|
-
</div>
|
37
|
-
</div>
|
38
|
-
</div>
|
39
|
-
</div>
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Security
|
5
|
-
class TimelineComponent < BaseComponent
|
6
|
-
def initialize
|
7
|
-
super()
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def timeline_points
|
13
|
-
[
|
14
|
-
{ position: "10%", severity: "critical", date: "Jan 2025" },
|
15
|
-
{ position: "30%", severity: "medium", date: "Feb 2025" },
|
16
|
-
{ position: "65%", severity: "low", date: "Apr 2025" },
|
17
|
-
{ position: "85%", severity: "critical", date: "May 2025" }
|
18
|
-
]
|
19
|
-
end
|
20
|
-
|
21
|
-
def legend_items
|
22
|
-
[
|
23
|
-
{ color: "#dc3545", label: "Critical" },
|
24
|
-
{ color: "#ffc107", label: "Medium" },
|
25
|
-
{ color: "#28a745", label: "Low" }
|
26
|
-
]
|
27
|
-
end
|
28
|
-
|
29
|
-
def insights
|
30
|
-
[
|
31
|
-
{
|
32
|
-
title: "Notable Trend",
|
33
|
-
description: "4 vulnerabilities discovered in the last 3 months."
|
34
|
-
},
|
35
|
-
{
|
36
|
-
title: "Recent Activity",
|
37
|
-
description: "Last security scan: #{Time.now.strftime('%B %d, %Y')}"
|
38
|
-
}
|
39
|
-
]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
<section id="tasks" class="dashboard-section">
|
2
|
-
<h2 class="section-title">Tasks</h2>
|
3
|
-
|
4
|
-
<%= render Solidstats::Ui::TabNavigationComponent.new(tabs: tab_items) %>
|
5
|
-
|
6
|
-
<div class="tabs-content">
|
7
|
-
<div class="tab-content active" id="todos">
|
8
|
-
<%= render partial: 'todos' %>
|
9
|
-
</div>
|
10
|
-
<div class="tab-content" id="fixmes">
|
11
|
-
<!-- FIXME specific content -->
|
12
|
-
</div>
|
13
|
-
<div class="tab-content" id="hacks">
|
14
|
-
<!-- HACK specific content -->
|
15
|
-
</div>
|
16
|
-
</div>
|
17
|
-
</section>
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
class TasksSectionComponent < BaseComponent
|
5
|
-
def initialize(todo_items: [])
|
6
|
-
@todo_items = todo_items
|
7
|
-
super()
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
attr_reader :todo_items
|
13
|
-
|
14
|
-
def tab_items
|
15
|
-
[
|
16
|
-
{ id: "todos", label: "TODO Items", active: true },
|
17
|
-
{ id: "fixmes", label: "FIXMEs" },
|
18
|
-
{ id: "hacks", label: "HACKs" }
|
19
|
-
]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solidstats
|
4
|
-
module Ui
|
5
|
-
# Reusable action button component with consistent styling
|
6
|
-
class ActionButtonComponent < Solidstats::BaseComponent
|
7
|
-
def initialize(text:, variant: :primary, size: :md, icon: nil, href: nil, **options)
|
8
|
-
@text = text
|
9
|
-
@variant = variant
|
10
|
-
@size = size
|
11
|
-
@icon = icon
|
12
|
-
@href = href
|
13
|
-
@options = options
|
14
|
-
super()
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
attr_reader :text, :variant, :size, :icon, :href, :options
|
20
|
-
|
21
|
-
def button_classes
|
22
|
-
css_classes(
|
23
|
-
"action-button",
|
24
|
-
variant_class,
|
25
|
-
size_class,
|
26
|
-
icon ? "action-button--with-icon" : nil
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
def variant_class
|
31
|
-
case variant
|
32
|
-
when :secondary
|
33
|
-
"action-button--secondary"
|
34
|
-
when :danger
|
35
|
-
"action-button--danger"
|
36
|
-
when :ghost
|
37
|
-
"action-button--ghost"
|
38
|
-
else
|
39
|
-
"action-button--primary"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def size_class
|
44
|
-
case size
|
45
|
-
when :sm
|
46
|
-
"action-button--sm"
|
47
|
-
when :lg
|
48
|
-
"action-button--lg"
|
49
|
-
else
|
50
|
-
"action-button--md"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def tag_name
|
55
|
-
href ? :a : :button
|
56
|
-
end
|
57
|
-
|
58
|
-
def tag_attributes
|
59
|
-
base_attrs = { class: button_classes }
|
60
|
-
|
61
|
-
if href
|
62
|
-
base_attrs[:href] = href
|
63
|
-
else
|
64
|
-
base_attrs[:type] = options[:type] || "button"
|
65
|
-
end
|
66
|
-
|
67
|
-
base_attrs.merge(options.except(:type))
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
<%# filepath: /Users/mezbah/microstartup/infolily_organizer/gems/solidstats/ui/dashboard_layout_component.html.erb %>
|
2
|
-
<%= tag.div(**dashboard_attributes) do %>
|
3
|
-
<%= tag.header(class: header_classes) do %>
|
4
|
-
<div class="header-main">
|
5
|
-
<h1><%= title_with_icon %></h1>
|
6
|
-
<span class="audit-date"><%= formatted_subtitle %></span>
|
7
|
-
</div>
|
8
|
-
|
9
|
-
<%= render(Solidstats::Ui::NavigationComponent.new(
|
10
|
-
current_section: current_section,
|
11
|
-
sections: navigation_sections,
|
12
|
-
actions: navigation_actions
|
13
|
-
)) %>
|
14
|
-
<% end %>
|
15
|
-
|
16
|
-
<% if content.present? %>
|
17
|
-
<%= content %>
|
18
|
-
<% end %>
|
19
|
-
<% end %>
|