metadata_presenter 2.15.7 → 2.15.11
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 +4 -0
- data/app/models/metadata_presenter/column_number.rb +20 -3
- data/app/models/metadata_presenter/coordinates.rb +10 -6
- data/app/models/metadata_presenter/grid.rb +103 -5
- data/app/models/metadata_presenter/row_number.rb +3 -3
- data/app/operators/metadata_presenter/contains_operator.rb +11 -0
- data/app/operators/metadata_presenter/does_not_contain_operator.rb +11 -0
- data/config/initializers/inflections.rb +1 -0
- data/fixtures/branching_10.json +23 -36
- data/fixtures/branching_10.png +0 -0
- data/lib/metadata_presenter/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eed2edbd83d209d0d3dbe101acba9e00e58a97c15d6f808e702c973a785d9ca9
|
4
|
+
data.tar.gz: 3edc797ab259c41f3b64ba3beb35825ef7a7a699b6057baf8f2e37255f789c6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c623243b91fc49d8656c71daea983dfb23eec612e61b374a3d7ae356047162ad6e273ca292639f0ef830e7c15b30a06754cf06e6c117873773fb9fb6a4a5c36c
|
7
|
+
data.tar.gz: abe236b3cbf2674c92716a5b89fb6b5fe41b5e3c34eeb67b3d57b71b2a439109dbd6ed3827e0829a8ee4983c6e5ec4f3a470e1c42d85dc4b7d491948f2762360
|
@@ -25,18 +25,35 @@ module MetadataPresenter
|
|
25
25
|
|
26
26
|
def column_number
|
27
27
|
@column_number ||= begin
|
28
|
-
return
|
28
|
+
return last_column if confirmation_page?
|
29
|
+
return latest_column if checkanswers_page?
|
29
30
|
|
30
31
|
existing_column || new_column
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
35
|
+
def confirmation_page?
|
36
|
+
service.confirmation_page&.uuid == uuid
|
37
|
+
end
|
38
|
+
|
39
|
+
def checkanswers_page?
|
40
|
+
service.checkanswers_page&.uuid == uuid
|
41
|
+
end
|
42
|
+
|
34
43
|
def latest_column
|
35
44
|
[existing_column, new_column].compact.max
|
36
45
|
end
|
37
46
|
|
38
|
-
def
|
39
|
-
|
47
|
+
def last_column
|
48
|
+
checkanswers_column.present? ? checkanswers_column + 1 : latest_column
|
49
|
+
end
|
50
|
+
|
51
|
+
def checkanswers_column
|
52
|
+
@checkanswers_column ||= begin
|
53
|
+
return if service.checkanswers_page.blank?
|
54
|
+
|
55
|
+
coordinates.uuid_column(service.checkanswers_page&.uuid)
|
56
|
+
end
|
40
57
|
end
|
41
58
|
|
42
59
|
def existing_column
|
@@ -39,7 +39,7 @@ module MetadataPresenter
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def set_branch_spacers_column(branch_uuid, column)
|
42
|
-
branch_spacers[branch_uuid].each do |
|
42
|
+
branch_spacers[branch_uuid].each do |position|
|
43
43
|
position[:column] = column
|
44
44
|
end
|
45
45
|
end
|
@@ -50,7 +50,7 @@ module MetadataPresenter
|
|
50
50
|
# to draw an arrow therefore we increment the row number from the branches
|
51
51
|
# calculated starting row
|
52
52
|
def set_branch_spacers_row(branch_uuid, starting_row)
|
53
|
-
branch_spacers[branch_uuid].each.with_index(starting_row) do |
|
53
|
+
branch_spacers[branch_uuid].each.with_index(starting_row) do |position, row|
|
54
54
|
position[:row] = row
|
55
55
|
end
|
56
56
|
end
|
@@ -68,11 +68,15 @@ module MetadataPresenter
|
|
68
68
|
# need an additional line for an arrow.
|
69
69
|
def setup_branch_spacers
|
70
70
|
service.branches.each.with_object({}) do |branch, hash|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
hash[branch.uuid] = initial_spacer(branch)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initial_spacer(branch)
|
76
|
+
destinations = exiting_destinations_from_branch(branch).map do |uuid|
|
77
|
+
{ uuid: uuid, row: nil, column: nil }
|
75
78
|
end
|
79
|
+
has_or_conditionals?(branch) ? destinations.uniq : destinations
|
76
80
|
end
|
77
81
|
end
|
78
82
|
end
|
@@ -41,7 +41,7 @@ module MetadataPresenter
|
|
41
41
|
set_row_numbers
|
42
42
|
add_by_coordinates
|
43
43
|
insert_expression_spacers
|
44
|
-
trim_pointers unless main_flow.empty?
|
44
|
+
trim_pointers unless main_flow.empty? # only used by detached grids
|
45
45
|
trim_spacers
|
46
46
|
insert_warning if main_flow.empty?
|
47
47
|
|
@@ -222,9 +222,42 @@ module MetadataPresenter
|
|
222
222
|
service.flow_object(uuid)
|
223
223
|
end
|
224
224
|
|
225
|
+
def trim_pointers
|
226
|
+
update_branch_destination_pointers
|
227
|
+
trim_to_first_pointer
|
228
|
+
update_coordinates
|
229
|
+
replace_pointers
|
230
|
+
end
|
231
|
+
|
232
|
+
# Since a detached grid is built in the same way as the main flow grid, objects
|
233
|
+
# that appear later in the flow are left in their latest position. However
|
234
|
+
# for detached grids we want to show a Pointer to that object. This only
|
235
|
+
# happens for branch destinations so in those instances we need to replace
|
236
|
+
# the Spacers with Pointers.
|
237
|
+
def update_branch_destination_pointers
|
238
|
+
@ordered.each_with_index do |column, column_number|
|
239
|
+
next_column = column_number + 1
|
240
|
+
|
241
|
+
column.each do |flow_object|
|
242
|
+
next unless flow_object.branch?
|
243
|
+
|
244
|
+
coordinates.branch_spacers[flow_object.uuid].map do |destination|
|
245
|
+
if replace_with_pointer?(next_column, destination[:row], destination[:uuid])
|
246
|
+
@ordered[next_column][destination[:row]] = MetadataPresenter::Pointer.new(uuid: destination[:uuid])
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def replace_with_pointer?(column_number, row_number, destination_uuid)
|
254
|
+
@ordered[column_number][row_number].is_a?(MetadataPresenter::Spacer) &&
|
255
|
+
main_flow.include?(destination_uuid)
|
256
|
+
end
|
257
|
+
|
225
258
|
# A row should end at the first Pointer object it finds.
|
226
259
|
# Therefore replace any Pointers after the first one with Spacers.
|
227
|
-
def
|
260
|
+
def trim_to_first_pointer
|
228
261
|
max_potential_rows.times do |row|
|
229
262
|
first_index_of = first_pointer(row)
|
230
263
|
next unless first_index_of
|
@@ -237,8 +270,70 @@ module MetadataPresenter
|
|
237
270
|
end
|
238
271
|
|
239
272
|
def first_pointer(row)
|
240
|
-
row_objects
|
241
|
-
|
273
|
+
row_objects(row).find_index { |obj| obj.is_a?(MetadataPresenter::Pointer) }
|
274
|
+
end
|
275
|
+
|
276
|
+
def row_objects(row)
|
277
|
+
@ordered.map { |column| column[row] }
|
278
|
+
end
|
279
|
+
|
280
|
+
# It's a shame to have to do this.
|
281
|
+
# Once the Pointers have been trimmed back the original positions for each
|
282
|
+
# object will no longer be correct so we need to update them.
|
283
|
+
# We only really need to do this because we replace Pointers with Spacers
|
284
|
+
# later on.
|
285
|
+
def update_coordinates
|
286
|
+
@ordered.each_with_index do |column, column_number|
|
287
|
+
column.each_with_index do |flow_object, row_number|
|
288
|
+
next if flow_object.is_a?(MetadataPresenter::Spacer)
|
289
|
+
|
290
|
+
@coordinates.set_column(flow_object.uuid, column_number)
|
291
|
+
@coordinates.set_row(flow_object.uuid, row_number)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def replace_pointers
|
297
|
+
@ordered.each_with_index do |column, column_number|
|
298
|
+
next if column_number.zero?
|
299
|
+
|
300
|
+
column.each_with_index do |flow_object, row_number|
|
301
|
+
next if flow_object.is_a?(MetadataPresenter::Spacer)
|
302
|
+
|
303
|
+
previous_column = column_number - 1
|
304
|
+
if replace_with_spacer?(previous_column, column_number, row_number, flow_object.uuid)
|
305
|
+
@ordered[column_number][row_number] = MetadataPresenter::Spacer.new
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def replace_with_spacer?(previous_column, current_column, row_number, uuid)
|
312
|
+
no_flow_objects?(previous_column, row_number, uuid) ||
|
313
|
+
at_different_position?(current_column, row_number, uuid)
|
314
|
+
end
|
315
|
+
|
316
|
+
# Unless the destination is the Pointer for a branch in the directly preceeding
|
317
|
+
# column, we want to swap Pointers for Spacers if there are no Flow objects
|
318
|
+
# in that row.
|
319
|
+
def no_flow_objects?(previous_column, row_number, uuid)
|
320
|
+
!branch_destination?(uuid, previous_column) &&
|
321
|
+
row_objects(row_number).none?(MetadataPresenter::Flow)
|
322
|
+
end
|
323
|
+
|
324
|
+
# The object already exists elsewhere in the flow so we can replace the Pointer
|
325
|
+
# and let the frontend draw an arrow to that position.
|
326
|
+
def at_different_position?(column_number, row_number, uuid)
|
327
|
+
@coordinates.uuid_column(uuid) != column_number &&
|
328
|
+
@coordinates.uuid_row(uuid) != row_number
|
329
|
+
end
|
330
|
+
|
331
|
+
def branch_destination?(uuid, column_number)
|
332
|
+
@ordered[column_number].any? do |flow_object|
|
333
|
+
next unless flow_object.branch?
|
334
|
+
|
335
|
+
flow_object.all_destination_uuids.include?(uuid)
|
336
|
+
end
|
242
337
|
end
|
243
338
|
|
244
339
|
# Find the very last MetadataPresenter::Flow object in every column and
|
@@ -254,17 +349,20 @@ module MetadataPresenter
|
|
254
349
|
end
|
255
350
|
|
256
351
|
def only_spacers?(trimmed_column)
|
257
|
-
trimmed_column.all?
|
352
|
+
trimmed_column.all?(MetadataPresenter::Spacer)
|
258
353
|
end
|
259
354
|
|
260
355
|
# Each branch has a certain number of exits that require their own line
|
261
356
|
# and arrow. When there are 'OR' conditions we need to insert additional
|
262
357
|
# spacers into the necessary row in the column after the one the branch is
|
263
358
|
# located in.
|
359
|
+
# This is done for the column directly after a branching point
|
264
360
|
def insert_expression_spacers
|
265
361
|
service.branches.each do |branch|
|
266
362
|
next if coordinates.uuid_column(branch.uuid).nil?
|
267
363
|
|
364
|
+
next unless has_or_conditionals?(branch)
|
365
|
+
|
268
366
|
previous_uuid = ''
|
269
367
|
next_column = coordinates.uuid_column(branch.uuid) + 1
|
270
368
|
exiting_destinations_from_branch(branch).each_with_index do |uuid, row|
|
@@ -42,7 +42,7 @@ module MetadataPresenter
|
|
42
42
|
return if branches_in_column.empty?
|
43
43
|
|
44
44
|
row_numbers = branches_in_column.map do |branch_uuid, _|
|
45
|
-
coordinates.branch_spacers[branch_uuid].map { |
|
45
|
+
coordinates.branch_spacers[branch_uuid].map { |position| position[:row] }
|
46
46
|
end
|
47
47
|
row_numbers.flatten.max + 1
|
48
48
|
end
|
@@ -54,7 +54,7 @@ module MetadataPresenter
|
|
54
54
|
def branch_spacer_row
|
55
55
|
return if spacers_for_current_object.empty?
|
56
56
|
|
57
|
-
spacers_for_current_object.map { |position| position[:row] }.max
|
57
|
+
spacers_for_current_object.flatten.map { |position| position[:row] }.max
|
58
58
|
end
|
59
59
|
|
60
60
|
def first_row?
|
@@ -84,7 +84,7 @@ module MetadataPresenter
|
|
84
84
|
end
|
85
85
|
|
86
86
|
current_object_spacers = spacer_positions.map do |branch_uuid, _|
|
87
|
-
coordinates.branch_spacers[branch_uuid][uuid]
|
87
|
+
coordinates.branch_spacers[branch_uuid].select { |branch_spacer| branch_spacer[:uuid] == uuid }
|
88
88
|
end
|
89
89
|
current_object_spacers.compact
|
90
90
|
end
|
data/fixtures/branching_10.json
CHANGED
@@ -120,7 +120,7 @@
|
|
120
120
|
},
|
121
121
|
"79c18654-7ecb-43f9-bd7f-0b09eb9c075e": {
|
122
122
|
"next": {
|
123
|
-
"default": "
|
123
|
+
"default": "1314e473-9096-4434-8526-03a7b4b7b132"
|
124
124
|
},
|
125
125
|
"_type": "flow.page"
|
126
126
|
},
|
@@ -219,28 +219,15 @@
|
|
219
219
|
"next": {
|
220
220
|
"default": "7742dfcc-db2e-480b-9071-294fbe1769a2",
|
221
221
|
"conditionals": [
|
222
|
-
{
|
223
|
-
"next": "1314e473-9096-4434-8526-03a7b4b7b132",
|
224
|
-
"_type": "if",
|
225
|
-
"_uuid": "0bdc8fde-be62-4945-8496-854e867a665d",
|
226
|
-
"expressions": [
|
227
|
-
{
|
228
|
-
"page": "4e54ed97-d0df-462e-9a88-fd0f23ea62f5",
|
229
|
-
"field": "3b56e4a0-a850-4e50-a394-95a895465e26",
|
230
|
-
"operator": "is",
|
231
|
-
"component": "3c2c14a4-75db-459a-b11e-34e1972a45f2"
|
232
|
-
}
|
233
|
-
]
|
234
|
-
},
|
235
222
|
{
|
236
223
|
"next": "da2576f9-7ddd-4316-b24b-103708139214",
|
237
224
|
"_type": "if",
|
238
|
-
"_uuid": "
|
225
|
+
"_uuid": "cd28e391-bdc6-47ce-8a07-24a4642432dc",
|
239
226
|
"expressions": [
|
240
227
|
{
|
241
228
|
"page": "4e54ed97-d0df-462e-9a88-fd0f23ea62f5",
|
242
|
-
"field": "
|
243
|
-
"operator": "
|
229
|
+
"field": "3b56e4a0-a850-4e50-a394-95a895465e26",
|
230
|
+
"operator": "is_answered",
|
244
231
|
"component": "3c2c14a4-75db-459a-b11e-34e1972a45f2"
|
245
232
|
}
|
246
233
|
]
|
@@ -405,7 +392,7 @@
|
|
405
392
|
"name": "page-b_checkboxes_1",
|
406
393
|
"_type": "checkbox",
|
407
394
|
"_uuid": "4fb4f5ac-8337-48f6-87ee-2062f4ce1b4d",
|
408
|
-
"label": "Option 1",
|
395
|
+
"label": "Page B Option 1",
|
409
396
|
"value": "value-1",
|
410
397
|
"errors": {
|
411
398
|
},
|
@@ -421,7 +408,7 @@
|
|
421
408
|
"name": "page-b_checkboxes_1",
|
422
409
|
"_type": "checkbox",
|
423
410
|
"_uuid": "c074548d-22a7-4339-9bfe-383741b04c79",
|
424
|
-
"label": "Option 2",
|
411
|
+
"label": "Page B Option 2",
|
425
412
|
"value": "value-2",
|
426
413
|
"errors": {
|
427
414
|
},
|
@@ -437,7 +424,7 @@
|
|
437
424
|
"name": "page-b_checkboxes_1",
|
438
425
|
"_type": "checkbox",
|
439
426
|
"_uuid": "4132af6c-bd4d-4734-956b-05ec414c6dcc",
|
440
|
-
"label": "Option 3",
|
427
|
+
"label": "Page B Option 3",
|
441
428
|
"value": "value-3",
|
442
429
|
"errors": {
|
443
430
|
},
|
@@ -559,7 +546,7 @@
|
|
559
546
|
"name": "page-f_checkboxes_1",
|
560
547
|
"_type": "checkbox",
|
561
548
|
"_uuid": "56febb54-3b06-417a-98b7-51c19e10631b",
|
562
|
-
"label": "Option A",
|
549
|
+
"label": "Page F Option A",
|
563
550
|
"value": "value-1",
|
564
551
|
"errors": {
|
565
552
|
},
|
@@ -575,7 +562,7 @@
|
|
575
562
|
"name": "page-f_checkboxes_1",
|
576
563
|
"_type": "checkbox",
|
577
564
|
"_uuid": "e495f6b3-a7e6-405e-85a3-cba4119f0507",
|
578
|
-
"label": "Option B",
|
565
|
+
"label": "Page F Option B",
|
579
566
|
"value": "value-2",
|
580
567
|
"errors": {
|
581
568
|
},
|
@@ -591,7 +578,7 @@
|
|
591
578
|
"name": "page-f_checkboxes_1",
|
592
579
|
"_type": "checkbox",
|
593
580
|
"_uuid": "b5e9d16c-0699-4f16-9c75-906b22599e20",
|
594
|
-
"label": "Option C",
|
581
|
+
"label": "Page F Option C",
|
595
582
|
"value": "value-3",
|
596
583
|
"errors": {
|
597
584
|
},
|
@@ -607,7 +594,7 @@
|
|
607
594
|
"name": "page-f_checkboxes_1",
|
608
595
|
"_type": "checkbox",
|
609
596
|
"_uuid": "89856dbf-7412-45c7-b5e1-dcaf8e810cdd",
|
610
|
-
"label": "Option D",
|
597
|
+
"label": "Page F Option D",
|
611
598
|
"value": "value-4",
|
612
599
|
"errors": {
|
613
600
|
},
|
@@ -781,7 +768,7 @@
|
|
781
768
|
"name": "page-i_checkboxes_1",
|
782
769
|
"_type": "checkbox",
|
783
770
|
"_uuid": "98f181fb-530e-4002-8204-3b89b37fefad",
|
784
|
-
"label": "Option 1",
|
771
|
+
"label": "Page I Option 1",
|
785
772
|
"value": "value-1",
|
786
773
|
"errors": {
|
787
774
|
},
|
@@ -797,7 +784,7 @@
|
|
797
784
|
"name": "page-i_checkboxes_1",
|
798
785
|
"_type": "checkbox",
|
799
786
|
"_uuid": "99249f5e-c238-46b9-b447-03272c284a40",
|
800
|
-
"label": "Option 2",
|
787
|
+
"label": "Page I Option 2",
|
801
788
|
"value": "value-2",
|
802
789
|
"errors": {
|
803
790
|
},
|
@@ -813,7 +800,7 @@
|
|
813
800
|
"name": "page-i_checkboxes_1",
|
814
801
|
"_type": "checkbox",
|
815
802
|
"_uuid": "66823323-7df7-4a44-9d3b-0397af465dce",
|
816
|
-
"label": "Option 3",
|
803
|
+
"label": "Page I Option 3",
|
817
804
|
"value": "value-3",
|
818
805
|
"errors": {
|
819
806
|
},
|
@@ -857,7 +844,7 @@
|
|
857
844
|
"name": "page-j_checkboxes_1",
|
858
845
|
"_type": "checkbox",
|
859
846
|
"_uuid": "3b56e4a0-a850-4e50-a394-95a895465e26",
|
860
|
-
"label": "Option 1",
|
847
|
+
"label": "Page J Option 1",
|
861
848
|
"value": "value-1",
|
862
849
|
"errors": {
|
863
850
|
},
|
@@ -873,7 +860,7 @@
|
|
873
860
|
"name": "page-j_checkboxes_1",
|
874
861
|
"_type": "checkbox",
|
875
862
|
"_uuid": "951ca999-8616-4626-adb2-d604f27262a5",
|
876
|
-
"label": "Option 2",
|
863
|
+
"label": "Page J Option 2",
|
877
864
|
"value": "value-2",
|
878
865
|
"errors": {
|
879
866
|
},
|
@@ -889,7 +876,7 @@
|
|
889
876
|
"name": "page-j_checkboxes_1",
|
890
877
|
"_type": "checkbox",
|
891
878
|
"_uuid": "478152c5-73d1-4359-bc15-01e069fe2490",
|
892
|
-
"label": "Option 3",
|
879
|
+
"label": "Page J Option 3",
|
893
880
|
"value": "value-3",
|
894
881
|
"errors": {
|
895
882
|
},
|
@@ -902,10 +889,10 @@
|
|
902
889
|
],
|
903
890
|
"errors": {
|
904
891
|
},
|
905
|
-
"legend": "Page J",
|
892
|
+
"legend": "Page J (Optional)",
|
906
893
|
"collection": "components",
|
907
894
|
"validation": {
|
908
|
-
"required":
|
895
|
+
"required": false
|
909
896
|
}
|
910
897
|
}
|
911
898
|
],
|
@@ -1198,10 +1185,10 @@
|
|
1198
1185
|
}
|
1199
1186
|
],
|
1200
1187
|
"locale": "en",
|
1201
|
-
"created_at": "
|
1202
|
-
"created_by": "
|
1203
|
-
"service_id": "
|
1204
|
-
"version_id": "
|
1188
|
+
"created_at": "2022-02-02T12:32:13Z",
|
1189
|
+
"created_by": "b7eff904-9fec-4c48-b6ac-4572b490a040",
|
1190
|
+
"service_id": "e68dca75-20b8-468e-9436-e97791a914c5",
|
1191
|
+
"version_id": "195ea111-9d4c-4176-837d-0d751c37bbcd",
|
1205
1192
|
"service_name": "Branching Fixture 10 ",
|
1206
1193
|
"configuration": {
|
1207
1194
|
"meta": {
|
data/fixtures/branching_10.png
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metadata_presenter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.15.
|
4
|
+
version: 2.15.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MoJ Forms
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_design_system_formbuilder
|
@@ -303,6 +303,8 @@ files:
|
|
303
303
|
- app/models/metadata_presenter/traversed_pages.rb
|
304
304
|
- app/models/metadata_presenter/uploaded_file.rb
|
305
305
|
- app/operators/metadata_presenter/base_operator.rb
|
306
|
+
- app/operators/metadata_presenter/contains_operator.rb
|
307
|
+
- app/operators/metadata_presenter/does_not_contain_operator.rb
|
306
308
|
- app/operators/metadata_presenter/is_answered_operator.rb
|
307
309
|
- app/operators/metadata_presenter/is_not_answered_operator.rb
|
308
310
|
- app/operators/metadata_presenter/is_not_operator.rb
|