metadata_presenter 2.18.7 → 2.19.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 +4 -4
- data/README.md +2 -0
- data/app/controllers/metadata_presenter/answers_controller.rb +7 -0
- data/app/controllers/metadata_presenter/engine_controller.rb +18 -0
- data/app/controllers/metadata_presenter/save_and_return_controller.rb +142 -22
- data/app/controllers/metadata_presenter/submissions_controller.rb +11 -0
- data/app/models/metadata_presenter/email_confirmation.rb +3 -7
- data/app/models/metadata_presenter/page.rb +2 -0
- data/app/models/metadata_presenter/resume_form.rb +16 -0
- data/app/models/metadata_presenter/saved_form.rb +19 -3
- data/app/validators/email_confirmation_validator.rb +3 -2
- data/app/validators/saved_progress_validator.rb +4 -0
- data/app/validators/secret_answer_validator.rb +7 -0
- data/app/views/metadata_presenter/page/checkanswers.html.erb +11 -3
- data/app/views/metadata_presenter/page/content.html.erb +9 -1
- data/app/views/metadata_presenter/page/multiplequestions.html.erb +9 -2
- data/app/views/metadata_presenter/page/singlequestion.html.erb +11 -1
- data/app/views/metadata_presenter/save_and_return/email_confirmation.html.erb +19 -16
- data/app/views/metadata_presenter/save_and_return/record_error.html.erb +9 -0
- data/app/views/metadata_presenter/save_and_return/record_failure.html.erb +9 -0
- data/app/views/metadata_presenter/save_and_return/record_link_expired.html.erb +9 -0
- data/app/views/metadata_presenter/save_and_return/record_link_used.html.erb +9 -0
- data/app/views/metadata_presenter/save_and_return/resume_from_start.html.erb +11 -0
- data/app/views/metadata_presenter/save_and_return/resume_progress.html.erb +50 -0
- data/app/views/metadata_presenter/save_and_return/return.html.erb +26 -0
- data/app/views/metadata_presenter/save_and_return/save_progress.html.erb +3 -3
- data/app/views/metadata_presenter/save_and_return/show.html.erb +37 -34
- data/config/locales/en.yml +36 -1
- data/config/routes.rb +8 -1
- data/lib/metadata_presenter/version.rb +1 -1
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b55fc1ebe10f65b4d0ebbaa969f4a1a77ca51ffa6a537329879294e10bc9058e
|
4
|
+
data.tar.gz: 7062a65a1e84854b1cade841121862576d417acf02347b263cd85f6817ebd180
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d0fe37a83a9f221ebc6055ae7034388746b13c715ca3d9c533d9128839847f51eafd01db6d9430a09232b00efd2b36a321ed6dbb78f3ea3edc71027ac9bc782
|
7
|
+
data.tar.gz: ce129d017803fddd5b02ebcc076909aeedff699f1c9443cf061501d1f9f64cdd74fe234b69c7a9b851af9649522abd8395686c0738055191d6724b6b7fb1b976
|
data/README.md
CHANGED
@@ -95,6 +95,8 @@ The `autocomplete_items` takes the components on a page and retrieves any items
|
|
95
95
|
|
96
96
|
`payment_link_url` method will present the payment link url. For the Runner this is the value of the `ENV['PAYMENT_LINK']` variable. In the Editor the value comes from the `ServiceConfiguration` table.
|
97
97
|
|
98
|
+
`save_and_return_enabled?` method checks whether save and return is enabled in the Runner or Editor app. In the Runner save and return is enabled when the `ENV['SAVE_AND_RETURN']` environment variable is present. In the Editor, save and return enabled can be ascertained by checking the `ServiceConfiguration` table.
|
99
|
+
|
98
100
|
## Generate documentation
|
99
101
|
|
100
102
|
Run `rake doc` and open the doc/index.html
|
@@ -6,6 +6,12 @@ module MetadataPresenter
|
|
6
6
|
@previous_answers = reload_user_data.deep_dup
|
7
7
|
@page_answers = PageAnswers.new(page, answers_params, autocomplete_items(page.components))
|
8
8
|
|
9
|
+
if params[:save_for_later].present?
|
10
|
+
save_user_data
|
11
|
+
# NOTE: if the user is on a file upload page, files will not be uploaded before redirection
|
12
|
+
redirect_to save_path(page_slug: params[:page_slug]) and return
|
13
|
+
end
|
14
|
+
|
9
15
|
upload_files if upload?
|
10
16
|
|
11
17
|
if @page_answers.validate_answers
|
@@ -49,6 +55,7 @@ module MetadataPresenter
|
|
49
55
|
end
|
50
56
|
|
51
57
|
def answers_params
|
58
|
+
params.permit(:page_slug, :save_for_later)
|
52
59
|
params[:answers] ? params[:answers].permit! : {}
|
53
60
|
end
|
54
61
|
|
@@ -21,6 +21,24 @@ module MetadataPresenter
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def get_saved_progress(uuid)
|
25
|
+
if defined? super
|
26
|
+
super(uuid)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def increment_record_counter(uuid)
|
31
|
+
if defined? super
|
32
|
+
super(uuid)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def invalidate_record(uuid)
|
37
|
+
if defined? super
|
38
|
+
super(uuid)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
24
42
|
def back_link
|
25
43
|
previous_page = PreviousPage.new(
|
26
44
|
service:,
|
@@ -1,31 +1,42 @@
|
|
1
1
|
module MetadataPresenter
|
2
2
|
class SaveAndReturnController < EngineController
|
3
|
-
helper_method :secret_questions, :page_slug, :confirmed_email
|
3
|
+
helper_method :secret_questions, :page_slug, :confirmed_email, :get_service_name, :get_uuid, :label_text
|
4
4
|
|
5
5
|
def show
|
6
6
|
@saved_form = SavedForm.new
|
7
7
|
end
|
8
8
|
|
9
9
|
def page_slug
|
10
|
+
if session['returning_slug'].present?
|
11
|
+
return session['returning_slug']
|
12
|
+
end
|
10
13
|
if session['saved_form'].present?
|
11
|
-
session['saved_form']['page_slug']
|
14
|
+
return session['saved_form']['page_slug']
|
15
|
+
end
|
16
|
+
if params['saved_form'].present?
|
17
|
+
return params['saved_form']['page_slug']
|
12
18
|
end
|
19
|
+
|
13
20
|
params[:page_slug]
|
14
21
|
end
|
15
22
|
|
16
23
|
def confirmed_email
|
17
|
-
session['saved_form']['email']
|
18
|
-
|
24
|
+
email = session['saved_form']['email']
|
25
|
+
session[:saved_form] = nil
|
26
|
+
|
27
|
+
email
|
19
28
|
end
|
20
29
|
|
21
30
|
def create
|
22
31
|
@saved_form = SavedForm.new
|
23
32
|
@saved_form.populate_param_values(saved_form_params)
|
24
|
-
@saved_form.
|
33
|
+
@saved_form.secret_question_text = text_for(params['saved_form']['secret_question'])
|
34
|
+
@saved_form.secret_question = params['saved_form']['secret_question']
|
25
35
|
@saved_form.populate_service_values(service)
|
26
36
|
@saved_form.populate_session_values(session)
|
27
37
|
if @saved_form.valid?
|
28
38
|
# put in session until we have confirmed email address
|
39
|
+
@saved_form.secret_question = @saved_form.secret_question_text
|
29
40
|
session[:saved_form] = @saved_form
|
30
41
|
redirect_to '/save/email_confirmation'
|
31
42
|
else
|
@@ -35,37 +46,137 @@ module MetadataPresenter
|
|
35
46
|
|
36
47
|
def email_confirmation
|
37
48
|
@saved_form = session[:saved_form]
|
38
|
-
@email_confirmation = EmailConfirmation.new
|
49
|
+
@email_confirmation = EmailConfirmation.new(@saved_form['email'])
|
39
50
|
end
|
40
51
|
|
41
52
|
def confirm_email
|
42
|
-
@email_confirmation = EmailConfirmation.new
|
43
|
-
@email_confirmation.assign_attributes(confirmation_params[:email_confirmation], session['saved_form']['email'])
|
53
|
+
@email_confirmation = EmailConfirmation.new(confirmation_params[:email_confirmation])
|
44
54
|
|
45
55
|
if @email_confirmation.valid?
|
56
|
+
session['saved_form']['email'] = @email_confirmation.email_confirmation
|
46
57
|
response = save_form_progress
|
47
|
-
if response.status
|
58
|
+
if response.status == 500
|
48
59
|
internal_server_error and return
|
49
60
|
end
|
50
61
|
|
51
|
-
|
62
|
+
payload = response.body.merge(email: @email_confirmation.email_confirmation).deep_symbolize_keys
|
63
|
+
create_save_and_return_submission(payload)
|
64
|
+
|
52
65
|
redirect_to '/save/progress_saved'
|
53
66
|
else
|
54
67
|
render :email_confirmation, status: :unprocessable_entity
|
55
68
|
end
|
56
69
|
end
|
57
70
|
|
58
|
-
|
59
|
-
|
60
|
-
|
71
|
+
def return
|
72
|
+
response = get_saved_progress(get_uuid)
|
73
|
+
|
74
|
+
if response.status == 404
|
75
|
+
redirect_to '/record_error' and return
|
76
|
+
end
|
77
|
+
|
78
|
+
if response.status == 400
|
79
|
+
redirect_to '/record_failure' and return
|
80
|
+
end
|
81
|
+
|
82
|
+
if response.status == 422
|
83
|
+
redirect_to '/already_used' and return
|
84
|
+
end
|
85
|
+
|
86
|
+
@saved_form = SavedForm.new.from_json(response.body.to_json)
|
87
|
+
@resume_form = ResumeForm.new(@saved_form.secret_question)
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_uuid
|
91
|
+
if params[:uuid].present?
|
92
|
+
return params[:uuid]
|
93
|
+
end
|
94
|
+
|
95
|
+
params[:resume_form][:uuid].presence
|
96
|
+
end
|
61
97
|
|
62
|
-
#
|
63
|
-
|
98
|
+
# rubocop:disable Style/RescueStandardError
|
99
|
+
def submit_secret_answer
|
100
|
+
response = get_saved_progress(get_uuid)
|
64
101
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
102
|
+
if response.status != 200
|
103
|
+
if response.status == 400
|
104
|
+
redirect_to '/record_failure' and return
|
105
|
+
end
|
106
|
+
|
107
|
+
redirect_to '/record_error' and return
|
108
|
+
end
|
109
|
+
|
110
|
+
@saved_form = SavedForm.new.from_json(response.body.to_json)
|
111
|
+
@resume_form = ResumeForm.new(@saved_form.secret_question)
|
112
|
+
@resume_form.secret_answer = resume_form_params[:resume_form][:secret_answer]
|
113
|
+
@resume_form.recorded_answer = @saved_form.secret_answer
|
114
|
+
@resume_form.attempts_remaining = 2 - @saved_form.attempts.to_i
|
115
|
+
|
116
|
+
if @resume_form.valid?
|
117
|
+
# redirect back to right place in form
|
118
|
+
session[:user_id] = @saved_form.user_id
|
119
|
+
session[:user_token] = @saved_form.user_token
|
120
|
+
session[:returning_slug] = @saved_form.page_slug
|
121
|
+
|
122
|
+
invalidate_record(@saved_form.id)
|
123
|
+
|
124
|
+
if @saved_form.service_version == service.version_id
|
125
|
+
redirect_to '/resume_progress' and return
|
126
|
+
else
|
127
|
+
redirect_to '/resume_from_start' and return
|
128
|
+
end
|
129
|
+
else
|
130
|
+
if @resume_form.attempts_remaining <= 0
|
131
|
+
begin
|
132
|
+
increment_record_counter(@saved_form.id)
|
133
|
+
rescue => e
|
134
|
+
Rails.logger.info(e)
|
135
|
+
redirect_to '/record_failure' and return
|
136
|
+
end
|
137
|
+
redirect_to '/record_failure' and return
|
138
|
+
end
|
139
|
+
|
140
|
+
increment_record_counter(@saved_form.id)
|
141
|
+
|
142
|
+
render :return, params: { uuid: @saved_form.id }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
# rubocop:enable Style/RescueStandardError
|
146
|
+
|
147
|
+
def resume_progress
|
148
|
+
@user_data = load_user_data
|
149
|
+
|
150
|
+
@page ||= service.find_page_by_url('check-answers')
|
151
|
+
|
152
|
+
if @page
|
153
|
+
@page_answers = PageAnswers.new(@page, @answered_pages)
|
154
|
+
|
155
|
+
render template: 'metadata_presenter/save_and_return/resume_progress'
|
156
|
+
else
|
157
|
+
not_found
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def save_progress
|
162
|
+
session['saved_form']['user_id'] = nil
|
163
|
+
session['saved_form']['user_token'] = nil
|
164
|
+
session['user_id'] = nil
|
165
|
+
session['user_token'] = nil
|
166
|
+
end
|
167
|
+
|
168
|
+
def answered_pages
|
169
|
+
TraversedPages.new(service, @user_data, @page).all
|
170
|
+
end
|
171
|
+
|
172
|
+
def pages_presenters
|
173
|
+
PageAnswersPresenter.map(
|
174
|
+
view: view_context,
|
175
|
+
pages: answered_pages,
|
176
|
+
answers: @user_data
|
177
|
+
)
|
178
|
+
end
|
179
|
+
helper_method :pages_presenters
|
69
180
|
|
70
181
|
def secret_questions
|
71
182
|
[
|
@@ -98,10 +209,19 @@ module MetadataPresenter
|
|
98
209
|
)
|
99
210
|
end
|
100
211
|
|
101
|
-
|
212
|
+
def resume_form_params
|
213
|
+
params.permit(
|
214
|
+
{ resume_form: %i[secret_answer uuid] },
|
215
|
+
:authenticity_token
|
216
|
+
)
|
217
|
+
end
|
218
|
+
|
219
|
+
def get_service_name
|
220
|
+
service.service_name
|
221
|
+
end
|
102
222
|
|
103
|
-
def
|
104
|
-
|
223
|
+
def label_text(text)
|
224
|
+
"<h2 class='govuk-heading-m'>#{text}</h2>"
|
105
225
|
end
|
106
226
|
end
|
107
227
|
end
|
@@ -21,5 +21,16 @@ module MetadataPresenter
|
|
21
21
|
super
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
def create_save_and_return_submission(payload)
|
26
|
+
# The runner is the only app that sends the save and return submission.
|
27
|
+
# and it is not needed on the editor app (editing & previewing).
|
28
|
+
# So in the Runner we defined the #create_save_and_return_submission in the parent
|
29
|
+
# controller and in the Editor we don't.
|
30
|
+
#
|
31
|
+
if defined?(super)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
24
35
|
end
|
25
36
|
end
|
@@ -2,16 +2,12 @@ module MetadataPresenter
|
|
2
2
|
class EmailConfirmation
|
3
3
|
include ActiveModel::Model
|
4
4
|
|
5
|
-
attr_accessor :email_confirmation
|
6
|
-
:session_email
|
5
|
+
attr_accessor :email_confirmation
|
7
6
|
|
8
7
|
validates_with EmailConfirmationValidator
|
9
8
|
|
10
|
-
def initialize
|
11
|
-
|
12
|
-
def assign_attributes(email_confirmation, session_email)
|
13
|
-
@email_confirmation = email_confirmation
|
14
|
-
@session_email = session_email
|
9
|
+
def initialize(email)
|
10
|
+
self.email_confirmation = email
|
15
11
|
end
|
16
12
|
end
|
17
13
|
end
|
@@ -19,11 +19,13 @@ module MetadataPresenter
|
|
19
19
|
page.confirmation
|
20
20
|
page.multiplequestions
|
21
21
|
page.exit
|
22
|
+
save_and_return.resume_progress
|
22
23
|
].freeze
|
23
24
|
END_OF_ROUTE_PAGES = %w[
|
24
25
|
page.checkanswers
|
25
26
|
page.confirmation
|
26
27
|
page.exit
|
28
|
+
save_and_return.resume_progress
|
27
29
|
].freeze
|
28
30
|
|
29
31
|
def editable_attributes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module MetadataPresenter
|
2
|
+
class ResumeForm
|
3
|
+
include ActiveModel::Model
|
4
|
+
|
5
|
+
attr_accessor :secret_question,
|
6
|
+
:secret_answer,
|
7
|
+
:recorded_answer,
|
8
|
+
:attempts_remaining
|
9
|
+
|
10
|
+
validates_with SecretAnswerValidator
|
11
|
+
|
12
|
+
def initialize(secret_question)
|
13
|
+
self.secret_question = secret_question
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module MetadataPresenter
|
2
2
|
class SavedForm
|
3
3
|
include ActiveModel::Model
|
4
|
+
include ActiveModel::Serializers::JSON
|
5
|
+
|
4
6
|
validates_with SavedProgressValidator
|
5
7
|
|
6
8
|
attr_accessor :email,
|
7
9
|
:secret_question,
|
10
|
+
:secret_question_text,
|
8
11
|
:secret_answer,
|
9
12
|
:page_slug,
|
10
13
|
:service_slug,
|
@@ -13,9 +16,13 @@ module MetadataPresenter
|
|
13
16
|
:user_token,
|
14
17
|
:user_data_payload,
|
15
18
|
:attempts,
|
16
|
-
:active
|
19
|
+
:active,
|
20
|
+
:id,
|
21
|
+
:created_at,
|
22
|
+
:updated_at
|
23
|
+
|
24
|
+
validates :secret_question, :secret_answer, :service_slug, :page_slug, :service_version, :user_id, :user_token, presence: { message: 'Enter an answer for "%{attribute}"' }, allow_blank: false
|
17
25
|
|
18
|
-
validates :secret_question, :secret_answer, :service_slug, :page_slug, :service_version, :user_id, :user_token, presence: true, allow_blank: false
|
19
26
|
def initialize; end
|
20
27
|
|
21
28
|
def populate_param_values(params)
|
@@ -28,12 +35,21 @@ module MetadataPresenter
|
|
28
35
|
def populate_session_values(session)
|
29
36
|
self.user_id = session[:user_id]
|
30
37
|
self.user_token = session[:user_token]
|
31
|
-
self.user_data_payload = session[:user_data]
|
32
38
|
end
|
33
39
|
|
34
40
|
def populate_service_values(service)
|
35
41
|
self.service_slug = service.service_slug
|
36
42
|
self.service_version = service.version_id
|
37
43
|
end
|
44
|
+
|
45
|
+
def attributes=(hash)
|
46
|
+
hash.each do |key, value|
|
47
|
+
send("#{key}=", value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def attributes
|
52
|
+
instance_values
|
53
|
+
end
|
38
54
|
end
|
39
55
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class EmailConfirmationValidator < ActiveModel::Validator
|
2
2
|
def validate(record)
|
3
|
-
|
4
|
-
|
3
|
+
regex = URI::MailTo::EMAIL_REGEXP
|
4
|
+
if record.email_confirmation.match(regex).nil?
|
5
|
+
record.errors.add(:email_confirmation, I18n.t('presenter.save_and_return.validation.email'))
|
5
6
|
end
|
6
7
|
end
|
7
8
|
end
|
@@ -4,5 +4,9 @@ class SavedProgressValidator < ActiveModel::Validator
|
|
4
4
|
if record.email.match(regex).nil?
|
5
5
|
record.errors.add(:email, I18n.t('presenter.save_and_return.validation.email'))
|
6
6
|
end
|
7
|
+
|
8
|
+
if record.secret_answer.length > 100
|
9
|
+
record.errors.add(:secret_answer, I18n.t('presenter.save_and_return.validation.answer_too_long', attribute: 'Secret answer'))
|
10
|
+
end
|
7
11
|
end
|
8
12
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class SecretAnswerValidator < ActiveModel::Validator
|
2
|
+
def validate(record)
|
3
|
+
if record.secret_answer.strip.downcase != record.recorded_answer.strip.downcase
|
4
|
+
record.errors.add(:secret_answer, I18n.t('presenter.save_and_return.validation.answer_not_matched', attempts: record.attempts_remaining))
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
@@ -84,9 +84,17 @@
|
|
84
84
|
content_components: @page.supported_content_components
|
85
85
|
} %>
|
86
86
|
|
87
|
-
<
|
88
|
-
<%=
|
89
|
-
|
87
|
+
<div class="govuk-button-group">
|
88
|
+
<button <%= 'disabled' if editable? %> data-prevent-double-click="true" class="fb-block fb-block-actions govuk-button" data-module="govuk-button" data-block-id="actions" data-block-type="actions">
|
89
|
+
<%= t('presenter.actions.submit') -%></button>
|
90
|
+
<% if save_and_return_enabled? %>
|
91
|
+
<% if editor_preview? || editable? %>
|
92
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later', disabled: true %>
|
93
|
+
<% else %>
|
94
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later'%>
|
95
|
+
<% end %>
|
96
|
+
<% end %>
|
97
|
+
</div>
|
90
98
|
<% end %>
|
91
99
|
|
92
100
|
</div>
|
@@ -25,7 +25,15 @@
|
|
25
25
|
content_components: @page.supported_content_components
|
26
26
|
} %>
|
27
27
|
|
28
|
-
|
28
|
+
<div class="govuk-button-group">
|
29
|
+
<%= f.govuk_submit(disabled: editable?) %>
|
30
|
+
<% if save_and_return_enabled? %>
|
31
|
+
<% if editor_preview? || editable? %>
|
32
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later', disabled: true %>
|
33
|
+
<% else %>
|
34
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later'%>
|
35
|
+
<% end %>
|
36
|
+
<% end %> </div>
|
29
37
|
<% end %>
|
30
38
|
</div>
|
31
39
|
</div>
|
@@ -17,8 +17,15 @@
|
|
17
17
|
content_components: @page.supported_content_components
|
18
18
|
}
|
19
19
|
%>
|
20
|
-
|
21
|
-
|
20
|
+
<div class="govuk-button-group">
|
21
|
+
<%= f.govuk_submit(disabled: editable?) %>
|
22
|
+
<% if save_and_return_enabled? %>
|
23
|
+
<% if editor_preview? || editable? %>
|
24
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later', disabled: true %>
|
25
|
+
<% else %>
|
26
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later'%>
|
27
|
+
<% end %>
|
28
|
+
<% end %> </div>
|
22
29
|
<% end %>
|
23
30
|
</div>
|
24
31
|
</div>
|
@@ -20,7 +20,17 @@
|
|
20
20
|
</div>
|
21
21
|
<% end %>
|
22
22
|
|
23
|
-
|
23
|
+
<div class="govuk-button-group">
|
24
|
+
<%= f.govuk_submit(disabled: editable?) %>
|
25
|
+
|
26
|
+
<% if save_and_return_enabled? %>
|
27
|
+
<% if editor_preview? || editable? %>
|
28
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later', disabled: true %>
|
29
|
+
<% else %>
|
30
|
+
<%= button_to t('presenter.save_and_return.save'), '/', params: { page_slug:request.env['PATH_INFO'] }, method: :post, class: "govuk-button govuk-button--secondary", name: 'save_for_later'%>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
33
|
+
</div>
|
24
34
|
<% end %>
|
25
35
|
</div>
|
26
36
|
</div>
|
@@ -1,22 +1,25 @@
|
|
1
1
|
<div class="fb-main-grid-wrapper">
|
2
2
|
<div class="govuk-grid-row">
|
3
3
|
<div class="govuk-grid-column-two-thirds">
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
4
|
+
<a class="govuk-back-link" href="<%= :back %>"><%= t('presenter.back') %></a>
|
5
|
+
<%= form_for @email_confirmation do |f| %>
|
6
|
+
<%= f.govuk_error_summary %>
|
7
|
+
<div class="govuk-form-group">
|
8
|
+
<%=
|
9
|
+
f.govuk_email_field :email_confirmation,
|
10
|
+
label: { size: 'l', text: t('presenter.save_and_return.confirm_email.heading') },
|
11
|
+
name: "email_confirmation",
|
12
|
+
spellcheck: "false",
|
13
|
+
autocomplete: "email"
|
14
|
+
%>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<p class="mojf-settings-screen__description"><%= t('presenter.save_and_return.confirm_email.description') %></p>
|
18
|
+
<br/>
|
19
|
+
<div class="govuk-button-group">
|
20
|
+
<%= f.govuk_submit t('presenter.save_and_return.show.continue') %> <%= link_to t('presenter.save_and_return.show.cancel'), page_slug, class: "govuk-button govuk-button--secondary" %>
|
21
|
+
<div class="govuk-button-group">
|
22
|
+
<% end %>
|
20
23
|
</div>
|
21
24
|
</div>
|
22
25
|
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.errors.generic_problem.heading') %></h1>
|
5
|
+
<p><%= t('presenter.save_and_return.resume.errors.generic_problem.info_1') %></p>
|
6
|
+
<p><%= t('presenter.save_and_return.resume.errors.generic_problem.info_2') %></p>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.errors.failure.heading') %></h1>
|
5
|
+
<p><%= t('presenter.save_and_return.resume.errors.failure.info_1') %></p>
|
6
|
+
<p><%= t('presenter.save_and_return.resume.errors.failure.info_2') %></p>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.errors.expired.heading') %></h1>
|
5
|
+
<p><%= t('presenter.save_and_return.resume.errors.expired.info_1') %></p>
|
6
|
+
<p><%= t('presenter.save_and_return.resume.errors.expired.info_2') %></p>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.errors.link_used.heading') %></h1>
|
5
|
+
<p><%= t('presenter.save_and_return.resume.errors.link_used.info_1') %></p>
|
6
|
+
<p><%= t('presenter.save_and_return.resume.errors.link_used.info_2') %></p>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.from_start.heading', service_name: service.service_name) %></h1>
|
5
|
+
<p class="govuk-hint"><%= t('presenter.save_and_return.resume.from_start.info_1') %></p>
|
6
|
+
<br/>
|
7
|
+
<p class="govuk-hint"><%= t('presenter.save_and_return.resume.from_start.info_2') %></p>
|
8
|
+
<%= link_to t('presenter.save_and_return.resume.from_start.continue'), root_path, class: "govuk-button" %>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
</div>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper" data-fb-pagetype="resume_progress">
|
2
|
+
<h1 class="fb-editable govuk-heading-xl"
|
3
|
+
data-fb-content-type="element">
|
4
|
+
<%= t('presenter.save_and_return.resume.progress.heading', service_name: get_service_name) %>
|
5
|
+
</h1>
|
6
|
+
<div class="govuk-grid-row">
|
7
|
+
<div class="govuk-grid-column-two-thirds">
|
8
|
+
<p><%= t('presenter.save_and_return.resume.progress.content_1') %></p>
|
9
|
+
<p><%= t('presenter.save_and_return.resume.progress.content_2') %></p>
|
10
|
+
<%= form_for @page, url: reserved_submissions_path, html: { id: 'answers-form' } do |f| %>
|
11
|
+
<dl class="fb-block fb-block-answers govuk-summary-list">
|
12
|
+
<% pages_presenters.each do |page_answers_presenters| %>
|
13
|
+
<% page_answers_presenters.each_with_index do |page_answers_presenter, index| %>
|
14
|
+
|
15
|
+
<% if !page_answers_presenter.answer.empty? %>
|
16
|
+
|
17
|
+
<div class="govuk-summary-list__row">
|
18
|
+
<dt class="govuk-summary-list__key">
|
19
|
+
<%= page_answers_presenter.humanised_title %>
|
20
|
+
</dt>
|
21
|
+
|
22
|
+
<dd class="govuk-summary-list__value">
|
23
|
+
<%= page_answers_presenter.answer %>
|
24
|
+
</dd>
|
25
|
+
<dd class="govuk-summary-list__actions">
|
26
|
+
<%= link_to(
|
27
|
+
editable? ? '#' : page_answers_presenter.url,
|
28
|
+
class: 'govuk-link'
|
29
|
+
) do %>
|
30
|
+
Change<span class="govuk-visually-hidden"> Your answer for <%= page_answers_presenter.humanised_title %></span>
|
31
|
+
<% end %>
|
32
|
+
</dd>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<% if page_answers_presenter.last_multiple_question?(index, page_answers_presenters.size) %>
|
36
|
+
<% end %>
|
37
|
+
</dl>
|
38
|
+
<dl class="fb-block fb-block-answers govuk-summary-list">
|
39
|
+
<% end %>
|
40
|
+
<% end %>
|
41
|
+
<% end %>
|
42
|
+
</dl>
|
43
|
+
|
44
|
+
<div class="govuk-button-group">
|
45
|
+
<%= link_to t('presenter.save_and_return.resume.progress.continue'), page_slug, class: "govuk-button" %> <a href="<%= save_path(:page_slug=>page_slug) %>" class="govuk-button govuk-button--secondary" data-module="govuk-button" data-component="save-button"><%= t('presenter.save_and_return.save') %></a>
|
46
|
+
</div>
|
47
|
+
<% end %>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
</div>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<div class="fb-main-grid-wrapper">
|
2
|
+
<div class="govuk-grid-row">
|
3
|
+
<div class="govuk-grid-column-two-thirds">
|
4
|
+
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.resume.heading', service_name: get_service_name) %></h1>
|
5
|
+
<p><%= t('presenter.save_and_return.resume.content') %></p>
|
6
|
+
<%= form_for @resume_form do |f| %>
|
7
|
+
<%= f.govuk_error_summary %>
|
8
|
+
<%= f.hidden_field(:uuid, value: get_uuid) %>
|
9
|
+
<div class="govuk-form-group">
|
10
|
+
<%=
|
11
|
+
f.govuk_text_field :secret_answer,
|
12
|
+
label: { text: to_html(label_text(f.object.secret_question)) }
|
13
|
+
%>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="govuk-warning-text">
|
17
|
+
<span class="govuk-warning-text__icon" aria-hidden="true">!</span>
|
18
|
+
<strong class="govuk-warning-text__text">
|
19
|
+
<span class="govuk-warning-text__assistive">Warning</span>
|
20
|
+
<%= t('presenter.save_and_return.resume.information') %>
|
21
|
+
</strong>
|
22
|
+
</div>
|
23
|
+
<%= f.govuk_submit t('presenter.save_and_return.resume.continue') %><% end %>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
</div>
|
@@ -3,11 +3,11 @@
|
|
3
3
|
<div class="govuk-grid-column-two-thirds">
|
4
4
|
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.saved.heading') %></h1>
|
5
5
|
<p class="mojf-settings-screen__description"><%= t('presenter.save_and_return.saved.success', email: confirmed_email) %></p>
|
6
|
-
<p
|
6
|
+
<p><%= t('presenter.save_and_return.saved.info_1') %></p>
|
7
7
|
<br/>
|
8
|
-
<p
|
8
|
+
<p><%= t('presenter.save_and_return.saved.info_2') %></p>
|
9
9
|
<br/>
|
10
|
-
<p
|
10
|
+
<p><%= t('presenter.save_and_return.saved.info_3') %></p>
|
11
11
|
</div>
|
12
12
|
</div>
|
13
13
|
</div>
|
@@ -4,41 +4,44 @@
|
|
4
4
|
<h1 id="page-heading" class="govuk-heading-xl"><%= t('presenter.save_and_return.show.heading') %></h1>
|
5
5
|
<p class="mojf-settings-screen__description"><%= t('presenter.save_and_return.show.description') %></p>
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
label: { text: t('presenter.save_and_return.show.secret_answer') },
|
7
|
+
<%= form_for @saved_form do |f| %>
|
8
|
+
<%= f.govuk_error_summary %>
|
9
|
+
<div class="govuk-form-group">
|
10
|
+
<%= f.hidden_field(:page_slug, value: page_slug) %>
|
11
|
+
<%=
|
12
|
+
f.govuk_email_field :email,
|
13
|
+
label: { text: to_html(label_text(t('presenter.save_and_return.show.email'))) },
|
14
|
+
hint: {
|
15
|
+
data: { "fb-default-text" => default_text('hint') },
|
16
|
+
text: t('presenter.save_and_return.show.email_hint')
|
17
|
+
},
|
18
|
+
name: "email",
|
19
|
+
spellcheck: "false",
|
20
|
+
autocomplete: "email"
|
21
|
+
%>
|
22
|
+
<%=
|
23
|
+
f.govuk_collection_radio_buttons :secret_question,
|
24
|
+
secret_questions,
|
25
|
+
:id,
|
26
|
+
:name,
|
27
|
+
legend: { text: t('presenter.save_and_return.show.secret_question') },
|
28
|
+
hint: {
|
29
|
+
data: { "fb-default-text" => default_text('hint') },
|
30
|
+
text: t('presenter.save_and_return.show.secret_question_hint')
|
31
|
+
},
|
32
|
+
bold_labels: false
|
33
|
+
%>
|
34
|
+
<%=
|
35
|
+
f.govuk_text_field :secret_answer,
|
36
|
+
label: { text: to_html(label_text(t('presenter.save_and_return.show.secret_answer'))) },
|
37
37
|
name: "secret_answer"
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
%>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div class="govuk-button-group">
|
42
|
+
<%= f.govuk_submit t('presenter.save_and_return.show.continue') %> <%= link_to t('presenter.save_and_return.show.cancel'), page_slug, class: "govuk-button govuk-button--secondary" %>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
42
45
|
</div>
|
43
46
|
</div>
|
44
47
|
</div>
|
data/config/locales/en.yml
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
en:
|
2
2
|
presenter:
|
3
|
+
back: 'Back'
|
3
4
|
actions:
|
4
5
|
start: Start now
|
5
6
|
continue: Continue
|
@@ -42,7 +43,7 @@ en:
|
|
42
43
|
heading: 'Save for later'
|
43
44
|
description: 'We will send you a one-off link that you can use to resume this form within 28 days.'
|
44
45
|
email: 'Email address'
|
45
|
-
email_hint: '
|
46
|
+
email_hint: 'We will only use this to send you a link to your form'
|
46
47
|
secret_question: 'Pick a security question'
|
47
48
|
secret_question_hint: 'We will use this to verify your identity when you return'
|
48
49
|
secret_answer: 'The answer to your security question'
|
@@ -60,10 +61,44 @@ en:
|
|
60
61
|
validation:
|
61
62
|
email: 'Enter an email address in the correct format, like name@example.com'
|
62
63
|
email_not_matched: 'Does not match'
|
64
|
+
answer_not_matched: 'Your answer is incorrect. You have %{attempts} attempts remaining.'
|
65
|
+
answer_too_long: 'Your answer for %{attribute} must be 100 characters or fewer.'
|
63
66
|
secret_questions:
|
64
67
|
one: "What is your mother's maiden name?"
|
65
68
|
two: 'What is the last name of your favourite teacher?'
|
66
69
|
three: 'What is the name of the hospital where you were born?'
|
70
|
+
resume:
|
71
|
+
heading: "Continue with \"%{service_name}\""
|
72
|
+
continue: 'Continue'
|
73
|
+
content: 'To retrieve your information, enter the answer to your security question that you set when saving your progress.'
|
74
|
+
information: 'This will use up your save link. To save your progress again, you will need to repeat the save process and generate another link.'
|
75
|
+
errors:
|
76
|
+
generic_problem:
|
77
|
+
heading: 'There is a problem with your link'
|
78
|
+
info_1: 'Please try again. If you copied and pasted the link into your browser, check you copied the entire link.'
|
79
|
+
info_2: 'If this problem persists, you will need to start the form again. Your saved answers will be securely deleted after 28 days.'
|
80
|
+
expired:
|
81
|
+
heading: 'Your link has expired'
|
82
|
+
info_1: 'It has been more than 28 days since you saved your progress on this form and the link is no longer valid.'
|
83
|
+
info_2: 'Your saved answers have been be securely deleted.'
|
84
|
+
link_used:
|
85
|
+
heading: 'That link has already been used'
|
86
|
+
info_1: 'Links to resume a form only work once. If you have saved your progress more than once, check for a more recent link.'
|
87
|
+
info_2: 'Otherwise, you will need to start the form again. Your saved answers will be securely deleted after 28 days.'
|
88
|
+
failure:
|
89
|
+
heading: 'Your information cannot be retrieved'
|
90
|
+
info_1: 'The answer to your security question was incorrect and you have run out of attempts to retrieve your information.'
|
91
|
+
info_2: 'You will need to start the form again. Your saved answers will be securely deleted.'
|
92
|
+
from_start:
|
93
|
+
heading: "\"%{service_name}\" has been updated"
|
94
|
+
info_1: 'Your information has been successfully retrieved. However, the form has been updated since your last visit.'
|
95
|
+
info_2: 'Please check from the beginning in case anything has changed, such as new requirements or questions.'
|
96
|
+
continue: 'Continue'
|
97
|
+
progress:
|
98
|
+
heading: '%{service_name}'
|
99
|
+
content_1: 'You have sucessfuly retrieved your saved information.'
|
100
|
+
content_2: 'Here are the answers you have provided so far.'
|
101
|
+
continue: 'Continue'
|
67
102
|
footer:
|
68
103
|
cookies:
|
69
104
|
heading: "Cookies"
|
data/config/routes.rb
CHANGED
@@ -15,7 +15,14 @@ MetadataPresenter::Engine.routes.draw do
|
|
15
15
|
get 'save/email_confirmation', to: 'save_and_return#email_confirmation'
|
16
16
|
post 'email_confirmations', to: 'save_and_return#confirm_email'
|
17
17
|
get 'save/progress_saved', to: 'save_and_return#save_progress'
|
18
|
-
|
18
|
+
get '/return/:uuid', to: 'save_and_return#return'
|
19
|
+
post 'resume_forms', to: 'save_and_return#submit_secret_answer'
|
20
|
+
get 'record_error', to: 'save_and_return#record_error'
|
21
|
+
get 'record_failure', to: 'save_and_return#record_failure'
|
22
|
+
get 'expired', to: 'save_and_return#record_link_expired'
|
23
|
+
get 'already_used', to: 'save_and_return#record_link_used'
|
24
|
+
get 'resume_from_start', to: 'save_and_return#resume_from_start'
|
25
|
+
get 'resume_progress', to: 'save_and_return#resume_progress'
|
19
26
|
|
20
27
|
post '/', to: 'answers#create'
|
21
28
|
match '*path', to: 'answers#create', via: :post
|
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.
|
4
|
+
version: 2.19.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MoJ Forms
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: govuk_design_system_formbuilder
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - "<"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 6.2.0
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: sassc-rails
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 2.1.2
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - '='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.1.2
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: better_errors
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -287,6 +301,7 @@ files:
|
|
287
301
|
- app/models/metadata_presenter/page_answers.rb
|
288
302
|
- app/models/metadata_presenter/page_warning.rb
|
289
303
|
- app/models/metadata_presenter/previous_page.rb
|
304
|
+
- app/models/metadata_presenter/resume_form.rb
|
290
305
|
- app/models/metadata_presenter/route.rb
|
291
306
|
- app/models/metadata_presenter/row_number.rb
|
292
307
|
- app/models/metadata_presenter/saved_form.rb
|
@@ -325,6 +340,7 @@ files:
|
|
325
340
|
- app/validators/metadata_presenter/virus_scan_validator.rb
|
326
341
|
- app/validators/metadata_presenter/word_count.rb
|
327
342
|
- app/validators/saved_progress_validator.rb
|
343
|
+
- app/validators/secret_answer_validator.rb
|
328
344
|
- app/views/errors/404.html
|
329
345
|
- app/views/errors/500.html
|
330
346
|
- app/views/layouts/metadata_presenter/application.html.erb
|
@@ -365,6 +381,13 @@ files:
|
|
365
381
|
- app/views/metadata_presenter/page/standalone.html.erb
|
366
382
|
- app/views/metadata_presenter/page/start.html.erb
|
367
383
|
- app/views/metadata_presenter/save_and_return/email_confirmation.html.erb
|
384
|
+
- app/views/metadata_presenter/save_and_return/record_error.html.erb
|
385
|
+
- app/views/metadata_presenter/save_and_return/record_failure.html.erb
|
386
|
+
- app/views/metadata_presenter/save_and_return/record_link_expired.html.erb
|
387
|
+
- app/views/metadata_presenter/save_and_return/record_link_used.html.erb
|
388
|
+
- app/views/metadata_presenter/save_and_return/resume_from_start.html.erb
|
389
|
+
- app/views/metadata_presenter/save_and_return/resume_progress.html.erb
|
390
|
+
- app/views/metadata_presenter/save_and_return/return.html.erb
|
368
391
|
- app/views/metadata_presenter/save_and_return/save_progress.html.erb
|
369
392
|
- app/views/metadata_presenter/save_and_return/show.html.erb
|
370
393
|
- app/views/metadata_presenter/session/_timeout_fallback.html.erb
|