diff options
Diffstat (limited to 'app/services/work_items')
4 files changed, 98 insertions, 6 deletions
diff --git a/app/services/work_items/callbacks/award_emoji.rb b/app/services/work_items/callbacks/award_emoji.rb index 6344813d4b9..9ff5b6d049d 100644 --- a/app/services/work_items/callbacks/award_emoji.rb +++ b/app/services/work_items/callbacks/award_emoji.rb @@ -15,7 +15,8 @@ module WorkItems def execute_emoji_service(action, name) class_name = { add: ::AwardEmojis::AddService, - remove: ::AwardEmojis::DestroyService + remove: ::AwardEmojis::DestroyService, + toggle: ::AwardEmojis::ToggleService } raise_error(invalid_action_error(action)) unless class_name.key?(action) diff --git a/app/services/work_items/create_service.rb b/app/services/work_items/create_service.rb index 903736cf662..354a33a0384 100644 --- a/app/services/work_items/create_service.rb +++ b/app/services/work_items/create_service.rb @@ -32,8 +32,11 @@ module WorkItems end def before_create(work_item) - execute_widgets(work_item: work_item, callback: :before_create_callback, - widget_params: @widget_params) + execute_widgets( + work_item: work_item, + callback: :before_create_callback, + widget_params: @widget_params + ) super end @@ -41,8 +44,11 @@ module WorkItems def transaction_create(work_item) super.tap do |save_result| if save_result - execute_widgets(work_item: work_item, callback: :after_create_in_transaction, - widget_params: @widget_params) + execute_widgets( + work_item: work_item, + callback: :after_create_in_transaction, + widget_params: @widget_params + ) end end end diff --git a/app/services/work_items/related_work_item_links/create_service.rb b/app/services/work_items/related_work_item_links/create_service.rb index 6a9ddd5c83d..f313881470a 100644 --- a/app/services/work_items/related_work_item_links/create_service.rb +++ b/app/services/work_items/related_work_item_links/create_service.rb @@ -25,7 +25,7 @@ module WorkItems end def previous_related_issuables - @related_issues ||= issuable.related_issues(current_user).to_a + @related_issues ||= issuable.linked_work_items(authorize: false).to_a end private diff --git a/app/services/work_items/related_work_item_links/destroy_service.rb b/app/services/work_items/related_work_item_links/destroy_service.rb new file mode 100644 index 00000000000..6d1920d01b2 --- /dev/null +++ b/app/services/work_items/related_work_item_links/destroy_service.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +module WorkItems + module RelatedWorkItemLinks + class DestroyService < BaseService + def initialize(work_item, user, params) + @work_item = work_item + @current_user = user + @params = params.dup + @failed_ids = [] + @removed_ids = [] + end + + def execute + return error(_('No work item found.'), 403) unless can?(current_user, :admin_work_item_link, work_item) + return error(_('No work item IDs provided.'), 409) if params[:item_ids].empty? + + destroy_links_for(params[:item_ids]) + + if removed_ids.any? + success(message: response_message, items_removed: removed_ids, items_with_errors: failed_ids.flatten) + else + error(error_message) + end + end + + private + + attr_reader :work_item, :current_user, :failed_ids, :removed_ids + + def destroy_links_for(item_ids) + destroy_links(source: work_item, target: item_ids, direction: :target) + destroy_links(source: item_ids, target: work_item, direction: :source) + end + + def destroy_links(source:, target:, direction:) + WorkItems::RelatedWorkItemLink.for_source_and_target(source, target).each do |link| + linked_item = link.try(direction) + + if can?(current_user, :admin_work_item_link, linked_item) + link.destroy! + removed_ids << linked_item.id + create_notes(link) + else + failed_ids << linked_item.id + end + end + end + + def create_notes(link) + SystemNoteService.unrelate_issuable(link.source, link.target, current_user) + SystemNoteService.unrelate_issuable(link.target, link.source, current_user) + end + + def error_message + not_linked = params[:item_ids] - (removed_ids + failed_ids) + error_messages = [] + + if failed_ids.any? + error_messages << format( + _('%{item_ids} could not be removed due to insufficient permissions'), item_ids: failed_ids.to_sentence + ) + end + + if not_linked.any? + error_messages << format( + _('%{item_ids} could not be removed due to not being linked'), item_ids: not_linked.to_sentence + ) + end + + return '' unless error_messages.any? + + format(_('IDs with errors: %{error_messages}.'), error_messages: error_messages.join(', ')) + end + + def response_message + success_message = format(_('Successfully unlinked IDs: %{item_ids}.'), item_ids: removed_ids.to_sentence) + + return success_message unless error_message.present? + + "#{success_message} #{error_message}" + end + end + end +end |