diff --git a/Gemfile.lock b/Gemfile.lock index f4d5c8396..9e3034db2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM logstash-event (1.2.02) logstash-logger (0.25.1) logstash-event (~> 1.2) - loofah (2.2.1) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) @@ -220,8 +220,8 @@ GEM activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) railties (4.2.10) actionpack (= 4.2.10) activesupport (= 4.2.10) diff --git a/app/assets/stylesheets/petitions/_forms.scss b/app/assets/stylesheets/petitions/_forms.scss index 7a6cc9ddc..6c0cd36fc 100644 --- a/app/assets/stylesheets/petitions/_forms.scss +++ b/app/assets/stylesheets/petitions/_forms.scss @@ -27,6 +27,10 @@ select.form-control:hover { width: 25%; } +.form-control-auto { + width: auto; +} + .form-group { margin-bottom: $gutter; clear: both; diff --git a/app/controllers/admin/holidays_controller.rb b/app/controllers/admin/holidays_controller.rb new file mode 100644 index 000000000..695b702de --- /dev/null +++ b/app/controllers/admin/holidays_controller.rb @@ -0,0 +1,34 @@ +class Admin::HolidaysController < Admin::AdminController + before_action :require_sysadmin + before_action :fetch_holiday + + def edit + respond_to do |format| + format.html + end + end + + def update + if @holiday.update(holiday_params) + redirect_to edit_admin_site_url, notice: :site_updated + else + respond_to do |format| + format.html { render :edit } + end + end + end + + private + + def fetch_holiday + @holiday = Holiday.instance + end + + def holiday_params + params.require(:holiday).permit(*holiday_attributes) + end + + def holiday_attributes + %i[christmas_start christmas_end easter_start easter_end] + end +end diff --git a/app/helpers/date_time_helper.rb b/app/helpers/date_time_helper.rb index 230d32e5f..316f9e068 100644 --- a/app/helpers/date_time_helper.rb +++ b/app/helpers/date_time_helper.rb @@ -59,12 +59,10 @@ def scheduled_for_debate_in_words(date, today = Date.current) end def christmas_period?(today = Date.current) - if today.mon == 12 - today.day > 21 ? true : false - elsif today.mon == 1 - today.day < 5 ? true : false - else - false - end + Holiday.christmas?(today) + end + + def easter_period?(today = Date.current) + Holiday.easter?(today) end end diff --git a/app/models/holiday.rb b/app/models/holiday.rb new file mode 100644 index 000000000..6f0b1b39b --- /dev/null +++ b/app/models/holiday.rb @@ -0,0 +1,48 @@ +class Holiday < ActiveRecord::Base + class << self + def before_remove_const + Thread.current[:__holiday__] = nil + end + + def instance + Thread.current[:__holiday__] ||= first_or_create(defaults) + end + + def christmas?(today = Date.current) + instance.christmas?(today) + end + + def easter?(today = Date.current) + instance.easter?(today) + end + + private + + def defaults + { + christmas_start: '2017-12-22', + christmas_end: '2018-01-04', + easter_start: '2018-03-30', + easter_end: '2018-04-09' + } + end + end + + def christmas?(today = Date.current) + christmas.cover?(today) + end + + def easter?(today = Date.current) + easter.cover?(today) + end + + private + + def christmas + christmas_start..christmas_end + end + + def easter + easter_start..easter_end + end +end diff --git a/app/models/invalidation.rb b/app/models/invalidation.rb index 52ef47f73..26af65b78 100644 --- a/app/models/invalidation.rb +++ b/app/models/invalidation.rb @@ -1,3 +1,5 @@ +require 'textacular/searchable' + class Invalidation < ActiveRecord::Base extend Searchable(:id, :summary, :details, :petition_id) include Browseable diff --git a/app/views/admin/holidays/edit.html.erb b/app/views/admin/holidays/edit.html.erb new file mode 100644 index 000000000..0368a46b6 --- /dev/null +++ b/app/views/admin/holidays/edit.html.erb @@ -0,0 +1,28 @@ +

Edit Site

+ +
+
+ <%= render "admin/shared/site_tabs" %> +
+ +
+ <%= form_for @holiday, url: admin_holidays_url do |form| %> +
+ + <%= form.date_select :christmas_start, {}, tabindex: increment, class: 'form-control form-control-auto' %> + – + <%= form.date_select :christmas_end, {}, tabindex: increment, class: 'form-control form-control-auto' %> +
+ +
+ + <%= form.date_select :easter_start, {}, tabindex: increment, class: 'form-control form-control-auto' %> + – + <%= form.date_select :easter_end, {}, tabindex: increment, class: 'form-control form-control-auto' %> +
+ + <%= form.submit 'Save', class: 'button' %> + <%= link_to 'Cancel', admin_root_path, class: 'button-secondary' %> + <% end %> +
+
diff --git a/app/views/admin/shared/_site_tabs.html.erb b/app/views/admin/shared/_site_tabs.html.erb new file mode 100644 index 000000000..6655cf8f7 --- /dev/null +++ b/app/views/admin/shared/_site_tabs.html.erb @@ -0,0 +1,33 @@ +

+ <% if params[:tab] == "petitions" %> + <%= link_to "Description", edit_admin_site_path %> | + Petitions | + <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | + <%= link_to "Access", edit_admin_site_path(tab: 'access') %> | + <%= link_to "Holidays", edit_admin_holidays_path %> + <% elsif params[:tab] == "moderation" %> + <%= link_to "Description", edit_admin_site_path %> | + <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | + Moderation | + <%= link_to "Access", edit_admin_site_path(tab: 'access') %> | + <%= link_to "Holidays", edit_admin_holidays_path %> + <% elsif params[:tab] == "access" %> + <%= link_to "Description", edit_admin_site_path %> | + <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | + <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | + Access | + <%= link_to "Holidays", edit_admin_holidays_path %> + <% elsif controller_name == "holidays" %> + <%= link_to "Description", edit_admin_site_path %> | + <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | + <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | + <%= link_to "Access", edit_admin_site_path(tab: 'access') %> | + Holidays + <% else %> + Description | + <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | + <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | + <%= link_to "Access", edit_admin_site_path(tab: 'access') %> | + <%= link_to "Holidays", edit_admin_holidays_path %> + <% end %> +

diff --git a/app/views/admin/sites/edit.html.erb b/app/views/admin/sites/edit.html.erb index 3b88d563a..7e246569b 100644 --- a/app/views/admin/sites/edit.html.erb +++ b/app/views/admin/sites/edit.html.erb @@ -2,29 +2,7 @@
-

- <% if params[:tab] == "petitions" %> - <%= link_to "Description", edit_admin_site_path %> | - Petitions | - <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | - <%= link_to "Access", edit_admin_site_path(tab: 'access') %> - <% elsif params[:tab] == "moderation" %> - <%= link_to "Description", edit_admin_site_path %> | - <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | - Moderation | - <%= link_to "Access", edit_admin_site_path(tab: 'access') %> - <% elsif params[:tab] == "access" %> - <%= link_to "Description", edit_admin_site_path %> | - <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | - <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | - Access - <% else %> - Description | - <%= link_to "Petitions", edit_admin_site_path(tab: 'petitions') %> | - <%= link_to "Moderation", edit_admin_site_path(tab: 'moderation') %> | - <%= link_to "Access", edit_admin_site_path(tab: 'access') %> - <% end %> -

+ <%= render "admin/shared/site_tabs" %>
diff --git a/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.html.erb b/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.html.erb index 5449b42d1..36d023fcf 100644 --- a/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.html.erb +++ b/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.html.erb @@ -6,6 +6,8 @@ <% if christmas_period? %>

<%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less but over the Christmas period it may take us a little longer than usual. We’ll check your petition as quickly as we can.

+<% elsif easter_period? %> +

<%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less but over the Easter period it may take us a little longer than usual. We’ll check your petition as quickly as we can.

<% else %>

<%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less.

<% end %> diff --git a/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.text.erb b/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.text.erb index f57264024..e9317369d 100644 --- a/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.text.erb +++ b/app/views/sponsor_mailer/sponsor_signed_email_on_threshold.text.erb @@ -6,6 +6,8 @@ Your petition is nearly ready to go. <% if christmas_period? %> <%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less but over the Christmas period it may take us a little longer than usual. We’ll check your petition as quickly as we can. +<% elsif christmas_period? %> +<%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less but over the Easter period it may take us a little longer than usual. We’ll check your petition as quickly as we can. <% else %> <%= @sponsor_count %> people have supported your petition so far. We’re checking your petition to make sure it meets the petition standards. If it does, we’ll publish it. This usually takes a week or less. <% end %> diff --git a/config/routes.rb b/config/routes.rb index 434d6aaf1..0fe572070 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -127,6 +127,7 @@ resource :rate_limits, path: 'rate-limits', only: %i[edit update] resource :site, only: %i[edit update] + resource :holidays, only: %i[edit update] resources :signatures, only: %i[index destroy] do post :validate, :invalidate, on: :member diff --git a/db/migrate/20180329062433_create_holidays.rb b/db/migrate/20180329062433_create_holidays.rb new file mode 100644 index 000000000..cdce7e50f --- /dev/null +++ b/db/migrate/20180329062433_create_holidays.rb @@ -0,0 +1,11 @@ +class CreateHolidays < ActiveRecord::Migration + def change + create_table :holidays do |t| + t.date :christmas_start + t.date :christmas_end + t.date :easter_start + t.date :easter_end + t.timestamps null: false + end + end +end diff --git a/db/structure.sql b/db/structure.sql index bc2b9e17f..bbba100f5 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -657,6 +657,40 @@ CREATE SEQUENCE government_responses_id_seq ALTER SEQUENCE government_responses_id_seq OWNED BY government_responses.id; +-- +-- Name: holidays; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE holidays ( + id integer NOT NULL, + christmas_start date, + christmas_end date, + easter_start date, + easter_end date, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- +-- Name: holidays_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE holidays_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: holidays_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE holidays_id_seq OWNED BY holidays.id; + + -- -- Name: invalidations; Type: TABLE; Schema: public; Owner: -; Tablespace: -- @@ -1266,6 +1300,13 @@ ALTER TABLE ONLY feedback ALTER COLUMN id SET DEFAULT nextval('feedback_id_seq': ALTER TABLE ONLY government_responses ALTER COLUMN id SET DEFAULT nextval('government_responses_id_seq'::regclass); +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY holidays ALTER COLUMN id SET DEFAULT nextval('holidays_id_seq'::regclass); + + -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1478,6 +1519,14 @@ ALTER TABLE ONLY government_responses ADD CONSTRAINT government_responses_pkey PRIMARY KEY (id); +-- +-- Name: holidays_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY holidays + ADD CONSTRAINT holidays_pkey PRIMARY KEY (id); + + -- -- Name: invalidations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -2607,3 +2656,5 @@ INSERT INTO schema_migrations (version) VALUES ('20171204113835'); INSERT INTO schema_migrations (version) VALUES ('20171204122339'); +INSERT INTO schema_migrations (version) VALUES ('20180329062433'); + diff --git a/features/step_definitions/common_steps.rb b/features/step_definitions/common_steps.rb index f6db04646..d649611e9 100644 --- a/features/step_definitions/common_steps.rb +++ b/features/step_definitions/common_steps.rb @@ -47,7 +47,7 @@ end Then(/^I wait for (\d+) ((?:day|week|month|year|)s?)$/) do |duration, period| - travel(duration.to_i.send(period) + 1.second) + travel_to(Time.current + (duration.to_i.send(period) + 1.second)) end Then /^the response status should be (\d+)$/ do |code| diff --git a/spec/helpers/date_time_helper_spec.rb b/spec/helpers/date_time_helper_spec.rb index e81c7dfb8..b44ea987f 100644 --- a/spec/helpers/date_time_helper_spec.rb +++ b/spec/helpers/date_time_helper_spec.rb @@ -186,4 +186,56 @@ end end end + + describe "#easter_period?" do + context "when the date is before the 30th Mar" do + around do |example| + travel_to("2018-03-29") { example.run } + end + + it "returns false" do + expect(helper.easter_period?).to eq(false) + end + end + + context "when the date is the 30th Mar" do + around do |example| + travel_to("2018-03-30") { example.run } + end + + it "returns true" do + expect(helper.easter_period?).to eq(true) + end + end + + context "when the date is between 30th Mar and 9th Apr" do + around do |example| + travel_to("2018-04-01") { example.run } + end + + it "returns true" do + expect(helper.easter_period?).to eq(true) + end + end + + context "when the date is the 9th Apr" do + around do |example| + travel_to("2018-04-09") { example.run } + end + + it "returns true" do + expect(helper.easter_period?).to eq(true) + end + end + + context "when the date is after the 9th Apr" do + around do |example| + travel_to("2018-04-10") { example.run } + end + + it "returns false" do + expect(helper.easter_period?).to eq(false) + end + end + end end diff --git a/spec/mailers/sponsor_mailer_spec.rb b/spec/mailers/sponsor_mailer_spec.rb index f91ac1ef4..2fead99e5 100644 --- a/spec/mailers/sponsor_mailer_spec.rb +++ b/spec/mailers/sponsor_mailer_spec.rb @@ -158,5 +158,41 @@ expect(mail).not_to have_body_text(%r[over the Christmas period it may take us a little longer than usual]) end end + + context "before the Easter period" do + around do |example| + travel_to("2018-03-29") { example.run } + end + + it_behaves_like "a sponsor signed on threshold email" + + it "doesn't include the moderation delay message" do + expect(mail).not_to have_body_text(%r[over the Easter period it may take us a little longer than usual]) + end + end + + context "during the Easter period" do + around do |example| + travel_to("2018-04-01") { example.run } + end + + it_behaves_like "a sponsor signed on threshold email" + + it "includes the moderation delay message" do + expect(mail).to have_body_text(%r[over the Easter period it may take us a little longer than usual]) + end + end + + context "after the Easter period" do + around do |example| + travel_to("2018-04-10") { example.run } + end + + it_behaves_like "a sponsor signed on threshold email" + + it "doesn't include the moderation delay message" do + expect(mail).not_to have_body_text(%r[over the Easter period it may take us a little longer than usual]) + end + end end end