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 @@
+
\ 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 @@
- <% exercises.each do |exercise| %>
- <% cache [exercise, exercise.status_for(current_user), Organization.current] do %>
- - >
- <%= exercise_status_icon exercise %>
- <%= link_to_path_element(exercise) %>
-
- <% end %>
+ <%
+ assignments = guide.assignments_for(current_user)
+ statuses = assignments.map(&:status)
+ %>
+ <% cache_if statuses.chunk_while(&:==).count <= 2, [guide, statuses, Organization.current] do %>
+ <% assignments.each do |assignment| %>
+ <% cache [assignment.exercise, assignment.status, Organization.current] do %>
+ - >
+ <%= assignment_status_icon assignment %>
+ <%= link_to_path_element(assignment.exercise) %>
+
+ <% end %>
+ <% end %>
<% end %>
+
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