diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index def15199f..40a7680bb 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -30,15 +30,8 @@ def tab_list(tabs) '').html_safe end - def next_guides_box(guide, options={}) - return if guide.path.blank? - - suggested = guide.next_guides - if suggested.empty? - t :path_finished, path: link_to_path(guide.path) - else - link_to t(:next_guide, name: suggested.first.name), suggested.first, class: 'btn btn-success' - end + def path_finished(guide) + t :path_finished_html, path: link_to_path(@guide.path) if @guide.path end def corollary_box(with_corollary) diff --git a/app/helpers/concerns/with_navigation.rb b/app/helpers/concerns/with_navigation.rb index 92b7c3290..e500a7e5b 100644 --- a/app/helpers/concerns/with_navigation.rb +++ b/app/helpers/concerns/with_navigation.rb @@ -1,17 +1,13 @@ module WithNavigation def next_button(navigable) - sibling_button(navigable.next_for(current_user), :next_exercise, 'chevron-right', 'btn btn-success', true) + ContinueNavigation.new(self).button(navigable) || RevisitNavigation.new(self).button(navigable) end def next_nav_button(navigable) - sibling_button(navigable.next, :next_exercise, 'chevron-circle-right', 'text-info', true) + ForwardNavigation.new(self).button(navigable) end def previous_nav_button(navigable) - sibling_button(navigable.previous, :previous_exercise, 'chevron-circle-left', 'text-info') - end - - def sibling_button(sibling, key, icon, clazz, right=false) - link_to fa_icon(icon, text: t(key), right: right), sibling, class: clazz if sibling + BackwardNavigation.new(self).button(navigable) end end diff --git a/app/helpers/concerns/with_navigation/anonymous_navigation.rb b/app/helpers/concerns/with_navigation/anonymous_navigation.rb new file mode 100644 index 000000000..6064b72ac --- /dev/null +++ b/app/helpers/concerns/with_navigation/anonymous_navigation.rb @@ -0,0 +1,7 @@ +module WithNavigation + module AnonymousNavigation + def clazz + 'text-info' + end + end +end \ No newline at end of file diff --git a/app/helpers/concerns/with_navigation/backward_navigation.rb b/app/helpers/concerns/with_navigation/backward_navigation.rb new file mode 100644 index 000000000..19874a328 --- /dev/null +++ b/app/helpers/concerns/with_navigation/backward_navigation.rb @@ -0,0 +1,17 @@ +module WithNavigation + class BackwardNavigation < Navigation + include AnonymousNavigation + + def icon + 'chevron-circle-left' + end + + def key + :navigation_previous + end + + def sibling_for(navigable) + navigable.previous + end + end +end \ No newline at end of file diff --git a/app/helpers/concerns/with_navigation/continue_navigation.rb b/app/helpers/concerns/with_navigation/continue_navigation.rb new file mode 100644 index 000000000..b96e0037f --- /dev/null +++ b/app/helpers/concerns/with_navigation/continue_navigation.rb @@ -0,0 +1,23 @@ +module WithNavigation + class ContinueNavigation < Navigation + def right + true + end + + def icon + 'chevron-right' + end + + def key + :navigation_continue + end + + def clazz + 'btn btn-success' + end + + def sibling_for(navigable) + navigable.next_for(current_user) + end + end +end \ No newline at end of file diff --git a/app/helpers/concerns/with_navigation/forward_navigation.rb b/app/helpers/concerns/with_navigation/forward_navigation.rb new file mode 100644 index 000000000..ada3750b4 --- /dev/null +++ b/app/helpers/concerns/with_navigation/forward_navigation.rb @@ -0,0 +1,21 @@ +module WithNavigation + class ForwardNavigation < Navigation + include AnonymousNavigation + + def right + true + end + + def icon + 'chevron-circle-right' + end + + def key + :navigation_next + end + + def sibling_for(navigable) + navigable.next + end + end +end \ No newline at end of file diff --git a/app/helpers/concerns/with_navigation/navigation.rb b/app/helpers/concerns/with_navigation/navigation.rb new file mode 100644 index 000000000..d2a9dda65 --- /dev/null +++ b/app/helpers/concerns/with_navigation/navigation.rb @@ -0,0 +1,24 @@ +module WithNavigation + class Navigation + def initialize(template) + @template = template + end + + def button(navigable) + sibling = sibling_for(navigable) + link_to link_icon(sibling), sibling, class: clazz if sibling && sibling != navigable + end + + def link_icon(sibling) + fa_icon(icon, text: I18n.t(key, sibling: sibling.name), right: right) + end + + def right + false + end + + def method_missing(name, *args, &block) + @template.send(name, *args, &block) + end + end +end \ No newline at end of file diff --git a/app/helpers/concerns/with_navigation/revisit_navigation.rb b/app/helpers/concerns/with_navigation/revisit_navigation.rb new file mode 100644 index 000000000..0322bf7e1 --- /dev/null +++ b/app/helpers/concerns/with_navigation/revisit_navigation.rb @@ -0,0 +1,23 @@ +module WithNavigation + class RevisitNavigation < Navigation + def right + true + end + + def icon + 'chevron-right' + end + + def key + :navigation_revisit + end + + def clazz + 'btn btn-warning' + end + + def sibling_for(navigable) + navigable.first_for(current_user) + end + end +end \ No newline at end of file diff --git a/app/models/concerns/with_exercises.rb b/app/models/concerns/with_exercises.rb index 7368960b1..fdc175ba0 100644 --- a/app/models/concerns/with_exercises.rb +++ b/app/models/concerns/with_exercises.rb @@ -11,7 +11,6 @@ def exercises_count def pending_exercises(user) exercises. - at_locale. joins("left join solutions on solutions.exercise_id = exercises.id and solutions.submitter_id = #{user.id} diff --git a/app/models/concerns/with_guide.rb b/app/models/concerns/with_guide.rb index 70dd0fe75..c64958075 100644 --- a/app/models/concerns/with_guide.rb +++ b/app/models/concerns/with_guide.rb @@ -7,16 +7,8 @@ module WithGuide belongs_to :guide end - def next_for(user) - sibling_for user, 'exercises.position > :position', 'exercises.position asc' - end - - def previous_for(user) - sibling_for user, 'exercises.position < :position', 'exercises.position desc' - end - - def sibling_for(user, query, order) - guide.pending_exercises(user).where(query, position: position).order(order).first if guide + def siblings_for(user) + guide.pending_exercises(user) end def siblings diff --git a/app/models/concerns/with_guides.rb b/app/models/concerns/with_guides.rb index e18331453..1d5290c1c 100644 --- a/app/models/concerns/with_guides.rb +++ b/app/models/concerns/with_guides.rb @@ -5,6 +5,18 @@ module WithGuides has_many :guides, -> { order(:position) } end + def pending_guides(user) + guides. + joins('left join exercises + on exercises.guide_id = guides.id'). + joins("left join solutions + on solutions.exercise_id = exercises.id + and solutions.submitter_id = #{user.id} + and solutions.status = #{Status::Passed.to_i}"). + where('solutions.id is null'). + uniq + end + def first_guide guides.first end diff --git a/app/models/concerns/with_path.rb b/app/models/concerns/with_path.rb index 6fcb50f01..27738e6b2 100644 --- a/app/models/concerns/with_path.rb +++ b/app/models/concerns/with_path.rb @@ -7,11 +7,10 @@ module WithPath belongs_to :path end - def next_guides - path ? siblings.where('guides.position > :position', position: position).order('guides.position asc') : [] + def siblings_for(user) + path.pending_guides(user) end - def siblings path.guides end diff --git a/app/models/concerns/with_siblings.rb b/app/models/concerns/with_siblings.rb index 521594ff5..9b5fc6d3c 100644 --- a/app/models/concerns/with_siblings.rb +++ b/app/models/concerns/with_siblings.rb @@ -13,6 +13,22 @@ def previous siblings.where(position: position - 1).first unless orphan? end + def next_for(user) + sibling_for user, "#{qualified_position} > :position", "#{qualified_position} asc" + end + + def previous_for(user) + sibling_for user, "#{qualified_position} < :position", "#{qualified_position} desc" + end + + def sibling_for(user, query, order) + siblings_for(user).where(query, position: position).order(order).first if parent + end + + def first_for(user) + siblings_for(user).order(position: :asc).first if parent + end + def orphan? parent.nil? end @@ -24,5 +40,11 @@ def contextualized_name name end end + + private + + def qualified_position + "#{self.class.table_name}.position" + end end diff --git a/app/models/exercise.rb b/app/models/exercise.rb index ac75bf0f4..1e895bc2a 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -21,7 +21,6 @@ class Exercise < ActiveRecord::Base acts_as_taggable - enum layout: [:editor_right, :editor_bottom, :no_editor, :scratchy] after_initialize :defaults, if: :new_record? @@ -33,7 +32,6 @@ class Exercise < ActiveRecord::Base markup_on :description, :hint, :teaser, :corollary - def self.create_or_update_for_import!(guide, original_id, options) exercise = find_or_initialize_by(original_id: original_id, guide_id: guide.id) exercise.assign_attributes(options) @@ -75,7 +73,6 @@ def guide_expectations if guide.present? then guide.expectations else [] end end - def generate_custom_slug if guide "#{guide.name}-#{position}-#{name}" diff --git a/app/views/exercise_solutions/_results.html.erb b/app/views/exercise_solutions/_results.html.erb index abbc6c3f9..5824ab184 100644 --- a/app/views/exercise_solutions/_results.html.erb +++ b/app/views/exercise_solutions/_results.html.erb @@ -54,9 +54,8 @@ fa_icon(:bug, text: t(:notify_problem_to_author)), subject: t(:problem_with_exercise, title: solution.exercise.name), class: 'text-warning warning pull-left' %> - <%= next_button(@exercise) %> - <%= next_guides_box(@guide) if @stats.try &:done? %> + <%= next_button(@exercise) || next_button(@guide) %>