Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new transition form #1384

Merged
merged 11 commits into from
Sep 11, 2023
52 changes: 49 additions & 3 deletions app/controllers/sites_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
class SitesController < ApplicationController
before_action :find_site
before_action :find_site, only: %i[edit update show]
before_action :find_organisation, only: %i[new create]
before_action :check_user_is_gds_editor, only: %i[edit update]
before_action :check_user_is_site_manager, only: %i[new create]

def new
@site_form = SiteForm.new(organisation_slug: @organisation.whitehall_slug)
end

def create
@site_form = SiteForm.new(create_params)

if (site = @site_form.save)
redirect_to site_path(site), flash: { success: "Transition site created" }
else
render :new
end
end

def edit; end

def update
if @site.update(site_params)
if @site.update(update_params)
redirect_to site_path(@site), flash: { success: "Transition date updated" }
else
redirect_to edit_site_path(@site), flash: { alert: "We couldn't save your change" }
Expand All @@ -24,7 +40,30 @@ def find_site
@site = Site.find_by!(abbr: params[:id])
end

def site_params
def find_organisation
@organisation = Organisation.find_by(whitehall_slug: params[:organisation_id])
end

def create_params
params.require(:site_form).permit(
:organisation_slug,
:abbr,
:tna_timestamp,
:homepage,
:homepage_title,
:global_type,
:global_new_url,
:global_redirect_append_path,
:homepage_furl,
:hostname,
:query_params,
:special_redirect_strategy,
:aliases,
extra_organisations: [],
)
end

def update_params
params.require(:site).permit(:launch_date)
end

Expand All @@ -34,4 +73,11 @@ def check_user_is_gds_editor
redirect_to site_path(@site), alert: message
end
end

def check_user_is_site_manager
unless current_user.site_manager?
message = "Only Site Managers can access that."
redirect_to organisation_path(@organisation), alert: message
end
end
end
105 changes: 105 additions & 0 deletions app/forms/site_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
class SiteForm
include ActiveModel::Model
include ActiveModel::Attributes

attribute :organisation_slug
attribute :abbr
attribute :tna_timestamp, :datetime
attribute :homepage
attribute :homepage_title
attribute :extra_organisations
attribute :global_type
attribute :global_new_url
attribute :homepage_furl
attribute :query_params
attribute :global_redirect_append_path, :boolean, default: false
attribute :special_redirect_strategy

attribute :hostname
attribute :aliases

validate :validate_children
validate :validate_aliases
validate :aliases_are_unique

def save
return false if invalid?

ActiveRecord::Base.transaction do
site.save!
hosts.each(&:save!)
aka_hosts.each(&:save!)
end

site
end

def organisations
Organisation.where.not(whitehall_slug: organisation_slug)
end

private

def site
@site ||= Site.new(
abbr:,
tna_timestamp:,
homepage:,
organisation: Organisation.find_by(whitehall_slug: organisation_slug),
extra_organisations: Organisation.where(title: extra_organisations),
homepage_title:,
homepage_furl:,
global_type:,
global_new_url:,
global_redirect_append_path:,
query_params:,
special_redirect_strategy:,
)
end

def hosts
[default_host].concat(alias_hosts)
end

def aka_hosts
hosts.map { |host| build_aka_host(host) }
end

def default_host
@default_host ||= Host.new(hostname:, site:)
end

def alias_hosts
return [] if aliases.nil?

@alias_hosts ||= aliases.split(",").map do |host|
Host.new(hostname: host, site:)
end
end

def build_aka_host(host)
Host.new(hostname: host.aka_hostname, canonical_host: host, site:)
end

def validate_children
[site, default_host].each do |child|
errors.merge!(child.errors) if child.invalid?
end
end

def validate_aliases
alias_hosts.each do |host|
next if host.valid?

host.errors.each do |error|
errors.add(:aliases, "\"#{host.hostname}\" #{error.message}")
end
end
end

def aliases_are_unique
if alias_hosts.length != alias_hosts.map(&:hostname).uniq.length
errors.add(:aliases, "must be unique")
end
end
end
8 changes: 8 additions & 0 deletions app/models/concerns/nilify_blanks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ module NilifyBlanks

def nilify_blanks
attributes.each do |column, value|
next if nilify_except.include?(column.to_sym)

self[column] = nil if value.blank?
end
end

private

def nilify_except
[]
end
end
9 changes: 8 additions & 1 deletion app/models/host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class Host < ApplicationRecord
validates :hostname, presence: true
validates :hostname, hostname: true
validates :site, presence: true
validate :canonical_host_id_xor_aka_present
validate :canonical_host_id_xor_aka_present, if: -> { hostname.present? }
validate :hostname_is_downcased, if: -> { hostname.present? }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just not downcase the host before we send it on?


after_update :update_hits_relations, if: :saved_change_to_site_id?

Expand Down Expand Up @@ -71,4 +72,10 @@ def update_hits_relations
hits.update_all(mapping_id: nil)
Transition::Import::HitsMappingsRelations.refresh!(site)
end

def hostname_is_downcased
if hostname != hostname.downcase
errors.add(:hostname, "must be lowercase")
end
end
end
12 changes: 11 additions & 1 deletion app/models/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
require "./lib/transition/path_or_url"

class Site < ApplicationRecord
include NilifyBlanks

GLOBAL_TYPES = %w[redirect archive].freeze
SPECIAL_REDIRECT_STRATEGY_TYPES = %w[via_aka supplier].freeze

belongs_to :organisation

has_many :hosts
Expand All @@ -20,8 +25,9 @@ class Site < ApplicationRecord
validates :organisation, presence: true
validates :homepage, presence: true, non_blank_url: true
validates :abbr, uniqueness: true, presence: true, format: { with: /\A[a-zA-Z0-9_-]+\z/, message: "can only contain alphanumeric characters, underscores and dashes" }
validates :special_redirect_strategy, inclusion: { in: %w[via_aka supplier], allow_nil: true }
validates :special_redirect_strategy, inclusion: { in: SPECIAL_REDIRECT_STRATEGY_TYPES, allow_blank: true }
validates :global_new_url, presence: { if: :global_redirect? }
validates :global_new_url, absence: { if: :global_archive? }
validates :global_new_url,
format: { without: /\?/,
message: "cannot contain a query when the path is appended",
Expand Down Expand Up @@ -131,4 +137,8 @@ def should_remove_unused_view?
def remove_all_hits_view
Postgres::MaterializedView.drop(precomputed_view_name)
end

def nilify_except
%i[global_redirect_append_path query_params precompute_all_hits_view]
end
end
4 changes: 4 additions & 0 deletions app/views/organisations/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
<%= render 'in_conjunction_with' %>
</header>

<% if current_user.site_manager? %>
<%= link_to "Add a transition site", new_organisation_site_path(@organisation), class: "btn btn-default" %>
<% end %>

<% unless @sites.empty? %>
<h2>Sites</h2>
<table class="sites table table-hover table-striped table-bordered" data-module="filterable-table">
Expand Down
120 changes: 120 additions & 0 deletions app/views/sites/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<% breadcrumb(:new_site, @organisation) %>

<div class="page-title-with-border">
<h1>New transition site</h1>
</div>

<%= form_for @site_form, html: { role: "form" }, url: organisation_sites_path do |form| %>
<%= render "shared/error_messages", error_messages: form.object.errors.full_messages %>

<div class="form-group row">
<div class="col-md-8">
<%= form.hidden_field :organisation_slug, value: @organisation.whitehall_slug %>

<div class="form-group">
<%= form.label :abbr %>
<%= form.text_field :abbr, class: "form-control", aria: { describedby: "abbr-help" } %>
<small id="abbr-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.abbr") %></small>
</div>

<div class="form-group">
<%= form.label :tna_timestamp %>
<%= form.text_field :tna_timestamp, class: "form-control", aria: { describedby: "tna-timestamp-help" } %>
<small id="tna-timestamp-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.tna_timestamp").html_safe %></small>
</div>

<div class="form-group">
<%= form.label :homepage %>
<%= form.text_field :homepage, class: "form-control", aria: { describedby: "homepage-help" } %>
<small id="homepage-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.homepage") %></small>
</div>

<div class="form-group">
<%= form.label :hostname %>
<%= form.text_field :hostname, class: "form-control", aria: { describedby: "hostname-help" } %>
<small id="hostname-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.hostname") %></small>
</div>

<div class="form-group">
<%= form.label :homepage_title %>
<%= form.text_field :homepage_title, class: "form-control", aria: { describedby: "homepage-title-help" } %>
<small id="homepage-title-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.homepage_title") %></small>
</div>

<div class="form-group">
<%= form.label :extra_organisations %>
<%= form.collection_select :extra_organisations,
form.object.organisations,
:id,
:title,
{},
{ multiple: true, class: "form-control", aria: { describedby: "extra-organisations-help" } }
%>
<small id="extra-organisations-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.extra_organisations") %></small>
</div>

<div class="form-group">
<%= form.label :homepage_furl %>
<%= form.text_field :homepage_furl, class: "form-control", aria: { describedby: "homepage-furl-help" } %>
<small id="homepage-furl-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.homepage_furl") %></small>
</div>

<div class="form-group">
<%= form.label :global_type %>
<%= form.collection_radio_buttons :global_type,
Site::GLOBAL_TYPES,
:to_s,
:humanize,
aria: { describedby: "global-type-help" } do |button| %>
<div class="radio">
<%= button.label do %>
<%= button.radio_button + button.text %>
<% end %>
</div>
<% end %>
<small id="global-type-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.global_type") %></small>
</div>

<div class="form-group">
<%= form.label :global_new_url %>
<%= form.text_field :global_new_url, class: "form-control" %>
</div>

<div class="form-group">
<%= form.label :query_params %>
<%= form.text_field :query_params, class: "form-control", aria: { describedby: "query-params-help" } %>
<small id="query-params-help" class="form-text text-muted row"><%= I18n.t("activemodel.hint.site_form.query_params") %></small>
</div>

<div class="form-check">
<%= form.label :global_redirect_append_path %>
<%= form.check_box :global_redirect_append_path, aria: { describedby: "global-redirect-append-path-help" } %>
<small id="global-redirect-append-path-help" class="form-text text-muted row"><%= I18n.t("activemodel.hint.site_form.global_redirect_append_path") %></small>
</div>

<div class="form-group">
<%= form.label :special_redirect_strategy %>
<%= form.collection_radio_buttons :special_redirect_strategy,
Site::SPECIAL_REDIRECT_STRATEGY_TYPES,
:to_s,
:humanize,
aria: { describedby: "special-redirect-strategy-help" } do |button| %>
<div class="radio">
<%= button.label do %>
<%= button.radio_button + button.text %>
<% end %>
</div>
<% end %>
<small id="special-redirect-strategy-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.special_redirect_strategy") %></small>
</div>

<div class="form-group">
<%= form.label :aliases %>
<%= form.text_area :aliases, class: "form-control", aria: { describedby: "aliases-help" } %>
<small id="aliases-help" class="form-text text-muted"><%= I18n.t("activemodel.hint.site_form.aliases") %></small>
</div>

<%= form.submit 'Save', class: 'add-top-margin btn btn-success' %>
</div>
</div>
<% end %>
5 changes: 5 additions & 0 deletions config/breadcrumbs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
parent :root
end

crumb :new_site do |organisation|
link "New transition site"
parent :organisation, organisation
end

crumb :site do |site|
link site.default_host.hostname, site_path(site)
parent :organisation, site.organisation
Expand Down
Loading