option_attr parameter for sd_question(), limited to the mc and mc_multiple types. It can be used to define the extra attributes for the designated options with a question mark icon to the right which can be triggered either with hovering or clicking. For example, an mc question might have option = c("option_1, "option_2", "option_3", "option_4"). Then we can give option_attr = c("Attribute 1", NA, "Attribute 3") to define attributes for the 1st and 3rd options.question_id: [1, 2, 3]) failed silently when all shuffled items used indices with no plain question IDs mixed in. Options now shuffle correctly regardless of format.sd_store_value().sd_values() and sd_value() as new approach of accessing question values, replacing the Shiny default input$. sd_values() and sd_value() are able to restore user inputs from db after refreshing the page. They also accept either quoted question IDs or unquoted, so that either sd_value(fruit) or sd_value("fruit") is fine. They also support multiple parameters, which return into a vector of values. For example, sd_value(fruit, vegetable) returns c("apple", "lettuce"). sd_value()is the alias ofsd_values()`, so they function the same.mc, mc_buttons, mc_multiple, and mc_multiple_buttons. Subquestion shuffling supported for matrix. In YAML of survey.qmd, 2 new keys are available: shuffled and all-shuffled. shuffled is used to list the question IDs of these 5 question types to have their options/subquestions randomly shuffled. all-shuffled is by default false and can be set to true to apply shuffling to all questions.question_id: 1-5 means to shuffle the first 5 options of the question, or the first 5 subquestions if it's a matrix question. Other supported syntax: question_id: [1, 2, 4, 7], question_id: [1-5, 8-10]. No indexing means to shuffle all options/subquestions.required-questions and all-questions-required YAML keys are renamed as required and all-required, respectively.required and shuffled both accepting question IDs, and all-required and all-shuffled both accepting true and false.sd_server(), which only supports db as its only parameter. To define survey settings, please only use the YAML header in survey.qmd.sd_question() function no longer has the matrix_option_width parameter. Since the matrix question type only has a question column and an option column, we chose to only keep matrix_question_width to control the question column width. The option column width is defined automatically according to whatever is left. Also, now matrix_question_width is default to NULL, in which case the width is auto-defined according to the length of the longest question. Users can overwrite it by defining matrix_question_width to a specific value, and we support numeric, string, or string with %. For example, it's valid to define matrix_question_width = "40%", = "40", and = 40, all of which result in 40% of width.sd_question(), for example c("Label 1", "Label 2"), will be stored as they are. This is for compatibility with special characters.sd_create_messages() function.textarea questions were being parsed as "unknown" type instead of "textarea", preventing proper restoration when navigating between pages.matrix_question_width and matrix_option_width arguments to sd_question to modify the width of the question and option columns in the type = "matrix" questions.sd_close() so respondents can submit another response with proper cookie handling.theme: [united, custom.scss].barcolor under the theme-settings YAML section to customize the progress bar color, accepting both text color names (over 140 supported by browser CSS) and hex color codes in 3 or 6 digits, e.g. #FF5733 or #F53. If not defined, it shows ~ as the value in settings.yml, indicating it's using the default setting which follows the theme.inst/examples/ directory. Now all exported functions are documented with simple execution showcases, plus a designated template from one of the supported templates.sd_nav() replacing sd_next(), which contains both previous and next buttons.sd_close() now supports addition of previous button as well.sd_question() now supports either option or options. If both are provided, option will be used. When defining option or options, users can now only provide display labels, and the db values will be auto-converted to snake case. For example, sd_question(options = c("Option 1", "Option 2")) will have db values of option_1 and option_2.surveydown now supports previous buttons. Under survey-settings, users can now define show-previous (default to FALSE) to enable previous button globally. In sd_nav(), users can define show_previous being TRUE or FALSE to override the global setting for that specific page.format, echo, and warning in YAML header of survey.qmd anymore. The survey can have a clean start and runs fine without the YAML header.sd_nav() for each page. It's auto-injected unless sd_nav() or sd_close() is explicitly defined in the page with or without parameters.settings.yml content structure with 3 sections: theme-settings, survey-settings, and system-messages. They appear with our without YAML header of survey.qmd and are verbose (meaning all keys and values always appear).surveydown now supports both previous and next buttons, we decided to disable the Enter key for triggering next button to avoid confusion.--- page_id to start a new page, and there is no need to end the page. The previous syntax of starting a page with ::: {.sd_page id=page_id} and ending with ::: still works."auto" mode of sd_db_connect() will correctly detect if gssencmode should be "prefer" or "disable", based on the actual connection status.mc and mc_multiple question types in sd_question() will have their options HTML and markdown compatible.numeric question type input logic.:::) are properly matched in survey.qmd files.sd_server() is called as the last statement in the server function.sd_create_survey() function now obtains survey templates from these new individual repos. The function syntax remains the same.sd_stop_if() function to stop the navigate button if certain conditions cannot be met.sd_skip_forward() function, and reuse sd_stop_if().sd_show_if(), sd_skip_if(), and sd_stop_if()), these judging questions are auto-assigned as required questions.sd_create_survey() to update with the latest templates.sd_store_value() - Now session-persistent with database integration, compatible with local testing. It also saves the value into the server so it matches the database.sd_server() parameters can now be configured in the survey.qmd YAML header (e.g., use_cookies: yes, auto_scroll: no). Parameters in sd_server() take priority over YAML.questions.yml. Now it's fixed by auto-assigning the labels from the values. This auto-assignment is already applied in general cases where option labels are empty.sd_dashboard() function; functionality is now included in the {sdstudio} package.sd_output() with type being "question". Now users can still use sd_output() to display reactive questions with same IDs, but the internal HTML IDs will be different by appending a _question in the end.sd_server(): capture_metadata automatically captures and stores browser information and IP address. Defaults to TRUE.sd_redirect() function used to trigger Shiny Client error of duplicated IDs for input and output. Now it's fixed by adding a unique ID to the button."matrix" question type has better layout."text", "textarea" and "numeric" types could bypass the "required" question check with mouse clicking on their areas. Now it's fixed.gssencmode now has values of "auto", "prefer", and "disable", with "auto" being default.survey.qmd or app.R file.slider, slider_numeric, date, and daterage questions now will be marked as answered without user interaction if the Next/Close button is pushed, and will have their default value saved.mc_buttons and mc_multiple_buttons now can properly save data.sd_question(), "numeric" question type will only allow numeric inputs and +/- signs.sd_server(): highlight_unanswered gives color shading for the unanswered questions, default to TRUE, can be turned off by changing to FALSE.sd_server(): highlight_color changes the shading color, default to "gray" (or "grey" as an acceptable spelling), can be changed to "blue", "orange", "green", or "purple".sd_create_survey() now accepts a new ask argument, defaults to TRUE. If ask = FALSE, the survey creation will proceed without asking.0.11.1 version, sd_show_if() works for pages as well, but it will make sd_skip_forward() totally ignored. Now this is fixed.sd_create_survey() now accepts template as the first argument, and path as the second. This follows intuition that we firstly choose a template, and then define the location.sd_show_if() now works for both questions and pages with the same syntax. Therefore, we also added an ID check for the uniqueness of the page_id and question_id altogether. If there is a duplicated ID, the survey will stop and show an error."questions.yml".yml argument in sd_question(), defaults to "questions.yml", to allow users which yml file to use for questions. For details, refer to the Defining Questions documentation page.sd_create_survey(): now the the template argument is by default "default".sd_create_survey(): new template = "questions_yml" option to create a survey with the questions_yml template.sd_create_survey() now accepts two arguments. The template argument is by default "plain_template", which creates a default plain template of surveydown. It also accepts a list of templates. On our surveydown-dev organization page, there are 14 repos starting with template_, each serving as a survey template. The path argument is unchanged. It defines the relative path of the template location..sd_page id=page_id. The previous structure also works.sd_create_survey()) to match with new recommended page structure.sd_show_password() function entirely (previously was depreciated)usethis packageyesno() function to replace usethis::ui_yeah()sd_dashboard() now accepts an argument of gssencmode, defaults to "prefer". This is same logic as the gssencmode argument in sd_db_connect().sd_dashboard() and sd_db_connect() accepts the gssencmode argument to embrace the different gssencmode situations of the internet connection. It is not embedded into sd_db_config() because gssencmode is not accessible for all connections (some may have NULL). This extra argument for sd_dashboard() and sd_db_connect() can be considered as a work-around.sd_skip_if() function is depreciated and replaced with sd_skip_forward() for clarity of what the function does.sd_skip_if() to be able to use static values and reactive expressions as conditions.sd_show_if() to be able to use static values and reactive expressions as conditions.sd_reactive() function to store reactive values in the data, addressing #179."slider_numeric" type to sd_question(), which supports both single and dual numeric sliders.... argument to all question types in sd_question() so that users can pass other input arguments specific to each input type.gssencmode parameter out of the database settings and made it an argument in sd_db_connect() so that users can pass NULL if needed to completely ignore it when making connections.sd_create_survey() to match the new database configuration introduced in v0.8.0.sd_server(required_questions = "matrix_question").sd_db_config(). Stores database parameters in a local .env file. Replaces sd_set_password() and sd_show_password(), which are now depreciated.sd_db_connect. Replaces older sd_database() function, which is now depreciated.sd_dashboard() that locally runs an interactive shiny app for monitoring data in database.mc_multiple question type could not resume its UI if multiple options are selected. Now it's solved.sd_question_custom() function is created for custom question definition. See the leaflet-map and plotly template surveys for more details.custom type added for sd_question(). Now users can create customized question types according to their own needs. A demo of leaflet map is created as well to showcase this ability.sd_ui() function handles the rendering of the survey.qmd file and extracting the header contents. All surveydown css and js dependencies are loaded via a simple lua filter when rendering. This simplifies how these dependencies get loaded into the resulting shiny app.ignore = TRUE in sd_server() will turn off cookies, regardless of the value of use_cookies.session_id but a complete JSON object of the current page questions, answers, and latest time stamp.data.csv -> preview_data.csv).sd_server() accepts a new argument use_cookies, defaults to TRUE. It enables cookies so that reopening the survey will resume the participant to where the survey was left. The database will trace to the original session_id and continuous the data update based on user input. If changed to FALSE, the survey will start as brand new session upon reopening.preview_data.csv. This file works exactly the same as online database, and is compatible with cookies functionality.sd_server(). You can trigger it by: sd_server(language = "zh-CN").language argument in sd_server(). Custom language messages can be further modified by providing a translations.yml file in the root project folder.sd_create_translations() function to generate a template translations.yml file to use to edit the system messages.ctb)is_matrix metadata was not recorded for matrix sub-questions when exported into the _survey/questions.yml file, which caused an error if any matrix question was required. This is now corrected when obtaining the question structure from the stored _survey/questions.yml file.sd_update() function.sd_deploy() function.sd_output() to now be able to output the chosen question values, chosen question option label(s), and the question label itself. Addresses feature request #128.sd_update() now directly force update the package without checking for version difference anymore.sd_is_answered() function to check if a question is answered or not and returns TRUE or FALSE accordingly. For "matrix" type, only if all sub-questions are answered will it be marked as TRUE.sd_add_question() now has a chunk argument, if TRUE it will include the outer chunk wrapper. Default is FALSE.matrix question type now will have its root question id shown in the data sheet. This id is essential in other logic, for example it can be used as a handle for the sd_show_if() logic. This root id is also removed from the all_question_required logic, since it's only a handle and doesn't provide option to answer.use_html argument in sd_server(). Now the survey.qmd file will always be rendered when the app runs only if one of two conditions are met: 1) the survey.html file is not detected, or 2) the survey.html file is outdated. Otherwise, it will use the rendered survey.html file.auto_scroll now works better and smoother.text, textarea, numeric, select, date, and daterange.auto_scroll changed to FALSE by default.check_skip_show() checks, so you'd get an error that the question id was invalid.sd_server() accepts a new parameter called "rate_survey", default to FALSE. If TRUE, the Exit button will trigger a rating question. If FALSE, the Exit button will only trigger a double confirmation to ensure the user really wants to exit.sd_close() function call.session_id, time_start, time_end, and exit_survey_rating. There could be more in the future.sd_output() function will take care of the styling setting of reactive questions. For example, sd_output(id = "some_question_id", type = "question", width = "80%") will define with of 80% for a reactive question.sd_show_if() can take care of cross-page conditional reactive questions.sd_server() now has a new parameter called auto_scroll. It's default to TRUE, which enables auto scrolling that tracks the user's input, can be turned off by changing to FALSE. Thanks to the contribution from Zain Hoda.sd_question() now has the "matrix" type.sweetalert.sd_completion_code() function.sd_output() with type = 'value' argument. Previously only question values could be displayed in the UI with sd_output().sd_add_question() to instantly create a question template. Defaults to type of "mc" but also accepts all other types ("text", "textarea", "numeric", etc.). The function call will delete itself after running.sd_add_page() to instantly create a page template. Make sure to run this function outside any division or code chunk. The function call will delete itself after running.database_uploading() so only the changed fields get written, and also the writing happens after checking the show_if conditions (addresses #100).refresh_interval argument in sd_get_data() as defaulting to NULL, which means the data will not be reactively fetched, regardless of the context it is used in. The data will only continuously refresh if sd_get_data() is called within a reactive context and refresh_interval > 0.sd_set_password() to not print out user's password and provide clearer instructions.sd_show_password() added to show a stored password. The user will be prompted to double confirm that they want to show it. If there is no password, the user will be prompted so, along with a message of using sd_set_password() to create the password.sd_ui() function to set placeholders for the shiny app ui.skip_if and show_if works, removing skip_if_custom and show_if_custom. Now they work similar to the case_when() function, where you provide the formula condition ~ target for each condition in either function. These are also provided globally inside the server() function using sd_skip_if() and sd_show_if()."survey.qmd".sd_include_folder() function so users can add a folder to the shiny resource path.images, js, css, and www folders as well as folders to quarto files to the shiny resource path when the package loads.sd_next() works to improve page navigation and ensure that each sd_next() button has a unique id based on the current page.sd_create_survey() changed to sourcing template directly from the package. Two parameters are provided. The first parameter is path, which defines the relative path of the target. If left blank, the path will be the current working directory. The second parameter is structure, which defines which structure of the template the user wants to choose, default as "single" and can be changed to "multi".sd_deploy() as a wrapper function of rsconnect::deployApp() to deploy the survey.sd_update() as a replacement of sd_update_surveydown() to update the package.sd_version() as a replacement of sd_check_versions() to check for the current version and the latest version.sd_close() function to create a close button for the survey.<br> above the Next button anymore. The Next buttons can now be in the same chunk as the questions as spacing has been added.sd_store_value(). There used to be a problem if a value is a list with multiple entries. Now they are collapsed with commas due to the application of format_question_value() on the value variable.reactive argument for sd_get_data(). Now all functions that should be compatible with both reactive (server) and static (ui) conditions will automatically match, without necessity of explicitly specifying them.sd_redirect() updated with a parameter called newtab, defaults to FALSE. If TRUE, the redirection link will be opened in a new tab. If used together with delay, the new tab might be blocked by the browser after count-down, but the user click will not be blocked.database_uploading() function to secure it from possible SQL injection attacks.sd_server() for efficiency; converted local data storage to lists instead of data frames.session_id as the leading column, and removed the respondent_id column.sd_redirect() to create redirection to external links, either by providing a button, a countdown, or both. This function can be called both in the survey body and the server chunk.sd_get_url_pars() to reactively get the parameters in the URL.sd_next() and sd_redirect() both support the "Enter" key for a better user experience.sd_database().sd_output() function that replaces the original sd_display_question() (by specifying type = "question") and sd_display_value() (by specifying type = "value"). The original 2 functions are depreciated and will be removed in future updates. If sd_output() is only used with "id" specified, it works the same as shiny::uiOutput().sd_database(), now db_name is changed to dbname, and table_name is changed to table, for consistency with Supabase, and simplicity of parameter names.sd_database() will also prompt "If you have verified all connection details are correct but still cannot access the database, consider setting the gssencmode parameter to "disable" in the sd_database() function." We don't encourage users to disable gssencmode, since it's more secure to have it on, but if users encounter with connection error, this will be a possible solution.sd_server() function in the last update that affected numeric questions being determined as answered or not, that is now fixed.sd_display_value() was used multiple times on different question IDs, it could only fetch the last user input. Now it's fixed.inst/quarto/filters from surveydown.lua to sd_main.lua and updated the extension v0.2.5 to call this via a more robust, cross-platform approach.sd_wrapper.lua to avoid naming conflict. Now the extension is only used as a wrapper. The sd_main.lua and related CSS and JS files are all in the R package.sd_store_value() and sd_copy_value() to the server.R file (these are server operations).respondent_id variable that tracks the respondent based on their starting the survey.jhelvy to surveydown-dev in version control functions.page_id and question_id, the survey will stop and show error.sd_get_data() with a reactive argument to enable reactive data fetching.sd_question() now has a reactive argument to enable reactive questions, and sd_question_reactive() was removed.sd_admin_enable() internal, changed to admin_enable().sd_admin_ui() and sd_add_admin() from the package.SUPABASE_PASSWORD environment variable, but it should be SURVEYDOWN_PASSWORD.sd_get_data() and works.show_if_custom logic was not working for multiple conditions, now it does.skip_if_custom logic could error if a condition was NULL (fixed with isTRUE()).sd_config(), items were being assigned with the <- operator, causing them to be deleted when the thing being assigned was NULL. Now changed to =.sd_display_value() for displaying a question value based on the question id.sd_copy_value() for making a copy of a question value, which may be needed if you need to display something more than once since you can't make more than one object with the same id.sd_reactive_output() to sd_display_question().sd_store_value() works to avoid a global environment, and changed the arg name from name to id.sd_add_admin() function to react to admin_page condition, if set to true an 'Admin' page will be created for survey creators.sd_admin_ui() function to create the UI for the Admin page button..lua file and the css styles.sd_config() as a separate required_questions argument, instead of being defined in sd_question().sd_question_reactive() and sd_reactive_output().sd_store_value() function to store variables into the database. For example, sd_store_value(respondentID, "respID") will store the value of respondentID into a column named "respID". If the name is not provided, the column will be named as its original variable name, in this case, respondentID.timestamp column in the beginning of the result dataframe.sd_database() function added with pause argument default to FALSE. If pause = FALSE, database will be properly connected; if pause = TRUE, a local CSV will be generated and survey results will be stored there.sd_config() function has preview removed due to pause in sd_database.pause = FALSE (aka default), warning messages will be shown for missing or incorrect password, and will prompt the usage of sd_set_password().admin_page argument in config.R.sd_set_password() function to set the supabase password as the survey environment variable. This function takes in a string, which should be your supabase password. We recommend you to only run it in the R Console so that your password does not appear in the .qmd file.sd_set_password(), an .Renviron file will be created in your survey project root directory. In this file, SUPABASE_PASSWORD=your_password will be created, with your_password being whatever your input of sd_set_password(). Then, .Renviron will be added to your .gitignore file to avoid being pushed to GitHub..Renviron file, SUPABASE_PASSWORD=your_password will be concatenated to the end. If there is already a definition of SUPABASE_PASSWORD, it will be overwritten. If there is no .gitignore file, it will be created. If there is already an .Renviron in .gitignore, it won't be duplicated.sd_set_password() once to define supabase password for your survey project. It takes care of the rest of necessary operations, and you can rerun sd_set_password() to change the password, with the previous value safely overwritten.sd_database, a gssencmode argument is added and set to "prefer" by default. In some cases, local deployment may fail due to network environments such as VPN settings. It can be solved by setting gssencmode = "disable" in the survey qmd file.example.qmd survey has instructions for supabase configuration and shinyapps deployment..gitignore file has .Renviron included. This file will store supabase password and is essential for shinyapps deployment. Eliminating this file from pushing to GitHub will ensure that your password is only saved locally.create_survey() changed to sd_create_survey() for function name consistency.sd_update_extension() function to update the surveydown Quarto extension.sd_check_versions() function to check the version of both the R package and the Quarto extension. If any of them don't match with the latest version, there will be a suggestion to run the sd_update_surveydown() function.sd_update_surveydown() function to update both the R package and the Quarto extension.theme command using the bootswatch themes or a custom scss file.backgroundcolor.mc_button and mu_multiple_buttons types of questions are now centered.surveydown::create_survey() function will download the whole extension repo, containing the extension, an example survey, and an RStudio project.show_if can be applied to multiple options of the same question, which allows users to have more than one option in a question that triggers the revealing of a hidden question.required argument in sd_question(), which allows users to force a question to be required. If not answered, a popup window blocks the user from continuing to the next page.Initial version!