Browse Source

Cldc 1662 add housing provider (#954)

* wip

* Rename managing_agents column

* add managing relationship

* f

* feat: add my features branched off managing agents branch

* feat: update nav behaviour

* feat: simplify housing_providers view

* feat: fix pluralise to default to plural rather than singular

* feat: remove managing agent related code so can be merged directly

* tests: update tests and add new ones for housing_providers

* refactor: rubocop conciliation

* tests: fix failing navigation tests

* tests: one more plural test

* refactor: erb linting

* refactor: erb linting

* feat: right-align "Remove" text

* feat: update nokogiri to pass bundler-audit

* feat: grey out search button

* feat: remove section-break

* feat: add housing provider page with details and button

* feat: tidy up routing

* feat: add wip housing provider behaviour without functioning search

* feat: wip add housing provider functionality hard coded to add FooBar LTD as provider to DLUHC

* feat: remove redundant code

* feat: add data passing behaviour without accessible autocomplete

* feat: use accessible autocomplete (not working)

* feat: use accessible autocomplete (now working)

* feat: wip commit error messages

* feat: add banner always

* feat: add conditional banner behaviour, back link and update logs titles

* feat: add search icon to accessible autocomplete, make hint text aligned correctly

* feat: use pluck not all

* tests: add initial test

* feat: refactor create logic

* feat: add sub org title

* feat: add correct no housing providers text

* feat: add correct no housing providers text

* tests: add tests for add housing provider page

* feat: remove unnecessary line from controller

* fet: simplify controller args

* fet: update schema

* feat: update schema

* feat: remove create_managing_agent

* test: add support user tests

* test: add create_housing_provider tests

* refactor: rubocop autocorrect

* refactor: erblinting

* test: fix tests

* refactor: erblinting

* feat: don't use !important tag

Co-authored-by: Jack S <jacopo.scotti@softwire.com>
pull/958/head
natdeanlewissoftwire 2 years ago committed by GitHub
parent
commit
b45b98108a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 41
      app/controllers/organisation_relationships_controller.rb
  2. 10
      app/frontend/styles/_accessible-autocomplete.scss
  3. 6
      app/views/logs/index.html.erb
  4. 3
      app/views/organisation_relationships/_related_organisation_select_question.html.erb
  5. 36
      app/views/organisation_relationships/add_housing_provider.html.erb
  6. 40
      app/views/organisation_relationships/housing_providers.html.erb
  7. 2
      config/routes.rb
  8. 124
      spec/requests/organisations_controller_spec.rb

41
app/controllers/organisation_relationships_controller.rb

@ -8,9 +8,11 @@ class OrganisationRelationshipsController < ApplicationController
def housing_providers
housing_providers = organisation.housing_providers
unpaginated_filtered_housing_providers = filtered_collection(housing_providers, search_term)
organisations = Organisation.where.not(id: @organisation.id).pluck(:id, :name)
respond_to do |format|
format.html do
@pagy, @housing_providers = pagy(unpaginated_filtered_housing_providers)
@organisations = organisations
@searched = search_term.presence
@total_count = housing_providers.size
render "organisation_relationships/housing_providers", layout: "application"
@ -31,18 +33,55 @@ class OrganisationRelationshipsController < ApplicationController
end
end
def add_housing_provider
@organisations = Organisation.where.not(id: @organisation.id).pluck(:id, :name)
respond_to do |format|
format.html do
render "organisation_relationships/add_housing_provider", layout: "application"
end
end
end
def create_housing_provider
child_organisation_id = @organisation.id
parent_organisation_id = related_organisation_id
relationship_type = OrganisationRelationship::OWNING
if related_organisation_id.empty?
@organisation.errors.add :related_organisation_id, "You must choose a housing provider"
@organisations = Organisation.where.not(id: child_organisation_id).pluck(:id, :name)
render "organisation_relationships/add_housing_provider"
return
elsif OrganisationRelationship.exists?(child_organisation_id:, parent_organisation_id:, relationship_type:)
@organisation.errors.add :related_organisation_id, "You have already added this housing provider"
@organisations = Organisation.where.not(id: child_organisation_id).pluck(:id, :name)
render "organisation_relationships/add_housing_provider"
return
end
create!(child_organisation_id:, parent_organisation_id:, relationship_type:)
redirect_to housing_providers_organisation_path(related_organisation_id:)
end
def create!(child_organisation_id:, parent_organisation_id:, relationship_type:)
@resource = OrganisationRelationship.new(child_organisation_id:, parent_organisation_id:, relationship_type:)
@resource.save!
end
private
def organisation
@organisation ||= Organisation.find(params[:id])
end
def related_organisation_id
params["organisation"]["related_organisation_id"]
end
def search_term
params["search"]
end
def authenticate_scope!
if current_user.organisation != organisation
if current_user.organisation != organisation && !current_user.support?
render_not_found
end
end

10
app/frontend/styles/_accessible-autocomplete.scss

@ -5,12 +5,22 @@
.autocomplete__input {
font-family: inherit;
background-image: url("data:image/svg+xml,%3Csvg class='app-search__icon' width='20' height='20' viewBox='0 0 27 27' fill='none' xmlns='http://www.w3.org/2000/svg' aria-hidden='true' focusable='false'%3E%3Ccircle cx='12.0161' cy='11.0161' r='8.51613' stroke='currentColor' stroke-width='3'%3E%3C/circle%3E%3Cline x1='17.8668' y1='17.3587' x2='26.4475' y2='25.9393' stroke='currentColor' stroke-width='3'%3E%3C/line%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 1em 1em;
background-position: 7px center;
text-indent: govuk-spacing(6);
}
.autocomplete__option__append {
font-weight: bold;
}
.autocomplete__hint {
font-family: inherit;
text-indent: govuk-spacing(6);
}
.autocomplete__option__hint {
display: block;
color: $govuk-secondary-text-colour;

6
app/views/logs/index.html.erb

@ -3,7 +3,11 @@
<% content_for :title, title %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Logs", sub: nil } : { main: "Logs", sub: current_user.organisation.name } %>
<% if current_page?(controller: 'lettings_logs', action: 'index') %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Lettings logs", sub: nil } : { main: "Lettings logs", sub: current_user.organisation.name } %>
<% elsif current_page?(controller: 'sales_logs', action: 'index') %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Sales logs", sub: nil } : { main: "Sales logs", sub: current_user.organisation.name } %>
<% end %>
<div class="app-filter-layout" data-controller="filter-layout">
<div class="govuk-button-group app-filter-toggle">

3
app/views/organisation_relationships/_related_organisation_select_question.html.erb

@ -0,0 +1,3 @@
<% answers = question.answer_options.map { |key, value| OpenStruct.new(id: key, name: value) } %>
<%= f.govuk_collection_select :related_organisation_id, answers, :id, :name, label: { hidden: true }, "data-controller": "accessible-autocomplete" do %>
<% end %>

36
app/views/organisation_relationships/add_housing_provider.html.erb

@ -0,0 +1,36 @@
<%= form_with model: @organisation, url: housing_providers_organisation_path, method: "post", local: true do |f| %>
<% if current_user.support? %>
<%= render partial: "organisations/headings", locals: { main: @organisation.name, sub: nil } %>
<%= render SubNavigationComponent.new(items: secondary_items(request.path, @organisation.id)) %>
<h2 class="govuk-visually-hidden">Add Housing Provider</h2>
<% end %>
<% if current_user.support? %>
<%= govuk_back_link(href: :back) %>
<%= render partial: "organisations/headings", locals: { main: "What is the name of this organisation's housing provider?", sub: nil } %>
<p class="govuk-body">Start typing to search for a housing provider</p>
<% else %>
<% content_for :before_content do %>
<%= govuk_back_link(href: :back) %>
<% end %>
<%= render partial: "organisations/headings", locals: { main: "What is the name of your housing provider?", sub: nil } %>
<p class="govuk-body">Start typing to search for your housing provider</p>
<% end %>
<% answer_options = { "" => "Select an option" } %>
<% @organisations.each do |organisation| %>
<% answer_options[organisation[0]] = organisation[1] %>
<% end %>
<%= render partial: "organisation_relationships/related_organisation_select_question", locals: {
question: Form::Question.new("", { "answer_options" => answer_options }, nil),
f:,
} %>
<%= f.govuk_submit "Add" %>
<%= govuk_details(summary_text: "Can't find the housing provider you're looking for?") do %>
<ul class="govuk-list govuk-list--bullet">
<li>Double check the spelling and try again</li>
<li>Type the first few letters to see the suggestions</li>
<li>If you still can't find it,
<%= govuk_link_to("contact the DLUHC service desk", "https://digital.dclg.gov.uk/jira/servicedesk/customer/portal/4/group/21", rel: "noreferrer noopener", target: "_blank") %>
</li>
</ul>
<% end %>
<% end %>

40
app/views/organisation_relationships/housing_providers.html.erb

@ -1,21 +1,45 @@
<% item_label = format_label(@pagy.count, "housing providers") %>
<% title = "Housing Providers" %>
<% content_for :title, title %>
<% if current_user.data_coordinator? %>
<% if params["related_organisation_id"] %>
<%= govuk_notification_banner(
title_text: "Success",
success: true, title_heading_level: 3,
title_id: "swanky-notifications"
) do |notification_banner|
notification_banner.heading(text: "#{Organisation.find(params['related_organisation_id']).name} is now one of your housing providers")
end %>
<% end %>
<% end %>
<% if current_user.support? %>
<%= render partial: "organisations/headings", locals: { main: @organisation.name, sub: nil } %>
<%= render SubNavigationComponent.new(items: secondary_items(request.path, @organisation.id)) %>
<h2 class="govuk-visually-hidden">Housing Providers</h2>
<% if params["related_organisation_id"] %>
<%= govuk_notification_banner(
title_text: "Success",
success: true, title_heading_level: 3,
title_id: "swanky-notifications"
) do |notification_banner|
notification_banner.heading(text: "#{Organisation.find(params['related_organisation_id']).name} is now one of this organisation's housing providers")
end %>
<% end %>
<p class="govuk-body">This organisation can submit logs for its housing providers.</p>
<% if @total_count == 0 %>
<p class="govuk-body">This organisation does not currently have any housing providers.</p>
<% end %>
<% else %>
<%= render partial: "organisations/headings", locals: { main: "Your housing providers", sub: nil } %>
<%= render partial: "organisations/headings", locals: { main: "Your housing providers", sub: current_user.organisation.name } %>
<p class="govuk-body">Your organisation can submit logs for its housing providers.</p>
<% if @total_count == 0 %>
<p class="govuk-body">You do not currently have any housing providers.</p>
<% end %>
<% end %>
<% if @total_count == 0 %>
<p class="govuk-body">This organisation does not currently have any housing providers.</p>
<% end %>
<% if current_user.data_coordinator? || current_user.support? %>
<%= govuk_button_link_to "Add a housing provider", housing_providers_organisation_path(organisation_id: @organisation.id), html: { method: :get } %>
<% if current_user.support? %>
<%= govuk_button_link_to "Add a housing provider", housing_providers_add_organisation_path(organisation_id: @organisation.id), html: { method: :get } %>
<% elsif current_user.data_coordinator? %>
<%= govuk_button_link_to "Add a housing provider", housing_providers_add_organisation_path, html: { method: :get } %>
<% end %>
<% if @total_count != 0 %>
<%= render SearchComponent.new(current_user:, search_label: "Search for a housing provider", value: @searched) %>

2
config/routes.rb

@ -80,6 +80,8 @@ Rails.application.routes.draw do
get "logs/csv-confirmation", to: "lettings_logs#csv_confirmation"
get "schemes", to: "organisations#schemes"
get "housing-providers", to: "organisation_relationships#housing_providers"
get "housing-providers/add", to: "organisation_relationships#add_housing_provider"
post "housing-providers", to: "organisation_relationships#create_housing_provider"
get "managing-agents", to: "organisation_relationships#managing_agents"
end
end

124
spec/requests/organisations_controller_spec.rb

@ -254,7 +254,7 @@ RSpec.describe OrganisationsController, type: :request do
expect(response.body).to include(user.email)
end
it "shows hidden accesibility fields only for active users in the current user's organisation" do
it "shows hidden accessibility fields only for active users in the current user's organisation" do
expected_case_row_log = "<span class=\"govuk-visually-hidden\">User </span><span class=\"govuk-!-font-weight-regular app-!-colour-muted\">#{user.email}</span>"
unauthorized_case_row_log = "<span class=\"govuk-visually-hidden\">User </span><span class=\"govuk-!-font-weight-regular app-!-colour-muted\">#{other_org_user.email}</span>"
expect(CGI.unescape_html(response.body)).to include(expected_case_row_log)
@ -288,7 +288,7 @@ RSpec.describe OrganisationsController, type: :request do
context "with an organisation that the user belongs to" do
let!(:housing_provider) { FactoryBot.create(:organisation) }
let!(:other_org_housing_provider) { FactoryBot.create(:organisation, name: "Foobar LTD") }
let!(:other_organisation) { FactoryBot.create(:organisation, name: "Foobar LTD") }
let!(:other_organisation) { FactoryBot.create(:organisation, name: "Foobar LTD 2") }
before do
FactoryBot.create(:organisation_relationship, child_organisation: organisation, parent_organisation: housing_provider, relationship_type: OrganisationRelationship.relationship_types[:owning])
@ -319,6 +319,20 @@ RSpec.describe OrganisationsController, type: :request do
it "shows the pagination count" do
expect(page).to have_content("1 total housing providers")
end
context "when adding a housing provider" do
before do
get "/organisations/#{organisation.id}/housing-providers/add", headers:, params: {}
end
it "has the correct header" do
expect(response.body).to include("What is the name of your housing provider?")
end
it "shows an add button" do
expect(page).to have_button("Add")
end
end
end
context "with an organisation that are not in scope for the user, i.e. that they do not belong to" do
@ -520,6 +534,34 @@ RSpec.describe OrganisationsController, type: :request do
expect { request }.not_to change(Organisation, :count)
end
end
describe "organisation_relationships#create_housing_provider" do
let!(:housing_provider) { FactoryBot.create(:organisation) }
let(:params) do
{
"organisation": {
"related_organisation_id": housing_provider.id,
},
}
end
let(:request) { post "/organisations/#{organisation.id}/housing-providers", headers:, params: }
it "creates a new organisation relationship" do
expect { request }.to change(OrganisationRelationship, :count).by(1)
end
it "sets the organisation relationship attributes correctly" do
request
expect(OrganisationRelationship).to exist(child_organisation_id: organisation.id, parent_organisation_id: housing_provider.id, relationship_type: OrganisationRelationship::OWNING)
end
it "redirects to the organisation list" do
request
expect(response).to redirect_to("/organisations/#{organisation.id}/housing-providers?related_organisation_id=#{housing_provider.id}")
end
end
end
context "with a data provider user" do
@ -1152,6 +1194,56 @@ RSpec.describe OrganisationsController, type: :request do
end
end
context "when viewing a specific organisation's housing providers" do
let!(:housing_provider) { FactoryBot.create(:organisation) }
let!(:other_org_housing_provider) { FactoryBot.create(:organisation, name: "Foobar LTD") }
let!(:other_organisation) { FactoryBot.create(:organisation, name: "Foobar LTD 2") }
before do
FactoryBot.create(:organisation_relationship, child_organisation: organisation, parent_organisation: housing_provider, relationship_type: OrganisationRelationship.relationship_types[:owning])
FactoryBot.create(:organisation_relationship, child_organisation: other_organisation, parent_organisation: other_org_housing_provider, relationship_type: OrganisationRelationship.relationship_types[:owning])
get "/organisations/#{organisation.id}/housing-providers", headers:, params: {}
end
it "displays the name of the organisation" do
expect(page).to have_content(organisation.name)
end
it "has a sub-navigation with correct tabs" do
expect(page).to have_css(".app-sub-navigation")
expect(page).to have_content("Users")
end
it "shows a table of housing providers" do
expected_html = "<table class=\"govuk-table\""
expect(response.body).to include(expected_html)
expect(response.body).to include(housing_provider.name)
end
it "shows only housing providers for this organisation" do
expect(page).to have_content(housing_provider.name)
expect(page).not_to have_content(other_org_housing_provider.name)
end
it "shows the pagination count" do
expect(page).to have_content("1 total housing providers")
end
context "when adding a housing provider" do
before do
get "/organisations/#{organisation.id}/housing-providers/add", headers:, params: {}
end
it "has the correct header" do
expect(response.body).to include("What is the name of this organisation&#39;s housing provider?")
end
it "shows an add button" do
expect(page).to have_button("Add")
end
end
end
context "when there are more than 20 organisations" do
let(:total_organisations_count) { Organisation.all.count }
@ -1309,6 +1401,34 @@ RSpec.describe OrganisationsController, type: :request do
end
end
end
describe "organisation_relationships#create_housing_provider" do
let!(:housing_provider) { FactoryBot.create(:organisation) }
let(:params) do
{
"organisation": {
"related_organisation_id": housing_provider.id,
},
}
end
let(:request) { post "/organisations/#{organisation.id}/housing-providers", headers:, params: }
it "creates a new organisation relationship" do
expect { request }.to change(OrganisationRelationship, :count).by(1)
end
it "sets the organisation relationship attributes correctly" do
request
expect(OrganisationRelationship).to exist(child_organisation_id: organisation.id, parent_organisation_id: housing_provider.id, relationship_type: OrganisationRelationship::OWNING)
end
it "redirects to the organisation list" do
request
expect(response).to redirect_to("/organisations/#{organisation.id}/housing-providers?related_organisation_id=#{housing_provider.id}")
end
end
end
end

Loading…
Cancel
Save