metadata_presenter 2.10.0 → 2.11.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 +4 -4
- data/app/models/metadata_presenter/branch_destinations.rb +18 -0
- data/app/models/metadata_presenter/column_number.rb +25 -0
- data/app/models/metadata_presenter/coordinates.rb +59 -0
- data/app/models/metadata_presenter/grid.rb +48 -41
- data/app/models/metadata_presenter/row_number.rb +71 -0
- data/fixtures/branching_10.json +1271 -0
- data/fixtures/branching_10.png +0 -0
- data/lib/metadata_presenter/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cca8a3428e516ba176e5a898a1d1a76cd57fa836041f0c3fc492a8cd394e88a
|
4
|
+
data.tar.gz: 9940b709ccce5e211444fe6b7cf84dfeed78f1c13591c9291b797a3eca4ac609
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b9c3ae006ca76d0386db74a2fb39d106884dc0cd285457c05be6f3d3f75e2a30cc79511112d3881c532ba7e6e3c087e5e83e4116a708cf3cd81b4ea345de813
|
7
|
+
data.tar.gz: 659da027fb5c27df2c007dfd961bfce0148879aec3833f72c53f4d195080bde041b29c53260c397430e5425383a2c7a364e1ed8fd4d22bbabdb33417ecb896ed
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MetadataPresenter
|
2
|
+
module BranchDestinations
|
3
|
+
# The frontend requires that expressions of type 'or' get there own line and
|
4
|
+
# arrow. 'and' expression types continue to be grouped together.
|
5
|
+
# Return the UUIDs of the destinations exiting a branch and allow duplicates
|
6
|
+
# if the expression type is an 'or'.
|
7
|
+
def exiting_destinations_from_branch(branch)
|
8
|
+
destination_uuids = branch.conditionals.map do |conditional|
|
9
|
+
if conditional.type == 'or'
|
10
|
+
conditional.expressions.map { |_| conditional.next }
|
11
|
+
else
|
12
|
+
conditional.next
|
13
|
+
end
|
14
|
+
end
|
15
|
+
destination_uuids.flatten.push(branch.default_next)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MetadataPresenter
|
2
|
+
class ColumnNumber
|
3
|
+
def initialize(uuid:, coordinates:, new_column:)
|
4
|
+
@uuid = uuid
|
5
|
+
@coordinates = coordinates
|
6
|
+
@new_column = new_column
|
7
|
+
end
|
8
|
+
|
9
|
+
def number
|
10
|
+
use_new_column? ? new_column : existing_column
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :uuid, :coordinates, :new_column
|
16
|
+
|
17
|
+
def use_new_column?
|
18
|
+
existing_column.nil? || new_column > existing_column
|
19
|
+
end
|
20
|
+
|
21
|
+
def existing_column
|
22
|
+
@existing_column ||= @coordinates.uuid_column(uuid)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module MetadataPresenter
|
2
|
+
class Coordinates
|
3
|
+
def initialize(flow)
|
4
|
+
@flow = flow
|
5
|
+
@positions = setup_positions
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :positions
|
9
|
+
|
10
|
+
def set_column(uuid, number)
|
11
|
+
positions[uuid][:column] = number
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_row(uuid, number)
|
15
|
+
positions[uuid][:row] = number
|
16
|
+
end
|
17
|
+
|
18
|
+
def uuid_column(uuid)
|
19
|
+
positions[uuid][:column]
|
20
|
+
end
|
21
|
+
|
22
|
+
def uuid_row(uuid)
|
23
|
+
positions[uuid][:row]
|
24
|
+
end
|
25
|
+
|
26
|
+
def uuid_at_position(column, row)
|
27
|
+
positions.find do |uuid, position|
|
28
|
+
if position[:column] == column && position[:row] == row
|
29
|
+
return uuid
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def position(uuid)
|
35
|
+
positions[uuid]
|
36
|
+
end
|
37
|
+
|
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
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def positions_in_column(column_number)
|
47
|
+
positions.select { |_, position| position[:column] == column_number }
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :flow
|
53
|
+
attr_writer :positions
|
54
|
+
|
55
|
+
def setup_positions
|
56
|
+
flow.keys.index_with { |_uuid| { row: nil, column: nil } }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -12,6 +12,7 @@ module MetadataPresenter
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class Grid
|
15
|
+
include BranchDestinations
|
15
16
|
attr_reader :start_from
|
16
17
|
|
17
18
|
def initialize(service, start_from: nil, main_flow: [])
|
@@ -21,7 +22,7 @@ module MetadataPresenter
|
|
21
22
|
@ordered = []
|
22
23
|
@routes = []
|
23
24
|
@traversed = []
|
24
|
-
@coordinates =
|
25
|
+
@coordinates = MetadataPresenter::Coordinates.new(service.flow)
|
25
26
|
end
|
26
27
|
|
27
28
|
ROW_ZERO = 0
|
@@ -30,8 +31,8 @@ module MetadataPresenter
|
|
30
31
|
return @ordered unless @ordered.empty?
|
31
32
|
|
32
33
|
@ordered = make_grid
|
33
|
-
|
34
|
-
|
34
|
+
set_column_numbers
|
35
|
+
set_row_numbers
|
35
36
|
add_by_coordinates
|
36
37
|
insert_expression_spacers
|
37
38
|
trim_pointers unless main_flow.empty?
|
@@ -62,10 +63,6 @@ module MetadataPresenter
|
|
62
63
|
attr_reader :service, :main_flow
|
63
64
|
attr_accessor :ordered, :traversed, :routes, :coordinates
|
64
65
|
|
65
|
-
def setup_coordinates
|
66
|
-
service.flow.keys.index_with { |_uuid| { row: nil, column: nil } }
|
67
|
-
end
|
68
|
-
|
69
66
|
def route_from_start
|
70
67
|
@route_from_start ||=
|
71
68
|
MetadataPresenter::Route.new(
|
@@ -83,7 +80,12 @@ module MetadataPresenter
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def max_potential_rows
|
86
|
-
@max_potential_rows ||=
|
83
|
+
@max_potential_rows ||= begin
|
84
|
+
destinations_count = service.branches.map do |branch|
|
85
|
+
exiting_destinations_from_branch(branch).count
|
86
|
+
end
|
87
|
+
destinations_count.sum
|
88
|
+
end
|
87
89
|
end
|
88
90
|
|
89
91
|
def max_potential_columns
|
@@ -121,29 +123,47 @@ module MetadataPresenter
|
|
121
123
|
end
|
122
124
|
end
|
123
125
|
|
124
|
-
def
|
126
|
+
def set_column_numbers
|
125
127
|
@routes.each do |route|
|
126
|
-
route.flow_uuids.each.with_index(route.column) do |uuid,
|
127
|
-
column_number =
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
route.flow_uuids.each.with_index(route.column) do |uuid, new_column|
|
129
|
+
column_number = MetadataPresenter::ColumnNumber.new(
|
130
|
+
uuid: uuid,
|
131
|
+
new_column: new_column,
|
132
|
+
coordinates: @coordinates
|
133
|
+
).number
|
134
|
+
@coordinates.set_column(uuid, column_number)
|
131
135
|
end
|
132
136
|
end
|
133
137
|
end
|
134
138
|
|
135
|
-
def
|
139
|
+
def set_row_numbers
|
136
140
|
@routes.each do |route|
|
137
|
-
next if @traversed.include?(route.traverse_from)
|
141
|
+
next if @traversed.include?(route.traverse_from) && appears_later_in_flow?(route)
|
138
142
|
|
143
|
+
current_row = route.row
|
139
144
|
route.flow_uuids.each do |uuid|
|
140
|
-
|
145
|
+
row_number = MetadataPresenter::RowNumber.new(
|
146
|
+
uuid: uuid,
|
147
|
+
route: route,
|
148
|
+
current_row: current_row,
|
149
|
+
coordinates: @coordinates,
|
150
|
+
service: service
|
151
|
+
).number
|
152
|
+
@coordinates.set_row(uuid, row_number)
|
153
|
+
|
141
154
|
update_route_rows(route, uuid)
|
142
155
|
@traversed.push(uuid) unless @traversed.include?(uuid)
|
156
|
+
current_row = row_number
|
143
157
|
end
|
144
158
|
end
|
145
159
|
end
|
146
160
|
|
161
|
+
# New routes can be linked to later. We need to also traverse these to see
|
162
|
+
# if anything should be moved to a different row.
|
163
|
+
def appears_later_in_flow?(route)
|
164
|
+
@coordinates.uuid_column(route.traverse_from) > route.column
|
165
|
+
end
|
166
|
+
|
147
167
|
# Each Route object has a starting row. Each Route object has no knowledge
|
148
168
|
# of other potential routes and pages/branches that may or may not exist in
|
149
169
|
# them. The starting row may need to change dependent upon what has been
|
@@ -161,7 +181,8 @@ module MetadataPresenter
|
|
161
181
|
end
|
162
182
|
|
163
183
|
def add_by_coordinates
|
164
|
-
|
184
|
+
service.flow.each_key do |uuid|
|
185
|
+
position = coordinates.position(uuid)
|
165
186
|
next if detached?(position)
|
166
187
|
|
167
188
|
@ordered[position[:column]][position[:row]] = get_flow_object(uuid)
|
@@ -219,37 +240,23 @@ module MetadataPresenter
|
|
219
240
|
# the one the branch is located in.
|
220
241
|
def insert_expression_spacers
|
221
242
|
service.branches.each do |branch|
|
222
|
-
|
223
|
-
next if position[:row].nil? || position[:column].nil? # detached branch
|
243
|
+
next if coordinates.uuid_column(branch.uuid).nil?
|
224
244
|
|
225
|
-
|
226
|
-
|
227
|
-
exiting_destinations_from_branch(branch).
|
228
|
-
if
|
245
|
+
previous_uuid = ''
|
246
|
+
next_column = coordinates.uuid_column(branch.uuid) + 1
|
247
|
+
exiting_destinations_from_branch(branch).each_with_index do |uuid, row|
|
248
|
+
if uuid == previous_uuid
|
229
249
|
@ordered[next_column].insert(row, MetadataPresenter::Spacer.new)
|
230
250
|
end
|
231
|
-
|
232
|
-
uuids.push(uuid) unless uuids.include?(uuid)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
# The frontend requires that expressions of type 'or' get there own line and
|
238
|
-
# arrow. 'and' expression types continue to be grouped together.
|
239
|
-
# Return the UUIDs of the destinations exiting a branch and allow duplicates
|
240
|
-
# if the expression type is an 'or'.
|
241
|
-
def exiting_destinations_from_branch(branch)
|
242
|
-
destination_uuids = branch.conditionals.map do |conditional|
|
243
|
-
if conditional.type == 'or'
|
244
|
-
conditional.expressions.map(&:next)
|
245
|
-
else
|
246
|
-
conditional.next
|
251
|
+
previous_uuid = uuid
|
247
252
|
end
|
248
253
|
end
|
249
|
-
destination_uuids.flatten
|
250
254
|
end
|
251
255
|
|
252
256
|
# Any destinations exiting the branch that have not already been traversed.
|
257
|
+
# This removes any branch destinations that already exist on other rows. If
|
258
|
+
# that is the case then the arrow will flow towards whatever row that object
|
259
|
+
# is located.
|
253
260
|
def routes_exiting_branch(branch)
|
254
261
|
branch.all_destination_uuids.reject { |uuid| @traversed.include?(uuid) }
|
255
262
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module MetadataPresenter
|
2
|
+
class RowNumber
|
3
|
+
include BranchDestinations
|
4
|
+
|
5
|
+
def initialize(uuid:, route:, current_row:, coordinates:, service:)
|
6
|
+
@uuid = uuid
|
7
|
+
@route = route
|
8
|
+
@current_row = current_row
|
9
|
+
@coordinates = coordinates
|
10
|
+
@service = service
|
11
|
+
end
|
12
|
+
|
13
|
+
ROW_ZERO = 0
|
14
|
+
|
15
|
+
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
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :uuid, :route, :current_row, :coordinates, :service
|
30
|
+
|
31
|
+
def existing_row
|
32
|
+
@existing_row ||= coordinates.uuid_row(uuid)
|
33
|
+
end
|
34
|
+
|
35
|
+
def first_row?
|
36
|
+
@first_row ||= route.row.zero?
|
37
|
+
end
|
38
|
+
|
39
|
+
def object_above
|
40
|
+
@object_above ||=
|
41
|
+
service.flow_object(coordinates.uuid_at_position(uuid_column, row_above))
|
42
|
+
end
|
43
|
+
|
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
|
48
|
+
end
|
49
|
+
|
50
|
+
def uuid_column
|
51
|
+
@uuid_column ||= coordinates.uuid_column(uuid)
|
52
|
+
end
|
53
|
+
|
54
|
+
def row_above
|
55
|
+
@row_above ||= route.row - 1
|
56
|
+
end
|
57
|
+
|
58
|
+
# If an object has already been positioned on row 0 then leave it there.
|
59
|
+
# If the object is a checkanswers or confirmation type then always place it
|
60
|
+
# on row 0.
|
61
|
+
def place_on_row_zero?
|
62
|
+
cya_or_confirmation_page? || coordinates.uuid_row(uuid) == ROW_ZERO
|
63
|
+
end
|
64
|
+
|
65
|
+
def cya_or_confirmation_page?
|
66
|
+
%w[page.checkanswers page.confirmation].include?(
|
67
|
+
service.find_page_by_uuid(uuid)&.type
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|