Welcome to mirror list, hosted at ThFree Co, Russian Federation.

work_item_actions.rb « quick_actions « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2adee0f9a9a0cc03a0b870e934d8b7683d47842b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# frozen_string_literal: true

module Gitlab
  module QuickActions
    module WorkItemActions
      extend ActiveSupport::Concern
      include Gitlab::QuickActions::Dsl

      included do
        desc { _('Change work item type') }
        explanation do |target_type|
          format(_("Converts work item to %{type}. Widgets not supported in new type are removed."), type: target_type)
        end
        types WorkItem
        params 'Task | Objective | Key Result | Issue'
        command :type do |type_name|
          @execution_message[:type] = update_type(type_name, :type)
        end

        desc { _('Promote work item') }
        explanation do |type_name|
          format(_("Promotes work item to %{type}."), type: type_name)
        end
        types WorkItem
        params 'issue | objective'
        condition { supports_promotion? }
        command :promote_to do |type_name|
          @execution_message[:promote_to] = update_type(type_name, :promote_to)
        end

        desc { _('Change work item parent') }
        explanation do |parent_param|
          format(_("Change work item's parent to %{parent_ref}."), parent_ref: parent_param)
        end
        types WorkItem
        params 'Parent #iid, reference or URL'
        condition { supports_parent? && can_admin_link? }
        command :set_parent do |parent_param|
          @updates[:set_parent] = extract_work_items(parent_param).first
          @execution_message[:set_parent] = success_msg[:set_parent]
        end

        desc { _('Add children to work item') }
        explanation do |child_param|
          format(_("Add %{child_ref} to this work item as child(ren)."), child_ref: child_param)
        end
        types WorkItem
        params 'Children #iids, references or URLs'
        condition { supports_children? && can_admin_link? }
        command :add_child do |child_param|
          @updates[:add_child] = extract_work_items(child_param)
          @execution_message[:add_child] = success_msg[:add_child]
        end
      end

      private

      # rubocop:disable Gitlab/ModuleWithInstanceVariables
      def update_type(type_name, command)
        new_type = ::WorkItems::Type.find_by_name(type_name.titleize)
        error_message = command == :type ? validate_type(new_type) : validate_promote_to(new_type)
        return error_message if error_message.present?

        @updates[:issue_type] = new_type.base_type
        @updates[:work_item_type] = new_type

        success_msg[command]
      end
      # rubocop:enable Gitlab/ModuleWithInstanceVariables

      def validate_type(type)
        return error_msg(:not_found) unless type.present?
        return error_msg(:same_type) if quick_action_target.work_item_type == type
        return error_msg(:forbidden) unless current_user.can?(:"create_#{type.base_type}", quick_action_target)

        nil
      end

      # rubocop: disable CodeReuse/ActiveRecord
      def extract_work_items(params)
        return if params.nil?

        issuable_type = params.include?('work_items') ? :work_item : :issue
        issuables = extract_references(params, issuable_type)
        return unless issuables

        WorkItem.find(issuables.pluck(:id))
      end
      # rubocop: enable CodeReuse/ActiveRecord

      def validate_promote_to(type)
        return error_msg(:not_found, action: 'promote') unless type && supports_promote_to?(type.name)
        return if current_user.can?(:"create_#{type.base_type}", quick_action_target)

        error_msg(:forbidden, action: 'promote')
      end

      def current_type
        quick_action_target.work_item_type
      end

      def supports_promotion?
        current_type.base_type.in?(promote_to_map.keys)
      end

      def supports_promote_to?(type_name)
        type_name == promote_to_map[current_type.base_type]
      end

      def promote_to_map
        { issue: 'Incident', task: 'Issue' }.with_indifferent_access
      end

      def error_msg(reason, action: 'convert')
        message = {
          not_found: 'Provided type is not supported',
          forbidden: 'You have insufficient permissions',
          same_type: 'Types are the same'
        }.freeze

        format(_("Failed to %{action} this work item: %{reason}."), { action: action, reason: message[reason] })
      end

      def success_msg
        {
          type: _('Type changed successfully.'),
          promote_to: _("Work item promoted successfully."),
          set_parent: _('Work item parent set successfully'),
          add_child: _('Child work item(s) added successfully')
        }
      end

      def supports_parent?
        ::WorkItems::HierarchyRestriction.find_by_child_type_id(quick_action_target.work_item_type_id).present?
      end

      def supports_children?
        ::WorkItems::HierarchyRestriction.find_by_parent_type_id(quick_action_target.work_item_type_id).present?
      end

      def can_admin_link?
        current_user.can?(:admin_issue_link, quick_action_target)
      end
    end
  end
end