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

design_reference_filter.rb « filter « banzai « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 7455dfe00efcfc6c7a4ddeee900f16e691d12b5d (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
# frozen_string_literal: true

module Banzai
  module Filter
    class DesignReferenceFilter < AbstractReferenceFilter
      FEATURE_FLAG = :design_management_reference_filter_gfm_pipeline

      class Identifier
        include Comparable
        attr_reader :issue_iid, :filename

        def initialize(issue_iid:, filename:)
          @issue_iid = issue_iid
          @filename = filename
        end

        def as_composite_id(id_for_iid)
          id = id_for_iid[issue_iid]
          return unless id

          { issue_id: id, filename: filename }
        end

        def <=>(other)
          return unless other.is_a?(Identifier)

          [issue_iid, filename] <=> [other.issue_iid, other.filename]
        end
        alias_method :eql?, :==

        def hash
          [issue_iid, filename].hash
        end
      end

      self.reference_type = :design

      # This filter must be enabled by setting the
      # design_management_reference_filter_gfm_pipeline flag
      def call
        return doc unless enabled?

        super
      end

      def find_object(project, identifier)
        records_per_parent[project][identifier]
      end

      def parent_records(project, identifiers)
        return [] unless project.design_management_enabled?

        iids        = identifiers.map(&:issue_iid).to_set
        issues      = project.issues.where(iid: iids)
        id_for_iid  = issues.index_by(&:iid).transform_values(&:id)
        issue_by_id = issues.index_by(&:id)

        designs(identifiers, id_for_iid).each do |d|
          issue = issue_by_id[d.issue_id]
          # optimisation: assign values we have already fetched
          d.project = project
          d.issue = issue
        end
      end

      def relation_for_paths(paths)
        super.includes(:route, :namespace, :group)
      end

      def parent_type
        :project
      end

      # optimisation to reuse the parent_per_reference query information
      def parent_from_ref(ref)
        parent_per_reference[ref || current_parent_path]
      end

      def url_for_object(design, project)
        path_options = { vueroute: design.filename }
        Gitlab::Routing.url_helpers.designs_project_issue_path(project, design.issue, path_options)
      end

      def data_attributes_for(_text, _project, design, **_kwargs)
        super.merge(issue: design.issue_id)
      end

      def self.object_class
        ::DesignManagement::Design
      end

      def self.object_sym
        :design
      end

      def self.parse_symbol(raw, match_data)
        filename = match_data[:url_filename]
        iid = match_data[:issue].to_i
        Identifier.new(filename: CGI.unescape(filename), issue_iid: iid)
      end

      def record_identifier(design)
        Identifier.new(filename: design.filename, issue_iid: design.issue.iid)
      end

      private

      def designs(identifiers, id_for_iid)
        identifiers
          .map { |identifier| identifier.as_composite_id(id_for_iid) }
          .compact
          .in_groups_of(100, false) # limitation of by_issue_id_and_filename, so we batch
          .flat_map { |ids| DesignManagement::Design.by_issue_id_and_filename(ids) }
      end

      def enabled?
        Feature.enabled?(FEATURE_FLAG, parent)
      end
    end
  end
end