metadata_presenter 2.12.0 → 2.14.1

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: 120ed63601d40a759fe3176e0555341c7cc7220cc1bac5a87cf58d5989d670fa
4
- data.tar.gz: 84e748f9388d3208ade3db02f37f662e8ab4e7fca1aef8488411dd05dabe6a93
3
+ metadata.gz: b7184f97740de68d7fb003316d4d2bc5a822ccdfa13749c858b638b64b7f59e6
4
+ data.tar.gz: 6d540b23868160de18de5c3ef87c5a9ef2f7ecc279ed72e4e2c9ab5bb3c0369d
5
5
  SHA512:
6
- metadata.gz: 2bd170ba65c91f723ada48baff42bd90228cbf22f5aaa56eb158203b3f497037635bdeaf8e17f760556ad6bf55fb6ed922727c2bae9914e6f9e81cad54d708da
7
- data.tar.gz: 8045ff1fe8a8366bedc081a4864687e7da1f56119ca71285f03bb3457787c9644513e8f54195b5fc6feb8cdbb3fc6d899bbf86b683109f910235e81a01288a05
6
+ metadata.gz: 10c4c37e567f4b1c58546627c480ceda59a1c65bdafeacf65014c044a380a03a7f22f40180674054f5614adc742fd95aca4624b6d8a1af3ac2158b96a0ebbac0
7
+ data.tar.gz: 3eb7004878552017ce8c9e180675330d824461234ad410f11384b788eeb5ab46a480526020a7edf4efd6ece8d1f7588d0cfd2ed3561fe9270d2c936717072b4b
@@ -1,25 +1,46 @@
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
- use_new_column? ? new_column : existing_column
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
16
37
 
17
- def use_new_column?
18
- existing_column.nil? || new_column > existing_column
38
+ def cya_or_confirmation_page?
39
+ [service.checkanswers_page&.uuid, service.confirmation_page&.uuid].include?(uuid)
19
40
  end
20
41
 
21
42
  def existing_column
22
- @existing_column ||= @coordinates.uuid_column(uuid)
43
+ @coordinates.uuid_column(uuid)
23
44
  end
24
45
  end
25
46
  end
@@ -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,29 +34,45 @@ module MetadataPresenter
31
34
  end
32
35
  end
33
36
 
34
- def position(uuid)
35
- positions[uuid]
37
+ def positions_in_column(column_number)
38
+ positions.select { |_, position| position[:column] == column_number }
36
39
  end
37
40
 
38
- def occupied?(column, row, new_object_uuid)
39
- positions.any? do |uuid, position|
40
- position[:column] == column &&
41
- position[:row] == row &&
42
- new_object_uuid != uuid
41
+ def set_branch_spacers_column(branch_uuid, column)
42
+ branch_spacers[branch_uuid].each do |_, position|
43
+ position[:column] = column
43
44
  end
44
45
  end
45
46
 
46
- def positions_in_column(column_number)
47
- positions.select { |_, position| position[:column] == column_number }
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
48
56
  end
49
57
 
50
58
  private
51
59
 
52
- attr_reader :flow
53
- attr_writer :positions
60
+ attr_reader :service
61
+ attr_writer :positions, :branch_spacers
54
62
 
55
63
  def setup_positions
56
- 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
57
76
  end
58
77
  end
59
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,10 +192,13 @@ 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
- @ordered[position[:column]][position[:row]] = get_flow_object(uuid)
198
+ column = position[:column]
199
+ row = position[:row]
200
+ insert_spacer(column, row) if occupied?(column, row, uuid)
201
+ @ordered[column][row] = get_flow_object(uuid)
189
202
  end
190
203
  end
191
204
 
@@ -193,6 +206,11 @@ module MetadataPresenter
193
206
  position[:row].nil? || position[:column].nil?
194
207
  end
195
208
 
209
+ def occupied?(column, row, uuid)
210
+ object = @ordered[column][row]
211
+ object.is_a?(MetadataPresenter::Flow) && object.uuid != uuid
212
+ end
213
+
196
214
  def get_flow_object(uuid)
197
215
  # main_flow is always empty if the Grid is _actually_ building the main flow
198
216
  return MetadataPresenter::Pointer.new(uuid: uuid) if main_flow.include?(uuid)
@@ -236,8 +254,9 @@ module MetadataPresenter
236
254
  end
237
255
 
238
256
  # Each branch has a certain number of exits that require their own line
239
- # and arrow. Insert any spacers into the necessary row in the column after
240
- # 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.
241
260
  def insert_expression_spacers
242
261
  service.branches.each do |branch|
243
262
  next if coordinates.uuid_column(branch.uuid).nil?
@@ -245,14 +264,61 @@ module MetadataPresenter
245
264
  previous_uuid = ''
246
265
  next_column = coordinates.uuid_column(branch.uuid) + 1
247
266
  exiting_destinations_from_branch(branch).each_with_index do |uuid, row|
248
- if uuid == previous_uuid
249
- @ordered[next_column].insert(row, MetadataPresenter::Spacer.new)
250
- end
267
+ insert_spacer(next_column, row) if uuid == previous_uuid
251
268
  previous_uuid = uuid
252
269
  end
253
270
  end
254
271
  end
255
272
 
273
+ def insert_spacer(column, row)
274
+ @ordered[column].insert(row, MetadataPresenter::Spacer.new)
275
+ end
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
+
256
322
  # Any destinations exiting the branch that have not already been traversed.
257
323
  # This removes any branch destinations that already exist on other rows. If
258
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,46 +11,87 @@ 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?
19
-
20
- if object_above.branch? && uuid != object_above.uuid
21
- coordinates.uuid_row(object_above.uuid) + number_of_destinations
22
- else
23
- existing_row.nil? ? current_row : [current_row, existing_row].max
14
+ if service.flow_object(uuid).branch?
15
+ coordinates.set_branch_spacers_row(uuid, calculated_row)
24
16
  end
17
+
18
+ calculated_row
25
19
  end
26
20
 
27
21
  private
28
22
 
29
23
  attr_reader :uuid, :route, :current_row, :coordinates, :service
30
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
+
31
35
  def existing_row
32
36
  @existing_row ||= coordinates.uuid_row(uuid)
33
37
  end
34
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.
41
+ def potential_row
42
+ return if branches_in_column.empty?
43
+
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
58
+ end
59
+
35
60
  def first_row?
36
61
  @first_row ||= route.row.zero?
37
62
  end
38
63
 
39
- def object_above
40
- @object_above ||=
41
- service.flow_object(coordinates.uuid_at_position(uuid_column, row_above))
64
+ def branches_in_column
65
+ @branches_in_column ||= branches(uuid_column)
42
66
  end
43
67
 
44
- # Takes into account the 'or' type of conditionals which requires an
45
- # additional spacer
46
- def number_of_destinations
47
- exiting_destinations_from_branch(object_above).count
68
+ def branches_in_previous_column
69
+ @branches_in_previous_column ||= branches(uuid_column - 1)
48
70
  end
49
71
 
50
- def uuid_column
51
- @uuid_column ||= coordinates.uuid_column(uuid)
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?
77
+ end
52
78
  end
53
79
 
54
- def row_above
55
- @row_above ||= route.row - 1
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
91
+ end
92
+
93
+ def uuid_column
94
+ @uuid_column ||= coordinates.uuid_column(uuid)
56
95
  end
57
96
 
58
97
  # If an object has already been positioned on row 0 then leave it there.
@@ -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",