diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb index b93ac76..7fd7078 100644 --- a/app/controllers/phases_controller.rb +++ b/app/controllers/phases_controller.rb @@ -14,65 +14,17 @@ phase_id = params[:id].to_i phase = plan.template.phases.select {|p| p.id == phase_id}.first readonly = !plan.editable_by?(current_user.id) - - # 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.guidance_groups.map{|pgg| pgg.id} - guidance_groups = GuidanceGroup.includes({guidances: :themes}).where(published: true, id: 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.includes(guidances:[:themes]).each do |guidance_group| - guidance_group.guidances.each do |guidance| - if guidance.published - 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 - 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 - + guidance_groups_ids = plan.guidance_groups.collect(&:id) + guidance_groups = GuidanceGroup.where(published: true, id: guidance_groups_ids) + if !user_signed_in? then respond_to do |format| format.html { redirect_to edit_user_registration_path } end - else - render('/phases/edit', locals: { plan: plan, phase: phase, readonly: readonly, question_guidance: question_guidance }) + else + render('/phases/edit', locals: { plan: plan, phase: phase, readonly: readonly, + question_guidance: plan.guidance_by_question_as_hash, + guidance_groups: guidance_groups }) end end diff --git a/app/models/plan.rb b/app/models/plan.rb index 20b5fb3..09224df 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -258,84 +258,87 @@ end end - ## - # returns the guidances associated with the project's organisation, for a specified question - # - # @param question [Question] the question to find guidance for - # @return array of hashes with orgname, themes and the guidance itself - def guidance_for_question(question) - guidances = [] + # Returns all of the plan's available guidance by question as a hash for use on the write plan page + # { + # QUESTION: { + # GUIDANCE_GROUP: { + # THEME: [GUIDANCE, GUIDANCE], + # THEME: [GUIDANCE] + # } + # } + # } + def guidance_by_question_as_hash + # Get all of the selected guidance groups for the plan + guidance_groups_ids = self.guidance_groups.collect(&:id) + guidance_groups = GuidanceGroup.where(published: true, id: guidance_groups_ids) - # add in the guidance for the template org - unless self.template.org.nil? then - self.template.org.guidance_groups.each do |group| - group.guidances.each do |guidance| - common_themes = guidance.themes.all & question.themes.all - if common_themes.length > 0 - guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } + # Gather all of the Themes used in the plan as a hash + # { + # QUESTION: [THEME, THEME], + # QUESTION: [THEME] + # } + question_themes = {} + themes_used = [] + self.questions.joins(:themes).pluck('questions.id', 'themes.title').each do |qt| + themes_used << qt[1] unless themes_used.include?(qt[1]) + question_themes[qt[0]] = [] unless question_themes[qt[0]].present? + question_themes[qt[0]] << qt[1] unless question_themes[qt[0]].include?(qt[1]) + end + + # Gather all of the Guidance available for the themes used in the plan as a hash + # { + # THEME: { + # GUIDANCE_GROUP: [GUIDANCE, GUIDANCE], + # GUIDANCE_GROUP: [GUIDANCE] + # } + # } + theme_guidance = {} + GuidanceGroup.includes(guidances: :themes).joins(:guidances). + where('guidance_groups.published = ? AND guidances.published = ? AND themes.title IN (?) AND guidance_groups.id IN (?)', true, true, themes_used, guidance_groups.collect(&:id)). + pluck('guidance_groups.name', 'themes.title', 'guidances.text').each do |tg| + + theme_guidance[tg[1]] = {} unless theme_guidance[tg[1]].present? + theme_guidance[tg[1]][tg[0]] = [] unless theme_guidance[tg[1]][tg[0]].present? + theme_guidance[tg[1]][tg[0]] << tg[2] unless theme_guidance[tg[1]][tg[0]].include?(tg[2]) + end + + # Generate a hash for the view that contains all of a question guidance + # { + # QUESTION: { + # GUIDANCE_GROUP: { + # THEME: [GUIDANCE, GUIDANCE], + # THEME: [GUIDANCE] + # } + # } + # } + question_guidance = {} + question_themes.keys.each do |question| + ggs = {} + # Gather all of the guidance groups applicable to the themes assigned to the question + groups = [] + question_themes[question].each do |theme| + groups << theme_guidance[theme].keys if theme_guidance[theme].present? + end + + # Loop through all of the applicable guidance groups and collect their themed guidance + groups.flatten.uniq.each do |guidance_group| + guidances_by_theme = {} + + # Collect all of the guidances for each theme used by the question + question_themes[question].each do |theme| + if theme_guidance[theme].present? && theme_guidance[theme][guidance_group].present? + guidances_by_theme[theme] = [] unless guidances_by_theme[theme].present? + guidances_by_theme[theme] = theme_guidance[theme][guidance_group] end end + + ggs[guidance_group] = guidances_by_theme unless ggs[guidance_group] end + + question_guidance[question] = ggs end - - # add in the guidance for the user's org - unless self.owner.nil? - unless self.owner.org.nil? then - self.owner.org.guidance_groups.each do |group| - group.guidances.each do |guidance| - common_themes = guidance.themes.all & question.themes.all - if common_themes.length > 0 - guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } - end - end - end - end - end - - # Get guidance by theme from any guidance groups currently selected - self.guidance_groups.each do |group| - group.guidances.each do |guidance| - common_themes = guidance.themes.all & question.themes.all - if common_themes.length > 0 - guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } - end - end - end - - return guidances - end - - - - - ## - # adds the given guidance to a hash indexed by a passed guidance group and theme - # - # @param guidance_array [{GuidanceGroup => {Theme => Array}}] the passed hash of arrays of guidances. Indexed by GuidanceGroup and Theme. - # @param guidance_group [GuidanceGroup] the guidance_group index of the hash - # @param theme [Theme] the theme object for the GuidanceGroup - # @param guidance [Guidance] the guidance object to be appended to the correct section of the array - # @return [{GuidanceGroup => {Theme => Array}}] the updated object which was passed in - def add_guidance_to_array(guidance_array, guidance_group, theme, guidance) - if guidance_array[guidance_group].nil? then - guidance_array[guidance_group] = {} - end - if theme.nil? then - if guidance_array[guidance_group]["no_theme"].nil? then - guidance_array[guidance_group]["no_theme"] = [] - end - if !guidance_array[guidance_group]["no_theme"].include?(guidance) then - guidance_array[guidance_group]["no_theme"].push(guidance) - end - else - if guidance_array[guidance_group][theme].nil? then - guidance_array[guidance_group][theme] = [] - end - if !guidance_array[guidance_group][theme].include?(guidance) then - guidance_array[guidance_group][theme].push(guidance) - end - end - return guidance_array + + question_guidance end ## diff --git a/app/views/annotations/_show.html.erb b/app/views/annotations/_show.html.erb index 65439aa..b5085f4 100644 --- a/app/views/annotations/_show.html.erb +++ b/app/views/annotations/_show.html.erb @@ -2,11 +2,11 @@ <% if example_answer.present? || guidance.present? %> > <% if example_answer.present? %> -
<%= "#{for_plan ? "#{org} " : ''}#{_('Example answer')}" %>
+
<%= _('Example answer') %>
<%= raw example_answer.text %>
<% end %> <% if guidance.present? %> -
<%= "#{for_plan ? "#{org} " : ''}#{_('Guidance')}" %>
+
<%= _('Guidance') %>
<%= raw guidance.text %>
<% end %> diff --git a/app/views/guidance_groups/_show.html.erb b/app/views/guidance_groups/_show.html.erb index f54e2b3..2238f91 100644 --- a/app/views/guidance_groups/_show.html.erb +++ b/app/views/guidance_groups/_show.html.erb @@ -1,25 +1,40 @@ -<%# locals: { group, theme, question, guidance_accordion_id }%> -
- -
- -
-
- <%= raw group[:text] %> -
-
+
+
+ <% group[theme].each do |guidance| %> + <%= raw guidance %> + <% end %> +
+
+ <% i += 1 %> + <% end %> + \ No newline at end of file diff --git a/app/views/phases/_edit_plan_answers.html.erb b/app/views/phases/_edit_plan_answers.html.erb index e23c7ca..ce5f6d9 100644 --- a/app/views/phases/_edit_plan_answers.html.erb +++ b/app/views/phases/_edit_plan_answers.html.erb @@ -1,4 +1,4 @@ -<%# locals: { plan, phase, readonly, question_guidance } %> +<%# locals: { plan, phase, readonly, question_guidance, guidance_groups } %>
@@ -84,7 +84,7 @@
- <%= render partial: '/phases/guidances_notes', locals: { plan: plan, template: phase.template, question: question, answer: answer, question_guidance: question_guidance } %> + <%= render partial: '/phases/guidances_notes', locals: { plan: plan, template: phase.template, question: question, answer: answer, question_guidance: question_guidance, guidance_groups: guidance_groups } %>
<% end %> diff --git a/app/views/phases/_guidances_notes.html.erb b/app/views/phases/_guidances_notes.html.erb index 7f33c87..85ff945 100644 --- a/app/views/phases/_guidances_notes.html.erb +++ b/app/views/phases/_guidances_notes.html.erb @@ -1,69 +1,91 @@ -<%# locals: { plan, template, question, answer, question_guidance } %> +<%# locals: { plan, template, question, answer, question_guidance, guidance_groups } %> <% annotations = question.annotations.where(type: Annotation.types[:guidance]) %> -<% guidances = question_guidance[question.id] || {} %> -<% guidances_active = annotations.present? || guidances.present? %> -
- - -
-
-
- <%= _('expand all') %> - | - <%= _('collapse all') %> + + <% guidance_accordion_id = 0 %> + <% guidance_set.keys.each do |group| %> + <% obj = guidance_groups.select{ |gg| gg.name == group }.first %> + <% if obj.present? %> +
+ <%= render partial: 'guidance_groups/show', + locals: { group: guidance_set[group], question: question, guidance_accordion_id: guidance_accordion_id } %> + <% guidance_accordion_id += 1 %> + <% i += 1 %>
- -
- - <% num_annotations = 0 %> - <% i = 0 %> - <% if annotations.present? %> - <% annotations.each do |annotation| %> - <%= render partial: 'annotations/show', - locals: { - template: template, - example_answer: (annotation.example_answer? ? annotation : nil), - guidance: (annotation.guidance? ? annotation : nil), - for_plan: true - } %> - <% num_annotations += 1%> - <% i += 1 %> - <% end %> - <% end %> - - <% guidance_accordion_id = num_annotations %> - <% guidances.each_pair do |theme, groups| %> - <% groups.each do |group| %> - <%= render partial: 'guidance_groups/show', - locals: { group: group, theme: theme, question: question, - guidance_accordion_id: guidance_accordion_id } %> - <% guidance_accordion_id += 1 %> - <% i += 1 %> - <% end %> - <% end %> -
-
- <% if plan.present? %> -
- <%= render partial: '/notes/layout', locals: { plan: plan, question: question, answer: answer } %> -
+ <% end %> <% end %> +
+ + <% if plan.present? %> +
+ <%= render partial: '/notes/layout', locals: { plan: plan, question: question, answer: answer } %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/phases/admin_preview.html.erb b/app/views/phases/admin_preview.html.erb index ff2dcbe..b98f0bc 100644 --- a/app/views/phases/admin_preview.html.erb +++ b/app/views/phases/admin_preview.html.erb @@ -19,6 +19,7 @@ <%= render partial: "/org_admin/templates/admin_nav_tabs", locals: { template: @template, active: @phase.id } %> - <%= render partial: '/phases/edit_plan_answers', locals: { plan: nil, phase: @phase, readonly: true, question_guidance: {} } %> + <%= render partial: '/phases/edit_plan_answers', locals: { plan: nil, phase: @phase, readonly: true, question_guidance: {}, + guidance_groups: [] } %> \ No newline at end of file diff --git a/lib/assets/stylesheets/overrides.scss b/lib/assets/stylesheets/overrides.scss index 53550d2..e1d0c01 100644 --- a/lib/assets/stylesheets/overrides.scss +++ b/lib/assets/stylesheets/overrides.scss @@ -86,30 +86,36 @@ /* TABS STYLING */ -.nav-tabs{ +.nav-tabs, .nav-pills { background-color: $grey; color: $white; border: none; margin-right:2px; margin-bottom: 10px; } -.nav-tabs > li > a{ +.nav-tabs > li > a, .nav-pills > li > a { border-radius: 2px; color: $white; } -.nav-tabs > li > a:hover{ +.nav-tabs > li > a:hover, .nav-pills > li > a:hover { background-color: $white; color: $grey; border:1px solid $grey; - border-bottom: none; + border-bottom: 1px solid $white; /* white border prevents tabs from shifting on mouseover/mouseout */ } -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:focus, -.nav-tabs > li.active > a:hover{ +.nav-tabs > li.active > a, .nav-pills >li.active > a, +.nav-tabs > li.active > a:focus, .nav-pills > li.active > a:focus, +.nav-tabs > li.active > a:hover, .nav-pills > li.active > a:hover { background-color: $white !important; color:$grey; border:1px solid $grey; - border-bottom: none; + border-bottom: 1px solid $white; /* white border prevents tabs from shifting on mouseover/mouseout */ +} +.nav-pills > li > a:hover, +.nav-pills > li.active > a, +.nav-pills > li.active > a:focus, +.nav-pills > li.active > a:hover, { + border-bottom: 1px solid $grey; } /* PANEL STYLING */ @@ -125,6 +131,10 @@ background-color: $grey; color: $white; } +.panel-title > a.reverse { + background-color: $white; + color: $grey; +} /* LIST STYLING */ span.sublist { @@ -424,3 +434,4 @@ input { display: inline-block; } strong { margin: 0 10px; } } + diff --git a/test/unit/plan_test.rb b/test/unit/plan_test.rb index 667b649..1099e63 100644 --- a/test/unit/plan_test.rb +++ b/test/unit/plan_test.rb @@ -98,47 +98,26 @@ end # --------------------------------------------------- - test "retrieves the selected guidance for a specific question" do - q = @template.phases.first.sections.first.questions.first - - ['By Template', 'By Org', 'Selected'].each do |txt| - t = Theme.create!(title: "Theme test for - #{txt}") - gg = GuidanceGroup.create!(name: "GuidanceGroup test for - #{txt}", org: @creator.org) - g = Guidance.create!(text: "Guidance test for - #{txt}", guidance_group: gg, themes: [t]) - q = @template.phases.first.sections.first.questions.first - q.themes << t - q.save + test "retrieves the available guidance for a the plan as a hash" do + guidance_groups = GuidanceGroup.includes(guidances: :themes).where(published: true) + @plan.guidance_groups << guidance_groups + @plan.save! + + phase = @template.phases.first + hash = @plan.guidance_by_question_as_hash + + phase.sections.includes(questions: :themes).each do |section| + section.questions.each do |question| + question.themes.each do |theme| + guidance_groups.includes(guidances: :themes).each do |guidance_group| + themed_guidance = guidance_group.guidances.collect{ |g| g.themes.collect(&:title) }.flatten.uniq + if themed_guidance.include?(theme.title) + assert hash[question.id][guidance_group.name][theme.title].length > 0, "expected themed guidance to appear for Question: #{question.id}, GuidanceGroup: #{guidance_group.name} and Theme: #{theme.title}" + end + end + end + end end - - @template.org.guidance_groups << GuidanceGroup.find_by(name: "GuidanceGroup test for - By Template") - @template.org.save - @plan.owner.org.guidance_groups << GuidanceGroup.find_by(name: "GuidanceGroup test for - By Org") - @plan.owner.org.save - @plan.guidance_groups << GuidanceGroup.find_by(name: "GuidanceGroup test for - Selected") - @plan.save - @plan.reload - - gs = @plan.guidance_for_question(q) - - # Template org's themed guidance - hash = gs.select{|h| h[:guidance] == Guidance.find_by(text: "Guidance test for - By Template")}.first - assert_not hash.nil?, "expected to find the guidance by template" - assert hash[:theme].include?("Theme test for - By Template"), "expected to find the theme by template" - - # User org's themed guidance - hash = gs.select{|h| h[:guidance] == Guidance.find_by(text: "Guidance test for - By Org")}.first - assert_not hash.nil?, "expected to find the guidance by org" - assert hash[:theme].include?("Theme test for - By Org"), "expected to find the theme by org" - - # Selected guidance group's guidance - hash = gs.select{|h| h[:guidance] == Guidance.find_by(text: "Guidance test for - Selected")}.first - assert_not hash.nil?, "expected to find the guidance by selected" - assert hash[:theme].include?("Theme test for - Selected"), "expected to find the theme by selected" - end - - # --------------------------------------------------- - test "adds the guidance to a guidance array" do - # TODO: Skipping because the add_guidance_to_array method doesn't seem to be called from anywhere end # ---------------------------------------------------