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

bulk_update.rb « issues « mutations « graphql « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 05e83fc82bbd3d9a1c723e3c09987835913651aa (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
# frozen_string_literal: true

module Mutations
  module Issues
    class BulkUpdate < BaseMutation
      graphql_name 'IssuesBulkUpdate'

      include Gitlab::Graphql::Authorize::AuthorizeResource

      MAX_ISSUES = 100

      description 'Allows updating several properties for a set of issues. ' \
                  'Does nothing if the `bulk_update_issues_mutation` feature flag is disabled.'

      argument :parent_id, ::Types::GlobalIDType[::IssueParent],
        required: true,
        description: 'Global ID of the parent to which the bulk update will be scoped. ' \
                     'The parent can be a project **(FREE ALL)** or a group **(PREMIUM ALL)**. ' \
                     'Example `IssueParentID` are `"gid://gitlab/Project/1"` and `"gid://gitlab/Group/1"`.'

      argument :ids, [::Types::GlobalIDType[::Issue]],
        required: true,
        description: 'Global ID array of the issues that will be updated. ' \
                     "IDs that the user can\'t update will be ignored. A max of #{MAX_ISSUES} can be provided."

      argument :assignee_ids, [::Types::GlobalIDType[::User]],
        required: false,
        description: 'Global ID array of the users that will be assigned to the given issues. ' \
                     'Existing assignees will be replaced with the ones on this list.'

      argument :milestone_id, ::Types::GlobalIDType[::Milestone],
        required: false,
        description: 'Global ID of the milestone that will be assigned to the issues.'

      argument :state_event, Types::IssueStateEventEnum,
        description: 'Close or reopen an issue.',
        required: false

      argument :add_label_ids, [::Types::GlobalIDType[::Label]],
        description: 'Global ID array of the labels that will be added to the issues. ',
        required: false

      argument :remove_label_ids, [::Types::GlobalIDType[::Label]],
        description: 'Global ID array of the labels that will be removed from the issues. ',
        required: false

      argument :subscription_event, Types::IssuableSubscriptionEventEnum,
        description: 'Subscribe to or unsubscribe from issue notifications.',
        required: false

      field :updated_issue_count, GraphQL::Types::Int,
        null: true,
        description: 'Number of issues that were successfully updated.'

      def ready?(**args)
        if Feature.disabled?(:bulk_update_issues_mutation)
          raise Gitlab::Graphql::Errors::ResourceNotAvailable, '`bulk_update_issues_mutation` feature flag is disabled.'
        end

        if args[:ids].size > MAX_ISSUES
          raise Gitlab::Graphql::Errors::ArgumentError,
                format(_('No more than %{max_issues} issues can be updated at the same time'), max_issues: MAX_ISSUES)
        end

        super
      end

      def resolve(ids:, parent_id:, **attributes)
        parent = find_parent!(parent_id)

        result = Issuable::BulkUpdateService.new(
          parent,
          current_user,
          prepared_params(attributes, ids)
        ).execute('issue')

        if result.success?
          { updated_issue_count: result.payload[:count], errors: [] }
        else
          { errors: result.errors }
        end
      end

      private

      def find_parent!(parent_id)
        parent = GitlabSchema.find_by_gid(parent_id).sync
        raise_resource_not_available_error! unless current_user.can?("read_#{parent.to_ability_name}", parent)

        parent
      end

      def prepared_params(attributes, ids)
        prepared = attributes.except(*global_id_arguments).merge(issuable_ids: model_ids_from(ids).uniq)

        global_id_arguments.each do |argument|
          next unless attributes.key?(argument)

          prepared[argument] = model_ids_from(attributes[argument])
        end

        # Ruby 3+: This can be simplified to:
        # prepared.transform_keys(param_mappings)
        prepared.transform_keys { |key| param_mappings[key] || key }
      end

      def param_mappings
        {}
      end

      def global_id_arguments
        %i[assignee_ids milestone_id add_label_ids remove_label_ids]
      end

      def model_ids_from(attributes)
        return if attributes.nil?
        return attributes.map(&:model_id) if attributes.is_a?(Array)

        attributes.model_id
      end
    end
  end
end

Mutations::Issues::BulkUpdate.prepend_mod