-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathpage_controller.rb
More file actions
200 lines (153 loc) · 6.84 KB
/
page_controller.rb
File metadata and controls
200 lines (153 loc) · 6.84 KB
1
2
3
4
5
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
module Forms
class PageController < BaseController
before_action :prepare_step, :set_request_logging_attributes, :changing_existing_answer, :check_goto_page_routing_error
def set_request_logging_attributes
super
CurrentRequestLoggingAttributes.question_number = @step.page_number if @step&.page_number
CurrentRequestLoggingAttributes.answer_type = @step&.page&.answer_type if @step&.page&.answer_type
# Add question-level attributes to OpenTelemetry span
TelemetryService.set_question_attributes(@step, @form) if @step && @form
end
def show
return redirect_to form_page_path(@form.id, @form.form_slug, current_context.next_page_slug) unless current_context.can_visit?(@step.id)
return redirect_to review_file_page if @step.answered_file_question?
setup_instance_vars_for_view
end
def change
return redirect_to form_page_path(@form.id, @form.form_slug, current_context.next_page_slug) unless current_context.can_visit?(@step.id)
return redirect_to review_file_page if @step.answered_file_question?
setup_instance_vars_for_view
render :show
end
def save
page_params = params.fetch(:question, {}).permit(*@step.params)
@step.assign_question_attributes(page_params)
current_context.clear_submission_details if is_first_page?
validation_context = @step.autocomplete_selection_question? ? :skip_none_of_the_above_question_validation : nil
if current_context.save_step(@step, context: validation_context)
# Redirect before logging when the question has multiple pages so that we don't send multiple form started
# metrics to CloudWatch if this is the first question.
return redirect_to selection_none_of_the_above_page if redirect_to_none_of_the_above_page?
unless mode.preview?
LogEventService.new(current_context, @step, request, changing_existing_answer, page_params).log_page_save
end
redirect_post_save
else
setup_instance_vars_for_view
render :show, status: :unprocessable_content
end
end
private
def prepare_step
page_slug = params.require(:page_slug)
begin
@step = current_context.find_or_create(page_slug)
rescue Flow::StepFactory::PageNotFoundError
return redirect_to form_page_path(@form.id, @form.form_slug, current_context.next_page_slug)
end
if @step.respond_to?(:answer_index)
@step.answer_index = answer_index
end
@support_details = current_context.support_details
end
def answer_index
params.fetch(:answer_index, 1).to_i
end
def setup_instance_vars_for_view
@question_edit_link = question_edit_link
@save_url = save_url
@back_link = back_link(@step.id)
end
def question_edit_link
"#{Settings.forms_admin.base_url}/forms/#{@form.id}/pages-by-external-id/#{@step.id}/edit-question"
end
def save_url
save_form_page_path(@form.id, @form.form_slug, @step.id, changing_existing_answer: @changing_existing_answer, answer_index:)
end
def changing_existing_answer
@changing_existing_answer = ActiveModel::Type::Boolean.new.cast(params[:changing_existing_answer])
end
def back_link(page_slug)
return check_your_answers_path(form_id: current_context.form.id) if changing_existing_answer
previous_step = current_context.previous_step(page_slug)
return nil unless previous_step
if previous_step.repeatable?
add_another_answer_path(form_id: current_context.form.id, form_slug: current_context.form.form_slug, page_slug: previous_step.id)
else
form_page_path(@form.id, @form.form_slug, previous_step.page_id)
end
end
def redirect_post_save
return redirect_to review_file_page, success: t("banner.success.file_uploaded") if @step.answered_file_question?
return redirect_to exit_page_path(form_id: @form.id, form_slug: @form.form_slug, page_slug: @step.id) if @step.exit_page_condition_matches?
redirect_to next_page
end
def redirect_if_not_answered_file_question
unless @step.answered_file_question?
redirect_to form_page_path(@form.id, @form.form_slug, @step.id)
end
end
def redirect_to_none_of_the_above_page?
@step.autocomplete_selection_question? && @step.question.show_none_of_the_above_question?
end
def review_file_page
review_file_path(form_id: @form.id, form_slug: @form.form_slug, page_slug: @step.id, changing_existing_answer:)
end
def selection_none_of_the_above_page
selection_none_of_the_above_path(form_id: @form.id, form_slug: @form.form_slug, page_slug: @step.id)
end
def next_page
if changing_existing_answer
return next_step_changing
end
next_step_path
end
def next_step_path
if should_show_add_another?(@step)
return add_another_answer_path(form_id: @form.id, form_slug: @form.form_slug, page_slug: @step.id)
end
next_step_in_form_path
end
def next_step_changing
if should_show_add_another?(@step)
return change_add_another_answer_path(form_id: @form.id, form_slug: @form.form_slug, page_slug: @step.id)
end
check_answers_path
end
def next_step_in_form_path
form_page_path(@form.id, @form.form_slug, @step.next_page_slug_after_routing)
end
def check_answers_path
check_your_answers_path(form_id: current_context.form.id, form_slug: current_context.form.form_slug)
end
def should_show_add_another?(step)
step.repeatable? && !step.skipped?
end
def check_goto_page_routing_error
return if @step.conditions_with_goto_errors.blank?
first_condition_with_error = @step.conditions_with_goto_errors.first
first_goto_error_name = first_condition_with_error.validation_errors.find { |error|
Step::GOTO_PAGE_ERROR_NAMES.include?(error.name)
}.name
event_name = if first_goto_error_name == "cannot_have_goto_page_before_routing_page"
"goto_page_before_routing_page_error"
else
"goto_page_doesnt_exist_error"
end
EventLogger.log_page_event(event_name, @step.question.question_text, nil)
routes_page_id = first_condition_with_error.check_page_id
routes_page = @current_context.find_or_create(routes_page_id)
render template: "errors/goto_page_routing_error", locals: {
error_name: first_goto_error_name,
link_url: admin_edit_condition_url(@form.id, routes_page_id),
question_number: routes_page.page_number,
}, status: :unprocessable_content
end
def admin_edit_condition_url(form_id, page_id)
"#{Settings.forms_admin.base_url}/forms/#{form_id}/pages-by-external-id/#{page_id}/routes"
end
def is_first_page?
current_context.form.start_page.to_s == @step.id
end
end
end