Skip to content

Commit

Permalink
Merge branch 'master' into rc-v0.10.0
Browse files Browse the repository at this point in the history
* master:
  Do not reset question submissions (#270)
  only display visible output in exercise (#268)
  • Loading branch information
schloerke committed Aug 7, 2019
2 parents ee55d4c + d06e6a9 commit 97ccd5d
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ learnr 0.10.0 (unreleased)

* Missing package dependencies will ask to be installed at tutorial run time. (@isteves, [#253](https://github.com/rstudio/learnr/issues/253))

* When questions are tried again, the existing answer will remain, not forcing the user to restart from scratch. ([#270](https://github.com/rstudio/learnr/issues/270))


## Bug fixes

Expand Down
53 changes: 45 additions & 8 deletions R/exercise.R
Original file line number Diff line number Diff line change
Expand Up @@ -237,15 +237,20 @@ evaluate_exercise <- function(exercise, envir) {
# only has one argument, only visible values are handled; if it has more
# arguments, the second argument indicates whether the value is visible.
last_value <- NULL
last_value_is_visible <- TRUE
default_output_handler <- evaluate::new_output_handler()
has_visible_arg <- length(formals(default_output_handler$value)) > 1
learnr_output_handler <- evaluate::new_output_handler(value = function(x, visible) {
last_value <<- x

last_value_is_visible <<- visible
if (has_visible_arg) {
default_output_handler$value(x, visible)
} else {
default_output_handler$value(x)
if (visible) {
default_output_handler$value(x)
} else {
invisible()
}
}
})

Expand Down Expand Up @@ -321,7 +326,8 @@ evaluate_exercise <- function(exercise, envir) {
return(error_result("Error occured while parsing chunk option 'exercise.checker'."))
}

if (is.null(exercise$check) || is.null(checker))
checker_fn_does_not_exist <- is.null(exercise$check) || is.null(checker)
if (checker_fn_does_not_exist)
checker <- function(...) { NULL }

# call the checker
Expand All @@ -348,14 +354,33 @@ evaluate_exercise <- function(exercise, envir) {
feedback_validated(checker_feedback)

# amend output with feedback as required
if (!is.null(checker_feedback)) {
feedback_html <- feedback_as_html(checker_feedback)
if (checker_feedback$location == "append")
feedback_html <-
if (!is.null(checker_feedback)) {
feedback_as_html(checker_feedback)
} else {
NULL
}

if (
# if the last value was invisible
!last_value_is_visible &&
# if the checker function exists
!checker_fn_does_not_exist
) {
# works with NULL feedback
feedback_html <- htmltools::tagList(feedback_html, invisible_feedback())
}

if (!is.null(feedback_html)) {
# if no feedback, append invisible_feedback
feedback_location <- checker_feedback$location %||% "append"
if (feedback_location == "append") {
html_output <- htmltools::tagList(html_output, feedback_html)
else if (checker_feedback$location == "prepend")
} else if (feedback_location == "prepend") {
html_output <- htmltools::tagList(feedback_html, html_output)
else if (checker_feedback$location == "replace")
} else if (feedback_location == "replace") {
html_output <- feedback_html
}
}

# return a list with the various results of the expression
Expand All @@ -380,6 +405,18 @@ error_result <- function(error_message) {
html_output = error_message_html(error_message)
)
}
invisible_feedback <- function() {
feedback_as_html(
feedback_validated(
list(
message = "Last value being used to check answer is invisible. See `?invisible` for more information",
type = "warning",
correct = FALSE,
location = "append"
)
)
)
}

timeout_error_message <- function() {
paste("Error: Your code ran longer than the permitted time",
Expand Down
10 changes: 8 additions & 2 deletions R/quiz.R
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,10 @@ question_module_server_impl <- function(
if (is.null(submitted_answer())) {
# has not submitted, show regular answers
return(
question_ui_initialize(question, submitted_answer())
# if there is an existing input$answer, display it.
# if there is no answer... init with NULL
# Do not re-render the UI for every input$answer change
question_ui_initialize(question, isolate(input$answer))
)
}

Expand Down Expand Up @@ -526,7 +529,10 @@ question_module_server_impl <- function(
observeEvent(input$action_button, {

if (button_type() == "try_again") {
init_question(NULL)
# maintain current submission / do not randomize answer order
# only reset the submitted answers
# does NOT reset input$answer
submitted_answer(NULL)

# submit "reset" to server
reset_question_submission_event(
Expand Down

0 comments on commit 97ccd5d

Please sign in to comment.