diff --git a/app/controllers/publish/courses/about_this_course_controller.rb b/app/controllers/publish/courses/about_this_course_controller.rb new file mode 100644 index 0000000000..8615a24d05 --- /dev/null +++ b/app/controllers/publish/courses/about_this_course_controller.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Publish + module Courses + class AboutThisCourseController < PublishController + before_action :authorise_with_pundit + + def edit + @about_this_course_form = CourseAboutThisCourseForm.new(course_enrichment) + + @about_this_course_form.valid? if show_errors_on_publish? + end + + def update + @about_this_course_form = CourseAboutThisCourseForm.new(course_enrichment, params: about_params) + + if @about_this_course_form.save! + course_updated_message I18n.t('publish.providers.about_course.edit.about_this_course') + + redirect_to redirect_path + else + render :edit + end + end + + private + + def authorise_with_pundit + authorize provider + end + + def about_params + params.require(:publish_course_about_this_course_form).permit(*CourseAboutThisCourseForm::FIELDS) + end + + def course + @course ||= CourseDecorator.new(provider.courses.find_by!(course_code: params[:code])) + end + + def course_enrichment + @course_enrichment ||= course.enrichments.find_or_initialize_draft + end + + def redirect_path + publish_provider_recruitment_cycle_course_path( + provider.provider_code, + recruitment_cycle.year, + course.course_code + ) + end + end + end +end diff --git a/app/forms/publish/course_about_this_course_form.rb b/app/forms/publish/course_about_this_course_form.rb new file mode 100644 index 0000000000..8e3cfdbf17 --- /dev/null +++ b/app/forms/publish/course_about_this_course_form.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Publish + class CourseAboutThisCourseForm < BaseProviderForm + alias course_enrichment model + + FIELDS = %i[about_course].freeze + + attr_accessor(*FIELDS) + + delegate :recruitment_cycle_year, :provider_code, :name, to: :course + + validates :about_course, presence: true + validates :about_course, words_count: { maximum: 400, message: :too_long } + + def save! + if valid? + assign_attributes_to_model + course_enrichment.status = :draft if course_enrichment.rolled_over? + course_enrichment.save! + else + false + end + end + + private + + def compute_fields + course_enrichment.attributes.symbolize_keys.slice(*FIELDS).merge(new_attributes) + end + end +end diff --git a/app/forms/publish/course_information_form.rb b/app/forms/publish/course_information_form.rb index 9be6136090..5726b98020 100644 --- a/app/forms/publish/course_information_form.rb +++ b/app/forms/publish/course_information_form.rb @@ -5,7 +5,6 @@ class CourseInformationForm < BaseProviderForm alias course_enrichment model FIELDS = %i[ - about_course interview_process how_school_placements_work ].freeze @@ -14,9 +13,6 @@ class CourseInformationForm < BaseProviderForm delegate :recruitment_cycle_year, :provider_code, :name, to: :course - validates :about_course, presence: true - validates :about_course, words_count: { maximum: 400, message: :too_long } - validates :interview_process, words_count: { maximum: 250, message: :too_long } validates :how_school_placements_work, presence: true diff --git a/app/services/courses/copy.rb b/app/services/courses/copy.rb index 9c0f98551c..3d41edc927 100644 --- a/app/services/courses/copy.rb +++ b/app/services/courses/copy.rb @@ -16,7 +16,6 @@ class Copy ].freeze ABOUT_FIELDS = [ - ['About the course', 'about_course'], ['Interview process', 'interview_process'], ['How school placements work', 'how_school_placements_work'] ].freeze diff --git a/app/views/publish/courses/_description_content.html.erb b/app/views/publish/courses/_description_content.html.erb index e956647b3b..f6fc2e2cbf 100644 --- a/app/views/publish/courses/_description_content.html.erb +++ b/app/views/publish/courses/_description_content.html.erb @@ -7,7 +7,7 @@ "About this course", value_provided?(course.about_course), %w[about_course], - action_path: course.is_withdrawn? ? nil : about_publish_provider_recruitment_cycle_course_path(@provider.provider_code, course.recruitment_cycle_year, course.course_code), + action_path: course.is_withdrawn? ? nil : about_this_course_publish_provider_recruitment_cycle_course_path(@provider.provider_code, course.recruitment_cycle_year, course.course_code), action_visually_hidden_text: "details about this course" ) %> @@ -17,7 +17,7 @@ "Interview process", value_provided?(course.interview_process), %w[interview_process], - action_path: course.is_withdrawn? ? nil : "#{about_publish_provider_recruitment_cycle_course_path(@provider.provider_code, course.recruitment_cycle_year, course.course_code)}#interview-process", + action_path: course.is_withdrawn? ? nil : about_publish_provider_recruitment_cycle_course_path(@provider.provider_code, course.recruitment_cycle_year, course.course_code), action_visually_hidden_text: "details about the interview process" ) %> diff --git a/app/views/publish/courses/about_this_course/edit.html.erb b/app/views/publish/courses/about_this_course/edit.html.erb new file mode 100644 index 0000000000..6f5dc6a127 --- /dev/null +++ b/app/views/publish/courses/about_this_course/edit.html.erb @@ -0,0 +1,79 @@ +<% content_for :page_title, title_with_error_prefix( + t("publish.providers.about_course.edit.page_title", course_name_and_code: @course.name_and_code), + @about_this_course_form.errors.any? +) %> + +<% if params[:copy_from].present? %> + <%= render partial: "publish/courses/copy_content_warning", locals: { copied_fields: @copied_fields } %> +<% end %> + +
<%= t("publish.providers.about_course.edit.description") %>
+ +<%= t("publish.providers.about_course.edit.candidates_say") %>
+ +<%= t("publish.providers.about_course.edit.remember_to") %>
+ ++ <%= govuk_link_to t("publish.providers.about_course.edit.view_examples"), course_summary_examples_path %> +
+ + <%= f.govuk_text_area(:about_course, + value: @copied_fields_values&.dig("about_course") || @about_this_course_form.about_course, + label: { text: t("publish.providers.about_course.edit.about_this_course"), size: "s" }, + max_words: 400, + rows: 20) %> + <%= f.govuk_submit t("publish.providers.about_course.edit.submit_button") %> + <% end %> ++ <%= govuk_link_to(t("cancel"), publish_provider_recruitment_cycle_course_path(@provider.provider_code, + @provider.recruitment_cycle.year, + @course.course_code)) %> +
diff --git a/app/views/publish/courses/course_information/edit.html.erb b/app/views/publish/courses/course_information/edit.html.erb index 6462b195f0..52d93d3bca 100644 --- a/app/views/publish/courses/course_information/edit.html.erb +++ b/app/views/publish/courses/course_information/edit.html.erb @@ -28,36 +28,6 @@ <%= page_title %> -The course summary appears at the top of the page on Find, so it's important that candidates can quickly learn why this course is different from another.
- -Tell candidates:
- -Remember to:
- -- <%= govuk_link_to "View more guidance and course summary examples", course_summary_examples_path %> -
- - <%= f.govuk_text_area(:about_course, - value: @copied_fields_values&.dig("about_course") || @course.about_course, - label: { text: "About this course", size: "s" }, - max_words: 400, - rows: 20) %> - -diff --git a/config/locales/en.yml b/config/locales/en.yml index 32ffe1f955..39deda3f15 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -315,6 +315,26 @@ en: course_fees: edit: course_fees: Course fees + about_course: + edit: + about_this_course: About this course + page_title: About this course - %{course_name_and_code} + submit_button: Update about this course + description: > + The course summary appears at the top of the page on Find. Use it to show how this course is different from + others, this helps candidates understand whether it is right for them. + candidates_say: "Candidates say the most important information is:" + candidate_say_li_1: how and where they'll spend their time + candidate_say_li_2: how the course is structured, for example which specific modules or areas are taught + candidate_say_li_3: how they'll be supported - for example, tutors and mentoring + candidate_say_li_4: the qualification and experience they will have at the end of the course. + remember_to: "Remember to:" + remember_to_li_1: keep it brief and to the point, people struggle with long blocks of writing online + remember_to_li_2: use bullet points, headings and paragraphs to make your writing easy to read + remember_to_li_3: spell out acronyms the first time you use them, for example, ITT, NQT, SCITT + remember_to_li_4: > + link to your organisation's website for people who want more detail about who you are and what you do. + view_examples: View more guidance and course summary examples study_mode: form: select_all_that_apply: Select all that apply @@ -564,7 +584,7 @@ en: less_than_or_equal_to: "must be less than or equal to £100,000" not_an_integer: "must not include pence, like 1000 or 1500" about_course: - blank: "^Enter details about this course" + blank: Enter information about this course how_school_placements_work: blank: "^Enter details about school placements" required_qualifications: @@ -802,11 +822,13 @@ en: invalid: "Enter a real postcode" urn: format: "URN must be 5 or 6 numbers" - publish/course_information_form: + publish/course_about_this_course_form: attributes: about_course: - blank: "Enter details about this course" - too_long: "Reduce the word count for about course" + blank: Enter information about this course + too_long: Reduce the word count for about course + publish/course_information_form: + attributes: interview_process: too_long: "Reduce the word count for interview process" how_school_placements_work: diff --git a/config/routes/publish.rb b/config/routes/publish.rb index 2badae725e..e2151cdb75 100644 --- a/config/routes/publish.rb +++ b/config/routes/publish.rb @@ -159,6 +159,8 @@ get '/age_range', on: :member, to: 'courses/age_range#edit' put '/age_range', on: :member, to: 'courses/age_range#update' + get '/about_this_course', on: :member, to: 'courses/about_this_course#edit' + patch '/about_this_course', on: :member, to: 'courses/about_this_course#update' get '/about', on: :member, to: 'courses/course_information#edit' patch '/about', on: :member, to: 'courses/course_information#update' get '/requirements', on: :member, to: 'courses/requirements#edit' diff --git a/spec/features/publish/courses/editing_course_about_this_course_spec.rb b/spec/features/publish/courses/editing_course_about_this_course_spec.rb new file mode 100644 index 0000000000..dc3d53a8fe --- /dev/null +++ b/spec/features/publish/courses/editing_course_about_this_course_spec.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'rails_helper' + +feature 'Editing about this course section' do + scenario 'adding valid data' do + given_i_am_authenticated_as_a_provider_user + and_there_is_a_course_i_want_to_edit + when_i_visit_the_about_course_edit_page + and_i_enter_information_into_the_about_course_field + and_i_submit_the_form + then_about_course_data_has_changed + + when_i_visit_the_about_course_edit_page + then_i_see_the_new_about_course_information + end + + scenario 'navigating to course summary examples' do + given_i_am_authenticated_as_a_provider_user + and_there_is_a_course_i_want_to_edit + when_i_visit_the_about_course_edit_page + and_i_click_the_link_to_view_examples + then_i_am_redirected_to_the_expected_page + end + + scenario 'entering invalid data' do + given_i_am_authenticated_as_a_provider_user + and_there_is_a_course_i_want_to_edit + when_i_visit_the_about_course_edit_page + and_i_delete_information_in_the_about_course_field + and_i_submit_the_form + then_i_see_an_error_message + end + + private + + def given_i_am_authenticated_as_a_provider_user + given_i_am_authenticated(user: create(:user, :with_provider)) + end + + def and_there_is_a_course_i_want_to_edit + given_a_course_exists(enrichments: [build(:course_enrichment, :published)]) + end + + def when_i_visit_the_about_course_edit_page + visit about_this_course_publish_provider_recruitment_cycle_course_path( + provider.provider_code, + course.recruitment_cycle_year, + course.course_code + ) + end + + def and_i_click_the_link_to_view_examples + click_on 'View more guidance and course summary examples' + end + + def then_i_am_redirected_to_the_expected_page + expect(page).to have_content 'Course summary examples' + expect(page).to have_current_path course_summary_examples_path, ignore_query: true + end + + def and_i_submit_the_form + click_on 'Update about this course' + end + + def then_i_see_the_new_about_course_information + expect(find_field('About this course').value).to eq 'Here is very useful information about this course' + end + + def then_about_course_data_has_changed + enrichment = course.reload.enrichments.find_or_initialize_draft + + expect(enrichment.about_course).to eq('Here is very useful information about this course') + expect(page).to have_content 'Here is very useful information about this course' + end + + def then_i_see_an_error_message + expect(page).to have_content('Enter information about this course').twice + end + + def and_i_delete_information_in_the_about_course_field + fill_in 'About this course', with: '' + end + + def and_i_enter_information_into_the_about_course_field + fill_in 'About this course', with: 'Here is very useful information about this course' + end + + def provider + @provider ||= @current_user.providers.first + end +end diff --git a/spec/features/publish/courses/editing_course_information_spec.rb b/spec/features/publish/courses/editing_course_information_spec.rb index d9c0b49df4..0bec15adc2 100644 --- a/spec/features/publish/courses/editing_course_information_spec.rb +++ b/spec/features/publish/courses/editing_course_information_spec.rb @@ -31,14 +31,12 @@ [ 'Your changes are not yet saved', - 'About the course', 'Interview process', 'How school placements work' ].each do |name| expect(publish_course_information_edit_page.copy_content_warning).to have_content(name) end - expect(publish_course_information_edit_page.about_course.value).to eq(course2_enrichment.about_course) expect(publish_course_information_edit_page.interview_process.value).to eq(course2_enrichment.interview_process) expect(publish_course_information_edit_page.school_placements.value).to eq(course2_enrichment.how_school_placements_work) end @@ -51,21 +49,15 @@ [ 'Your changes are not yet saved', - 'About the course' + 'How school placements work' ].each do |name| expect(publish_course_information_edit_page.copy_content_warning).to have_content(name) end - [ - 'Interview process', - 'How school placements work' - ].each do |name| - expect(publish_course_information_edit_page.copy_content_warning).to have_no_content(name) - end + expect(publish_course_information_edit_page.copy_content_warning).to have_no_content('Interview process') - expect(publish_course_information_edit_page.about_course.value).to eq(course3_enrichment.about_course) expect(publish_course_information_edit_page.interview_process.value).to eq(course2_enrichment.interview_process) - expect(publish_course_information_edit_page.school_placements.value).to eq(course2_enrichment.how_school_placements_work) + expect(publish_course_information_edit_page.school_placements.value).to eq(course3_enrichment.how_school_placements_work) end end @@ -93,17 +85,15 @@ def when_i_visit_the_publish_course_information_edit_page end def and_i_set_information_about_the_course - @about_course = 'This is a new description' @interview_process = 'This is a new interview process' @school_placements = 'This is a new school placements' - publish_course_information_edit_page.about_course.set(@about_course) publish_course_information_edit_page.interview_process.set(@interview_process) publish_course_information_edit_page.school_placements.set(@school_placements) end def and_i_submit_with_invalid_data - publish_course_information_edit_page.about_course.set(nil) + publish_course_information_edit_page.school_placements.set(nil) and_i_submit end @@ -118,14 +108,13 @@ def then_i_should_see_a_success_message def and_the_course_information_is_updated enrichment = course.reload.enrichments.find_or_initialize_draft - expect(enrichment.about_course).to eq(@about_course) expect(enrichment.interview_process).to eq(@interview_process) expect(enrichment.how_school_placements_work).to eq(@school_placements) end def then_i_should_see_an_error_message expect(publish_course_information_edit_page.error_messages).to include( - I18n.t('activemodel.errors.models.publish/course_information_form.attributes.about_course.blank') + 'Enter details about school placements' ) end diff --git a/spec/support/page_objects/publish/course_information_edit.rb b/spec/support/page_objects/publish/course_information_edit.rb index e78181c0f0..91d734f5d3 100644 --- a/spec/support/page_objects/publish/course_information_edit.rb +++ b/spec/support/page_objects/publish/course_information_edit.rb @@ -11,7 +11,6 @@ class CourseInformationEdit < PageObjects::Base sections :errors, Sections::ErrorLink, '.govuk-error-summary__list li>a' element :copy_content_warning, '[data-qa="copy-course-warning"]' - element :about_course, '#publish-course-information-form-about-course-field' element :interview_process, '#publish-course-information-form-interview-process-field' element :school_placements, '#publish-course-information-form-how-school-placements-work-field' element :use_content, '[data-qa="course__use_content"]' diff --git a/spec/support/shared_contexts/copy_courses.rb b/spec/support/shared_contexts/copy_courses.rb index a2ac101a7e..ebbbcbb302 100644 --- a/spec/support/shared_contexts/copy_courses.rb +++ b/spec/support/shared_contexts/copy_courses.rb @@ -21,15 +21,13 @@ let(:course2_enrichment) do build(:course_enrichment, - about_course: 'Course 2 - About course', interview_process: 'Course 2 - Interview process', how_school_placements_work: 'Course 2 - How teaching placements work') end let(:course3_enrichment) do build(:course_enrichment, - about_course: 'Course 3 - About course', interview_process: nil, - how_school_placements_work: '') + how_school_placements_work: 'Course 3 - this is how placements work here') end end