Skip to content

Commit

Permalink
Breaking up the Campaign Request Form Date Inputs
Browse files Browse the repository at this point in the history
Date picker arrows in Support app stopped working after the migration to Dart Sass. It’s caused by a known issue in the way Dart Sass handles the icon as Unicode - sass/sass#1395 we were not able to find a workaround. Date picker are not very accessible. When users are filling the dates in the form they normally know them already (and don’t need to pick it by looking at a calendar).

Users see a  symbol instead of an arrow. There’s alt text (Next, Prev). It’s also possible to enter date manually.

This will allow us to drop dependency on jquery-ui-rails.

Due to delivery priorities, we're not converting the entire form into Design System at the moment.
  • Loading branch information
PeterHattyar committed Aug 28, 2024
1 parent 1078aa0 commit d4f16b0
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 42 deletions.
12 changes: 9 additions & 3 deletions app/controllers/campaign_requests_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ def campaign_request_params
full_responsibility_confirmation
accessibility_confirmation
cookie_and_privacy_notice_confirmation
start_date
end_date
development_start_date
start_day
start_month
start_year
end_day
end_month
end_year
development_start_day
development_start_month
development_start_year
performance_review_contact_email
government_theme
description
Expand Down
38 changes: 31 additions & 7 deletions app/models/support/gds/campaign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ module Support
module GDS
class Campaign
include ActiveModel::Model
include DesignSystemDateHelper
attr_accessor :has_read_guidance_confirmation,
:has_read_oasis_guidance_confirmation,
:full_responsibility_confirmation,
:accessibility_confirmation,
:cookie_and_privacy_notice_confirmation,
:signed_campaign,
:start_date,
:end_date,
:development_start_date,
:start_day,
:start_month,
:start_year,
:end_day,
:end_month,
:end_year,
:development_start_day,
:development_start_month,
:development_start_year,
:performance_review_contact_email,
:government_theme,
:description,
Expand All @@ -27,9 +34,15 @@ class Campaign
:ga_contact_email

validates :signed_campaign,
:start_date,
:end_date,
:development_start_date,
:start_day,
:start_month,
:start_year,
:end_day,
:end_month,
:end_year,
:development_start_day,
:development_start_month,
:development_start_year,
:performance_review_contact_email,
:government_theme,
:description,
Expand All @@ -50,14 +63,25 @@ class Campaign
:accessibility_confirmation,
:cookie_and_privacy_notice_confirmation,
acceptance: { allow_nil: false, accept: "Yes" }

validates_date :start_date, on_or_after: :today
validates_date :end_date, after: :start_date
validates_date :development_start_date, on_or_before: :start_date
validates :proposed_url, format: /((http|https):\/\/)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.(campaign\.)?gov.uk?/

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :performance_review_contact_email, :ga_contact_email, format: { with: VALID_EMAIL_REGEX }

def start_date
formatted_date(start_day, start_month, start_year)
end

def end_date
formatted_date(end_day, end_month, end_year)
end

def development_start_date
formatted_date(development_start_day, development_start_month, development_start_year)
end
end
end
end
56 changes: 50 additions & 6 deletions app/views/campaign_requests/_request_details.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,22 @@
Start date of campaign site<abbr title="required">*</abbr>
<% end %>
</span>
<span class="form-wrapper">
<%= r.text_field :start_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.start_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %>

<br>

<span class="govuk-date-input__item">
<%= r.label :start_day, "Day", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :start_day, required: false, value: r.object.start_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "start-day" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :start_month, "Month", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :start_month, required: false, value: r.object.start_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "start-month" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :start_year, "Year", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :start_year, required: false, value: r.object.start_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "start-year" %>
</span>
<p class="help-block">
Once your site is live, you should allow time for testing before driving traffic to it. We advise leaving 1-2 days for no-cost campaigns, and at least a week for paid advertising campaigns.
Expand All @@ -92,9 +106,24 @@
Proposed end date of campaign site<abbr title="required">*</abbr>
<% end %>
</span>
<span class="form-wrapper">
<%= r.text_field :end_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.end_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %>

<br>

<span class="govuk-date-input__item">
<%= r.label :end_day, "Day", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :end_day, required: false, value: r.object.end_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "end-day" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :end_month, "Month", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :end_month, required: false, value: r.object.end_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "end-month" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :end_year, "Year", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :end_year, required: false, value: r.object.end_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "end-year" %>
</span>

</div>

<div class="form-group">
Expand All @@ -103,9 +132,24 @@
Site build to commence on<abbr title="required">*</abbr>
<% end %>
</span>
<span class="form-wrapper">
<%= r.text_field :development_start_date, required: true, aria: { required: true }, placeholder: "dd-mm-yyyy", value: r.object.development_start_date, class: "input-md-2 form-control", data: { module: "calendar", format: "dd-mm-yy", min_date: 0 } %>

<br>

<span class="govuk-date-input__item">
<%= r.label :development_start_day, "Day", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :development_start_day, required: false, value: r.object.development_start_day, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "development-start-day" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :development_start_month, "Month", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :development_start_month, required: false, value: r.object.development_start_month, class: "govuk-input govuk-date-input__input govuk-input--width-2", id: "development-start-month" %>
</span>

<span class="govuk-date-input__item">
<%= r.label :development_start_year, "Year", class: "govuk-label govuk-date-input__label" %>
<%= r.text_field :development_start_year, required: false, value: r.object.development_start_year, class: "govuk-input govuk-date-input__input govuk-input--width-4", id: "development-start-year" %>
</span>

</div>
<p class="help-block">
We expect the website to go live within 1 month of approval
Expand Down
24 changes: 18 additions & 6 deletions spec/features/campaign_requests_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,15 @@
accessibility_confirmation: true,
cookie_and_privacy_notice_confirmation: true,
signed_campaign: "John Smith",
start_date: "01-01-#{next_year}",
end_date: "01-02-#{next_year}",
development_start_date: "31-12-2019",
start_day: "01",
start_month: "01",
start_year: next_year.to_s,
end_day: "01",
end_month: "02",
end_year: next_year.to_s,
development_start_day: "31",
development_start_month: "12",
development_start_year: "2019",
performance_review_contact_email: "[email protected]",
government_theme: "Example government theme",
description: "Pensions",
Expand Down Expand Up @@ -129,9 +135,15 @@ def user_makes_a_campaign_request(details)
check "I/We agree to take responsibility to maintain and up-date the Cookie Notice and Privacy Notice as necessary, with our Data Protection Officer (NB : GDS will add a basic \"boilerplate\", however departments will need to identify if additions are needed)." if details[:cookie_and_privacy_notice_confirmation]

fill_in "Name of the Head of Digital Communications who signed off the campaign website application*", with: details[:signed_campaign]
fill_in "Start date of campaign site*", with: details[:start_date]
fill_in "Proposed end date of campaign site*", with: details[:end_date]
fill_in "Site build to commence on", with: details[:development_start_date]
find("#start-day").set(details[:start_day])
find("#start-month").set(details[:start_month])
find("#start-year").set(details[:start_year])
find("#end-day").set(details[:end_day])
find("#end-month").set(details[:end_month])
find("#end-year").set(details[:end_year])
find("#development-start-day").set(details[:development_start_day])
find("#development-start-month").set(details[:development_start_month])
find("#development-start-year").set(details[:development_start_year])
fill_in "Contact email/s for website performance review every 6 months*", with: details[:performance_review_contact_email]
fill_in "Which of the current Government Communications Plan priority themes does this campaign website support and how?*", with: details[:government_theme]
fill_in "Campaign description*", with: details[:description]
Expand Down
142 changes: 122 additions & 20 deletions spec/models/support/gds/campaign_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,52 @@ def as_str(date)
date.strftime("%d-%m-%Y")
end

subject do
Campaign.new(
let(:required_attr) do
{
signed_campaign: "Test Signer",
has_read_guidance_confirmation: "Yes",
has_read_oasis_guidance_confirmation: "Yes",
full_responsibility_confirmation: "Yes",
accessibility_confirmation: "Yes",
cookie_and_privacy_notice_confirmation: "Yes",
start_date: as_str(Time.zone.today),
end_date: as_str(Date.tomorrow),
development_start_date: as_str(Time.zone.today),
start_day: Time.zone.today.strftime("%d"),
start_month: Time.zone.today.strftime("%m"),
start_year: Time.zone.today.strftime("%Y"),
end_day: Time.zone.tomorrow.strftime("%d"),
end_month: Time.zone.tomorrow.strftime("%m"),
end_year: Time.zone.tomorrow.strftime("%Y"),
development_start_day: Time.zone.today.strftime("%d"),
development_start_month: Time.zone.today.strftime("%m"),
development_start_year: Time.zone.today.strftime("%Y"),
performance_review_contact_email: "[email protected]",
government_theme: "Test theme",
description: "Test Description",
call_to_action: "Test Call to Action",
proposed_url: "example.campaign.gov.uk",
site_title: "Some title",
site_tagline: "Some tagline",
site_metadescription: "tag1, tag2",
cost_of_campaign: 1200,
hmg_code: "HMGXX-XXX",
strategic_planning_code: "CSBXX-XXX",
ga_contact_email: "[email protected]",
)
}
end

subject do
Campaign.new(required_attr)
end

it { should validate_presence_of(:signed_campaign) }
it { should validate_presence_of(:start_date) }
it { should validate_presence_of(:end_date) }
it { should validate_presence_of(:development_start_date) }
it { should validate_presence_of(:start_day) }
it { should validate_presence_of(:start_month) }
it { should validate_presence_of(:start_year) }
it { should validate_presence_of(:end_day) }
it { should validate_presence_of(:end_month) }
it { should validate_presence_of(:end_year) }
it { should validate_presence_of(:development_start_day) }
it { should validate_presence_of(:development_start_month) }
it { should validate_presence_of(:development_start_year) }
it { should validate_presence_of(:performance_review_contact_email) }
it { should validate_presence_of(:government_theme) }
it { should validate_presence_of(:description) }
Expand All @@ -58,9 +76,32 @@ def as_str(date)
it { should allow_value("example.campaign.gov.uk").for(:proposed_url) }
it { should_not allow_value("Non Campaign platform").for(:proposed_url) }

it { should_not allow_value("xxx").for(:start_date) }
it { should_not allow_value("xxx").for(:end_date) }
it { should_not allow_value("xxx").for(:development_start_date) }
it "should not allow 'start date' values to be random characters " do
constraint = Campaign.new(
start_day: "xxx",
start_month: "xxx",
start_year: "xxx",
)
expect(constraint).to_not be_valid
end

it "should not allow 'end date' values to be random characters " do
constraint = Campaign.new(
end_day: "xxx",
end_month: "xxx",
end_year: "xxx",
)
expect(constraint).to_not be_valid
end

it "should not allow 'development start date' values to be random characters " do
constraint = Campaign.new(
development_start_day: "xxx",
development_start_month: "xxx",
development_start_year: "xxx",
)
expect(constraint).to_not be_valid
end

it { should allow_value("[email protected]").for(:performance_review_contact_email) }
it { should allow_value("[email protected]").for(:performance_review_contact_email) }
Expand All @@ -70,16 +111,77 @@ def as_str(date)
it { should_not allow_value("test").for(:performance_review_contact_email) }
it { should_not allow_value("test@").for(:performance_review_contact_email) }

it { should allow_value(as_str(Date.tomorrow)).for(:start_date) }
it { should allow_value(as_str(Time.zone.today)).for(:start_date) }
it { should_not allow_value(as_str(Time.zone.today - 1)).for(:start_date) }
it "allows the start date to be after today" do
required_attr[:start_day] = Time.zone.tomorrow.strftime("%d")
required_attr[:start_month] = Time.zone.tomorrow.strftime("%m")
required_attr[:start_year] = Time.zone.tomorrow.strftime("%Y")

required_attr[:end_day] = (Time.zone.tomorrow + 1).strftime("%d")
required_attr[:end_month] = (Time.zone.tomorrow + 1).strftime("%m")
required_attr[:end_year] = (Time.zone.tomorrow + 1).strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to be_valid
end

it "allows the start date to be today" do
constraint = Campaign.new(required_attr)
expect(constraint).to be_valid
end

it "doesn't allow the start date to in the past" do
required_attr[:start_day] = Time.zone.yesterday.strftime("%d")
required_attr[:start_month] = Time.zone.yesterday.strftime("%m")
required_attr[:start_year] = Time.zone.yesterday.strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to_not be_valid
end

it "allows the end date to be after the start day" do
required_attr[:end_day] = Time.zone.tomorrow.strftime("%d")
required_attr[:end_month] = Time.zone.tomorrow.strftime("%m")
required_attr[:end_year] = Time.zone.tomorrow.strftime("%Y")

it { should allow_value(as_str(Date.tomorrow)).for(:end_date) }
it { should_not(allow_value(as_str(Time.zone.today)).for(:end_date)) }
constraint = Campaign.new(required_attr)
expect(constraint).to be_valid
end

it "should not allow the end date to be before the start date" do
required_attr[:end_day] = Time.zone.today.strftime("%d")
required_attr[:end_month] = Time.zone.today.strftime("%m")
required_attr[:end_year] = Time.zone.today.strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to_not be_valid
end

it { should_not allow_value(as_str(Date.tomorrow)).for(:development_start_date) }
it { should allow_value(as_str(Time.zone.today - 1)).for(:development_start_date) }
it { should allow_value(as_str(Time.zone.today)).for(:development_start_date) }
it "should not allow the development start date to be after start date" do
required_attr[:development_start_day] = Time.zone.tomorrow.strftime("%d")
required_attr[:development_start_month] = Time.zone.tomorrow.strftime("%m")
required_attr[:development_start_year] = Time.zone.tomorrow.strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to_not be_valid
end

it "should allow the development start date to be before the start date" do
required_attr[:development_start_day] = Time.zone.yesterday.strftime("%d")
required_attr[:development_start_month] = Time.zone.yesterday.strftime("%m")
required_attr[:development_start_year] = Time.zone.yesterday.strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to be_valid
end

it "should allow the development start date to be on the start date" do
required_attr[:development_start_day] = Time.zone.today.strftime("%d")
required_attr[:development_start_month] = Time.zone.today.strftime("%m")
required_attr[:development_start_year] = Time.zone.today.strftime("%Y")

constraint = Campaign.new(required_attr)
expect(constraint).to be_valid
end

it { should allow_value("[email protected]").for(:ga_contact_email) }
it { should allow_value("[email protected]").for(:ga_contact_email) }
Expand Down

0 comments on commit d4f16b0

Please sign in to comment.