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

type.rb « work_items « models « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e1f6a13f7a7d345dd1d2b5a7f7247e0cefc4e6d5 (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
147
148
149
150
151
152
# frozen_string_literal: true

# Note: initial thinking behind `icon_name` is for it to do triple duty:
# 1. one of our svg icon names, such as `external-link` or a new one `bug`
# 2. if it's an absolute url, then url to a user uploaded icon/image
# 3. an emoji, with the format of `:smile:`
module WorkItems
  class Type < ApplicationRecord
    self.table_name = 'work_item_types'

    include CacheMarkdownField

    # type name is used in restrictions DB seeder to assure restrictions for
    # default types are pre-filled
    TYPE_NAMES = {
      issue: 'Issue',
      incident: 'Incident',
      test_case: 'Test Case',
      requirement: 'Requirement',
      task: 'Task',
      objective: 'Objective',
      key_result: 'Key Result'
    }.freeze

    # Base types need to exist on the DB on app startup
    # This constant is used by the DB seeder
    # TODO - where to add new icon names created?
    BASE_TYPES = {
      issue: { name: TYPE_NAMES[:issue], icon_name: 'issue-type-issue', enum_value: 0 },
      incident: { name: TYPE_NAMES[:incident], icon_name: 'issue-type-incident', enum_value: 1 },
      test_case: { name: TYPE_NAMES[:test_case], icon_name: 'issue-type-test-case', enum_value: 2 }, ## EE-only
      requirement: { name: TYPE_NAMES[:requirement], icon_name: 'issue-type-requirements', enum_value: 3 }, ## EE-only
      task: { name: TYPE_NAMES[:task], icon_name: 'issue-type-task', enum_value: 4 },
      objective: { name: TYPE_NAMES[:objective], icon_name: 'issue-type-objective', enum_value: 5 }, ## EE-only
      key_result: { name: TYPE_NAMES[:key_result], icon_name: 'issue-type-keyresult', enum_value: 6 } ## EE-only
    }.freeze

    WIDGETS_FOR_TYPE = {
      issue: [
        Widgets::Assignees,
        Widgets::Labels,
        Widgets::Description,
        Widgets::Hierarchy,
        Widgets::StartAndDueDate,
        Widgets::Milestone,
        Widgets::Notes
      ],
      incident: [
        Widgets::Description,
        Widgets::Hierarchy,
        Widgets::Notes
      ],
      test_case: [
        Widgets::Description,
        Widgets::Notes
      ],
      requirement: [
        Widgets::Description,
        Widgets::Notes
      ],
      task: [
        Widgets::Assignees,
        Widgets::Labels,
        Widgets::Description,
        Widgets::Hierarchy,
        Widgets::StartAndDueDate,
        Widgets::Milestone,
        Widgets::Notes
      ],
      objective: [
        Widgets::Assignees,
        Widgets::Labels,
        Widgets::Description,
        Widgets::Hierarchy,
        Widgets::Milestone,
        Widgets::Notes
      ],
      key_result: [
        Widgets::Assignees,
        Widgets::Labels,
        Widgets::Description,
        Widgets::Hierarchy,
        Widgets::StartAndDueDate,
        Widgets::Notes
      ]
    }.freeze

    # A list of types user can change between - both original and new
    # type must be included in this list. This is needed for legacy issues
    # where it's possible to switch between issue and incident.
    CHANGEABLE_BASE_TYPES = %w[issue incident test_case].freeze

    WI_TYPES_WITH_CREATED_HEADER = %w[issue incident].freeze

    cache_markdown_field :description, pipeline: :single_line

    enum base_type: BASE_TYPES.transform_values { |value| value[:enum_value] }

    belongs_to :namespace, optional: true
    has_many :work_items, class_name: 'Issue', foreign_key: :work_item_type_id, inverse_of: :work_item_type

    before_validation :strip_whitespace

    # TODO: review validation rules
    # https://gitlab.com/gitlab-org/gitlab/-/issues/336919
    validates :name, presence: true
    validates :name, uniqueness: { case_sensitive: false, scope: [:namespace_id] }
    validates :name, length: { maximum: 255 }
    validates :icon_name, length: { maximum: 255 }

    scope :default, -> { where(namespace: nil) }
    scope :order_by_name_asc, -> { order(arel_table[:name].lower.asc) }
    scope :by_type, ->(base_type) { where(base_type: base_type) }

    def self.available_widgets
      WIDGETS_FOR_TYPE.values.flatten.uniq
    end

    def self.default_by_type(type)
      found_type = find_by(namespace_id: nil, base_type: type)
      return found_type if found_type

      Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types
      Gitlab::DatabaseImporters::WorkItems::HierarchyRestrictionsImporter.upsert_restrictions
      find_by(namespace_id: nil, base_type: type)
    end

    def self.default_issue_type
      default_by_type(:issue)
    end

    def self.allowed_types_for_issues
      base_types.keys.excluding('task', 'objective', 'key_result')
    end

    def default?
      namespace.blank?
    end

    def widgets
      WIDGETS_FOR_TYPE[base_type.to_sym]
    end

    private

    def strip_whitespace
      name&.strip!
    end
  end
end

WorkItems::Type.prepend_mod