summaryrefslogtreecommitdiff
path: root/app/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/components')
-rw-r--r--app/components/diffs/base_component.rb10
-rw-r--r--app/components/diffs/overflow_warning_component.html.haml9
-rw-r--r--app/components/diffs/overflow_warning_component.rb73
-rw-r--r--app/components/diffs/stats_component.html.haml1
-rw-r--r--app/components/diffs/stats_component.rb67
-rw-r--r--app/components/pajamas/alert_component.html.haml13
-rw-r--r--app/components/pajamas/alert_component.rb45
7 files changed, 218 insertions, 0 deletions
diff --git a/app/components/diffs/base_component.rb b/app/components/diffs/base_component.rb
new file mode 100644
index 00000000000..9e1347d1e84
--- /dev/null
+++ b/app/components/diffs/base_component.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Diffs
+ class BaseComponent < ViewComponent::Base
+ # To make converting the partials to components easier,
+ # we delegate all missing methods to the helpers,
+ # where they probably are.
+ delegate_missing_to :helpers
+ end
+end
diff --git a/app/components/diffs/overflow_warning_component.html.haml b/app/components/diffs/overflow_warning_component.html.haml
new file mode 100644
index 00000000000..907d066e73d
--- /dev/null
+++ b/app/components/diffs/overflow_warning_component.html.haml
@@ -0,0 +1,9 @@
+= render Pajamas::AlertComponent.new(title: _('Too many changes to show.'),
+ variant: :warning,
+ alert_class: 'gl-mb-5') do
+ .gl-alert-body
+ = message
+
+ .gl-alert-actions
+ = diff_link
+ = patch_link
diff --git a/app/components/diffs/overflow_warning_component.rb b/app/components/diffs/overflow_warning_component.rb
new file mode 100644
index 00000000000..0d0e225beb4
--- /dev/null
+++ b/app/components/diffs/overflow_warning_component.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Diffs
+ class OverflowWarningComponent < BaseComponent
+ # Skipping coverage because of https://gitlab.com/gitlab-org/gitlab/-/issues/357381
+ #
+ # This is fully tested by the output in the view part of this component,
+ # but undercoverage doesn't understand the relationship between the two parts.
+ #
+ # :nocov:
+ def initialize(diffs:, diff_files:, project:, commit: nil, merge_request: nil)
+ @diffs = diffs
+ @diff_files = diff_files
+ @project = project
+ @commit = commit
+ @merge_request = merge_request
+ end
+
+ def message
+ html_escape(message_text) % {
+ display_size: @diff_files.size,
+ real_size: @diffs.real_size,
+ strong_open: '<strong>'.html_safe,
+ strong_close: '</strong>'.html_safe
+ }
+ end
+
+ def diff_link
+ text = _("Plain diff")
+
+ if commit?
+ link_to text, project_commit_path(@project, @commit, format: :diff), class: button_classes
+ elsif merge_request?
+ link_to text, merge_request_path(@merge_request, format: :diff), class: button_classes
+ end
+ end
+
+ def patch_link
+ text = _("Email patch")
+
+ if commit?
+ link_to text, project_commit_path(@project, @commit, format: :patch), class: button_classes
+ elsif merge_request?
+ link_to text, merge_request_path(@merge_request, format: :patch), class: button_classes
+ end
+ end
+
+ private
+
+ def commit?
+ current_controller?(:commit) &&
+ @commit.present?
+ end
+
+ def merge_request?
+ current_controller?("projects/merge_requests/diffs") &&
+ @merge_request.present? &&
+ @merge_request.persisted?
+ end
+
+ def message_text
+ _(
+ "To preserve performance only %{strong_open}%{display_size} " \
+ "of %{real_size}%{strong_close} files are displayed."
+ )
+ end
+
+ def button_classes
+ "btn gl-alert-action btn-default gl-button btn-default-secondary"
+ end
+ # :nocov:
+ end
+end
diff --git a/app/components/diffs/stats_component.html.haml b/app/components/diffs/stats_component.html.haml
new file mode 100644
index 00000000000..c0e816639a7
--- /dev/null
+++ b/app/components/diffs/stats_component.html.haml
@@ -0,0 +1 @@
+.js-diff-stats-dropdown{ data: { changed: @changed, added: @added, deleted: @removed, files: diff_files_data } }
diff --git a/app/components/diffs/stats_component.rb b/app/components/diffs/stats_component.rb
new file mode 100644
index 00000000000..55589c7b015
--- /dev/null
+++ b/app/components/diffs/stats_component.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Diffs
+ class StatsComponent < BaseComponent
+ attr_reader :diff_files
+
+ def initialize(diff_files:)
+ @diff_files = diff_files
+ @changed ||= diff_files.size
+ @added ||= diff_files.sum(&:added_lines)
+ @removed ||= diff_files.sum(&:removed_lines)
+ end
+
+ def diff_files_data
+ diffs_map = @diff_files.map do |f|
+ {
+ href: "##{helpers.hexdigest(f.file_path)}",
+ title: f.new_path,
+ name: f.file_path,
+ path: diff_file_path_text(f),
+ icon: diff_file_changed_icon(f),
+ iconColor: "#{diff_file_changed_icon_color(f)}",
+ added: f.added_lines,
+ removed: f.removed_lines
+ }
+ end
+
+ Gitlab::Json.dump(diffs_map)
+ end
+
+ # Disabled undercoverage reports for this method
+ # as it returns a false positive on the last line,
+ # which is covered in the tests
+ #
+ # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/357381
+ #
+ # :nocov:
+ def diff_file_path_text(diff_file, max: 60)
+ path = diff_file.new_path
+
+ return path unless path.size > max && max > 3
+
+ "...#{path[-(max - 3)..]}"
+ end
+ # :nocov:
+
+ private
+
+ def diff_file_changed_icon(diff_file)
+ if diff_file.deleted_file?
+ "file-deletion"
+ elsif diff_file.new_file?
+ "file-addition"
+ else
+ "file-modified"
+ end
+ end
+
+ def diff_file_changed_icon_color(diff_file)
+ if diff_file.deleted_file?
+ "danger"
+ elsif diff_file.new_file?
+ "success"
+ end
+ end
+ end
+end
diff --git a/app/components/pajamas/alert_component.html.haml b/app/components/pajamas/alert_component.html.haml
new file mode 100644
index 00000000000..a1d3c700e57
--- /dev/null
+++ b/app/components/pajamas/alert_component.html.haml
@@ -0,0 +1,13 @@
+.gl-alert{ role: 'alert', class: ["gl-alert-#{@variant}", @alert_class], data: @alert_data }
+ = sprite_icon(icon, css_class: icon_classes)
+ - if @dismissible
+ %button.btn.gl-dismiss-btn.btn-default.btn-sm.gl-button.btn-default-tertiary.btn-icon.js-close{ type: 'button',
+ aria: { label: _('Dismiss') },
+ class: @close_button_class,
+ data: @close_button_data }
+ = sprite_icon('close')
+ .gl-alert-content{ role: 'alert' }
+ - if @title
+ %h4.gl-alert-title
+ = @title
+ = content
diff --git a/app/components/pajamas/alert_component.rb b/app/components/pajamas/alert_component.rb
new file mode 100644
index 00000000000..4bb6c41661b
--- /dev/null
+++ b/app/components/pajamas/alert_component.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+# Renders a GlAlert root element
+module Pajamas
+ class AlertComponent < Pajamas::Component
+ # @param [String] title
+ # @param [Symbol] variant
+ # @param [Boolean] dismissible
+ # @param [String] alert_class
+ # @param [Hash] alert_data
+ # @param [String] close_button_class
+ # @param [Hash] close_button_data
+ def initialize(
+ title: nil, variant: :info, dismissible: true,
+ alert_class: nil, alert_data: {}, close_button_class: nil, close_button_data: {})
+ @title = title
+ @variant = variant
+ @dismissible = dismissible
+ @alert_class = alert_class
+ @alert_data = alert_data
+ @close_button_class = close_button_class
+ @close_button_data = close_button_data
+ end
+
+ private
+
+ delegate :sprite_icon, to: :helpers
+
+ ICONS = {
+ info: 'information-o',
+ warning: 'warning',
+ success: 'check-circle',
+ danger: 'error',
+ tip: 'bulb'
+ }.freeze
+
+ def icon
+ ICONS[@variant]
+ end
+
+ def icon_classes
+ "gl-alert-icon#{' gl-alert-icon-no-title' if @title.nil?}"
+ end
+ end
+end