metadata_presenter 3.2.9 → 3.2.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 897373db9fc9e22cdd101785b6906d6a0cc657bba1ed4bab5eb81e5834eac598
4
- data.tar.gz: c295de4f671132adc78f8cff9ce26594996c64c4f91eaff46ae1bacaeb114b5b
3
+ metadata.gz: 63fc209d420f65d544451620bbc2331e554d607e8c3df329f5f243bd285b3bff
4
+ data.tar.gz: 91a2d6a553874cc6aa8012f845af32a99168a8a94528ca9aa13cb758e1acec36
5
5
  SHA512:
6
- metadata.gz: 1c82446ff868a0ec684a4a5f239189a0abaa05983cb752209f9f7739bc7d144d0300a9314e005f251478c6ce7486a9571be47c7ccdc139bd13fa9c333b010fa4
7
- data.tar.gz: d88712f097b7ba9ef105bc15a5b4c18c909f72c998c820ff8b4113f1769c7e971670a24f9ec6a65d82981fc0f51b05927b664790df51395dc2e475ec1fa8c119
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
@@ -36,6 +36,12 @@ module MetadataPresenter
36
36
  MetadataPresenter::DefaultMetadata[type.to_s]&.[]('heading')
37
37
  end
38
38
 
39
+ def timeout_fallback(time)
40
+ time.strftime('%l:%M %p')
41
+ rescue NoMethodError
42
+ time
43
+ end
44
+
39
45
  def multiupload_files_remaining
40
46
  component = page_multiupload_component
41
47
  answers = @user_data.keys.include?(component.id) ? @user_data.find(component.id).first : []
@@ -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
 
@@ -2,7 +2,7 @@
2
2
  <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
3
3
  <strong class="govuk-warning-text__text">
4
4
  <span class="govuk-warning-text__assistive">Warning</span>
5
- <%= t('presenter.session_timeout_warning.timer_fallback') %> <%= session_expiry_time&.strftime('%l:%M %p') %>.
5
+ <%= t('presenter.session_timeout_warning.timer_fallback') %> <%= timeout_fallback(session_expiry_time) %>.
6
6
  <%= t('presenter.session_timeout_warning.timer_extra') %>
7
7
  </strong>
8
8
  </div>
@@ -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
  }