gitlab-ce/app/services/work_items/data_sync/widgets/hierarchy.rb

90 lines
3.7 KiB
Ruby

# frozen_string_literal: true
module WorkItems
module DataSync
module Widgets
class Hierarchy < Base
ALLOWED_PARAMS = %i[parent_work_item_id].freeze
def after_save_commit
return unless target_work_item.get_widget(:hierarchy)
handle_parent
# we only handle child items for `move` functionality, `clone` does not copy child items.
return unless params[:operation] == :move
handle_children
end
def post_move_cleanup
# Cleanup children linked to moved item when that is an issue because we are currently creating those
# child items in the destination namespace anyway. If we decide to relink child items for Issue WIT
# then we should not be deleting them here.
work_item.child_links.each { |child_link| child_link.work_item.destroy! } if work_item.work_item_type.issue?
# cleanup parent link
work_item.parent_link&.destroy!
end
private
def handle_parent
return unless work_item.parent_link.present?
parent_link_attributes = work_item.parent_link.attributes.except("id").tap do |attributes|
attributes["work_item_id"] = target_work_item.id
attributes["namespace_id"] = target_work_item.namespace_id
attributes["work_item_parent_id"] = params[:parent_work_item_id] if params[:parent_work_item_id].present?
end
WorkItems::ParentLink.create!(parent_link_attributes)
end
def handle_children
# We only support moving child items for the issue work item type for now
return move_children if work_item.work_item_type.issue?
# Relink child items to the new work item first. This will be used for any work item type other than issue.
# For issue work item type we actually move the child items(tasks) to
# the destination namespace. This is to keep feature parity with existing move functionality on issue.
relink_children_to_target_work_item
end
def relink_children_to_target_work_item
work_item.child_links.each_batch(of: BATCH_SIZE) do |child_links_batch|
# We need to upsert because an work item cannot have multiple parents,
# so we cannot create a "copy" parent link record where same child work item
# points to the target work item as the new parent
WorkItems::ParentLink.upsert_all(new_work_item_child_link(child_links_batch), unique_by: :work_item_id)
end
end
def new_work_item_child_link(child_links_batch)
child_links_batch.map do |child_link|
child_link.attributes.except("id").tap do |attrs|
attrs['work_item_parent_id'] = target_work_item.id
end
end
end
def move_children
# We iterate over "new work item" child links now, because we have relinked child items from moved work item
# to the new work item in `relink_children_to_target_work_item`.
work_item.child_links.each do |link|
# This is going to be moved to an async worker. This is planned as a follow-up up iteration for a bunch of
# other work item association data. The async implementation for move will be tracked in:
# https://gitlab.com/groups/gitlab-org/-/epics/15934
::WorkItems::DataSync::MoveService.new(
work_item: link.work_item, target_namespace: target_work_item.namespace, current_user: current_user,
params: { parent_work_item_id: target_work_item.id, skip_work_item_type_check: true }
).execute
end
end
end
end
end
end
WorkItems::DataSync::Widgets::Hierarchy.prepend_mod