diff --git a/app/controllers/exercise_solutions_controller.rb b/app/controllers/exercise_solutions_controller.rb index a39b7028e..8c44efa5d 100644 --- a/app/controllers/exercise_solutions_controller.rb +++ b/app/controllers/exercise_solutions_controller.rb @@ -4,6 +4,8 @@ class ExerciseSolutionsController < AjaxController include Mumuki::Laboratory::Controllers::ExerciseSeed before_action :set_messages, only: :create + before_action :set_guide!, only: :create + before_action :set_stats!, only: :create before_action :validate_accessible!, only: :create def create @@ -27,4 +29,12 @@ def solution_params client_result: params[:client_result].try { |it| it.permit(:status, test_results: [:title, :status, :result, :summary]).to_h } } end + + def set_guide! + @guide = @exercise.guide + end + + def set_stats! + @stats = @guide.stats_for(current_user) + end end diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index b38dd4616..9de8d7057 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -1,10 +1,13 @@ class ExercisesController < ApplicationController + before_action :set_parents!, only: :show + include Mumuki::Laboratory::Controllers::Content include Mumuki::Laboratory::Controllers::ExerciseSeed include Mumuki::Laboratory::Controllers::ImmersiveNavigation - before_action :set_guide!, only: :show + before_action :set_progress!, only: :show, if: :current_user? before_action :set_assignment!, only: :show, if: :current_user? + before_action :validate_accessible!, only: :show before_action :start!, only: :show @@ -20,15 +23,15 @@ def show_transparently private def subject - @exercise ||= Exercise.find_by(id: params[:id]) + @exercise ||= Exercise.find(params[:id]) end def accessible_subject - subject.navigable_parent + @navigable_parent end def start! - @exercise.navigable_parent.start! current_user + @navigable_parent.start! current_user end def set_assignment! @@ -38,9 +41,13 @@ def set_assignment! @default_content = @assignment.default_content end - def set_guide! - raise Mumuki::Domain::NotFoundError if @exercise.nil? + def set_parents! @guide = @exercise.guide + @navigable_parent = @exercise.navigable_parent + end + + def set_progress! + @assignments, @stats = @guide.assignments_and_stats_for(current_user) end def exercise_params @@ -50,4 +57,12 @@ def exercise_params :guide_id, :number, :layout, :expectations_yaml) end + + + def subject_used_here? + # overriden because of performance reasons + # this method will be called only on show, so it is safe + # to check for navigable_parent presence + @navigable_parent.present? + end end diff --git a/app/helpers/breadcrumbs_helper.rb b/app/helpers/breadcrumbs_helper.rb index 56bbb8642..04e581c25 100644 --- a/app/helpers/breadcrumbs_helper.rb +++ b/app/helpers/breadcrumbs_helper.rb @@ -2,7 +2,9 @@ module BreadcrumbsHelper include DiscussionsHelper def breadcrumbs(e, extra=nil) - breadcrumbs0(e.navigable_name, e, extra, 'last') + Rails.cache.fetch [:breadcrumb, e, extra, Organization.current] do + breadcrumbs0(e.navigable_name, e, extra, 'last') + end end def header_breadcrumbs(link_for_organization: true) diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 0c92b68c5..fe0523a14 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -7,9 +7,9 @@ def fixed_fa_icon(name, options = {}) fa_icon name, options.merge(class: 'fa-fw fixed-icon') end - def exercise_status_icon(exercise) - link_to exercise_status_fa_icon(exercise), - exercise_path(exercise) if current_user? + def assignment_status_icon(assignment) + link_to contextualization_fa_icon(assignment), + exercise_path(assignment.exercise) if current_user? end def language_icon(language) @@ -22,10 +22,6 @@ def contextualization_fa_icon(contextualization) fa_icon(*icon_for(contextualization)) end - def exercise_status_fa_icon(exercise) - contextualization_fa_icon(exercise.assignment_for(current_user)) - end - def discussion_status_fa_icon(discussion) contextualization_fa_icon(discussion) end @@ -35,10 +31,6 @@ def icon_for(iconizable) [iconized[:type], class: "text-#{iconized[:class]} status-icon"] end - def class_for_exercise(exercise) - icon_class_for(exercise.assignment_for(current_user)) - end - def icon_class_for(iconizable) iconizable.iconize[:class].to_s end diff --git a/app/helpers/links_helper.rb b/app/helpers/links_helper.rb index b8d2a1ee7..c24d36d04 100644 --- a/app/helpers/links_helper.rb +++ b/app/helpers/links_helper.rb @@ -1,8 +1,10 @@ module LinksHelper def link_to_path_element(element, options={}) - name = extract_name element, options - link_to name, element, options + mode = options[:mode] + Rails.cache.fetch [:link, element, mode, Organization.current] do + link_to extract_name(element, mode), element + end end def link_to_error_404 @@ -65,15 +67,8 @@ def turbolinks_enable_for(exercise) private - def extract_name(named, options) - case options.delete(:mode) - when :plain - named.name - when :friendly - named.friendly - else - named.navigable_name - end + def extract_name(named, mode ) + mode == :plain ? named.name : named.navigable_name end def edit_link_to_bibliotheca diff --git a/app/helpers/progress_bar_helper.rb b/app/helpers/progress_bar_helper.rb index 3346715f4..3dc7be052 100644 --- a/app/helpers/progress_bar_helper.rb +++ b/app/helpers/progress_bar_helper.rb @@ -1,8 +1,8 @@ module ProgressBarHelper include IconsHelper - def class_for_progress_list_item(exercise, active) - "progress-list-item text-center #{class_for_exercise(exercise)} #{active ? 'active' : ''}" + def class_for_progress_list_item(assignment, active) + "progress-list-item text-center #{icon_class_for(assignment)} #{active ? 'active' : ''}" end end diff --git a/app/views/chapters/show.html.erb b/app/views/chapters/show.html.erb index d8ab2bf48..4a3dfb514 100644 --- a/app/views/chapters/show.html.erb +++ b/app/views/chapters/show.html.erb @@ -26,9 +26,9 @@

<%= t(:lessons) %>

- <% @chapter.lessons.each do |lesson| %> + <% @chapter.lessons.includes(guide: :exercises).each do |lesson| %>

<%= lesson.number %>. <%= link_to_path_element lesson, mode: :plain %>

- <%= render partial: 'layouts/progress_listing', locals: { exercises: lesson.exercises } %> + <%= render partial: 'layouts/progress_listing', locals: { guide: lesson.guide } %> <% end %>
<% end %> diff --git a/app/views/exercise_solutions/_results.html.erb b/app/views/exercise_solutions/_results.html.erb index bb4a343fe..1090b8339 100644 --- a/app/views/exercise_solutions/_results.html.erb +++ b/app/views/exercise_solutions/_results.html.erb @@ -1,8 +1,3 @@ -<% - @guide = @exercise.guide - @stats = @guide.stats_for(current_user) -%> - <% if assignment.results_hidden? %> <%= render partial: 'exercise_solutions/results_hidden', locals: {assignment: assignment} %> <% elsif !assignment.attempts_left? %> diff --git a/app/views/exercises/show.html.erb b/app/views/exercises/show.html.erb index 9f7cf09e6..4b5340f92 100644 --- a/app/views/exercises/show.html.erb +++ b/app/views/exercises/show.html.erb @@ -6,10 +6,8 @@ <%= render partial: 'layouts/authoring', locals: {guide: @guide} %> -<% @stats = @exercise.stats_for(current_user) %> - -<% if @exercise.navigable_parent.timed? && !current_user.teacher? %> - <%= render partial: 'layouts/timer', locals: {end_time: @exercise.navigable_parent.real_end_time(current_user)} %> +<% if @navigable_parent.timed? && !current_user.teacher? %> + <%= render partial: 'layouts/timer', locals: {end_time: @navigable_parent.real_end_time(current_user)} %> <% end %> <% unless @exercise.input_kids? %> @@ -29,9 +27,7 @@ <% end %>
- <% if @stats && standalone_mode? %> - <%= render partial: 'layouts/progress_bar', locals: {actual: @exercise, guide: @exercise.guide, stats: @stats} %> - <% end %> + <%= render partial: 'layouts/progress_bar' if current_user? && standalone_mode? %>
<% content_for :assignment do %> @@ -65,6 +61,6 @@ <%= render partial: 'layouts/modals/level_up' %> <% end %> - <%= render partial: 'layouts/modals/guide_corollary', locals: {guide: @guide} %> + <%= render partial: 'layouts/modals/guide_corollary', locals: {guide: @guide} if @stats.almost_done? %> <%= render partial: 'layouts/modals/new_message', locals: {exercise: @exercise} if should_render_message_input?(@exercise) %> <% end if current_user? %> diff --git a/app/views/layouts/_guide.html.erb b/app/views/layouts/_guide.html.erb index 4726ac48e..925e665e0 100644 --- a/app/views/layouts/_guide.html.erb +++ b/app/views/layouts/_guide.html.erb @@ -2,7 +2,7 @@ <%= render partial: 'layouts/authoring', locals: {guide: @guide} %> -<% if subject.timed? && subject.started?(current_user) && !current_user.teacher? %> +<% if subject.timed? && @stats.started? && !current_user.teacher? %> <%= render partial: 'layouts/timer', locals: {end_time: subject.real_end_time(current_user)} %> <% end %> @@ -10,10 +10,10 @@

<%= t :exercises %> - <%= restart_guide_link(@guide) if current_user && @guide.started?(current_user) && @guide.resettable? %> + <%= restart_guide_link(@guide) if current_user && @stats.started? && @guide.resettable? %>

-<%= render partial: 'layouts/progress_listing', locals: {exercises: @guide.exercises} %> +<%= render partial: 'layouts/progress_listing', locals: { guide: @guide } %> <% if @stats&.done? %>
diff --git a/app/views/layouts/_progress_bar.html.erb b/app/views/layouts/_progress_bar.html.erb index 3e499cf4c..d98313e1c 100644 --- a/app/views/layouts/_progress_bar.html.erb +++ b/app/views/layouts/_progress_bar.html.erb @@ -1,12 +1,15 @@
- <% guide.exercises.each do |e| %> - - href="<%= exercise_path(e)%>" - aria-label="<%= e.navigable_name %>" - title="<%= e.navigable_name %>" - data-mu-exercise-id="<%= e.id %>" - class="<%= class_for_progress_list_item(e, e == actual)%>"> - + <% @assignments.each do |assignment| %> + <% exercise = assignment.exercise %> + <% cache [:progress_list_item, exercise, assignment.status, Organization.current, exercise == @exercise] do %> + + href="<%= exercise_path(exercise)%>" + aria-label="<%= exercise.navigable_name %>" + title="<%= exercise.navigable_name %>" + data-mu-exercise-id="<%= exercise.id %>" + class="<%= class_for_progress_list_item(assignment, exercise == @exercise)%>"> + + <% end %> <% end %> -
+
\ No newline at end of file diff --git a/app/views/layouts/_progress_listing.html.erb b/app/views/layouts/_progress_listing.html.erb index d0bace21b..d7d32e225 100644 --- a/app/views/layouts/_progress_listing.html.erb +++ b/app/views/layouts/_progress_listing.html.erb @@ -1,10 +1,17 @@ diff --git a/lib/mumuki/laboratory/controllers/content.rb b/lib/mumuki/laboratory/controllers/content.rb index 31921f335..480d0a81b 100644 --- a/lib/mumuki/laboratory/controllers/content.rb +++ b/lib/mumuki/laboratory/controllers/content.rb @@ -7,6 +7,10 @@ module Mumuki::Laboratory::Controllers::Content # ensures contents are in current organization's path def validate_used_here! #TODO refactor subject logic (e.g. we can't move validate_accessible! here because ExerciseSolutionsController does not declare a subject) - raise Mumuki::Domain::NotFoundError unless subject&.used_in?(Organization.current) + raise Mumuki::Domain::NotFoundError unless subject_used_here? + end + + def subject_used_here? + subject&.used_in?(Organization.current) end end diff --git a/lib/mumuki/laboratory/controllers/results_rendering.rb b/lib/mumuki/laboratory/controllers/results_rendering.rb index b2b8dec4a..97172d5f8 100644 --- a/lib/mumuki/laboratory/controllers/results_rendering.rb +++ b/lib/mumuki/laboratory/controllers/results_rendering.rb @@ -3,8 +3,6 @@ module Mumuki::Laboratory::Controllers::ResultsRendering included do include ProgressBarHelper, ExerciseInputHelper - - before_action :set_guide_previously_done! end def render_results_json(assignment, results = {}) @@ -56,10 +54,7 @@ def render_results_button(assignment) end def guide_finished_by_solution? - !@guide_previously_done && @exercise.guide_done_for?(current_user) + @stats.almost_but_not_done? && @exercise.guide_done_for?(current_user) end - def set_guide_previously_done! - @guide_previously_done = @exercise.guide_done_for?(current_user) - end end diff --git a/mumuki-laboratory.gemspec b/mumuki-laboratory.gemspec index 4c7612867..82246dad7 100644 --- a/mumuki-laboratory.gemspec +++ b/mumuki-laboratory.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.add_dependency "rails", "~> 5.1.6" - s.add_dependency 'mumuki-domain', '~> 8.3.0' + s.add_dependency 'mumuki-domain', '~> 8.4.0' s.add_dependency 'mumukit-bridge', '~> 4.1' s.add_dependency 'mumukit-login', '~> 7.3' s.add_dependency 'mumukit-nuntius', '~> 6.1' diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 40f638bb8..df36d3105 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -482,6 +482,7 @@ t.datetime "legal_terms_accepted_at" t.datetime "forum_terms_accepted_at" t.boolean "banned_from_forum" + t.boolean "uppercase_mode" t.index ["avatar_type", "avatar_id"], name: "index_users_on_avatar_type_and_avatar_id" t.index ["disabled_at"], name: "index_users_on_disabled_at" t.index ["last_organization_id"], name: "index_users_on_last_organization_id" diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index c67da7a59..5411723ee 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -17,7 +17,6 @@ before { reindex_current_organization! } it { expect(link_to_path_element(exercise, mode: :plain)).to eq 'foo3' } - it { expect(link_to_path_element(exercise, mode: :friendly)).to eq 'C1: bar - foo3' } it { expect(link_to_path_element(exercise)).to eq '3. foo3' } end