Skip to content

Commit

Permalink
rate survey on exit is done
Browse files Browse the repository at this point in the history
  • Loading branch information
pingfan-hu committed Oct 4, 2024
1 parent 7aaaa07 commit afb6e3e
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 46 deletions.
78 changes: 47 additions & 31 deletions R/server.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' @description
#' This function defines the server-side logic for a Shiny application used in surveydown.
#' It handles various operations such as conditional display, progress tracking,
#' page navigation, and database updates for survey responses.
#' page navigation, database updates for survey responses, and exit survey functionality.
#'
#' @param db A list containing database connection information created using
#' \code{\link{sd_database}} function. Defaults to \code{NULL}.
Expand All @@ -16,6 +16,7 @@
#' @param start_page Character string. The ID of the page to start on. Defaults to NULL.
#' @param admin_page Logical. Whether to include an admin page for viewing and downloading survey data. Defaults to `FALSE`.
#' @param auto_scroll Logical. Whether to enable auto-scrolling to the next question after answering. Defaults to TRUE.
#' @param rate_survey Logical. If TRUE, shows a rating question when exiting the survey. If FALSE, shows a simple confirmation dialog. Defaults to FALSE.
#'
#' @import shiny
#' @import shinyWidgets
Expand All @@ -35,6 +36,7 @@
#' \item Sets up admin functionality if enabled in the configuration.
#' \item Controls auto-scrolling behavior based on the `auto_scroll` parameter.
#' \item Uses sweetalert for warning messages when required questions are not answered.
#' \item Handles the exit survey process based on the `rate_survey` parameter.
#' }
#'
#' @section Progress Bar:
Expand All @@ -52,10 +54,9 @@
#' after the current question is answered. This behavior can be disabled by setting
#' `auto_scroll` to FALSE.
#'
#' @section Warning Messages:
#' The function uses sweetalert to display warning messages when users attempt to proceed
#' without answering all required questions. This provides a more user-friendly experience
#' compared to standard Shiny notifications.
#' @section Exit Survey:
#' When `rate_survey` is TRUE, the function will show a rating question when the user attempts to exit the survey.
#' When FALSE, it will show a simple confirmation dialog. The rating, if provided, is saved with the survey data.
#'
#' @return
#' This function does not return a value; it sets up the server-side logic for the Shiny application.
Expand All @@ -69,7 +70,7 @@
#' shinyApp(
#' ui = sd_ui(),
#' server = function(input, output, session) {
#' sd_server(db = db, auto_scroll = TRUE)
#' sd_server(db = db, auto_scroll = TRUE, rate_survey = TRUE)
#' }
#' )
#' }
Expand All @@ -85,7 +86,8 @@ sd_server <- function(
all_questions_required = FALSE,
start_page = NULL,
admin_page = FALSE,
auto_scroll = TRUE
auto_scroll = TRUE,
rate_survey = FALSE
) {

# Get input, output, and session from the parent environment
Expand Down Expand Up @@ -382,45 +384,59 @@ sd_server <- function(
}
})

# Add this new observer for the exit survey modal
# Survey rating ----
# Observer for the exit survey modal
observeEvent(input$show_exit_modal, {
showModal(modalDialog(
title = "Before you go...",
sd_question(
type = 'mc_buttons',
id = 'survey_rating',
label = "Rate your survey experience from 1-poor to 5-excellent.",
option = c(
"1" = "1",
"2" = "2",
"3" = "3",
"4" = "4",
"5" = "5"
if (rate_survey) {
showModal(modalDialog(
title = "Before you go...",
sd_question(
type = 'mc_buttons',
id = 'survey_rating',
label = "Rate your survey experience:<br><small>(from 1-poor to 5-excellent)</small>",
option = c(
"1" = "1",
"2" = "2",
"3" = "3",
"4" = "4",
"5" = "5"
)
),
footer = tagList(
modalButton("Cancel"),
actionButton("submit_rating", "Submit and Exit")
)
),
footer = tagList(
modalButton("Cancel"),
actionButton("submit_rating", "Submit and Exit")
)
))
))
} else {
showModal(modalDialog(
title = "Confirm Exit",
"Are you sure you want to exit the survey?",
footer = tagList(
modalButton("Cancel"),
actionButton("confirm_exit", "Exit")
)
))
}
})

# Add this observer to handle the rating submission
# Observer to handle the rating submission or exit confirmation
observeEvent(input$submit_rating, {
# Save the rating
rating <- input$survey_rating
all_data[['exit_survey_rating']] <- rating
changed_fields(c(changed_fields(), 'exit_survey_rating'))

# Update data immediately
isolate({
update_data(latest_data(), time_last = TRUE)
})

# Close the modal
# Close the modal and the window
removeModal()
session$sendCustomMessage("closeWindow", list())
})

# Send a message to close the window
observeEvent(input$confirm_exit, {
# Close the modal and the window
removeModal()
session$sendCustomMessage("closeWindow", list())
})

Expand Down
40 changes: 25 additions & 15 deletions R/ui.R
Original file line number Diff line number Diff line change
Expand Up @@ -475,31 +475,42 @@ make_next_button_id <- function(page_id) {
return(paste0(page_id, "_next"))
}

#' Create a 'Close' Button to Exit the Survey with Confirmation
#' Create a 'Close' Button to Exit the Survey
#'
#' This function creates a 'Close' button that, when clicked, will prompt for confirmation
#' before attempting to close the current browser tab or window.
#' The button can be activated by clicking or by pressing the Enter key when visible.
#' This function creates a 'Close' button that, when clicked, will trigger the exit process
#' for the survey. Depending on the server-side configuration, this may show a rating question
#' or a simple confirmation dialog before attempting to close the current browser tab or window.
#'
#' @param label Character string. The label of the 'Close' button. Defaults to "Exit Survey".
#' @param confirm_message Character string. The message to display in the confirmation dialog.
#' Defaults to "Are you sure you want to exit the survey?".
#'
#' @details The function generates a Shiny action button that, when clicked, displays a confirmation dialog.
#' If confirmed, it attempts to close the current browser tab or window. Note that for security reasons,
#' some browsers may not allow JavaScript to close windows that were not opened by JavaScript.
#' In such cases, the button will prompt the user to close the tab manually.
#' @return A Shiny tagList containing the 'Close' button UI element and associated JavaScript for the exit process.
#'
#' @details
#' The function generates a Shiny action button that, when clicked, triggers the 'show_exit_modal' event.
#' The server-side logic (controlled by the `rate_survey` parameter in `sd_server()`) determines
#' whether to show a rating question or a simple confirmation dialog.
#'
#' @return A Shiny tagList containing the 'Close' button UI element and associated JavaScript for confirmation.
#' The function also includes a custom message handler for closing the window. This is necessary
#' because some browsers may not allow JavaScript to close windows that were not opened by JavaScript.
#' In such cases, the user will be prompted to close the tab manually.
#'
#' @note The actual behavior of the exit process (whether to show a rating question or not)
#' is controlled by the `rate_survey` parameter in the `sd_server()` function, not in this UI function.
#'
#' @examples
#' \dontrun{
#' # In your UI code:
#' sd_close()
#' sd_close("Exit Survey", "Are you sure you want to exit? Your progress will not be saved.")
#'
#' # With a custom label:
#' sd_close("Finish and Exit")
#' }
#'
#' @seealso \code{\link{sd_server}}
#'
#' @export
sd_close <- function(label = "Exit Survey") {
button_id <- "close-survey-button"

shiny::tagList(
shiny::div(
style = "margin-top: 0.5rem; margin-bottom: 0.5rem;",
Expand All @@ -508,12 +519,11 @@ sd_close <- function(label = "Exit Survey") {
label = label,
class = "sd-enter-button",
style = "display: block; margin: auto;",
onclick = "console.log('Exit button clicked'); Shiny.setInputValue('show_exit_modal', true, {priority: 'event'});"
onclick = "Shiny.setInputValue('show_exit_modal', true, {priority: 'event'});"
)
),
shiny::tags$script(shiny::HTML("
Shiny.addCustomMessageHandler('closeWindow', function(message) {
console.log('Closing window');
window.close();
if (!window.closed) {
alert('Please close this tab manually to exit the survey.');
Expand Down
6 changes: 6 additions & 0 deletions inst/css/surveydown.css
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ div:where(.swal2-container) .swal2-html-container {
padding: 0 2em;
}

/* Exit pop-up */
.modal {
display: block !important;
opacity: 1 !important;
Expand All @@ -304,3 +305,8 @@ div:where(.swal2-container) .swal2-html-container {
.modal-dialog {
z-index: 1050 !important;
}

.modal-body .shiny-input-container .control-label {
text-align: center;
width: 100%;
}

0 comments on commit afb6e3e

Please sign in to comment.