├── .Rbuildignore ├── .gitignore ├── CODE_OF_CONDUCT.md ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── app_server.R ├── app_ui.R ├── golem_utils_server.R ├── golem_utils_ui.R ├── mod_my_fifth_module.R ├── mod_my_first_module.R ├── mod_my_fourth_module.R ├── mod_my_other_module.R ├── mod_my_third_module.R └── run_app.R ├── README.Rmd ├── README.md ├── data-raw └── dataset.R ├── data ├── dataset.rda └── plop.rda ├── dev ├── 01_start.R ├── 02_dev.R ├── 03_deploy.R └── run_dev.R ├── golemexample.Rproj ├── inst └── app │ └── www │ ├── alertme.js │ ├── custom.css │ ├── guit.jpg │ ├── handlers.js │ └── plop.md ├── man ├── mod_my_first_module.Rd ├── mod_my_fourth_module.Rd ├── mod_my_other_module.Rd ├── mod_my_third_module.Rd └── run_app.Rd └── tests ├── testthat.R └── testthat └── test-golem-recommended.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^data-raw$ 4 | dev_history.R 5 | ^dev$ 6 | $run_dev.* 7 | ^README\.Rmd$ 8 | ^CODE_OF_CONDUCT\.md$ 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | inst/doc 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (https://www.contributor-covenant.org), version 1.0.0, available at 25 | https://contributor-covenant.org/version/1/0/0/. 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: golemexample 2 | Title: Golem Example 3 | Version: 0.0.0.9000 4 | Authors@R: person('Colin', 'Fay', email = 'contact@colinfay.me', role = c('cre', 'aut')) 5 | Description: A Package to show the basics of a golem. 6 | License: What license is it under? 7 | Encoding: UTF-8 8 | LazyData: true 9 | Imports: 10 | shiny, 11 | golem, 12 | processx, 13 | attempt, 14 | DT, 15 | glue, 16 | htmltools 17 | Remotes: 18 | Thinkr-open/golem 19 | RoxygenNote: 6.1.1 20 | URL: https://github.com/colinfay/golemexample 21 | BugReports: https://github.com/colinfay/golemexample/issues 22 | Suggests: 23 | testthat 24 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(mod_my_first_module_server) 4 | export(mod_my_first_module_ui) 5 | export(mod_my_fourth_module_server) 6 | export(mod_my_fourth_module_ui) 7 | export(mod_my_other_module_server) 8 | export(mod_my_other_module_ui) 9 | export(mod_my_third_module_server) 10 | export(mod_my_third_module_ui) 11 | export(run_app) 12 | import(golem) 13 | import(shiny) 14 | importFrom(glue,glue) 15 | importFrom(golem,with_golem_options) 16 | importFrom(htmltools,HTML) 17 | importFrom(htmltools,tagAppendAttributes) 18 | importFrom(htmltools,tagList) 19 | importFrom(htmltools,tags) 20 | importFrom(shiny,NS) 21 | importFrom(shiny,column) 22 | importFrom(shiny,shinyApp) 23 | importFrom(shiny,tagList) 24 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # golemexample 0.0.0.9000 2 | 3 | * Added a `NEWS.md` file to track changes to the package. 4 | -------------------------------------------------------------------------------- /R/app_server.R: -------------------------------------------------------------------------------- 1 | #' @import shiny 2 | #' @import golem 3 | app_server <- function(input, output,session) { 4 | # List the first level callModules here 5 | print(get_golem_options("time")) 6 | r <- reactiveValues() 7 | callModule(mod_my_first_module_server, "my_first_module_ui_1") 8 | callModule(mod_my_other_module_server, "my_other_module_ui_1", r) 9 | callModule(mod_my_third_module_server, "my_third_module_ui_1", r) 10 | callModule(mod_my_fourth_module_server, "my_fourth_module_ui_1") 11 | } 12 | -------------------------------------------------------------------------------- /R/app_ui.R: -------------------------------------------------------------------------------- 1 | #' @import shiny 2 | app_ui <- function() { 3 | tagList( 4 | # Leave this function for adding external resources 5 | golem_add_external_resources(), 6 | # List the first level UI elements here 7 | fluidPage( 8 | h1(get_golem_options("name")), 9 | mod_my_first_module_ui("my_first_module_ui_1"), 10 | col_12( 11 | br() 12 | ), 13 | col_6( 14 | mod_my_other_module_ui("my_other_module_ui_1") %>% div(align = "center") 15 | ), 16 | col_6( 17 | mod_my_third_module_ui("my_third_module_ui_1") %>% div(align = "center") 18 | ), 19 | col_6( 20 | mod_my_fourth_module_ui("my_fourth_module_ui_1") %>% div(align = "center") 21 | ), 22 | col_6( 23 | mod_my_fifth_module_ui("my_fifth_module_ui_1") %>% div(align = "left") 24 | ) 25 | ) 26 | ) 27 | } 28 | 29 | #' @import shiny 30 | golem_add_external_resources <- function(){ 31 | 32 | addResourcePath( 33 | 'www', system.file('app/www', package = 'golemexample') 34 | ) 35 | 36 | tags$head( 37 | golem::activate_js(), 38 | golem::favicon(), 39 | # Add here all the external resources 40 | # If you have a custom.css in the inst/app/www 41 | # Or for example, you can add shinyalert::useShinyalert() here 42 | tags$link(rel="stylesheet", type="text/css", href="www/custom.css"), 43 | tags$script(src="www/alertme.js"), 44 | tags$script(src="www/handlers.js") 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /R/golem_utils_server.R: -------------------------------------------------------------------------------- 1 | # Inverted versions of in, is.null and is.na 2 | `%not_in%` <- Negate(`%in%`) 3 | 4 | not_null <- Negate(is.null) 5 | 6 | not_na <- Negate(is.na) 7 | 8 | # Removes the null from a vector 9 | drop_nulls <- function(x){ 10 | x[!sapply(x, is.null)] 11 | } 12 | 13 | # If x is null, return y, otherwise return x 14 | "%||%" <- function(x, y){ 15 | if (is.null(x)) { 16 | y 17 | } else { 18 | x 19 | } 20 | } 21 | # If x is NA, return y, otherwise return x 22 | "%|NA|%" <- function(x, y){ 23 | if (is.na(x)) { 24 | y 25 | } else { 26 | x 27 | } 28 | } 29 | 30 | # typing reactiveValues is too long 31 | rv <- shiny::reactiveValues 32 | rvtl <- shiny::reactiveValuesToList -------------------------------------------------------------------------------- /R/golem_utils_ui.R: -------------------------------------------------------------------------------- 1 | # Turn an R list into an HTML list 2 | # 3 | # @param list An R list 4 | # @param class a class for the list 5 | # @return an HTML list 6 | # @examples 7 | # list_to_li(c("a","b")) 8 | # 9 | #' @importFrom htmltools tags tagAppendAttributes tagList 10 | list_to_li <- function(list, class = NULL){ 11 | if (is.null(class)){ 12 | tagList(lapply(list, tags$li)) 13 | } else { 14 | res <- lapply(list, tags$li) 15 | res <- lapply(res, function(x) tagAppendAttributes(x, class = class)) 16 | tagList(res) 17 | } 18 | 19 | } 20 | 21 | #' @importFrom htmltools tags tagAppendAttributes tagList 22 | list_to_p <- function(list, class = NULL){ 23 | if (is.null(class)){ 24 | tagList(lapply(list, tags$p)) 25 | } else { 26 | res <- lapply(list, tags$p) 27 | res <- lapply(res, function(x) tagAppendAttributes(x, class = class)) 28 | tagList(res) 29 | } 30 | 31 | } 32 | 33 | #' @importFrom glue glue 34 | #' @importFrom htmltools tags tagAppendAttributes tagList 35 | named_to_li <- function(list, class = NULL){ 36 | if(is.null(class)){ 37 | res <- mapply( 38 | function(x, y){ 39 | tags$li(HTML(glue("{y}: {x}"))) 40 | }, 41 | list, names(list), SIMPLIFY = FALSE) 42 | #res <- lapply(res, HTML) 43 | tagList(res) 44 | } else { 45 | res <- mapply( 46 | function(x, y){ 47 | tags$li(HTML(glue("{y}: {x}"))) 48 | }, 49 | list, names(list), SIMPLIFY = FALSE) 50 | res <- lapply(res, function(x) tagAppendAttributes(x, class = class)) 51 | tagList(res) 52 | } 53 | } 54 | 55 | # Remove a tag attribute 56 | # 57 | # @param tag the tag 58 | # @param ... the attributes to remove 59 | # 60 | # @return a new tag 61 | # @export 62 | # 63 | # @examples 64 | # a <- shiny::tags$p(src = "plop", "pouet") 65 | # tagRemoveAttributes(a, "src") 66 | tagRemoveAttributes <- function(tag, ...) { 67 | attrs <- as.character(list(...)) 68 | for (i in seq_along(attrs)) { 69 | tag$attribs[[ attrs[i] ]] <- NULL 70 | } 71 | tag 72 | } 73 | 74 | # Hide or display a tag 75 | # @param tag the tag 76 | # @return a tag 77 | # @examples 78 | # ## Hide 79 | # a <- shiny::tags$p(src = "plop", "pouet") 80 | # undisplay(a) 81 | # b <- shiny::actionButton("go_filter", "go") 82 | # undisplay(b) 83 | 84 | #' @importFrom htmltools tagList 85 | undisplay <- function(tag) { 86 | # if not already hidden 87 | if (!is.null(tag$attribs$style) && !grepl("display:\\s+none", tag$attribs$style)) { 88 | tag$attribs$style <- paste("display: none;", tag$attribs$style) 89 | } else { 90 | tag$attribs$style <- "display: none;" 91 | } 92 | tag 93 | } 94 | 95 | #' @importFrom htmltools tagList 96 | display <- function(tag) { 97 | if (!is.null(tag$attribs$style) && grepl("display:\\s+none", tag$attribs$style)) { 98 | tag$attribs$style <- gsub("(\\s)*display:(\\s)*none(\\s)*(;)*(\\s)*", "", tag$attribs$style) 99 | } 100 | tag 101 | } 102 | 103 | # Hide an elements by calling jquery hide on it 104 | #' @importFrom htmltools tags 105 | jq_hide <- function(id) { 106 | tags$script(sprintf("$('#%s').hide()", id)) 107 | } 108 | 109 | # Add a red star at the end of the text 110 | # 111 | # Adds a red star at the end of the text 112 | # (for example for indicating mandatory fields). 113 | # 114 | # @param text the HTLM text to put before the red star 115 | # 116 | # @return an html element 117 | # 118 | # @examples 119 | # with_red_star("Enter your name here") 120 | # 121 | #' @importFrom htmltools tags HTML 122 | with_red_star <- function(text) { 123 | htmltools::tags$span( 124 | HTML( 125 | paste0( 126 | text, 127 | htmltools::tags$span( 128 | style = "color:red", "*" 129 | ) 130 | ) 131 | ) 132 | ) 133 | } 134 | 135 | 136 | 137 | # Repeat tags$br 138 | # 139 | # @param times the number of br to return 140 | # 141 | # @return the number of br specified in times 142 | # @export 143 | # 144 | # @examples 145 | # rep_br(5) 146 | # 147 | #' @importFrom htmltools HTML 148 | rep_br <- function(times = 1) { 149 | HTML(rep("
", times = times)) 150 | } 151 | 152 | # Create an url 153 | # 154 | # @param url the URL 155 | # @param text the text to display 156 | # 157 | # @return an a tag 158 | # @export 159 | # 160 | # @examples 161 | # enurl("https://www.thinkr.fr", "ThinkR") 162 | enurl <- function(url, text){ 163 | tags$a(href = url, text) 164 | } 165 | 166 | 167 | # Columns 12, 6 and 4 168 | # 169 | # Most shiny columns are 12, 6 or 4 of width. 170 | # These are convenient wrappers around 171 | # `column(12, ...)`, `column(6, ...)` and `column(4, ...)`. 172 | # 173 | # @export 174 | # @rdname columns 175 | #' @importFrom shiny column 176 | col_12 <- function(...){ 177 | column(12, ...) 178 | } 179 | 180 | #' @importFrom shiny column 181 | col_6 <- function(...){ 182 | column(6, ...) 183 | } 184 | 185 | #' @importFrom shiny column 186 | col_4 <- function(...){ 187 | column(4, ...) 188 | } 189 | -------------------------------------------------------------------------------- /R/mod_my_fifth_module.R: -------------------------------------------------------------------------------- 1 | # Module UI 2 | 3 | #' @title mod_my_fifth_module_ui and mod_my_fifth_module_server 4 | #' @description A shiny Module. 5 | #' 6 | #' @param id shiny id 7 | #' @param input internal 8 | #' @param output internal 9 | #' @param session internal 10 | #' 11 | #' @rdname mod_my_fifth_module 12 | #' 13 | #' @keywords internal 14 | #' @export 15 | #' @importFrom shiny NS tagList 16 | mod_my_fifth_module_ui <- function(id){ 17 | ns <- NS(id) 18 | tagList( 19 | includeMarkdown( 20 | system.file("app/www/plop.md", package = "golemexample") 21 | ) 22 | ) 23 | } 24 | 25 | # Module Server 26 | 27 | #' @rdname mod_my_fifth_module 28 | #' @export 29 | #' @keywords internal 30 | 31 | mod_my_fifth_module_server <- function(input, output, session){ 32 | ns <- session$ns 33 | } 34 | 35 | ## To be copied in the UI 36 | # 37 | 38 | ## To be copied in the server 39 | # callModule(mod_my_fifth_module_server, "my_fifth_module_ui_1") 40 | 41 | -------------------------------------------------------------------------------- /R/mod_my_first_module.R: -------------------------------------------------------------------------------- 1 | # Module UI 2 | 3 | #' @title mod_my_first_module_ui and mod_my_first_module_server 4 | #' @description A shiny Module. 5 | #' 6 | #' @param id shiny id 7 | #' @param input internal 8 | #' @param output internal 9 | #' @param session internal 10 | #' 11 | #' @rdname mod_my_first_module 12 | #' 13 | #' @keywords internal 14 | #' @export 15 | #' @importFrom shiny NS tagList 16 | mod_my_first_module_ui <- function(id){ 17 | ns <- NS(id) 18 | tagList( 19 | col_6( 20 | tags$div( 21 | align = "center", 22 | tags$img( 23 | src = "www/guit.jpg", width = "50%", align = "center" 24 | ) 25 | ) 26 | ), 27 | col_6( 28 | tableOutput(ns("df")) 29 | ), 30 | col_6( 31 | tags$div( 32 | align = "center", 33 | tags$button("Alert!", onclick = "alertme();") 34 | ) 35 | ), 36 | col_6( 37 | tags$div( 38 | align = "center", 39 | actionButton(ns("go"), "Go!") 40 | ) 41 | ) 42 | ) 43 | } 44 | 45 | # Module Server 46 | 47 | #' @rdname mod_my_first_module 48 | #' @export 49 | #' @keywords internal 50 | 51 | mod_my_first_module_server <- function(input, output, session, r){ 52 | ns <- session$ns 53 | output$df <- renderTable({ 54 | dataset 55 | }) 56 | 57 | observeEvent( input$go , { 58 | golem::invoke_js("alertarg", "12") 59 | }) 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /R/mod_my_fourth_module.R: -------------------------------------------------------------------------------- 1 | # Module UI 2 | 3 | #' @title mod_my_fourth_module_ui and mod_my_fourth_module_server 4 | #' @description A shiny Module. 5 | #' 6 | #' @param id shiny id 7 | #' @param input internal 8 | #' @param output internal 9 | #' @param session internal 10 | #' 11 | #' @rdname mod_my_fourth_module 12 | #' 13 | #' @keywords internal 14 | #' @export 15 | #' @importFrom shiny NS tagList 16 | mod_my_fourth_module_ui <- function(id){ 17 | #browser() 18 | ns <- NS(id) 19 | tagList( 20 | h2( 21 | names(plop) 22 | ), 23 | verbatimTextOutput(ns("fruits")) 24 | ) 25 | } 26 | 27 | # Module Server 28 | 29 | #' @rdname mod_my_fourth_module 30 | #' @export 31 | #' @keywords internal 32 | 33 | mod_my_fourth_module_server <- function(input, output, session){ 34 | ns <- session$ns 35 | output$fruits <- renderPrint({ 36 | plop 37 | }) 38 | } 39 | 40 | ## To be copied in the UI 41 | # 42 | 43 | ## To be copied in the server 44 | # 45 | 46 | -------------------------------------------------------------------------------- /R/mod_my_other_module.R: -------------------------------------------------------------------------------- 1 | # Module UI 2 | 3 | #' @title mod_my_other_module_ui and mod_my_other_module_server 4 | #' @description A shiny Module. 5 | #' 6 | #' @param id shiny id 7 | #' @param input internal 8 | #' @param output internal 9 | #' @param session internal 10 | #' 11 | #' @rdname mod_my_other_module 12 | #' 13 | #' @keywords internal 14 | #' @export 15 | #' @importFrom shiny NS tagList 16 | mod_my_other_module_ui <- function(id){ 17 | ns <- NS(id) 18 | tagList( 19 | col_12( 20 | h3("Collecting value here in r"), 21 | selectInput(ns("which"), "Which ?", c("iris", "mtcars", "airquality")) 22 | ) 23 | ) 24 | } 25 | 26 | # Module Server 27 | 28 | #' @rdname mod_my_other_module 29 | #' @export 30 | #' @keywords internal 31 | 32 | mod_my_other_module_server <- function(input, output, session, r){ 33 | ns <- session$ns 34 | 35 | r$my_other_module <- reactiveValues() 36 | 37 | observeEvent( input$which , { 38 | r$my_other_module$which <- input$which 39 | }) 40 | 41 | 42 | } 43 | 44 | ## To be copied in the UI 45 | # 46 | 47 | ## To be copied in the server 48 | # 49 | 50 | -------------------------------------------------------------------------------- /R/mod_my_third_module.R: -------------------------------------------------------------------------------- 1 | # Module UI 2 | 3 | #' @title mod_my_third_module_ui and mod_my_third_module_server 4 | #' @description A shiny Module. 5 | #' 6 | #' @param id shiny id 7 | #' @param input internal 8 | #' @param output internal 9 | #' @param session internal 10 | #' 11 | #' @rdname mod_my_third_module 12 | #' 13 | #' @keywords internal 14 | #' @export 15 | #' @importFrom shiny NS tagList 16 | mod_my_third_module_ui <- function(id){ 17 | ns <- NS(id) 18 | tagList( 19 | tableOutput(ns("df")) 20 | ) 21 | } 22 | 23 | # Module Server 24 | 25 | #' @rdname mod_my_third_module 26 | #' @export 27 | #' @keywords internal 28 | 29 | mod_my_third_module_server <- function(input, output, session, r){ 30 | ns <- session$ns 31 | output$df <- renderTable({ 32 | print(r$my_other_module$which) 33 | head(get(r$my_other_module$which), 10) 34 | }) 35 | } 36 | 37 | ## To be copied in the UI 38 | # 39 | 40 | ## To be copied in the server 41 | # 42 | 43 | -------------------------------------------------------------------------------- /R/run_app.R: -------------------------------------------------------------------------------- 1 | #' Run the Shiny Application 2 | #' 3 | #' @export 4 | #' @importFrom shiny shinyApp 5 | #' @importFrom golem with_golem_options 6 | run_app <- function( 7 | name = "example", 8 | time = Sys.time(), 9 | port = 2811 10 | ) { 11 | with_golem_options( 12 | app = shinyApp(ui = app_ui, 13 | server = app_server, 14 | options = list(port = port)), 15 | golem_opts = list(name = name, time = time) 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | # golemexample 16 | 17 | 18 | [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) 19 | 20 | 21 | The goal of golemexample is to provide some examples for the inner configuration of a `{golem}` app. 22 | 23 | ## Share value across modules 24 | 25 | + Add a top level reactiveValue 26 | 27 | + Add a nested level inside modules 28 | 29 | + Share this across modules 30 | 31 | ## Change Shiny Options 32 | 33 | 34 | 35 | ## Adding external files 36 | 37 | ### CSS 38 | 39 | + Added with `dev/02_dev.R#29` 40 | 41 | + Personnalized in `inst/app/www/custom.css` 42 | 43 | + Linked to the app at `R/app_ui.R#27` 44 | 45 | ### JS 46 | 47 | #### Classic 48 | 49 | __A simple JS can be used from UI.__ 50 | 51 | + Added with `dev/02_dev.R#27` 52 | 53 | + Personnalized in `inst/app/www/alertme.js` 54 | 55 | + Linked to the app at `R/app_ui.R#28` 56 | 57 | + Called with `tags$button("Alert!", onclick = "alertme();")` at `R/mod_my_first_module.R#33` 58 | 59 | #### Handlers 60 | 61 | __A handler JS can be used from server side with `golem::invoke_js()`.__ 62 | 63 | + Added with `dev/02_dev.R#28` 64 | 65 | + Personnalized in `inst/app/www/handler.js` 66 | 67 | + Linked to the app at `R/app_ui.R#29` 68 | 69 | + Called with `golem::invoke_js("alertarg", "12")` at `R/mod_my_first_module.R#58` 70 | 71 | ### Image 72 | 73 | + Downloaded at `inst/app/www/guit.jpg` 74 | 75 | + Linked with `tags$img(src = "www/guit.jpg")` at `R/mod_my_first_module.R#23` 76 | 77 | ## Passing arguments to `run_app` 78 | 79 | + `run_app` 80 | 81 | + Read in UI at `R/app_ui.R#8` 82 | 83 | + Read in server at `R/app_server.R#5` 84 | 85 | ## Using datasets inside your app 86 | 87 | + Register your dataset as a package data 88 | which is turned into 89 | 90 | + Use your data object wherever you need it (in your UI or server) 91 | 92 | ## Using shiny::includeXXX 93 | 94 | + Add elements in `inst/app/www` 95 | 96 | + Use `system.file("app/www/plop.md", package = "golemexample")` 97 | 98 |
99 | 100 | Please note that the 'golemexample' project is released with a 101 | [Contributor Code of Conduct](CODE_OF_CONDUCT.md). 102 | By contributing to this project, you agree to abide by its terms. 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # golemexample 5 | 6 | 7 | 8 | [![Lifecycle: 9 | experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) 10 | 11 | 12 | The goal of golemexample is to provide some examples for the inner 13 | configuration of a `{golem}` app. 14 | 15 | ## Share value across modules 16 | 17 | - Add a top level reactiveValue 18 | 19 | 20 | - Add a nested level inside modules 21 | 22 | 23 | - Share this across modules 24 | 25 | 26 | ## Change Shiny Options 27 | 28 | 29 | 30 | ## Adding external files 31 | 32 | ### CSS 33 | 34 | - Added with `dev/02_dev.R#29` 35 | 36 | 37 | - Personnalized in `inst/app/www/custom.css` 38 | 39 | 40 | - Linked to the app at `R/app_ui.R#27` 41 | 42 | 43 | ### JS 44 | 45 | #### Classic 46 | 47 | **A simple JS can be used from UI.** 48 | 49 | - Added with `dev/02_dev.R#27` 50 | 51 | 52 | - Personnalized in `inst/app/www/alertme.js` 53 | 54 | 55 | - Linked to the app at `R/app_ui.R#28` 56 | 57 | 58 | - Called with `tags$button("Alert!", onclick = "alertme();")` at 59 | `R/mod_my_first_module.R#33` 60 | 61 | 62 | #### Handlers 63 | 64 | **A handler JS can be used from server side with `golem::invoke_js()`.** 65 | 66 | - Added with `dev/02_dev.R#28` 67 | 68 | 69 | - Personnalized in `inst/app/www/handler.js` 70 | 71 | 72 | - Linked to the app at `R/app_ui.R#29` 73 | 74 | 75 | - Called with `golem::invoke_js("alertarg", "12")` at 76 | `R/mod_my_first_module.R#58` 77 | 78 | 79 | ### Image 80 | 81 | - Downloaded at `inst/app/www/guit.jpg` 82 | 83 | 84 | - Linked with `tags$img(src = "www/guit.jpg")` at 85 | `R/mod_my_first_module.R#23` 86 | 87 | 88 | ## Passing arguments to `run_app` 89 | 90 | - `run_app` 91 | 92 | 93 | - Read in UI at `R/app_ui.R#8` 94 | 95 | 96 | - Read in server at `R/app_server.R#5` 97 | 98 | 99 | ## Using datasets inside your app 100 | 101 | - Register your dataset as a package data 102 | 103 | which is turned into 104 | 105 | 106 | - Use your data object wherever you need it (in your UI or server) 107 | 108 | ## Using shiny::includeXXX 109 | 110 | - Add elements in `inst/app/www` 111 | 112 | 113 | - Use `system.file("app/www/plop.md", package = "golemexample")` 114 | 115 | 116 |
117 | 118 | Please note that the ‘golemexample’ project is released with a 119 | [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to 120 | this project, you agree to abide by its terms. 121 | -------------------------------------------------------------------------------- /data-raw/dataset.R: -------------------------------------------------------------------------------- 1 | ## code to prepare `dataset` dataset goes here 2 | 3 | dataset <- head(mtcars) 4 | usethis::use_data(dataset) 5 | 6 | plop <- list( 7 | fruits = stringr::fruit 8 | ) 9 | 10 | usethis::use_data(plop) 11 | -------------------------------------------------------------------------------- /data/dataset.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColinFay/golemexample/5fd5f72b74aa35bac78acc8f31e4a4fb150c17c6/data/dataset.rda -------------------------------------------------------------------------------- /data/plop.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColinFay/golemexample/5fd5f72b74aa35bac78acc8f31e4a4fb150c17c6/data/plop.rda -------------------------------------------------------------------------------- /dev/01_start.R: -------------------------------------------------------------------------------- 1 | # Building a Prod-Ready, Robust Shiny Application. 2 | # 3 | # Each step is optional. 4 | # 5 | # 1 - On init 6 | # 7 | ## 1.1 - Fill the descripion & set options 8 | ## 9 | ## Add information about the package that will contain your app 10 | 11 | golem::fill_desc( 12 | pkg_name = "golemexample", # The Name of the package containing the App 13 | pkg_title = "Golem Example", # The Title of the package containing the App 14 | pkg_description = "A Package to show the basics of a golem.", # The Description of the package containing the App 15 | author_first_name = "Colin", # Your First Name 16 | author_last_name = "Fay", # Your Last Name 17 | author_email = "contact@colinfay.me", # Your Email 18 | repo_url = "https://github.com/colinfay/golemexample" # The (optional) URL of the GitHub Repo 19 | ) 20 | 21 | ## Use this desc to set {golem} options 22 | 23 | golem::set_golem_options() 24 | 25 | ## 1.2 - Set common Files 26 | ## 27 | ## If you want to use the MIT licence, README, code of conduct, lifecycle badge, and news 28 | 29 | usethis::use_mit_license( name = "Colin Fay" ) # You can set another licence here 30 | usethis::use_readme_rmd( open = FALSE ) 31 | usethis::use_code_of_conduct() 32 | usethis::use_lifecycle_badge( "Experimental" ) 33 | 34 | usethis::use_news_md( open = FALSE ) 35 | usethis::use_git() 36 | 37 | ## 1.3 - Add a data-raw folder 38 | ## 39 | ## If you have data in your package 40 | usethis::use_data_raw( name = "dataset", open = FALSE ) # Change "my_dataset" 41 | 42 | ## 1.4 - Init Tests 43 | ## 44 | ## Create a template for tests 45 | 46 | golem::use_recommended_tests() 47 | 48 | ## 1.5 : Use Recommended Package 49 | 50 | golem::use_recommended_deps() 51 | 52 | ## 1.6 Add various tools 53 | 54 | # If you want to change the favicon (default is golem's one) 55 | golem::remove_favicon() 56 | golem::use_favicon("") # path = "path/to/ico". Can be an online file. 57 | 58 | # Add helper functions 59 | golem::use_utils_ui() 60 | golem::use_utils_server() 61 | 62 | # You're now set! 63 | # go to dev/02_dev.R 64 | rstudioapi::navigateToFile( "dev/02_dev.R" ) 65 | 66 | -------------------------------------------------------------------------------- /dev/02_dev.R: -------------------------------------------------------------------------------- 1 | # Building a Prod-Ready, Robust Shiny Application. 2 | # 3 | # Each step is optional. 4 | # 5 | 6 | # 2. All along your project 7 | 8 | ## 2.1 Add modules 9 | ## 10 | golem::add_module( name = "my_first_module" ) # Name of the module 11 | golem::add_module( name = "my_other_module" ) # Name of the module 12 | golem::add_module( name = "my_third_module" ) # Name of the module 13 | golem::add_module( name = "my_fourth_module" ) # Name of the module 14 | 15 | ## 2.2 Add dependencies 16 | 17 | usethis::use_package( "thinkr" ) # To call each time you need a new package 18 | 19 | ## 2.3 Add tests 20 | 21 | usethis::use_test( "app" ) 22 | 23 | ## 2.4 Add a browser button 24 | 25 | golem::browser_button() 26 | 27 | ## 2.5 Add external files 28 | 29 | golem::add_js_file( "alertme" ) 30 | golem::add_js_handler( "handlers" ) 31 | golem::add_css_file( "custom" ) 32 | 33 | # 3. Documentation 34 | 35 | ## 3.1 Vignette 36 | usethis::use_vignette("golemexample") 37 | devtools::build_vignettes() 38 | 39 | ## 3.2 Code coverage 40 | ## You'll need GitHub there 41 | usethis::use_github() 42 | usethis::use_travis() 43 | usethis::use_appveyor() 44 | 45 | # You're now set! 46 | # go to dev/03_deploy.R 47 | rstudioapi::navigateToFile("dev/03_deploy.R") 48 | -------------------------------------------------------------------------------- /dev/03_deploy.R: -------------------------------------------------------------------------------- 1 | # Deploy a Prod-Ready, Robust Shiny Application. 2 | # 3 | # 4. Test my package 4 | 5 | devtools::test() 6 | rhub::check_for_cran() 7 | 8 | # 5. Deployment elements 9 | 10 | ## 5.1 If you want to deploy on RStudio related platforms 11 | golem::add_rstudioconnect_file() 12 | golem::add_shinyappsio_file() 13 | golem::add_shinyserver_file() 14 | 15 | ## 5.2 If you want to deploy via a generic Dockerfile 16 | golem::add_dockerfile() 17 | 18 | ## 5.2 If you want to deploy to ShinyProxy 19 | golem::add_dockerfile_shinyproxy() 20 | 21 | ## 5.2 If you want to deploy to Heroku 22 | golem::add_dockerfile_heroku() 23 | -------------------------------------------------------------------------------- /dev/run_dev.R: -------------------------------------------------------------------------------- 1 | # Set options here 2 | options(golem.app.prod = FALSE) # TRUE = production mode, FALSE = development mode 3 | 4 | # Detach all loaded packages and clean your environment 5 | golem::detach_all_attached() 6 | # rm(list=ls(all.names = TRUE)) 7 | 8 | # Document and reload your package 9 | golem::document_and_reload() 10 | 11 | # Run the application 12 | run_app() 13 | -------------------------------------------------------------------------------- /golemexample.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /inst/app/www/alertme.js: -------------------------------------------------------------------------------- 1 | alertme = function(){ 2 | alert("simple js!"); 3 | } -------------------------------------------------------------------------------- /inst/app/www/custom.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: pink; 3 | } -------------------------------------------------------------------------------- /inst/app/www/guit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColinFay/golemexample/5fd5f72b74aa35bac78acc8f31e4a4fb150c17c6/inst/app/www/guit.jpg -------------------------------------------------------------------------------- /inst/app/www/handlers.js: -------------------------------------------------------------------------------- 1 | $( document ).ready(function() { 2 | Shiny.addCustomMessageHandler('alertarg', function(arg) { 3 | alert(arg); 4 | }) 5 | }); 6 | -------------------------------------------------------------------------------- /inst/app/www/plop.md: -------------------------------------------------------------------------------- 1 | ## An example of an included markdown 2 | 3 | Note that external markdown can be put in inst/app/www/ or anywhere inst/. 4 | 5 | `addResourcePath()` adds a link __available at runtime__, i.e while your app is served in your browser. 6 | 7 | Including an external JS or HTML is to be done like this: 8 | 9 | ``` r 10 | includeMarkdown( 11 | system.file("app/www/plop.md", package = "golemexample") 12 | ) 13 | ``` -------------------------------------------------------------------------------- /man/mod_my_first_module.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_my_first_module.R 3 | \name{mod_my_first_module_ui} 4 | \alias{mod_my_first_module_ui} 5 | \alias{mod_my_first_module_server} 6 | \title{mod_my_first_module_ui and mod_my_first_module_server} 7 | \usage{ 8 | mod_my_first_module_ui(id) 9 | 10 | mod_my_first_module_server(input, output, session, r) 11 | } 12 | \arguments{ 13 | \item{id}{shiny id} 14 | 15 | \item{input}{internal} 16 | 17 | \item{output}{internal} 18 | 19 | \item{session}{internal} 20 | } 21 | \description{ 22 | A shiny Module. 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/mod_my_fourth_module.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_my_fourth_module.R 3 | \name{mod_my_fourth_module_ui} 4 | \alias{mod_my_fourth_module_ui} 5 | \alias{mod_my_fourth_module_server} 6 | \title{mod_my_fourth_module_ui and mod_my_fourth_module_server} 7 | \usage{ 8 | mod_my_fourth_module_ui(id) 9 | 10 | mod_my_fourth_module_server(input, output, session) 11 | } 12 | \arguments{ 13 | \item{id}{shiny id} 14 | 15 | \item{input}{internal} 16 | 17 | \item{output}{internal} 18 | 19 | \item{session}{internal} 20 | } 21 | \description{ 22 | A shiny Module. 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/mod_my_other_module.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_my_other_module.R 3 | \name{mod_my_other_module_ui} 4 | \alias{mod_my_other_module_ui} 5 | \alias{mod_my_other_module_server} 6 | \title{mod_my_other_module_ui and mod_my_other_module_server} 7 | \usage{ 8 | mod_my_other_module_ui(id) 9 | 10 | mod_my_other_module_server(input, output, session, r) 11 | } 12 | \arguments{ 13 | \item{id}{shiny id} 14 | 15 | \item{input}{internal} 16 | 17 | \item{output}{internal} 18 | 19 | \item{session}{internal} 20 | } 21 | \description{ 22 | A shiny Module. 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/mod_my_third_module.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mod_my_third_module.R 3 | \name{mod_my_third_module_ui} 4 | \alias{mod_my_third_module_ui} 5 | \alias{mod_my_third_module_server} 6 | \title{mod_my_third_module_ui and mod_my_third_module_server} 7 | \usage{ 8 | mod_my_third_module_ui(id) 9 | 10 | mod_my_third_module_server(input, output, session, r) 11 | } 12 | \arguments{ 13 | \item{id}{shiny id} 14 | 15 | \item{input}{internal} 16 | 17 | \item{output}{internal} 18 | 19 | \item{session}{internal} 20 | } 21 | \description{ 22 | A shiny Module. 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/run_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/run_app.R 3 | \name{run_app} 4 | \alias{run_app} 5 | \title{Run the Shiny Application} 6 | \usage{ 7 | run_app(name = "example", time = Sys.time(), port = 2811) 8 | } 9 | \description{ 10 | Run the Shiny Application 11 | } 12 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(golemexample) 3 | 4 | test_check("golemexample") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-golem-recommended.R: -------------------------------------------------------------------------------- 1 | context("golem tests") 2 | 3 | library(golem) 4 | 5 | test_that("app ui", { 6 | ui <- app_ui() 7 | expect_shinytaglist(ui) 8 | }) 9 | 10 | test_that("app server", { 11 | server <- app_server 12 | expect_is(server, "function") 13 | }) 14 | 15 | # Configure this test to fit your need 16 | test_that( 17 | "app launches",{ 18 | skip_on_cran() 19 | skip_on_travis() 20 | skip_on_appveyor() 21 | x <- processx::process$new( 22 | "R", 23 | c( 24 | "-e", 25 | "setwd('../../'); pkgload::load_all();run_app()" 26 | ) 27 | ) 28 | Sys.sleep(5) 29 | expect_true(x$is_alive()) 30 | x$kill() 31 | } 32 | ) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | --------------------------------------------------------------------------------