diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7f8b1f5..3c83335 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,7 @@ +# frozen_string_literal: true + class ApplicationController < ActionController::Base + protect_from_forgery with: :exception # Look for template overrides before rendering @@ -16,11 +19,15 @@ private + def current_org + current_user.org + end + def user_not_authorized if user_signed_in? - redirect_to plans_url, alert: _('You are not authorized to perform this action.') + redirect_to plans_url, alert: _("You are not authorized to perform this action.") else - redirect_to root_url, alert: _('You need to sign in or sign up before continuing.') + redirect_to root_url, alert: _("You need to sign in or sign up before continuing.") end end @@ -30,7 +37,8 @@ end def store_location - # store last url - this is needed for post-login redirect to whatever the user last visited. + # store last url - this is needed for post-login redirect to whatever the user last + # visited. unless ["/users/sign_in", "/users/sign_up", "/users/password", @@ -43,7 +51,9 @@ def after_sign_in_path_for(resource) referer_path = URI(request.referer).path unless request.referer.nil? or nil - if from_external_domain? || referer_path.eql?(new_user_session_path) || referer_path.eql?(new_user_registration_path) || referer_path.nil? + if from_external_domain? || referer_path.eql?(new_user_session_path) || + referer_path.eql?(new_user_registration_path) || + referer_path.nil? root_path else request.referer @@ -51,8 +61,10 @@ end def after_sign_up_path_for(resource) - referer_path = URI(request.referer).path unless request.referer.nil? or nil - if from_external_domain? || referer_path.eql?(new_user_session_path) || referer_path.nil? + referer_path = URI(request.referer).path unless request.referer.nil? + if from_external_domain? || + referer_path.eql?(new_user_session_path) || + referer_path.nil? root_path else request.referer @@ -69,23 +81,27 @@ def authenticate_admin! # currently if admin has any super-admin task, they can view the super-admin - redirect_to root_path unless user_signed_in? && (current_user.can_add_orgs? || current_user.can_change_org? || current_user.can_super_admin?) + unless user_signed_in? && (current_user.can_add_orgs? || + current_user.can_change_org? || + current_user.can_super_admin?) + redirect_to root_path + end end def failed_create_error(obj, obj_name) - "#{_('Could not create your %{o}.') % {o: obj_name}} #{errors_to_s(obj)}" + "#{_('Could not create your %{o}.') % { o: obj_name }} #{errors_to_s(obj)}" end def failed_update_error(obj, obj_name) - "#{_('Could not update your %{o}.') % {o: obj_name}} #{errors_to_s(obj)}" + "#{_('Could not update your %{o}.') % { o: obj_name }} #{errors_to_s(obj)}" end def failed_destroy_error(obj, obj_name) - "#{_('Could not delete the %{o}.') % {o: obj_name}} #{errors_to_s(obj)}" + "#{_('Could not delete the %{o}.') % { o: obj_name }} #{errors_to_s(obj)}" end def success_message(obj_name, action) - "#{_('Successfully %{action} your %{object}.') % {object: obj_name, action: action}}" + _("Successfully %{action} your %{object}.") % { object: obj_name, action: action } end # Override rails default render action to look for a branded version of a @@ -102,8 +118,8 @@ def errors_to_s(obj) if obj.errors.count > 0 msg = "
" - obj.errors.each do |e,m| - if m.include?('empty') || m.include?('blank') + obj.errors.each do |e, m| + if m.include?("empty") || m.include?("blank") msg += "#{_(e)} - #{_(m)}
" else msg += "'#{obj[e]}' - #{_(m)}
" @@ -135,4 +151,5 @@ false end end + end diff --git a/app/controllers/org_admin/sections_controller.rb b/app/controllers/org_admin/sections_controller.rb index bb8d0b7..41c545d 100644 --- a/app/controllers/org_admin/sections_controller.rb +++ b/app/controllers/org_admin/sections_controller.rb @@ -62,37 +62,29 @@ # POST /org_admin/templates/[:template_id]/phases/[:phase_id]/sections def create - phase = Phase.find(params[:phase_id]) - if phase.present? - section = Section.new(section_params.merge(phase_id: phase.id)) - authorize section - begin - section = get_new(section) - if section.save - flash[:notice] = success_message(_("section"), _("created")) - redirect_to edit_org_admin_template_phase_path( - id: section.phase.id, - template_id: section.phase.template.id, - section: section.id) - else - flash[:alert] = failed_create_error(section, _("section")) - redirect_to edit_org_admin_template_phase_path( - template_id: section.phase.template.id, - id: section.phase.id - ) - end - rescue StandardError => e - flash[:alert] = _("Unable to create a new version of this template.") - redirect_to edit_org_admin_template_phase_path( - template_id: section.phase.template.id, - id: section.phase.id - ) - end - else - # rubocop:disable Metrics/LineLength - flash[:alert] = _("Unable to create a new section because the phase you specified does not exist.") - # rubocop:enable Metrics/LineLength + @phase = Phase.find_by(id: params[:phase_id]) + if @phase.nil? + flash[:alert] = + _("Unable to create a new section. The phase you specified does not exist.") redirect_to edit_org_admin_template_path(template_id: params[:template_id]) + return + end + @section = @phase.sections.new(section_params) + authorize @section + @section = get_new(@section) + if @section.save + flash[:notice] = success_message(_("section"), _("created")) + redirect_to edit_org_admin_template_phase_path( + id: @section.phase_id, + template_id: @phase.template_id, + section: @section.id + ) + else + flash[:alert] = failed_create_error(@section, _("section")) + redirect_to edit_org_admin_template_phase_path( + template_id: @phase.template_id, + id: @section.phase_id + ) end end diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb index 3a9e399..aeb72e2 100644 --- a/app/controllers/org_admin/templates_controller.rb +++ b/app/controllers/org_admin/templates_controller.rb @@ -144,31 +144,27 @@ # GET /org_admin/templates/new def new authorize Template - render "container", locals: { - partial_path: "new", - template: Template.new(org: current_user.org), - referrer: request.referrer.present? ? request.referrer : org_admin_templates_path - } + @template = current_org.templates.new end # POST /org_admin/templates def create authorize Template # creates a new template with version 0 and new family_id - template = Template.new(template_params) - template.org_id = current_user.org.id - template.links = if params["template-links"].present? - ActiveSupport::JSON.decode(params["template-links"]) - else - { "funder": [], "sample_plan": [] } - end - if template.save - redirect_to edit_org_admin_template_path(template), - notice: success_message(template_type(template), _("created")) + @template = Template.new(template_params) + @template.org_id = current_user.org.id + @template.locale = current_org.language.abbreviation + @template.links = if params["template-links"].present? + ActiveSupport::JSON.decode(params["template-links"]) + else + { "funder": [], "sample_plan": [] } + end + if @template.save + redirect_to edit_org_admin_template_path(@template), + notice: success_message(template_type(@template), _("created")) else - flash[:alert] = failed_create_error(template, template_type(template)) - render partial: "org_admin/templates/new", - locals: { template: template, hash: hash } + flash[:alert] = failed_create_error(@template, template_type(@template)) + render :new end end diff --git a/app/helpers/template_helper.rb b/app/helpers/template_helper.rb index 42ab240..3905e98 100644 --- a/app/helpers/template_helper.rb +++ b/app/helpers/template_helper.rb @@ -1,8 +1,36 @@ +# frozen_string_literal: true + module TemplateHelper - def links_to_a_elements(links, separator = ', ') + + def template_details_path(template) + if template_modifiable?(template) + edit_org_admin_template_path(template) + else + if template.persisted? + org_admin_template_path(template) + else + org_admin_templates_path + end + end + end + + # Is this Template modifiable? + # + # template - A Template object + # + # Returns Boolean + def template_modifiable?(template) + template.latest? && + template.customization_of.blank? && + template.id.present? && + template.org_id = current_user.org.id + end + + def links_to_a_elements(links, separator = ", ") a = links.map do |l| "#{l['text']}" end a.join(separator) end -end \ No newline at end of file + +end diff --git a/app/models/section.rb b/app/models/section.rb index 42cb330..49f9237 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: sections @@ -21,6 +23,7 @@ # class Section < ActiveRecord::Base + include ValidationMessages include ValidationValues include ActsAsSortable @@ -108,8 +111,8 @@ copy.phase_id = options.fetch(:phase_id, nil) copy.save!(validate: false) if options.fetch(:save, false) options[:section_id] = copy.id - self.questions.map{ |question| copy.questions << question.deep_copy(options) } - return copy + self.questions.map { |question| copy.questions << question.deep_copy(options) } + copy end # Can't be modified as it was duplicatd over from another Phase. @@ -129,6 +132,7 @@ def set_number return if phase.nil? - self.number ||= phase.sections.maximum(:number) + 1 + self.number ||= phase.sections.maximum(:number).to_i + 1 end + end diff --git a/app/views/org_admin/questions/_form.html.erb b/app/views/org_admin/questions/_form.html.erb index ccf2757..cfa4a54 100644 --- a/app/views/org_admin/questions/_form.html.erb +++ b/app/views/org_admin/questions/_form.html.erb @@ -1,79 +1,95 @@ -

<%= question.id.present? ? _('Question %{number}:') % { number: question.number } : _('New question:') %>

-<%= form_for(question, url: url, namespace: question.id.present? ? question.id : 'new_question', html: { method: method, class: 'question_form' }) do |f| %> - <% current_format = question.question_format.present? ? question.question_format : QuestionFormat.find_by(formattype: QuestionFormat.formattypes[:textarea]) %> +

+ <%= question.id.present? ? _('Question %{number}:') % { number: question.number } : _('New question:') %> +

- -
- <%= f.label(:number, _('Question Number'), class: "control-label") %> - <%= f.number_field(:number, in: 1..50, class: "form-control", 'aria-required': true) %> -
- -
- <%= f.label(:text, _('Question text'), class: "control-label") %> - <%= f.text_area(:text, class: "question", 'aria-required': true) %> -
- -
- <%= f.label(:question_format_id, _('Answer format'), class: "control-label") %> - <%= f.select :question_format_id, - options_from_collection_for_select(QuestionFormat.all.order("title"), - :id, - :title, - question.question_format_id), - {}, - class: "form-control question_format", - 'data-toggle': 'tooltip', - 'data-html': true, - title: _("You can choose from:") - %> -
- -
-
- <%= render "/org_admin/question_options/option_fields", f: f, q: question %> - +<%= form_for(question, url: url, + namespace: question.id.present? ? question.id : 'new_question', + html: { method: method, class: 'question_form' }) do |f| %> + + <% current_format = question.question_format.present? ? question.question_format : QuestionFormat.find_by(formattype: QuestionFormat.formattypes[:textarea]) %> +
+ +
+ <%= f.label(:number, _('Question Number'), class: "control-label") %> + <%= f.number_field(:number, in: 1..50, class: "form-control", + aria: { required: true }) %>
-
- <% comment_disp = current_format.option_based? || current_format.rda_metadata? %> -
- -
+ + +
+ <%= f.label(:text, _('Question text'), class: "control-label") %> + <%= f.text_area(:text, class: "question", 'aria-required': true) %> +
+ + +
+ <%= f.label(:question_format_id, _('Answer format'), class: "control-label") %> + <%= f.select :question_format_id, + options_from_collection_for_select(QuestionFormat.all.order("title"), + :id, + :title, + question.question_format_id), + {}, + class: "form-control question_format", + 'data-toggle': 'tooltip', + 'data-html': true, + title: _("You can choose from:
  • - text area (large box for paragraphs);
  • - text field (for a short answer);
  • - checkboxes where options are presented in a list and multiple values can be selected;
  • - radio buttons where options are presented in a list but only one can be selected;
  • - dropdown like this box - only one option can be selected;
  • - multiple select box allows users to select several options from a scrollable list, using the CTRL key;
") + %> +
+ + +
+
+ <%= render "/org_admin/question_options/option_fields", f: f, q: question %> + +
+
+ + <% comment_disp = current_format.option_based? || current_format.rda_metadata? %> +
+ +
+ -
- <%= f.label(:default_value, _('Default answer'), class: "control-label") %> -
- - <%= f.text_field(:default_value, class: 'form-control') %> - - - <%= text_area_tag('question[default_value]', question.default_value, id: "#{question.id.present? ? question.id : 'new'}_question_default_value_area", class: "form-control question") %> - +
+ <%= f.label(:default_value, _('Default answer'), class: "control-label") %> +
+ + <%= f.text_field(:default_value, class: 'form-control') %> + + + <%= text_area_tag('question[default_value]', question.default_value, id: "#{question.id.present? ? question.id : 'new'}_question_default_value_area", class: "form-control question") %> + +
- <%# example_answer and guidance annotations as nested fields %> - <% question.annotations_per_org(current_user.org_id).each do |annotation| %> - <%= f.fields_for(:annotations, annotation) do |annotation_fields| %> - <%= render partial: 'org_admin/annotations/form', locals: { f: annotation_fields } %> - <% end %> - <% end %> - -
- <%= render partial: 'org_admin/shared/theme_selector', - locals: { f: f, all_themes: Theme.all.order("title"), as_radio: false, - popover_message: _('Select one or more themes that are relevant to this question. This will allow similarly themed organisation-level guidance to appear alongside your question.') } %> -
-
-
- <%= f.submit _('Save'), class: "btn btn-default", role:'button' %> - <% if question.id.present? && !question.section.phase.template.published? %> - <% href = org_admin_template_phase_section_question_path(template_id: template.id, phase_id: question.section.phase.id, section_id: question.section.id, id: question.id) %> - <%= link_to _('Delete'), href, method: :delete, class: "btn btn-default", role:'button', 'data-confirm': _("You are about to delete question #%{question_number}. Are you sure?") % { question_number: question.number } %> - <%= link_to _('Cancel'), href, class: "btn btn-default ajaxified-question", method: 'get', remote: true %> - <% else %> - <%= link_to _('Cancel'), '#', class: "btn btn-default cancel-new-question" %> +
+ <%# example_answer and guidance annotations as nested fields %> + <% question.annotations_per_org(current_user.org_id).each do |annotation| %> + <%= f.fields_for(:annotations, annotation) do |annotation_fields| %> + <%= render partial: 'org_admin/annotations/form', locals: { f: annotation_fields } %> <% end %> + <% end %> + +
+ <%= render partial: 'org_admin/shared/theme_selector', + locals: { f: f, all_themes: Theme.all.order("title"), as_radio: false, + popover_message: _('Select one or more themes that are relevant to this question. This will allow similarly themed organisation-level guidance to appear alongside your question.') } %> +
+
+
+ <%= f.submit _('Save'), class: "btn btn-default", role:'button' %> + <% if question.id.present? && !question.section.phase.template.published? %> + <% href = org_admin_template_phase_section_question_path(template_id: template.id, phase_id: question.section.phase.id, section_id: question.section.id, id: question.id) %> + <%= link_to _('Delete'), href, method: :delete, class: "btn btn-default", role:'button', 'data-confirm': _("You are about to delete question #%{question_number}. Are you sure?") % { question_number: question.number } %> + <%= link_to _('Cancel'), href, class: "btn btn-default ajaxified-question", method: 'get', remote: true %> + <% else %> + <%= link_to _('Cancel'), '#', class: "btn btn-default cancel-new-question" %> + <% end %> +
<% end %> diff --git a/app/views/org_admin/templates/_form.html.erb b/app/views/org_admin/templates/_form.html.erb index 9684ac1..146b11d 100644 --- a/app/views/org_admin/templates/_form.html.erb +++ b/app/views/org_admin/templates/_form.html.erb @@ -18,9 +18,9 @@
<%= f.label(:visibility) do %> <%= check_box_tag('template_visibility', '0', - (template.visibility == 'organisationally_visible')) %> + (f.object.visibility == 'organisationally_visible')) %> - <%= _('for internal %{org_name} use only') % { org_name: template.org.name } %> + <%= _('for internal %{org_name} use only') % { org_name: f.object.org.name } %> <% end %>
@@ -29,9 +29,9 @@
<%= label_tag(:status, _('Status'), class: "control-label") %>

- <% if template.published? %> + <% if f.object.published? %> <%= _('Published') %> - <% elsif (template.version.present? && template.version <= 0) || !template.id.present? %> + <% elsif (f.object.version.present? && f.object.version <= 0) || !f.object.id.present? %> <%= _('Unpublished') %> <% else %> <%= _('Draft') %> @@ -39,28 +39,28 @@

-<% if template.id.present? %> +<% if f.object.id.present? %>
<%= label_tag(:created_at, _('Created at'), class: "control-label") %>

- <%= l template.created_at.to_date, formats: :short %> + <%= l f.object.created_at.to_date, formats: :short %>

<%= label_tag(:updated, _('Last updated'), class: "control-label") %>

- <%= l template.updated_at.to_date, formats: :short %> + <%= l f.object.updated_at.to_date, formats: :short %>

<% end %> -<% if template.org.funder? %> +<% if f.object.org.funder? %>
<%= render(partial: '/shared/links', locals: { context: 'funder', title: _('Funder Links'), - links: Hash(template.links).fetch('funder', []), + links: Hash(f.object.links).fetch('funder', []), max_number_links: MAX_NUMBER_LINKS_FUNDER, tooltip: _('Add links to funder websites that provide additional information about the requirements for this template') }) %>
@@ -69,11 +69,11 @@ locals: { context: 'sample_plan', title: _('Sample Plan Links'), - links: Hash(template.links).fetch('sample_plan', []), + links: Hash(f.object.links).fetch('sample_plan', []), max_number_links: MAX_NUMBER_LINKS_SAMPLE_PLAN, tooltip: _('Add links to sample plans if provided by the funder.') }) %>
- <%= hidden_field_tag('template-links', ActiveSupport::JSON.encode(template.links)) %> + <%= hidden_field_tag('template-links', ActiveSupport::JSON.encode(f.object.links)) %> <% end %>
diff --git a/app/views/org_admin/templates/_navigation.html.erb b/app/views/org_admin/templates/_navigation.html.erb index ca7a7b1..3c87adf 100644 --- a/app/views/org_admin/templates/_navigation.html.erb +++ b/app/views/org_admin/templates/_navigation.html.erb @@ -1,7 +1,6 @@ -<% details_path = modifiable ? edit_org_admin_template_path(template.id) : template.id.present? ? org_admin_template_path(template.id) : org_admin_templates_path %>