From a20a75ef6e09c37b9693eea42b88a80529049875 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Fri, 3 Jan 2025 14:39:20 -0500 Subject: [PATCH 1/6] added new question type mc_drag_drop based on sortable (using a forked version as R package sortsurvey -- see https://github.com/saudiwin/sortable_survey). Seems to work pretty well -- see test survey in test_rank_question/ --- DESCRIPTION | 3 +- R/ui.R | 11 +++++ man/sd_question.Rd | 2 + test_rank_question/app.R | 41 +++++++++++++++++ test_rank_question/survey.Rproj | 22 +++++++++ test_rank_question/survey.qmd | 79 +++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 test_rank_question/app.R create mode 100644 test_rank_question/survey.Rproj create mode 100644 test_rank_question/survey.qmd diff --git a/DESCRIPTION b/DESCRIPTION index 9d46dfc3..37af5383 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -52,6 +52,7 @@ Imports: usethis, utils, xml2, - yaml + yaml, + sortsurvey URL: https://pkg.surveydown.org BugReports: https://github.com/surveydown-dev/surveydown/issues diff --git a/R/ui.R b/R/ui.R index 106a6ba3..998d85e4 100644 --- a/R/ui.R +++ b/R/ui.R @@ -228,6 +228,8 @@ extract_head_content <- function(html_content) { #' - "mc_multiple": Multiple choice (multiple selections allowed) #' - "mc_buttons": Multiple choice with button-style options (single selection) #' - "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) +#' - "mc_drag_drop": Multiple choice in which the respondent can reorder the +#' choices using drag and drop (based on the [sortsurvey rank_list_survey question](sortable::rank_list_survey)) #' - "text": Single-line text input #' - "textarea": Multi-line text input #' - "numeric": Numeric input @@ -369,6 +371,15 @@ sd_question <- function( }); ", id, js_interaction)))) + } else if(type == "mc_drag_drop") { + + output <- sortsurvey::rank_list_survey( + input_id = id, + text = label, + labels = list_name_md_to_html(option), + options= sortsurvey::sortable_options(direction = direction) + ) + } else if (type == "text") { output <- shiny::textInput( diff --git a/man/sd_question.Rd b/man/sd_question.Rd index 58c2e96f..cc93f40a 100644 --- a/man/sd_question.Rd +++ b/man/sd_question.Rd @@ -79,6 +79,8 @@ The function supports various question types: \item "mc_multiple": Multiple choice (multiple selections allowed) \item "mc_buttons": Multiple choice with button-style options (single selection) \item "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) +\item "mc_drag_drop": Multiple choice in which the respondent can reorder the +choices using drag and drop (based on the \href{sortable::rank_list_survey}{sortsurvey rank_list_survey question}) \item "text": Single-line text input \item "textarea": Multi-line text input \item "numeric": Numeric input diff --git a/test_rank_question/app.R b/test_rank_question/app.R new file mode 100644 index 00000000..bd515e9a --- /dev/null +++ b/test_rank_question/app.R @@ -0,0 +1,41 @@ +# remotes::install_github("surveydown-dev/surveydown", force = TRUE) +library(surveydown) + +# Database setup + +# surveydown stores data on a database that you define at https://supabase.com/ +# To connect to a database, update the sd_database() function with details +# from your supabase database. For this demo, we set ignore = TRUE, which will +# ignore the settings and won't attempt to connect to the database. This is +# helpful for local testing if you don't want to record testing data in the +# database table. See the documentation for details: +# https://surveydown.org/store-data + +db <- sd_database( + host = "", + dbname = "", + port = "", + user = "", + table = "", + ignore = TRUE +) + + +# Server setup +server <- function(input, output, session) { + + # Define any conditional skip logic here (skip to page if a condition is true) + sd_skip_if() + + # Define any conditional display logic here (show a question if a condition is true) + sd_show_if() + + # Database designation and other settings + sd_server( + db = db + ) + +} + +# shinyApp() initiates your app - don't change it +shiny::shinyApp(ui = sd_ui(), server = server) diff --git a/test_rank_question/survey.Rproj b/test_rank_question/survey.Rproj new file mode 100644 index 00000000..69fafd4b --- /dev/null +++ b/test_rank_question/survey.Rproj @@ -0,0 +1,22 @@ +Version: 1.0 + +RestoreWorkspace: No +SaveWorkspace: No +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes +LineEndingConversion: Posix + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace diff --git a/test_rank_question/survey.qmd b/test_rank_question/survey.qmd new file mode 100644 index 00000000..1fe61d2e --- /dev/null +++ b/test_rank_question/survey.qmd @@ -0,0 +1,79 @@ +--- +echo: false +warning: false +--- + +```{r} +library(surveydown) +``` + +::: {#welcome .sd-page} + +# Welcome to our survey! + +This is a simple demonstration of a surveydown survey. It has two pages with one question on each page. + +Here is a basic "multiple choice" question, created using `type = 'mc'` inside the `sd_question()` function: + +```{r} +sd_question( + type = 'mc', + id = 'penguins', + label = "Which type of penguin do you like the best?", + option = c( + 'Adélie' = 'adelie', + 'Chinstrap' = 'chinstrap', + 'Gentoo' = 'gentoo' + ) +) + +sd_question( + type = 'mc_drag_drop', + id = 'penguins_drag', + label = "Which type of penguin do you like the best?", + option = c( + 'Adélie' = 'adelie', + 'Chinstrap' = 'chinstrap', + 'Gentoo' = 'gentoo' + ) +) + +``` + +You need to insert next buttons with `sd_next()` and set the `next_page` argument to the name of the page you want to go to next. + +```{r} +sd_next(next_page = 'page2') +``` + +::: + +::: {#page2 .sd-page} + +This is another page in your survey. + +{surveydown} supports many types of questions. For example, here is a simple `text` type question: + +```{r} +sd_question( + type = "text", + id = "silly_word", + label = "Write a silly word here:" +) + +sd_next(next_page = 'end') +``` + +::: + +::: {#end .sd-page} + +## End + +This it the last page in the survey. + +```{r} +sd_close("Exit Survey") +``` + +::: From bf63d07f8b6cb029fe38a709a1722cc81a33af88 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Fri, 3 Jan 2025 14:46:08 -0500 Subject: [PATCH 2/6] now using package sortable itself --- DESCRIPTION | 2 +- R/ui.R | 9 ++++++--- man/sd_question.Rd | 2 +- surveydown.Rproj | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 37af5383..f4bd0a8b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -53,6 +53,6 @@ Imports: utils, xml2, yaml, - sortsurvey + sortable URL: https://pkg.surveydown.org BugReports: https://github.com/surveydown-dev/surveydown/issues diff --git a/R/ui.R b/R/ui.R index 998d85e4..a1d4f396 100644 --- a/R/ui.R +++ b/R/ui.R @@ -229,7 +229,7 @@ extract_head_content <- function(html_content) { #' - "mc_buttons": Multiple choice with button-style options (single selection) #' - "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) #' - "mc_drag_drop": Multiple choice in which the respondent can reorder the -#' choices using drag and drop (based on the [sortsurvey rank_list_survey question](sortable::rank_list_survey)) +#' choices using drag and drop based on the [sortable::rank_list] question. #' - "text": Single-line text input #' - "textarea": Multi-line text input #' - "numeric": Numeric input @@ -373,11 +373,14 @@ sd_question <- function( } else if(type == "mc_drag_drop") { - output <- sortsurvey::rank_list_survey( + # uses sortable.js via package sortable to implement drag and drop question + # sortable_options has a lot more options that we can expose + + output <- sortable::rank_list( input_id = id, text = label, labels = list_name_md_to_html(option), - options= sortsurvey::sortable_options(direction = direction) + options= sortable::sortable_options(direction = direction) ) } else if (type == "text") { diff --git a/man/sd_question.Rd b/man/sd_question.Rd index cc93f40a..3a7a3103 100644 --- a/man/sd_question.Rd +++ b/man/sd_question.Rd @@ -80,7 +80,7 @@ The function supports various question types: \item "mc_buttons": Multiple choice with button-style options (single selection) \item "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) \item "mc_drag_drop": Multiple choice in which the respondent can reorder the -choices using drag and drop (based on the \href{sortable::rank_list_survey}{sortsurvey rank_list_survey question}) +choices using drag and drop based on the \link[sortable:rank_list]{sortable::rank_list} question. \item "text": Single-line text input \item "textarea": Multi-line text input \item "numeric": Numeric input diff --git a/surveydown.Rproj b/surveydown.Rproj index fd8dd284..28ddd7ba 100644 --- a/surveydown.Rproj +++ b/surveydown.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: 3cd6a428-6761-4ab1-aa17-b65c2b0d5267 RestoreWorkspace: No SaveWorkspace: No From c76e6c851cf5d788e55e5d23889812101f9b6aa1 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Fri, 3 Jan 2025 15:01:55 -0500 Subject: [PATCH 3/6] had to go back to using port of sortable --- DESCRIPTION | 2 +- R/ui.R | 9 +++------ man/sd_question.Rd | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f4bd0a8b..37af5383 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -53,6 +53,6 @@ Imports: utils, xml2, yaml, - sortable + sortsurvey URL: https://pkg.surveydown.org BugReports: https://github.com/surveydown-dev/surveydown/issues diff --git a/R/ui.R b/R/ui.R index a1d4f396..998d85e4 100644 --- a/R/ui.R +++ b/R/ui.R @@ -229,7 +229,7 @@ extract_head_content <- function(html_content) { #' - "mc_buttons": Multiple choice with button-style options (single selection) #' - "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) #' - "mc_drag_drop": Multiple choice in which the respondent can reorder the -#' choices using drag and drop based on the [sortable::rank_list] question. +#' choices using drag and drop (based on the [sortsurvey rank_list_survey question](sortable::rank_list_survey)) #' - "text": Single-line text input #' - "textarea": Multi-line text input #' - "numeric": Numeric input @@ -373,14 +373,11 @@ sd_question <- function( } else if(type == "mc_drag_drop") { - # uses sortable.js via package sortable to implement drag and drop question - # sortable_options has a lot more options that we can expose - - output <- sortable::rank_list( + output <- sortsurvey::rank_list_survey( input_id = id, text = label, labels = list_name_md_to_html(option), - options= sortable::sortable_options(direction = direction) + options= sortsurvey::sortable_options(direction = direction) ) } else if (type == "text") { diff --git a/man/sd_question.Rd b/man/sd_question.Rd index 3a7a3103..cc93f40a 100644 --- a/man/sd_question.Rd +++ b/man/sd_question.Rd @@ -80,7 +80,7 @@ The function supports various question types: \item "mc_buttons": Multiple choice with button-style options (single selection) \item "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) \item "mc_drag_drop": Multiple choice in which the respondent can reorder the -choices using drag and drop based on the \link[sortable:rank_list]{sortable::rank_list} question. +choices using drag and drop (based on the \href{sortable::rank_list_survey}{sortsurvey rank_list_survey question}) \item "text": Single-line text input \item "textarea": Multi-line text input \item "numeric": Numeric input From 049289b7d76ab63db4510a235ce62500f2b68bd5 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Fri, 3 Jan 2025 17:12:24 -0500 Subject: [PATCH 4/6] need to explicitly import rank_list_survey in order to register it correctlly in shiny file (some inheritance issue) --- NAMESPACE | 1 + R/ui.R | 6 +++--- man/sd_question.Rd | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index a1cfe5bf..75f218de 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -28,3 +28,4 @@ export(sd_skip_if) export(sd_store_value) export(sd_ui) export(sd_version) +importFrom(sortsurvey,rank_list_survey) diff --git a/R/ui.R b/R/ui.R index 998d85e4..47580635 100644 --- a/R/ui.R +++ b/R/ui.R @@ -229,7 +229,7 @@ extract_head_content <- function(html_content) { #' - "mc_buttons": Multiple choice with button-style options (single selection) #' - "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) #' - "mc_drag_drop": Multiple choice in which the respondent can reorder the -#' choices using drag and drop (based on the [sortsurvey rank_list_survey question](sortable::rank_list_survey)) +#' choices using drag and drop based on the sortsurvey rank_list_survey question (see [sortsurvey::rank_list_survey()]) #' - "text": Single-line text input #' - "textarea": Multi-line text input #' - "numeric": Numeric input @@ -270,7 +270,7 @@ extract_head_content <- function(html_content) { #' # Clean up #' setwd(orig_dir) #' } -#' +#' @importFrom sortsurvey rank_list_survey #' @export sd_question <- function( type, @@ -373,7 +373,7 @@ sd_question <- function( } else if(type == "mc_drag_drop") { - output <- sortsurvey::rank_list_survey( + output <- rank_list_survey( input_id = id, text = label, labels = list_name_md_to_html(option), diff --git a/man/sd_question.Rd b/man/sd_question.Rd index cc93f40a..babe8966 100644 --- a/man/sd_question.Rd +++ b/man/sd_question.Rd @@ -80,7 +80,7 @@ The function supports various question types: \item "mc_buttons": Multiple choice with button-style options (single selection) \item "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) \item "mc_drag_drop": Multiple choice in which the respondent can reorder the -choices using drag and drop (based on the \href{sortable::rank_list_survey}{sortsurvey rank_list_survey question}) +choices using drag and drop based on the sortsurvey rank_list_survey question (see \code{\link[sortsurvey:rank_list_survey]{sortsurvey::rank_list_survey()}}) \item "text": Single-line text input \item "textarea": Multi-line text input \item "numeric": Numeric input @@ -119,5 +119,4 @@ if (interactive()) { # Clean up setwd(orig_dir) } - } From 4b480f11caca4096008eaf2216d3a7fc80ebb161 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Tue, 7 Jan 2025 11:49:44 -0500 Subject: [PATCH 5/6] have bucket list working (but not in sd_question) and renamed questions to rank_list and bucket_list --- NAMESPACE | 1 + R/config.R | 2 +- R/ui.R | 26 +++++++++++++++++++++--- man/sd_question.Rd | 4 +++- test_rank_question/survey.qmd | 37 +++++++++++++++++++++++++++++++++-- 5 files changed, 63 insertions(+), 7 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 75f218de..7410c368 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -28,4 +28,5 @@ export(sd_skip_if) export(sd_store_value) export(sd_ui) export(sd_version) +importFrom(sortsurvey,bucket_list_survey) importFrom(sortsurvey,rank_list_survey) diff --git a/R/config.R b/R/config.R index 4fe777c1..6ef876a7 100644 --- a/R/config.R +++ b/R/config.R @@ -319,7 +319,7 @@ extract_question_structure_html <- function(html_content) { ) # Extract options for the question ( mc, *_multiple, *_buttons, and select) - if (grepl("radio|checkbox|select|matrix", type)) { + if (grepl("radio|checkbox|select|matrix|list", type)) { options <- question_node |> rvest::html_nodes("input[type='radio'], input[type='checkbox'], option") |> rvest::html_attr("value") diff --git a/R/ui.R b/R/ui.R index 47580635..dbe70626 100644 --- a/R/ui.R +++ b/R/ui.R @@ -228,8 +228,10 @@ extract_head_content <- function(html_content) { #' - "mc_multiple": Multiple choice (multiple selections allowed) #' - "mc_buttons": Multiple choice with button-style options (single selection) #' - "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) -#' - "mc_drag_drop": Multiple choice in which the respondent can reorder the +#' - "rank_list": Multiple choice in which the respondent can reorder the #' choices using drag and drop based on the sortsurvey rank_list_survey question (see [sortsurvey::rank_list_survey()]) +#' - "bucket_list": Multiple choice options which the respondent can put into two +#' different buckets based on the sortsurvey bucket_list_survey question (see [sortsurvey::bucket_list_survey()]) #' - "text": Single-line text input #' - "textarea": Multi-line text input #' - "numeric": Numeric input @@ -270,7 +272,7 @@ extract_head_content <- function(html_content) { #' # Clean up #' setwd(orig_dir) #' } -#' @importFrom sortsurvey rank_list_survey +#' @importFrom sortsurvey rank_list_survey bucket_list_survey #' @export sd_question <- function( type, @@ -371,7 +373,7 @@ sd_question <- function( }); ", id, js_interaction)))) - } else if(type == "mc_drag_drop") { + } else if(type == "rank_list") { output <- rank_list_survey( input_id = id, @@ -380,6 +382,24 @@ sd_question <- function( options= sortsurvey::sortable_options(direction = direction) ) + } else if (type=="bucket_list") { + + bucket_list_survey( + header = label, + group_name = id, + add_rank_list( + text = "Drag from here", + labels = list_name_md_to_html(option) + ), + add_rank_list( + text = "to here", + labels = NULL + ),output_width="100%", + output_height="100%", + options= sortsurvey::sortable_options(direction = direction), + # NOTE: direction doesn't seem to work in bucket list questions + orientation=direction) + } else if (type == "text") { output <- shiny::textInput( diff --git a/man/sd_question.Rd b/man/sd_question.Rd index babe8966..b25151f3 100644 --- a/man/sd_question.Rd +++ b/man/sd_question.Rd @@ -79,8 +79,10 @@ The function supports various question types: \item "mc_multiple": Multiple choice (multiple selections allowed) \item "mc_buttons": Multiple choice with button-style options (single selection) \item "mc_multiple_buttons": Multiple choice with button-style options (multiple selections allowed) -\item "mc_drag_drop": Multiple choice in which the respondent can reorder the +\item "rank_list": Multiple choice in which the respondent can reorder the choices using drag and drop based on the sortsurvey rank_list_survey question (see \code{\link[sortsurvey:rank_list_survey]{sortsurvey::rank_list_survey()}}) +\item "bucket_list": Multiple choice options which the respondent can put into two +different buckets based on the sortsurvey bucket_list_survey question (see \code{\link[sortsurvey:bucket_list_survey]{sortsurvey::bucket_list_survey()}}) \item "text": Single-line text input \item "textarea": Multi-line text input \item "numeric": Numeric input diff --git a/test_rank_question/survey.qmd b/test_rank_question/survey.qmd index 1fe61d2e..e9aea8b7 100644 --- a/test_rank_question/survey.qmd +++ b/test_rank_question/survey.qmd @@ -5,6 +5,7 @@ warning: false ```{r} library(surveydown) +library(sortsurvey) ``` ::: {#welcome .sd-page} @@ -28,9 +29,9 @@ sd_question( ) sd_question( - type = 'mc_drag_drop', + type = 'rank_list', id = 'penguins_drag', - label = "Which type of penguin do you like the best?", + label = "Which type of penguin do you like the best? Rank them from best to worst.", option = c( 'Adélie' = 'adelie', 'Chinstrap' = 'chinstrap', @@ -38,8 +39,40 @@ sd_question( ) ) + + ``` +# Bucket list style: + +```{r} + +# add in drag and drop question +# horizontal method doesn't seem to work regardless of what width/height is +# set to + +# DOES NOT WORK: input id is only set for bucket top class, +# need to set two other input IDs for rank_list objects + +# see function bucket_list_survey in sortsurvey https://github.com/saudiwin/sortable_survey/blob/main/R/bucket_list.R +# and add_rank_list in sortable: https://rstudio.github.io/sortable/reference/add_rank_list.html + +sd_question( + type = 'bucket_list', + id = 'penguins_bucket', + label = "Which type of penguin do you like the best? Drag those penguins to the second bucket.", + option = c( + 'Adélie' = 'adelie', + 'Chinstrap' = 'chinstrap', + 'Gentoo' = 'gentoo' + ) + +) + + +``` + + You need to insert next buttons with `sd_next()` and set the `next_page` argument to the name of the page you want to go to next. ```{r} From 53006b47ae7f6654998a6078ea95567149a863d7 Mon Sep 17 00:00:00 2001 From: Bob Kubinec Date: Fri, 9 May 2025 15:39:30 -0400 Subject: [PATCH 6/6] update description --- DESCRIPTION | 1 - 1 file changed, 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 418d8b4d..869cb8d3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -51,7 +51,6 @@ Imports: shinyWidgets, utils, xml2, - dragdrop yaml, sortsurvey URL: https://pkg.surveydown.org