metadata_presenter 3.2.10 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 81a35dc58abc591f0cedb227a3e20f75931601caee2aac4c1a4ce11712b915d6
4
- data.tar.gz: fd98093f0104eff5ad0e5f825a0a10f36cc5e1fdc00a4b894c8caebbb6feb7bc
3
+ metadata.gz: 63fc209d420f65d544451620bbc2331e554d607e8c3df329f5f243bd285b3bff
4
+ data.tar.gz: 91a2d6a553874cc6aa8012f845af32a99168a8a94528ca9aa13cb758e1acec36
5
5
  SHA512:
6
- metadata.gz: decab91ce86b76b49479cb9c7a3886658e828a1ae2130c34396a93996e895aa26de3955986661f20f8c49d2b562e0dc5d25a9a527c956aab8c1415e24eb80d6e
7
- data.tar.gz: ab347bae508e604a82d3fb09907eaaefdeba07f2019c4cd84bd53cb5cac70162a2b4bc414664ffd60cbfae0d2b114907f8bc0326c82f7b674db5e95cf1b71d61
6
+ metadata.gz: 58b2be95c2268ffa1c4f4d65561348dd48bcdc92e19eacc238ef5561d1c47c4028709def52c39f50f500cbf534dd42a101d54ab36a8dbffba24ab77d6ab14c7d
7
+ data.tar.gz: 1183d876e40b55148b978aa429b1b35a6861d0a10ebd404d68a284a65821a0e651ce8d564183118781225af5805e763cbe98de4a468ed6be2ad98ef831f1a537
@@ -113,35 +113,6 @@ module MetadataPresenter
113
113
  end
114
114
  helper_method :external_or_relative_link
115
115
 
116
- def load_conditional_content
117
- if @page.content_component_present?
118
- if components_without_conditionals(@page).present?
119
- return components_without_conditionals(@page) + show_components(@page).compact
120
- end
121
-
122
- show_components(@page).compact
123
- end
124
- end
125
- helper_method :load_conditional_content
126
-
127
- def components_without_conditionals(page)
128
- page.content_components.select { |component|
129
- component.conditionals.blank?
130
- }.map(&:uuid)
131
- end
132
-
133
- def show_components(page)
134
- return @page.content_components.map(&:uuid) if editor_preview?
135
-
136
- page.content_components.map do |content_component|
137
- EvaluateContentConditionals.new(
138
- service:,
139
- component: content_component,
140
- user_data: load_user_data
141
- ).show_component
142
- end
143
- end
144
-
145
116
  private
146
117
 
147
118
  def not_found
@@ -180,5 +151,18 @@ module MetadataPresenter
180
151
  def editor_preview?
181
152
  URI(request.original_url).path.split('/').include?('preview')
182
153
  end
154
+
155
+ def single_page_preview?
156
+ return false if in_runner?
157
+ return true if request.referrer.blank?
158
+
159
+ !URI(request.referrer).path.split('/').include?('preview')
160
+ end
161
+ helper_method :single_page_preview?
162
+
163
+ def in_runner?
164
+ ::Rails.application.class.module_parent.name == 'FbRunner'
165
+ end
166
+ helper_method :in_runner?
183
167
  end
184
168
  end
@@ -8,7 +8,11 @@ module MetadataPresenter
8
8
  @page ||= service.find_page_by_url(request.env['PATH_INFO'])
9
9
  if @page
10
10
  load_autocomplete_items
11
- load_conditional_content
11
+ if single_page_preview?
12
+ @page.load_all_content
13
+ else
14
+ @page.load_conditional_content(service, @user_data)
15
+ end
12
16
 
13
17
  @page_answers = PageAnswers.new(@page, @user_data)
14
18
  render template: @page.template
@@ -35,6 +39,11 @@ module MetadataPresenter
35
39
  TraversedPages.new(service, load_user_data, @page).all
36
40
  end
37
41
 
42
+ def conditional_components_present?
43
+ @page.conditional_components.any?
44
+ end
45
+ helper_method :conditional_components_present?
46
+
38
47
  private
39
48
 
40
49
  def set_caching_header
@@ -88,6 +88,12 @@ class MetadataPresenter::Component < MetadataPresenter::Metadata
88
88
  end
89
89
  end
90
90
 
91
+ def find_conditional_content_by_uuid(uuid)
92
+ metadata['conditionals'].select do |conditional|
93
+ conditional['_uuid'] == uuid
94
+ end
95
+ end
96
+
91
97
  private
92
98
 
93
99
  def validation_bundle_key
@@ -1,35 +1,81 @@
1
1
  module MetadataPresenter
2
2
  class EvaluateContentConditionals
3
3
  include ActiveModel::Model
4
- attr_accessor :service, :component, :user_data
4
+ attr_accessor :service, :user_data
5
5
 
6
- def show_component
7
- component_uuid
6
+ def evaluate_content_components(page)
7
+ displayed_components = []
8
+ page.content_components.map do |content_component|
9
+ next if page.conditionals_uuids_by_type('never').include?(content_component.uuid)
10
+
11
+ if page.conditionals_uuids_by_type('always').include?(content_component.uuid)
12
+ displayed_components << content_component.uuid
13
+ end
14
+ if page.conditionals_uuids_by_type('conditional').include?(content_component.uuid)
15
+ displayed_components << uuid_to_include?(content_component)
16
+ end
17
+ end
18
+ displayed_components.compact
8
19
  end
9
20
 
10
- def component_uuid
11
- @results ||=
12
- conditionals.map do |conditional|
13
- evaluated_expressions = conditional.expressions.map do |expression|
14
- expression.service = service
15
-
16
- Operator.new(
17
- expression.operator
18
- ).evaluate(
19
- expression.field_label,
20
- user_data[expression.expression_component.id]
21
- )
22
- end
21
+ private
23
22
 
24
- if conditional.type == 'or' && evaluated_expressions.any?
25
- component.uuid
26
- elsif evaluated_expressions.all?
27
- component.uuid
23
+ def uuid_to_include?(candidate_component)
24
+ evaluation_conditions = []
25
+ if candidate_component.conditionals.count == 1
26
+ # if there are only and rules or the particular case where there is only one condition
27
+ evaluation_conditions << evaluate_condition(candidate_component.conditionals[0])
28
+ return candidate_component.uuid if evaluation_conditions.flatten.all?
29
+ elsif candidate_component.conditionals.count > 1
30
+ # if there are or rule
31
+ if candidate_component.conditionals[0][:_type] == 'and'
32
+ # if there are 'and' in conditions between the 'or' rule
33
+ candidate_component.conditionals.map do |conditional|
34
+ evaluation_conditions << evaluate_condition(conditional).flatten.all?
28
35
  end
36
+ return candidate_component.uuid if evaluation_conditions.flatten.any?
29
37
  end
30
- @results.flatten.compact.first
38
+ if candidate_component.conditionals[0][:_type] == 'if'
39
+ # then this is an 'or' condition between conditionals
40
+ candidate_component.conditionals.map do |conditional|
41
+ evaluation_conditions << evaluate_condition(conditional)
42
+ end
43
+ return candidate_component.uuid if evaluation_conditions.flatten.any?
44
+ end
45
+ end
31
46
  end
32
47
 
33
- delegate :conditionals, to: :component
48
+ def evaluate_condition(conditional)
49
+ evaluation_expressions = []
50
+ conditional.expressions.map do |expression|
51
+ expression.service = service
52
+ case expression.operator
53
+ when 'is'
54
+ evaluation_expressions << check_answer_equal_expression(expression, user_data)
55
+ when 'is_not'
56
+ evaluation_expressions << !check_answer_equal_expression(expression, user_data)
57
+ when 'is_answered'
58
+ evaluation_expressions << user_data[expression.expression_component.id].present?
59
+ when 'is_not_answered'
60
+ evaluation_expressions << user_data[expression.expression_component.id].blank?
61
+ when 'contains'
62
+ evaluation_expressions << check_answer_include_expression(expression, user_data)
63
+ when 'does_not_contain'
64
+ evaluation_expressions << !check_answer_include_expression(expression, user_data)
65
+ end
66
+ end
67
+ evaluation_expressions
68
+ end
69
+
70
+ def check_answer_equal_expression(expression, user_data)
71
+ expression.field_label == user_data[expression.expression_component.id]
72
+ end
73
+
74
+ def check_answer_include_expression(expression, user_data)
75
+ answer = user_data[expression.expression_component.id]
76
+ return false if answer.blank?
77
+
78
+ answer.include?(expression.field_label)
79
+ end
34
80
  end
35
81
  end
@@ -141,8 +141,37 @@ module MetadataPresenter
141
141
  end
142
142
  end
143
143
 
144
- def content_component_present?
145
- components.any?(&:content?)
144
+ def conditional_content_to_show
145
+ @conditional_content_to_show || []
146
+ end
147
+
148
+ def show_conditional_component?(component_id)
149
+ conditional_content_to_show.include?(component_id)
150
+ end
151
+
152
+ def load_conditional_content(service, user_data)
153
+ if content_component_present?
154
+ evaluator = EvaluateContentConditionals.new(service:, user_data:)
155
+ items = evaluator.evaluate_content_components(self)
156
+ items << legacy_content_components
157
+ assign_conditional_component(items.flatten)
158
+ end
159
+ end
160
+
161
+ def content_components_by_type(*display)
162
+ content_components.filter { |component| display.include? component[:display] }
163
+ end
164
+
165
+ def conditionals_uuids_by_type(*display)
166
+ content_components_by_type(*display).map { |component| component[:_uuid] }
167
+ end
168
+
169
+ def load_all_content
170
+ @conditional_content_to_show = content_components
171
+ end
172
+
173
+ def conditional_components
174
+ conditionals_uuids_by_type('never', 'conditional')
146
175
  end
147
176
 
148
177
  private
@@ -172,5 +201,17 @@ module MetadataPresenter
172
201
  def raw_type
173
202
  type.gsub('page.', '')
174
203
  end
204
+
205
+ def assign_conditional_component(items)
206
+ @conditional_content_to_show = items
207
+ end
208
+
209
+ def content_component_present?
210
+ all_components.any?(&:content?)
211
+ end
212
+
213
+ def legacy_content_components
214
+ content_components.filter_map { |component| component[:_uuid] if component[:display].blank? }
215
+ end
175
216
  end
176
217
  end
@@ -21,6 +21,14 @@ class MetadataPresenter::Service < MetadataPresenter::Metadata
21
21
  branches.map(&:conditionals).flatten
22
22
  end
23
23
 
24
+ def content_expressions
25
+ content_conditionals.flat_map(&:expressions)
26
+ end
27
+
28
+ def content_conditionals
29
+ pages.flat_map(&:content_components).flat_map(&:conditionals)
30
+ end
31
+
24
32
  def flow_object(uuid)
25
33
  MetadataPresenter::Flow.new(uuid, metadata.flow[uuid])
26
34
  rescue StandardError
@@ -78,23 +86,32 @@ class MetadataPresenter::Service < MetadataPresenter::Metadata
78
86
 
79
87
  def page_with_component(uuid)
80
88
  pages.find do |page|
81
- Array(page.components).any? { |component| component.uuid == uuid }
89
+ Array(page.all_components).any? { |component| component.uuid == uuid }
82
90
  end
83
91
  end
84
92
 
85
- private
93
+ def pages_with_conditional_content_for_page(uuid)
94
+ pages.select do |page|
95
+ uuid.in? page.content_components_by_type('conditional').flat_map(&:conditionals).flat_map(&:expressions).map(&:page)
96
+ end
97
+ end
86
98
 
87
- def all_pages
88
- @all_pages ||= pages + standalone_pages
99
+ def pages_with_conditional_content_for_question(uuid)
100
+ pages.select do |page|
101
+ uuid.in? page.content_components_by_type('conditional').flat_map(&:conditionals).flat_map(&:expressions).map(&:component)
102
+ end
89
103
  end
90
104
 
91
- def flow_page(current_page)
92
- page_index = pages.index(current_page)
93
- pages[page_index - 1] if page_index.present?
105
+ def pages_with_conditional_content_for_question_option(uuid)
106
+ pages.select do |page|
107
+ uuid.in? page.content_components_by_type('conditional').flat_map(&:conditionals).flat_map(&:expressions).map(&:field)
108
+ end
94
109
  end
95
110
 
96
- def referrer_page(referrer)
97
- find_page_by_url(URI(referrer).path) if referrer
111
+ private
112
+
113
+ def all_pages
114
+ @all_pages ||= pages + standalone_pages
98
115
  end
99
116
 
100
117
  def strip_slash(url)
@@ -1,12 +1,16 @@
1
1
  <% components.each_with_index do |component, index| %>
2
+
2
3
  <% if component.type == 'content' %>
4
+ <% next unless (editable? || @page.show_conditional_component?(component.uuid) || single_page_preview?) %>
5
+
3
6
  <editable-content id="<%= "page[#{component.collection}[#{index}]]" %>"
4
7
  class="fb-editable govuk-!-margin-top-8"
5
8
  type="<%= component.type %>"
6
9
  default-content="<%= default_text('content') %>"
7
10
  content="<%= component.content %>"
8
11
  data-fb-content-id="<%= "page[#{component.collection}[#{index}]]" %>"
9
- data-config="<%= component.to_json %>">
12
+ data-config="<%= component.to_json %>"
13
+ data-conditional-api-path="<%= editable? ? URI.decode_www_form_component(api_service_edit_conditional_content_path(service.service_id, component.uuid)) : '' %>">
10
14
  <%= to_html(component.content) %>
11
15
  </editable-content>
12
16
  <% end %>
@@ -0,0 +1,5 @@
1
+ <% if single_page_preview? && !editable? && @page.conditional_components.any? %>
2
+ <%= govuk_notification_banner(title_text: 'Important') do |nb|
3
+ nb.with_heading(text: t('presenter.conditional_content.notification'))
4
+ end %>
5
+ <% end%>
@@ -2,6 +2,8 @@
2
2
  <div class="govuk-grid-row">
3
3
  <div class="govuk-grid-column-two-thirds">
4
4
 
5
+ <%= render partial:'metadata_presenter/component/conditional_component_banner'%>
6
+
5
7
  <h1 class="fb-editable govuk-heading-xl"
6
8
  data-fb-content-type="element"
7
9
  data-fb-content-id="page[heading]"
@@ -11,6 +13,7 @@
11
13
 
12
14
  <%= form_for @page, url: reserved_submissions_path, authenticity_token: false, html: { id: 'answers-form' } do |f| %>
13
15
  <%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
16
+
14
17
  <%= render partial: 'metadata_presenter/component/components',
15
18
  locals: {
16
19
  f: f,
@@ -1,59 +1,64 @@
1
1
  <% content_for :manual_global_analytics_properties do %>'page_title': 'Confirmation page'<% end %>
2
2
  <div class="fb-main-grid-wrapper" data-fb-pagetype="<%= @page.type %>">
3
- <% if payment_link_enabled? %>
4
- <div class="govuk-panel govuk-panel--confirmation-payment govuk-grid-column-two-thirds">
5
- <% else %>
6
- <div class="govuk-panel govuk-panel--confirmation govuk-grid-column-two-thirds">
7
- <% end %>
8
- <h1 class="fb-editable govuk-panel__title"
9
- data-fb-content-type="element"
10
- data-fb-content-id="page[heading]"
11
- data-fb-default-value="<%= default_page_title(@page.type) %>">
12
- <% if payment_link_enabled? && @page.heading == I18n.t('presenter.confirmation.application_complete') %>
13
- <p><%= I18n.t('presenter.confirmation.payment_enabled') %></p>
14
- <% else %>
15
- <%= @page.heading %>
16
- <% end %>
17
- </h1>
18
3
 
19
- <div class="govuk-panel__body">
20
- <% if reference_number_enabled? %>
21
- <p><%= I18n.t('presenter.confirmation.reference_number') %><br />
22
- <strong><%= show_reference_number %></strong>
23
- </p>
4
+ <%= render partial:'metadata_presenter/component/conditional_component_banner'%>
5
+
6
+ <% if payment_link_enabled? %>
7
+ <div class="govuk-panel govuk-panel--confirmation-payment govuk-grid-column-two-thirds">
8
+ <% else %>
9
+ <div class="govuk-panel govuk-panel--confirmation govuk-grid-column-two-thirds">
24
10
  <% end %>
11
+ <h1 class="fb-editable govuk-panel__title"
12
+ data-fb-content-type="element"
13
+ data-fb-content-id="page[heading]"
14
+ data-fb-default-value="<%= default_page_title(@page.type) %>">
15
+ <% if payment_link_enabled? && @page.heading == I18n.t('presenter.confirmation.application_complete') %>
16
+ <p><%= I18n.t('presenter.confirmation.payment_enabled') %></p>
17
+ <% else %>
18
+ <%= @page.heading %>
19
+ <% end %>
20
+ </h1>
25
21
 
26
- <%# Do not replace with app/views/metadata_presenter/attribute _lede.html.erb because that is different %>
27
- <% if @page.lede %>
28
- <div class="fb-editable"
29
- data-fb-content-id="page[lede]"
30
- data-fb-content-type="element"
31
- data-fb-default-text="<%= default_text('lede') %>">
32
- <%= @page.lede %>
33
- </div>
34
- <%- end %>
35
- </div>
36
- </div>
22
+ <div class="govuk-panel__body">
23
+ <% if reference_number_enabled? %>
24
+ <p><%= I18n.t('presenter.confirmation.reference_number') %><br />
25
+ <strong><%= show_reference_number %></strong>
26
+ </p>
27
+ <% end %>
37
28
 
38
- <div class="govuk-grid-row">
39
- <div class="govuk-grid-column-two-thirds">
40
- <% unless @page.body == default_text('body') %>
41
- <%= render 'metadata_presenter/attribute/body' %>
42
- <% end %>
29
+ <%# Do not replace with app/views/metadata_presenter/attribute _lede.html.erb because that is different %>
30
+ <% if @page.lede %>
31
+ <div class="fb-editable"
32
+ data-fb-content-id="page[lede]"
33
+ data-fb-content-type="element"
34
+ data-fb-default-text="<%= default_text('lede') %>">
35
+ <%= @page.lede %>
36
+ </div>
37
+ <%- end %>
38
+ </div>
39
+ </div>
43
40
 
44
- <%= render partial: 'metadata_presenter/component/components',
45
- locals: {
46
- f: nil,
47
- components: @page.components,
48
- tag: nil,
49
- classes: nil,
50
- input_components: @page.supported_input_components,
51
- content_components: @page.supported_content_components
52
- } %>
41
+ <div class="govuk-grid-row">
42
+ <div class="govuk-grid-column-two-thirds">
43
+ <% unless @page.body == default_text('body') %>
44
+ <%= render 'metadata_presenter/attribute/body' %>
45
+ <% end %>
53
46
 
47
+ <% render partial:'metadata_presenter/component/conditional_component_banner'%>
48
+
49
+ <%= render partial: 'metadata_presenter/component/components',
50
+ locals: {
51
+ f: nil,
52
+ components: @page.components,
53
+ tag: nil,
54
+ classes: nil,
55
+ input_components: @page.supported_input_components,
56
+ content_components: @page.supported_content_components
57
+ } %>
58
+
59
+ </div>
60
+ </div>
61
+ <% if payment_link_enabled? %>
62
+ <a href="<%= payment_link_url %>" class="govuk-button" data-module="govuk-button" data-component="pay-button"><%= t('presenter.confirmation.continue_to_pay_button') %></a>
63
+ <% end %>
54
64
  </div>
55
- </div>
56
- <% if payment_link_enabled? %>
57
- <a href="<%= payment_link_url %>" class="govuk-button" data-module="govuk-button" data-component="pay-button"><%= t('presenter.confirmation.continue_to_pay_button') %></a>
58
- <% end %>
59
- </div>
@@ -2,6 +2,8 @@
2
2
  <div class="govuk-grid-row">
3
3
  <div class="govuk-grid-column-two-thirds">
4
4
 
5
+ <%= render partial:'metadata_presenter/component/conditional_component_banner'%>
6
+
5
7
  <%= render 'metadata_presenter/attribute/section_heading' %>
6
8
 
7
9
  <h1 class="fb-editable govuk-heading-xl"
@@ -2,6 +2,8 @@
2
2
  <div class="govuk-grid-row">
3
3
  <div class="govuk-grid-column-two-thirds">
4
4
 
5
+ <%= render partial:'metadata_presenter/component/conditional_component_banner'%>
6
+
5
7
  <%= render 'metadata_presenter/attribute/section_heading' %>
6
8
 
7
9
  <h1 class="fb-editable govuk-heading-xl"
@@ -15,6 +17,7 @@
15
17
 
16
18
  <%= form_for @page_answers, as: :answers, url: @page.url, method: :post, authenticity_token: false do |f| %>
17
19
  <%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
20
+
18
21
 
19
22
  <%= render partial: 'metadata_presenter/component/components',
20
23
  locals: {
@@ -2,6 +2,8 @@
2
2
  <div class="govuk-grid-row">
3
3
  <div class="govuk-grid-column-two-thirds">
4
4
 
5
+ <%= render partial:'metadata_presenter/component/conditional_component_banner'%>
6
+
5
7
  <%= render 'metadata_presenter/attribute/section_heading' %>
6
8
  <%= render 'metadata_presenter/attribute/heading' %>
7
9
 
@@ -55,6 +55,8 @@ en:
55
55
  singular: 'You can add 1 more file (maximum 7MB)'
56
56
  plural: 'You can add up to %{num} files (maximum 7MB per file)'
57
57
  none: "You can't add any more files. Remove a file if you need to add a different one."
58
+ conditional_content:
59
+ notification: "Some content on this page will be hidden under certain conditions. Preview the full form or publish to Test to check."
58
60
  save_and_return:
59
61
  save: 'Save for later'
60
62
  show:
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "_id": "component.content",
3
3
  "_type": "content",
4
+ "display": "always",
4
5
  "content": "[Optional content]"
5
6
  }