diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index 8b762fd..b590d41 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -22,7 +22,6 @@ @old_answer = nil if @answer.nil? - logger.debug "didn't find answer so creating a new one" @answer = Answer.new(params[:answer]) authorize @answer @answer.save diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb index 6133a45..8c66763 100644 --- a/app/controllers/phases_controller.rb +++ b/app/controllers/phases_controller.rb @@ -4,17 +4,74 @@ after_action :verify_authorized - # GET /plans/PLANID/phases/PHASEID/edit + # GET /plans/:plan_id/phases/:id/edit def edit - @plan = Plan.find(params[:plan_id]) + @plan = Plan.eager_load2(params[:plan_id]) authorize @plan - @plan_data = @plan.to_hash - phase_id = params[:id].to_i - @phase = Phase.find(phase_id) - @phase_data = @plan_data["template"]["phases"].select {|p| p["id"] == phase_id}.first + @phase = @plan.template.phases.select {|p| p.id == phase_id}.first + + # the eager_load pulls in ALL answers + # need to restrict to just ones for this plan + @plan.template.phases.each do |phase| + phase.sections do |section| + section.questions.each do |question| + question.answers = question.answers.to_a.select {|answer| answer.plan_id == @plan.id} + end + end + end + + # Now we need to get all the themed guidance for the plan. + # TODO: think this through again, there may be a better way to do this. + # + # Ultimately we are heading to a map from question id to theme to guidance. + # + # get the ids of the dynamically selected guidance groups + # and keep a map of them so we can extract the names later + guidance_groups_ids = @plan.plan_guidance_groups.select{|pgg| pgg.selected}.map{|pgg| pgg.guidance_group.id} + guidance_groups = GuidanceGroup.includes({guidances: :themes}).find(guidance_groups_ids) + + # create a map from theme to array of guidances + # where guidance is a hash with the text and the org name + theme_guidance = {} + + guidance_groups.each do |guidance_group| + guidance_group.guidances.each do |guidance| + guidance.themes.each do |theme| + title = theme.title + if !theme_guidance.has_key?(title) + theme_guidance[title] = Array.new + end + theme_guidance[title] << { + text: guidance.text, + org: guidance_group.name + } + end + end + end + + # create hash from question id to theme to guidance array + # so when we arerendering a question we can grab the guidance out of this + # + # question_guidance = { + # question.id => { + # theme => [ {text: "......", org: "....."} ] + # } + # } + @question_guidance = {} + @plan.questions.each do |question| + qg = {} + question.themes.each do |t| + title = t.title + qg[title] = theme_guidance[title] if theme_guidance.has_key?(title) + end + if !@question_guidance.has_key?(question.id) + @question_guidance[question.id] = Array.new + end + @question_guidance[question.id] = qg + end if !user_signed_in? then respond_to do |format| @@ -27,7 +84,7 @@ # GET /plans/PLANID/phases/PHASEID/status.json def status - @plan = Plan.find(params[:plan_id]) + @plan = Plan.eager_load(params[:plan_id]) authorize @plan if user_signed_in? && @plan.readable_by?(current_user.id) then respond_to do |format| @@ -42,7 +99,7 @@ #show and edit a phase of the template def admin_show - @phase = Phase.find(params[:id]) + @phase = Phase.eager_load(params[:id]) authorize @phase @edit = params[:edit] == "true" ? true : false #verify if there are any sections if not create one diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 43be23d..abc7b8f 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -104,15 +104,13 @@ # GET /plans/show def show - @plan = Plan.find(params[:id]) + @plan = Plan.eager_load(params[:id]) authorize @plan - @plan_data = @plan.to_hash - @editing = params[:editing] && @plan.administerable_by?(current_user.id) @selected_guidance_groups = [] - all_guidance_groups = @plan_data["plan_guidance_groups"] - @selected_guidance_groups = all_guidance_groups.map{ |pgg| [ pgg["guidance_group"]["name"], pgg["guidance_group"]["id"], :checked => pgg["selected"] ] } + 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! if user_signed_in? && @plan.readable_by?(current_user.id) then diff --git a/app/models/plan.rb b/app/models/plan.rb index 4c5f974..ba76aa4 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -995,6 +995,35 @@ 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. + # TODO: revisit this and work out for sure that maintaining the difference is worthwhile. + # it may not be. Also make sure nether is doing more thanit needs to. + # + def self.eager_load(id) + Plan.includes( + [{template: [ + {phases: {sections: {questions: :answers}}}, + {customizations: :org} + ]}, + {plan_guidance_groups: {guidance_group: :guidances}} + ]).find(id) + end + + def self.eager_load2(id) + Plan.includes( + [{template: [ + {phases: {sections: {questions: [{answers: :notes}, :suggested_answers, :question_format, :themes]}}}, + {customizations: :org}, + :org + ]}, + {plan_guidance_groups: {guidance_group: {guidances: :themes}}}, + {questions: :themes} + ]).find(id) + end + + private diff --git a/app/models/question.rb b/app/models/question.rb index c36aaef..4533cc6 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -50,6 +50,10 @@ return format.option_based end + def plan_answers(plan_id) + return self.answers.to_a.select{|ans| ans.plan_id == plan_id} + end + ## # deep copy the given question and all it's associations # diff --git a/app/models/section.rb b/app/models/section.rb index 87e98b6..b88ee79 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -24,6 +24,14 @@ "#{title}" end + def num_answered_questions(plan_id) + n = 0 + self.questions.each do |question| + n += question.plan_answers(plan_id).select{|answer| answer.text.present?}.count + end + return n + end + ## # deep copy of the given section and all it's associations # diff --git a/app/views/phases/_add_note.html.erb b/app/views/phases/_add_note.html.erb index 2b59859..190f89b 100644 --- a/app/views/phases/_add_note.html.erb +++ b/app/views/phases/_add_note.html.erb @@ -1,12 +1,9 @@ -<% new_note = Note.new - if !answer.nil? - answerid = answer["id"] - else - answerid = answer_obj.id - end +<% + new_note = Note.new + answerid = answer.id %> <%= form_for :new_note, @@ -14,8 +11,8 @@ :html=>{:method=>:post, :id => "new_note_form_#{answerid}", :class => "add_note_form"} do |f| %> <%= f.hidden_field :user_id, :value => current_user.id %> <%= f.hidden_field :answer_id, :value => answerid %> - <%= f.hidden_field :question_id, :value => question["id"] %> - <%= f.hidden_field :plan_id, :value => plan_data["id"] %> + <%= f.hidden_field :question_id, :value => question.id %> + <%= f.hidden_field :plan_id, :value => plan_id %> <%= text_area_tag("#{answerid}new_note_text".to_sym, "" , class: "tinymce") %>
diff --git a/app/views/phases/_answer_form.html.erb b/app/views/phases/_answer_form.html.erb index dee0e31..5b498fe 100644 --- a/app/views/phases/_answer_form.html.erb +++ b/app/views/phases/_answer_form.html.erb @@ -8,56 +8,55 @@
<% - answer = nil - answer_obj = nil - if question.has_key?("answers") - answer = question["answers"].first - answer_obj = Answer.find(answer["id"]) + answers = question.plan_answers(plan.id) + if answers.present? + answer = answers.first else - answer_obj = Answer.new + answer = Answer.new end - question_id = question["id"] - question_obj = Question.find(question_id) - q_format = question_obj.question_format + question_id = question.id + q_format = question.question_format %>
- <%= semantic_form_for answer_obj, :url => {:controller => :answers, :action => :update }, :remote => true do |f| %> + <%= semantic_form_for answer, :url => {:controller => :answers, :action => :update }, :remote => true do |f| %> <%= f.inputs do %> - <%= f.input :plan_id, :as => :hidden, :input_html => { :value => @plan_data["id"] } %> + <%= f.input :plan_id, :as => :hidden, :input_html => { :value => @plan.id } %> <%= f.input :user_id, :as => :hidden, :input_html => { :value => current_user.id } %> <%= f.input :question_id, :as => :hidden, :input_html => { :value => question_id, :class => "question_id" } %> <%= f.hidden_field :lock_version %> - <%= raw question["text"] %> + <%= raw question.text %> - <% if question.has_key?("suggested_answer") && question["suggested_answer"]["text"].present? %> - <% suggested_answer = question["suggested_answer"] %> -
- - <% if suggested_answer["is_example"] then %> - <%= _('Example of answer')%> - <%else%> - <%= _('Suggested answer')%> - <%end%> - + <% if question.suggested_answers.any? %> + <% suggested_answer = question.suggested_answers.first %> + <% if suggested_answer.text.present? %> +
+ + <% if suggested_answer.is_example? then %> + <%= _('Example of answer')%> + <%else%> + <%= _('Suggested answer')%> + <%end%> + -
-

- <%= raw suggested_answer["text"] %> -

+
+

+ <%= raw suggested_answer.text %> +

+
-
+ <% end %> <% end %> -
+
- <% if question_obj.isOptionBased? %> + <% if question.isOptionBased? %> <% options = question.options.order("number") %> @@ -92,7 +91,7 @@ <% if q_format.textfield? %> <%= text_field_tag("answer-text-#{question_id}".to_sym, strip_tags(answer.text), class: "question_text_field") %> <% elsif q_format.textarea? %> - <%= text_area_tag("answer-text-#{question_id}".to_sym, answer_obj.text, class: "tinymce") %> + <%= text_area_tag("answer-text-#{question_id}".to_sym, answer.text, class: "tinymce") %> <% end %> <% end %> @@ -105,10 +104,10 @@ <% end %>
- <% if answer.nil? || !answer.has_key?("created_at") || answer["created_at"].nil? %> + <% if answer.nil? || answer.created_at.nil? %> <%= _('Not answered yet') %> <% else %> - <%= _('Answered')%><%= answer_obj.created_at %><%= _(' by')%><%= answer_obj.user.name %> + <%= _('Answered')%><%= answer.created_at %><%= _(' by')%><%= answer.user.name %> <% end %>
@@ -118,10 +117,10 @@
- <% comments = answer_obj.notes.all %> + <% comments = answer.notes.all %> <%= hidden_field_tag :question_id, question_id, :class => "question_id" %>
    - <% if (!question["guidance"].nil? && question["guidance"] != "") || question.has_key?("theme_guidance") then %> + <% if question.guidance.present? || question_guidances[question_id] %> <% css_style_comment_div = "display: none;"%> <% css_style_guidance_div = ""%> @@ -158,7 +157,7 @@
    - <% if question["guidance"].present? %> + <% if question.guidance.present? %>
    @@ -172,50 +171,38 @@
    -
    <%= raw question["guidance"] %>
    +
    <%= raw question.guidance %>
    <% end %> - - <% gnum = 0 %> - <% if question.has_key?("theme_guidance") %> - <% question["theme_guidance"].each_key do |theme| %> - <% question["theme_guidance"][theme].each do |guidance| %> - <% - orgname = guidance["org"] - gnum = gnum + 1 - text = guidance["text"] - %> - -
    - - -
    - -
    - <%= orgname %> guidance on <%= theme %> -
    -
    + <% guidance_accordion_id = 0 %> + <% question_guidances.each_pair do |theme, group| %> + <% group.each do |gobj| %> +
    + +
    +
    <%= raw gobj[:text] %>
    +
    + <% guidance_accordion_id += 1 %>
    - - -
    -
    <%= raw text %>
    -
    -
    - <% end %> - <% end %> - <% end %> + <% end %> + <% end %>
    - <%= render :partial => "note", locals: {question: question, answer_obj: answer_obj, answer: answer, plan: plan, plan_data: plan_data}%> + <%= render :partial => "note", locals: {question: question, answer: answer, plan: plan }%>
diff --git a/app/views/phases/_answer_form_ro.html.erb b/app/views/phases/_answer_form_ro.html.erb index d0f18ea..674cc29 100644 --- a/app/views/phases/_answer_form_ro.html.erb +++ b/app/views/phases/_answer_form_ro.html.erb @@ -149,9 +149,10 @@
<% @comments = Notes.where("question_id = ? AND plan_id = ?", question.id, answer.plan_id ) %> <%= hidden_field_tag :question_id, question.id, :class => "question_id" %> - <% @question_guidances = @plan.guidance_for_question(question) %> +
    - <% if (!question.guidance.nil? && question.guidance != "") || @question_guidances.count > 0 then %> + + <% if (!question.guidance.nil? && question.guidance != "") || !question_guidances.empty? then %> <% css_style_comment_div = "display: none;"%> <% css_style_guidance_div = ""%> @@ -206,28 +207,25 @@
<% end %> - - <% @question_guidances.each_pair do |group,themes| %> - <% themes.each_pair do |theme,guidances| %> - <% guidances.each do |guidance| %> + + <% guidance_accordion_id = 1 %> + <% question_guidances.each_pair do |theme, group| %> + <% group.each do |gobj| %>
-
-
<%= raw guidance.text %>
+
+
<%= raw gobj[:text] %>
+ <% guidance_accordion_id += 1 %>
<% end %> - <% end %> <% end %>
diff --git a/app/views/phases/_list_notes.html.erb b/app/views/phases/_list_notes.html.erb index 27593dc..bd2ae70 100644 --- a/app/views/phases/_list_notes.html.erb +++ b/app/views/phases/_list_notes.html.erb @@ -6,46 +6,42 @@ <% style_to_add = "" %> <%end%> - -<% notes.sort! {|x,y| y["updated_at"] <=> x["updated_at"] } %> -
- <% notes.each do |c|%> + <% notes.each do |note|%>
- <% user = c["user"] %> - <% user = User.find(c["user_id"]) %> - <%= user["name"] %>
- (<%= l c["updated_at"], format: :custom %>) + <% user = note.user.name %> + <%= user %>
+ (<%= l note.updated_at, format: :custom %>)
- <% if c["archived"] %> + <% if note.archived %> - <% if c["archived_by"] == current_user.id %> + <% if note.archived_by == current_user.id %> <%= _('Note removed by you')%> <% else %> - <% archived_by_user = User.find(c["archived_by"]) %> + <% archived_by_user = User.find(note.archived_by) %> <%= _('Note removed by')%> <%= archived_by_user.name %> <%end%> <%else%> <%= link_to _('View'),"#", :class => "dmp_table_link view_comment_button" %> - <%= hidden_field_tag :note_id, c["id"], :class => "comment_id" %> + <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> - <% if current_user.id == c["user_id"] %> + <% if current_user.id == note.user_id %> <%= link_to _('Edit'),"#", :class => "dmp_table_link edit_comment_button" %> - <%= hidden_field_tag :note_id, c["id"], :class => "comment_id" %> + <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> <%= link_to _('Remove'),"#", :class => "dmp_table_link archive_comment_button" %> <% end%> - <% if plan.administerable_by?(current_user.id) && current_user.id != c["user_id"] %> - <%= hidden_field_tag :note_id, c["id"], :class => "comment_id" %> + <% if plan.administerable_by?(current_user.id) && current_user.id != note.user_id %> + <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> <%= link_to _('Remove'),"#", :class => "dmp_table_link archive_comment_button" %> <% end%> <%end%> @@ -60,10 +56,10 @@
-<% notes_not_archived = notes.select { |n| n["archived"].nil? } %> -<% latest_note = notes_not_archived.sort { |x,y| y["updated_at"] <=> x["updated_at"] }.first %> +<% notes_not_archived = notes.select { |n| n.archived.nil? } %> +<% latest_note = notes_not_archived.sort { |x,y| y.updated_at <=> x.updated_at }.first %> <% if !latest_note.nil? then%> -
" class ="view_comment_class"> +
<%= render :partial => "view_note", locals: {note: latest_note} %>
diff --git a/app/views/phases/_note.html.erb b/app/views/phases/_note.html.erb index 8ad56e5..ce15d4c 100644 --- a/app/views/phases/_note.html.erb +++ b/app/views/phases/_note.html.erb @@ -1,10 +1,10 @@ - <% if answer.present? && answer.has_key?("notes") %> - <% notes = answer["notes"] %> - <% answerid = answer["id"] %> - <%= hidden_field_tag :answer_id, answer["id"] %> + <% if answer.present? && answer.notes.any? %> + <% notes = answer.notes.all.to_a.sort! {|x,y| y["updated_at"] <=> x["updated_at"] } %> + <% answerid = answer.id %> + <%= hidden_field_tag :answer_id, answer.id %>
@@ -14,7 +14,7 @@
- <%= render :partial => "list_notes", locals: {question: question, notes: notes, plan:plan} %> + <%= render :partial => "list_notes", locals: {question_id: question.id, notes: notes, plan: plan} %>
@@ -27,10 +27,10 @@ <% else%> <%= _('Share note with collaborators')%> - <%= render :partial => "add_note", locals: {answer: answer, answer_obj: answer_obj, question: question, plan_data: plan_data}%> + <%= render :partial => "add_note", locals: {answer: answer, question: question, plan_id: plan.id }%> <% end%> diff --git a/app/views/phases/edit.html.erb b/app/views/phases/edit.html.erb index 4d4cc96..3dbdc34 100644 --- a/app/views/phases/edit.html.erb +++ b/app/views/phases/edit.html.erb @@ -7,7 +7,7 @@ --> -<%= render :partial => "/plans/plan_title", locals: {plan: @plan, plan_data: @plan_data} %> +<%= render :partial => "/plans/plan_title", locals: {plan: @plan} %> @@ -30,15 +30,15 @@
-<%= render :partial => "/plans/plan_nav_tabs", locals: {plan: @plan, plan_data: @plan_data, active: @phase.title } %> +<%= render :partial => "/plans/plan_nav_tabs", locals: {plan: @plan, active: @phase.title} %>
- <% @phase_data["sections"].each do |section| %> + <% @phase.sections.each do |section| %> - <% sectionid = section["id"] %> + <% sectionid = section.id %> <% if session[:question_id_comments].to_i != 0 then %> @@ -48,13 +48,11 @@ <%end%> <% end%> - -
- <% num_section_questions = section["questions"].count %> - <% num_section_answers = section["nanswers"] %> + <% num_section_questions = section.questions.to_a.count %> + <% num_section_answers = section.num_answered_questions(@plan.id) %> <% question_word = "questions" %> <% if num_section_questions == 1 then %> <% question_word = "question" %> @@ -63,9 +61,9 @@
- "> -
"> - <%= section["title"] %> + +
+ <%= section.title %> <% if num_section_questions.to_i > num_section_answers.to_i then %> (<%= section_status %>) <% else %> @@ -81,7 +79,7 @@
- <%= raw section["description"] %> + <%= raw section.description %>
@@ -100,8 +98,8 @@
- <% section["questions"].each do |question| %> - <% if question["id"] == session[:question_id_comments].to_i then id_css = "current_question" end %> + <% section.questions.each do |question| %> + <% if question.id == session[:question_id_comments].to_i then id_css = "current_question" end %>
<% partialname = "answer_form" if @readonly @@ -109,15 +107,15 @@ end %> - <% guidances = question["guidances"] %> + <% guidances = @question_guidance[question.id] %> <%= render partial: partialname, locals: { plan: @plan, - plan_data: @plan_data, - phase_id: @phase_data["id"], + phase_id: @phase.id, question: question, - last_question_id: section["questions"].last["id"], + question_guidances: guidances, + last_question_id: section.questions.last.id, } %>
diff --git a/app/views/plans/_export.html.erb b/app/views/plans/_export.html.erb index 1352bc2..2d53826 100644 --- a/app/views/plans/_export.html.erb +++ b/app/views/plans/_export.html.erb @@ -1,9 +1,9 @@ diff --git a/app/views/plans/_plan_details.html.erb b/app/views/plans/_plan_details.html.erb index b3f6d2e..8329658 100644 --- a/app/views/plans/_plan_details.html.erb +++ b/app/views/plans/_plan_details.html.erb @@ -198,21 +198,21 @@ - <%if @plan_data["template"]["org"]["name"].present? %> + <%if plan.template.org.name.present? %> - + <%end%> - <%if @plan_data["template"]["customization_of"].present? %> - <%= " (Customised from " + @plan_data["template"]["customization_of"]["org"]["name"] + ")" %> + <%if plan.template.customization_of.present? %> + <%= " (Customised from " + plan.template.customization_of.org.name + ")" %> <%end%>
<%= constant("organisation_types.funder") %><%= @plan_data["template"]["org"]["name"] %><%= plan.template.org.name %>
- <% phases = @plan_data["template"]["phases"] %> + <% phases = plan.template.phases %> <% if phases.any? %> <% if phases.count == 1 then %> <% phases.each do |phase| %> @@ -221,10 +221,10 @@ <%= link_to _('Answer questions'), edit_plan_path(plan), :class => 'btn btn-primary' %>
<%= _('Export') %>
- <%= render :partial => "plans/export", locals: {plan: plan, plan_data: plan_data} %> + <%= render :partial => "plans/export", locals: {plan: plan } %>
-

<%= raw phase["description"] %>

- <% if phase["sections"].any? %> +

<%= raw phase.description %>

+ <% if phase.sections.any? %> @@ -236,14 +236,14 @@ <% phase["sections"].each do |section| %>
-

<%= section["title"] %>

+

<%= section.title %>

- <% if section["questions"].any? %> + <% if section.questions.any? %>
    - <% section["questions"].each do |ques|%> + <% section.questions.each do |ques|%>
  • - <%= raw ques["text"] %> + <%= raw ques.text %>
  • <%end%>
@@ -257,29 +257,29 @@ <%end%> <%else%>
- <%= raw plan_data["template"]["description"] %> + <%= raw plan.template.description %>
<% phases.each do |phase| %>
-
" class="accordion-project collapse"> +
<%= link_to _('Answer questions'), edit_plan_path(plan), :class => 'btn btn-primary' %> - -export-dialog" data-toggle="modal" class='btn btn-primary'><%= _('Export') %> + <%= _('Export') %>
- <%= render :partial => "plans/export", locals: {plan: plan, plan_data: plan_data} %> + <%= render :partial => "plans/export", locals: {plan: plan} %>
-

<%= raw phase["description"] %> +

<%= raw phase.description %>

- <% if phase["sections"].any? %> + <% if phase.sections.any? %> @@ -288,17 +288,17 @@ - <% phase["sections"].each do |section| %> + <% phase.sections.each do |section| %>
-

<%= section["title"] %>

+

<%= section.title %>

- <% if section["questions"].any? %> + <% if section.questions.any? %>
    - <% section["questions"].each do |ques|%> + <% section.questions.each do |ques|%>
  • - - <%= raw ques["text"] %> + - <%= raw ques.text %>
  • <%end%>
diff --git a/app/views/plans/_plan_nav_tabs.html.erb b/app/views/plans/_plan_nav_tabs.html.erb index 6c88d98..1c7c168 100644 --- a/app/views/plans/_plan_nav_tabs.html.erb +++ b/app/views/plans/_plan_nav_tabs.html.erb @@ -1,16 +1,17 @@