2019-12-04 20:38:33 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Analytics
|
|
|
|
module CycleAnalytics
|
|
|
|
module Stage
|
|
|
|
extend ActiveSupport::Concern
|
2019-12-26 22:10:19 +05:30
|
|
|
include RelativePositioning
|
|
|
|
include Gitlab::Utils::StrongMemoize
|
2019-12-04 20:38:33 +05:30
|
|
|
|
|
|
|
included do
|
2019-12-26 22:10:19 +05:30
|
|
|
belongs_to :start_event_label, class_name: 'GroupLabel', optional: true
|
|
|
|
belongs_to :end_event_label, class_name: 'GroupLabel', optional: true
|
|
|
|
|
2019-12-04 20:38:33 +05:30
|
|
|
validates :name, presence: true
|
2019-12-21 20:55:43 +05:30
|
|
|
validates :name, exclusion: { in: Gitlab::Analytics::CycleAnalytics::DefaultStages.names }, if: :custom?
|
2019-12-04 20:38:33 +05:30
|
|
|
validates :start_event_identifier, presence: true
|
|
|
|
validates :end_event_identifier, presence: true
|
2019-12-26 22:10:19 +05:30
|
|
|
validates :start_event_label, presence: true, if: :start_event_label_based?
|
|
|
|
validates :end_event_label, presence: true, if: :end_event_label_based?
|
2019-12-04 20:38:33 +05:30
|
|
|
validate :validate_stage_event_pairs
|
2019-12-26 22:10:19 +05:30
|
|
|
validate :validate_labels
|
2019-12-04 20:38:33 +05:30
|
|
|
|
|
|
|
enum start_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents.to_enum, _prefix: :start_event_identifier
|
|
|
|
enum end_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents.to_enum, _prefix: :end_event_identifier
|
|
|
|
|
|
|
|
alias_attribute :custom_stage?, :custom
|
2019-12-21 20:55:43 +05:30
|
|
|
scope :default_stages, -> { where(custom: false) }
|
2019-12-26 22:10:19 +05:30
|
|
|
scope :ordered, -> { order(:relative_position, :id) }
|
2020-01-01 13:55:28 +05:30
|
|
|
scope :for_list, -> { includes(:start_event_label, :end_event_label).ordered }
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def parent=(_)
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def parent
|
|
|
|
raise NotImplementedError
|
|
|
|
end
|
|
|
|
|
|
|
|
def start_event
|
2019-12-26 22:10:19 +05:30
|
|
|
strong_memoize(:start_event) do
|
|
|
|
Gitlab::Analytics::CycleAnalytics::StageEvents[start_event_identifier].new(params_for_start_event)
|
|
|
|
end
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def end_event
|
2019-12-26 22:10:19 +05:30
|
|
|
strong_memoize(:end_event) do
|
|
|
|
Gitlab::Analytics::CycleAnalytics::StageEvents[end_event_identifier].new(params_for_end_event)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def start_event_label_based?
|
|
|
|
start_event_identifier && start_event.label_based?
|
|
|
|
end
|
|
|
|
|
|
|
|
def end_event_label_based?
|
|
|
|
end_event_identifier && end_event.label_based?
|
|
|
|
end
|
|
|
|
|
|
|
|
def start_event_identifier=(identifier)
|
|
|
|
clear_memoization(:start_event)
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
|
|
|
def end_event_identifier=(identifier)
|
|
|
|
clear_memoization(:end_event)
|
|
|
|
super
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def params_for_start_event
|
2019-12-26 22:10:19 +05:30
|
|
|
start_event_label.present? ? { label: start_event_label } : {}
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def params_for_end_event
|
2019-12-26 22:10:19 +05:30
|
|
|
end_event_label.present? ? { label: end_event_label } : {}
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def default_stage?
|
|
|
|
!custom
|
|
|
|
end
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
# The model class that is going to be queried, Issue or MergeRequest
|
|
|
|
def subject_class
|
2019-12-04 20:38:33 +05:30
|
|
|
start_event.object_type
|
|
|
|
end
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
def matches_with_stage_params?(stage_params)
|
|
|
|
default_stage? &&
|
|
|
|
start_event_identifier.to_s.eql?(stage_params[:start_event_identifier].to_s) &&
|
|
|
|
end_event_identifier.to_s.eql?(stage_params[:end_event_identifier].to_s)
|
|
|
|
end
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
def find_with_same_parent!(id)
|
|
|
|
parent.cycle_analytics_stages.find(id)
|
|
|
|
end
|
|
|
|
|
2019-12-04 20:38:33 +05:30
|
|
|
private
|
|
|
|
|
|
|
|
def validate_stage_event_pairs
|
|
|
|
return if start_event_identifier.nil? || end_event_identifier.nil?
|
|
|
|
|
|
|
|
unless pairing_rules.fetch(start_event.class, []).include?(end_event.class)
|
2019-12-26 22:10:19 +05:30
|
|
|
errors.add(:end_event, s_('CycleAnalytics|not allowed for the given start event'))
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def pairing_rules
|
|
|
|
Gitlab::Analytics::CycleAnalytics::StageEvents.pairing_rules
|
|
|
|
end
|
2019-12-26 22:10:19 +05:30
|
|
|
|
|
|
|
def validate_labels
|
|
|
|
validate_label_within_group(:start_event_label, start_event_label_id) if start_event_label_id_changed?
|
|
|
|
validate_label_within_group(:end_event_label, end_event_label_id) if end_event_label_id_changed?
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_label_within_group(association_name, label_id)
|
|
|
|
return unless label_id
|
|
|
|
return unless group
|
|
|
|
|
|
|
|
unless label_available_for_group?(label_id)
|
|
|
|
errors.add(association_name, s_('CycleAnalyticsStage|is not available for the selected group'))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def label_available_for_group?(label_id)
|
|
|
|
LabelsFinder.new(nil, { group_id: group.id, include_ancestor_groups: true, only_group_labels: true })
|
|
|
|
.execute(skip_authorization: true)
|
|
|
|
.by_ids(label_id)
|
|
|
|
.exists?
|
|
|
|
end
|
2019-12-04 20:38:33 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|