Skip to content
Snippets Groups Projects
Commit cc656a11 authored by Douwe Maan's avatar Douwe Maan
Browse files

Refactor resolvability checks based on type

parent 64c1735c
No related branches found
No related tags found
No related merge requests found
Showing
with 107 additions and 39 deletions
Loading
Loading
@@ -292,17 +292,6 @@ module Issuable
self.class.to_ability_name
end
 
# Convert this Issuable class name to a format usable by notifications.
#
# Examples:
#
# issuable.class # => MergeRequest
# issuable.human_class_name # => "merge request"
def human_class_name
@human_class_name ||= self.class.name.titleize.downcase
end
# Returns a Hash of attributes to be used for Twitter card metadata
def card_attributes
{
Loading
Loading
module Noteable
# Names of all implementers of `Noteable` that support resolvable notes.
RESOLVABLE_TYPES = %w(MergeRequest).freeze
def base_class_name
self.class.base_class.name
end
# Convert this Noteable class name to a format usable by notifications.
#
# Examples:
#
# noteable.class # => MergeRequest
# noteable.human_class_name # => "merge request"
def human_class_name
@human_class_name ||= base_class_name.titleize.downcase
end
def supports_resolvable_notes?
RESOLVABLE_TYPES.include?(base_class_name)
end
def supports_discussions?
DiscussionNote::NOTEABLE_TYPES.include?(base_class_name)
end
def discussion_notes
notes
end
Loading
Loading
Loading
Loading
@@ -20,6 +20,8 @@ module ResolvableDiscussion
:last_note
)
 
delegate :potentially_resolvable?, to: :first_note
delegate :resolved_at,
:resolved_by,
 
Loading
Loading
@@ -27,11 +29,6 @@ module ResolvableDiscussion
allow_nil: true
end
 
# Keep this method in sync with the `potentially_resolvable` scope on `ResolvableNote`
def potentially_resolvable?
for_merge_request?
end
def resolvable?
return @resolvable if @resolvable.present?
 
Loading
Loading
module ResolvableNote
extend ActiveSupport::Concern
 
# Names of all subclasses of `Note` that can be resolvable.
RESOLVABLE_TYPES = %w(DiffNote DiscussionNote).freeze
 
included do
Loading
Loading
@@ -8,10 +9,8 @@ module ResolvableNote
 
validates :resolved_by, presence: true, if: :resolved?
 
# Keep this scope in sync with the logic in `#potentially_resolvable?` in subclasses of `Discussion` that are resolvable.
# `RESOLVABLE_TYPES` should include names of all subclasses that are resolvable (where the method can return true), and
# the scope should also match the criteria `ResolvableDiscussion#potentially_resolvable?` puts on resolvability.
scope :potentially_resolvable, -> { where(type: RESOLVABLE_TYPES).where(noteable_type: 'MergeRequest') }
# Keep this scope in sync with `#potentially_resolvable?`
scope :potentially_resolvable, -> { where(type: RESOLVABLE_TYPES).where(noteable_type: Noteable::RESOLVABLE_TYPES) }
# Keep this scope in sync with `#resolvable?`
scope :resolvable, -> { potentially_resolvable.user }
 
Loading
Loading
@@ -31,7 +30,10 @@ module ResolvableNote
end
end
 
delegate :potentially_resolvable?, to: :to_discussion
# Keep this method in sync with the `potentially_resolvable` scope
def potentially_resolvable?
RESOLVABLE_TYPES.include?(self.class.name) && noteable.supports_resolvable_notes?
end
 
# Keep this method in sync with the `resolvable` scope
def resolvable?
Loading
Loading
# A discussion on merge request or commit diffs consisting of `DiffNote` notes.
#
# A discussion of this type can be resolvable.
class DiffDiscussion < Discussion
include DiscussionOnDiff
 
def self.note_class
DiffNote
end
delegate :position,
:original_position,
 
Loading
Loading
# A note on merge request or commit diffs
#
# A note of this type can be resolvable.
class DiffNote < Note
include NoteOnDiff
 
Loading
Loading
# A non-diff discussion on an issue, merge request, commit, or snippet, consisting of `DiscussionNote` notes.
#
# A discussion of this type can be resolvable.
class Discussion
include ResolvableDiscussion
 
Loading
Loading
@@ -54,6 +56,10 @@ class Discussion
nil
end
 
def self.note_class
DiscussionNote
end
def initialize(notes, noteable = nil)
@notes = notes
@noteable = noteable
Loading
Loading
# A note in a non-diff discussion on an issue, merge request, commit, or snippet
# A note in a non-diff discussion on an issue, merge request, commit, or snippet.
#
# A note of this type can be resolvable.
class DiscussionNote < Note
# Names of all implementers of `Noteable` that support discussions.
NOTEABLE_TYPES = %w(MergeRequest Issue Commit Snippet).freeze
RESOLVABLE_TYPES = %w(MergeRequest).freeze
 
validates :noteable_type, inclusion: { in: NOTEABLE_TYPES }
 
Loading
Loading
# A discussion to wrap a single `Note` note on the root of an issue, merge request,
# commit, or snippet, that is not displayed as a discussion.
#
# A discussion of this type is never resolvable.
class IndividualNoteDiscussion < Discussion
def potentially_resolvable?
false
def self.note_class
Note
end
 
def individual_note?
Loading
Loading
# A discussion on merge request or commit diffs consisting of `LegacyDiffNote` notes.
#
# All new diff discussions are of the type `DiffDiscussion`, but any diff discussions created
# before the introduction of the new implementation still use `LegacyDiffDiscussion`.
#
# A discussion of this type is never resolvable.
class LegacyDiffDiscussion < Discussion
include DiscussionOnDiff
 
Loading
Loading
@@ -8,8 +11,8 @@ class LegacyDiffDiscussion < Discussion
true
end
 
def potentially_resolvable?
false
def self.note_class
LegacyDiffNote
end
 
def collapsed?
Loading
Loading
# A note on merge request or commit diffs, using the legacy implementation.
#
# All new diff notes are of the type `DiffNote`, but any diff notes created
# before the introduction of the new implementation still use `LegacyDiffNote`.
#
# A note of this type is never resolvable.
class LegacyDiffNote < Note
include NoteOnDiff
 
Loading
Loading
# A note on the root of an issue, merge request, commit, or snippet.
#
# A note of this type is never resolvable.
class Note < ActiveRecord::Base
extend ActiveModel::Naming
include Gitlab::CurrentSettings
Loading
Loading
@@ -225,11 +228,7 @@ class Note < ActiveRecord::Base
end
 
def can_be_discussion_note?
DiscussionNote::NOTEABLE_TYPES.include?(self.noteable_type) && !part_of_discussion?
end
def can_be_resolvable?
DiscussionNote::RESOLVABLE_TYPES.include?(self.noteable_type)
self.noteable.supports_discussions? && !part_of_discussion?
end
 
def discussion_class(noteable = nil)
Loading
Loading
Loading
Loading
@@ -2,6 +2,8 @@
# contains that commit, they are displayed as if they were a discussion.
#
# This represents one of those discussions, consisting of `Note` notes.
#
# A discussion of this type is never resolvable.
class OutOfContextDiscussion < Discussion
# Returns an array of discussion ID components
def self.build_discussion_id(note)
Loading
Loading
@@ -13,8 +15,8 @@ class OutOfContextDiscussion < Discussion
def self.override_discussion_id(note)
discussion_id(note)
end
def potentially_resolvable?
false
def self.note_class
Note
end
end
Loading
Loading
@@ -36,12 +36,14 @@ module Issues
 
def item_for_discussion(discussion)
first_note_to_resolve = discussion.first_note_to_resolve || discussion.first_note
other_note_count = discussion.notes.size - 1
note_url = Gitlab::UrlBuilder.build(first_note_to_resolve)
 
is_very_first_note = first_note_to_resolve == discussion.first_note
action = is_very_first_note ? "started" : "commented on"
note_url = Gitlab::UrlBuilder.build(first_note_to_resolve)
other_note_count = discussion.notes.size - 1
discussion_info = "- [ ] #{first_note_to_resolve.author.to_reference} #{action} a [discussion](#{note_url}): "
discussion_info << " (+#{other_note_count} #{'comment'.pluralize(other_note_count)})" if other_note_count > 0
 
Loading
Loading
- noteable_type = @note.noteable_type
- noteable_name = @note.noteable.human_class_name
 
.pull-left.btn-group.append-right-10.comment-type-dropdown.js-comment-type-dropdown
%input.btn.btn-nr.btn-create.comment-btn.js-comment-button.js-comment-submit-button{ type: 'submit', value: 'Comment' }
- if @note.can_be_discussion_note?
= button_tag type: 'button', class: 'btn btn-nr dropdown-toggle comment-btn js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => 'Open comment type dropdown' do
= icon('caret-down')
%ul#resolvable-comment-menu.dropdown-menu{ data: { dropdown: true } }
%li#comment.droplab-item-selected{ data: { value: '', 'button-text' => 'Comment', 'secondary-button-text' => "Comment & close #{noteable_type.titleize.downcase}" } }
%li#comment.droplab-item-selected{ data: { value: '', 'button-text' => 'Comment', 'secondary-button-text' => "Comment & close #{noteable_name}" } }
= icon('check')
.description
%strong Comment
%p= "Add a general comment to this #{noteable_type.titleize.downcase}."
%p
Add a general comment to this #{noteable_name}.
%li.divider
- if @note.can_be_resolvable?
%li#discussion{ data: { value: 'DiscussionNote', 'button-text' => 'Start discussion', 'secondary-button-text' => "Start discussion & close #{noteable_type.titleize.downcase}" } }
= icon('check')
.description
%strong Start discussion
%p
Discuss a specific suggestion or question that needs to be resolved.
- else
%li#discussion{ data: { value: 'DiscussionNote', 'button-text' => 'Start discussion', 'secondary-button-text' => "Start discussion & close #{noteable_type.titleize.downcase}"} }
= icon('check')
.description
%strong Start discussion
%p
Discuss a specific suggestion or question.
%li#discussion{ data: { value: 'DiscussionNote', 'button-text' => 'Start discussion', 'secondary-button-text' => "Start discussion & close #{noteable_name}" } }
= icon('check')
.description
%strong Start discussion
%p
= succeed '.' do
Discuss a specific suggestion or question
- if @note.noteable.supports_resolvable_notes?
that needs to be resolved
Loading
Loading
@@ -28,7 +28,7 @@
.error-alert
 
.note-form-actions.clearfix
= render partial: 'projects/notes/comment_type_button', locals: { show_close_button: true }
= render partial: 'projects/notes/comment_button'
 
= yield(:note_actions)
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment