├── .gitignore ├── DESCRIPTION ├── Dockerfile ├── NAMESPACE ├── R ├── app_server.R ├── app_ui.R ├── fct_code.R ├── fct_themes.R ├── mod_00_info.R ├── mod_11_whatIsShiny.R ├── mod_12_understandingReactivity.R ├── mod_13_usingReactivity.R ├── mod_14_controllingReactivity.R ├── mod_15_appStructure.R ├── mod_16_shinyModules.R ├── mod_21_usingCSS.R ├── mod_22_usingJS.R ├── mod_23_attaliverse.R ├── mod_24_extendingShiny.R ├── mod_25_customInputs.R ├── mod_31_sessionObject.R ├── mod_32_trackingUsage.R ├── mod_33_visualisationPlotly.R ├── mod_34_visualisationR2D3.R ├── mod_35_errorHandling.R ├── mod_36_optimisation.R ├── mod_40_references.R ├── mod_x_template.R ├── run_app.R └── widget_treant.R ├── README.Rmd ├── README.md ├── TODO.md ├── app.R ├── inst ├── app │ ├── global.R │ ├── server.R │ ├── ui.R │ └── www │ │ ├── .sass_cache_keys │ │ ├── advancedShiny.ico │ │ ├── clipboard.min.js │ │ ├── d3 │ │ ├── folder.js │ │ ├── reactive_graph.css │ │ ├── reactive_graph.js │ │ ├── reactive_graph_data.json │ │ └── treelist_data.json │ │ ├── gif │ │ ├── debounced_input$num.gif │ │ ├── raw_input$num.gif │ │ └── throttled_input$num.gif │ │ ├── img │ │ ├── advancedShiny.png │ │ ├── complex_reactlog_1.png │ │ ├── complex_reactlog_2.png │ │ ├── folder.png │ │ ├── html_css_inspected.png │ │ ├── rockets.png │ │ ├── shiny_dependencies.png │ │ ├── simple_app_luxtheme.png │ │ ├── simple_app_notheme.png │ │ └── simple_reactlog.png │ │ ├── initiate_clipboard.js │ │ ├── styling.css │ │ └── styling.scss ├── conversion_staging.R ├── htmlwidgets │ ├── lib │ │ └── Treant-1.0.0 │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── Treant.css │ │ │ ├── Treant.js │ │ │ ├── build │ │ │ ├── jquery.easing.js │ │ │ ├── jquery.min.js │ │ │ ├── jquery.mousewheel.js │ │ │ ├── package.json │ │ │ ├── perfect-scrollbar.css │ │ │ ├── perfect-scrollbar.js │ │ │ └── raphael.js │ ├── treant.js │ └── treant.yaml └── static │ ├── advancedShiny_hex.png │ ├── app-status-badge.png │ ├── app-status-badge.svg │ ├── pkg-version-badge.png │ └── pkg-version-badge.svg ├── man ├── add_snippet.Rd ├── app_server.Rd ├── app_ui.Rd ├── code_block.Rd ├── code_snippet.Rd ├── get_shinydashboard_theme.Rd ├── hello.Rd ├── node.Rd ├── run_IAS_app.Rd ├── tab_appStructure_server.Rd ├── tab_appStructure_ui.Rd ├── tab_attaliverse_server.Rd ├── tab_attaliverse_ui.Rd ├── tab_controllingReactivity_server.Rd ├── tab_controllingReactivity_ui.Rd ├── tab_customInputs_server.Rd ├── tab_customInputs_ui.Rd ├── tab_errorHandling_server.Rd ├── tab_errorHandling_ui.Rd ├── tab_extendingShiny_server.Rd ├── tab_extendingShiny_ui.Rd ├── tab_info_server.Rd ├── tab_info_ui.Rd ├── tab_modCCx_server.Rd ├── tab_modCCx_ui.Rd ├── tab_optimisation_server.Rd ├── tab_optimisation_ui.Rd ├── tab_references_server.Rd ├── tab_references_ui.Rd ├── tab_sessionObject_server.Rd ├── tab_sessionObject_ui.Rd ├── tab_shinyModules_server.Rd ├── tab_shinyModules_ui.Rd ├── tab_trackingUsage_server.Rd ├── tab_trackingUsage_ui.Rd ├── tab_understandingReactivity_server.Rd ├── tab_understandingReactivity_ui.Rd ├── tab_usingCSS_server.Rd ├── tab_usingCSS_ui.Rd ├── tab_usingJS_server.Rd ├── tab_usingJS_ui.Rd ├── tab_usingReactivity_server.Rd ├── tab_usingReactivity_ui.Rd ├── tab_visualisationPlotly_server.Rd ├── tab_visualisationPlotly_ui.Rd ├── tab_visualisationR2D3_server.Rd ├── tab_visualisationR2D3_ui.Rd ├── tab_whatIsShiny_server.Rd ├── tab_whatIsShiny_ui.Rd ├── treant-shiny.Rd └── treant.Rd ├── references.txt ├── renv.lock └── renv ├── .gitignore ├── activate.R └── settings.dcf /.gitignore: -------------------------------------------------------------------------------- 1 | *.Rproj 2 | .Rproj.user 3 | .Rprofile 4 | .Rhistory 5 | .RData 6 | .Rbuildignore 7 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: advancedShiny 2 | Type: Package 3 | Title: Demonstrating Intermediate & Advanced Shiny Methods 4 | Version: 0.0.1 5 | Authors@R: 6 | c( 7 | person("Chris", "Brownlie", email = "christopher.brownlie@education.gov.uk", role = c("aut", "cre")) 8 | ) 9 | Description: Package containing an R Shiny app which is initially being developed for 10 | DfE's Coffee & Coding sessions. It aims to showcase some intermediate and advanced R 11 | Shiny concepts & methods and will be used both to accompany the presentations as well 12 | as for reference after the fact. 13 | License: MIT + file LICENSE 14 | Encoding: UTF-8 15 | RoxygenNote: 7.1.1 16 | Imports: 17 | shiny, 18 | shinydashboard, 19 | shinydashboardPlus, 20 | shinyjs, 21 | htmltools, 22 | htmlwidgets, 23 | r2d3, 24 | pkgload, 25 | rjson 26 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openanalytics/r-base 2 | 3 | LABEL maintainer "Chris Brownlie " 4 | 5 | # system libraries of general use 6 | RUN apt-get update && apt-get install -y \ 7 | sudo \ 8 | pandoc \ 9 | pandoc-citeproc \ 10 | libcurl4-gnutls-dev \ 11 | libcairo2-dev \ 12 | libxt-dev \ 13 | libssl-dev \ 14 | libssh2-1-dev \ 15 | libssl1.0.0 16 | 17 | # basic shiny functionality 18 | RUN R -e "install.packages(c('shiny', 'rmarkdown'), repos='https://cloud.r-project.org/')" 19 | 20 | # install dependencies of the euler app 21 | RUN R -e "install.packages(c('shinydashboard', 'shinydashboardPlus', 'shinyjs', 'htmltools', 'htmlwidgets', 'r2d3', 'pkgload', 'rjson'), repos='https://cloud.r-project.org/')" 22 | 23 | # copy the app to the image 24 | RUN mkdir /root/advancedShiny 25 | COPY advancedShiny /root/advancedShiny 26 | 27 | COPY Rprofile.site /usr/lib/R/etc/ 28 | 29 | EXPOSE 3838 30 | 31 | CMD ["R", "-e", "shiny::runApp('/root/advancedShiny')"] -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(code_block) 4 | export(code_snippet) 5 | export(get_shinydashboard_theme) 6 | export(l) 7 | export(node) 8 | export(renderTreant) 9 | export(run_IAS_app) 10 | export(tab_appStructure_server) 11 | export(tab_appStructure_ui) 12 | export(tab_attaliverse_server) 13 | export(tab_attaliverse_ui) 14 | export(tab_controllingReactivity_server) 15 | export(tab_controllingReactivity_ui) 16 | export(tab_customInputs_server) 17 | export(tab_customInputs_ui) 18 | export(tab_errorHandling_server) 19 | export(tab_errorHandling_ui) 20 | export(tab_extendingShiny_server) 21 | export(tab_extendingShiny_ui) 22 | export(tab_info_server) 23 | export(tab_info_ui) 24 | export(tab_modCCx_server) 25 | export(tab_modCCx_ui) 26 | export(tab_optimisation_server) 27 | export(tab_optimisation_ui) 28 | export(tab_references_server) 29 | export(tab_references_ui) 30 | export(tab_sessionObject_server) 31 | export(tab_sessionObject_ui) 32 | export(tab_shinyModules_server) 33 | export(tab_shinyModules_ui) 34 | export(tab_trackingUsage_server) 35 | export(tab_trackingUsage_ui) 36 | export(tab_understandingReactivity_server) 37 | export(tab_understandingReactivity_ui) 38 | export(tab_usingCSS_server) 39 | export(tab_usingCSS_ui) 40 | export(tab_usingJS_server) 41 | export(tab_usingJS_ui) 42 | export(tab_usingReactivity_server) 43 | export(tab_usingReactivity_ui) 44 | export(tab_visualisationPlotly_server) 45 | export(tab_visualisationPlotly_ui) 46 | export(tab_visualisationR2D3_server) 47 | export(tab_visualisationR2D3_ui) 48 | export(tab_whatIsShiny_server) 49 | export(tab_whatIsShiny_ui) 50 | export(treant) 51 | export(treantOutput) 52 | import(htmltools) 53 | importFrom(shiny,column) 54 | importFrom(shiny,fluidRow) 55 | importFrom(shiny,icon) 56 | importFrom(shiny,runApp) 57 | importFrom(shiny,shinyAppDir) 58 | importFrom(shinydashboardPlus,box) 59 | -------------------------------------------------------------------------------- /R/app_server.R: -------------------------------------------------------------------------------- 1 | #' Server function for the advancedShiny app 2 | app_server <- function(input, output, session) { 3 | 4 | # Create a reactiveValues object to act as the app's data store. This will 5 | # be passed to all modules. It is a reactiveValues object so any changes will 6 | # instantly be visible to all modules. It has the same uses as the session$userData 7 | # environment, but this method is preferred as it is more explicit. 8 | appData <- reactiveValues() 9 | 10 | 11 | # Call the module server for each tab 12 | tab_info_server("info", 13 | appData = appData) 14 | 15 | # Section 1 - How shiny works 16 | tab_whatIsShiny_server("whatIsShiny", 17 | appData = appData) 18 | 19 | tab_understandingReactivity_server("understandingReactivity", 20 | appData = appData) 21 | 22 | tab_usingReactivity_server("usingReactivity", 23 | appData = appData) 24 | 25 | tab_controllingReactivity_server("controllingReactivity", 26 | appData = appData) 27 | 28 | tab_appStructure_server("appStructure", 29 | appData = appData) 30 | 31 | tab_shinyModules_server("shinyModules", 32 | appData = appData) 33 | 34 | # Section 2 - Making it pretty 35 | tab_usingCSS_server("usingCSS", 36 | appData = appData) 37 | 38 | tab_usingJS_server("usingJS", 39 | appData = appData) 40 | 41 | tab_attaliverse_server("attaliverse", 42 | appData = appData) 43 | 44 | tab_extendingShiny_server("extendingShiny", 45 | appData = appData) 46 | 47 | tab_customInputs_server("customInputs", 48 | appData = appData) 49 | 50 | # Section 3 - Improvements & Analytics 51 | tab_sessionObject_server("sessionObject", 52 | appData = appData) 53 | 54 | tab_trackingUsage_server("trackingUsage", 55 | appData = appData) 56 | 57 | tab_visualisationPlotly_server("visualisationPlotly", 58 | appData = appData) 59 | 60 | tab_visualisationR2D3_server("visualisationR2D3", 61 | appData = appData) 62 | 63 | tab_errorHandling_server("errorHandling", 64 | appData = appData) 65 | 66 | tab_optimisation_server("optimisation", 67 | appData = appData) 68 | 69 | # Section 4 - References 70 | tab_references_server("references", 71 | appData = appData) 72 | 73 | } 74 | -------------------------------------------------------------------------------- /R/app_ui.R: -------------------------------------------------------------------------------- 1 | #' UI for the advancedShiny app 2 | app_ui <- function() { 3 | 4 | # Convert the Sass styling sheet to CSS so it can be called in dashboardBody below 5 | sass::sass( 6 | sass::sass_file(system.file("app/www/styling.scss", package = "advancedShiny")), 7 | output = system.file("app/www/styling.css", package = "advancedShiny") 8 | ) 9 | 10 | # Header definition 11 | header <- shinydashboardPlus::dashboardHeader(title = span("advancedShiny", tags$img(src = "img/rockets.png", height = 50), class = "sidebar-title")) 12 | 13 | # Sidebar definition 14 | sidebar <- shinydashboard::dashboardSidebar( 15 | shinydashboard::sidebarMenu( 16 | 17 | id = "sidebar_nav", 18 | 19 | shinydashboard::menuItem( 20 | "About this app", 21 | tabName = "0_about_this_app" 22 | ), 23 | 24 | # Section 1 'How Shiny Works' 25 | shinydashboard::menuItem( 26 | "1 - How shiny works", 27 | tabName = "1_how_shiny_works", 28 | startExpanded = TRUE, 29 | 30 | shinydashboard::menuSubItem( 31 | "1.1 - What is shiny, actually?", 32 | tabName = "1_1_what_is_shiny" 33 | ), 34 | 35 | shinydashboard::menuSubItem( 36 | "1.2 - Understanding reactivity", 37 | tabName = "1_2_understanding_reactivity" 38 | ), 39 | 40 | shinydashboard::menuSubItem( 41 | "1.3 - Using reactivity", 42 | tabName = "1_3_using_reactivity" 43 | ), 44 | 45 | shinydashboard::menuSubItem( 46 | "1.4 - Controlling reactivity", 47 | tabName = "1_4_controlling_reactivity" 48 | ), 49 | 50 | shinydashboard::menuSubItem( 51 | "1.5 - Structuring an app", 52 | tabName = "1_5_structuring_an_app" 53 | ), 54 | 55 | shinydashboard::menuSubItem( 56 | "1.6 - Shiny modules", 57 | tabName = "1_6_shiny_modules" 58 | ) 59 | ), 60 | 61 | # Section 2 'Making it pretty' 62 | shinydashboard::menuItem( 63 | "2 - Making it pretty", 64 | tabName = "2_making_it_pretty", 65 | startExpanded = TRUE, 66 | 67 | shinydashboard::menuSubItem( 68 | "2.1 - Improving UI with CSS", 69 | tabName = "2_1_improving_ui_with_css" 70 | ), 71 | 72 | shinydashboard::menuSubItem( 73 | "2.2 - Improving UX with JS", 74 | tabName = "2_2_improving_ux_with_js" 75 | ), 76 | 77 | shinydashboard::menuSubItem( 78 | "2.3 - The attali-verse", 79 | tabName = "2_3_the_attali_verse" 80 | ), 81 | 82 | shinydashboard::menuSubItem( 83 | "2.4 - Extending shiny", 84 | tabName = "2_4_extending_shiny" 85 | ), 86 | 87 | shinydashboard::menuSubItem( 88 | "2.5 - Custom shiny inputs", 89 | tabName = "2_5_custom_shiny_inputs" 90 | ) 91 | ), 92 | 93 | # Section 3 'Improvements & Graphics' 94 | shinydashboard::menuItem( 95 | "3 - Improvements & Graphics", 96 | tabName = "3_improvements_and_graphics", 97 | startExpanded = TRUE, 98 | 99 | shinydashboard::menuSubItem( 100 | "3.1 - The session object", 101 | tabName = "3_1_the_session_object" 102 | ), 103 | 104 | shinydashboard::menuSubItem( 105 | "3.2 - Tracking usage", 106 | tabName = "3_2_tracking_usage" 107 | ), 108 | 109 | shinydashboard::menuSubItem( 110 | "3.3 - Advanced viz 1 (plotly)", 111 | tabName = "3_3_advanced_vis_1_plotly" 112 | ), 113 | 114 | shinydashboard::menuSubItem( 115 | "3.4 - Advanced viz 2 (r2d3)", 116 | tabName = "3_4_advanced_vis_2_r2d3" 117 | ), 118 | 119 | shinydashboard::menuSubItem( 120 | "3.5 - Error handling & debugging", 121 | tabName = "3_5_error_handling_and_debugging" 122 | ), 123 | 124 | shinydashboard::menuSubItem( 125 | "3.6 - Optimisation", 126 | tabName = "3_6_optimisation" 127 | ) 128 | ), 129 | 130 | # References & Materials 131 | shinydashboard::menuItem( 132 | "References & Further Materials", 133 | tabName = "4_references" 134 | ) 135 | 136 | ) 137 | ) 138 | 139 | # Body definition 140 | body <- shinydashboard::dashboardBody( 141 | 142 | tags$head( 143 | 144 | # Include custom CSS 145 | tags$link(href = "styling.css", rel = "stylesheet", type = "text/css"), 146 | tags$link(rel = "shortcut icon", href = "advancedShiny.ico") 147 | ), 148 | 149 | # Use custom dashboard theme designed using fresh (see R/fct_themes.R) 150 | fresh::use_theme(get_shinydashboard_theme()), 151 | 152 | # Include shinyjs and custom extensions 153 | shinyjs::useShinyjs(), 154 | 155 | # Include clipboard.js for copying code snippets 156 | tags$script(src = "clipboard.min.js"), # clipboard.js 157 | tags$script(src = "initiate_clipboard.js"), # custom clipboard function 158 | 159 | # Call each module UI which will contain the definition for each tab 160 | shinydashboard::tabItems( 161 | 162 | # Section 0 - the landing page 163 | shinydashboard::tabItem( 164 | "0_about_this_app", 165 | tab_info_ui("info") 166 | ), 167 | 168 | # Section 1 - How Shiny Works 169 | shinydashboard::tabItem( 170 | "1_1_what_is_shiny", 171 | tab_whatIsShiny_ui("whatIsShiny") 172 | ), 173 | 174 | shinydashboard::tabItem( 175 | "1_2_understanding_reactivity", 176 | tab_understandingReactivity_ui("understandingReactivity") 177 | ), 178 | 179 | shinydashboard::tabItem( 180 | "1_3_using_reactivity", 181 | tab_usingReactivity_ui("usingReactivity") 182 | ), 183 | 184 | shinydashboard::tabItem( 185 | "1_4_controlling_reactivity", 186 | tab_controllingReactivity_ui("controllingReactivity") 187 | ), 188 | 189 | shinydashboard::tabItem( 190 | "1_5_structuring_an_app", 191 | tab_appStructure_ui("appStructure") 192 | ), 193 | 194 | shinydashboard::tabItem( 195 | "1_6_shiny_modules", 196 | tab_shinyModules_ui("shinyModules") 197 | ), 198 | 199 | 200 | # Section 2 - Making it pretty 201 | shinydashboard::tabItem( 202 | "2_1_improving_ui_with_css", 203 | tab_usingCSS_ui("usingCSS") 204 | ), 205 | 206 | shinydashboard::tabItem( 207 | "2_2_improving_ux_with_js", 208 | tab_usingJS_ui("usingJS") 209 | ), 210 | 211 | shinydashboard::tabItem( 212 | "2_3_the_attali_verse", 213 | tab_attaliverse_ui("attaliverse") 214 | ), 215 | 216 | shinydashboard::tabItem( 217 | "2_4_extending_shiny", 218 | tab_extendingShiny_ui("extendingShiny") 219 | ), 220 | 221 | shinydashboard::tabItem( 222 | "2_5_custom_shiny_inputs", 223 | tab_customInputs_ui("customInputs") 224 | ), 225 | 226 | # Section 3 - Improvements & Analytics 227 | shinydashboard::tabItem( 228 | "3_1_the_session_object", 229 | tab_sessionObject_ui("sessionObject") 230 | ), 231 | 232 | shinydashboard::tabItem( 233 | "3_2_tracking_usage", 234 | tab_trackingUsage_ui("trackingUsage") 235 | ), 236 | 237 | shinydashboard::tabItem( 238 | "3_3_advanced_vis_1_plotly", 239 | tab_visualisationPlotly_ui("visualisationPlotly") 240 | ), 241 | 242 | shinydashboard::tabItem( 243 | "3_4_advanced_vis_2_r2d3", 244 | tab_visualisationR2D3_ui("visualisationR2D3") 245 | ), 246 | 247 | shinydashboard::tabItem( 248 | "3_5_error_handling_and_debugging", 249 | tab_errorHandling_ui("errorHandling") 250 | ), 251 | 252 | shinydashboard::tabItem( 253 | "3_6_optimisation", 254 | tab_optimisation_ui("optimisation") 255 | ), 256 | 257 | shinydashboard::tabItem( 258 | "4_references", 259 | tab_references_ui("references") 260 | ) 261 | 262 | 263 | ) 264 | 265 | ) 266 | 267 | 268 | # Combine elements to create UI 269 | ui <- shinydashboardPlus::dashboardPage(title = "advancedShiny", 270 | header = header, 271 | sidebar = sidebar, 272 | body = body) 273 | 274 | # Return the ui 275 | ui 276 | } -------------------------------------------------------------------------------- /R/fct_code.R: -------------------------------------------------------------------------------- 1 | #' Include code snippets 2 | #' 3 | #' Generate formatted markdown with a copy to clipboard button to allow users to 4 | #' copy code to their clipboard. 5 | #' 6 | #' @param vec a character vector of code (one element per line) to be shown 7 | #' 8 | #' @return a HTML string which can be inserted directly into the UI of the app, showing the 9 | #' code as a formatted snippet along with a 'Copy' button 10 | #' 11 | #' @export 12 | code_snippet <- function(vec) { 13 | HTML( 14 | paste0('
',
15 |          paste(vec, collapse = "\n"),
16 |          '',
17 |          '
21 |          
') 22 | ) 23 | } 24 | 25 | #' Convert code to code snippet 26 | #' 27 | #' @param script the R script to convert to a code snippet 28 | #' 29 | #' @return inserts the code necessary as a code snippet below the current selection 30 | add_snippet <- function(script = system.file("conversion_staging.R", package = "advancedShiny")) { 31 | 32 | code <- readLines(script) 33 | 34 | snippet <- paste0('code_snippet(c("', paste(code, collapse = '",\n"'), '")\n)') 35 | 36 | rstudioapi::insertText(text = snippet) 37 | } 38 | 39 | #' Render code i.e. package (or function) name 40 | #' 41 | #' Renders either a package name (as italics and formatted as code) or a function (formatted as code), 42 | #' optionally include a link 43 | #' 44 | #' @param code the text to be formatted 45 | #' @param pkg logical, if TRUE the output text will be italicised (representing a package name). If FALSE it 46 | #' won't be italicised (representing a function name or arbitrary R code). 47 | #' @param href optional link to include 48 | #' 49 | #' @return a HTML string which can be inserted directly into the UI of the app, showing the 50 | #' code as formatted, (potentially) clickable text 51 | #' 52 | #' @import htmltools 53 | #' 54 | #' @export 55 | code_block <- function(string, 56 | pkg = FALSE, 57 | href = NULL, 58 | noWS = NULL) { 59 | if (length(href)) { 60 | if(pkg) { 61 | tags$a(tags$i(tags$code(string)), href = href, .noWS = noWS) 62 | } else { 63 | tags$a(tags$code(string), href = href, .noWS = noWS) 64 | } 65 | } else { 66 | if (pkg) { 67 | tags$i(tags$code(string), .noWS = noWS) 68 | } else { 69 | tags$code(string, .noWS = noWS) 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /R/fct_themes.R: -------------------------------------------------------------------------------- 1 | #' Custom shinydashboard theme 2 | #' 3 | #' Customise some visual elements of the dashboard using the *fresh* package. 4 | #' This function returns a theme which is passed to use_theme, in the dashboardBody 5 | #' element of the UI. 6 | #' 7 | #' @return a shinydashboard theme created using fresh::create_theme 8 | #' 9 | #' @export 10 | get_shinydashboard_theme <- function() { 11 | 12 | fresh::create_theme( 13 | fresh::adminlte_color( 14 | light_blue = "#434C5E" 15 | ), 16 | fresh::adminlte_sidebar( 17 | width = "300px" 18 | ), 19 | fresh::adminlte_global( 20 | content_bg = "#FFF", 21 | box_bg = "#D8DEE9", 22 | info_box_bg = "#D8DEE9" 23 | ) 24 | ) 25 | 26 | } 27 | -------------------------------------------------------------------------------- /R/mod_00_info.R: -------------------------------------------------------------------------------- 1 | #' Info module 2 | 3 | #' Info module UI 4 | #' 5 | #' Defines the UI for the Info module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @import htmltools 12 | #' @importFrom shinydashboardPlus box 13 | #' @importFrom shiny fluidRow column icon 14 | #' 15 | #' @export 16 | tab_info_ui <- function(id) { 17 | 18 | ns <- NS(id) 19 | 20 | tagList( 21 | h3("Info", 22 | class = "tab-title"), 23 | fluidRow( 24 | column( 25 | width = 8, 26 | box( 27 | title = "Purpose of this app", 28 | solidHeader = TRUE, 29 | width = NULL, 30 | icon = icon("info-circle"), 31 | status = "info", 32 | 33 | p("This app is designed to introduce beginner and intermediate R Shiny users to some more advanced concepts, techniques and methods.", 34 | "The initial goal is for this app to serve as a tutorial and cheatsheet for shiny and hopefully introduce R developers in the 35 | department to some new shiny solutions and possibilities."), 36 | 37 | p("This project will", tags$b("not"), "cover every single thing that R Shiny has to offer. Additionally, 38 | although the name implies all topics are at least intermediate level, some are more straightforward and every effort will be made to 39 | ensure the content can be understood by those who are fairly new to R Shiny."), 40 | 41 | p("A basic knowledge of R and R Shiny is assumed, however. For a beginners introduction to either of these, see the official documentation and get 42 | started guide, or check out the", tags$a("Coffee & Coding sharepoint page", 43 | href = "https://educationgovuk.sharepoint.com/sites/sarpi/g/AC/Coffee%20and%20Coding.aspx"), 44 | "as there has been previous beginner-level talks on these two topics.") 45 | ), 46 | 47 | box( 48 | title = "Shiny Ladder of Enlightenment", 49 | solidHeader = TRUE, 50 | width = NULL, 51 | icon = icon("swimming-pool"), 52 | status = "info", 53 | 54 | p("In a talk at Shiny Dev Con 2016, Joe Cheng (creator of shiny and CTO at RStudio) proposed a (semi-serious) 'Ladder 55 | of Enlightenment' for shiny. The ladder gives an idea of different levels of understanding of shiny and how it works 56 | (particularly how reactivity works). 57 | The ladder is as follows:"), 58 | tags$ol( 59 | tags$li("Has used 'output' and 'input'"), 60 | tags$li("Has used reactive expressions (", code_block("reactive()", noWS = "outside"), ")"), 61 | tags$li("Has used", code_block("observe()"), "and/or ", code_block("observeEvent()", noWS = "outside"), ". 62 | Has written reactive expressions that depend on other reactive expressions. Has used", code_block("isolate()"), 63 | "properly."), 64 | tags$li("Can", tags$i("confidently"), "say when to use", code_block("reactive()"), "vs. ", code_block("observe()", noWS = "outside"), 65 | ". Has used ", code_block("invalidateLater()", noWS = "outside"), "."), 66 | tags$li("Writes higher-order reactives (functions that have reactive expressions as input parameters and return values)."), 67 | tags$li("Understands that reactive expressions are monads.") 68 | ), 69 | p("It is assumed that if you are using this app you are at least at step 1 and probably higher."), 70 | p("Much of the first section of this app, particularly tabs 1.2-1.4 (Understanding, Using and Controlling reactivity) will cover steps 2-4 (and briefly touch on 5)."), 71 | p("As Joe commented in his talk, there are probably only a handful of people in the world who are at step 6 (himself 72 | and Hadley (Wickham) being two of them). This is because reaching this step would require both expert knowledge of maths 73 | and computing, as well as deep understanding of shiny internals and how the package was built. As such this won't be spoken 74 | about here. If you're wondering what monads are, I would suggest you don't(!) - if you really want to know you can google 'what 75 | are monads' and come back here once you've emerged from the rabbit hole!") 76 | ) 77 | ), 78 | 79 | column( 80 | width = 4, 81 | box( 82 | title = "Using the app", 83 | solidHeader = TRUE, 84 | width = NULL, 85 | icon = icon("book"), 86 | status = "info", 87 | 88 | p("As you can see, the app has been structured in a similiar fashion to a bookdown site, with sequential chapters that can be accessed 89 | using the navigation sidebar. The content has been arranged into three broad categories, which will roughly correspond with the 90 | Coffee & Coding sessions to be delivered. The topics are", tags$b("not"), "arranged in order of difficulty, but a logical order has 91 | been decided upon and we have tried to put simple or more fundamental concepts earlier on in each section. Feel free to look through 92 | each tab in order or to jump around and look at only the parts which interest you."), 93 | 94 | p("Where possible, code snippets will be provided which you can copy and paste to try out some of the methods showcased here. The full 95 | repository for this app will also be available so you can check out the full code if you want to (link will be provided below at a later 96 | date). The app has been structured as an R package (see section 1.5 for more info), so you can clone the repository and run the app 97 | yourself with the code below."), 98 | 99 | code_snippet(c("remotes::install_github('chrisbrownlie/advancedShiny')", 100 | "library(advancedShiny)", 101 | "run_IAS_app()")), 102 | 103 | p(strong("Note that for any of the code examples which require reactivity, a mini example app will often be provided but if not you can enter a demo 104 | reactive state using:")), 105 | code_snippet(c("shiny::reactiveConsole(TRUE)")) 106 | ), 107 | 108 | box( 109 | title = "Contributions", 110 | solidHeader = TRUE, 111 | width = NULL, 112 | icon = icon("users"), 113 | status = "purple", 114 | 115 | p("This app was developed by:"), 116 | tags$ul( 117 | tags$li( 118 | tags$a("Chris Brownlie", href = "mailto:christopher.brownlie@education.gov.uk") 119 | ) 120 | ), 121 | p("with contributions from:"), 122 | tags$ul( 123 | ), 124 | p("For more info or to contribute, contact one of the above.") 125 | ) #end box 126 | ) #end column 127 | ) #end fluidRow 128 | ) #end tagList 129 | 130 | } 131 | 132 | #' Info module server 133 | #' 134 | #' Defines the server logic for the Info module 135 | #' 136 | #' @param id to be used to namespace the module 137 | #' @param appData the appData reactiveValues object, defined in server.R and available 138 | #' to all modules 139 | #' 140 | #' @return the module server, returned from a moduleServer function call 141 | #' 142 | #' @export 143 | tab_info_server <- function(id, 144 | appData) { 145 | 146 | moduleServer( 147 | id, 148 | function(input, 149 | output, 150 | session, 151 | appData = appData) { 152 | 153 | # Alias the namespace function for ease of use 154 | ns <- session$ns 155 | 156 | } 157 | ) 158 | 159 | } 160 | -------------------------------------------------------------------------------- /R/mod_16_shinyModules.R: -------------------------------------------------------------------------------- 1 | #' Shiny Modules module 2 | 3 | #' Shiny Modules module UI 4 | #' 5 | #' Defines the UI for the Shiny Modules module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_shinyModules_ui <- function(id) { 13 | ns <- NS(id) 14 | 15 | tagList( 16 | h3("Shiny Modules", 17 | class = "tab-title" 18 | ), 19 | fluidRow( 20 | column( 21 | width = 4, 22 | box( 23 | title = "Why...so...modular?", 24 | solidHeader = TRUE, 25 | width = NULL, 26 | closable = FALSE, 27 | collapsible = TRUE, 28 | icon = icon("boxes"), 29 | status = "maroon", 30 | p( 31 | "This tab will introduce Shiny modules and discuss how and why you might use them. If you 32 | are developing a shiny app which you think could potentially grow in future or be 33 | anything more than a very simple app, you should", tags$b("absolutely, definitely use modules."), 34 | "There are two key benefits to using Shiny modules and they are outlined below:" 35 | ), 36 | tags$ul( 37 | tags$li("If you've ever built a complex shiny app you'll know it can easily reach thousands of lines 38 | of code if you aren't careful. This quickly becomes a nightmare to maintain and debug, as you 39 | can end up scrawling through lines of your server to find where that one reactive object is defined. 40 | Modules give you an easy way to split your app code into separate, manageable scripts."), 41 | tags$li( 42 | "The '1000 button problem': usually if you find yourself repeating code, you should be writing a 43 | function and calling that instead. This isn't so straightforward with reactive Shiny code because of", 44 | tags$i("namespacing."), "Every instance of an object needs a unique ID to match the UI to the server and this can 45 | quickly cause major headaches when developing your app. Modules provide a neat way to resolve this." 46 | ) 47 | ), 48 | p("From personal experience, the first of these is the more useful aspect of Shiny modules and the reason why I would 49 | recommend always using them unless you have a reason not to."), 50 | p("The box on the right shows an example of how modules can be used, so feel free to use this as a starting point for 51 | developing your own modules."), 52 | tags$i("On a side note: be careful when researching/googling shiny modules and be sure not to confuse them with", tags$b("wahani"), "modules, 53 | which are an unrelated topic in R.") 54 | ), 55 | 56 | box( 57 | title = "Housekeeping", 58 | solidHeader = TRUE, 59 | width = NULL, 60 | closable = FALSE, 61 | collapsible = TRUE, 62 | icon = icon("broom"), 63 | status = "maroon", 64 | 65 | p("As mentioned above, one of the key benefits of using shiny modules is keeping different elements of your app 66 | separate and in short, manageable scripts. The workflow proposed here (in this tab and the previous tab) is 67 | inspired by various other frameworks and is opinionated. As always, feel free to pick and choose which of the 68 | below you use, but when it comes to using modules, the following points are recommended:"), 69 | tags$ul( 70 | tags$li("Each page of your app should be a separate module. This is straightforward for dashboard-style apps 71 | where you can simply have a separate module for each tab, for other apps you may have to 72 | make judgement calls about the separate parts of your app."), 73 | tags$li("Each module (UI and server function) should be in its own script, named according to the conventions 74 | outlined on the previous tab (e.g. 'mod_01_homepage.R')."), 75 | tags$li("Every page's module server function should have a mandatory data argument, to which can be passed your 76 | app_data reactiveValues (see the 'Sharing is caring' box on the previous tab)."), 77 | tags$li("Each module function should be documented in the same way as a normal function with roxygen comments.") 78 | ), 79 | p("Following these steps, as well as following the advice to structure your app as a package, will also mean that 80 | you can reuse modules in different apps. You could even develop a package with a module in and then just use 81 | that package when you are developing other apps in future. For example, if you have a particular section of reactive 82 | UI that is used in multiple apps.") 83 | ), 84 | 85 | box( 86 | title = "Summary", 87 | status = "maroon", 88 | icon = icon("info-circle"), 89 | solidHeader = TRUE, 90 | closable = TRUE, 91 | collapsible = TRUE, 92 | width = NULL, 93 | p("So in summary:"), 94 | tags$ul( 95 | tags$li("Always use modules!"), 96 | tags$li("Separate your app into sections and have each section in a separate"), 97 | tags$li("Use modules as an alternative to functions which have reactive inputs and outputs"), 98 | tags$li("Shiny modules are an implementation of the software development method of", tags$i("namespacing")) 99 | ) 100 | ) 101 | ), # endColumn 102 | 103 | column( 104 | width = 8, 105 | box( 106 | title = "1000 Button Problem", 107 | solidHeader = TRUE, 108 | width = NULL, 109 | closable = FALSE, 110 | collapsible = TRUE, 111 | icon = icon("braille"), 112 | status = "maroon", 113 | p("Imagine you are building an app with several independent counter buttons. This can be achieved using functions for UI 114 | and server logic, but for a very large app you would run into problems due to the fact that input and output 115 | IDs share a", tags$i("global namespace"), "in shiny. This means that all inputs and outputs must have unique IDs."), 116 | p("This issue is resolved in computer science by using", tags$i("namespacing"), "whereby objects must only have unique 117 | IDs within their namespace and namespaces can be nested. In practice you can simply think of a namespace as a prefix to 118 | an ID. For example, if you have two outputs called 'my_button', you can put them into separate namespaces called 'first' 119 | and 'second'. This would be equivalent to (but far more elegant than) renaming the outputs 'first-my_button' and 120 | 'second-my_button'."), 121 | p("Shiny modules were introduced to allow developers to take advantage of namespacing. See below for how to use them, in 122 | the context of an app with multiple counters."), 123 | code_snippet(c( 124 | "library(shiny)", 125 | "", 126 | "counterButton <- function(id, label = 'Counter') {", 127 | " ns <- NS(id)", 128 | " tagList(", 129 | " actionButton(ns('button'), label = label),", 130 | " verbatimTextOutput(ns('out'))", 131 | " )", 132 | "}", 133 | "", 134 | "counterServer <- function(id) {", 135 | " moduleServer(", 136 | " id,", 137 | " function(input, output, session) {", 138 | " count <- reactiveVal(0)", 139 | " observeEvent(input$button, {", 140 | " count(count() + 1)", 141 | " })", 142 | " output$out <- renderText({", 143 | " count()", 144 | " })", 145 | " count", 146 | " }", 147 | " )", 148 | "}", 149 | "", 150 | "ui <- fluidPage(", 151 | " counterButton('counter1', 'Counter #1'),", 152 | " counterButton('counter2', 'Counter #2'),", 153 | " counterButton('counter3', 'Counter #3')", 154 | ")", 155 | "", 156 | "server <- function(input, output, session) {", 157 | " counterServer('counter1')", 158 | " counterServer('counter2')", 159 | " counterServer('counter3')", 160 | "}", 161 | "", 162 | "shinyApp(ui, server)" 163 | )), 164 | br(), 165 | p("There are 5 important points to note about the code above:"), 166 | tags$ul( 167 | tags$li("The module is defined in two parts just like a shiny app, with a UI and a server function"), 168 | tags$li("Both elements of a module take in an id argument. This is crucial as it allows shiny to match 169 | the module UI to module server for each instance of the module."), 170 | tags$li( 171 | "The UI function uses a function from shiny to access the current namespace.", code_block("NS(id)"), 172 | "will return a function that adds the current (unique) namespace to whatever is supplied to it. So 173 | by applying the resulting ns() function to each output in the module, the outputs will be unique to 174 | that particular 'id'." 175 | ), 176 | tags$li("Note the moduleServer call in the counterServer function. This allows you to write code as you would 177 | for a shiny server, using the input, output and session objects as required."), 178 | tags$li( 179 | "Outputs in the server function do not need to be wrapped in a namespacing function because this is handled 180 | by moduleServer(),", 181 | tags$b("but if you use renderUI(), any outputs or inputs must be namespaced in the same way as in the UI 182 | function."), 183 | "This is done by adding the following line of code to the top of your moduleServer function call: ", 184 | code_block("ns <- session$ns") 185 | ) 186 | ) 187 | ) # end box 188 | ) # end column 189 | ) # end fluidRow 190 | ) # end tagList 191 | } 192 | 193 | #' Shiny Modules module server 194 | #' 195 | #' Defines the server logic for the Shiny Modules module 196 | #' 197 | #' @param id to be used to namespace the module 198 | #' @param appData the appData reactiveValues object, defined in server.R and available 199 | #' to all modules 200 | #' 201 | #' @return the module server, returned from a moduleServer function call 202 | #' 203 | #' @export 204 | tab_shinyModules_server <- function(id, 205 | appData) { 206 | moduleServer( 207 | id, 208 | function(input, 209 | output, 210 | session, 211 | appData = appData) { 212 | 213 | # Alias the namespace function for ease of use 214 | ns <- session$ns 215 | } 216 | ) 217 | } 218 | -------------------------------------------------------------------------------- /R/mod_21_usingCSS.R: -------------------------------------------------------------------------------- 1 | #' Using CSS module 2 | 3 | #' Using CSS module UI 4 | #' 5 | #' Defines the UI for the Using CSS module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_usingCSS_ui <- function(id) { 13 | ns <- NS(id) 14 | 15 | tagList( 16 | h3("Using CSS", 17 | class = "tab-title" 18 | ), 19 | fluidRow( 20 | column( 21 | width = 6, 22 | box( 23 | title = "What is CSS?", 24 | status = "success", 25 | icon = icon("info-circle"), 26 | solidHeader = TRUE, 27 | closable = TRUE, 28 | collapsible = TRUE, 29 | width = NULL, 30 | p("In Section 1.1 'What is shiny, actually?', I described shiny as 'an R to {HTML-Javascript-CSS} translator', as 31 | these are the three core components of the front-end of most modern web apps. One way to decribe this triad is: HTML 32 | (HyperText Markup Language) provides the building blocks for your UI; Javascript determines what the building 33 | blocks do and CSS (Cascading Style Sheets) determines what the blocks look 34 | like. This is perhaps an oversimplification (disclaimer: I am not a front-end dev or web designer!), but I think it 35 | gives a good practical understanding of how the three interact."), 36 | p( 37 | "In shiny, the HTML code will mostly be generated using shiny functions such as", code_block("fluidPage()"), code_block("p()"), 38 | "and the various", code_block("*input()"), "and", code_block("render*()"), "functions." 39 | ), 40 | p("The javascript in the app comes from many places, including the shiny package itself and this is discussed in 41 | detail in other tabs. The CSS that comes bundled with shiny gives a generic, bland look and feel to the app so 42 | in order to spice things up, you must add your own CSS."), 43 | p("CSS can be used to specify the color, shape, size, shadow, background colour, spacing, padding and many other attributes of 44 | each individual element or type of element on your page."), 45 | br(), 46 | p("You can see some examples of CSS if you inspect any web app - including this one - by opening the developer tools (usually by 47 | right clicking and 'Inspect'). The picture below shows an example of what you might see:"), 48 | p("The pane on the left shows the HTML of the page and the pane on the right shows some of the styles specified by the CSS of the 49 | page."), 50 | tags$img(src = "img/html_css_inspected.png", width = "100%") 51 | ), # end box 52 | 53 | box( 54 | title = "{shinydashboard(Plus)} vs {bslib}/{thematic}", 55 | status = "success", 56 | icon = icon("info-circle"), 57 | solidHeader = TRUE, 58 | closable = TRUE, 59 | collapsible = TRUE, 60 | width = NULL, 61 | p(tags$i("Note: this box is not technically about CSS but what is discussed below is an important design choice for the developer 62 | of a shiny app (as is CSS).")), 63 | p("When deciding what your app will look like, CSS gives you fine-tuned control over each object in your UI. Before you 64 | reach this point though there is often a key decision to be made: to dashboard or not to dashboard."), 65 | p( 66 | "There are essentially limitless ways to structure a shiny app, as you could always even write the custom HTML to achieve 67 | the layout you desire, but typically (in my experience at least) it will usually boil down to whether a dashboard structure 68 | makes sense or not. If it does, you can make use of the", code_block("shinydashboard", T), "and", 69 | code_block("shinydashboardPlus", T), "packages to speed up your development, if not you will probably use a vanilla shiny", 70 | code_block("fluidPage()"), "or", code_block("navbarPage()"), "layout and have more design choices to make about how to structure 71 | pages and navigation etc." 72 | ), 73 | p("To clarify, this advancedShiny app uses a dashboard layout - a header, a body (central pane) and a sidebar (navigation pane) which 74 | allows you to switch between different named tabs, each one containing related information in structured boxes/sections. A 75 | non-dashboard layout may consist of a single page, or multiple pages where the layout differs depending on which page is currently 76 | visible, for example."), 77 | p("The shinydashboard package can be used (and has been used here) to get a dashboard-style look and feel to the app, providing 78 | functions for", code_block("dashboardPage()"), code_block("dashboardHeader()"), code_block("dashboardBody()"), "etc. Additionally 79 | the", code_block("shinydashboardPlus", T), "package extends this and gives more options such as closable and collapsible boxes, 80 | and more colours to use."), 81 | br(), 82 | p("If your app is not a dashboard layout, you can make use of the", code_block("bslib", T), "package which allows you to specify 83 | custom theming and use existing Bootstrap themes in your app.", code_block("bslib", T), "also makes it possible to use Bootstrap 84 | 4 or 5, where shiny defaults to Bootstrap 3."), 85 | p("As", code_block("bslib", T), "is (like shiny) an RStudio package, it benefits from seamless integration with base shiny. All 86 | shiny's top-level layout functions (e.g. fluidPage), have a 'theme' parameter. So you can simply supply a function from bslib 87 | as an argument to that. Take the example app below (adapted from an RStudio example app):"), 88 | code_snippet(c( 89 | "library(shiny)", 90 | "", 91 | "ui <- navbarPage('Navbar!',", 92 | " tabPanel('Plot',", 93 | " sidebarLayout(", 94 | " sidebarPanel(", 95 | " radioButtons('plotType', 'Plot type',", 96 | " c('Scatter'='p', 'Line'='l')", 97 | " )", 98 | " ),", 99 | " mainPanel(", 100 | " plotOutput('plot')", 101 | " )", 102 | " )", 103 | " ),", 104 | " tabPanel('Summary'),", 105 | " navbarMenu('More')", 106 | ")", 107 | "", 108 | "server <- function(input, output, session) {", 109 | " ", 110 | " output$plot <- renderPlot({", 111 | " plot(cars, type=input$plotType)", 112 | " })", 113 | " ", 114 | "}", 115 | "", 116 | "shinyApp(ui, server)" 117 | )), 118 | p("This app has the basic shiny styling (see sample below):"), 119 | tags$img(src = "img/simple_app_notheme.png", 120 | width = "100%"), 121 | p("But by using", code_block("bslib", T), "you can change the look and feel with just one line of code, 122 | added to the", code_block("navbarPage()"), "call:"), 123 | code_snippet(c( 124 | "...", 125 | "ui <- navbarPage('Navbar!',", 126 | " theme = bslib::bs_theme(bootswatch = 'lux') # add theme", 127 | " tabPanel('Plot',", 128 | " ..." 129 | )), 130 | p("Resulting in app that looks slightly more appealing:"), 131 | tags$img(src = "img/simple_app_luxtheme.png", 132 | width = "100%"), 133 | p("Admittedly, in this example app the changes aren't radical (mostly just the font, some colouring and 134 | the behaviour of the navbar buttons), but for more complex apps you can see how powerful it would be 135 | to overhaul the general look and feel with a single line of code."), 136 | p("Additionally, you specify your own custom theme with the various arguments to", code_block("bs_theme()"), 137 | "as opposed to a pre-made bootswatch theme (like the example above). If you choose this route you have far 138 | more control and can even adjust your theme using a real time editor via the", code_block("bs_themer()"), 139 | "function.") 140 | ) # end box 141 | ), # end column 142 | column( 143 | width = 6, 144 | box( 145 | title = "How to add CSS to your app", 146 | status = "success", 147 | icon = icon("info-circle"), 148 | solidHeader = TRUE, 149 | closable = TRUE, 150 | collapsible = TRUE, 151 | width = NULL, 152 | p("There are three main ways you can add custom styles to your app. This tutorial will not cover CSS syntax, but will assume 153 | you have a working knowledge of how to style HTML elements using CSS."), 154 | h4("1. Separate CSS file"), 155 | p("This is the best way to add custom CSS to your app. It involves keeping all your styling contained into a single file 156 | or collection of files, away from the logic of your app. It also makes it far easier to maintain consistent styles across 157 | your entire app. To include a file in your app, you should store it in the www/ folder (see 1.5 - Structuring an app)."), 158 | p("Assuming you have created a CSS file called 'styles.css' and stored it in your www/ folder, you then simply need to add 159 | the following code to your UI:"), 160 | code_snippet(c("tags$head(tags$link(href = 'styles.css', rel = 'stylesheet', type = 'text/css'))")), 161 | p("This will make any styles available to your app."), 162 | hr(), 163 | h4("Per-element styling"), 164 | p("A quicker but far more messy way to style an element is to include it directly, using the 'style' argument to the element ( 165 | where it is available). For example, it can be used on a 'div' to style everything within it:"), 166 | code_snippet(c("tags$div(", 167 | " style = 'font-size:40px; font-weight:bold;',", 168 | " p('This text will be large and bold')", 169 | ")")), 170 | p("Alternatively, you can include class definitions using", code_block("tags$style()"), ", e.g.:"), 171 | code_snippet(c("tags$style('", 172 | " .blue-stuff {", 173 | " color: blue;", 174 | " }", 175 | " ", 176 | " .red-stuff {", 177 | " color: red;", 178 | " }'", 179 | ")")), 180 | hr(), 181 | h4("Dynamically add CSS"), 182 | p("This is rarer and should only be used in specific cases, but the shinyjs package can be used to add a class to an object 183 | after the app has been launched. See example below (using tags$style() css from above):"), 184 | code_snippet(c("ui <- fluidPage(", 185 | " shinyjs::useShinyjs(),", 186 | " tags$style('", 187 | " .blue-stuff {", 188 | " color: blue;", 189 | " }", 190 | " ", 191 | " .red-stuff {", 192 | " color: red;", 193 | " }'", 194 | " ),", 195 | " p('This is the text', id = 'my-text'),", 196 | " actionButton('red', 'Make red'),", 197 | " actionButton('blue', 'Make blue')", 198 | ")", 199 | "", 200 | "server <- function(input, output) {", 201 | " observeEvent(input$red, {", 202 | " shinyjs::removeClass(id = 'my-text', class = 'blue-stuff')", 203 | " shinyjs::addClass(id = 'my-text', class = 'red-stuff')", 204 | " })", 205 | " observeEvent(input$blue, {", 206 | " shinyjs::removeClass(id = 'my-text', class = 'red-stuff')", 207 | " shinyjs::addClass(id = 'my-text', class = 'blue-stuff')", 208 | " })", 209 | "}", 210 | "", 211 | "shinyApp(ui = ui, server = server)")) 212 | ), # end box 213 | 214 | box( 215 | title = "Getting {sass}y", 216 | status = "success", 217 | icon = icon("info-circle"), 218 | solidHeader = TRUE, 219 | closable = TRUE, 220 | collapsible = TRUE, 221 | width = NULL, 222 | 223 | p("Once you have mastered adding CSS to your app, you can begin to make use of SASS (Syntactically 224 | Awesome Style Sheets) - a CSS extension language described as 'CSS with superpowers'. All SASS is, 225 | is a way to make managing large/complex CSS sheets easier, by adding various useful things such as: 226 | allowing you to set variables, nest your styles and use partial styles (among other things). SASS 227 | then generates the final CSS stylesheet automatically. Helpfully, there is an R package allowing you 228 | to make use of SASS in your shiny apps with almost no additional effort required - the package is called", 229 | code_block("sass", T)), 230 | p("View the code at the top of the app_ui() function for this package to get an idea of how to use", 231 | code_block("sass", T), "in this proposed workflow.") 232 | ) # end box 233 | ) # end column 234 | ) # end fluidRow 235 | ) # end tagList 236 | } 237 | 238 | #' Using CSS module server 239 | #' 240 | #' Defines the server logic for the Using CSS module 241 | #' 242 | #' @param id to be used to namespace the module 243 | #' @param appData the appData reactiveValues object, defined in server.R and available 244 | #' to all modules 245 | #' 246 | #' @return the module server, returned from a moduleServer function call 247 | #' 248 | #' @export 249 | tab_usingCSS_server <- function(id, 250 | appData) { 251 | moduleServer( 252 | id, 253 | function(input, 254 | output, 255 | session, 256 | appData = appData) { 257 | 258 | # Alias the namespace function for ease of use 259 | ns <- session$ns 260 | } 261 | ) 262 | } 263 | -------------------------------------------------------------------------------- /R/mod_22_usingJS.R: -------------------------------------------------------------------------------- 1 | #' Using Javascript module 2 | 3 | #' Using Javascript module UI 4 | #' 5 | #' Defines the UI for the Using Javascript module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_usingJS_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Using Javascript", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "What is Javascript?", 25 | status = "warning", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL, 31 | 32 | p("As mentioned in tab 1.1 ('What is shiny, actually?'), Javascript is one of the three languages of the web 33 | that shiny code gets converted into. The way I like to think about it is that Javascript handles how objects 34 | move and interact with the user. In reality, Javascript is a very powerful programming language that can be 35 | used in a plethora of ways."), 36 | 37 | p("As has already been stated by others before me, Javascript really is the best way you can take your Shiny skills from 38 | decent to world-class. Proper use of Javascript is, in my opinion, the number one way to improve user experience in 39 | your app. When it comes down to it, user experience is almost always the one key metric for how successful an app is. If 40 | a user can't get what they need from an app or faces unnecessary complications and hurdles to doing so, it doesn't matter 41 | how pretty it looks or how many complicated concepts it implements, they simply won't use it."), 42 | 43 | p("Javascript is more complicated than its two companions in shiny web development (HTML and CSS), but is far more 44 | powerful as a result. Many of the core concepts of Javascript have parallels in R - or most other programming languages 45 | for that matter (variables, functions, conditionals etc.)."), 46 | 47 | 48 | h5("This tab will not discuss the technicalities of using Javascript in any depth, as there are already fantastic resources available elsewhere:"), 49 | tags$ul( 50 | tags$li("See", tags$a("here for a basic introduction to Javascript.", href = "https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics#what_is_javascript")), 51 | tags$li("See", tags$a("here for a slightly more in-depth tutorial.", href = "https://unleash-shiny.rinterface.com/survival-kit-javascript.html#programming-with-js-basis")), 52 | tags$li("See", tags$a("here for a more detailed discussion of how to use JS in production shiny apps.", href = "https://engineering-shiny.org/using-javascript.html")) 53 | ), 54 | 55 | p("Instead, this tab will focus on trying to explain practically why you might want to look into using JS or ways to get started.") 56 | ), #end box 57 | 58 | box( 59 | title = "Some cool use cases for adding JS to your app", 60 | status = "warning", 61 | icon = icon("info-circle"), 62 | solidHeader = TRUE, 63 | closable = TRUE, 64 | collapsible = TRUE, 65 | width = NULL, 66 | 67 | p("This is just some of the ways I've used Javascript in an app or you might want to (this list is far from exhaustive):"), 68 | 69 | tags$ul( 70 | tags$li("To monitor whether a user makes changes so that when they try to close the app they get a popup saying 'you have unsaved changes'"), 71 | tags$li("To animate an element of the page when a user hovers their mouse over it"), 72 | tags$li("To speed up the reactivity of your UI using e.g.", code_block("shinyjs", T)), 73 | tags$li("To create custom interactive, animated graphics using e.g.", code_block("r2d3", T)), 74 | tags$li("To insert a custom API into your app to allow communication with other programs/services"), 75 | tags$li("To identify a user's browser information to enable customise your app based on viewing device") 76 | ) 77 | 78 | ) #end box 79 | ), #end column 80 | column( 81 | width = 6, 82 | box( 83 | title = "How to add javascript to your app", 84 | status = "warning", 85 | icon = icon("info-circle"), 86 | solidHeader = TRUE, 87 | closable = TRUE, 88 | collapsible = TRUE, 89 | width = NULL, 90 | 91 | p("As with CSS, there are two main ways to add JS to your app: the clean way and the messy way."), 92 | 93 | h6("The messy way"), 94 | p("Javascript code can be added directly inline to your app, using", code_block("shiny::JS()"), "or", code_block("tags$script('{javascript code}')")), 95 | 96 | h6("The clean way"), 97 | p("You can keep your Javascript code in a separate file(s) in the www/ folder and include them using", code_block("shiny::includeScript()"), 98 | "or", code_block("tags$link(src = 'myscript.js')")) 99 | ), #end box 100 | 101 | box( 102 | title = "shinyjs", 103 | status = "warning", 104 | icon = icon("info-circle"), 105 | solidHeader = TRUE, 106 | closable = TRUE, 107 | collapsible = TRUE, 108 | width = NULL, 109 | 110 | p("One of the best ways to get started using Javascript in your shiny apps is to leverage the powerful and lightweight", code_block("shinyjs", T), 111 | "package. Created by", tags$a("Dean Attali", href = "https://github.com/daattali", .noWS = 'outside'), ", it wraps several useful Javascript 112 | actions into neat R functions. This allows you to introduce Javascript functionality to your app without even having to learn the language 113 | to begin with!"), 114 | 115 | p("For a full list of what shinyjs provides, see the", tags$a("documentation site", href = "https://deanattali.com/shinyjs/"), "but see below 116 | just a couple of examples."), 117 | 118 | h6("Hiding/disabling elements"), 119 | p("This is probably what I use shinyjs for the most, quickly and easily hiding, unhiding and disabling elements. There are many situations 120 | where you want to take the ability to do something out of your users' hands for a period of time. The shinyjs functions make this very easy. 121 | See an example below. Notice the use of", code_block("hidden()"), "to ensure the element starts in a hidden state - there is an equivalent", 122 | code_block("disabled"), "function too for starting an element in a disabled state."), 123 | code_snippet(c("library(shiny)", 124 | "library(shinyjs)", 125 | "", 126 | "ui <- fluidPage(", 127 | " useShinyjs(),", 128 | " hidden(p('some sample text', id = 'txt')),", 129 | " actionButton('show', 'Show text'),", 130 | " actionButton('hide', 'Hide text'),", 131 | " actionButton('disable', 'Disable hiding/showing'),", 132 | " actionButton('enable', 'Enable hiding/showing')", 133 | ")", 134 | "", 135 | "server <- function(input, output) {", 136 | " observeEvent(input$show, {", 137 | " show('txt')", 138 | " })", 139 | " observeEvent(input$hide, {", 140 | " hide('txt')", 141 | " })", 142 | " observeEvent(input$disable, {", 143 | " disable('show')", 144 | " disable('hide')", 145 | " })", 146 | " observeEvent(input$enable, {", 147 | " enable('show')", 148 | " enable('hide')", 149 | " })", 150 | "}", 151 | "", 152 | "shinyApp(ui, server)")), 153 | 154 | h6("Delaying events"), 155 | p("There are multiple ways to delay reactivity in shiny (see 1.4 - Controlling reactivity), but shinyjs provides yet another way to 156 | simply control the flow and timing of events in your app, using the", code_block("delay"), "function."), 157 | p("See an example of this below:"), 158 | code_snippet(c("library(shiny)", 159 | "library(shinyjs)", 160 | "", 161 | "ui <- fluidPage(", 162 | " useShinyjs(),", 163 | " p('some sample text', id = 'txt'),", 164 | " actionButton('hide3', 'Hide text for 3 seconds'),", 165 | " actionButton('hide1', 'Wait 3 seconds, then hide text for 1 second'),", 166 | ")", 167 | "", 168 | "server <- function(input, output) {", 169 | " observeEvent(input$hide3, {", 170 | " hide('txt')", 171 | " delay(3000, show('txt'))", 172 | " })", 173 | " observeEvent(input$hide1, {", 174 | " delay(3000, hide('txt'))", 175 | " delay(4000, show('txt')) # important: delay time is from when observer first runs", 176 | " })", 177 | "}", 178 | "", 179 | "shinyApp(ui, server)")) 180 | ) #end box 181 | ) #end column 182 | ) #end fluidRow 183 | 184 | ) 185 | 186 | } 187 | 188 | #' Using Javascript module server 189 | #' 190 | #' Defines the server logic for the Using Javascript module 191 | #' 192 | #' @param id to be used to namespace the module 193 | #' @param appData the appData reactiveValues object, defined in server.R and available 194 | #' to all modules 195 | #' 196 | #' @return the module server, returned from a moduleServer function call 197 | #' 198 | #' @export 199 | tab_usingJS_server <- function(id, 200 | appData) { 201 | 202 | moduleServer( 203 | id, 204 | function(input, 205 | output, 206 | session, 207 | appData = appData) { 208 | 209 | # Alias the namespace function for ease of use 210 | ns <- session$ns 211 | 212 | } 213 | ) 214 | 215 | } 216 | -------------------------------------------------------------------------------- /R/mod_23_attaliverse.R: -------------------------------------------------------------------------------- 1 | #' Attali-verse module 2 | 3 | #' Attali-verse module UI 4 | #' 5 | #' Defines the UI for the Attali-verse module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_attaliverse_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Attali-verse", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "Dean Attali", 25 | status = "navy", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL, 31 | 32 | p("In the previous tab, I introduced shinyjs as one of the best ways to get started using Javascript in your 33 | shiny apps. This package was created by an R guru by the name of Dean Attali. Dean runs an R Shiny consulting 34 | firm and has created several R packages specifically to enhance shiny apps and fill some of the gaps in base 35 | shiny functionality."), 36 | p("This collection of packages do not have an official name so I've (semi-seriously) referred to them as the 37 | 'Attali-verse'. There are several packages, each with their own specific use case - and I personally have found 38 | some of them invaluable when creating interactive, user-friendly apps."), 39 | p("This tab introduces some of the most useful packages, because I believe that all shiny developers should at 40 | least be aware of them as they may make your life much, much easier."), 41 | p("See", tags$a("Dean's Github", href = "https://github.com/daattali"), "for more or to see all other packages.") 42 | ), #end box 43 | 44 | box( 45 | title = "shinyalert", 46 | status = "navy", 47 | icon = icon("info-circle"), 48 | solidHeader = TRUE, 49 | closable = TRUE, 50 | collapsible = TRUE, 51 | width = NULL 52 | ) #end box 53 | ), #end column 54 | column( 55 | width = 6, 56 | box( 57 | title = "shinycssloaders", 58 | status = "navy", 59 | icon = icon("info-circle"), 60 | solidHeader = TRUE, 61 | closable = TRUE, 62 | collapsible = TRUE, 63 | width = NULL 64 | ), #end box 65 | 66 | box( 67 | title = "...and the rest", 68 | status = "navy", 69 | icon = icon("info-circle"), 70 | solidHeader = TRUE, 71 | closable = TRUE, 72 | collapsible = TRUE, 73 | width = NULL 74 | ) #end box 75 | ) #end column 76 | ) #end fluidRow 77 | ) 78 | 79 | } 80 | 81 | #' Attali-verse module server 82 | #' 83 | #' Defines the server logic for the Attali-verse module 84 | #' 85 | #' @param id to be used to namespace the module 86 | #' @param appData the appData reactiveValues object, defined in server.R and available 87 | #' to all modules 88 | #' 89 | #' @return the module server, returned from a moduleServer function call 90 | #' 91 | #' @export 92 | tab_attaliverse_server <- function(id, 93 | appData) { 94 | 95 | moduleServer( 96 | id, 97 | function(input, 98 | output, 99 | session, 100 | appData = appData) { 101 | 102 | # Alias the namespace function for ease of use 103 | ns <- session$ns 104 | 105 | } 106 | ) 107 | 108 | } 109 | -------------------------------------------------------------------------------- /R/mod_24_extendingShiny.R: -------------------------------------------------------------------------------- 1 | #' Extending Shiny module 2 | 3 | #' Extending Shiny module UI 4 | #' 5 | #' Defines the UI for the Extending Shiny module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_extendingShiny_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Extending Shiny", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "Javascript is powerful", 25 | status = "purple", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "shinyHelper, shinyFeedback, shinyEffects", 35 | status = "purple", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL 41 | ) #end box 42 | ), #end column 43 | column( 44 | width = 6, 45 | box( 46 | title = "htmlwidgets", 47 | status = "purple", 48 | icon = icon("info-circle"), 49 | solidHeader = TRUE, 50 | closable = TRUE, 51 | collapsible = TRUE, 52 | width = NULL 53 | ), #end box 54 | 55 | box( 56 | title = "Higher-order reactives", 57 | status = "purple", 58 | icon = icon("info-circle"), 59 | solidHeader = TRUE, 60 | closable = TRUE, 61 | collapsible = TRUE, 62 | width = NULL 63 | ) #end box 64 | ) #end column 65 | ) #end fluidRow 66 | 67 | ) 68 | 69 | } 70 | 71 | #' Extending Shiny module server 72 | #' 73 | #' Defines the server logic for the Extending Shiny module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_extendingShiny_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_25_customInputs.R: -------------------------------------------------------------------------------- 1 | #' Custom Shiny Inputs module 2 | 3 | #' Custom Shiny Inputs module UI 4 | #' 5 | #' Defines the UI for the Custom Shiny Inputs module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_customInputs_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Custom Shiny Inputs", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "What actually are shiny inputs?", 25 | status = "success", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "Bindings and Findings", 35 | status = "success", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL 41 | ) #end box 42 | ), #end column 43 | column( 44 | width = 6, 45 | box( 46 | title = "Creating your own input", 47 | status = "success", 48 | icon = icon("info-circle"), 49 | solidHeader = TRUE, 50 | closable = TRUE, 51 | collapsible = TRUE, 52 | width = NULL 53 | ), #end box 54 | 55 | box( 56 | title = "{charpente}", 57 | status = "success", 58 | icon = icon("info-circle"), 59 | solidHeader = TRUE, 60 | closable = TRUE, 61 | collapsible = TRUE, 62 | width = NULL 63 | ) #end box 64 | ) #end column 65 | ) #end fluidRow 66 | ) 67 | 68 | } 69 | 70 | #' Custom Shiny Inputs module server 71 | #' 72 | #' Defines the server logic for the Custom Shiny Inputs module 73 | #' 74 | #' @param id to be used to namespace the module 75 | #' @param appData the appData reactiveValues object, defined in server.R and available 76 | #' to all modules 77 | #' 78 | #' @return the module server, returned from a moduleServer function call 79 | #' 80 | #' @export 81 | tab_customInputs_server <- function(id, 82 | appData) { 83 | 84 | moduleServer( 85 | id, 86 | function(input, 87 | output, 88 | session, 89 | appData = appData) { 90 | 91 | # Alias the namespace function for ease of use 92 | ns <- session$ns 93 | 94 | } 95 | ) 96 | 97 | } 98 | -------------------------------------------------------------------------------- /R/mod_31_sessionObject.R: -------------------------------------------------------------------------------- 1 | #' Session Object module 2 | 3 | #' Session Object module UI 4 | #' 5 | #' Defines the UI for the Session Object module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_sessionObject_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Session Object", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "Apps, Clients, Servers, Sessions", 25 | status = "danger", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "Making the most of sessions", 35 | status = "danger", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL, 41 | p("onDisconnect, userData etc.") 42 | ) #end box 43 | ), #end column 44 | column( 45 | width = 6, 46 | box( 47 | title = "Under the hood of the session object", 48 | status = "danger", 49 | icon = icon("info-circle"), 50 | solidHeader = TRUE, 51 | closable = TRUE, 52 | collapsible = TRUE, 53 | width = NULL 54 | ), #end box 55 | 56 | box( 57 | title = "DfE-Specific advice", 58 | status = "danger", 59 | icon = icon("info-circle"), 60 | solidHeader = TRUE, 61 | closable = TRUE, 62 | collapsible = TRUE, 63 | width = NULL 64 | ) #end box 65 | ) #end column 66 | ) #end fluidRow 67 | ) 68 | 69 | } 70 | 71 | #' Session Object module server 72 | #' 73 | #' Defines the server logic for the Session Object module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_sessionObject_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_32_trackingUsage.R: -------------------------------------------------------------------------------- 1 | #' Tracking Usage module 2 | 3 | #' Tracking Usage module UI 4 | #' 5 | #' Defines the UI for the Tracking Usage module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_trackingUsage_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Tracking Usage", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "Why might you want to track app usage?", 25 | status = "info", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "The manual way", 35 | status = "info", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL 41 | ) #end box 42 | ), #end column 43 | column( 44 | width = 6, 45 | box( 46 | title = "The shinylogs way", 47 | status = "info", 48 | icon = icon("info-circle"), 49 | solidHeader = TRUE, 50 | closable = TRUE, 51 | collapsible = TRUE, 52 | width = NULL 53 | ), #end box 54 | 55 | box( 56 | title = "DfE-Specific advice", 57 | status = "info", 58 | icon = icon("info-circle"), 59 | solidHeader = TRUE, 60 | closable = TRUE, 61 | collapsible = TRUE, 62 | width = NULL 63 | ) #end box 64 | ) #end column 65 | ) #end fluidRow 66 | ) 67 | 68 | } 69 | 70 | #' Tracking Usage module server 71 | #' 72 | #' Defines the server logic for the Tracking Usage module 73 | #' 74 | #' @param id to be used to namespace the module 75 | #' @param appData the appData reactiveValues object, defined in server.R and available 76 | #' to all modules 77 | #' 78 | #' @return the module server, returned from a moduleServer function call 79 | #' 80 | #' @export 81 | tab_trackingUsage_server <- function(id, 82 | appData) { 83 | 84 | moduleServer( 85 | id, 86 | function(input, 87 | output, 88 | session, 89 | appData = appData) { 90 | 91 | # Alias the namespace function for ease of use 92 | ns <- session$ns 93 | 94 | } 95 | ) 96 | 97 | } 98 | -------------------------------------------------------------------------------- /R/mod_33_visualisationPlotly.R: -------------------------------------------------------------------------------- 1 | #' Visualisation with plotly module 2 | 3 | #' Visualisation with plotly module UI 4 | #' 5 | #' Defines the UI for the Visualisation with plotly module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_visualisationPlotly_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Visualisation with plotly", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "What is plotly? and what is Plotly? and what is {plotly}?", 25 | status = "black", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL, 31 | p("short version: Plotly created plotly which can be accessed via {plotly}") 32 | ), #end box 33 | 34 | box( 35 | title = "The full extent of interaction and customisability", 36 | status = "black", 37 | icon = icon("info-circle"), 38 | solidHeader = TRUE, 39 | closable = TRUE, 40 | collapsible = TRUE, 41 | width = NULL 42 | ) #end box 43 | ), #end column 44 | column( 45 | width = 6, 46 | box( 47 | title = "{plotly} vs {ggplot2}", 48 | status = "black", 49 | icon = icon("info-circle"), 50 | solidHeader = TRUE, 51 | closable = TRUE, 52 | collapsible = TRUE, 53 | width = NULL 54 | ), #end box 55 | 56 | box( 57 | title = "Some examples", 58 | status = "black", 59 | icon = icon("info-circle"), 60 | solidHeader = TRUE, 61 | closable = TRUE, 62 | collapsible = TRUE, 63 | width = NULL 64 | ) #end box 65 | ) #end column 66 | ) #end fluidRow 67 | ) 68 | 69 | } 70 | 71 | #' Visualisation with plotly module server 72 | #' 73 | #' Defines the server logic for the Visualisation with plotly module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_visualisationPlotly_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_34_visualisationR2D3.R: -------------------------------------------------------------------------------- 1 | #' Visualisation with r2d3 module 2 | 3 | #' Visualisation with r2d3 module UI 4 | #' 5 | #' Defines the UI for the Visualisation with r2d3 module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_visualisationR2D3_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Visualisation with r2d3 et al.", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "What is d3? and what is {r2d3}?", 25 | status = "maroon", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "Complete control (examples)", 35 | status = "maroon", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL 41 | ) #end box 42 | ), #end column 43 | column( 44 | width = 6, 45 | box( 46 | title = "{r2d3} vs {plotly} vs {ggplot2}", 47 | status = "maroon", 48 | icon = icon("info-circle"), 49 | solidHeader = TRUE, 50 | closable = TRUE, 51 | collapsible = TRUE, 52 | width = NULL 53 | ), #end box 54 | 55 | box( 56 | title = "Other JS plotting libraries", 57 | status = "maroon", 58 | icon = icon("info-circle"), 59 | solidHeader = TRUE, 60 | closable = TRUE, 61 | collapsible = TRUE, 62 | width = NULL, 63 | p("e.g. {leaflet}, {dygraphs}, {networkD3}, {echarts4r}, {highcharter}, {sigmajs}") 64 | ) #end box 65 | ) #end column 66 | ) #end fluidRow 67 | ) 68 | 69 | } 70 | 71 | #' Visualisation with r2d3 module server 72 | #' 73 | #' Defines the server logic for the Visualisation with r2d3 module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_visualisationR2D3_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_35_errorHandling.R: -------------------------------------------------------------------------------- 1 | #' Error Handling & Debugging module 2 | 3 | #' Error Handling & Debugging module UI 4 | #' 5 | #' Defines the UI for the Error Handling & Debugging module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_errorHandling_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Error Handling & Debugging", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "With base R", 25 | status = "orange", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL, 31 | p("tryCatch(), withRestarts(), stop(), warning(), message(), browser()") 32 | ), #end box 33 | 34 | box( 35 | title = "With {shiny}", 36 | status = "orange", 37 | icon = icon("info-circle"), 38 | solidHeader = TRUE, 39 | closable = TRUE, 40 | collapsible = TRUE, 41 | width = NULL 42 | ) #end box 43 | ), #end column 44 | column( 45 | width = 6, 46 | box( 47 | title = "With {testthat} and {shinytest}", 48 | status = "orange", 49 | icon = icon("info-circle"), 50 | solidHeader = TRUE, 51 | closable = TRUE, 52 | collapsible = TRUE, 53 | width = NULL 54 | ), #end box 55 | 56 | box( 57 | title = "With {whereami}", 58 | status = "orange", 59 | icon = icon("info-circle"), 60 | solidHeader = TRUE, 61 | closable = TRUE, 62 | collapsible = TRUE, 63 | width = NULL 64 | ) #end box 65 | ) #end column 66 | ) #end fluidRow 67 | ) 68 | 69 | } 70 | 71 | #' Error Handling & Debugging module server 72 | #' 73 | #' Defines the server logic for the Error Handling & Debugging module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_errorHandling_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_36_optimisation.R: -------------------------------------------------------------------------------- 1 | #' Optimisation module 2 | 3 | #' Optimisation module UI 4 | #' 5 | #' Defines the UI for the Optimisation module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_optimisation_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("Optimisation", 18 | class = "tab-title"), 19 | 20 | fluidRow( 21 | column( 22 | width = 6, 23 | box( 24 | title = "Optimising using {profvis}", 25 | status = "success", 26 | icon = icon("info-circle"), 27 | solidHeader = TRUE, 28 | closable = TRUE, 29 | collapsible = TRUE, 30 | width = NULL 31 | ), #end box 32 | 33 | box( 34 | title = "Caching in shiny apps and {memoise}", 35 | status = "success", 36 | icon = icon("info-circle"), 37 | solidHeader = TRUE, 38 | closable = TRUE, 39 | collapsible = TRUE, 40 | width = NULL 41 | ) #end box 42 | ), #end column 43 | column( 44 | width = 6, 45 | box( 46 | title = "Asynchronous programming with {promises} and {future}", 47 | status = "success", 48 | icon = icon("info-circle"), 49 | solidHeader = TRUE, 50 | closable = TRUE, 51 | collapsible = TRUE, 52 | width = NULL 53 | ), #end box 54 | 55 | box( 56 | title = "Some common optimisations", 57 | status = "success", 58 | icon = icon("info-circle"), 59 | solidHeader = TRUE, 60 | closable = TRUE, 61 | collapsible = TRUE, 62 | width = NULL, 63 | p("e.g. multiple tabs, paste>sprintf, data.frame>data.table, grepl^>startsWith, vectorisation/de-looping, use SQL databases, {Rcpp}, {minifyr}") 64 | ) #end box 65 | ) #end column 66 | ) #end fluidRow 67 | ) 68 | 69 | } 70 | 71 | #' Optimisation module server 72 | #' 73 | #' Defines the server logic for the Optimisation module 74 | #' 75 | #' @param id to be used to namespace the module 76 | #' @param appData the appData reactiveValues object, defined in server.R and available 77 | #' to all modules 78 | #' 79 | #' @return the module server, returned from a moduleServer function call 80 | #' 81 | #' @export 82 | tab_optimisation_server <- function(id, 83 | appData) { 84 | 85 | moduleServer( 86 | id, 87 | function(input, 88 | output, 89 | session, 90 | appData = appData) { 91 | 92 | # Alias the namespace function for ease of use 93 | ns <- session$ns 94 | 95 | } 96 | ) 97 | 98 | } 99 | -------------------------------------------------------------------------------- /R/mod_40_references.R: -------------------------------------------------------------------------------- 1 | #' References & Further Materials module 2 | 3 | #' References & Further Materials module UI 4 | #' 5 | #' Defines the UI for the References & Further Materials module 6 | #' 7 | #' @param id to be used to namespace the module 8 | #' 9 | #' @return the module UI, as a tagList 10 | #' 11 | #' @export 12 | tab_references_ui <- function(id) { 13 | 14 | ns <- NS(id) 15 | 16 | tagList( 17 | h3("References & Further Materials", 18 | class = "tab-title") 19 | ) 20 | 21 | } 22 | 23 | #' References & Further Materials module server 24 | #' 25 | #' Defines the server logic for the References & Further Materials module 26 | #' 27 | #' @param id to be used to namespace the module 28 | #' @param appData the appData reactiveValues object, defined in server.R and available 29 | #' to all modules 30 | #' 31 | #' @return the module server, returned from a moduleServer function call 32 | #' 33 | #' @export 34 | tab_references_server <- function(id, 35 | appData) { 36 | 37 | moduleServer( 38 | id, 39 | function(input, 40 | output, 41 | session, 42 | appData = appData) { 43 | 44 | # Alias the namespace function for ease of use 45 | ns <- session$ns 46 | 47 | } 48 | ) 49 | 50 | } 51 | -------------------------------------------------------------------------------- /R/mod_x_template.R: -------------------------------------------------------------------------------- 1 | # NOTE: replace placeholders with module name: modTCx = Title Case; modCCx = camelCase 2 | 3 | #' modTCx module 4 | 5 | #' modTCx module UI 6 | #' 7 | #' Defines the UI for the modTCx module 8 | #' 9 | #' @param id to be used to namespace the module 10 | #' 11 | #' @return the module UI, as a tagList 12 | #' 13 | #' @export 14 | tab_modCCx_ui <- function(id) { 15 | 16 | ns <- NS(id) 17 | 18 | tagList( 19 | h3("modTCx", 20 | class = "tab-title") 21 | ) 22 | 23 | } 24 | 25 | #' modTCx module server 26 | #' 27 | #' Defines the server logic for the modTCx module 28 | #' 29 | #' @param id to be used to namespace the module 30 | #' @param appData the appData reactiveValues object, defined in server.R and available 31 | #' to all modules 32 | #' 33 | #' @return the module server, returned from a moduleServer function call 34 | #' 35 | #' @export 36 | tab_modCCx_server <- function(id, 37 | appData) { 38 | 39 | moduleServer( 40 | id, 41 | function(input, 42 | output, 43 | session, 44 | appData = appData) { 45 | 46 | # Alias the namespace function for ease of use 47 | ns <- session$ns 48 | 49 | } 50 | ) 51 | 52 | } 53 | -------------------------------------------------------------------------------- /R/run_app.R: -------------------------------------------------------------------------------- 1 | #' Run the app 2 | #' 3 | #' Initiate an instance of the 'Intermediate & Advanced Shiny' app. If the current context is interactive, 4 | #' (i.e. if the function is called from RStudio), this function will initiate the app stored in 5 | #' inst/app with the runApp function. If the context is not interactive (i.e. the project is being sourced in RStudio 6 | #' Connect after having been deployed), then the function will return a shiny.appobj object, using the function 7 | #' shinyAppDir. This distinction is necessary to allow the app to be deployed. 8 | #' 9 | #' Note: an alias function 'l' is also provided to speed up workflow (after making changes, load them with 'Ctrl+Shift+L', 10 | #' then launch the app with 'l()') 11 | #' 12 | #' @return either run the app as a side effect or return a shiny.appobj object 13 | #' 14 | #' @importFrom shiny runApp shinyAppDir 15 | #' 16 | #' @export 17 | run_IAS_app <- function() { 18 | 19 | if (interactive()) { 20 | 21 | runApp(appDir = system.file("app", 22 | package = "advancedShiny")) 23 | 24 | } else { 25 | 26 | shinyAppDir(appDir = system.file("app", 27 | package = "advancedShiny")) 28 | 29 | } 30 | 31 | } 32 | 33 | #' @export 34 | l <- run_IAS_app 35 | -------------------------------------------------------------------------------- /R/widget_treant.R: -------------------------------------------------------------------------------- 1 | #' treant htmlwidget 2 | #' 3 | #' interface to the Treant javascript package 4 | #' 5 | #' @param structure a list of lists denoting the structure of the tree to be built 6 | #' 7 | #' @export 8 | treant <- function(structure, width = NULL, height = NULL) { 9 | 10 | # forward options using x 11 | x = list( 12 | chart = list( 13 | container = "", 14 | rootOrientation = "NORTH", 15 | nodeAlign = "BOTTOM", 16 | connectors = list( 17 | type = "step" 18 | ), 19 | node = list( 20 | HTMLclass = "treant-node", 21 | collapsable = TRUE 22 | ) 23 | ), 24 | 25 | nodeStructure = structure 26 | ) 27 | 28 | # create widget 29 | htmlwidgets::createWidget( 30 | name = 'treant', 31 | x, 32 | width = width, 33 | height = height, 34 | package = 'advancedShiny' 35 | ) 36 | } 37 | 38 | #' Define treant tree node 39 | #' 40 | #' Helper function for defining tree structure, helps 41 | #' to create trees/nodes with less code 42 | #' 43 | #' @param name the name of the node 44 | #' @param desc the description of the node 45 | #' @param children a list of children nodes 46 | #' 47 | #' @export 48 | node <- function(name, desc, children = NULL, ...) { 49 | list( 50 | text = list(name = name, 51 | desc = desc), 52 | ..., 53 | children = children 54 | ) 55 | } 56 | 57 | #' Shiny bindings for treant 58 | #' 59 | #' Output and render functions for using treant within Shiny 60 | #' applications and interactive Rmd documents. 61 | #' 62 | #' @param outputId output variable to read from 63 | #' @param width,height Must be a valid CSS unit (like \code{'100\%'}, 64 | #' \code{'400px'}, \code{'auto'}) or a number, which will be coerced to a 65 | #' string and have \code{'px'} appended. 66 | #' @param expr An expression that generates a treant 67 | #' @param env The environment in which to evaluate \code{expr}. 68 | #' @param quoted Is \code{expr} a quoted expression (with \code{quote()})? This 69 | #' is useful if you want to save an expression in a variable. 70 | #' 71 | #' @name treant-shiny 72 | #' 73 | #' @export 74 | treantOutput <- function(outputId, width = '100%', height = '400px'){ 75 | htmlwidgets::shinyWidgetOutput(outputId, 'treant', width, height, package = 'advancedShiny') 76 | } 77 | 78 | #' @rdname treant-shiny 79 | #' @export 80 | renderTreant <- function(expr, env = parent.frame(), quoted = FALSE) { 81 | if (!quoted) { expr <- substitute(expr) } # force quoted 82 | htmlwidgets::shinyRenderWidget(expr, treantOutput, env, quoted = TRUE) 83 | } 84 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | # Set some variables for the info badges 9 | status <- "development-orange" 10 | pkg_version <- paste(pkgload::pkg_version(), collapse = ".") 11 | 12 | # Get badges based on variables (converted to png because Azure Devops doesn't render SVG) 13 | download.file(url = paste0("https://img.shields.io/badge/version-", pkg_version, "-blue.svg"), 14 | destfile = "inst/static/pkg-version-badge.svg") 15 | rsvg::rsvg_png(svg = "inst/static/pkg-version-badge.svg", 16 | file = "inst/static/pkg-version-badge.png") 17 | 18 | download.file(url = paste0("https://img.shields.io/badge/status-", status, ".svg"), 19 | destfile = "inst/static/app-status-badge.svg") 20 | rsvg::rsvg_png(svg = "inst/static/app-status-badge.svg", 21 | file = "inst/static/app-status-badge.png") 22 | ``` 23 | 24 | # advancedShiny 25 | 26 | 27 | ![version: num](inst/static/pkg-version-badge.png) 28 | ![status: status](inst/static/app-status-badge.png) 29 | 30 | 31 | The goal of advancedShiny is to provide an R Shiny application which can showcase some intermediate & advanced R Shiny techniques to DfE colleagues at Coffee & Coding sessions. 32 | 33 | ## Installation 34 | 35 | You can install advancedShiny from [GitHub](https://github.com/chrisbrownlie/advancedShiny) with: 36 | 37 | ``` r 38 | # install.packages("devtools") 39 | devtools::install_github("chrisbrownlie/advancedShiny") 40 | ``` 41 | ## Usage 42 | 43 | The app can be run with the following command: 44 | 45 | ```{r eval=FALSE} 46 | library(advancedShiny) 47 | run_IAS_app() 48 | ``` 49 | 50 | # More info 51 | See TODO.md for a more detailed plan and structure of what the app will contain or contact [Chris Brownlie](mailto:chris.brownlie@hotmail.co.uk) for more information. 52 | 53 | # Acknowledgements 54 | Thanks to the RStudio team for the shiny package, and to the people and organisations who have contributed to the development of shiny & R, including (but not limited to): Dean Attali, Appsilon, dreamRs, thinkR & Guangchang Yu. Much of this package and app builds from their work and I encourage you to check out their work if you want to become a shiny wizard. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # advancedShiny 5 | 6 | 7 | 8 | ![version: num](inst/static/pkg-version-badge.png) ![status: 9 | status](inst/static/app-status-badge.png) 10 | 11 | The goal of advancedShiny is to provide an R Shiny application which can 12 | showcase some intermediate & advanced R Shiny techniques to DfE 13 | colleagues at Coffee & Coding sessions. 14 | 15 | ## Installation 16 | 17 | You can install advancedShiny from 18 | [GitHub](https://github.com/chrisbrownlie/advancedShiny) with: 19 | 20 | ``` r 21 | # install.packages("devtools") 22 | devtools::install_github("chrisbrownlie/advancedShiny") 23 | ``` 24 | 25 | ## Usage 26 | 27 | The app can be run with the following command: 28 | 29 | ``` r 30 | library(advancedShiny) 31 | run_IAS_app() 32 | ``` 33 | 34 | # More info 35 | 36 | See TODO.md for a more detailed plan and structure of what the app will 37 | contain or contact [Chris Brownlie](mailto:chris.brownlie@hotmail.co.uk) 38 | for more information. 39 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Plan/To Do 2 | 3 | ## Basic principles 4 | - shinydashboard layout 5 | - a module per tab to keep code easy to navigate/maintain 6 | - using fluid structure { fluidRow() -> column(width=..) -> shinydashboardPlus::box(width=NULL) } as the basis for every tabs ui 7 | - each box: single topic; valid title; solid header; consistent status/colours; collapsible & closable where desired 8 | - include code snippets where possible/appropriate, using the code_snippet() function (see R/fct_utils.R) 9 | - file naming conventions adhered to for any functions etc. that are required 10 | 11 | ## Plan for each tab: 12 | (Bullet points indicate rough/minimum points to cover, initials in brackets indicate who will complete) 13 | 14 | - [x] Info (CB) 15 | - What the app is 16 | - How to use it 17 | - Important points 18 | 19 | ### SECTION 1 20 | - [x] What is Shiny, actually? (CB) 21 | - What a web app is 22 | - How shiny converts R to HTML, JS and CSS 23 | - Shiny dependencies (httpuv etc.) 24 | 25 | - [x] Understanding reactivity (CB) 26 | - How reactivity makes a pull relationship look like a push relationship 27 | - Graph showing the flushing cycle and reactive graph 28 | - reactlog 29 | 30 | - [x] Using reactivity (CB) 31 | - Types of object (reactive values, expressions, outputs) 32 | - When to use reactive vs observe 33 | - Including observeEvent vs eventReactive 34 | 35 | - [x] Controlling reactivity (CB) 36 | - Using debounce & throttle 37 | - Using invalidateLater & reactivePoll 38 | - Using isolate & req 39 | 40 | - [x] Structuring an app (CB) 41 | - As a package 42 | - File naming conventions 43 | - Workflow (using roxygen2, devtools, usethis etc.) 44 | - Making use of reactivevalues not being copy-on-modify 45 | - Using modules (briefly mention, covered in next tab) 46 | 47 | - [x ] Shiny modules (CB) 48 | - The 1000 button problem 49 | - Namespacing 50 | - Using modules effectively 51 | 52 | ### SECTION 2 53 | - [ ] Improving UI with CSS 54 | - Key choices when designing shiny apps - choice between shinydashboard[Plus] or shiny+bslib (or other) 55 | - What is CSS and how to include in shiny 56 | - Using Sass 57 | 58 | - [ ] Improving UX with JS 59 | - What is JS 60 | - Ways to include JS in shiny 61 | - Some example use cases 62 | - Briefly mention shinyjs (covered in next tab) 63 | 64 | - [ ] The attaliverse 65 | - What is attaliverse 66 | - List all the packages 67 | - shinyjs 68 | - Some details of each, minimum include some detail for each of (shinyalert, shinycssloaders, shinydisconnect, shinybrowser) 69 | 70 | - [ ] Extending shiny (CB) 71 | - The power of javascript 72 | - Packages which extend/improve shiny (e.g. shinyhelper, shinyFeedback, shinyEffects) 73 | - Creating your own widget with htmlwidgets 74 | 75 | - [ ] Custom shiny inputs (CB) 76 | - Types of inputs in shiny & other packages 77 | - Input bindings and events 78 | - Creating your own input element 79 | - charpente 80 | 81 | ### SECTION 3 82 | - [ ] The session object (CB) 83 | - Apps, sessions and users 84 | - Elements of the session object and what they are useful for 85 | - DfE-specific 86 | 87 | - [ ] Tracking usage 88 | - Why it can be useful 89 | - Custom methods (observers, save to sql etc.) 90 | - shinylogs 91 | 92 | - [ ] Advanced Visualisation 1 (plotly) 93 | - The basics of plotly 94 | - plotly vs ggplot2 95 | - Possibilities with plotly 96 | 97 | - [ ] Advanced Visualisation 2 (r2d3 + other js libs) (CB) 98 | - When to use r2d3 vs plotly/ggplot2 99 | - Extent of control 100 | - How to use js visualisations in shiny 101 | 102 | - [ ] Error handling & Debugging 103 | - base R error handling (tryCatch, withRestarts) 104 | - shiny-specific error handling (validate, safeError) 105 | - unit testing (briefly) and shiny testing (shinytest, testServer, testModule) 106 | - whereami 107 | 108 | - [ ] Optimisation 109 | - profvis 110 | - Caching 111 | - Async/futureverse 112 | -------------------------------------------------------------------------------- /app.R: -------------------------------------------------------------------------------- 1 | pkgload::load_all() 2 | advancedShiny::run_IAS_app() -------------------------------------------------------------------------------- /inst/app/global.R: -------------------------------------------------------------------------------- 1 | # Set variables which are available at the beginning of all sessions 2 | -------------------------------------------------------------------------------- /inst/app/server.R: -------------------------------------------------------------------------------- 1 | # Important: return the function itself rather than the output of the function 2 | advancedShiny:::app_server -------------------------------------------------------------------------------- /inst/app/ui.R: -------------------------------------------------------------------------------- 1 | # Create the ui object using the unexported app_ui function 2 | ui <- advancedShiny:::app_ui() -------------------------------------------------------------------------------- /inst/app/www/.sass_cache_keys: -------------------------------------------------------------------------------- 1 | 5532b373c7254f6f601a353f4b6d33a4 -------------------------------------------------------------------------------- /inst/app/www/advancedShiny.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisbrownlie/advancedShiny/54872944139f995c1b62b612927afb7f3035d8cf/inst/app/www/advancedShiny.ico -------------------------------------------------------------------------------- /inst/app/www/clipboard.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * clipboard.js v2.0.8 3 | * https://clipboardjs.com/ 4 | * 5 | * Licensed MIT © Zeno Rocha 6 | */ 7 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 2 | _______ _ _ 3 | |__ __| | | (_) 4 | | |_ __ ___ __ _ _ __ | |_ ______ _ ___ 5 | | | '__/ _ \/ _` | '_ \| __|______| / __| 6 | | | | | __/ (_| | | | | |_ | \__ \ 7 | |_|_| \___|\__,_|_| |_|\__| | |___/ 8 | _/ | 9 | |__/ 10 | 11 | 12 | Treant-js is an SVG based JS library for drawing tree diagrams. 13 | It relies on Raphael for handling SVG and animations. 14 | 15 | For Docs, Examples, and everything else see: 16 | http://fperucic.github.io/treant-js 17 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/Treant.css: -------------------------------------------------------------------------------- 1 | /* required LIB STYLES */ 2 | /* .Treant se automatski dodaje na svaki chart conatiner */ 3 | .Treant { position: relative; overflow: hidden; padding: 0 !important; } 4 | .Treant > .node, 5 | .Treant > .pseudo { position: absolute; display: block; visibility: hidden; } 6 | .Treant.Treant-loaded .node, 7 | .Treant.Treant-loaded .pseudo { visibility: visible; } 8 | .Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; } 9 | .Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; } 10 | .Treant .collapsed .collapse-switch { background-color: #868DEE; } 11 | .Treant > .node img { border: none; float: left; } -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/build: -------------------------------------------------------------------------------- 1 | java -jar {path}/compiler.jar --compilation_level SIMPLE_OPTIMIZATIONS --warning_level QUIET --externs jquery.min.js --externs perfect-scrollbar/perfect-scrollbar.js --externs raphael.js --language_in ECMASCRIPT5 --js Treant.js --js_output_file Treant.min.js 2 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/jquery.easing.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ 3 | * 4 | * Uses the built in easing capabilities added In jQuery 1.1 5 | * to offer multiple easing options 6 | * 7 | * TERMS OF USE - jQuery Easing 8 | * 9 | * Open source under the BSD License. 10 | * 11 | * Copyright © 2008 George McGinley Smith 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * Redistributions of source code must retain the above copyright notice, this list of 18 | * conditions and the following disclaimer. 19 | * Redistributions in binary form must reproduce the above copyright notice, this list 20 | * of conditions and the following disclaimer in the documentation and/or other materials 21 | * provided with the distribution. 22 | * 23 | * Neither the name of the author nor the names of contributors may be used to endorse 24 | * or promote products derived from this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 27 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 31 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 34 | * OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | */ 37 | 38 | // t: current time, b: begInnIng value, c: change In value, d: duration 39 | jQuery.easing['jswing'] = jQuery.easing['swing']; 40 | 41 | jQuery.extend( jQuery.easing, 42 | { 43 | def: 'easeOutQuad', 44 | swing: function (x, t, b, c, d) { 45 | //alert(jQuery.easing.default); 46 | return jQuery.easing[jQuery.easing.def](x, t, b, c, d); 47 | }, 48 | easeInQuad: function (x, t, b, c, d) { 49 | return c*(t/=d)*t + b; 50 | }, 51 | easeOutQuad: function (x, t, b, c, d) { 52 | return -c *(t/=d)*(t-2) + b; 53 | }, 54 | easeInOutQuad: function (x, t, b, c, d) { 55 | if ((t/=d/2) < 1) return c/2*t*t + b; 56 | return -c/2 * ((--t)*(t-2) - 1) + b; 57 | }, 58 | easeInCubic: function (x, t, b, c, d) { 59 | return c*(t/=d)*t*t + b; 60 | }, 61 | easeOutCubic: function (x, t, b, c, d) { 62 | return c*((t=t/d-1)*t*t + 1) + b; 63 | }, 64 | easeInOutCubic: function (x, t, b, c, d) { 65 | if ((t/=d/2) < 1) return c/2*t*t*t + b; 66 | return c/2*((t-=2)*t*t + 2) + b; 67 | }, 68 | easeInQuart: function (x, t, b, c, d) { 69 | return c*(t/=d)*t*t*t + b; 70 | }, 71 | easeOutQuart: function (x, t, b, c, d) { 72 | return -c * ((t=t/d-1)*t*t*t - 1) + b; 73 | }, 74 | easeInOutQuart: function (x, t, b, c, d) { 75 | if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 76 | return -c/2 * ((t-=2)*t*t*t - 2) + b; 77 | }, 78 | easeInQuint: function (x, t, b, c, d) { 79 | return c*(t/=d)*t*t*t*t + b; 80 | }, 81 | easeOutQuint: function (x, t, b, c, d) { 82 | return c*((t=t/d-1)*t*t*t*t + 1) + b; 83 | }, 84 | easeInOutQuint: function (x, t, b, c, d) { 85 | if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 86 | return c/2*((t-=2)*t*t*t*t + 2) + b; 87 | }, 88 | easeInSine: function (x, t, b, c, d) { 89 | return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 90 | }, 91 | easeOutSine: function (x, t, b, c, d) { 92 | return c * Math.sin(t/d * (Math.PI/2)) + b; 93 | }, 94 | easeInOutSine: function (x, t, b, c, d) { 95 | return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 96 | }, 97 | easeInExpo: function (x, t, b, c, d) { 98 | return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 99 | }, 100 | easeOutExpo: function (x, t, b, c, d) { 101 | return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 102 | }, 103 | easeInOutExpo: function (x, t, b, c, d) { 104 | if (t==0) return b; 105 | if (t==d) return b+c; 106 | if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 107 | return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 108 | }, 109 | easeInCirc: function (x, t, b, c, d) { 110 | return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 111 | }, 112 | easeOutCirc: function (x, t, b, c, d) { 113 | return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 114 | }, 115 | easeInOutCirc: function (x, t, b, c, d) { 116 | if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 117 | return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 118 | }, 119 | easeInElastic: function (x, t, b, c, d) { 120 | var s=1.70158;var p=0;var a=c; 121 | if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 122 | if (a < Math.abs(c)) { a=c; var s=p/4; } 123 | else var s = p/(2*Math.PI) * Math.asin (c/a); 124 | return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 125 | }, 126 | easeOutElastic: function (x, t, b, c, d) { 127 | var s=1.70158;var p=0;var a=c; 128 | if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 129 | if (a < Math.abs(c)) { a=c; var s=p/4; } 130 | else var s = p/(2*Math.PI) * Math.asin (c/a); 131 | return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 132 | }, 133 | easeInOutElastic: function (x, t, b, c, d) { 134 | var s=1.70158;var p=0;var a=c; 135 | if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 136 | if (a < Math.abs(c)) { a=c; var s=p/4; } 137 | else var s = p/(2*Math.PI) * Math.asin (c/a); 138 | if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 139 | return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 140 | }, 141 | easeInBack: function (x, t, b, c, d, s) { 142 | if (s == undefined) s = 1.70158; 143 | return c*(t/=d)*t*((s+1)*t - s) + b; 144 | }, 145 | easeOutBack: function (x, t, b, c, d, s) { 146 | if (s == undefined) s = 1.70158; 147 | return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 148 | }, 149 | easeInOutBack: function (x, t, b, c, d, s) { 150 | if (s == undefined) s = 1.70158; 151 | if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 152 | return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 153 | }, 154 | easeInBounce: function (x, t, b, c, d) { 155 | return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; 156 | }, 157 | easeOutBounce: function (x, t, b, c, d) { 158 | if ((t/=d) < (1/2.75)) { 159 | return c*(7.5625*t*t) + b; 160 | } else if (t < (2/2.75)) { 161 | return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 162 | } else if (t < (2.5/2.75)) { 163 | return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 164 | } else { 165 | return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 166 | } 167 | }, 168 | easeInOutBounce: function (x, t, b, c, d) { 169 | if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; 170 | return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; 171 | } 172 | }); 173 | 174 | /* 175 | * 176 | * TERMS OF USE - EASING EQUATIONS 177 | * 178 | * Open source under the BSD License. 179 | * 180 | * Copyright © 2001 Robert Penner 181 | * All rights reserved. 182 | * 183 | * Redistribution and use in source and binary forms, with or without modification, 184 | * are permitted provided that the following conditions are met: 185 | * 186 | * Redistributions of source code must retain the above copyright notice, this list of 187 | * conditions and the following disclaimer. 188 | * Redistributions in binary form must reproduce the above copyright notice, this list 189 | * of conditions and the following disclaimer in the documentation and/or other materials 190 | * provided with the distribution. 191 | * 192 | * Neither the name of the author nor the names of contributors may be used to endorse 193 | * or promote products derived from this software without specific prior written permission. 194 | * 195 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 196 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 197 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 198 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 199 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 200 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 201 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 202 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 203 | * OF THE POSSIBILITY OF SUCH DAMAGE. 204 | * 205 | */ -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/jquery.mousewheel.js: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 2 | * Licensed under the MIT License (LICENSE.txt). 3 | * 4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6 | * Thanks to: Seamus Leahy for adding deltaX and deltaY 7 | * 8 | * Version: 3.0.6 9 | * 10 | * Requires: 1.2.2+ 11 | */ 12 | 13 | (function($) { 14 | 15 | var types = ['DOMMouseScroll', 'mousewheel']; 16 | 17 | if ($.event.fixHooks) { 18 | for ( var i=types.length; i; ) { 19 | $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; 20 | } 21 | } 22 | 23 | $.event.special.mousewheel = { 24 | setup: function() { 25 | if ( this.addEventListener ) { 26 | for ( var i=types.length; i; ) { 27 | this.addEventListener( types[--i], handler, false ); 28 | } 29 | } else { 30 | this.onmousewheel = handler; 31 | } 32 | }, 33 | 34 | teardown: function() { 35 | if ( this.removeEventListener ) { 36 | for ( var i=types.length; i; ) { 37 | this.removeEventListener( types[--i], handler, false ); 38 | } 39 | } else { 40 | this.onmousewheel = null; 41 | } 42 | } 43 | }; 44 | 45 | $.fn.extend({ 46 | mousewheel: function(fn) { 47 | return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 48 | }, 49 | 50 | unmousewheel: function(fn) { 51 | return this.unbind("mousewheel", fn); 52 | } 53 | }); 54 | 55 | 56 | function handler(event) { 57 | var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; 58 | event = $.event.fix(orgEvent); 59 | event.type = "mousewheel"; 60 | 61 | // Old school scrollwheel delta 62 | if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; } 63 | if ( orgEvent.detail ) { delta = -orgEvent.detail/3; } 64 | 65 | // New school multidimensional scroll (touchpads) deltas 66 | deltaY = delta; 67 | 68 | // Gecko 69 | if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { 70 | deltaY = 0; 71 | deltaX = -1*delta; 72 | } 73 | 74 | // Webkit 75 | if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } 76 | if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } 77 | 78 | // Add event and delta to the front of the arguments 79 | args.unshift(event, delta, deltaX, deltaY); 80 | 81 | return ($.event.dispatch || $.event.handle).apply(this, args); 82 | } 83 | 84 | })(jQuery); 85 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "treantjs", 3 | "version": "1.0.0", 4 | "description": "JavaScipt library for visualization of tree diagrams", 5 | "main": "Treant.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/fperucic/treant-js.git" 15 | }, 16 | "keywords": [ 17 | "treant", 18 | "diagram", 19 | "tree", 20 | "js", 21 | "svg", 22 | "draw" 23 | ], 24 | "author": "Fran Peručić", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/fperucic/treant-js/issues" 28 | }, 29 | "homepage": "https://github.com/fperucic/treant-js#readme" 30 | } -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/perfect-scrollbar.css: -------------------------------------------------------------------------------- 1 | .ps-container .ps-scrollbar-x { 2 | position: absolute; /* please don't change 'position' */ 3 | bottom: 3px; /* there must be 'bottom' for ps-scrollbar-x */ 4 | height: 8px; 5 | background-color: #aaa; 6 | border-radius: 4px; 7 | -webkit-border-radius: 4px; 8 | -moz-border-radius: 4px; 9 | opacity: 0; 10 | filter: alpha(opacity = 0); 11 | -webkit-transition: opacity.2s linear; 12 | -moz-transition: opacity .2s linear; 13 | transition: opacity .2s linear; 14 | } 15 | 16 | .ps-container:hover .ps-scrollbar-x { 17 | opacity: 0.6; 18 | filter: alpha(opacity = 60); 19 | } 20 | 21 | .ps-container .ps-scrollbar-x:hover { 22 | opacity: 0.9; 23 | filter: alpha(opacity = 90); 24 | cursor:default; 25 | } 26 | 27 | .ps-container .ps-scrollbar-x.in-scrolling { 28 | opacity: 0.9; 29 | filter: alpha(opacity = 90); 30 | } 31 | 32 | .ps-container .ps-scrollbar-y { 33 | position: absolute; /* please don't change 'position' */ 34 | right: 3px; /* there must be 'right' for ps-scrollbar-y */ 35 | width: 8px; 36 | background-color: #aaa; 37 | border-radius: 4px; 38 | -webkit-border-radius: 4px; 39 | -moz-border-radius: 4px; 40 | opacity: 0; 41 | filter: alpha(opacity = 0); 42 | -webkit-transition: opacity.2s linear; 43 | -moz-transition: opacity .2s linear; 44 | transition: opacity .2s linear; 45 | } 46 | 47 | .ps-container:hover .ps-scrollbar-y { 48 | opacity: 0.6; 49 | filter: alpha(opacity = 60); 50 | } 51 | 52 | .ps-container .ps-scrollbar-y:hover { 53 | opacity: 0.9; 54 | filter: alpha(opacity = 90); 55 | cursor: default; 56 | } 57 | 58 | .ps-container .ps-scrollbar-y.in-scrolling { 59 | opacity: 0.9; 60 | filter: alpha(opacity = 90); 61 | } 62 | -------------------------------------------------------------------------------- /inst/htmlwidgets/lib/Treant-1.0.0/perfect-scrollbar.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 HyeonJe Jun (http://github.com/noraesae) 2 | * Licensed under the MIT License 3 | */ 4 | ((function($) { 5 | 6 | // The default settings for the plugin 7 | var defaultSettings = { 8 | wheelSpeed: 10, 9 | wheelPropagation: false 10 | }; 11 | 12 | $.fn.perfectScrollbar = function(suppliedSettings, option) { 13 | 14 | // Use the default settings 15 | var settings = $.extend( true, {}, defaultSettings ); 16 | if (typeof suppliedSettings === "object") { 17 | // But over-ride any supplied 18 | $.extend( true, settings, suppliedSettings ); 19 | } else { 20 | // If no settings were supplied, then the first param must be the option 21 | option = suppliedSettings; 22 | } 23 | 24 | if(option === 'update') { 25 | if($(this).data('perfect_scrollbar_update')) { 26 | $(this).data('perfect_scrollbar_update')(); 27 | } 28 | return $(this); 29 | } 30 | else if(option === 'destroy') { 31 | if($(this).data('perfect_scrollbar_destroy')) { 32 | $(this).data('perfect_scrollbar_destroy')(); 33 | } 34 | return $(this); 35 | } 36 | 37 | if($(this).data('perfect_scrollbar')) { 38 | // if there's already perfect_scrollbar 39 | return $(this).data('perfect_scrollbar'); 40 | } 41 | 42 | var $this = $(this).addClass('ps-container'), 43 | $content = $(this).children(), 44 | $scrollbar_x = $("
").appendTo($this), 45 | $scrollbar_y = $("
").appendTo($this), 46 | container_width, 47 | container_height, 48 | content_width, 49 | content_height, 50 | scrollbar_x_width, 51 | scrollbar_x_left, 52 | scrollbar_x_bottom = parseInt($scrollbar_x.css('bottom'), 10), 53 | scrollbar_y_height, 54 | scrollbar_y_top, 55 | scrollbar_y_right = parseInt($scrollbar_y.css('right'), 10); 56 | 57 | var updateContentScrollTop = function() { 58 | var scroll_top = parseInt(scrollbar_y_top * content_height / container_height, 10); 59 | $this.scrollTop(scroll_top); 60 | $scrollbar_x.css({bottom: scrollbar_x_bottom - scroll_top}); 61 | }; 62 | 63 | var updateContentScrollLeft = function() { 64 | var scroll_left = parseInt(scrollbar_x_left * content_width / container_width, 10); 65 | $this.scrollLeft(scroll_left); 66 | $scrollbar_y.css({right: scrollbar_y_right - scroll_left}); 67 | }; 68 | 69 | var updateBarSizeAndPosition = function() { 70 | container_width = $this.width(); 71 | container_height = $this.height(); 72 | content_width = $content.outerWidth(false); 73 | content_height = $content.outerHeight(false); 74 | if(container_width < content_width) { 75 | scrollbar_x_width = parseInt(container_width * container_width / content_width, 10); 76 | scrollbar_x_left = parseInt($this.scrollLeft() * container_width / content_width, 10); 77 | } 78 | else { 79 | scrollbar_x_width = 0; 80 | scrollbar_x_left = 0; 81 | $this.scrollLeft(0); 82 | } 83 | if(container_height < content_height) { 84 | scrollbar_y_height = parseInt(container_height * container_height / content_height, 10); 85 | scrollbar_y_top = parseInt($this.scrollTop() * container_height / content_height, 10); 86 | } 87 | else { 88 | scrollbar_y_height = 0; 89 | scrollbar_y_left = 0; 90 | $this.scrollTop(0); 91 | } 92 | 93 | $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft(), bottom: scrollbar_x_bottom - $this.scrollTop(), width: scrollbar_x_width}); 94 | $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop(), right: scrollbar_y_right - $this.scrollLeft(), height: scrollbar_y_height}); 95 | }; 96 | 97 | var moveBarX = function(current_left, delta_x) { 98 | var new_left = current_left + delta_x, 99 | max_left = container_width - scrollbar_x_width; 100 | 101 | if(new_left < 0) { 102 | scrollbar_x_left = 0; 103 | } 104 | else if(new_left > max_left) { 105 | scrollbar_x_left = max_left; 106 | } 107 | else { 108 | scrollbar_x_left = new_left; 109 | } 110 | $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft()}); 111 | }; 112 | 113 | var moveBarY = function(current_top, delta_y) { 114 | var new_top = current_top + delta_y, 115 | max_top = container_height - scrollbar_y_height; 116 | 117 | if(new_top < 0) { 118 | scrollbar_y_top = 0; 119 | } 120 | else if(new_top > max_top) { 121 | scrollbar_y_top = max_top; 122 | } 123 | else { 124 | scrollbar_y_top = new_top; 125 | } 126 | $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop()}); 127 | }; 128 | 129 | var bindMouseScrollXHandler = function() { 130 | var current_left, 131 | current_page_x; 132 | 133 | $scrollbar_x.bind('mousedown.perfect-scroll', function(e) { 134 | current_page_x = e.pageX; 135 | current_left = $scrollbar_x.position().left; 136 | $scrollbar_x.addClass('in-scrolling'); 137 | e.stopPropagation(); 138 | e.preventDefault(); 139 | }); 140 | 141 | $(document).bind('mousemove.perfect-scroll', function(e) { 142 | if($scrollbar_x.hasClass('in-scrolling')) { 143 | moveBarX(current_left, e.pageX - current_page_x); 144 | updateContentScrollLeft(); 145 | e.stopPropagation(); 146 | e.preventDefault(); 147 | } 148 | }); 149 | 150 | $(document).bind('mouseup.perfect-scroll', function(e) { 151 | if($scrollbar_x.hasClass('in-scrolling')) { 152 | $scrollbar_x.removeClass('in-scrolling'); 153 | } 154 | }); 155 | }; 156 | 157 | var bindMouseScrollYHandler = function() { 158 | var current_top, 159 | current_page_y; 160 | 161 | $scrollbar_y.bind('mousedown.perfect-scroll', function(e) { 162 | current_page_y = e.pageY; 163 | current_top = $scrollbar_y.position().top; 164 | $scrollbar_y.addClass('in-scrolling'); 165 | e.stopPropagation(); 166 | e.preventDefault(); 167 | }); 168 | 169 | $(document).bind('mousemove.perfect-scroll', function(e) { 170 | if($scrollbar_y.hasClass('in-scrolling')) { 171 | moveBarY(current_top, e.pageY - current_page_y); 172 | updateContentScrollTop(); 173 | e.stopPropagation(); 174 | e.preventDefault(); 175 | } 176 | }); 177 | 178 | $(document).bind('mouseup.perfect-scroll', function(e) { 179 | if($scrollbar_y.hasClass('in-scrolling')) { 180 | $scrollbar_y.removeClass('in-scrolling'); 181 | } 182 | }); 183 | }; 184 | 185 | // bind handlers 186 | var bindMouseWheelHandler = function() { 187 | var shouldPreventDefault = function(deltaX, deltaY) { 188 | var scrollTop = $this.scrollTop(); 189 | if(scrollTop === 0 && deltaY > 0 && deltaX === 0) { 190 | return !settings.wheelPropagation; 191 | } 192 | else if(scrollTop >= content_height - container_height && deltaY < 0 && deltaX === 0) { 193 | return !settings.wheelPropagation; 194 | } 195 | 196 | var scrollLeft = $this.scrollLeft(); 197 | if(scrollLeft === 0 && deltaX < 0 && deltaY === 0) { 198 | return !settings.wheelPropagation; 199 | } 200 | else if(scrollLeft >= content_width - container_width && deltaX > 0 && deltaY === 0) { 201 | return !settings.wheelPropagation; 202 | } 203 | return true; 204 | }; 205 | 206 | $this.mousewheel(function(e, delta, deltaX, deltaY) { 207 | $this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed)); 208 | $this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed)); 209 | 210 | // update bar position 211 | updateBarSizeAndPosition(); 212 | 213 | if(shouldPreventDefault(deltaX, deltaY)) { 214 | e.preventDefault(); 215 | } 216 | }); 217 | }; 218 | 219 | // bind mobile touch handler 220 | var bindMobileTouchHandler = function() { 221 | var applyTouchMove = function(difference_x, difference_y) { 222 | $this.scrollTop($this.scrollTop() - difference_y); 223 | $this.scrollLeft($this.scrollLeft() - difference_x); 224 | 225 | // update bar position 226 | updateBarSizeAndPosition(); 227 | }; 228 | 229 | var start_coords = {}, 230 | start_time = 0, 231 | speed = {}, 232 | breaking_process = null; 233 | 234 | $this.bind("touchstart.perfect-scroll", function(e) { 235 | var touch = e.originalEvent.targetTouches[0]; 236 | 237 | start_coords.pageX = touch.pageX; 238 | start_coords.pageY = touch.pageY; 239 | 240 | start_time = (new Date()).getTime(); 241 | 242 | if (breaking_process !== null) { 243 | clearInterval(breaking_process); 244 | } 245 | }); 246 | $this.bind("touchmove.perfect-scroll", function(e) { 247 | var touch = e.originalEvent.targetTouches[0]; 248 | 249 | var current_coords = {}; 250 | current_coords.pageX = touch.pageX; 251 | current_coords.pageY = touch.pageY; 252 | 253 | var difference_x = current_coords.pageX - start_coords.pageX, 254 | difference_y = current_coords.pageY - start_coords.pageY; 255 | 256 | applyTouchMove(difference_x, difference_y); 257 | start_coords = current_coords; 258 | 259 | var current_time = (new Date()).getTime(); 260 | speed.x = difference_x / (current_time - start_time); 261 | speed.y = difference_y / (current_time - start_time); 262 | start_time = current_time; 263 | 264 | e.preventDefault(); 265 | }); 266 | $this.bind("touchend.perfect-scroll", function(e) { 267 | breaking_process = setInterval(function() { 268 | if(Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { 269 | clearInterval(breaking_process); 270 | return; 271 | } 272 | 273 | applyTouchMove(speed.x * 30, speed.y * 30); 274 | 275 | speed.x *= 0.8; 276 | speed.y *= 0.8; 277 | }, 10); 278 | }); 279 | }; 280 | 281 | var destroy = function() { 282 | $scrollbar_x.remove(); 283 | $scrollbar_y.remove(); 284 | $this.unbind('mousewheel'); 285 | $this.unbind('touchstart.perfect-scroll'); 286 | $this.unbind('touchmove.perfect-scroll'); 287 | $this.unbind('touchend.perfect-scroll'); 288 | $(window).unbind('mousemove.perfect-scroll'); 289 | $(window).unbind('mouseup.perfect-scroll'); 290 | $this.data('perfect_scrollbar', null); 291 | $this.data('perfect_scrollbar_update', null); 292 | $this.data('perfect_scrollbar_destroy', null); 293 | }; 294 | 295 | var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent); 296 | 297 | var initialize = function() { 298 | updateBarSizeAndPosition(); 299 | bindMouseScrollXHandler(); 300 | bindMouseScrollYHandler(); 301 | if(isMobile) bindMobileTouchHandler(); 302 | if($this.mousewheel) bindMouseWheelHandler(); 303 | $this.data('perfect_scrollbar', $this); 304 | $this.data('perfect_scrollbar_update', updateBarSizeAndPosition); 305 | $this.data('perfect_scrollbar_destroy', destroy); 306 | }; 307 | 308 | // initialize 309 | initialize(); 310 | 311 | return $this; 312 | }; 313 | })(jQuery)); 314 | -------------------------------------------------------------------------------- /inst/htmlwidgets/treant.js: -------------------------------------------------------------------------------- 1 | HTMLWidgets.widget({ 2 | 3 | name: "treant", 4 | 5 | type: "output", 6 | 7 | factory: function(el, width, height) { 8 | 9 | return { 10 | renderValue: function(x) { 11 | 12 | x.chart.container = '#' + el.id 13 | 14 | // create the treant object and return it 15 | var tre = new Treant(x); 16 | tre 17 | } 18 | }; 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /inst/htmlwidgets/treant.yaml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: treant 3 | version: 1.0.0 4 | src: htmlwidgets/lib/Treant-1.0.0 5 | script: 6 | - Treant.js 7 | - jquery.easing.js 8 | - jquery.mousewheel.js 9 | - raphael.js 10 | - perfect-scrollbar.js 11 | stylesheet: 12 | - Treant.css 13 | - perfect-scrollbar.css 14 | -------------------------------------------------------------------------------- /inst/static/advancedShiny_hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisbrownlie/advancedShiny/54872944139f995c1b62b612927afb7f3035d8cf/inst/static/advancedShiny_hex.png -------------------------------------------------------------------------------- /inst/static/app-status-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisbrownlie/advancedShiny/54872944139f995c1b62b612927afb7f3035d8cf/inst/static/app-status-badge.png -------------------------------------------------------------------------------- /inst/static/app-status-badge.svg: -------------------------------------------------------------------------------- 1 | status: developmentstatusdevelopment -------------------------------------------------------------------------------- /inst/static/pkg-version-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrisbrownlie/advancedShiny/54872944139f995c1b62b612927afb7f3035d8cf/inst/static/pkg-version-badge.png -------------------------------------------------------------------------------- /inst/static/pkg-version-badge.svg: -------------------------------------------------------------------------------- 1 | version: 0.1.0version0.1.0 -------------------------------------------------------------------------------- /man/add_snippet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fct_code.R 3 | \name{add_snippet} 4 | \alias{add_snippet} 5 | \title{Convert code to code snippet} 6 | \usage{ 7 | add_snippet( 8 | script = system.file("conversion_staging.R", package = "advancedShiny") 9 | ) 10 | } 11 | \arguments{ 12 | \item{script}{the R script to convert to a code snippet} 13 | } 14 | \value{ 15 | inserts the code necessary as a code snippet below the current selection 16 | } 17 | \description{ 18 | Convert code to code snippet 19 | } 20 | -------------------------------------------------------------------------------- /man/app_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/app_server.R 3 | \name{app_server} 4 | \alias{app_server} 5 | \title{Server function for the advancedShiny app} 6 | \usage{ 7 | app_server(input, output, session) 8 | } 9 | \description{ 10 | Server function for the advancedShiny app 11 | } 12 | -------------------------------------------------------------------------------- /man/app_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/app_ui.R 3 | \name{app_ui} 4 | \alias{app_ui} 5 | \title{UI for the advancedShiny app} 6 | \usage{ 7 | app_ui() 8 | } 9 | \description{ 10 | UI for the advancedShiny app 11 | } 12 | -------------------------------------------------------------------------------- /man/code_block.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fct_code.R 3 | \name{code_block} 4 | \alias{code_block} 5 | \title{Render code i.e. package (or function) name} 6 | \usage{ 7 | code_block(string, pkg = FALSE, href = NULL, noWS = NULL) 8 | } 9 | \arguments{ 10 | \item{pkg}{logical, if TRUE the output text will be italicised (representing a package name). If FALSE it 11 | won't be italicised (representing a function name or arbitrary R code).} 12 | 13 | \item{href}{optional link to include} 14 | 15 | \item{code}{the text to be formatted} 16 | } 17 | \value{ 18 | a HTML string which can be inserted directly into the UI of the app, showing the 19 | code as formatted, (potentially) clickable text 20 | } 21 | \description{ 22 | Renders either a package name (as italics and formatted as code) or a function (formatted as code), 23 | optionally include a link 24 | } 25 | -------------------------------------------------------------------------------- /man/code_snippet.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fct_code.R 3 | \name{code_snippet} 4 | \alias{code_snippet} 5 | \title{Include code snippets} 6 | \usage{ 7 | code_snippet(vec) 8 | } 9 | \arguments{ 10 | \item{vec}{a character vector of code (one element per line) to be shown} 11 | } 12 | \value{ 13 | a HTML string which can be inserted directly into the UI of the app, showing the 14 | code as a formatted snippet along with a 'Copy' button 15 | } 16 | \description{ 17 | Generate formatted markdown with a copy to clipboard button to allow users to 18 | copy code to their clipboard. 19 | } 20 | -------------------------------------------------------------------------------- /man/get_shinydashboard_theme.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fct_themes.R 3 | \name{get_shinydashboard_theme} 4 | \alias{get_shinydashboard_theme} 5 | \title{Custom shinydashboard theme} 6 | \usage{ 7 | get_shinydashboard_theme() 8 | } 9 | \value{ 10 | a shinydashboard theme created using fresh::create_theme 11 | } 12 | \description{ 13 | Customise some visual elements of the dashboard using the *fresh* package. 14 | This function returns a theme which is passed to use_theme, in the dashboardBody 15 | element of the UI. 16 | } 17 | -------------------------------------------------------------------------------- /man/hello.Rd: -------------------------------------------------------------------------------- 1 | \name{hello} 2 | \alias{hello} 3 | \title{Hello, World!} 4 | \usage{ 5 | hello() 6 | } 7 | \description{ 8 | Prints 'Hello, world!'. 9 | } 10 | \examples{ 11 | hello() 12 | } 13 | -------------------------------------------------------------------------------- /man/node.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/widget_treant.R 3 | \name{node} 4 | \alias{node} 5 | \title{Define treant tree node} 6 | \usage{ 7 | node(name, desc, children = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{name}{the name of the node} 11 | 12 | \item{desc}{the description of the node} 13 | 14 | \item{children}{a list of children nodes} 15 | } 16 | \description{ 17 | Helper function for defining tree structure, helps 18 | to create trees/nodes with less code 19 | } 20 | -------------------------------------------------------------------------------- /man/run_IAS_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/run_app.R 3 | \name{run_IAS_app} 4 | \alias{run_IAS_app} 5 | \title{Run the app} 6 | \usage{ 7 | run_IAS_app() 8 | } 9 | \value{ 10 | either run the app as a side effect or return a shiny.appobj object 11 | } 12 | \description{ 13 | Initiate an instance of the 'Intermediate & Advanced Shiny' app. If the current context is interactive, 14 | (i.e. if the function is called from RStudio), this function will initiate the app stored in 15 | inst/app with the runApp function. If the context is not interactive (i.e. the project is being sourced in RStudio 16 | Connect after having been deployed), then the function will return a shiny.appobj object, using the function 17 | shinyAppDir. This distinction is necessary to allow the app to be deployed. 18 | } 19 | \details{ 20 | Note: an alias function 'l' is also provided to speed up workflow (after making changes, load them with 'Ctrl+Shift+L', 21 | then launch the app with 'l()') 22 | } 23 | -------------------------------------------------------------------------------- /man/tab_appStructure_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_15_appStructure.R 3 | \name{tab_appStructure_server} 4 | \alias{tab_appStructure_server} 5 | \title{App Structure module server} 6 | \usage{ 7 | tab_appStructure_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the App Structure module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_appStructure_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_15_appStructure.R 3 | \name{tab_appStructure_ui} 4 | \alias{tab_appStructure_ui} 5 | \title{App Structure module 6 | App Structure module UI} 7 | \usage{ 8 | tab_appStructure_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the App Structure module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_attaliverse_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_23_attaliverse.R 3 | \name{tab_attaliverse_server} 4 | \alias{tab_attaliverse_server} 5 | \title{Attali-verse module server} 6 | \usage{ 7 | tab_attaliverse_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Attali-verse module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_attaliverse_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_23_attaliverse.R 3 | \name{tab_attaliverse_ui} 4 | \alias{tab_attaliverse_ui} 5 | \title{Attali-verse module 6 | Attali-verse module UI} 7 | \usage{ 8 | tab_attaliverse_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Attali-verse module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_controllingReactivity_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_14_controllingReactivity.R 3 | \name{tab_controllingReactivity_server} 4 | \alias{tab_controllingReactivity_server} 5 | \title{Controlling Reactivity module server} 6 | \usage{ 7 | tab_controllingReactivity_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Controlling Reactivity module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_controllingReactivity_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_14_controllingReactivity.R 3 | \name{tab_controllingReactivity_ui} 4 | \alias{tab_controllingReactivity_ui} 5 | \title{Controlling Reactivity module 6 | Controlling Reactivity module UI} 7 | \usage{ 8 | tab_controllingReactivity_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Controlling Reactivity module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_customInputs_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_25_customInputs.R 3 | \name{tab_customInputs_server} 4 | \alias{tab_customInputs_server} 5 | \title{Custom Shiny Inputs module server} 6 | \usage{ 7 | tab_customInputs_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Custom Shiny Inputs module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_customInputs_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_25_customInputs.R 3 | \name{tab_customInputs_ui} 4 | \alias{tab_customInputs_ui} 5 | \title{Custom Shiny Inputs module 6 | Custom Shiny Inputs module UI} 7 | \usage{ 8 | tab_customInputs_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Custom Shiny Inputs module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_errorHandling_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_35_errorHandling.R 3 | \name{tab_errorHandling_server} 4 | \alias{tab_errorHandling_server} 5 | \title{Error Handling & Debugging module server} 6 | \usage{ 7 | tab_errorHandling_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Error Handling & Debugging module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_errorHandling_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_35_errorHandling.R 3 | \name{tab_errorHandling_ui} 4 | \alias{tab_errorHandling_ui} 5 | \title{Error Handling & Debugging module 6 | Error Handling & Debugging module UI} 7 | \usage{ 8 | tab_errorHandling_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Error Handling & Debugging module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_extendingShiny_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_24_extendingShiny.R 3 | \name{tab_extendingShiny_server} 4 | \alias{tab_extendingShiny_server} 5 | \title{Extending Shiny module server} 6 | \usage{ 7 | tab_extendingShiny_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Extending Shiny module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_extendingShiny_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_24_extendingShiny.R 3 | \name{tab_extendingShiny_ui} 4 | \alias{tab_extendingShiny_ui} 5 | \title{Extending Shiny module 6 | Extending Shiny module UI} 7 | \usage{ 8 | tab_extendingShiny_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Extending Shiny module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_info_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_00_info.R 3 | \name{tab_info_server} 4 | \alias{tab_info_server} 5 | \title{Info module server} 6 | \usage{ 7 | tab_info_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Info module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_info_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_00_info.R 3 | \name{tab_info_ui} 4 | \alias{tab_info_ui} 5 | \title{Info module 6 | Info module UI} 7 | \usage{ 8 | tab_info_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Info module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_modCCx_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_x_template.R 3 | \name{tab_modCCx_server} 4 | \alias{tab_modCCx_server} 5 | \title{modTCx module server} 6 | \usage{ 7 | tab_modCCx_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the modTCx module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_modCCx_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_x_template.R 3 | \name{tab_modCCx_ui} 4 | \alias{tab_modCCx_ui} 5 | \title{modTCx module 6 | modTCx module UI} 7 | \usage{ 8 | tab_modCCx_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the modTCx module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_optimisation_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_36_optimisation.R 3 | \name{tab_optimisation_server} 4 | \alias{tab_optimisation_server} 5 | \title{Optimisation module server} 6 | \usage{ 7 | tab_optimisation_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Optimisation module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_optimisation_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_36_optimisation.R 3 | \name{tab_optimisation_ui} 4 | \alias{tab_optimisation_ui} 5 | \title{Optimisation module 6 | Optimisation module UI} 7 | \usage{ 8 | tab_optimisation_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Optimisation module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_references_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_40_references.R 3 | \name{tab_references_server} 4 | \alias{tab_references_server} 5 | \title{References & Further Materials module server} 6 | \usage{ 7 | tab_references_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the References & Further Materials module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_references_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_40_references.R 3 | \name{tab_references_ui} 4 | \alias{tab_references_ui} 5 | \title{References & Further Materials module 6 | References & Further Materials module UI} 7 | \usage{ 8 | tab_references_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the References & Further Materials module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_sessionObject_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_31_sessionObject.R 3 | \name{tab_sessionObject_server} 4 | \alias{tab_sessionObject_server} 5 | \title{Session Object module server} 6 | \usage{ 7 | tab_sessionObject_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Session Object module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_sessionObject_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_31_sessionObject.R 3 | \name{tab_sessionObject_ui} 4 | \alias{tab_sessionObject_ui} 5 | \title{Session Object module 6 | Session Object module UI} 7 | \usage{ 8 | tab_sessionObject_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Session Object module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_shinyModules_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_16_shinyModules.R 3 | \name{tab_shinyModules_server} 4 | \alias{tab_shinyModules_server} 5 | \title{Shiny Modules module server} 6 | \usage{ 7 | tab_shinyModules_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Shiny Modules module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_shinyModules_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_16_shinyModules.R 3 | \name{tab_shinyModules_ui} 4 | \alias{tab_shinyModules_ui} 5 | \title{Shiny Modules module 6 | Shiny Modules module UI} 7 | \usage{ 8 | tab_shinyModules_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Shiny Modules module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_trackingUsage_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_32_trackingUsage.R 3 | \name{tab_trackingUsage_server} 4 | \alias{tab_trackingUsage_server} 5 | \title{Tracking Usage module server} 6 | \usage{ 7 | tab_trackingUsage_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Tracking Usage module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_trackingUsage_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_32_trackingUsage.R 3 | \name{tab_trackingUsage_ui} 4 | \alias{tab_trackingUsage_ui} 5 | \title{Tracking Usage module 6 | Tracking Usage module UI} 7 | \usage{ 8 | tab_trackingUsage_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Tracking Usage module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_understandingReactivity_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_12_understandingReactivity.R 3 | \name{tab_understandingReactivity_server} 4 | \alias{tab_understandingReactivity_server} 5 | \title{Understanding Reactivity module server} 6 | \usage{ 7 | tab_understandingReactivity_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Understanding Reactivity module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_understandingReactivity_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_12_understandingReactivity.R 3 | \name{tab_understandingReactivity_ui} 4 | \alias{tab_understandingReactivity_ui} 5 | \title{Understanding Reactivity module 6 | Understanding Reactivity module UI} 7 | \usage{ 8 | tab_understandingReactivity_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Understanding Reactivity module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_usingCSS_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_21_usingCSS.R 3 | \name{tab_usingCSS_server} 4 | \alias{tab_usingCSS_server} 5 | \title{Using CSS module server} 6 | \usage{ 7 | tab_usingCSS_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Using CSS module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_usingCSS_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_21_usingCSS.R 3 | \name{tab_usingCSS_ui} 4 | \alias{tab_usingCSS_ui} 5 | \title{Using CSS module 6 | Using CSS module UI} 7 | \usage{ 8 | tab_usingCSS_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Using CSS module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_usingJS_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_22_usingJS.R 3 | \name{tab_usingJS_server} 4 | \alias{tab_usingJS_server} 5 | \title{Using Javascript module server} 6 | \usage{ 7 | tab_usingJS_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Using Javascript module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_usingJS_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_22_usingJS.R 3 | \name{tab_usingJS_ui} 4 | \alias{tab_usingJS_ui} 5 | \title{Using Javascript module 6 | Using Javascript module UI} 7 | \usage{ 8 | tab_usingJS_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Using Javascript module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_usingReactivity_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_13_usingReactivity.R 3 | \name{tab_usingReactivity_server} 4 | \alias{tab_usingReactivity_server} 5 | \title{Using Reactivity module server} 6 | \usage{ 7 | tab_usingReactivity_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Using Reactivity module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_usingReactivity_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_13_usingReactivity.R 3 | \name{tab_usingReactivity_ui} 4 | \alias{tab_usingReactivity_ui} 5 | \title{Using Reactivity module 6 | Using Reactivity module UI} 7 | \usage{ 8 | tab_usingReactivity_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Using Reactivity module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_visualisationPlotly_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_33_visualisationPlotly.R 3 | \name{tab_visualisationPlotly_server} 4 | \alias{tab_visualisationPlotly_server} 5 | \title{Visualisation with plotly module server} 6 | \usage{ 7 | tab_visualisationPlotly_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Visualisation with plotly module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_visualisationPlotly_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_33_visualisationPlotly.R 3 | \name{tab_visualisationPlotly_ui} 4 | \alias{tab_visualisationPlotly_ui} 5 | \title{Visualisation with plotly module 6 | Visualisation with plotly module UI} 7 | \usage{ 8 | tab_visualisationPlotly_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Visualisation with plotly module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_visualisationR2D3_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_34_visualisationR2D3.R 3 | \name{tab_visualisationR2D3_server} 4 | \alias{tab_visualisationR2D3_server} 5 | \title{Visualisation with r2d3 module server} 6 | \usage{ 7 | tab_visualisationR2D3_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the Visualisation with r2d3 module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_visualisationR2D3_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_34_visualisationR2D3.R 3 | \name{tab_visualisationR2D3_ui} 4 | \alias{tab_visualisationR2D3_ui} 5 | \title{Visualisation with r2d3 module 6 | Visualisation with r2d3 module UI} 7 | \usage{ 8 | tab_visualisationR2D3_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the Visualisation with r2d3 module 18 | } 19 | -------------------------------------------------------------------------------- /man/tab_whatIsShiny_server.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_11_whatIsShiny.R 3 | \name{tab_whatIsShiny_server} 4 | \alias{tab_whatIsShiny_server} 5 | \title{What Is Shiny? module server} 6 | \usage{ 7 | tab_whatIsShiny_server(id, appData) 8 | } 9 | \arguments{ 10 | \item{id}{to be used to namespace the module} 11 | 12 | \item{appData}{the appData reactiveValues object, defined in server.R and available 13 | to all modules} 14 | } 15 | \value{ 16 | the module server, returned from a moduleServer function call 17 | } 18 | \description{ 19 | Defines the server logic for the What Is Shiny? module 20 | } 21 | -------------------------------------------------------------------------------- /man/tab_whatIsShiny_ui.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_11_whatIsShiny.R 3 | \name{tab_whatIsShiny_ui} 4 | \alias{tab_whatIsShiny_ui} 5 | \title{What Is Shiny? module 6 | What Is Shiny? module UI} 7 | \usage{ 8 | tab_whatIsShiny_ui(id) 9 | } 10 | \arguments{ 11 | \item{id}{to be used to namespace the module} 12 | } 13 | \value{ 14 | the module UI, as a tagList 15 | } 16 | \description{ 17 | Defines the UI for the What Is Shiny? module 18 | } 19 | -------------------------------------------------------------------------------- /man/treant-shiny.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/widget_treant.R 3 | \name{treant-shiny} 4 | \alias{treant-shiny} 5 | \alias{treantOutput} 6 | \alias{renderTreant} 7 | \title{Shiny bindings for treant} 8 | \usage{ 9 | treantOutput(outputId, width = "100\%", height = "400px") 10 | 11 | renderTreant(expr, env = parent.frame(), quoted = FALSE) 12 | } 13 | \arguments{ 14 | \item{outputId}{output variable to read from} 15 | 16 | \item{width, height}{Must be a valid CSS unit (like \code{'100\%'}, 17 | \code{'400px'}, \code{'auto'}) or a number, which will be coerced to a 18 | string and have \code{'px'} appended.} 19 | 20 | \item{expr}{An expression that generates a treant} 21 | 22 | \item{env}{The environment in which to evaluate \code{expr}.} 23 | 24 | \item{quoted}{Is \code{expr} a quoted expression (with \code{quote()})? This 25 | is useful if you want to save an expression in a variable.} 26 | } 27 | \description{ 28 | Output and render functions for using treant within Shiny 29 | applications and interactive Rmd documents. 30 | } 31 | -------------------------------------------------------------------------------- /man/treant.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/widget_treant.R 3 | \name{treant} 4 | \alias{treant} 5 | \title{treant htmlwidget} 6 | \usage{ 7 | treant(structure, width = NULL, height = NULL) 8 | } 9 | \arguments{ 10 | \item{structure}{a list of lists denoting the structure of the tree to be built} 11 | } 12 | \description{ 13 | interface to the Treant javascript package 14 | } 15 | -------------------------------------------------------------------------------- /references.txt: -------------------------------------------------------------------------------- 1 | advancedShiny references 2 | 3 | - mastering shiny: https://mastering-shiny.org/ 4 | - outstanding UI with shiny: https://unleash-shiny.rinterface.com/ 5 | - engineering shiny: https://engineering-shiny.org/ 6 | - data storage: https://shiny.rstudio.com/articles/persistent-data-storage.html 7 | - caching: https://shiny.rstudio.com/articles/caching.html 8 | - using R6 in shiny: https://appsilon.com/super-solutions-for-shiny-apps-using-r6-classes/ 9 | - R6 performance: https://r6.r-lib.org/articles/Performance.html 10 | 11 | tab 1.2 12 | - reactivity an overview: https://shiny.rstudio.com/articles/reactivity-overview.html 13 | - how to understand reactivity: https://shiny.rstudio.com/articles/understanding-reactivity.html 14 | 15 | tab 1.4 16 | - reactive and observe https://github.com/rstudio/ShinyDeveloperConference/blob/master/Reactivity/slides.Rmd 17 | 18 | htmlwidgets 19 | https://deanattali.com/blog/htmlwidgets-tips/ 20 | https://www.rstudio.com/resources/rstudioconf-2017/linking-html-widgets-with-crosstalk/ 21 | 22 | reactivity 23 | https://www.rstudio.com/resources/shiny-dev-con/reactivity-pt-1-joe-cheng/ 24 | https://www.rstudio.com/resources/shiny-dev-con/reactivity-pt-2/ 25 | 26 | plotly 27 | https://www.rstudio.com/resources/webinars/accessing-and-responding-to-plotly-events-in-shiny/ -------------------------------------------------------------------------------- /renv/.gitignore: -------------------------------------------------------------------------------- 1 | cellar/ 2 | library/ 3 | local/ 4 | lock/ 5 | python/ 6 | staging/ 7 | -------------------------------------------------------------------------------- /renv/settings.dcf: -------------------------------------------------------------------------------- 1 | external.libraries: 2 | ignored.packages: 3 | package.dependency.fields: Imports, Depends, LinkingTo 4 | r.version: 5 | snapshot.type: implicit 6 | use.cache: TRUE 7 | vcs.ignore.library: TRUE 8 | vcs.ignore.local: TRUE 9 | --------------------------------------------------------------------------------