Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/helpers/timeboxes_helper.rb')
-rw-r--r--app/helpers/timeboxes_helper.rb302
1 files changed, 302 insertions, 0 deletions
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
new file mode 100644
index 00000000000..0bffdba7349
--- /dev/null
+++ b/app/helpers/timeboxes_helper.rb
@@ -0,0 +1,302 @@
+# frozen_string_literal: true
+
+module TimeboxesHelper
+ include EntityDateHelper
+ include Gitlab::Utils::StrongMemoize
+
+ def milestone_status_string(milestone)
+ if milestone.closed?
+ _('Closed')
+ elsif milestone.expired?
+ _('Past due')
+ elsif milestone.upcoming?
+ _('Upcoming')
+ else
+ _('Open')
+ end
+ end
+
+ def milestones_filter_path(opts = {})
+ if @project
+ project_milestones_path(@project, opts)
+ elsif @group
+ group_milestones_path(@group, opts)
+ else
+ dashboard_milestones_path(opts)
+ end
+ end
+
+ def milestones_issues_path(opts = {})
+ if @project
+ project_issues_path(@project, opts)
+ elsif @group
+ issues_group_path(@group, opts)
+ else
+ issues_dashboard_path(opts)
+ end
+ end
+
+ def milestones_browse_issuables_path(milestone, state: nil, type:)
+ opts = { milestone_title: milestone.title, state: state }
+
+ if @project
+ polymorphic_path([@project.namespace.becomes(Namespace), @project, type], opts)
+ elsif @group
+ polymorphic_url([type, @group], opts)
+ else
+ polymorphic_url([type, :dashboard], opts)
+ end
+ end
+
+ def milestone_issues_by_label_count(milestone, label, state:)
+ issues = milestone.issues.with_label(label.title)
+ issues =
+ case state
+ when :opened
+ issues.opened
+ when :closed
+ issues.closed
+ else
+ raise ArgumentError, _("invalid milestone state `%{state}`") % { state: state }
+ end
+
+ issues.size
+ end
+
+ # Returns count of milestones for different states
+ # Uses explicit hash keys as the 'opened' state URL params differs from the db value
+ # and we need to add the total
+ # rubocop: disable CodeReuse/ActiveRecord
+ def milestone_counts(milestones)
+ counts = milestones.reorder(nil).group(:state).count
+
+ {
+ opened: counts['active'] || 0,
+ closed: counts['closed'] || 0,
+ all: counts.values.sum || 0
+ }
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # Show 'active' class if provided GET param matches check
+ # `or_blank` allows the function to return 'active' when given an empty param
+ # Could be refactored to be simpler but that may make it harder to read
+ def milestone_class_for_state(param, check, match_blank_param = false)
+ if match_blank_param
+ 'active' if param.blank? || param == check
+ elsif param == check
+ 'active'
+ else
+ check
+ end
+ end
+
+ def milestone_progress_tooltip_text(milestone)
+ has_issues = milestone.total_issues_count > 0
+
+ if has_issues
+ [
+ _('Progress'),
+ _("%{percent}%% complete") % { percent: milestone.percent_complete }
+ ].join('<br />')
+ else
+ _('Progress')
+ end
+ end
+
+ def milestone_progress_bar(milestone)
+ options = {
+ class: 'progress-bar bg-success',
+ style: "width: #{milestone.percent_complete}%;"
+ }
+
+ content_tag :div, class: 'progress' do
+ content_tag :div, nil, options
+ end
+ end
+
+ def milestones_filter_dropdown_path
+ project = @target_project || @project
+ if project
+ project_milestones_path(project, :json)
+ elsif @group
+ group_milestones_path(@group, :json)
+ else
+ dashboard_milestones_path(:json)
+ end
+ end
+
+ def milestone_time_for(date, date_type)
+ title = date_type == :start ? "Start date" : "End date"
+
+ if date
+ time_ago = time_ago_in_words(date).sub("about ", "")
+ state = if date.past?
+ "ago"
+ else
+ "remaining"
+ end
+
+ content = [
+ title,
+ "<br />",
+ date.to_s(:medium),
+ "(#{time_ago} #{state})"
+ ].join(" ")
+
+ content.html_safe
+ else
+ title
+ end
+ end
+
+ def milestone_issues_tooltip_text(milestone)
+ total = milestone.total_issues_count
+ opened = milestone.opened_issues_count
+ closed = milestone.closed_issues_count
+
+ return _("Issues") if total.zero?
+
+ content = []
+
+ if opened > 0
+ content << n_("1 open issue", "%{issues} open issues", opened) % { issues: opened }
+ end
+
+ if closed > 0
+ content << n_("1 closed issue", "%{issues} closed issues", closed) % { issues: closed }
+ end
+
+ content.join('<br />').html_safe
+ end
+
+ def milestone_merge_requests_tooltip_text(milestone)
+ merge_requests = milestone.merge_requests
+
+ return _("Merge requests") if merge_requests.empty?
+
+ content = []
+
+ content << n_("1 open merge request", "%{merge_requests} open merge requests", merge_requests.opened.count) % { merge_requests: merge_requests.opened.count } if merge_requests.opened.any?
+ content << n_("1 closed merge request", "%{merge_requests} closed merge requests", merge_requests.closed.count) % { merge_requests: merge_requests.closed.count } if merge_requests.closed.any?
+ content << n_("1 merged merge request", "%{merge_requests} merged merge requests", merge_requests.merged.count) % { merge_requests: merge_requests.merged.count } if merge_requests.merged.any?
+
+ content.join('<br />').html_safe
+ end
+
+ def milestone_releases_tooltip_text(milestone)
+ count = milestone.releases.count
+
+ return _("Releases") if count.zero?
+
+ n_("%{releases} release", "%{releases} releases", count) % { releases: count }
+ end
+
+ def recent_releases_with_counts(milestone)
+ total_count = milestone.releases.size
+ return [[], 0, 0] if total_count == 0
+
+ recent_releases = milestone.releases.recent.to_a
+ more_count = total_count - recent_releases.size
+ [recent_releases, total_count, more_count]
+ end
+
+ def milestone_tooltip_due_date(milestone)
+ if milestone.due_date
+ "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})"
+ else
+ _('Milestone')
+ end
+ end
+
+ def timebox_date_range(timebox)
+ if timebox.start_date && timebox.due_date
+ "#{timebox.start_date.to_s(:medium)}–#{timebox.due_date.to_s(:medium)}"
+ elsif timebox.due_date
+ if timebox.due_date.past?
+ _("expired on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
+ else
+ _("expires on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
+ end
+ elsif timebox.start_date
+ if timebox.start_date.past?
+ _("started on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
+ else
+ _("starts on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
+ end
+ end
+ end
+ alias_method :milestone_date_range, :timebox_date_range
+
+ def milestone_tab_path(milestone, tab)
+ url_for(action: tab, format: :json)
+ end
+
+ def update_milestone_path(milestone, params = {})
+ if milestone.project_milestone?
+ project_milestone_path(milestone.project, milestone, milestone: params)
+ else
+ group_milestone_route(milestone, params)
+ end
+ end
+
+ def group_milestone_route(milestone, params = {})
+ params = nil if params.empty?
+
+ group_milestone_path(milestone.group, milestone.iid, milestone: params)
+ end
+
+ def group_or_project_milestone_path(milestone)
+ params =
+ if milestone.group_milestone?
+ { milestone: { title: milestone.title } }
+ else
+ { title: milestone.title }
+ end
+
+ milestone_path(milestone.milestone, params)
+ end
+
+ def edit_milestone_path(milestone)
+ if milestone.group_milestone?
+ edit_group_milestone_path(milestone.group, milestone)
+ elsif milestone.project_milestone?
+ edit_project_milestone_path(milestone.project, milestone)
+ end
+ end
+
+ def can_admin_project_milestones?
+ strong_memoize(:can_admin_project_milestones) do
+ can?(current_user, :admin_milestone, @project)
+ end
+ end
+
+ def can_admin_group_milestones?
+ strong_memoize(:can_admin_group_milestones) do
+ can?(current_user, :admin_milestone, @project.group)
+ end
+ end
+
+ def display_issues_count_warning?(milestone)
+ milestone_visible_issues_count(milestone) > Milestone::DISPLAY_ISSUES_LIMIT
+ end
+
+ def milestone_issues_count_message(milestone)
+ total_count = milestone_visible_issues_count(milestone)
+ limit = Milestone::DISPLAY_ISSUES_LIMIT
+ link_options = { milestone_title: @milestone.title }
+
+ message = _('Showing %{limit} of %{total_count} issues. ') % { limit: limit, total_count: total_count }
+ message += link_to(_('View all issues'), milestones_issues_path(link_options))
+
+ message.html_safe
+ end
+
+ private
+
+ def milestone_visible_issues_count(milestone)
+ @milestone_visible_issues_count ||= milestone.issues_visible_to_user(current_user).size
+ end
+end
+
+TimeboxesHelper.prepend_if_ee('EE::TimeboxesHelper')