Skip to content

Commit

Permalink
1425: Dynamic applicant language selection. (#296)
Browse files Browse the repository at this point in the history
* Dynamic language selection working. Needs some UI enhancements and to make the toggle only available to applicants

* Added previous language switcher, pinwheel language translation

* fixed all, but one test

* fixing broken tests

* Ensuring that language selector is only available to applicants. There's a weird radio bug so we're falling back to vanilla html, updated styling to match Figma

* updated _sandbox and _nyc invitation forms to match _ma

* Ensuring that the initial locale is determined by the cbv_flow_invitation

* Moving the session locale logic to the base_controller

* preserving query params when switching languages

* Avoid adding /en/ prefix to routes since it's the default locale

* relying on the request and params to resolve the locale, updated pinwheel api controller to use headers to resolve the locale

* Moved the set_locale method to the entries_controller since it's the only controller relying on it

* Addressing PR feedback

* fixing more bugs, addressing pr feedback
  • Loading branch information
George Byers authored Oct 2, 2024
1 parent 519348a commit f843f94
Show file tree
Hide file tree
Showing 25 changed files with 186 additions and 40 deletions.
5 changes: 3 additions & 2 deletions app/app/controllers/api/pinwheel_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ def create_token
token_response = pinwheel.create_link_token(
response_type: token_params[:response_type],
id: token_params[:id],
end_user_id: @cbv_flow.pinwheel_end_user_id
end_user_id: @cbv_flow.pinwheel_end_user_id,
language: token_params[:locale]
)
token = token_response["data"]["token"]

Expand All @@ -18,7 +19,7 @@ def create_token
private

def token_params
params.require(:pinwheel).permit(:response_type, :id)
params.require(:pinwheel).permit(:response_type, :id, :locale)
end

def track_event
Expand Down
5 changes: 4 additions & 1 deletion app/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class ApplicationController < ActionController::Base
helper :view
helper_method :current_site
helper_method :current_site, :show_translate_button?
around_action :switch_locale
before_action :add_newrelic_metadata
before_action :redirect_if_maintenance_mode
Expand All @@ -27,6 +27,9 @@ def site_config
end

private
def show_translate_button?
false
end

def current_site
@current_site ||= site_config[params[:site_id]]
Expand Down
12 changes: 10 additions & 2 deletions app/app/controllers/caseworker/cbv_flow_invitations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Caseworker::CbvFlowInvitationsController < Caseworker::BaseController
protect_from_forgery prepend: true
before_action :ensure_valid_params!
before_action :authenticate_user!
helper_method :language_options

def new
@site_id = site_id
Expand All @@ -14,7 +15,6 @@ def new

def create
invitation_params = base_params.merge(site_specific_params)

# handle errors from the mail service
begin
@cbv_flow_invitation = CbvInvitationService.new.invite(invitation_params, current_user)
Expand Down Expand Up @@ -48,6 +48,12 @@ def create

private

def language_options
CbvFlowInvitation::VALID_LOCALES.each_with_object({}) do |lang, options|
options[lang] = I18n.t(".shared.languages.#{lang}", default: lang.to_s.titleize)
end
end

def ensure_valid_params!
if site_config.site_ids.exclude?(site_id)
flash[:alert] = t("caseworker.cbv_flow_invitations.incorrect_site_id")
Expand All @@ -59,9 +65,10 @@ def base_params
cbv_flow_invitation_params.slice(
:first_name,
:middle_name,
:language,
:last_name,
:email_address,
:snap_application_date
:snap_application_date,
).merge(site_id: site_id)
end

Expand All @@ -80,6 +87,7 @@ def cbv_flow_invitation_params
params.fetch(:cbv_flow_invitation, {}).permit(
:first_name,
:middle_name,
:language,
:last_name,
:client_id_number,
:case_number,
Expand Down
4 changes: 4 additions & 0 deletions app/app/controllers/cbv/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ class Cbv::BaseController < ApplicationController

private

def show_translate_button?
true
end

def set_cbv_flow
if params[:token].present?
invitation = CbvFlowInvitation.find_by(auth_token: params[:token])
Expand Down
3 changes: 2 additions & 1 deletion app/app/controllers/cbv/summaries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ def track_transmitted_event(cbv_flow, payments)
paystub_count: payments.count,
account_count_with_additional_information:
cbv_flow.additional_information.values.count { |info| info["comment"].present? },
flow_started_seconds_ago: (Time.now - cbv_flow.created_at).to_i
flow_started_seconds_ago: (Time.now - cbv_flow.created_at).to_i,
language: I18n.locale
})
rescue => ex
Rails.logger.error "Failed to track NewRelic event: #{ex.message}"
Expand Down
10 changes: 4 additions & 6 deletions app/app/helpers/view_helper.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
module ViewHelper
DATE_FORMAT = "%B %d, %Y"

def format_active_locale(locale_string)
link_classes = "usa-nav__link"
if locale_string.to_sym == I18n.locale
link_classes = "#{link_classes} usa-current"
end
link_to t("shared.languages.#{locale_string}"), root_path(locale: locale_string), class: link_classes
def switch_locale_link(locale)
new_locale = locale == I18n.default_locale ? nil : locale
path = url_for(request.params.merge(locale: new_locale))
link_to t("shared.languages.#{locale}"), path, class: "usa-nav__link", data: { "turbo-prefetch": false }
end

def format_parsed_date(date)
Expand Down
8 changes: 6 additions & 2 deletions app/app/javascript/controllers/cbv/employer_search.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ export default class extends Controller {
}
}

getDocumentLocale() {
return document.documentElement.lang
}

async select(event) {
const { responseType, id } = event.target.dataset;
this.disableButtons()

const { token } = await fetchToken(responseType, id);
const locale = this.getDocumentLocale();
const { token } = await fetchToken(responseType, id, locale);
this.submit(token);
}

Expand Down
7 changes: 3 additions & 4 deletions app/app/javascript/utilities/pinwheel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import metaContent from "./meta";
import CSRF from './csrf';

const PINWHEEL_TOKENS_GENERATE = '/api/pinwheel/tokens';

export function loadPinwheel() {
return new Promise((resolve, reject) => {
loadScript('https://cdn.getpinwheel.com/pinwheel-v3.0.js', (err, script) => {
Expand All @@ -25,13 +24,13 @@ export function initializePinwheel(Pinwheel, linkToken, callbacks) {
return Pinwheel;
}

export const fetchToken = (response_type, id) => {
export const fetchToken = (response_type, id, locale) => {
return fetch(PINWHEEL_TOKENS_GENERATE, {
method: 'post',
headers: {
'X-CSRF-Token': CSRF.token,
'Content-Type': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ response_type, id }),
body: JSON.stringify({ response_type, id, locale }),
}).then(response => response.json());
}
6 changes: 5 additions & 1 deletion app/app/mailers/applicant_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ class ApplicantMailer < ApplicationMailer
helper :view, :application
helper_method :current_site
before_action :set_params

around_action :set_locale
def invitation_email
mail(
to: @cbv_flow_invitation.email_address,
Expand All @@ -12,6 +12,10 @@ def invitation_email

private

def set_locale(&action)
I18n.with_locale(@cbv_flow_invitation.language, &action)
end

def set_params
@cbv_flow_invitation = params[:cbv_flow_invitation]
end
Expand Down
14 changes: 13 additions & 1 deletion app/app/models/cbv_flow_invitation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,26 @@ class CbvFlowInvitation < ApplicationRecord
# Paystub report range
PAYSTUB_REPORT_RANGE = 90.days

VALID_LOCALES = Rails.application.config.i18n.available_locales.map(&:to_s).freeze

belongs_to :user
has_many :cbv_flows

has_secure_token :auth_token, length: 36

before_validation :parse_snap_application_date
before_validation :format_case_number, if: :nyc_site?
before_validation :normalize_language

validates :site_id, inclusion: Rails.application.config.sites.site_ids
validates :first_name, presence: true
validates :last_name, presence: true
validates :email_address, format: { with: EMAIL_REGEX, message: :invalid_format }
validates :language, inclusion: {
in: VALID_LOCALES,
message: :invalid_format,
case_sensitive: false
}

# MA specific validations
validates :agency_id_number, format: { with: MA_AGENCY_ID_REGEX, message: :invalid_format }, if: :ma_site?
Expand Down Expand Up @@ -86,7 +94,7 @@ def complete?
end

def to_url
Rails.application.routes.url_helpers.cbv_flow_entry_url(token: auth_token)
Rails.application.routes.url_helpers.cbv_flow_entry_url(token: auth_token, locale: language)
end

def paystubs_query_begins_at
Expand Down Expand Up @@ -158,4 +166,8 @@ def format_case_number
self.case_number = "000#{case_number}"
end
end

def normalize_language
self.language = language.to_s.downcase if language.present?
end
end
5 changes: 3 additions & 2 deletions app/app/services/pinwheel_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@ def fetch_platform(platform_id:)
@http.get(build_url("#{PLATFORMS_ENDPOINT}/#{platform_id}")).body
end

def create_link_token(end_user_id:, response_type:, id:)
def create_link_token(end_user_id:, response_type:, id:, language:)
params = {
org_name: I18n.t("shared.pilot_name"),
required_jobs: [ "paystubs" ],
end_user_id: end_user_id,
skip_intro_screen: true
skip_intro_screen: true,
language: language
}

case response_type.presence
Expand Down
22 changes: 16 additions & 6 deletions app/app/views/application/_header.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<% end %>
</em>
</div>

<% if user_signed_in? %>
<button class="usa-menu-btn"><%= t("shared.header.menu") %></button>
<% end %>
Expand All @@ -40,13 +41,22 @@
<button class="usa-nav__close">
<%= image_tag "@uswds/uswds/dist/img/usa-icons/close.svg", role: "img", alt: t("shared.header.close") %>
</button>
<% if user_signed_in? %>
<ul class="usa-nav__primary usa-accordion">
<li class="usa-nav__primary-item">
<%= button_to t("shared.header.log_out"), destroy_user_session_url(site_id: current_user.site_id), method: :delete, class: "usa-nav__link" %>
</li>
<ul class="usa-nav__primary usa-accordion">
<% if user_signed_in? %>
<li class="usa-nav__primary-item">
<%= button_to t("shared.header.log_out"), destroy_user_session_url(site_id: current_user.site_id), method: :delete, class: "usa-nav__link" %>
</li>
<% end %>

<% if show_translate_button? %>
<% I18n.available_locales.each do |locale| %>
<% next if locale == I18n.locale %>
<li class="usa-nav__primary-item">
<%= switch_locale_link(locale) %>
</li>
<% end %>
<% end %>
</ul>
<% end %>
</nav>
</div>
</header>
22 changes: 22 additions & 0 deletions app/app/views/caseworker/cbv_flow_invitations/_ma.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,25 @@
<%= f.email_field :email_address, label: t(".invite.email_address") %>

<%= f.text_field :beacon_id, label: t(".invite.beacon_id") %>

<div class="usa-form-group <%= "usa-form-group--error" if f.field_error(:language).present? %>">
<legend class="usa-legend"><%= t(".invite.language_label") %></legend>
<%= f.field_error :language %>
<div class="usa-radio-group">
<% language_options.each_with_index do |(value, label), index| %>
<div class="usa-radio usa-radio--tile">
<input
class="usa-radio__input usa-radio__input--tile"
id="language-<%= value %>-<%= index %>"
type="radio"
name="<%= f.object_name %>[language]"
value="<%= value %>"
<%= 'checked="checked"' if f.object.language == value %>
>
<label class="usa-radio__label" for="language-<%= value %>-<%= index %>">
<%= label %>
</label>
</div>
<% end %>
</div>
</div>
22 changes: 22 additions & 0 deletions app/app/views/caseworker/cbv_flow_invitations/_nyc.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,25 @@
<%= f.date_picker :snap_application_date, label: t(".invite.snap_application_date") %>

<%= f.email_field :email_address, label: t(".invite.email_address") %>

<div class="usa-form-group <%= "usa-form-group--error" if f.field_error(:language).present? %>">
<legend class="usa-legend"><%= t(".invite.language_label") %></legend>
<%= f.field_error :language %>
<div class="usa-radio-group">
<% language_options.each_with_index do |(value, label), index| %>
<div class="usa-radio usa-radio--tile">
<input
class="usa-radio__input usa-radio__input--tile"
id="language-<%= value %>-<%= index %>"
type="radio"
name="<%= f.object_name %>[language]"
value="<%= value %>"
<%= 'checked="checked"' if f.object.language == value %>
>
<label class="usa-radio__label" for="language-<%= value %>-<%= index %>">
<%= label %>
</label>
</div>
<% end %>
</div>
</div>
30 changes: 29 additions & 1 deletion app/app/views/caseworker/cbv_flow_invitations/_sandbox.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,34 @@

<%= f.text_field :case_number, label: t(".invite.case_number") %>

<%= f.date_picker :snap_application_date, label: t(".invite.todays_date") %>
<%= f.text_field :beacon_id, label: t(".invite.beacon_id") %>

<%= f.text_field :agency_id_number, label: t(".invite.agency_id_number") %>

<%= f.text_field :client_id_number, label: t(".invite.client_id_number") %>

<%= f.date_picker :snap_application_date, label: t(".invite.snap_application_date") %>

<%= f.email_field :email_address, label: t(".invite.email_address") %>

<div class="usa-form-group <%= "usa-form-group--error" if f.field_error(:language).present? %>">
<legend class="usa-legend"><%= t(".invite.language_label") %></legend>
<%= f.field_error :language %>
<div class="usa-radio-group">
<% language_options.each_with_index do |(value, label), index| %>
<div class="usa-radio usa-radio--tile">
<input
class="usa-radio__input usa-radio__input--tile"
id="language-<%= value %>-<%= index %>"
type="radio"
name="<%= f.object_name %>[language]"
value="<%= value %>"
<%= 'checked="checked"' if f.object.language == value %>
>
<label class="usa-radio__label" for="language-<%= value %>-<%= index %>">
<%= label %>
</label>
</div>
<% end %>
</div>
</div>
5 changes: 1 addition & 4 deletions app/app/views/cbv/summaries/show.pdf.erb
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,8 @@
<% end %>

<% if @cbv_flow.additional_information.dig(account_id, "comment").present? %>
<h2><%= t('.additional_information_title') %></h2>
<h2><%= t(".additional_information_title") %></h2>

<p><%= @cbv_flow.additional_information.dig(account_id, "comment") %></p>
<% end %>
<% end %>



2 changes: 1 addition & 1 deletion app/app/views/layouts/pdf.pdf.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
<head>
<meta charset="utf-8" />
<meta charset="utf-8" >
<title>Verify.gov</title>
<meta name="viewport" content="width=device-width,initial-scale=1">

Expand Down
Loading

0 comments on commit f843f94

Please sign in to comment.