From a56ed53047cf7b3ceb9d08d52fa82299451c66e9 Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:52:36 +0100 Subject: [PATCH 1/7] Modularise the POC --- R/add_external_resources.R | 3 +- R/app_server.R | 61 +++++++------------------------------- R/app_ui.R | 20 ++++--------- R/fct_plot.R | 20 +++++-------- R/fct_utils.R | 8 ----- R/mod_plot_trend.R | 46 ++++++++++++++++++++++++++++ R/mod_select_provider.R | 33 +++++++++++++++++++++ R/mod_select_strategy.R | 33 +++++++++++++++++++++ 8 files changed, 137 insertions(+), 87 deletions(-) delete mode 100644 R/fct_utils.R create mode 100644 R/mod_plot_trend.R create mode 100644 R/mod_select_provider.R create mode 100644 R/mod_select_strategy.R diff --git a/R/add_external_resources.R b/R/add_external_resources.R index 0b1778c..0725d7a 100644 --- a/R/add_external_resources.R +++ b/R/add_external_resources.R @@ -1,6 +1,7 @@ #' Add External Resources to the Application #' This function is internally used to add external resources inside the Shiny #' application. +#' @noRd add_external_resources <- function() { shiny::addResourcePath( "www", @@ -12,7 +13,7 @@ add_external_resources <- function() { } #' Access Files in the Current App -#' @param ... character vectors, specifying subdirectory and file(s) +#' @param ... Character vectors, specifying subdirectory and file(s) #' within your package. The default, none, returns the root of the app. #' @noRd app_sys <- function(...) { diff --git a/R/app_server.R b/R/app_server.R index 3d91550..f9e20c3 100644 --- a/R/app_server.R +++ b/R/app_server.R @@ -1,58 +1,17 @@ -#' The application server-side -#' @param input,output,session Internal parameters for {shiny}. +#' Server-Side Application +#' @param input,output,session Internal parameters for 'shiny'. #' @noRd app_server <- function(input, output, session) { - # Data ---- - container <- azkit::get_container(Sys.getenv("AZ_CONTAINER_INPUTS")) rates <- azkit::read_azure_parquet(container, "rates", "dev") - # Reactives ---- - - selected_provider <- shiny::reactive(input$provider_select) - selected_strategy <- shiny::reactive(input$strategy_select) - - rates_prepared <- shiny::reactive({ - rates |> - dplyr::filter( - .data$provider == selected_provider(), - .data$strategy == selected_strategy() - ) |> - dplyr::arrange(.data$fyear) - }) |> - shiny::bindEvent(selected_provider(), selected_strategy()) - - # Observers ---- - - shiny::observe({ - providers <- jsonlite::read_json( - app_sys("app", "data", "datasets.json"), - simplify_vector = TRUE - ) - provider_choices <- purrr::set_names(names(providers), providers) - shiny::updateSelectInput( - session, - "provider_select", - choices = provider_choices - ) - }) - - shiny::observe({ - strategies <- jsonlite::read_json( - app_sys("app", "data", "mitigators.json"), - simplify_vector = TRUE - ) - strategy_choices <- purrr::set_names(names(strategies), strategies) - shiny::updateSelectInput( - session, - "strategy_select", - choices = strategy_choices - ) - }) - - # Outputs ---- + selected_provider <- mod_select_provider_server("mod_select_provider") + selected_strategy <- mod_select_provider_server("mod_select_strategy") - output$rates_plot <- shiny::renderPlot({ - rates_prepared() |> plot_rates() - }) + mod_plot_trend_server( + "mod_plot_trend", + rates, + selected_provider, + selected_strategy + ) } diff --git a/R/app_ui.R b/R/app_ui.R index 24e582f..20820b9 100644 --- a/R/app_ui.R +++ b/R/app_ui.R @@ -1,20 +1,12 @@ -#' The application User-Interface -#' @param request Internal parameter for shiny. +#' Application User Interface +#' @param request Internal parameter for 'shiny'. #' @noRd app_ui <- function(request) { bslib::page_sidebar( title = "CPMA Explorer", sidebar = bslib::sidebar( - shiny::selectInput( - "provider_select", - "Choose a provider:", - choices = NULL - ), - shiny::selectInput( - "strategy_select", - "Choose a strategy:", - choices = NULL - ) + mod_select_provider_ui("mod_select_provider"), + mod_select_strategy_ui("mod_select_strategy"), ), bslib::card( @@ -30,9 +22,7 @@ app_ui <- function(request) { bslib::card( bslib::card_header("Trend in rates"), - bslib::card_body( - shiny::plotOutput("rates_plot") - ), + bslib::card_body(mod_plot_trend_ui("mod_plot_trend")), full_screen = TRUE ) ) diff --git a/R/fct_plot.R b/R/fct_plot.R index 38fec15..8004f23 100644 --- a/R/fct_plot.R +++ b/R/fct_plot.R @@ -6,23 +6,19 @@ #' financial year in the form `"2023/24"`. #' @param rate_col Character. Name of the column in `rates_df` containing the #' rate value (the type of which is dependent on the strategy). +#' @return A ggplot2 object. +#' @export plot_rates <- function(rates_df, fyear_col = "fyear", rate_col = "rate") { - x_breaks <- rates_df[[fyear_col]] - x_labels <- enstring_fyear(x_breaks) - rates_df |> - ggplot2::ggplot(ggplot2::aes( - x = .data[[fyear_col]], - y = .data[[rate_col]] - )) + + ggplot2::ggplot( + ggplot2::aes( + x = .data[[fyear_col]], + y = .data[[rate_col]] + ) + ) + ggplot2::geom_line() + ggplot2::labs( x = "Financial year", y = "Rate" - ) + - ggplot2::scale_x_continuous( - breaks = x_breaks, - labels = x_labels, - guide = ggplot2::guide_axis(angle = 45) ) } diff --git a/R/fct_utils.R b/R/fct_utils.R deleted file mode 100644 index 5d36b15..0000000 --- a/R/fct_utils.R +++ /dev/null @@ -1,8 +0,0 @@ -#' Convert a Financial Year to Character -#' @param year Integer. Expressed in the form `202526`. To be converted to the -#' form `"2025/26"`. -enstring_fyear <- function(year) { - yyyy <- stringr::str_sub(year, 1, 4) - yy <- stringr::str_sub(year, -2) - paste0(yyyy, "/", yy) -} diff --git a/R/mod_plot_trend.R b/R/mod_plot_trend.R new file mode 100644 index 0000000..39b2c54 --- /dev/null +++ b/R/mod_plot_trend.R @@ -0,0 +1,46 @@ +#' Plot Trend UI +#' @param id,input,output,session Internal parameters for `shiny`. +#' @noRd +mod_plot_trend_ui <- function(id) { + ns <- shiny::NS(id) + shiny::plotOutput(ns("rates_plot")) +} + +#' Plot Trend Server +#' @param id Internal parameter for `shiny`. +#' @param rates A data.frame. Annual rate values for combinations of provider +#' and TPMA. +#' @param selected_provider Character. Provider code, e.g. `"RCX"`. +#' @param selected_strategy Character. TPMA variable name, e.g. +#' `"discharged_no_treatment_adult_ambulance"`. +#' @noRd +mod_plot_trend_server <- function( + id, + rates, + selected_provider, + selected_strategy +) { + shiny::moduleServer(id, function(input, output, session) { + ns <- session$ns + + rates_prepared <- shiny::reactive({ + shiny::req(rates) + shiny::req(selected_provider()) + shiny::req(selected_strategy()) + + rates |> + dplyr::filter( + .data$provider == selected_provider(), + .data$strategy == selected_strategy() + ) |> + dplyr::arrange(.data$fyear) + }) |> + shiny::bindEvent(selected_provider(), selected_strategy()) + + output$rates_plot <- shiny::renderPlot({ + rates <- rates_prepared() + shiny::req(nrow(rates) > 0) + plot_rates(rates) + }) + }) +} diff --git a/R/mod_select_provider.R b/R/mod_select_provider.R new file mode 100644 index 0000000..5e26d1c --- /dev/null +++ b/R/mod_select_provider.R @@ -0,0 +1,33 @@ +#' Select Provider UI +#' @param id,input,output,session Internal parameters for `shiny`. +#' @noRd +mod_select_provider_ui <- function(id) { + ns <- shiny::NS(id) + shiny::selectInput( + ns("provider_select"), + "Choose a provider:", + choices = NULL + ) +} + +#' Select Provider Server +#' @param id Internal parameter for `shiny`. +#' @param +#' @noRd +mod_select_provider_server <- function(id) { + shiny::moduleServer(id, function(input, output, session) { + shiny::observe({ + providers <- jsonlite::read_json( + app_sys("app", "data", "datasets.json"), + simplify_vector = TRUE + ) + provider_choices <- purrr::set_names(names(providers), providers) + shiny::updateSelectInput( + session, + "provider_select", + choices = provider_choices + ) + }) + shiny::reactive(input$provider_select) + }) +} diff --git a/R/mod_select_strategy.R b/R/mod_select_strategy.R new file mode 100644 index 0000000..3ac6c45 --- /dev/null +++ b/R/mod_select_strategy.R @@ -0,0 +1,33 @@ +#' Select Strategy UI +#' @param id,input,output,session Internal parameters for `shiny`. +#' @noRd +mod_select_strategy_ui <- function(id) { + ns <- shiny::NS(id) + shiny::selectInput( + ns("strategy_select"), + "Choose a strategy:", + choices = NULL + ) +} + +#' Select Strategy Server +#' @param id Internal parameter for `shiny`. +#' @param +#' @noRd +mod_select_strategy_server <- function(id) { + shiny::moduleServer(id, function(input, output, session) { + shiny::observe({ + strategies <- jsonlite::read_json( + app_sys("app", "data", "mitigators.json"), + simplify_vector = TRUE + ) + strategy_choices <- purrr::set_names(names(strategies), strategies) + shiny::updateSelectInput( + session, + "strategy_select", + choices = strategy_choices + ) + }) + shiny::reactive(input$strategy_select) + }) +} From d348a2c857ca61889d68b8701636cf07d44c6e5c Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 18:02:59 +0100 Subject: [PATCH 2/7] Update terminology --- .Rbuildignore | 2 +- DESCRIPTION | 17 ++++++++--------- NAMESPACE | 1 + R/add_external_resources.R | 2 +- R/app_ui.R | 2 +- R/mod_select_provider.R | 1 - R/mod_select_strategy.R | 1 - README.md | 6 +++--- dev/deploy.R | 4 ++-- man/add_external_resources.Rd | 15 --------------- man/enstring_fyear.Rd | 15 --------------- man/plot_rates.Rd | 3 +++ ...orer-package.Rd => tpma.explorer-package.Rd} | 14 +++++++------- cpma-explorer.Rproj => tpma-explorer.Rproj | 0 14 files changed, 27 insertions(+), 56 deletions(-) delete mode 100644 man/add_external_resources.Rd delete mode 100644 man/enstring_fyear.Rd rename man/{cpma.explorer-package.Rd => tpma.explorer-package.Rd} (50%) rename cpma-explorer.Rproj => tpma-explorer.Rproj (100%) diff --git a/.Rbuildignore b/.Rbuildignore index 03e9f13..eeb3025 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -4,7 +4,7 @@ ^\.vscode$ ^app\.R$ ^CODEOWNERS$ -^cpma-explorer\.Rproj$ +^tpma-explorer\.Rproj$ ^dev$ ^LICENSE\.md$ ^README\.md$ diff --git a/DESCRIPTION b/DESCRIPTION index 224e9cc..f6d8c0b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,13 +1,13 @@ -Package: cpma.explorer -Title: Explore CPMA Data -Version: 0.0.0.9000 +Package: tpma.explorer +Title: Explore TPMA Data +Version: 0.1.0.9000 Authors@R: person("Matt", "Dray", , "matt.dray@nhs.net", role = c("aut", "cre")) Description: A Shiny-app-in-a-package to explore data related to - categories of potentially mitigaable activity (CPMAs). + Types of Potentially Mitigatable Activity (TPMAs). License: MIT + file LICENSE -URL: https://github.com/The-Strategy-Unit/cpma-explorer -BugReports: https://github.com/The-Strategy-Unit/cpma-explorer/issues +URL: https://github.com/The-Strategy-Unit/tpma-explorer +BugReports: https://github.com/The-Strategy-Unit/tpma-explorer/issues Depends: R (>= 4.1.0) Imports: @@ -19,10 +19,9 @@ Imports: jsonlite, purrr, rlang, - shiny, - stringr + shiny Remotes: The-Strategy-Unit/azkit Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 diff --git a/NAMESPACE b/NAMESPACE index 7076e99..b73ca71 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(plot_rates) export(run_app) importFrom(rlang,.data) importFrom(rlang,.env) diff --git a/R/add_external_resources.R b/R/add_external_resources.R index 0725d7a..5003741 100644 --- a/R/add_external_resources.R +++ b/R/add_external_resources.R @@ -17,5 +17,5 @@ add_external_resources <- function() { #' within your package. The default, none, returns the root of the app. #' @noRd app_sys <- function(...) { - system.file(..., package = "cpma.explorer") + system.file(..., package = "tpma.explorer") } diff --git a/R/app_ui.R b/R/app_ui.R index 20820b9..150f528 100644 --- a/R/app_ui.R +++ b/R/app_ui.R @@ -3,7 +3,7 @@ #' @noRd app_ui <- function(request) { bslib::page_sidebar( - title = "CPMA Explorer", + title = "TPMA Explorer", sidebar = bslib::sidebar( mod_select_provider_ui("mod_select_provider"), mod_select_strategy_ui("mod_select_strategy"), diff --git a/R/mod_select_provider.R b/R/mod_select_provider.R index 5e26d1c..7768541 100644 --- a/R/mod_select_provider.R +++ b/R/mod_select_provider.R @@ -12,7 +12,6 @@ mod_select_provider_ui <- function(id) { #' Select Provider Server #' @param id Internal parameter for `shiny`. -#' @param #' @noRd mod_select_provider_server <- function(id) { shiny::moduleServer(id, function(input, output, session) { diff --git a/R/mod_select_strategy.R b/R/mod_select_strategy.R index 3ac6c45..437a058 100644 --- a/R/mod_select_strategy.R +++ b/R/mod_select_strategy.R @@ -12,7 +12,6 @@ mod_select_strategy_ui <- function(id) { #' Select Strategy Server #' @param id Internal parameter for `shiny`. -#' @param #' @noRd mod_select_strategy_server <- function(id) { shiny::moduleServer(id, function(input, output, session) { diff --git a/README.md b/README.md index 90fb884..1485183 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# cpma-explorer +# tpma-explorer [![Project Status: Concept – Minimal or no implementation has been done yet, or the repository is only intended to be a limited example, demo, or proof-of-concept.](https://www.repostatus.org/badges/latest/concept.svg)](https://www.repostatus.org/#concept) -An app to explore data for categories of potentially-mitigable activity (CPMAs). +An app to explore data for Types of Potentially-Mitigable Activity (TPMAs). -The app is [deployed to Posit Connect](https://connect.strategyunitwm.nhs.uk/cpma-explorer/) (login and permissions required). +The app is [deployed to Posit Connect](https://connect.strategyunitwm.nhs.uk/tpma-explorer/) (login and permissions required). The app is made with [Shiny](https://shiny.posit.co/) and is an R package following [the nolem approach](https://github.com/StatsRhian/nolem). diff --git a/dev/deploy.R b/dev/deploy.R index a73e769..90d5a0b 100644 --- a/dev/deploy.R +++ b/dev/deploy.R @@ -1,6 +1,6 @@ rsconnect::deployApp( - appName = "cpma-explorer", - appTitle = "CPMA explorer", + appName = "tpma-explorer", + appTitle = "TPMA explorer", server = "connect.strategyunitwm.nhs.uk", appId = 200, appFiles = c( diff --git a/man/add_external_resources.Rd b/man/add_external_resources.Rd deleted file mode 100644 index 597d55f..0000000 --- a/man/add_external_resources.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/add_external_resources.R -\name{add_external_resources} -\alias{add_external_resources} -\title{Add External Resources to the Application -This function is internally used to add external resources inside the Shiny -application.} -\usage{ -add_external_resources() -} -\description{ -Add External Resources to the Application -This function is internally used to add external resources inside the Shiny -application. -} diff --git a/man/enstring_fyear.Rd b/man/enstring_fyear.Rd deleted file mode 100644 index 3ba131d..0000000 --- a/man/enstring_fyear.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/fct_utils.R -\name{enstring_fyear} -\alias{enstring_fyear} -\title{Convert a Financial Year to Character} -\usage{ -enstring_fyear(year) -} -\arguments{ -\item{year}{Integer. Expressed in the form \code{202526}. To be converted to the -form \code{"2025/26"}.} -} -\description{ -Convert a Financial Year to Character -} diff --git a/man/plot_rates.Rd b/man/plot_rates.Rd index bdf95d5..05fa127 100644 --- a/man/plot_rates.Rd +++ b/man/plot_rates.Rd @@ -17,6 +17,9 @@ financial year in the form \code{"2023/24"}.} \item{rate_col}{Character. Name of the column in \code{rates_df} containing the rate value (the type of which is dependent on the strategy).} } +\value{ +A ggplot2 object. +} \description{ Plot Trend in Rates } diff --git a/man/cpma.explorer-package.Rd b/man/tpma.explorer-package.Rd similarity index 50% rename from man/cpma.explorer-package.Rd rename to man/tpma.explorer-package.Rd index 35d3d4e..db2291f 100644 --- a/man/cpma.explorer-package.Rd +++ b/man/tpma.explorer-package.Rd @@ -1,18 +1,18 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/cpma-explorer-app.R \docType{package} -\name{cpma.explorer-package} -\alias{cpma.explorer} -\alias{cpma.explorer-package} -\title{cpma.explorer: Explore CPMA Data} +\name{tpma.explorer-package} +\alias{tpma.explorer} +\alias{tpma.explorer-package} +\title{tpma.explorer: Explore TPMA Data} \description{ -A Shiny-app-in-a-package to explore data related to categories of potentially mitigaable activity (CPMAs). +A Shiny-app-in-a-package to explore data related to Types of Potentially Mitigatable Activity (TPMAs). } \seealso{ Useful links: \itemize{ - \item \url{https://github.com/The-Strategy-Unit/cpma-explorer} - \item Report bugs at \url{https://github.com/The-Strategy-Unit/cpma-explorer/issues} + \item \url{https://github.com/The-Strategy-Unit/tpma-explorer} + \item Report bugs at \url{https://github.com/The-Strategy-Unit/tpma-explorer/issues} } } diff --git a/cpma-explorer.Rproj b/tpma-explorer.Rproj similarity index 100% rename from cpma-explorer.Rproj rename to tpma-explorer.Rproj From 372e2db5255cceeaef98e618226131c71ee20dd3 Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 19:14:06 +0100 Subject: [PATCH 3/7] Rename package script --- R/{cpma-explorer-app.R => tpma-explorer-app.R} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename R/{cpma-explorer-app.R => tpma-explorer-app.R} (100%) diff --git a/R/cpma-explorer-app.R b/R/tpma-explorer-app.R similarity index 100% rename from R/cpma-explorer-app.R rename to R/tpma-explorer-app.R From 298cb45695091d30235d56512f0f238ff6f6fcf3 Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 19:37:40 +0100 Subject: [PATCH 4/7] Extract lookups out of modules --- R/app_server.R | 24 ++++++++++++++++++++---- R/mod_select_provider.R | 9 ++++----- R/mod_select_strategy.R | 11 ++++++----- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/R/app_server.R b/R/app_server.R index f9e20c3..20c96db 100644 --- a/R/app_server.R +++ b/R/app_server.R @@ -3,14 +3,30 @@ #' @noRd app_server <- function(input, output, session) { container <- azkit::get_container(Sys.getenv("AZ_CONTAINER_INPUTS")) - rates <- azkit::read_azure_parquet(container, "rates", "dev") + rates_data <- azkit::read_azure_parquet(container, "rates", "dev") - selected_provider <- mod_select_provider_server("mod_select_provider") - selected_strategy <- mod_select_provider_server("mod_select_strategy") + providers_lookup <- jsonlite::read_json( + app_sys("app", "data", "datasets.json"), + simplify_vector = TRUE + ) + + strategies_lookup <- jsonlite::read_json( + app_sys("app", "data", "mitigators.json"), + simplify_vector = TRUE + ) + + selected_provider <- mod_select_provider_server( + "mod_select_provider", + providers_lookup + ) + selected_strategy <- mod_select_strategy_server( + "mod_select_strategy", + strategies_lookup + ) mod_plot_trend_server( "mod_plot_trend", - rates, + rates_data, selected_provider, selected_strategy ) diff --git a/R/mod_select_provider.R b/R/mod_select_provider.R index 7768541..cb003e1 100644 --- a/R/mod_select_provider.R +++ b/R/mod_select_provider.R @@ -12,14 +12,13 @@ mod_select_provider_ui <- function(id) { #' Select Provider Server #' @param id Internal parameter for `shiny`. +#' @param providers A named list. Names are provider codes (e.g. `"RCF"`) and +#' their values are the corresponding human-readable names and codes (e.g. +#' `"Airedale NHS Foundation Trust (RCF)"`). #' @noRd -mod_select_provider_server <- function(id) { +mod_select_provider_server <- function(id, providers) { shiny::moduleServer(id, function(input, output, session) { shiny::observe({ - providers <- jsonlite::read_json( - app_sys("app", "data", "datasets.json"), - simplify_vector = TRUE - ) provider_choices <- purrr::set_names(names(providers), providers) shiny::updateSelectInput( session, diff --git a/R/mod_select_strategy.R b/R/mod_select_strategy.R index 437a058..65b85a2 100644 --- a/R/mod_select_strategy.R +++ b/R/mod_select_strategy.R @@ -12,14 +12,15 @@ mod_select_strategy_ui <- function(id) { #' Select Strategy Server #' @param id Internal parameter for `shiny`. +#' @param strategies A named list. Names are TPMA variable names (e.g. +#' `"alcohol_partially_attributable_acute"`) and their values are the +#' corresponding human-readable names and codes (e.g. +#' `"Alcohol Related Admissions (Acute Conditions - Partially Attributable) +#' (IP-AA-001)"`). #' @noRd -mod_select_strategy_server <- function(id) { +mod_select_strategy_server <- function(id, strategies) { shiny::moduleServer(id, function(input, output, session) { shiny::observe({ - strategies <- jsonlite::read_json( - app_sys("app", "data", "mitigators.json"), - simplify_vector = TRUE - ) strategy_choices <- purrr::set_names(names(strategies), strategies) shiny::updateSelectInput( session, From 9924310c1d33966449bd3999b15b3347e5b0059a Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 19:38:06 +0100 Subject: [PATCH 5/7] Remove bindEvent, add validation message --- R/mod_plot_trend.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/mod_plot_trend.R b/R/mod_plot_trend.R index 39b2c54..1722baf 100644 --- a/R/mod_plot_trend.R +++ b/R/mod_plot_trend.R @@ -34,12 +34,14 @@ mod_plot_trend_server <- function( .data$strategy == selected_strategy() ) |> dplyr::arrange(.data$fyear) - }) |> - shiny::bindEvent(selected_provider(), selected_strategy()) + }) output$rates_plot <- shiny::renderPlot({ rates <- rates_prepared() - shiny::req(nrow(rates) > 0) + shiny::validate(shiny::need( + nrow(rates) > 0, + "No data available for these selections" + )) plot_rates(rates) }) }) From 9215b4ab35fb18b6d6b02d73454fe0d51a898bff Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 19:38:37 +0100 Subject: [PATCH 6/7] Redocument package --- man/tpma.explorer-package.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/tpma.explorer-package.Rd b/man/tpma.explorer-package.Rd index db2291f..491f73e 100644 --- a/man/tpma.explorer-package.Rd +++ b/man/tpma.explorer-package.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cpma-explorer-app.R +% Please edit documentation in R/tpma-explorer-app.R \docType{package} \name{tpma.explorer-package} \alias{tpma.explorer} From 26462e92656b7ba41a079073d95c49f8eb492424 Mon Sep 17 00:00:00 2001 From: Matt Dray <18232097+matt-dray@users.noreply.github.com> Date: Tue, 21 Oct 2025 19:40:45 +0100 Subject: [PATCH 7/7] Remove unused ns call --- R/mod_plot_trend.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/R/mod_plot_trend.R b/R/mod_plot_trend.R index 1722baf..66d9cf5 100644 --- a/R/mod_plot_trend.R +++ b/R/mod_plot_trend.R @@ -21,8 +21,6 @@ mod_plot_trend_server <- function( selected_strategy ) { shiny::moduleServer(id, function(input, output, session) { - ns <- session$ns - rates_prepared <- shiny::reactive({ shiny::req(rates) shiny::req(selected_provider())