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/models/work_item.rb')
-rw-r--r--app/models/work_item.rb79
1 files changed, 79 insertions, 0 deletions
diff --git a/app/models/work_item.rb b/app/models/work_item.rb
index a7cd522f023..10476339ca9 100644
--- a/app/models/work_item.rb
+++ b/app/models/work_item.rb
@@ -67,6 +67,16 @@ class WorkItem < Issue
end
end
+ # Returns widget object if available
+ # type parameter can be a symbol, for example, `:description`.
+ def get_widget(type)
+ widgets.find do |widget|
+ widget.instance_of?(WorkItems::Widgets.const_get(type.to_s.camelize, false))
+ end
+ rescue NameError
+ nil
+ end
+
def ancestors
hierarchy.ancestors(hierarchy_order: :asc)
end
@@ -130,6 +140,75 @@ class WorkItem < Issue
::Gitlab::WorkItems::WorkItemHierarchy.new(base, options: options)
end
+
+ override :allowed_work_item_type_change
+ def allowed_work_item_type_change
+ return unless work_item_type_id_changed?
+
+ child_links = WorkItems::ParentLink.for_parents(id)
+ parent_link = ::WorkItems::ParentLink.find_by(work_item: self)
+
+ validate_parent_restrictions(parent_link)
+ validate_child_restrictions(child_links)
+ validate_depth(parent_link, child_links)
+ end
+
+ def validate_parent_restrictions(parent_link)
+ return unless parent_link
+
+ parent_link.work_item.work_item_type_id = work_item_type_id
+
+ unless parent_link.valid?
+ errors.add(
+ :work_item_type_id,
+ format(
+ _('cannot be changed to %{new_type} with %{parent_type} as parent type.'),
+ new_type: work_item_type.name, parent_type: parent_link.work_item_parent.work_item_type.name
+ )
+ )
+ end
+ end
+
+ def validate_child_restrictions(child_links)
+ return if child_links.empty?
+
+ child_type_ids = child_links.joins(:work_item).select(self.class.arel_table[:work_item_type_id]).distinct
+ restrictions = ::WorkItems::HierarchyRestriction.where(
+ parent_type_id: work_item_type_id,
+ child_type_id: child_type_ids
+ )
+
+ # We expect a restriction for every child type
+ if restrictions.size < child_type_ids.size
+ errors.add(
+ :work_item_type_id,
+ format(_('cannot be changed to %{new_type} with these child item types.'), new_type: work_item_type.name)
+ )
+ end
+ end
+
+ def validate_depth(parent_link, child_links)
+ restriction = ::WorkItems::HierarchyRestriction.find_by_parent_type_id_and_child_type_id(
+ work_item_type_id,
+ work_item_type_id
+ )
+ return unless restriction&.maximum_depth
+
+ children_with_new_type = self.class.where(id: child_links.select(:work_item_id))
+ .where(work_item_type_id: work_item_type_id)
+ max_child_depth = ::Gitlab::WorkItems::WorkItemHierarchy.new(children_with_new_type).max_descendants_depth.to_i
+
+ ancestor_depth =
+ if parent_link&.work_item_parent && parent_link.work_item_parent.work_item_type_id == work_item_type_id
+ parent_link.work_item_parent.same_type_base_and_ancestors.count
+ else
+ 0
+ end
+
+ if max_child_depth + ancestor_depth > restriction.maximum_depth - 1
+ errors.add(:work_item_type_id, _('reached maximum depth'))
+ end
+ end
end
WorkItem.prepend_mod