From dd6dbe6f17889a3690cf5725fcb76c338758179a Mon Sep 17 00:00:00 2001 From: Eric Nantz Date: Fri, 15 Sep 2023 18:59:53 -0400 Subject: [PATCH 1/3] add example file for themes data --- data_examples/df_themes.rds | Bin 0 -> 787 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data_examples/df_themes.rds diff --git a/data_examples/df_themes.rds b/data_examples/df_themes.rds new file mode 100644 index 0000000000000000000000000000000000000000..cac1d8254f1d65993c93187719a320c7f0504b7e GIT binary patch literal 787 zcmV+u1MK`CiwFP!000001D#Y&PZL2H9@?!fpn?*JCo*RvL^!DzE5(A+#)ekmU@X(! zX**$eXEQU4U}8WK{Rk;(PQd;I zc=QDj_}l~Fhy1sI65@wHV+{A9h} zhzlx|bV8FlTA>|X>AJ>|U08epf3KFfFO>*w#kg;%mzhU>sT~qLSE>&hB8kt`xKva~ zOne7F5(?J@^Oeb+u2aFN#EW-vmHDjAI-%Z^+2ty89O~mbbBvgLNl>D=0P|+a<@R>W zy+M@SO=@$Sb2V-@J5^;eQizu+4RBdd`XW0G_AfY`>k zy-I}G!!@q-_WBCS#8*TrX5%HQQDU<>)4r9i?nNu?_aoJSg@tn(P*|ew*`vtZHzzS( z;(7(V5)$DITwXvGJ99RLGHHdbmSzNOaN#<5U2h^0Fi|C9hq?o;$qg&QB*&A!e-i!X zzZxta!i0J-`A^YMUa<+2y#=6Y6aJ+e)Qhpl96Miaj_PKOz-UW#ODKw@`^ zAhsUX|Ka&pF;Q{G6r28KF74c<>rV{U*N>Z&7cAeeFD&AXd( zsLQ;R2t!!VbEHl4P4WrwV+w# Date: Fri, 15 Sep 2023 19:00:31 -0400 Subject: [PATCH 2/3] add module code-along and exercise files --- .../codealong-1/execute-results/html.json | 16 +++++ materials/d1-02-structure/codealong-1.qmd | 59 +++++++++++++++++++ materials/d1-02-structure/ex-1.qmd | 50 ++++++++++++++++ units/d1-02-structure.qmd | 20 +++++++ 4 files changed, 145 insertions(+) create mode 100644 _freeze/materials/d1-02-structure/codealong-1/execute-results/html.json create mode 100644 materials/d1-02-structure/codealong-1.qmd create mode 100644 materials/d1-02-structure/ex-1.qmd diff --git a/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json b/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json new file mode 100644 index 0000000..11df227 --- /dev/null +++ b/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "c88328e0e03c4bc3dae3add79032a6de", + "result": { + "markdown": "---\ntitle: Modules for LEGO attribute selections\n---\n\n\nAs you make the transition to building production Shiny applications, Shiny modules are a very important tool to improve code organization and overall flow of your application. We will work together to build Shiny modules that let the user filter the underlying LEGO metadata based on a key variables in the overall data.\n\n## Requirements\n\nCreste three inputs for the user to subset the LEGO metadata by the following key variables:\n\n* Theme(s) associated with sets. Default should be all sets, but let the user customize selections with a search box.\n* Year range for when set was created. Give the user a visual cue of how many sets are present in each year.\n* Pre-defined ranges for how many parts are present in each set. Ranges are the following:\n + Small (1-50 parts)\n + Medium (51-200 parts)\n + Large (201 or more parts)\n + All sizes\n\n## Data\n\nThe following data sets included in the application contain the variables needed for the requirements (note that these snippets are a reduced sample of each source data set).\n\n### `sets`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(sets)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 368\nColumns: 6\n$ set_num \"001-1\", \"002-1\", \"1030-1\", \"1038-1\", \"1039-1\", \"1237-1\", \"1…\n$ name \"Gears\", \"4.5V Samsonite Gears Motor Set\", \"TECHNIC I: Simpl…\n$ year 1965, 1965, 1985, 1985, 1986, 2001, 1999, 1999, 1999, 1999, …\n$ theme_id 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …\n$ num_parts 43, 3, 210, 120, 39, 56, 30, 29, 28, 26, 28, 103, 98, 64, 28…\n$ img_url \"https://cdn.rebrickable.com/media/sets/001-1.jpg\", \"https:/…\n```\n\n\n:::\n:::\n\n\n### `themes`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(themes)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 30\nColumns: 3\n$ theme_id 191, 708, 693, 398, 650, 234, 56, 604, 136, 736, 692, 676, 2…\n$ name \"Dark Forest\", \"The LEGO Batman Movie\", \"Monkie Kid\", \"FIRST…\n$ parent_id 186, 697, NA, NA, 632, 233, 52, NA, 126, 501, 535, NA, 227, …\n```\n\n\n:::\n:::\n\n\n\n## Plan\n\n1. Create a new module R script (and possible a supporting R script) by using `golem::add_module()` in the `dev/02_dev.R` script.\n1. Pick a Shiny input type that matches our requirements.\n1. Ensure the server-side portion of the module returns the result of the selection, with additional post-processing if necessary.\n1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively.", + "supporting": [ + "codealong-1_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/materials/d1-02-structure/codealong-1.qmd b/materials/d1-02-structure/codealong-1.qmd new file mode 100644 index 0000000..48b5dd7 --- /dev/null +++ b/materials/d1-02-structure/codealong-1.qmd @@ -0,0 +1,59 @@ +--- +title: Modules for LEGO attribute selections +--- + +As you make the transition to building production Shiny applications, Shiny modules are a very important tool to improve code organization and overall flow of your application. We will work together to build Shiny modules that let the user filter the underlying LEGO metadata based on a key variables in the overall data. + +## Requirements + +Creste three inputs for the user to subset the LEGO metadata by the following key variables: + +* Theme(s) associated with sets. Default should be all sets, but let the user customize selections with a search box. +* Year range for when set was created. Give the user a visual cue of how many sets are present in each year. +* Pre-defined ranges for how many parts are present in each set. Ranges are the following: + + Small (1-50 parts) + + Medium (51-200 parts) + + Large (201 or more parts) + + All sizes + +## Data + +The following data sets included in the application contain the variables needed for the requirements (note that these snippets are a reduced sample of each source data set). + +### `sets` + +```{r} +#| echo: true +#| eval: false +dplyr::glimpse(sets) +``` + +```{r} +#| echo: false +#| eval: true +sets <- readRDS("../../data_examples/df_sets.rds") +dplyr::glimpse(sets) +``` + +### `themes` + +```{r} +#| echo: true +#| eval: false +dplyr::glimpse(themes) +``` + +```{r} +#| echo: false +#| eval: true +themes <- readRDS("../../data_examples/df_themes.rds") +dplyr::glimpse(themes) +``` + + +## Plan + +1. Create a new module R script (and possible a supporting R script) by using `golem::add_module()` in the `dev/02_dev.R` script. +1. Pick a Shiny input type that matches our requirements. +1. Ensure the server-side portion of the module returns the result of the selection, with additional post-processing if necessary. +1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively. \ No newline at end of file diff --git a/materials/d1-02-structure/ex-1.qmd b/materials/d1-02-structure/ex-1.qmd new file mode 100644 index 0000000..df791c4 --- /dev/null +++ b/materials/d1-02-structure/ex-1.qmd @@ -0,0 +1,50 @@ +--- +title: "Value Metrics Module" +--- + +## Access Instructions + +The project used for this particular exercise is hosted on [Posit Cloud](https://posit.cloud) in this [space](https://posit.cloud/spaces/400774/join?access_code=DDgV_peF5WCCCpB5JHjQtMN2aHByWoNF0k5p8Wp7). The project for this exercise is called **modules-exercise1**. + +## Exercise Instructions + +Your task is to create a new Shiny module that displays three important metrics to the user: + +* Total number of sets +* Total number of parts among the sets +* Total number of mini-figures + +Note that these quantities are dependent on the user selections from the inputs contained in the left sidebar (theme, year, and parts range). + +Keeping with the overall user interface style, you are recommended to use the [`value_box`](https://rstudio.github.io/bslib/reference/value_box.html) function from the [`{bslib}`](https://rstudio.github.io/bslib/) package. The metrics can be derived using the function below. In the application code, you will find reactive data frames called `sets_rv` and `part_meta_rv` which can be used in the parameters of the function below. + +```r +#' Derive key LEGO data set metrics +#' +#' @param sets_rv data frame containing sets information +#' @param part_meta_rv data frame containing parts metadata information +#' +#' @import dplyr +derive_widget_metrics <- function(sets_rv, part_meta_rv) { + # number of sets + n_sets <- length(unique(sets_rv$set_num)) + + # number of parts + n_parts <- sum(sets_rv$num_parts, na.rm = TRUE) + + # number of minifigs + n_minifigs <- part_meta_rv |> + summarize(total_minifigs = sum(minifig_ind)) |> + collect() |> + pull(total_minifigs) + + return( + list( + n_sets = n_sets, + n_parts = n_parts, + n_minifigs = n_minifigs + ) + ) +} +``` + diff --git a/units/d1-02-structure.qmd b/units/d1-02-structure.qmd index dcb8f21..9c7fb7b 100644 --- a/units/d1-02-structure.qmd +++ b/units/d1-02-structure.qmd @@ -15,6 +15,17 @@ listing: sort-ui: false filter-ui: false image-placeholder: assets/img/placeholder.png + - id: code-along + contents: + - ../materials/d1-02-structure/codealong-*.qmd + type: table + fields: [subtitle, title] + field-display-names: + subtitle: "Code-Along" + sort: [filename] + sort-ui: false + filter-ui: false + image-placeholder: assets/img/placeholder.png tbl-colwidths: [5,20,75] --- @@ -29,4 +40,13 @@ These slides are under construction and will be finalized prior to the workshop ```{=html} ``` +## Code-Along Examples + +::: {#code-along} +::: + +## Exercises + +::: {#exercises} +::: From c69267206b7d24420ea8479ebdaf70a5dd5377d0 Mon Sep 17 00:00:00 2001 From: Eric Nantz Date: Sat, 16 Sep 2023 21:29:12 -0400 Subject: [PATCH 3/3] finalize module code-along --- .../codealong-1/execute-results/html.json | 4 +- materials/d1-02-structure/codealong-1.qmd | 71 ++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json b/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json index 11df227..19b749f 100644 --- a/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json +++ b/_freeze/materials/d1-02-structure/codealong-1/execute-results/html.json @@ -1,7 +1,7 @@ { - "hash": "c88328e0e03c4bc3dae3add79032a6de", + "hash": "3bc604251443b99b15f919abb6ad30ca", "result": { - "markdown": "---\ntitle: Modules for LEGO attribute selections\n---\n\n\nAs you make the transition to building production Shiny applications, Shiny modules are a very important tool to improve code organization and overall flow of your application. We will work together to build Shiny modules that let the user filter the underlying LEGO metadata based on a key variables in the overall data.\n\n## Requirements\n\nCreste three inputs for the user to subset the LEGO metadata by the following key variables:\n\n* Theme(s) associated with sets. Default should be all sets, but let the user customize selections with a search box.\n* Year range for when set was created. Give the user a visual cue of how many sets are present in each year.\n* Pre-defined ranges for how many parts are present in each set. Ranges are the following:\n + Small (1-50 parts)\n + Medium (51-200 parts)\n + Large (201 or more parts)\n + All sizes\n\n## Data\n\nThe following data sets included in the application contain the variables needed for the requirements (note that these snippets are a reduced sample of each source data set).\n\n### `sets`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(sets)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 368\nColumns: 6\n$ set_num \"001-1\", \"002-1\", \"1030-1\", \"1038-1\", \"1039-1\", \"1237-1\", \"1…\n$ name \"Gears\", \"4.5V Samsonite Gears Motor Set\", \"TECHNIC I: Simpl…\n$ year 1965, 1965, 1985, 1985, 1986, 2001, 1999, 1999, 1999, 1999, …\n$ theme_id 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …\n$ num_parts 43, 3, 210, 120, 39, 56, 30, 29, 28, 26, 28, 103, 98, 64, 28…\n$ img_url \"https://cdn.rebrickable.com/media/sets/001-1.jpg\", \"https:/…\n```\n\n\n:::\n:::\n\n\n### `themes`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(themes)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 30\nColumns: 3\n$ theme_id 191, 708, 693, 398, 650, 234, 56, 604, 136, 736, 692, 676, 2…\n$ name \"Dark Forest\", \"The LEGO Batman Movie\", \"Monkie Kid\", \"FIRST…\n$ parent_id 186, 697, NA, NA, 632, 233, 52, NA, 126, 501, 535, NA, 227, …\n```\n\n\n:::\n:::\n\n\n\n## Plan\n\n1. Create a new module R script (and possible a supporting R script) by using `golem::add_module()` in the `dev/02_dev.R` script.\n1. Pick a Shiny input type that matches our requirements.\n1. Ensure the server-side portion of the module returns the result of the selection, with additional post-processing if necessary.\n1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively.", + "markdown": "---\ntitle: Modules for LEGO attribute selections\nformat:\n html:\n code-line-numbers: false\n---\n\n\nAs you make the transition to building production Shiny applications, Shiny modules are a very important tool to improve code organization and overall flow of your application. We will work together to build Shiny modules that let the user filter the underlying LEGO metadata based on a key variables in the overall data.\n\n## Requirements\n\nCreste three inputs for the user to subset the LEGO metadata by the following key variables:\n\n* Theme(s) associated with sets. Default should be all sets, but let the user customize selections with a search box.\n* Year range for when set was created. Give the user a visual cue of how many sets are present in each year.\n* Pre-defined ranges for how many parts are present in each set. Ranges are the following:\n + Small (1-50 parts)\n + Medium (51-200 parts)\n + Large (201 or more parts)\n + All sizes\n\n## Data\n\nThe following data sets included in the application contain the variables needed for the requirements (note that these snippets are a reduced sample of each source data set).\n\n### `sets`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(sets)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 368\nColumns: 6\n$ set_num \"001-1\", \"002-1\", \"1030-1\", \"1038-1\", \"1039-1\", \"1237-1\", \"1…\n$ name \"Gears\", \"4.5V Samsonite Gears Motor Set\", \"TECHNIC I: Simpl…\n$ year 1965, 1965, 1985, 1985, 1986, 2001, 1999, 1999, 1999, 1999, …\n$ theme_id 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …\n$ num_parts 43, 3, 210, 120, 39, 56, 30, 29, 28, 26, 28, 103, 98, 64, 28…\n$ img_url \"https://cdn.rebrickable.com/media/sets/001-1.jpg\", \"https:/…\n```\n\n\n:::\n:::\n\n\n### `themes`\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndplyr::glimpse(themes)\n```\n:::\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n\n```\nRows: 30\nColumns: 3\n$ theme_id 191, 708, 693, 398, 650, 234, 56, 604, 136, 736, 692, 676, 2…\n$ name \"Dark Forest\", \"The LEGO Batman Movie\", \"Monkie Kid\", \"FIRST…\n$ parent_id 186, 697, NA, NA, 632, 233, 52, NA, 126, 501, 535, NA, 227, …\n```\n\n\n:::\n:::\n\n\n## Plan\n\n1. Create a new module R script (and possible a supporting R script) by using `golem::add_module()` in the `dev/02_dev.R` script.\n1. Pick a Shiny input type that matches our requirements.\n1. Ensure the server-side portion of the module returns the result of the selection, with additional post-processing if necessary.\n1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively.\n\n## Solution (Theme Picker)\n\nCreate the module file with the following snippet:\n\n\n::: {.cell}\n\n```{.r .cell-code}\ngolem::add_module(name = \"theme_picker\", with_test = FALSE)\n```\n:::\n\n\nWhile we could choose a `selectInput` that displays the name of the theme as the choices and allow multiple to be selected, we want to incorporate a search box with snappy performance. The [`virtualSelectInput`](https://dreamrs.github.io/shinyWidgets/reference/virtualSelectInput.html) from the [`{shinyWidgets}`](https://dreamrs.github.io/shinyWidgets/index.html) package is an excellent solution.\n\nSince we have the `themes` data set available, we can also leverage the supporting function `shinyWidgets::prepare_choices()` to get the possible choices ready for the input. The module will simply return the selection as a reactive variable.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# UI portion\nmod_theme_picker_ui <- function(id, label = NULL) {\n ns <- NS(id)\n\n themes <- dplyr::arrange(themes, name)\n\n choices_list <- shinyWidgets::prepare_choices(\n themes,\n label = name,\n value = theme_id\n )\n\n tagList(\n virtualSelectInput(\n ns(\"virt_theme_id\"),\n label = label,\n choices = choices_list,\n selected = themes$theme_id,\n multiple = TRUE,\n search = TRUE\n )\n )\n}\n\n# server portion\nmod_theme_picker_server <- function(id){\n moduleServer( id, function(input, output, session){\n ns <- session$ns\n\n return(reactive(input$virt_theme_id))\n })\n}\n```\n:::\n\n\nAt the bottom of the module script, `{golem}` automatically includes commented code for referencing the module UI and server blocks in your main Shiny application. We can copy them into the `app_ui.R` and `app_server.R` files.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# app_ui.R\nmod_theme_picker_ui(\"theme_picker_1\")\n\n# app_server.R\ninput_theme_ids <- mod_theme_picker_server(\"theme_picker_1\")\n```\n:::\n", "supporting": [ "codealong-1_files" ], diff --git a/materials/d1-02-structure/codealong-1.qmd b/materials/d1-02-structure/codealong-1.qmd index 48b5dd7..b3b2fed 100644 --- a/materials/d1-02-structure/codealong-1.qmd +++ b/materials/d1-02-structure/codealong-1.qmd @@ -1,5 +1,8 @@ --- title: Modules for LEGO attribute selections +format: + html: + code-line-numbers: false --- As you make the transition to building production Shiny applications, Shiny modules are a very important tool to improve code organization and overall flow of your application. We will work together to build Shiny modules that let the user filter the underlying LEGO metadata based on a key variables in the overall data. @@ -50,10 +53,74 @@ themes <- readRDS("../../data_examples/df_themes.rds") dplyr::glimpse(themes) ``` - ## Plan 1. Create a new module R script (and possible a supporting R script) by using `golem::add_module()` in the `dev/02_dev.R` script. 1. Pick a Shiny input type that matches our requirements. 1. Ensure the server-side portion of the module returns the result of the selection, with additional post-processing if necessary. -1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively. \ No newline at end of file +1. Plug in the UI and server-side portions of the module in the main `app_ui.R` and `app_server.R` files, respectively. + +## Solution (Theme Picker) + +Create the module file with the following snippet: + +```{r} +#| echo: true +#| eval: false +golem::add_module(name = "theme_picker", with_test = FALSE) +``` + +While we could choose a `selectInput` that displays the name of the theme as the choices and allow multiple to be selected, we want to incorporate a search box with snappy performance. The [`virtualSelectInput`](https://dreamrs.github.io/shinyWidgets/reference/virtualSelectInput.html) from the [`{shinyWidgets}`](https://dreamrs.github.io/shinyWidgets/index.html) package is an excellent solution. + +Since we have the `themes` data set available, we can also leverage the supporting function `shinyWidgets::prepare_choices()` to get the possible choices ready for the input. The module will simply return the selection as a reactive variable. + +```{r} +#| echo: true +#| eval: false + +# UI portion +mod_theme_picker_ui <- function(id, label = NULL) { + ns <- NS(id) + + themes <- dplyr::arrange(themes, name) + + choices_list <- shinyWidgets::prepare_choices( + themes, + label = name, + value = theme_id + ) + + tagList( + virtualSelectInput( + ns("virt_theme_id"), + label = label, + choices = choices_list, + selected = themes$theme_id, + multiple = TRUE, + search = TRUE + ) + ) +} + +# server portion +mod_theme_picker_server <- function(id){ + moduleServer( id, function(input, output, session){ + ns <- session$ns + + return(reactive(input$virt_theme_id)) + }) +} +``` + +At the bottom of the module script, `{golem}` automatically includes commented code for referencing the module UI and server blocks in your main Shiny application. We can copy them into the `app_ui.R` and `app_server.R` files. + +```{r} +#| echo: true +#| eval: false + +# app_ui.R +mod_theme_picker_ui("theme_picker_1") + +# app_server.R +input_theme_ids <- mod_theme_picker_server("theme_picker_1") +```