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.rb b/app/models/form.rb index 57b529f10..b493c25c2 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -79,7 +79,7 @@ class Form when :in_progress "#{next_subsection.id}/check_answers".dasherize when :not_started - first_question_in_subsection = next_subsection.pages.first.id + first_question_in_subsection = next_subsection.pages.find { |page| page.routed_to?(case_log, nil) }.id first_question_in_subsection.to_s.dasherize else "error" 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 5ac48b310..5052b171c 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 ?", "%#{postcode.delete(' ')}%") } - 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/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 59010b6b3..1b5694feb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -44,35 +44,33 @@ 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: @@ -94,8 +92,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" @@ -103,8 +101,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" @@ -122,20 +120,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" @@ -150,9 +148,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: @@ -164,28 +162,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: @@ -201,7 +199,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: @@ -211,18 +209,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" @@ -338,7 +336,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 2cece714f..b76ecb891 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/form_spec.rb b/spec/models/form_spec.rb index 503900ab0..291343cd9 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -149,9 +149,9 @@ RSpec.describe Form, type: :model do expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("household-needs/check-answers") end - it "returns the first page of the next incomplete subsection (skipping completed subsections)" do + it "returns the first page of the next incomplete subsection (skipping completed subsections, and pages that are not routed to)" do answer_household_needs(case_log) - expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("accessible-select-too") + expect(form.next_incomplete_section_redirect_path(subsection, case_log)).to eq("property-postcode") end it "returns the declaration section for a completed case log" do diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb index 9cebd09ef..764a780d6 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 eef4744d4..30007fc4d 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 f3e118ab1..ce1abfe1b 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