summaryrefslogtreecommitdiff
path: root/app/presenters/merge_request_presenter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/presenters/merge_request_presenter.rb')
-rw-r--r--app/presenters/merge_request_presenter.rb168
1 files changed, 168 insertions, 0 deletions
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
new file mode 100644
index 00000000000..255f63db5c2
--- /dev/null
+++ b/app/presenters/merge_request_presenter.rb
@@ -0,0 +1,168 @@
+class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
+ include ActionView::Helpers::UrlHelper
+ include GitlabRoutingHelper
+ include MarkupHelper
+ include TreeHelper
+
+ presents :merge_request
+
+ def ci_status
+ if pipeline
+ status = pipeline.status
+ status = "success_with_warnings" if pipeline.success? && pipeline.has_warnings?
+
+ status || "preparing"
+ else
+ ci_service = source_project.try(:ci_service)
+ ci_service&.commit_status(diff_head_sha, source_branch)
+ end
+ end
+
+ def cancel_merge_when_pipeline_succeeds_path
+ if can_cancel_merge_when_pipeline_succeeds?(current_user)
+ cancel_merge_when_pipeline_succeeds_namespace_project_merge_request_path(
+ project.namespace,
+ project,
+ merge_request)
+ end
+ end
+
+ def create_issue_to_resolve_discussions_path
+ if can?(current_user, :create_issue, project) && project.issues_enabled?
+ new_namespace_project_issue_path(project.namespace,
+ project,
+ merge_request_to_resolve_discussions_of: iid)
+ end
+ end
+
+ def remove_wip_path
+ if can?(current_user, :update_merge_request, merge_request.project)
+ remove_wip_namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+ end
+
+ def merge_path
+ if can_be_merged_by?(current_user)
+ merge_namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+ end
+
+ def revert_in_fork_path
+ if user_can_fork_project? && can_be_reverted?(current_user)
+ continue_params = {
+ to: merge_request_path(merge_request),
+ notice: "#{edit_in_new_fork_notice} Try to cherry-pick this commit again.",
+ notice_now: edit_in_new_fork_notice_now
+ }
+
+ namespace_project_forks_path(merge_request.project.namespace, merge_request.project,
+ namespace_key: current_user.namespace.id,
+ continue: continue_params)
+ end
+ end
+
+ def cherry_pick_in_fork_path
+ if user_can_fork_project? && can_be_cherry_picked?
+ continue_params = {
+ to: merge_request_path(merge_request),
+ notice: "#{edit_in_new_fork_notice} Try to revert this commit again.",
+ notice_now: edit_in_new_fork_notice_now
+ }
+
+ namespace_project_forks_path(project.namespace, project,
+ namespace_key: current_user.namespace.id,
+ continue: continue_params)
+ end
+ end
+
+ def conflict_resolution_path
+ if conflicts_can_be_resolved_in_ui? && conflicts_can_be_resolved_by?(current_user)
+ conflicts_namespace_project_merge_request_path(project.namespace, project, merge_request)
+ end
+ end
+
+ def target_branch_commits_path
+ if target_branch_exists?
+ namespace_project_commits_path(project.namespace, project, target_branch)
+ end
+ end
+
+ def source_branch_path
+ if source_branch_exists?
+ namespace_project_branch_path(source_project.namespace, source_project, source_branch)
+ end
+ end
+
+ def source_branch_with_namespace_link
+ namespace = source_project_namespace
+ branch = source_branch
+
+ if source_branch_exists?
+ namespace = link_to(namespace, project_path(source_project))
+ branch = link_to(branch, namespace_project_commits_path(source_project.namespace, source_project, source_branch))
+ end
+
+ if for_fork?
+ namespace + ":" + branch
+ else
+ branch
+ end
+ end
+
+ def closing_issues_links
+ markdown issues_sentence(project, closing_issues), pipeline: :gfm, author: author, project: project
+ end
+
+ def mentioned_issues_links
+ mentioned_issues = issues_mentioned_but_not_closing(current_user)
+ markdown issues_sentence(project, mentioned_issues), pipeline: :gfm, author: author, project: project
+ end
+
+ def assign_to_closing_issues_link
+ issues = MergeRequests::AssignIssuesService.new(project,
+ current_user,
+ merge_request: merge_request,
+ closes_issues: closing_issues
+ ).assignable_issues
+ path = assign_related_issues_namespace_project_merge_request_path(project.namespace, project, merge_request)
+ if issues.present?
+ pluralize_this_issue = issues.count > 1 ? "these issues" : "this issue"
+ link_to "Assign yourself to #{pluralize_this_issue}", path, method: :post
+ end
+ end
+
+ def can_revert_on_current_merge_request?
+ user_can_collaborate_with_project? && can_be_reverted?(current_user)
+ end
+
+ def can_cherry_pick_on_current_merge_request?
+ user_can_collaborate_with_project? && can_be_cherry_picked?
+ end
+
+ private
+
+ def closing_issues
+ @closing_issues ||= closes_issues(current_user)
+ end
+
+ def pipeline
+ @pipeline ||= head_pipeline
+ end
+
+ def issues_sentence(project, issues)
+ # Sorting based on the `#123` or `group/project#123` reference will sort
+ # local issues first.
+ issues.map do |issue|
+ issue.to_reference(project)
+ end.sort.to_sentence
+ end
+
+ def user_can_collaborate_with_project?
+ can?(current_user, :push_code, project) ||
+ (current_user && current_user.already_forked?(project))
+ end
+
+ def user_can_fork_project?
+ can?(current_user, :fork_project, project)
+ end
+end