diff --git a/app/components/log_summary_component.html.erb b/app/components/log_summary_component.html.erb new file mode 100644 index 000000000..612f920bd --- /dev/null +++ b/app/components/log_summary_component.html.erb @@ -0,0 +1,67 @@ +
+
+
+
+

+ <%= govuk_link_to case_log_path(log) do %> + Log <%= log.id %> + <% end %> +

+ <% if log.tenancycode? or log.propcode? %> + + <% end %> +
+ + <% if log.needstype? or log.startdate? %> +

+ <% if log.needstype? %> + <%= log.is_general_needs? ? "General needs" : "Supported housing" %>
+ <% end %> + <% if log.startdate? %> + Tenancy starts + <% end %> +

+ <% end %> + + <% if current_user.support? %> + <% if log.owning_organisation or log.managing_organisation %> + + <% end %> + <% end %> +
+ + +
+
diff --git a/app/components/log_summary_component.rb b/app/components/log_summary_component.rb new file mode 100644 index 000000000..bbd504e5d --- /dev/null +++ b/app/components/log_summary_component.rb @@ -0,0 +1,13 @@ +class LogSummaryComponent < ViewComponent::Base + attr_reader :current_user, :log + + def initialize(current_user:, log:) + @current_user = current_user + @log = log + super + end + + def log_status + helpers.status_tag(log.status) + end +end diff --git a/app/components/search_result_caption_component.html.erb b/app/components/search_result_caption_component.html.erb index f16cc485e..f2a553828 100644 --- a/app/components/search_result_caption_component.html.erb +++ b/app/components/search_result_caption_component.html.erb @@ -1,7 +1,7 @@ - - <% if searched.present? %> - <%= count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total <%= item %>. <%= govuk_link_to("Clear search", path) %> - <% else %> - <%= count %> total <%= item %>. - <% end %> + + <% if searched.present? %> + <%= count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total <%= item %>. <%= govuk_link_to("Clear search", path) %> + <% else %> + <%= count %> total <%= item %> + <% end %> diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb index 907b0fddc..cb600b004 100644 --- a/app/controllers/organisations_controller.rb +++ b/app/controllers/organisations_controller.rb @@ -29,13 +29,24 @@ class OrganisationsController < ApplicationController end def users - @pagy, @users = pagy(filtered_users(@organisation.users.sorted_by_organisation_and_role, search_term)) - @searched = search_term.presence - @total_count = @organisation.users.size - if current_user.support? - render "users", layout: "application" - else - render "users/index" + organisation_users = @organisation.users.sorted_by_organisation_and_role + unpaginated_filtered_users = filtered_collection(organisation_users, search_term) + + respond_to do |format| + format.html do + @pagy, @users = pagy(unpaginated_filtered_users) + @searched = search_term.presence + @total_count = @organisation.users.size + + if current_user.support? + render "users", layout: "application" + else + render "users/index" + end + end + format.csv do + send_data unpaginated_filtered_users.to_csv, filename: "users-#{@organisation.name}-#{Time.zone.now}.csv" + end end end @@ -83,11 +94,18 @@ class OrganisationsController < ApplicationController organisation_logs = CaseLog.all.where(owning_organisation_id: @organisation.id) unpaginated_filtered_logs = filtered_case_logs(filtered_collection(organisation_logs, search_term)) - @pagy, @case_logs = pagy(unpaginated_filtered_logs) - @searched = search_term.presence - @total_count = organisation_logs.size - - render "logs", layout: "application" + respond_to do |format| + format.html do + @pagy, @case_logs = pagy(unpaginated_filtered_logs) + @searched = search_term.presence + @total_count = organisation_logs.size + render "logs", layout: "application" + end + + format.csv do + send_data unpaginated_filtered_logs.to_csv, filename: "logs-#{@organisation.name}-#{Time.zone.now}.csv" + end + end else redirect_to(case_logs_path) end diff --git a/app/frontend/styles/_log.scss b/app/frontend/styles/_log.scss new file mode 100644 index 000000000..f24f92a3f --- /dev/null +++ b/app/frontend/styles/_log.scss @@ -0,0 +1,23 @@ +.app-log-summary { + border-top: 1px solid $govuk-border-colour; + padding-top: govuk-spacing(3); +} + +.app-log-summary__header { + align-items: baseline; + display: flex; +} + +.app-log-summary__title { + margin: 0 govuk-spacing(3) govuk-spacing(2) 0; +} + +@include govuk-media-query(tablet) { + .app-log-summary__footer { + text-align: right; + } + + .app-log-summary__footer--actor { + display: block; + } +} diff --git a/app/frontend/styles/_metadata.scss b/app/frontend/styles/_metadata.scss new file mode 100644 index 000000000..7dc18d9b7 --- /dev/null +++ b/app/frontend/styles/_metadata.scss @@ -0,0 +1,23 @@ +.app-metadata { + @include govuk-font($size: 16, $tabular: true); + color: $govuk-secondary-text-colour; + margin-top: 0; + + &--inline { + display: flex; + gap: govuk-spacing(3); + margin: 0; + } + + &__item { + display: flex; + } + + &__term { + margin-right: govuk-spacing(1); + } + + &__definition { + margin-left: 0; + } +} diff --git a/app/frontend/styles/application.scss b/app/frontend/styles/application.scss index 4b26044d1..e862aec23 100644 --- a/app/frontend/styles/application.scss +++ b/app/frontend/styles/application.scss @@ -30,6 +30,8 @@ $govuk-breakpoints: ( @import "filter-layout"; @import "header"; @import "input"; +@import "log"; +@import "metadata"; @import "related-navigation"; @import "section-skip-link"; @import "table-group"; diff --git a/app/models/form/question.rb b/app/models/form/question.rb index eb437b456..c21477bc9 100644 --- a/app/models/form/question.rb +++ b/app/models/form/question.rb @@ -5,6 +5,11 @@ class Form::Question :inferred_answers, :hidden_in_check_answers, :inferred_check_answers_value, :guidance_partial, :prefix, :suffix, :requires_js, :fields_added, :derived + module GuidancePosition + TOP = 1 + BOTTOM = 2 + end + def initialize(id, hsh, page) @id = id @page = page @@ -12,6 +17,7 @@ class Form::Question @check_answer_label = hsh["check_answer_label"] @header = hsh["header"] @guidance_partial = hsh["guidance_partial"] + @guidance_position = GuidancePosition::TOP @hint_text = hsh["hint_text"] @type = hsh["type"] @min = hsh["min"] @@ -238,6 +244,14 @@ class Form::Question case_log[id].to_s == answer.id.to_s end + def top_guidance? + @guidance_partial && @guidance_position == GuidancePosition::TOP + end + + def bottom_guidance? + @guidance_partial && @guidance_position == GuidancePosition::BOTTOM + end + private def selected_answer_option_is_derived?(case_log) diff --git a/app/models/form/setup/questions/scheme_id.rb b/app/models/form/setup/questions/scheme_id.rb index 27a9a6664..3c4985de1 100644 --- a/app/models/form/setup/questions/scheme_id.rb +++ b/app/models/form/setup/questions/scheme_id.rb @@ -7,6 +7,8 @@ class Form::Setup::Questions::SchemeId < ::Form::Question @type = "select" @answer_options = answer_options @derived = true unless FeatureToggle.supported_housing_schemes_enabled? + @guidance_position = GuidancePosition::BOTTOM + @guidance_partial = "scheme_selection" end def answer_options diff --git a/app/models/scheme.rb b/app/models/scheme.rb index bf9111d9b..7b18d8b0e 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -7,7 +7,13 @@ class Scheme < ApplicationRecord scope :filter_by_id, ->(id) { where(id: (id.start_with?("S") ? id[1..] : id)) } scope :search_by_service_name, ->(name) { where("service_name ILIKE ?", "%#{name}%") } scope :search_by_postcode, ->(postcode) { joins("LEFT JOIN locations ON locations.scheme_id = schemes.id").where("locations.postcode ILIKE ?", "%#{UKPostcode.parse(postcode)}%") } - scope :search_by, ->(param) { search_by_postcode(param).or(search_by_service_name(param)).or(filter_by_id(param)).distinct } + scope :search_by_location_name, ->(name) { joins("LEFT JOIN locations ON locations.scheme_id = schemes.id").where("locations.name ILIKE ?", "%#{name}%") } + scope :search_by, lambda { |param| + search_by_postcode(param) + .or(search_by_service_name(param)) + .or(search_by_location_name(param)) + .or(filter_by_id(param)).distinct + } validate :validate_confirmed @@ -214,7 +220,6 @@ class Scheme < ApplicationRecord if confirmed == true required_attributes.any? do |attribute| if self[attribute].blank? - errors.add :base errors.add attribute.to_sym self.confirmed = false end diff --git a/app/views/case_logs/_log_list.html.erb b/app/views/case_logs/_log_list.html.erb index c08bfa067..6dab48bbc 100644 --- a/app/views/case_logs/_log_list.html.erb +++ b/app/views/case_logs/_log_list.html.erb @@ -1,68 +1,8 @@ -
- <%= govuk_table do |table| %> - <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular], id: title.dasherize) do |caption| %> - <%= render(SearchResultCaptionComponent.new(searched:, count: pagy.count, item_label:, total_count:, item: "logs", path: request.path)) %> - <%= govuk_link_to "Download (CSV)", "/logs.csv", type: "text/csv" %> - <% end %> - <%= table.head do |head| %> - <%= head.row do |row| %> - <% row.cell(header: true, text: "Log", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Tenant", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Property", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Tenancy starts", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Log created", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Log status", html_attributes: { - scope: "col", - }) %> - <% if current_user.support? %> - <% row.cell(header: true, text: "Owning organisation", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Managing organisation", html_attributes: { - scope: "col", - }) %> - <% end %> - <% end %> - <% end %> - <%= table.body do |body| %> - <% case_logs.map do |log| %> - <%= body.row do |row| %> - <% row.cell(header: true, html_attributes: { - scope: "row", - }) do %> - <%= govuk_link_to case_log_path(log) do %> - Log <%= log.id %> - <% end %> - <% end %> - <% row.cell( - text: log.tenancycode? ? log.tenancycode : "–", - classes: "app-!-font-tabular", - ) %> - <% row.cell( - text: log.propcode? ? log.propcode : "–", - classes: "app-!-font-tabular", - ) %> - <% row.cell(text: log.startdate.present? ? log.startdate.to_formatted_s(:govuk_date) : "–") %> - <% row.cell(text: log.created_at.to_formatted_s(:govuk_date)) %> - <% row.cell do %> - <%= status_tag(log.status) %> - <% end %> - <% if current_user.support? %> - <% row.cell(text: log.owning_organisation&.name) %> - <% row.cell(text: log.managing_organisation&.name) %> - <% end %> - <% end %> - <% end %> - <% end %> - <% end %> -
+

+ <%= render(SearchResultCaptionComponent.new(searched:, count: pagy.count, item_label:, total_count:, item: "logs", path: request.path)) %> + <%= govuk_link_to "Download (CSV)", "#{request.path}.csv", type: "text/csv" %> +

+ +<% case_logs.map do |log| %> + <%= render(LogSummaryComponent.new(current_user:, log:)) %> +<% end %> diff --git a/app/views/content/accessibility_statement.md b/app/views/content/accessibility_statement.md index 027a641e0..c0fcf7a5d 100644 --- a/app/views/content/accessibility_statement.md +++ b/app/views/content/accessibility_statement.md @@ -10,7 +10,7 @@ This website is run by the Department for Levelling Up, Housing and Communities We’ve also made the website text as simple as possible to understand. -AbilityNet has advice on making your device easier to use if you have a disability. +[AbilityNet has advice on making your device easier to use](https://mcmw.abilitynet.org.uk/) if you have a disability. ### How accessible this website is @@ -32,15 +32,15 @@ If you need information on this website in a different format like accessible PD We’ll consider your request and get back to you in 2 working days. -You can also contact us through the helpdesk. +You can also [contact us through the helpdesk](https://digital.dclg.gov.uk/jira/servicedesk/customer/portal/4/). ### Reporting accessibility problems with this website -We’re always looking to improve the accessibility of this website. If you find any problems not listed on this page or think we’re not meeting accessibility requirements, contact the helpdesk. +We’re always looking to improve the accessibility of this website. If you find any problems not listed on this page or think we’re not meeting accessibility requirements, [contact the helpdesk](https://digital.dclg.gov.uk/jira/servicedesk/customer/portal/4/). ### Enforcement procedure -The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, contact the Equality Advisory and Support Service (EASS). +The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, [contact the Equality Advisory and Support Service (EASS)](https://www.equalityadvisoryservice.com/). ## Technical information about this website’s accessibility @@ -48,7 +48,7 @@ DLUHC is committed to making its website accessible, in accordance with the Publ ### Compliance status -This website is partially compliant with the Web Content Accessibility Guidelines version 2.1 AA standard due to the non-compliances listed below. +This website is partially compliant with the [Web Content Accessibility Guidelines version 2.1](https://www.w3.org/TR/WCAG21/) AA standard due to the non-compliances listed below. ## Non-accessible content @@ -59,3 +59,17 @@ The content listed below is non-accessible for the following reasons. An empty link on the ‘Users’ page within ‘Your Organisation’ will cause problems for some users of assistive technology. This fails WCAG 2.1 success criteria 2.4.4 Link Purpose – in context (Level A) and 3.3.2 Labels or Instructions (Level A). We plan to fix this by December 2022. + +An optional field is not clearly labelled on the ‘Invite user to submit CORE data’ page. This fails WCAG 2.1 success criteria 3.3.2 Labels or Instructions (Level A). + +We plan to fix this by December 2022. + +A skip link for an error message on the ‘Household’s combined income after tax’ page doesn’t work. This fails WCAG 2.1 success criteria 4.1.2 Name, Role, Value (Level A). + +We plan to fix this by December 2022. + +## Preparation of this accessibility statement + +This statement was prepared on 27 July 2022. It was last reviewed on 1 August 2022. + +This website was last tested on 14 March 2022. The test was carried out by the Digital Accessibility Centre (DAC). diff --git a/app/views/form/_checkbox_question.html.erb b/app/views/form/_checkbox_question.html.erb index eb6cd8d40..41bd3cc6d 100644 --- a/app/views/form/_checkbox_question.html.erb +++ b/app/views/form/_checkbox_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_check_boxes_fieldset question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -20,3 +20,5 @@ <% end %> <% end %> <% end %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_date_question.html.erb b/app/views/form/_date_question.html.erb index 753ea5ba1..53abb5878 100644 --- a/app/views/form/_date_question.html.erb +++ b/app/views/form/_date_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_date_field question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -6,3 +6,5 @@ hint: { text: question.hint_text&.html_safe || "For example, 1 9 2022." }, width: 20, **stimulus_html_attributes(question) %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_numeric_output_question.html.erb b/app/views/form/_numeric_output_question.html.erb index fdcfa4148..7f3f73719 100644 --- a/app/views/form/_numeric_output_question.html.erb +++ b/app/views/form/_numeric_output_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %>
+ +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_numeric_question.html.erb b/app/views/form/_numeric_question.html.erb index 1d3d49646..d40067194 100644 --- a/app/views/form/_numeric_question.html.erb +++ b/app/views/form/_numeric_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_number_field question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -10,3 +10,5 @@ prefix_text: question.prefix.to_s, suffix_text: question.suffix_label(@case_log), **stimulus_html_attributes(question) %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_radio_question.html.erb b/app/views/form/_radio_question.html.erb index a6cd165f9..d7bcc0381 100644 --- a/app/views/form/_radio_question.html.erb +++ b/app/views/form/_radio_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_radio_buttons_fieldset question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -34,3 +34,5 @@ <% end %> <% end %> <% end %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_select_question.html.erb b/app/views/form/_select_question.html.erb index ef63153d7..ff4dd5f2e 100644 --- a/app/views/form/_select_question.html.erb +++ b/app/views/form/_select_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <% selected = @case_log.public_send(question.id) || "" %> <% answers = question.displayed_answer_options(@case_log).map { |key, value| OpenStruct.new(id: key, name: value.respond_to?(:service_name) ? value.service_name : nil, resource: value) } %> @@ -16,3 +16,5 @@ <%= answer.id == "" ? "disabled" : "" %>><%= answer.name || answer.resource %> <% end %> <% end %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_text_question.html.erb b/app/views/form/_text_question.html.erb index 4b11bea36..74e7e9b26 100644 --- a/app/views/form/_text_question.html.erb +++ b/app/views/form/_text_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_text_field question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -6,3 +6,5 @@ hint: { text: question.hint_text&.html_safe }, width: question.width || nil, **stimulus_html_attributes(question) %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/_textarea_question.html.erb b/app/views/form/_textarea_question.html.erb index e87cb558b..a9768e4d0 100644 --- a/app/views/form/_textarea_question.html.erb +++ b/app/views/form/_textarea_question.html.erb @@ -1,4 +1,4 @@ -<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %> +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.top_guidance? %> <%= f.govuk_text_area question.id.to_sym, caption: caption(caption_text, page_header, conditional), @@ -6,3 +6,5 @@ hint: { text: question.hint_text&.html_safe }, width: question.width || nil, **stimulus_html_attributes(question) %> + +<%= render partial: "form/guidance/#{question.guidance_partial}" if question.bottom_guidance? %> diff --git a/app/views/form/guidance/_scheme_selection.html.erb b/app/views/form/guidance/_scheme_selection.html.erb new file mode 100644 index 000000000..c48644077 --- /dev/null +++ b/app/views/form/guidance/_scheme_selection.html.erb @@ -0,0 +1,5 @@ +<% if current_user.data_provider? %> +

If you can’t find the supported housing service you’re looking for or not sure which to choose, contact a data coordinator at <%= current_user.organisation.name %>.

+<% elsif current_user.data_coordinator? %> +

or <%= govuk_link_to "create a new supported housing service", new_scheme_path %>

+<% end %> diff --git a/app/views/locations/index.html.erb b/app/views/locations/index.html.erb index 8d7b927b2..04e4c4bf6 100644 --- a/app/views/locations/index.html.erb +++ b/app/views/locations/index.html.erb @@ -13,6 +13,8 @@ <%= render SubNavigationComponent.new(items: scheme_items(request.path, @scheme.id, "Locations")) %> +

Locations

+ <%= render SearchComponent.new(current_user:, search_label: "Search by location name or postcode", value: @searched) %> <%= govuk_section_break(visible: true, size: "m") %> diff --git a/app/views/organisations/index.html.erb b/app/views/organisations/index.html.erb index 967c2d0bf..b81922c5e 100644 --- a/app/views/organisations/index.html.erb +++ b/app/views/organisations/index.html.erb @@ -5,8 +5,6 @@ <%= render partial: "organisations/headings", locals: request.path == "/organisations" ? { main: "Organisations", sub: nil } : { main: @organisation.name, sub: "Organisations" } %> -

Organisations

- <% if current_user.support? %> <%= govuk_button_link_to "Create a new organisation", new_organisation_path, html: { method: :get } %> <% end %> diff --git a/app/views/organisations/logs.html.erb b/app/views/organisations/logs.html.erb index 9d8e978dc..10b686f56 100644 --- a/app/views/organisations/logs.html.erb +++ b/app/views/organisations/logs.html.erb @@ -5,11 +5,12 @@ <%= render partial: "organisations/headings", locals: { main: @organisation.name, sub: nil } %> -<%= render SubNavigationComponent.new( - items: secondary_items(request.path, @organisation.id), -) %> - -

Logs

+<% if current_user.support? %> + <%= render SubNavigationComponent.new( + items: secondary_items(request.path, @organisation.id), + ) %> +

Logs

+<% end %>
diff --git a/app/views/organisations/schemes.html.erb b/app/views/organisations/schemes.html.erb index 4c59601e6..8e9690fe5 100644 --- a/app/views/organisations/schemes.html.erb +++ b/app/views/organisations/schemes.html.erb @@ -3,19 +3,24 @@ <% content_for :title, title %> -<%= render partial: "organisations/headings", locals: current_user.support? ? { main: @organisation.name, sub: nil } : { main: "Schemes", sub: current_user.organisation.name } %> +<%= render partial: "organisations/headings", locals: current_user.support? ? { main: @organisation.name, sub: nil } : { main: "Supported housing schemes", sub: current_user.organisation.name } %> <% if current_user.support? %> <%= render SubNavigationComponent.new( items: secondary_items(request.path, @organisation.id), ) %> +

Supported housing schemes

<% end %> <%= govuk_button_link_to "Create a new supported housing scheme", new_scheme_path, html: { method: :post } %> -

Supported housing schemes

+<%= govuk_details( + classes: "govuk-!-width-two-thirds", + summary_text: "What is a supported housing scheme?", + text: "A supported housing scheme (also known as a ‘supported housing service’) provides shared or self-contained housing for a particular client group, for example younger or vulnerable people. A single scheme can contain multiple units, for example bedrooms in shared houses or a bungalow with 3 bedrooms.", +) %> -<%= render SearchComponent.new(current_user:, search_label: "Search by scheme name, code or postcode", value: @searched) %> +<%= render SearchComponent.new(current_user:, search_label: "Search by scheme name, code, postcode or location name", value: @searched) %>
diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb index 5b82aedc7..3227e7b88 100644 --- a/app/views/organisations/show.html.erb +++ b/app/views/organisations/show.html.erb @@ -8,10 +8,9 @@ <%= render SubNavigationComponent.new( items: secondary_items(request.path, @organisation.id), ) %> +

About this organisation

<% end %> -

About this organisation

-
<%= govuk_summary_list do |summary_list| %> diff --git a/app/views/organisations/users.html.erb b/app/views/organisations/users.html.erb index e8dc383ed..c604a1c9f 100644 --- a/app/views/organisations/users.html.erb +++ b/app/views/organisations/users.html.erb @@ -5,11 +5,12 @@ <%= render partial: "organisations/headings", locals: { main: @organisation.name, sub: nil } %> -<%= render SubNavigationComponent.new( - items: secondary_items(request.path, @organisation.id), -) %> - -

Users

+<% if current_user.support? %> + <%= render SubNavigationComponent.new( + items: secondary_items(request.path, @organisation.id), + ) %> +

Users

+<% end %> <% if current_user.data_coordinator? || current_user.support? %> <%= govuk_button_link_to "Invite user", new_user_path(organisation_id: @organisation.id), html: { method: :get } %> diff --git a/app/views/schemes/check_answers.html.erb b/app/views/schemes/check_answers.html.erb index 561fca9c9..a9a6033c9 100644 --- a/app/views/schemes/check_answers.html.erb +++ b/app/views/schemes/check_answers.html.erb @@ -2,76 +2,76 @@ <%= render partial: "organisations/headings", locals: { main: "Check your changes before creating this scheme", sub: @scheme.service_name } %> <%= form_for(@scheme, as: :scheme, method: :patch) do |f| %> -
- <%= f.govuk_error_summary %> - <%= govuk_tabs(title: "Check your answers before creating this scheme") do |component| %> - <% component.tab(label: "Scheme") do %> -
- <% @scheme.check_details_attributes.each do |attr| %> - <% next if current_user.data_coordinator? && attr[:name] == ("owned by") %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_details_path(@scheme, check_answers: true) } %> - <% end %> - <% if !@scheme.arrangement_type_same? %> - <% @scheme.check_support_services_provider_attributes.each do |attr| %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_support_services_provider_path(@scheme, check_answers: true) } %> - <% end %> - <% end %> - <% @scheme.check_primary_client_attributes.each do |attr| %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_primary_client_group_path(@scheme, check_answers: true) } %> - <% end %> - <% @scheme.check_secondary_client_confirmation_attributes.each do |attr| %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_confirm_secondary_client_group_path(@scheme, check_answers: true) } %> - <% end %> - <% if @scheme.has_other_client_group == "Yes" %> - <% @scheme.check_secondary_client_attributes.each do |attr| %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_secondary_client_group_path(@scheme, check_answers: true) } %> - <% end %> - <% end %> - <% @scheme.check_support_attributes.each do |attr| %> - <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_support_path(@scheme, check_answers: true) } %> - <% end %> -
+ <%= f.govuk_error_summary %> + <%= govuk_tabs(title: "Check your answers before creating this scheme") do |component| %> + <% component.tab(label: "Scheme") do %> +

Scheme

+
+ <% @scheme.check_details_attributes.each do |attr| %> + <% next if current_user.data_coordinator? && attr[:name] == ("owned by") %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_details_path(@scheme, check_answers: true) } %> <% end %> - <% component.tab(label: "Locations") do %> - <%= govuk_table do |table| %> - <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> - <%= @scheme.locations.count %> <%= @scheme.locations.count.eql?(1) ? "location" : "locations" %> - <% end %> - <%= table.head do |head| %> - <%= head.row do |row| %> - <% row.cell(header: true, text: "Code", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Postcode", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Units", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Common unit type", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Available from", html_attributes: { - scope: "col", - }) %> - <% end %> - <% end %> - <% @scheme.locations.each do |location| %> - <%= table.body do |body| %> - <%= body.row do |row| %> - <% row.cell(text: location.id) %> - <% row.cell(text: simple_format(location_cell(location, "/schemes/#{@scheme.id}/locations/#{location.id}/edit"), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> - <% row.cell(text: location.units) %> - <% row.cell(text: simple_format("#{location.type_of_unit}")) %> - <% row.cell(text: location.startdate&.to_formatted_s(:govuk_date)) %> - <% end %> + <% if !@scheme.arrangement_type_same? %> + <% @scheme.check_support_services_provider_attributes.each do |attr| %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_support_services_provider_path(@scheme, check_answers: true) } %> + <% end %> + <% end %> + <% @scheme.check_primary_client_attributes.each do |attr| %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_primary_client_group_path(@scheme, check_answers: true) } %> + <% end %> + <% @scheme.check_secondary_client_confirmation_attributes.each do |attr| %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_confirm_secondary_client_group_path(@scheme, check_answers: true) } %> + <% end %> + <% if @scheme.has_other_client_group == "Yes" %> + <% @scheme.check_secondary_client_attributes.each do |attr| %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_secondary_client_group_path(@scheme, check_answers: true) } %> + <% end %> + <% end %> + <% @scheme.check_support_attributes.each do |attr| %> + <%= render partial: "scheme_summary_list_row", locals: { scheme: @scheme, attribute: attr, change_link: scheme_support_path(@scheme, check_answers: true) } %> + <% end %> +
+ <% end %> + <% component.tab(label: "Locations") do %> +

Locations

+ <%= govuk_table do |table| %> + <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> + <%= @scheme.locations.count %> <%= @scheme.locations.count.eql?(1) ? "location" : "locations" %> + <% end %> + <%= table.head do |head| %> + <%= head.row do |row| %> + <% row.cell(header: true, text: "Code", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Postcode", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Units", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Common unit type", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Available from", html_attributes: { + scope: "col", + }) %> + <% end %> + <% end %> + <% @scheme.locations.each do |location| %> + <%= table.body do |body| %> + <%= body.row do |row| %> + <% row.cell(text: location.id) %> + <% row.cell(text: simple_format(location_cell(location, "/schemes/#{@scheme.id}/locations/#{location.id}/edit"), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> + <% row.cell(text: location.units) %> + <% row.cell(text: simple_format("#{location.type_of_unit}")) %> + <% row.cell(text: location.startdate&.to_formatted_s(:govuk_date)) %> <% end %> - <% end %> <% end %> - <%= govuk_button_link_to "Add a location", new_location_path(id: @scheme.id), secondary: true %> <% end %> <% end %> -
+ <%= govuk_button_link_to "Add a location", new_location_path(id: @scheme.id), secondary: true %> + <% end %> + <% end %> <%= f.hidden_field :page, value: "check-answers" %> <%= f.hidden_field :confirmed, value: "true" %> <% button_label = @scheme.confirmed? ? "Save" : "Create scheme" %> diff --git a/app/views/schemes/index.html.erb b/app/views/schemes/index.html.erb index 190d29d3d..8e787a33d 100644 --- a/app/views/schemes/index.html.erb +++ b/app/views/schemes/index.html.erb @@ -5,11 +5,9 @@ <%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Supported housing schemes", sub: nil } : { main: "Supported housing schemes", sub: current_user.organisation.name } %> -

Supported housing schemes

- <%= govuk_button_link_to "Create a new supported housing scheme", new_scheme_path, html: { method: :post } %> -<%= render SearchComponent.new(current_user:, search_label: "Search by scheme name, code or postcode", value: @searched) %> +<%= render SearchComponent.new(current_user:, search_label: "Search by scheme name, code, postcode or location name", value: @searched) %>
diff --git a/app/views/schemes/show.html.erb b/app/views/schemes/show.html.erb index 2c700fd14..75cb533f7 100644 --- a/app/views/schemes/show.html.erb +++ b/app/views/schemes/show.html.erb @@ -12,15 +12,15 @@ <%= render SubNavigationComponent.new(items: scheme_items(request.path, @scheme.id, "Locations")) %> -
- <%= govuk_summary_list do |summary_list| %> - <% @scheme.display_attributes.each do |attr| %> - <% next if current_user.data_coordinator? && attr[:name] == ("Housing stock owned by") %> - <%= summary_list.row do |row| %> - <% row.key { attr[:name].eql?("Registered under Care Standards Act 2000") ? "Registered under Care Standards Act 2000" : attr[:name].to_s.humanize } %> - <% row.value { details_html(attr) } %> - <% row.action(text: "Change", href: scheme_edit_name_path(scheme_id: @scheme.id)) if attr[:edit] %> - <% end %> +

Scheme

+ +<%= govuk_summary_list do |summary_list| %> + <% @scheme.display_attributes.each do |attr| %> + <% next if current_user.data_coordinator? && attr[:name] == ("Housing stock owned by") %> + <%= summary_list.row do |row| %> + <% row.key { attr[:name].eql?("Registered under Care Standards Act 2000") ? "Registered under Care Standards Act 2000" : attr[:name].to_s.humanize } %> + <% row.value { details_html(attr) } %> + <% row.action(text: "Change", href: scheme_edit_name_path(scheme_id: @scheme.id)) if attr[:edit] %> <% end %> <% end %> -
+<% end %> diff --git a/app/views/users/_user_list.html.erb b/app/views/users/_user_list.html.erb index 7876d77dc..786e3c571 100644 --- a/app/views/users/_user_list.html.erb +++ b/app/views/users/_user_list.html.erb @@ -4,7 +4,7 @@ <%= render(SearchResultCaptionComponent.new(searched:, count: pagy.count, item_label:, total_count:, item: "users", path: request.path)) %> <% if current_user.support? %> <% query = searched.present? ? "?search=#{searched}" : nil %> - <%= govuk_link_to "Download (CSV)", "/users.csv#{query}", type: "text/csv" %> + <%= govuk_link_to "Download (CSV)", "#{request.path}.csv#{query}", type: "text/csv" %> <% end %> <% end %> <%= table.head do |head| %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index da05e2905..b9b9975be 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -3,9 +3,7 @@ <% content_for :title, title %> -<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Users", sub: nil } : { main: "User", sub: current_user.organisation.name } %> - -

Users

+<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Users", sub: nil } : { main: "Users", sub: current_user.organisation.name } %> <% if current_user.data_coordinator? || current_user.support? %> <%= govuk_button_link_to "Invite user", new_user_path, html: { method: :get } %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 14af424b8..14a640708 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -44,36 +44,34 @@ en: scheme: attributes: owning_organisation_id: - invalid: "Enter the existing organisation’s name" + invalid: "Enter the name of the organisation that owns the housing stock" managing_organisation_id: - invalid: "Enter the existing organisation’s name" + invalid: "Enter the name of the organisation that manages the housing stock" service_name: - invalid: "Enter the scheme’s name" + invalid: "Enter the name of the scheme" scheme_type: - invalid: "Select the scheme’s type" + invalid: "Select the type of scheme" registered_under_care_act: invalid: "Select if this scheme is registered under the Care Standards Act 2000" primary_client_group: - invalid: "Select what client group is this scheme intended for" + invalid: "Select what client group this scheme is intended for" secondary_client_group: - invalid: "Select what is the other client group" + invalid: "Select the other client group for this scheme" support_type: - invalid: "Select level of support given" + invalid: "Select the level of support provided by this scheme" intended_stay: - invalid: "Select intended length of stay" + invalid: "Select the intended length of stay" has_other_client_group: invalid: "Select if this scheme provides for another client group" arrangement_type: invalid: "Select who provides the support services used by this scheme" - base: - invalid: "You must answer all the required questions for this scheme" location: attributes: startdate: - invalid: "Enter a date in the correct format, for example 1 9 2022" + invalid: "Enter a date in the correct format, for example 31 1 2022" units: - blank: "Enter total number of units at this location" + blank: "Enter the total number of units at this location" type_of_unit: blank: "Select the most common type of unit at this location" mobility_type: @@ -81,8 +79,8 @@ en: validations: organisation: - name_missing: "Enter the organisation’s name" - provider_type_missing: "Select the organisation’s type" + name_missing: "Enter the name of the organisation" + provider_type_missing: "Select the organisation type" not_answered: "You must answer %{question}" other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided" @@ -90,8 +88,8 @@ en: numeric: valid: "%{field} must be between %{min} and %{max}" date: - invalid_date: "Enter a date in the correct format, for example 1 9 2022" - outside_collection_window: "Date must be within the current collection windows" + invalid_date: "Enter a date in the correct format, for example 31 1 2022" + outside_collection_window: "Enter a date within the current collection windows" postcode: "Enter a postcode in the correct format, for example AA1 1AA" email: taken: "Enter an email address that hasn’t already been used to sign up" @@ -109,20 +107,20 @@ en: property: mrcdate: - before_tenancy_start: "Major repairs date must be before the tenancy start date" + before_tenancy_start: "Enter a major repairs date that is before the tenancy start date" not_first_let: "Major repairs date must not be completed if the tenancy is a first let" - 730_days_before_tenancy_start: "The major repairs completion date should be no more than 730 days before the tenancy start date" + 730_days_before_tenancy_start: "Enter a major repairs completion date that is no more than 730 days before the tenancy start date" void_date: - ten_years_before_tenancy_start: "The void date must be no more than 10 years before the tenancy start date" - before_tenancy_start: "Void date must be before the tenancy start date" + ten_years_before_tenancy_start: "Enter a void date must no more than 10 years before the tenancy start date" + before_tenancy_start: "Enter a void date must that is before the tenancy start date" after_mrcdate: "Void date must be before the major repairs date if provided" offered: - relet_number: "Number of times the property has been re-let must be between 0 and 20" + relet_number: "Enter a number between 0 and 20 for the amount of times the property has been re-let" la: la_invalid_for_org: "%{org_name} does not operate in %{la_name}" - postcode_invalid_for_org: "Postcode must be in an area covered by %{org_name}" + postcode_invalid_for_org: "Enter a postcode in an area covered by %{org_name}" rsnvac: - first_let_not_social: "Reason for vacancy cannot be first let if unit has been previously let as social housing" + first_let_not_social: "Enter a reason for vacancy that is not 'first let' if unit has been previously let as social housing" first_let_social: "Reason for vacancy must be first let if unit has been previously let as social housing" previous_let_social: "Property cannot have a previous let type if being let as social housing for the first time" non_temp_accommodation: "Answer cannot be re-let to tenant who occupied the same property as temporary accommodation as you already told us this accommodation is not temporary" @@ -137,9 +135,9 @@ en: financial: tshortfall: - outstanding_amount_not_required: "You must not answer the outstanding amount question if you don’t have outstanding rent or charges" - more_than_rent: "Answer must be less than the basic rent amount" - must_be_positive: "Answer must be more than £0.01 as you told us there is an outstanding amount" + outstanding_amount_not_required: "You cannot answer the outstanding amount question if you don’t have outstanding rent or charges" + more_than_rent: "Enter a value less less than the basic rent amount" + must_be_positive: "Enter a value over £0.01 as you told us there is an outstanding amount" hbrentshortfall: outstanding_no_benefits: "Answer cannot be ‘yes’ to outstanding amount for basic rent or charges if tenant does not receive housing benefit or Universal Credit or you‘re not sure" benefits: @@ -151,28 +149,28 @@ en: earnings_missing: "Enter how much income the household has in total" negative_currency: "Enter an amount above 0" rent: - less_than_shortfall: "Answer must be more than the shortfall in basic rent" + less_than_shortfall: "Enter an amount that is more than the shortfall in basic rent" scharge: private_registered_provider: - general_needs: "Service charge must be between £0 and £55 per week if the landlord is a private registered provider and it is a general needs letting" - supported_housing: "Service charge must be between £0 and £280 per week if the landlord is a private registered provider and it is a supported housing letting" + general_needs: "Enter a value for the service charge between £0 and £55 per week if the landlord is a private registered provider and it is a general needs letting" + supported_housing: "Enter a value for the service charge between £0 and £280 per week if the landlord is a private registered provider and it is a supported housing letting" local_authority: - general_needs: "Service charge must be between £0 and £45 per week if the landlord is a local authority and it is a general needs letting" - supported_housing: "Service charge must be between £0 and £165 per week if the landlord is a local authority and it is a supported housing letting" + general_needs: "Enter a value for the service charge between £0 and £45 per week if the landlord is a local authority and it is a general needs letting" + supported_housing: "Enter a value for the service charge between £0 and £165 per week if the landlord is a local authority and it is a supported housing letting" pscharge: private_registered_provider: - general_needs: "Personal service charge must be between £0 and £30 per week if the landlord is a private registered provider and it is a general needs letting" - supported_housing: "Personal service charge must be between £0 and £200 per week if the landlord is a private registered provider and it is a supported housing letting" + general_needs: "Enter a value for the personal service charge between £0 and £30 per week if the landlord is a private registered provider and it is a general needs letting" + supported_housing: "Enter a value for the personal service charge between £0 and £200 per week if the landlord is a private registered provider and it is a supported housing letting" local_authority: - general_needs: "Personal service charge must be between £0 and £35 per week if the landlord is a local authority and it is a general needs letting" - supported_housing: "Personal service charge must be between £0 and £75 per week if the landlord is a local authority and it is a supported housing letting" + general_needs: "Enter a value for the personal service charge between £0 and £35 per week if the landlord is a local authority and it is a general needs letting" + supported_housing: "Enter a value for the personal service charge between £0 and £75 per week if the landlord is a local authority and it is a supported housing letting" supcharg: private_registered_provider: - general_needs: "Support charge must be between £0 and £40 per week if the landlord is a private registered provider and it is a general needs letting" - supported_housing: "Support charge must be between £0 and £465 per week if the landlord is a private registered provider and it is a supported housing letting" + general_needs: "Enter a value for the support charge between £0 and £40 per week if the landlord is a private registered provider and it is a general needs letting" + supported_housing: "Enter a value for the support charge between £0 and £465 per week if the landlord is a private registered provider and it is a supported housing letting" local_authority: - general_needs: "Support charge must be between £0 and £60 per week if the landlord is a local authority and it is a general needs letting" - supported_housing: "Support charge must be between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting" + general_needs: "Enter a value for the support charge between £0 and £60 per week if the landlord is a local authority and it is a general needs letting" + supported_housing: "Enter a value for the support charge between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting" brent: not_in_range: "Basic rent is outside of the expected range based on the lettings type, local authority and number of bedrooms" la: @@ -188,7 +186,7 @@ en: charges: complete_1_of_3: "Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’" tcharge: - under_10: "Total charge must be at least £10 per week" + under_10: "Enter a total charge that is at least £10 per week" rent_period: invalid_for_org: "%{org_name} does not charge rent %{rent_period}" carehome: @@ -198,18 +196,18 @@ en: reasonpref: not_homeless: "Answer cannot be ‘homeless or about to lose their home’ as you already told us the tenant was not homeless immediately prior to this letting" reasonable_preference_reason: - reason_required: "If reasonable preference is ‘yes’, a reason must be given" - reason_not_required: "If reasonable preference is ‘no’, no reason should be given" + reason_required: "Enter a reason if you've answered 'yes' to reasonable preference" + reason_not_required: "Do not enter a reason if you've answered 'no' to reasonable preference" underoccupation_benefitcap: dont_know_required: "Answer must be ‘don’t know’ as you told us you don’t know the tenant’s main reason for leaving" reservist: - injury_required: "You must answer whether the person was seriously injured or ill as a result of serving in the UK armed forces" + injury_required: "Tell us whether the person was seriously injured or ill as a result of serving in the UK armed forces" injury_not_required: "You cannot answer this question as you told us the person has not served in the UK armed forces or prefers not to say" leftreg: - question_required: "You must answer whether the person is still serving in the UK armed forces as you told us they’re a current or former regular" + question_required: "Tell us whether the person is still serving in the UK armed forces as you told us they’re a current or former regular" question_not_required: "You cannot answer whether the person is still serving in the UK armed forces as you told us they’re not a current or former regular" preg_occ: - no_female: "You must answer ‘no’ as there are no female tenants aged 11-65 in the household" + no_female: "Enter ‘no’ as there are no female tenants aged 11-65 in the household" age: retired_male: "Male tenant who is retired must be 65 or over" retired_female: "Female tenant who is retired must be 60 or over" @@ -325,7 +323,7 @@ en: name: "Location name (optional)" units: "Total number of units at this location" type_of_unit: "What is the most common type of unit at this location?" - startdate: "When did the first property in this location become available under this scheme?" + startdate: "When did the first property in this location become available under this scheme? (optional)" add_another_location: "Do you want to add another location?" mobility_type: "What are the mobility standards for the majority of units in this location?" descriptions: diff --git a/spec/components/log_summary_component_spec.rb b/spec/components/log_summary_component_spec.rb new file mode 100644 index 000000000..61bfc5280 --- /dev/null +++ b/spec/components/log_summary_component_spec.rb @@ -0,0 +1,34 @@ +require "rails_helper" + +RSpec.describe LogSummaryComponent, type: :component do + let(:support_user) { FactoryBot.create(:user, :support) } + let(:coordinator_user) { FactoryBot.create(:user) } + let(:propcode) { "P3647" } + let(:tenancycode) { "T62863" } + let(:log) { FactoryBot.create(:case_log, needstype: 1, startdate: Time.utc(2022, 1, 1), tenancycode:, propcode:) } + + context "when rendering log for a support user" do + it "show the log summary with organisational relationships" do + result = render_inline(described_class.new(current_user: support_user, log:)) + + expect(result).to have_link(log.id.to_s) + expect(result).to have_text(log.tenancycode) + expect(result).to have_text(log.propcode) + expect(result).to have_text("General needs") + expect(result).to have_text("Tenancy starts 1 January 2022") + expect(result).to have_text("Created 8 February 2022") + expect(result).to have_text("by Danny Rojas") + expect(result).to have_content("Owned by\n DLUHC") + expect(result).to have_content("Managed by\n DLUHC") + end + end + + context "when rendering log for a data coordinator user" do + it "show the log summary" do + result = render_inline(described_class.new(current_user: coordinator_user, log:)) + + expect(result).not_to have_content("Owned by\n DLUHC") + expect(result).not_to have_content("Managed by\n DLUHC") + end + end +end diff --git a/spec/components/search_result_caption_component_spec.rb b/spec/components/search_result_caption_component_spec.rb index a317e562e..ed4934633 100644 --- a/spec/components/search_result_caption_component_spec.rb +++ b/spec/components/search_result_caption_component_spec.rb @@ -10,7 +10,7 @@ RSpec.describe SearchResultCaptionComponent, type: :component do it "renders table caption including the search results and total" do result = render_inline(described_class.new(searched:, count:, item_label:, total_count:, item:, path:)) - expect(result.to_html).to eq(" \n #{count} #{item_label} found matching ‘#{searched}’ of #{total_count} total #{item}. Clear search\n\n") + expect(result.to_html).to eq("\n #{count} #{item_label} found matching ‘#{searched}’ of #{total_count} total #{item}. Clear search\n\n") end context "when no search results are found" do @@ -19,7 +19,7 @@ RSpec.describe SearchResultCaptionComponent, type: :component do it "renders table caption with total count only" do result = render_inline(described_class.new(searched:, count:, item_label:, total_count:, item:, path:)) - expect(result.to_html).to eq(" \n #{count} total #{item}.\n\n") + expect(result.to_html).to eq("\n #{count} total #{item}\n\n") end end end diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index bd088f70b..9792dfc42 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -34,7 +34,7 @@ RSpec.describe "Schemes scheme Features" do context "when I search for a specific scheme" do it "there is a search bar with a message and search button for schemes" do expect(page).to have_field("search") - expect(page).to have_content("Search by scheme name, code or postcode") + expect(page).to have_content("Search by scheme name, code, postcode or location name") expect(page).to have_button("Search") end @@ -109,7 +109,7 @@ RSpec.describe "Schemes scheme Features" do it "displays a search bar" do expect(page).to have_field("search") - expect(page).to have_content("Search by scheme name, code or postcode") + expect(page).to have_content("Search by scheme name, code, postcode or location name") expect(page).to have_button("Search") end diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb index 8ffa37ab6..b96b2737e 100644 --- a/spec/models/location_spec.rb +++ b/spec/models/location_spec.rb @@ -32,7 +32,7 @@ RSpec.describe Location, type: :model do it "does add an error when the postcode is invalid" do location.postcode = "invalid" expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Postcode Enter a postcode in the correct format, for example AA1 1AA") + .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Postcode #{I18n.t('validations.postcode')}") end end @@ -42,7 +42,7 @@ RSpec.describe Location, type: :model do it "does add an error when the postcode is invalid" do location.units = nil expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Units Enter total number of units at this location") + .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Units #{I18n.t('activerecord.errors.models.location.attributes.units.blank')}") end end @@ -52,7 +52,7 @@ RSpec.describe Location, type: :model do it "does add an error when the postcode is invalid" do location.type_of_unit = nil expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Type of unit Select the most common type of unit at this location") + .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Type of unit #{I18n.t('activerecord.errors.models.location.attributes.type_of_unit.blank')}") end end diff --git a/spec/models/scheme_spec.rb b/spec/models/scheme_spec.rb index d81d93bd6..dddf8edb4 100644 --- a/spec/models/scheme_spec.rb +++ b/spec/models/scheme_spec.rb @@ -45,6 +45,17 @@ RSpec.describe Scheme, type: :model do end end + context "when searching by location name" do + it "returns case insensitive matching records" do + expect(described_class.search_by_location_name(location.name.upcase).count).to eq(1) + expect(described_class.search_by_location_name(location.name.downcase).count).to eq(1) + expect(described_class.search_by_location_name(location.name.downcase).first.locations.first.name).to eq(location.name) + expect(described_class.search_by_location_name(location_2.name.upcase).count).to eq(1) + expect(described_class.search_by_location_name(location_2.name.downcase).count).to eq(1) + expect(described_class.search_by_location_name(location_2.name.downcase).first.locations.first.name).to eq(location_2.name) + end + end + context "when searching by all searchable fields" do before do location_2.update!(postcode: location_2.postcode.gsub(scheme_1.id.to_s, "0")) @@ -59,6 +70,9 @@ RSpec.describe Scheme, type: :model do expect(described_class.search_by(location.postcode.upcase).count).to eq(1) expect(described_class.search_by(location.postcode.downcase).count).to eq(1) expect(described_class.search_by(location.postcode.downcase).first.locations.first.postcode).to eq(location.postcode) + expect(described_class.search_by(location.name.upcase).count).to eq(1) + expect(described_class.search_by(location.name.downcase).count).to eq(1) + expect(described_class.search_by(location.name.downcase).first.locations.first.name).to eq(location.name) end end end diff --git a/spec/requests/case_logs_controller_spec.rb b/spec/requests/case_logs_controller_spec.rb index b509e723f..db60b2a65 100644 --- a/spec/requests/case_logs_controller_spec.rb +++ b/spec/requests/case_logs_controller_spec.rb @@ -172,10 +172,10 @@ RSpec.describe CaseLogsController, type: :request do sign_in user end - it "does have organisation columns" do + it "does have organisation values" do get "/logs", headers: headers, params: {} - expect(page).to have_content("Owning organisation") - expect(page).to have_content("Managing organisation") + expect(page).to have_content("Owned by") + expect(page).to have_content("Managed by") end it "shows case logs for all organisations" do @@ -449,7 +449,7 @@ RSpec.describe CaseLogsController, type: :request do end it "shows a table of logs" do - expect(CGI.unescape_html(response.body)).to match(//) + expect(CGI.unescape_html(response.body)).to match(/
/) expect(CGI.unescape_html(response.body)).to match(/logs/) end diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb index e4b1f88f0..6332415b1 100644 --- a/spec/requests/locations_controller_spec.rb +++ b/spec/requests/locations_controller_spec.rb @@ -885,7 +885,8 @@ RSpec.describe LocationsController, type: :request do end it "has search in the title" do - expect(page).to have_title("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expected_title = CGI.escapeHTML("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) end end end diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index 357dbb4ba..0498209f9 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -116,11 +116,6 @@ RSpec.describe OrganisationsController, type: :request do expect(page).to have_field("search", type: "search") end - it "has hidden accessibility field with description" do - expected_field = "

Supported housing schemes

" - expect(CGI.unescape_html(response.body)).to include(expected_field) - end - it "shows only schemes belonging to the same organisation" do expect(page).to have_content(same_org_scheme.id_to_display) schemes.each do |scheme| @@ -897,7 +892,7 @@ RSpec.describe OrganisationsController, type: :request do end it "shows the total organisations count" do - expect(CGI.unescape_html(response.body)).to match("#{total_organisations_count} total organisations.") + expect(CGI.unescape_html(response.body)).to match("#{total_organisations_count} total organisations") end it "has pagination links" do @@ -1025,4 +1020,65 @@ RSpec.describe OrganisationsController, type: :request do end end end + + context "when the user is a support user" do + let(:user) { FactoryBot.create(:user, :support) } + + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + end + + context "when they view the logs tab" do + before do + get "/organisations/#{organisation.id}/logs" + end + + it "has a CSV download button with the correct path" do + expect(page).to have_link("Download (CSV)", href: "/organisations/#{organisation.id}/logs.csv") + end + + context "when you download the CSV" do + let(:headers) { { "Accept" => "text/csv" } } + let(:other_organisation) { FactoryBot.create(:organisation) } + + before do + FactoryBot.create_list(:case_log, 3, owning_organisation: organisation) + FactoryBot.create_list(:case_log, 2, owning_organisation: other_organisation) + end + + it "only includes logs from that organisation" do + get "/organisations/#{organisation.id}/logs", headers:, params: {} + csv = CSV.parse(response.body) + expect(csv.count).to eq(4) + end + end + end + + context "when they view the users tab" do + before do + get "/organisations/#{organisation.id}/users" + end + + it "has a CSV download button with the correct path" do + expect(page).to have_link("Download (CSV)", href: "/organisations/#{organisation.id}/users.csv") + end + + context "when you download the CSV" do + let(:headers) { { "Accept" => "text/csv" } } + let(:other_organisation) { FactoryBot.create(:organisation) } + + before do + FactoryBot.create_list(:user, 3, organisation:) + FactoryBot.create_list(:user, 2, organisation: other_organisation) + end + + it "only includes users from that organisation" do + get "/organisations/#{other_organisation.id}/users", headers:, params: {} + csv = CSV.parse(response.body) + expect(csv.count).to eq(3) + end + end + end + end end diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 8549d79f0..47ba637e3 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -90,12 +90,7 @@ RSpec.describe SchemesController, type: :request do end it "shows the total organisations count" do - expect(CGI.unescape_html(response.body)).to match("#{schemes.count} total schemes.") - end - - it "has hidden accebility field with description" do - expected_field = "

Supported housing schemes

" - expect(CGI.unescape_html(response.body)).to include(expected_field) + expect(CGI.unescape_html(response.body)).to match("#{schemes.count} total schemes") end context "when params scheme_id is present" do @@ -118,7 +113,7 @@ RSpec.describe SchemesController, type: :request do end it "shows the total schemes count" do - expect(CGI.unescape_html(response.body)).to match("#{total_schemes_count} total schemes.") + expect(CGI.unescape_html(response.body)).to match("#{total_schemes_count} total schemes") end it "shows which schemes are being shown on the current page" do @@ -143,7 +138,7 @@ RSpec.describe SchemesController, type: :request do end it "shows the total schemes count" do - expect(CGI.unescape_html(response.body)).to match("#{total_schemes_count} total schemes.") + expect(CGI.unescape_html(response.body)).to match("#{total_schemes_count} total schemes") end it "has pagination links" do @@ -591,7 +586,7 @@ RSpec.describe SchemesController, type: :request do it "does not allow the scheme to be confirmed" do expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("activerecord.errors.models.scheme.attributes.base.invalid")) + expect(page).to have_content(I18n.t("activerecord.errors.models.scheme.attributes.managing_organisation_id.invalid")) end end