diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 1408264..d4dc86c 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -21,45 +21,65 @@ authorize @plan @funders = Org.funders.all + no_org = Org.new() + no_org.id = -1 + no_org.name = "No Funder" + @funders.unshift(no_org) + + respond_to do |format| format.html # new.html.erb end end + # we get here either from selecting a funder or if if the first selection + # results in multiple templates, from a template selection screen def create @plan = Plan.new authorize @plan @plan.save + message = "" + + # if we have a template_id we've been selcting between templates, otherwise funders if params[:template_id] @templates = [ Template.find(params[:template_id] ) ] else + funder_id = params[:plan][:funder_id].to_i - funder_id = params[:plan][:funder_id] - if !funder_id.blank? + if funder_id.present? && funder_id != -1 + @templates = [] + # get all funder @templates funder = Org.find(params[:plan][:funder_id]) - @templates = get_most_recent( funder.templates.where("published = ?", true).all ) + funder_templates = get_most_recent( funder.templates.where(published: true).all ) - orgtemplates = current_user.org.templates.all - replacements = [] + # get org templates and index by customization id + orgtemplates = get_most_recent( current_user.org.templates.all ) - # replace any that are customised by the org - orgtemplates.each do |orgt| - base_template = orgt.customization_of - @templates.delete(base_template) - replacements << orgt + orgt_by_customization = orgtemplates.collect{|t| [t.customization_of, t]}.to_h + + # go through funder templates and replace with org cusomizations if needed + funder_templates.each do |ft| + if orgt_by_customization.has_key?(ft.dmptemplate_id) + message = _(" - using template customised by your institution") + @templates << orgt_by_customization[ft.dmptemplate_id] + else + @templates << ft + end end - @templates + replacements + else # either didn't select funder or selected "No Funder" - else # get all org @templates which are not customisations - @templates = current_user.org.templates.where(customization_of: nil) + @templates = get_most_recent( current_user.org.templates.where(customization_of: nil) ) - # if none of these get the basic dcc template + message = _(" - choosing default template for your institution") + + # if none of these get the default template if @templates.blank? - @templates = Template.find_by_is_default(true) + @templates = get_most_recent( Template.where(is_default: true, customization_of: nil) ) + message = _(" - no funder or institution template, choosing default template") end end end @@ -69,11 +89,18 @@ # to choose otherwise just create the plan # and go to the plan/show template if @templates.length > 1 + message += _(" - there are more than one to choose from") + flash.notice = message + respond_to do |format| + format.html + end return end @plan.template = @templates[0] + @based_on = @plan.base_template() + @plan.principal_investigator = current_user.name @plan.title = _('My plan')+' ('+@plan.template.title+')' # We should use interpolated string since the order of the words from this message could vary among languages @@ -84,10 +111,11 @@ @selected_guidance_groups = @plan.guidance_groups.map{ |pgg| [pgg.name, pgg.id, :checked => false] } @selected_guidance_groups.sort! - + respond_to do |format| if @plan.save - format.html { redirect_to({:action => "show", :id => @plan.id, :editing => true }, {:notice => _('Plan was successfully created.')}) } + flash.notice = _('Plan was successfully created.') + message + format.html { redirect_to({:action => "show", :id => @plan.id, :editing => true }) } else flash[:notice] = failed_create_error(@plan, _('plan')) format.html { render action: "new" } @@ -106,6 +134,8 @@ all_guidance_groups = @plan.plan_guidance_groups @selected_guidance_groups = all_guidance_groups.map{ |pgg| [ pgg.guidance_group.name, pgg.guidance_group.id, :checked => pgg.selected ] } @selected_guidance_groups.sort! + @based_on = @plan.base_template + respond_to :html end @@ -358,12 +388,15 @@ private + # different versions of the same template have the same dmptemplate_id + # but different version numbers so for each set of templates with the + # same dmptemplate_id choose the highest version number. def get_most_recent( templates ) groups = Hash.new templates.each do |t| k = t.dmptemplate_id if !groups.has_key?(k) - groups[k] =t + groups[k] = t else other = groups[k] if other.version < t.version diff --git a/app/models/plan.rb b/app/models/plan.rb index 30ce215..436a851 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -85,6 +85,17 @@ + def base_template + base = nil + t = self.template + if t.customization_of.present? + base = Template.where("dmptemplate_id = ? and created_at < ?", t.customization_of, self.created_at).order(version: :desc).first + end + return base + end + + + ## # returns the most recent answer to the given question id # optionally can create an answer if none exists @@ -909,98 +920,6 @@ - ## - # - # The following method is to help optimise data access. - # Even using includes or joins the data access gets performed lazily - # and the caching appears to be forgotten at times over view/partial boundaries - # To get round it we can pull everything out into a hash and use that - # which guarantees no further DB accesses. - # - # The serializable_hash method only pulls in one level but this includes - # attributes which are "through" other attributes. So we do a basic - # conversion to hash and then a "fixup" which knits the pieces together into - # the structure which we really want. - # - def to_hash - plan_data = self.serializable_hash( - include: [ :template, :phases, :sections, - :answers, :notes, :roles, :users, :questions, - :plan_guidance_groups, :guidance_groups] - ) - - # serializable_hash only works over one level so we still need to go and extract - # the deeper levels and knit them in. - # - # want hash of questions by id to add in suggested answers and question_formats - question_hash = {} - - plan_data["questions"].each do |q| - question_hash[q["id"]] = q - end - - question_ids = question_hash.keys - - # pull out suggested answers - suggested_answers = SuggestedAnswer.where(question_id: question_ids).where.not(text: '') - suggested_answers.each do |sa| - question_hash[sa.question_id]["suggested_answer"] = sa.serializable_hash - end - - # pull out question_formats - qf_hash = {} - QuestionFormat.all.each do |qf| - qf_hash[qf.id] = qf.serializable_hash - end - # add question _formats to questions - question_hash.values.each do |q| - q["question_format"] = qf_hash[q["question_format_id"]] - end - - # get the ids of the dynamically selected guidance groups - # and keep a map of them so we can extract the name later - gg_ids = plan_data["plan_guidance_groups"].select{|pgg| pgg["selected"]}.map{|pgg| pgg["guidance_group_id"]} - gg_hash = {} - ggs = GuidanceGroup.find(gg_ids).each do |gg| - gg_hash[gg.id] = gg.serializable_hash - end - - # create a map from theme to array of guidances - theme_guidance = {} - guidances = Guidance.joins(:themes) - .select('guidances.guidance_group_id, guidances.text, themes.title') - .where(guidance_group: gg_ids) - .to_a - - guidances.each do |g| - title = g.title - if !theme_guidance.has_key?(title) - theme_guidance[title] = Array.new - end - theme_guidance[title] << { - "text" => g.text, - "org" => gg_hash[g.guidance_group_id]["name"] - } - end - - # link the guidance to the questions - plan_data["questions"].each do |q| - qg = {} - if q.has_key?("themes") - q["themes"].each do |t| - title = t["title"] - qg[title] = theme_guidance[title] if theme_guidance.has_key?(title) - end - q["theme_guidance"] = qg - end - end - - fixup_hash(plan_data) - - return plan_data - end - - # the following two methods are for eager loading. One gets used for the plan/show # page and the oter for the plan/edit. The difference is just that one pulls in more than # the other. diff --git a/app/views/plans/_dropdowns_new_plan.html.erb b/app/views/plans/_dropdowns_new_plan.html.erb index 1fb8708..c7e9d7e 100644 --- a/app/views/plans/_dropdowns_new_plan.html.erb +++ b/app/views/plans/_dropdowns_new_plan.html.erb @@ -1,13 +1,13 @@ -<%= semantic_form_for @plan, :url => {:controller => :plans, :action => :create }, :html=>{:method=>:post} do |f| %> +<%= semantic_form_for @plan, url: plans_path(@plan) do |f| %> <%= f.inputs do %> <%= hidden_field_tag :default_tag, "false" ,:id => "default_tag" %>

<%= _('Create a new plan') %>

-

<%= raw _("

Please select from the following drop-downs so we can determine what questions and guidance should be displayed in your plan.

If you aren't responding to specific requirements from a funder or an institution, select here to write a generic DMP based on the most common themes.

")%>

+

<%= raw _("

Please select from the following drop-down so we can determine what questions and guidance should be displayed in your plan.

")%>

@@ -19,7 +19,7 @@ <%= f.input :funder_id, :as => :select, :collection => @funders, - :label => _('If applying for funding, select your research funder.'), + :label => _('Select your research funder or no funder, as appropariate.'), :input_html => { :multiple => false, :class => ["select2", "select2-container"] }, :include_blank => _('Select Funder') %> diff --git a/app/views/plans/_plan_details.html.erb b/app/views/plans/_plan_details.html.erb index 3099163..dde9a2f 100644 --- a/app/views/plans/_plan_details.html.erb +++ b/app/views/plans/_plan_details.html.erb @@ -204,9 +204,8 @@ <%= plan.template.org.name %> <%end%> - <%if plan.template.customization_of.present? %> - <% ctemplate = Template.find(plan.template.customization_of) %> - <%= " (Customised from " + ctemplate.org.name + ")" %> + <%if based_on.present? %> + <%= " (Customised from " + based_on.org.name + ")" %> <%end%> diff --git a/app/views/plans/show.html.erb b/app/views/plans/show.html.erb index ea6bcbe..61c37e8 100644 --- a/app/views/plans/show.html.erb +++ b/app/views/plans/show.html.erb @@ -7,4 +7,4 @@ <%= render :partial => "plan_nav_tabs", locals: {plan: @plan, active: "details"} %> -<%= render :partial => "plan_details", locals: {plan: @plan, selected_guidance_groups: @selected_guidance_groups} %> +<%= render :partial => "plan_details", locals: {plan: @plan, based_on: @based_on, selected_guidance_groups: @selected_guidance_groups} %>