Show tips when implementing an exercise
This commit is contained in:
@ -262,6 +262,30 @@ class ExercisesController < ApplicationController
|
|||||||
else
|
else
|
||||||
current_user.id
|
current_user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Order of elements is important and will be kept
|
||||||
|
available_tips = ExerciseTip.where(exercise: @exercise)
|
||||||
|
.order(rank: :asc, parent_exercise_tip_id: :asc)
|
||||||
|
|
||||||
|
# Transform result set in a hash and prepare (temporary) children array.
|
||||||
|
# The children array will contain the sorted list of nested tips,
|
||||||
|
# shown for learners in the output sidebar with cards.
|
||||||
|
# Hash - Key: exercise_tip.id, value: exercise_tip Object loaded from database
|
||||||
|
nested_tips = available_tips.each_with_object({}) do |exercise_tip, hash|
|
||||||
|
exercise_tip.children = []
|
||||||
|
hash[exercise_tip.id] = exercise_tip
|
||||||
|
end
|
||||||
|
|
||||||
|
available_tips.each do |tip|
|
||||||
|
# A tip without a parent cannot be a children
|
||||||
|
next if tip.parent_exercise_tip_id.blank?
|
||||||
|
|
||||||
|
# Link tips if they are related
|
||||||
|
nested_tips[tip.parent_exercise_tip_id].children << tip
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return an array with top-level tips
|
||||||
|
@tips = nested_tips.values.select { |tip| tip.parent_exercise_tip_id.nil? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_course_token
|
def set_course_token
|
||||||
|
@ -12,4 +12,4 @@ import hljs from 'highlight.js'
|
|||||||
window.hljs = hljs;
|
window.hljs = hljs;
|
||||||
|
|
||||||
// CSS
|
// CSS
|
||||||
import 'highlight.js/styles/default.css'
|
import 'highlight.js/styles/tomorrow.css'
|
||||||
|
@ -55,6 +55,8 @@ div.h-100 id='output_sidebar_uncollapsed' class='d-none col-sm-12 enforce-bottom
|
|||||||
ul.body
|
ul.body
|
||||||
#output.mt-2
|
#output.mt-2
|
||||||
pre = t('exercises.implement.no_output_yet')
|
pre = t('exercises.implement.no_output_yet')
|
||||||
|
- unless @embed_options[:disable_hints] or @tips.blank?
|
||||||
|
= render(partial: 'tips_content')
|
||||||
- if CodeOcean::Config.new(:code_ocean).read[:flowr][:enabled] && !@embed_options[:disable_hints] && !@embed_options[:hide_test_results]
|
- if CodeOcean::Config.new(:code_ocean).read[:flowr][:enabled] && !@embed_options[:disable_hints] && !@embed_options[:hide_test_results]
|
||||||
#flowrHint.card.text-white.bg-info data-url=CodeOcean::Config.new(:code_ocean).read[:flowr][:url] role='tab'
|
#flowrHint.card.text-white.bg-info data-url=CodeOcean::Config.new(:code_ocean).read[:flowr][:url] role='tab'
|
||||||
.card-header = t('exercises.implement.flowr.heading')
|
.card-header = t('exercises.implement.flowr.heading')
|
||||||
|
13
app/views/exercises/_tips_content.html.slim
Normal file
13
app/views/exercises/_tips_content.html.slim
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
- content_for :head do
|
||||||
|
// Force a full page reload, see https://github.com/turbolinks/turbolinks/issues/326.
|
||||||
|
Otherwise, code might not be highlighted correctly (race condition)
|
||||||
|
meta name='turbolinks-visit-control' content='reload'
|
||||||
|
= javascript_pack_tag('highlight', 'data-turbolinks-track': true)
|
||||||
|
= stylesheet_pack_tag('highlight', media: 'all', 'data-turbolinks-track': true)
|
||||||
|
|
||||||
|
#tips.card.text-white.bg-info.mt-2 role="tab" style="display: block;"
|
||||||
|
.card-header.py-2
|
||||||
|
i.fa.fa-lightbulb
|
||||||
|
= t('exercises.implement.tips.heading')
|
||||||
|
.card-body.text-dark.bg-white.p-2
|
||||||
|
= render(partial: 'tips/collapsed_card', collection: @tips, as: :exercise_tip)
|
24
app/views/tips/_collapsed_card.html.slim
Normal file
24
app/views/tips/_collapsed_card.html.slim
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
- tip = exercise_tip.tip
|
||||||
|
.card.mb-2
|
||||||
|
.card-header.p-2 id="tip-heading-#{exercise_tip.id}" role="tab"
|
||||||
|
.card-title.mb-0
|
||||||
|
a.collapsed aria-controls="tip-collapse-#{exercise_tip.id}" aria-expanded="false" data-parent="#tips" data-toggle="collapse" href="#tip-collapse-#{exercise_tip.id}"
|
||||||
|
.clearfix role="button"
|
||||||
|
i.fa aria-hidden="true"
|
||||||
|
span
|
||||||
|
= t('activerecord.models.tip.one')
|
||||||
|
=< exercise_tip.rank
|
||||||
|
= ": #{tip.title}" if tip.title?
|
||||||
|
.card.card-collapse.collapse id="tip-collapse-#{exercise_tip.id}" aria-labelledby="tip-heading-#{exercise_tip.id}" role="tabpanel"
|
||||||
|
.card-body.p-3
|
||||||
|
h5
|
||||||
|
= t('exercises.implement.tips.description')
|
||||||
|
= tip.description
|
||||||
|
- if tip.example?
|
||||||
|
h5.mt-2
|
||||||
|
= t('exercises.implement.tips.example')
|
||||||
|
pre
|
||||||
|
code.mh-100 class="language-#{tip.file_type.editor_mode.gsub("ace/mode/", "")}"
|
||||||
|
= tip.example
|
||||||
|
.mb-4
|
||||||
|
= render(partial: 'tips/collapsed_card', collection: exercise_tip.children, as: :exercise_tip)
|
@ -125,6 +125,11 @@ de:
|
|||||||
title: Titel
|
title: Titel
|
||||||
description: Beschreibung
|
description: Beschreibung
|
||||||
example: Beispiel
|
example: Beispiel
|
||||||
|
exercise_tip:
|
||||||
|
tip: Tipp
|
||||||
|
exercise: Aufgabe
|
||||||
|
rank: Rang
|
||||||
|
parent_exercise_tip: Übergeordneter Tipp
|
||||||
file_template:
|
file_template:
|
||||||
name: "Name"
|
name: "Name"
|
||||||
file_type: "Dateityp"
|
file_type: "Dateityp"
|
||||||
@ -207,6 +212,9 @@ de:
|
|||||||
study_group:
|
study_group:
|
||||||
one: Lerngruppe
|
one: Lerngruppe
|
||||||
other: Lerngruppen
|
other: Lerngruppen
|
||||||
|
tip:
|
||||||
|
one: Tipp
|
||||||
|
other: Tipps
|
||||||
tag:
|
tag:
|
||||||
one: Tag
|
one: Tag
|
||||||
other: Tags
|
other: Tags
|
||||||
@ -407,6 +415,10 @@ de:
|
|||||||
text: "Uns ist aufgefallen, dass du schon lange an dieser Aufgabe arbeitest. Möchtest du vielleicht später weiter machen um erstmal auf neue Gedanken zu kommen?"
|
text: "Uns ist aufgefallen, dass du schon lange an dieser Aufgabe arbeitest. Möchtest du vielleicht später weiter machen um erstmal auf neue Gedanken zu kommen?"
|
||||||
error_hints:
|
error_hints:
|
||||||
heading: "Hinweise"
|
heading: "Hinweise"
|
||||||
|
tips:
|
||||||
|
heading: Tipps
|
||||||
|
description: Erklärung
|
||||||
|
example: Beispiel
|
||||||
flowr:
|
flowr:
|
||||||
heading: "Weitere Hinweise | Unterstützt von StackOverflow"
|
heading: "Weitere Hinweise | Unterstützt von StackOverflow"
|
||||||
go_to_question: "Lösung ansehen"
|
go_to_question: "Lösung ansehen"
|
||||||
|
@ -122,9 +122,14 @@ en:
|
|||||||
usage: Used
|
usage: Used
|
||||||
difficulty: Share on the Exercise
|
difficulty: Share on the Exercise
|
||||||
tip:
|
tip:
|
||||||
title: title
|
title: Title
|
||||||
description: description
|
description: Description
|
||||||
example: example
|
example: Example
|
||||||
|
exercise_tip:
|
||||||
|
tip: Tip
|
||||||
|
exercise: Exercise
|
||||||
|
rank: Rank
|
||||||
|
parent_exercise_tip: Parent Tip
|
||||||
file_template:
|
file_template:
|
||||||
name: "Name"
|
name: "Name"
|
||||||
file_type: "File Type"
|
file_type: "File Type"
|
||||||
@ -207,6 +212,9 @@ en:
|
|||||||
study_group:
|
study_group:
|
||||||
one: Study Group
|
one: Study Group
|
||||||
other: Study Groups
|
other: Study Groups
|
||||||
|
tip:
|
||||||
|
one: Tip
|
||||||
|
other: Tips
|
||||||
tag:
|
tag:
|
||||||
one: Tag
|
one: Tag
|
||||||
other: Tags
|
other: Tags
|
||||||
@ -407,6 +415,10 @@ en:
|
|||||||
text: "We recognized that you are already working quite a while on this exercise. We would like to encourage you to take a break and come back later."
|
text: "We recognized that you are already working quite a while on this exercise. We would like to encourage you to take a break and come back later."
|
||||||
error_hints:
|
error_hints:
|
||||||
heading: "Hints"
|
heading: "Hints"
|
||||||
|
tips:
|
||||||
|
heading: Tips
|
||||||
|
description: Description
|
||||||
|
example: Example
|
||||||
flowr:
|
flowr:
|
||||||
heading: "Gain more insights here | Powered by StackOverflow"
|
heading: "Gain more insights here | Powered by StackOverflow"
|
||||||
go_to_question: "Go to answer"
|
go_to_question: "Go to answer"
|
||||||
|
Reference in New Issue
Block a user