metadata_presenter 2.12.1 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a349beb4173c1f6361b321a95e36a407c5f5361153403cae2fbd15ffb7b8840
4
- data.tar.gz: 8e06745f55b04f1074a5da27b77e4f9cb720b95bfb328672c14cca059e4a3003
3
+ metadata.gz: 403f05545513e03fa74a28791ce736ec7cde6812e27f412ba8c60f8b18f8766c
4
+ data.tar.gz: 2f8eddc4cb7cbb664d3b7577f56c50fe6a6e27326aa1bf5ef449eaec66940b78
5
5
  SHA512:
6
- metadata.gz: 01f7f93e1b0d7a058ff856cb27ce07ec816b060e2b2299cec55be298aa046809a9e9ba82f9f770205b4fe647a8d3e046e1a0b10afad0a78fc5190e52aa28fc5f
7
- data.tar.gz: 5cb518f2fb78f26ae06d447d0d1a7a7f2b84de9b4f24057079464bdcd77945c36430c4718c49d1bc2a04ec48ab1cfb422fbfc02c952a516ca83d7cae3e29a2ff
6
+ metadata.gz: 627b8dc27af8939370194ce5a7bd753da8f7213f147b1140698b4a9f7e22f087722975293d7dee622abc983a612be4d877b71be4b9655fb58f7f620aab6c5c7b
7
+ data.tar.gz: 2a8c603f96b6692d851773db995a34b2ad232f60c766126b0ef5063531d5faad96572f8c576ebbd13a3c50aa06a8fb9f66773355355e1325b6be564327e3823e
@@ -1,18 +1,43 @@
1
1
  module MetadataPresenter
2
2
  class ColumnNumber
3
- def initialize(uuid:, coordinates:, new_column:)
3
+ def initialize(uuid:, coordinates:, new_column:, service:)
4
4
  @uuid = uuid
5
5
  @coordinates = coordinates
6
6
  @new_column = new_column
7
+ @service = service
7
8
  end
8
9
 
9
10
  def number
10
- [existing_column, new_column].compact.max
11
+ if service.flow_object(uuid).branch?
12
+ # Even though we are associating the column number to a specific flow object
13
+ # in the Coordinates model we do not use column_number + 1 as we are
14
+ # updating the position for the Spacers that exist for a branch which
15
+ # are always in the same column as the branch object itself.
16
+ coordinates.set_branch_spacers_column(uuid, column_number)
17
+ end
18
+
19
+ column_number
11
20
  end
12
21
 
13
22
  private
14
23
 
15
- attr_reader :uuid, :coordinates, :new_column
24
+ attr_reader :uuid, :coordinates, :new_column, :service
25
+
26
+ def column_number
27
+ @column_number ||= begin
28
+ return latest_column if cya_or_confirmation_page?
29
+
30
+ existing_column || new_column
31
+ end
32
+ end
33
+
34
+ def latest_column
35
+ [existing_column, new_column].compact.max
36
+ end
37
+
38
+ def cya_or_confirmation_page?
39
+ [service.checkanswers_page&.uuid, service.confirmation_page&.uuid].include?(uuid)
40
+ end
16
41
 
17
42
  def existing_column
18
43
  @coordinates.uuid_column(uuid)
@@ -1,11 +1,14 @@
1
1
  module MetadataPresenter
2
2
  class Coordinates
3
- def initialize(flow)
4
- @flow = flow
3
+ include BranchDestinations
4
+
5
+ def initialize(service)
6
+ @service = service
5
7
  @positions = setup_positions
8
+ @branch_spacers = setup_branch_spacers
6
9
  end
7
10
 
8
- attr_reader :positions
11
+ attr_reader :positions, :branch_spacers
9
12
 
10
13
  def set_column(uuid, number)
11
14
  positions[uuid][:column] = number
@@ -31,21 +34,45 @@ module MetadataPresenter
31
34
  end
32
35
  end
33
36
 
34
- def position(uuid)
35
- positions[uuid]
36
- end
37
-
38
37
  def positions_in_column(column_number)
39
38
  positions.select { |_, position| position[:column] == column_number }
40
39
  end
41
40
 
41
+ def set_branch_spacers_column(branch_uuid, column)
42
+ branch_spacers[branch_uuid].each do |_, position|
43
+ position[:column] = column
44
+ end
45
+ end
46
+
47
+ # The first conditional will always attempt to draw an arrow on the same row
48
+ # as the branch object.
49
+ # Each following conditional needs to have a spacers in order for the frontend
50
+ # to draw an arrow therefore we increment the row number from the branches
51
+ # calculated starting row
52
+ def set_branch_spacers_row(branch_uuid, starting_row)
53
+ branch_spacers[branch_uuid].each.with_index(starting_row) do |(_, position), row|
54
+ position[:row] = row
55
+ end
56
+ end
57
+
42
58
  private
43
59
 
44
- attr_reader :flow
45
- attr_writer :positions
60
+ attr_reader :service
61
+ attr_writer :positions, :branch_spacers
46
62
 
47
63
  def setup_positions
48
- flow.keys.index_with { |_uuid| { row: nil, column: nil } }
64
+ service.flow.keys.index_with { |_uuid| { row: nil, column: nil } }
65
+ end
66
+
67
+ # This also takes into account the 'OR' expressions which
68
+ # need an additional line for an arrow.
69
+ def setup_branch_spacers
70
+ service.branches.each.with_object({}) do |branch, hash|
71
+ destinations = exiting_destinations_from_branch(branch)
72
+ hash[branch.uuid] = destinations.index_with do |_uuid|
73
+ { row: nil, column: nil }
74
+ end
75
+ end
49
76
  end
50
77
  end
51
78
  end
@@ -11,6 +11,12 @@ module MetadataPresenter
11
11
  end
12
12
  end
13
13
 
14
+ class Warning < OpenStruct
15
+ def type
16
+ 'flow.warning'
17
+ end
18
+ end
19
+
14
20
  class Grid
15
21
  include BranchDestinations
16
22
  attr_reader :start_from
@@ -22,7 +28,7 @@ module MetadataPresenter
22
28
  @ordered = []
23
29
  @routes = []
24
30
  @traversed = []
25
- @coordinates = MetadataPresenter::Coordinates.new(service.flow)
31
+ @coordinates = MetadataPresenter::Coordinates.new(service)
26
32
  end
27
33
 
28
34
  ROW_ZERO = 0
@@ -37,13 +43,16 @@ module MetadataPresenter
37
43
  insert_expression_spacers
38
44
  trim_pointers unless main_flow.empty?
39
45
  trim_spacers
46
+ insert_warning if main_flow.empty?
40
47
 
41
48
  @ordered = @ordered.reject(&:empty?)
42
49
  end
43
50
 
44
51
  def ordered_flow
45
52
  @ordered_flow ||=
46
- build.flatten.reject { |obj| obj.is_a?(MetadataPresenter::Spacer) }
53
+ build.flatten.reject do |obj|
54
+ obj.is_a?(MetadataPresenter::Spacer) || obj.is_a?(MetadataPresenter::Warning)
55
+ end
47
56
  end
48
57
 
49
58
  def ordered_pages
@@ -129,7 +138,8 @@ module MetadataPresenter
129
138
  column_number = MetadataPresenter::ColumnNumber.new(
130
139
  uuid: uuid,
131
140
  new_column: new_column,
132
- coordinates: @coordinates
141
+ coordinates: @coordinates,
142
+ service: service
133
143
  ).number
134
144
  @coordinates.set_column(uuid, column_number)
135
145
  end
@@ -182,7 +192,7 @@ module MetadataPresenter
182
192
 
183
193
  def add_by_coordinates
184
194
  service.flow.each_key do |uuid|
185
- position = coordinates.position(uuid)
195
+ position = coordinates.positions[uuid]
186
196
  next if detached?(position)
187
197
 
188
198
  column = position[:column]
@@ -244,8 +254,9 @@ module MetadataPresenter
244
254
  end
245
255
 
246
256
  # Each branch has a certain number of exits that require their own line
247
- # and arrow. Insert any spacers into the necessary row in the column after
248
- # the one the branch is located in.
257
+ # and arrow. When there are 'OR' conditions we need to insert additional
258
+ # spacers into the necessary row in the column after the one the branch is
259
+ # located in.
249
260
  def insert_expression_spacers
250
261
  service.branches.each do |branch|
251
262
  next if coordinates.uuid_column(branch.uuid).nil?
@@ -263,6 +274,51 @@ module MetadataPresenter
263
274
  @ordered[column].insert(row, MetadataPresenter::Spacer.new)
264
275
  end
265
276
 
277
+ # Include a warning if a service does not have a CYA or Confirmation page in the
278
+ # main flow. The warning should always be in the first row, last column.
279
+ def insert_warning
280
+ if cya_and_confirmation_pages_not_in_service? ||
281
+ cya_and_confirmation_pages_detached?
282
+ @ordered.append([MetadataPresenter::Warning.new])
283
+ end
284
+ end
285
+
286
+ def cya_and_confirmation_pages_not_in_service?
287
+ (checkanswers_not_in_service? && confirmation_not_in_service?) ||
288
+ checkanswers_not_in_service? ||
289
+ confirmation_not_in_service?
290
+ end
291
+
292
+ def checkanswers_not_in_service?
293
+ service.checkanswers_page.blank?
294
+ end
295
+
296
+ def confirmation_not_in_service?
297
+ service.confirmation_page.blank?
298
+ end
299
+
300
+ def cya_and_confirmation_pages_detached?
301
+ (checkanswers_detached? && confirmation_detached?) ||
302
+ checkanswers_detached? ||
303
+ confirmation_detached?
304
+ end
305
+
306
+ def checkanswers_detached?
307
+ if service.checkanswers_page.present?
308
+ uuid = service.checkanswers_page.uuid
309
+ position = coordinates.positions[uuid]
310
+ detached?(position)
311
+ end
312
+ end
313
+
314
+ def confirmation_detached?
315
+ if service.confirmation_page.present?
316
+ uuid = service.confirmation_page.uuid
317
+ position = coordinates.positions[uuid]
318
+ detached?(position)
319
+ end
320
+ end
321
+
266
322
  # Any destinations exiting the branch that have not already been traversed.
267
323
  # This removes any branch destinations that already exist on other rows. If
268
324
  # that is the case then the arrow will flow towards whatever row that object
@@ -1,7 +1,5 @@
1
1
  module MetadataPresenter
2
2
  class RowNumber
3
- include BranchDestinations
4
-
5
3
  def initialize(uuid:, route:, current_row:, coordinates:, service:)
6
4
  @uuid = uuid
7
5
  @route = route
@@ -13,53 +11,83 @@ module MetadataPresenter
13
11
  ROW_ZERO = 0
14
12
 
15
13
  def number
16
- return route.row if first_row? && existing_row.nil?
17
-
18
- return ROW_ZERO if place_on_row_zero?
14
+ if service.flow_object(uuid).branch?
15
+ coordinates.set_branch_spacers_row(uuid, calculated_row)
16
+ end
19
17
 
20
- [current_row, existing_row, potential_row].compact.max
18
+ calculated_row
21
19
  end
22
20
 
23
21
  private
24
22
 
25
23
  attr_reader :uuid, :route, :current_row, :coordinates, :service
26
24
 
25
+ def calculated_row
26
+ @calculated_row ||= begin
27
+ return route.row if first_row? && existing_row.nil?
28
+
29
+ return ROW_ZERO if place_on_row_zero?
30
+
31
+ existing_row || [current_row, potential_row, branch_spacer_row].compact.max
32
+ end
33
+ end
34
+
27
35
  def existing_row
28
36
  @existing_row ||= coordinates.uuid_row(uuid)
29
37
  end
30
38
 
39
+ # This looks for any branches in the current column and checks that there is
40
+ # enough space for the any branch conditionals before returning a row number.
31
41
  def potential_row
32
- return unless object_above.branch? && uuid != object_above.uuid
42
+ return if branches_in_column.empty?
33
43
 
34
- coordinates.uuid_row(object_above.uuid) + number_of_destinations
44
+ row_numbers = branches_in_column.map do |branch_uuid, _|
45
+ coordinates.branch_spacers[branch_uuid].map { |_, position| position[:row] }
46
+ end
47
+ row_numbers.flatten.max + 1
48
+ end
49
+
50
+ # This looks at the previous column and finds any branches that link to the
51
+ # current object. If any are found it checks for rows numbers that relate
52
+ # to the current objects UUID in the branch spacers hash and defaults to
53
+ # returning the highest row number.
54
+ def branch_spacer_row
55
+ return if spacers_for_current_object.empty?
56
+
57
+ spacers_for_current_object.map { |position| position[:row] }.max
35
58
  end
36
59
 
37
60
  def first_row?
38
61
  @first_row ||= route.row.zero?
39
62
  end
40
63
 
41
- def object_above
42
- @object_above ||=
43
- service.flow_object(
44
- coordinates.uuid_at_position(uuid_column, row_number_for_object_above)
45
- )
64
+ def branches_in_column
65
+ @branches_in_column ||= branches(uuid_column)
46
66
  end
47
67
 
48
- def row_number_for_object_above
49
- column_objects.map { |_, p| p[:row] if p[:row] < current_row }.compact.max.to_i
68
+ def branches_in_previous_column
69
+ @branches_in_previous_column ||= branches(uuid_column - 1)
50
70
  end
51
71
 
52
- def column_objects
53
- objects_in_column = coordinates.positions_in_column(uuid_column).reject do |u, p|
54
- u == uuid || p[:row].nil?
72
+ def branches(column_number)
73
+ coordinates.positions_in_column(column_number).select do |key, position|
74
+ next if uuid == key || position[:row].blank?
75
+
76
+ service.flow_object(key).branch?
55
77
  end
56
- objects_in_column.sort_by { |_, p| p[:row] }
57
78
  end
58
79
 
59
- # Takes into account the 'or' type of conditionals which requires an
60
- # additional spacer
61
- def number_of_destinations
62
- exiting_destinations_from_branch(object_above).count
80
+ def spacers_for_current_object
81
+ @spacers_for_current_object ||= begin
82
+ spacer_positions = branches_in_previous_column.select do |key, _|
83
+ coordinates.branch_spacers[key]
84
+ end
85
+
86
+ current_object_spacers = spacer_positions.map do |branch_uuid, _|
87
+ coordinates.branch_spacers[branch_uuid][uuid]
88
+ end
89
+ current_object_spacers.compact
90
+ end
63
91
  end
64
92
 
65
93
  def uuid_column
@@ -60,6 +60,12 @@ class MetadataPresenter::Service < MetadataPresenter::Metadata
60
60
  end
61
61
  end
62
62
 
63
+ def checkanswers_page
64
+ @checkanswers_page ||= pages.find do |page|
65
+ page.type == 'page.checkanswers'
66
+ end
67
+ end
68
+
63
69
  def meta
64
70
  MetadataPresenter::Meta.new(configuration['meta'])
65
71
  end
@@ -1202,7 +1202,7 @@
1202
1202
  "created_by": "30b04817-8997-43ac-8f34-2ad817a966ea",
1203
1203
  "service_id": "14959589-1731-404d-a4c4-c3e8d85ed22c",
1204
1204
  "version_id": "7279554f-2d0a-4eec-b168-a0156d980bd2",
1205
- "service_name": "Branching 10 ",
1205
+ "service_name": "Branching Fixture 10 ",
1206
1206
  "configuration": {
1207
1207
  "meta": {
1208
1208
  "_id": "config.meta",