Class: Board

Inherits:
Object
  • Object
show all
Defined in:
lib/jirametrics/board.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw:, possible_statuses:, features: []) ⇒ Board

Returns a new instance of Board.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/jirametrics/board.rb', line 7

def initialize raw:, possible_statuses:, features: []
  @raw = raw
  @possible_statuses = possible_statuses
  @sprints = []
  @features = features

  columns = raw['columnConfig']['columns']
  ensure_uniqueness_of_column_names! columns

  # For a classic Kanban board (type 'kanban'), the first column will always be called 'Backlog'
  # and will NOT be visible on the board. This does not apply to team-managed boards (type 'simple').
  columns = columns.drop(1) if board_type == 'kanban'

  @backlog_statuses = []
  @visible_columns = columns.filter_map do |column|
    # It's possible for a column to be defined without any statuses and in this case, it won't be visible.
    BoardColumn.new column unless status_ids_from_column(column).empty?
  end
end

Instance Attribute Details

#cycletimeObject

Returns the value of attribute cycletime.



5
6
7
# File 'lib/jirametrics/board.rb', line 5

def cycletime
  @cycletime
end

#possible_statusesObject (readonly)

Returns the value of attribute possible_statuses.



4
5
6
# File 'lib/jirametrics/board.rb', line 4

def possible_statuses
  @possible_statuses
end

#project_configObject

Returns the value of attribute project_config.



5
6
7
# File 'lib/jirametrics/board.rb', line 5

def project_config
  @project_config
end

#rawObject (readonly)

Returns the value of attribute raw.



4
5
6
# File 'lib/jirametrics/board.rb', line 4

def raw
  @raw
end

#sprintsObject (readonly)

Returns the value of attribute sprints.



4
5
6
# File 'lib/jirametrics/board.rb', line 4

def sprints
  @sprints
end

#visible_columnsObject (readonly)

Returns the value of attribute visible_columns.



4
5
6
# File 'lib/jirametrics/board.rb', line 4

def visible_columns
  @visible_columns
end

Instance Method Details

#accumulated_status_ids_per_columnObject



122
123
124
125
126
127
128
129
130
# File 'lib/jirametrics/board.rb', line 122

def accumulated_status_ids_per_column
  accumulated_status_ids = []
  visible_columns.reverse.filter_map do |column|
    next if column == @fake_column

    accumulated_status_ids += column.status_ids
    [column.name, accumulated_status_ids.dup]
  end.reverse
end

#backlog_statusesObject



27
28
29
30
31
32
33
34
35
# File 'lib/jirametrics/board.rb', line 27

def backlog_statuses
  if @backlog_statuses.empty? && board_type == 'kanban'
    status_ids = status_ids_from_column raw['columnConfig']['columns'].first
    @backlog_statuses = status_ids.filter_map do |id|
      @possible_statuses.find_by_id id
    end
  end
  @backlog_statuses
end

#board_typeObject



83
# File 'lib/jirametrics/board.rb', line 83

def board_type = raw['type']

#column_not_found_message(column_name) ⇒ Object

Column-name matching is case-sensitive, so a config asking for "Done" against a board whose column is "DONE" fails -- and that's the mistake people actually make. When only the case differs, name the likely intended column outright instead of making the reader spot it in the list themselves.



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jirametrics/board.rb', line 70

def column_not_found_message column_name
  names = @visible_columns.collect(&:name)
  suggestion = names.find { |name| name.casecmp?(column_name) }
  unless suggestion
    return "No visible column named #{column_name.inspect}. " \
      "The visible columns are: #{names.collect(&:inspect).join(', ')}."
  end

  others = (names - [suggestion]).collect(&:inspect).join(', ')
  "You specified #{column_name.inspect} but probably meant #{suggestion.inspect}. Column names are " \
    "case-sensitive. If that's not it, the other visible columns are: #{others}."
end

#ensure_uniqueness_of_column_names!(json) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/jirametrics/board.rb', line 132

def ensure_uniqueness_of_column_names! json
  all_names = []
  json.each do |column_json|
    name = column_json['name']
    if all_names.include? name
      (2..).each do |i|
        new_name = "#{name}-#{i}"
        next if all_names.include?(new_name)

        name = new_name
        column_json['name'] = new_name
        break
      end
    end
    all_names << name
  end
end

#estimation_configurationObject



150
151
152
# File 'lib/jirametrics/board.rb', line 150

def estimation_configuration
  EstimationConfiguration.new raw: raw['estimation']
end

#idObject



107
108
109
# File 'lib/jirametrics/board.rb', line 107

def id
  @raw['id'].to_i
end

#inspectObject



154
155
156
# File 'lib/jirametrics/board.rb', line 154

def inspect
  "Board(id: #{id}, name: #{name.inspect}, board_type: #{board_type.inspect})"
end

#kanban?Boolean

Returns:

  • (Boolean)


92
93
94
95
96
97
# File 'lib/jirametrics/board.rb', line 92

def kanban?
  return true if board_type == 'kanban'
  return false unless board_type == 'simple'

  !scrum?
end

#nameObject



118
119
120
# File 'lib/jirametrics/board.rb', line 118

def name
  @raw['name']
end

#project_idObject



111
112
113
114
115
116
# File 'lib/jirametrics/board.rb', line 111

def project_id
  location = @raw['location']
  return nil unless location

  location['id'] if location['type'] == 'project'
end

#scrum?Boolean

Returns:

  • (Boolean)


85
86
87
88
89
90
# File 'lib/jirametrics/board.rb', line 85

def scrum?
  return true if board_type == 'scrum'
  return false unless board_type == 'simple'

  sprints_feature?
end

#server_url_prefixObject



37
38
39
40
41
# File 'lib/jirametrics/board.rb', line 37

def server_url_prefix
  raise "Cannot parse self: #{@raw['self'].inspect}" unless %r{^(?<prefix>https?://.+)/rest/} =~ @raw['self']

  prefix
end

#sprints_feature?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/jirametrics/board.rb', line 103

def sprints_feature?
  @features.any? { |f| f.name == 'jsw.agility.sprints' && f.enabled? }
end

#status_ids_from_column(column) ⇒ Object



48
49
50
# File 'lib/jirametrics/board.rb', line 48

def status_ids_from_column column
  column['statuses']&.collect { |status| status['id'].to_i } || []
end

#status_ids_in_or_right_of_column(column_name) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/jirametrics/board.rb', line 52

def status_ids_in_or_right_of_column column_name
  status_ids = []
  found_it = false

  @visible_columns.each do |column|
    # Check both the current name and also the original raw name in case anonymization has happened.
    found_it = true if column.name == column_name || column.raw['name'] == column_name
    status_ids += column.status_ids if found_it
  end

  raise column_not_found_message(column_name) unless found_it

  status_ids
end

#team_managed_kanban?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/jirametrics/board.rb', line 99

def team_managed_kanban?
  board_type == 'simple' && !sprints_feature?
end

#urlObject



43
44
45
46
# File 'lib/jirametrics/board.rb', line 43

def url
  # Strangely, the URL isn't anywhere in the returned data so we have to fabricate it.
  "#{server_url_prefix}/secure/RapidBoard.jspa?rapidView=#{id}"
end