diff --git a/02_dev/create_your_own_page/create_own_table_dev_mod_app.R b/02_dev/create_your_own_page/create_own_table_dev_mod_app.R index b5e4470..36f3450 100644 --- a/02_dev/create_your_own_page/create_own_table_dev_mod_app.R +++ b/02_dev/create_your_own_page/create_own_table_dev_mod_app.R @@ -36,9 +36,10 @@ ui <- bslib::page_fillable( Create_MainInputsUI("create_inputs")["LA grouping"], Create_MainInputsUI("create_inputs")["Other grouping"], YearRangeUI("year_range"), - Create_MainInputsUI("create_inputs")["Add selection"] + Create_MainInputsUI("create_inputs")["Clear all current selections"] ) ), + # Staging table and Add selections button StagingTableUI("staging_table"), QueryTableUI("query_table"), CreateOwnTableUI("create_own_table"), @@ -66,7 +67,8 @@ server <- function(input, output, session) { year_input <- YearRangeServer( "year_range", bds_metrics, - create_inputs$indicator + create_inputs$indicator, + create_inputs$clear_selections ) # Geog Groupings diff --git a/R/lait_modules/mod_create_own_inputs.R b/R/lait_modules/mod_create_own_inputs.R index ba7255e..5b80aaa 100644 --- a/R/lait_modules/mod_create_own_inputs.R +++ b/R/lait_modules/mod_create_own_inputs.R @@ -77,10 +77,23 @@ Create_MainInputsUI <- function(id) { shiny::checkboxInput(ns("inc_regions"), "Include All Regions", FALSE), shiny::checkboxInput(ns("inc_england"), "Include England", FALSE) ), + # Clear all current selections + "Clear all current selections" = div( + style = "height: 100%; display: flex; justify-content: center; align-items: flex-end;", + shinyGovstyle::button_Input( + inputId = ns("clear_all"), + label = "Clear all current selections", + type = "warning" + ) + ), # Add selection (query) button "Add selection" = div( style = "height: 100%; display: flex; justify-content: center; align-items: flex-end;", - shiny::actionButton(ns("add_query"), "Add selections", class = "gov-uk-button") + shinyGovstyle::button_Input( + inputId = ns("add_query"), + label = "Add selections", + type = "start" + ) ) ) } @@ -166,6 +179,19 @@ Create_MainInputsServer <- function(id, bds_metrics) { ignoreNULL = FALSE ) + # Clear all current selections + observeEvent(input$clear_all, { + # Reset inputs to their initial state + updateSelectizeInput(session, "geog_input", selected = NA) + updateSelectizeInput(session, "indicator", selected = NA) + updateRadioButtons(session, "la_group", selected = "no_groups") + updateCheckboxInput(session, "inc_regions", value = FALSE) + updateCheckboxInput(session, "inc_england", value = FALSE) + + # Emit a reset signal for year_range + session$sendCustomMessage("clear_year_range", TRUE) + }) + # Return create your own main inputs create_inputs <- list( geog = reactive(input$geog_input), @@ -175,6 +201,7 @@ Create_MainInputsServer <- function(id, bds_metrics) { la_group = reactive(input$la_group), inc_regions = reactive(input$inc_regions), inc_england = reactive(input$inc_england), + clear_selections = reactive(input$clear_all), add_query = reactive(input$add_query) ) @@ -223,7 +250,7 @@ YearRangeUI <- function(id) { #' @return A list containing reactive values for selected year range #' and available year choices. #' -YearRangeServer <- function(id, bds_metrics, indicator_input) { +YearRangeServer <- function(id, bds_metrics, indicator_input, clear_selections) { moduleServer(id, function(input, output, session) { # Compute years choices available based on selected indicator years_choices <- reactive({ @@ -272,6 +299,11 @@ YearRangeServer <- function(id, bds_metrics, indicator_input) { } }) + # Reset year range when clear all current selections button clicked + observeEvent(clear_selections(), { + shinyWidgets::updatePickerInput(session, "year_range", selected = NULL) + }) + # Collect selected year range and available year choices # (choices are used in query table to set year range info) year_input <- list( diff --git a/R/lait_modules/mod_create_own_table.R b/R/lait_modules/mod_create_own_table.R index a8f5bc7..da5de6f 100644 --- a/R/lait_modules/mod_create_own_table.R +++ b/R/lait_modules/mod_create_own_table.R @@ -197,7 +197,14 @@ StagingTableUI <- function(id) { div( class = "well", style = "overflow-y: visible;", - h3("Staging Table (View of current selections)"), + bslib::layout_column_wrap( + h3("Staging Table (View of current selections)"), + # Include empty divs so matches inputs above and add selections aligns + div(), + div(), + # Add selections button + Create_MainInputsUI("create_inputs")["Add selection"] + ), bslib::card( with_gov_spinner( reactable::reactableOutput(ns("staging_table")), @@ -207,6 +214,7 @@ StagingTableUI <- function(id) { ) } + # Staging table Server --------------------------------------------------------- # Output a formatted reactable table of the staging data # Few error message table outputs for incorrect/ missing selections diff --git a/R/lait_modules/mod_la_lvl_metadata.R b/R/lait_modules/mod_la_lvl_metadata.R index fd890fa..6c73898 100644 --- a/R/lait_modules/mod_la_lvl_metadata.R +++ b/R/lait_modules/mod_la_lvl_metadata.R @@ -1,147 +1,152 @@ -# nolint start: object_name -# -#' UI module for displaying metadata -#' -#' @param id A character string that is used as the namespace for the module's -#' input and output. -#' @return A UI element that displays the metadata. -#' -MetadataUI <- function(id) { - ns <- NS(id) - tagList( - uiOutput(ns("metadata")) - ) -} - - -#' Server module for fetching and rendering metadata -#' -#' @param id A character string that is used as the namespace for the module's -#' input and output. -#' @param indicator_input A reactive expression that returns the -#' current indicator. -#' @param data_metrics A data frame that contains the metrics data. -#' @param metadata_type A character string that specifies the type of -#' metadata to fetch. -#' @return A server-side module that fetches and renders the metadata. -#' -MetadataServer <- function(id, indicator_input, data_metrics, metadata_type) { - moduleServer(id, function(input, output, session) { - output$metadata <- renderUI({ - metadata <- data_metrics |> - get_metadata(indicator_input(), metadata_type) - - if (grepl("link", metadata_type)) { - label <- indicator_input() - metadata <- dfeshiny::external_link(href = metadata, link_text = label) - } - - # Collapse multiple newlines and limit
tags - if (is.character(metadata)) { - metadata <- gsub("\r\n|\n", "\n", metadata) # Normalize newlines - metadata <- gsub("\n{2,}", "

", metadata) # Replace multiple newlines with a single

- metadata <- gsub("\n", "", metadata) # Remove stray newlines - metadata <- HTML(metadata) - } - - metadata - }) - }) -} - - -#' UI module for displaying metadata at the LA level -#' -#' @param id A character string that is used as the namespace for -#' the module's input and output. -#' @return A UI element that displays the LA level metadata. -#' -LA_LevelMetaUI <- function(id) { - ns <- NS(id) - - div( - class = "well", - style = "overflow-y: visible;", - bslib::card( - bslib::card_body( - h3("Description:"), - MetadataUI(ns("description")), - h3("Methodology:"), - MetadataUI(ns("methodology")), - div( - # Creates a flex container where the items are centered vertically - style = "display: flex; align-items: baseline;", - h3("Last Updated:", - style = "margin-right: 1rem; margin-bottom: 0.3rem;" - ), - MetadataUI(ns("last_update")) - ), - div( - style = "display: flex; align-items: baseline;", - h3("Next Updated:", - style = "margin-right: 1rem; margin-bottom: 0.3rem;" - ), - MetadataUI(ns("next_update")) - ), - div( - style = "display: flex; align-items: baseline;", - h3("Source:", - style = "margin-right: 1rem; margin-bottom: 0.3rem;" - ), - MetadataUI(ns("source")) - ) - ) - ) - ) -} - - -#' Server module for fetching and rendering metadata at the LA level -#' -#' @param id A character string that is used as the namespace for the -#' module's input and output. -#' @param indicator_input A reactive expression that returns the -#' current indicator. -#' @param data_metrics A data frame that contains the metrics data. -#' @return A server-side module that fetches and renders the LA level metadata. -LA_LevelMetaServer <- function(id, indicator_input, data_metrics) { - moduleServer(id, function(input, output, session) { - # Pass the indicator_input reactive expression itself (without calling it) - output$description <- MetadataServer( - "description", - indicator_input, - data_metrics, - "Description" - ) - - output$methodology <- MetadataServer( - "methodology", - indicator_input, - data_metrics, - "Methodology" - ) - - output$last_update <- MetadataServer( - "last_update", - indicator_input, - data_metrics, - "Last Update" - ) - - output$next_update <- MetadataServer( - "next_update", - indicator_input, - data_metrics, - "Next Update" - ) - - output$source <- MetadataServer( - "source", - indicator_input, - data_metrics, - "Hyperlink(s)" - ) - }) -} - -# nolint end +# nolint start: object_name +# +#' UI module for displaying metadata +#' +#' @param id A character string that is used as the namespace for the module's +#' input and output. +#' @return A UI element that displays the metadata. +#' +MetadataUI <- function(id) { + ns <- NS(id) + + shinycssloaders::withSpinner( + uiOutput(ns("metadata")), + type = 7, + color = "#1d70b8", + size = 0.6, + proxy.height = "10px" + ) +} + + +#' Server module for fetching and rendering metadata +#' +#' @param id A character string that is used as the namespace for the module's +#' input and output. +#' @param indicator_input A reactive expression that returns the +#' current indicator. +#' @param data_metrics A data frame that contains the metrics data. +#' @param metadata_type A character string that specifies the type of +#' metadata to fetch. +#' @return A server-side module that fetches and renders the metadata. +#' +MetadataServer <- function(id, indicator_input, data_metrics, metadata_type) { + moduleServer(id, function(input, output, session) { + output$metadata <- renderUI({ + metadata <- data_metrics |> + get_metadata(indicator_input(), metadata_type) + + if (grepl("link", metadata_type)) { + label <- indicator_input() + metadata <- dfeshiny::external_link(href = metadata, link_text = label) + } + + # Collapse multiple newlines and limit
tags + if (is.character(metadata)) { + metadata <- gsub("\r\n|\n", "\n", metadata) # Normalize newlines + metadata <- gsub("\n{2,}", "

", metadata) # Replace multiple newlines with a single

+ metadata <- gsub("\n", "", metadata) # Remove stray newlines + metadata <- HTML(metadata) + } + + metadata + }) + }) +} + + +#' UI module for displaying metadata at the LA level +#' +#' @param id A character string that is used as the namespace for +#' the module's input and output. +#' @return A UI element that displays the LA level metadata. +#' +LA_LevelMetaUI <- function(id) { + ns <- NS(id) + + div( + class = "well", + style = "overflow-y: visible;", + bslib::card( + bslib::card_body( + h3("Description:"), + MetadataUI(ns("description")), + h3("Methodology:"), + MetadataUI(ns("methodology")), + div( + # Creates a flex container where the items are centered vertically + style = "display: flex; align-items: baseline;", + h3("Last Updated:", + style = "margin-right: 1rem; margin-bottom: 0.3rem;" + ), + MetadataUI(ns("last_update")) + ), + div( + style = "display: flex; align-items: baseline;", + h3("Next Updated:", + style = "margin-right: 1rem; margin-bottom: 0.3rem;" + ), + MetadataUI(ns("next_update")) + ), + div( + style = "display: flex; align-items: baseline;", + h3("Source:", + style = "margin-right: 1rem; margin-bottom: 0.3rem;" + ), + MetadataUI(ns("source")) + ) + ) + ) + ) +} + + +#' Server module for fetching and rendering metadata at the LA level +#' +#' @param id A character string that is used as the namespace for the +#' module's input and output. +#' @param indicator_input A reactive expression that returns the +#' current indicator. +#' @param data_metrics A data frame that contains the metrics data. +#' @return A server-side module that fetches and renders the LA level metadata. +LA_LevelMetaServer <- function(id, indicator_input, data_metrics) { + moduleServer(id, function(input, output, session) { + # Pass the indicator_input reactive expression itself (without calling it) + output$description <- MetadataServer( + "description", + indicator_input, + data_metrics, + "Description" + ) + + output$methodology <- MetadataServer( + "methodology", + indicator_input, + data_metrics, + "Methodology" + ) + + output$last_update <- MetadataServer( + "last_update", + indicator_input, + data_metrics, + "Last Update" + ) + + output$next_update <- MetadataServer( + "next_update", + indicator_input, + data_metrics, + "Next Update" + ) + + output$source <- MetadataServer( + "source", + indicator_input, + data_metrics, + "Hyperlink(s)" + ) + }) +} + +# nolint end diff --git a/server.R b/server.R index 8d85846..05aca8c 100644 --- a/server.R +++ b/server.R @@ -1,491 +1,491 @@ -# ----------------------------------------------------------------------------- -# This is the server file. -# -# Use it to create interactive elements like tables, charts and text for your -# app. -# -# Anything you create in the server file won't appear in your app until you call -# it in the UI file. This server script gives examples of plots and value boxes -# -# There are many other elements you can add in too, and you can play around with -# their reactivity. The "outputs" section of the shiny cheatsheet has a few -# examples of render calls you can use: -# https://shiny.rstudio.com/images/shiny-cheatsheet.pdf -# -# Find out more about building applications with Shiny here: -# -# http://shiny.rstudio.com/ -# -# ----------------------------------------------------------------------------- -server <- function(input, output, session) { - # Bookmarking =============================================================== - # This uses bookmarking to store input choices in the url. - # All inputs are excluded by default, and inputs can be added explicitly - # in the included_inputs variable below - shiny::observe({ - # Include these inputs for bookmarking - included_inputs <- c( - "la_inputs-la_name", - "la_inputs-topic_name", - "la_inputs-indicator_name", - "navsetpillslist" - ) - - # Exclude all other inputs - excluded_inputs <- setdiff( - names(shiny::reactiveValuesToList(input)), - included_inputs - ) - - # Set the excluded inputs for bookmarking - shiny::setBookmarkExclude(excluded_inputs) - - # Validate topic and indicator consistency - valid_indicators <- bds_metrics |> - dplyr::filter(Topic == input$`la_inputs-topic_name`) |> - dplyr::pull(Measure) - - if (input$`la_inputs-indicator_name` %in% valid_indicators) { - # Trigger bookmarking if topic and indicator are consistent - session$doBookmark() - } else { - # Redirect to a default URL if there is a mismatch - default_url <- site_primary # Replace with your default URL - shiny::updateQueryString(default_url, mode = "replace") - } - }) - - shiny::onBookmarked(function(url) { - # Update the query string with the bookmark URL - shiny::updateQueryString(url, mode = "replace") - }) - - - # Dynamically changes window title to be LAIT - page - LA - indicator - # (Selected by user) - shiny::observe({ - if (input$navsetpillslist %in% c("LA Level", "Regional Level")) { - shinytitle::change_window_title( - session, - paste0( - site_title, " - ", - input$navsetpillslist, ": ", - la_app_inputs$la(), ", ", - la_app_inputs$indicator() - ) - ) - } else { - shinytitle::change_window_title( - session, - paste0( - site_title, " - ", - input$navsetpillslist - ) - ) - } - }) - - # Cookies logic ============================================================= - output$cookie_status <- dfeshiny::cookies_banner_server( - "cookie-banner", - input_cookies = shiny::reactive(input$cookies), - parent_session = session, - google_analytics_key = google_analytics_key, - cookies_link_panel = "cookies_panel_ui" - ) - - dfeshiny::cookies_panel_server( - id = "cookie-panel", - input_cookies = shiny::reactive(input$cookies), - google_analytics_key = google_analytics_key - ) - - # =========================================================================== - # Start of LAIT - # =========================================================================== - - # reactiveValues object to store shared input values across pages - shared_page_inputs <- reactiveValues( - la = NULL, - topic = NULL, - indicator = NULL - ) - - # =========================================================================== - # LA Level Page - # =========================================================================== - # User Inputs =============================================================== - la_app_inputs <- appInputsServer("la_inputs", shared_page_inputs) - - # Page header - PageHeaderServer("la_header", la_app_inputs, "Local Authority View") - - # LA level tables =========================================================== - # Main table - la_main_tbl <- LA_LevelTableServer( - "la_table", - la_app_inputs, - bds_metrics, - stat_n_la - ) - - # Stats table - LA_StatsTableServer( - "la_stats", - la_app_inputs, - bds_metrics, - stat_n_la - ) - - # LA level charts =========================================================== - # LA line chart - la_linechart <- LA_LineChartServer( - "la_line_chart", - la_app_inputs, - bds_metrics, - stat_n_la, - covid_affected_indicators - ) - - # LA bar chart - la_barchart <- LA_BarChartServer( - "la_bar_chart", - la_app_inputs, - bds_metrics, - stat_n_la, - covid_affected_indicators - ) - - # LA Metadata =============================================================== - LA_LevelMetaServer( - "la_meta", - la_app_inputs$indicator, - metrics_clean - ) - - # Export values for use in UI tests - shiny::exportTestValues( - la_main_tbl = la_main_tbl(), - la_linechart = la_linechart(), - la_barchart = la_barchart() - ) - - - # =========================================================================== - # Regional Level Page - # =========================================================================== - # User Inputs =============================================================== - region_app_inputs <- appInputsServer("region_inputs", shared_page_inputs) - - # Header - PageHeaderServer("region_header", region_app_inputs, "Regional View") - - # Region tables ============================================================= - # Region LA table ----------------------------------------------------------- - RegionLA_TableServer( - "region_tables", - region_app_inputs, - bds_metrics, - stat_n_geog - ) - - # Region table -------------------------------------------------------------- - Region_TableServer( - "region_tables", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds - ) - - # Region stats table -------------------------------------------------------- - Region_StatsTableServer( - "region_stats_mod", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds - ) - - # Region charts ============================================================= - # Shared inputs for Region multi-choice charts - region_shared_inputs <- reactiveValues( - chart_line_input = NULL, - chart_bar_input = NULL - ) - - # Region focus line chart --------------------------------------------------- - Region_FocusLineChartServer( - "region_focus_line", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds, - covid_affected_indicators - ) - - # Region multi-choice line chart -------------------------------------------- - Region_MultiLineChartServer( - "region_multi_line", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds, - region_shared_inputs, - covid_affected_indicators - ) - - # Region focus bar chart --------------------------------------------------- - Region_FocusBarChartServer( - "region_focus_bar", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds, - covid_affected_indicators - ) - - # Region multi-choice bar chart --------------------------------------------- - Region_MultiBarChartServer( - "region_multi_bar", - region_app_inputs, - bds_metrics, - stat_n_geog, - region_names_bds, - region_shared_inputs, - covid_affected_indicators - ) - - # Region Metadata =========================================================== - LA_LevelMetaServer( - "region_meta", - region_app_inputs$indicator, - metrics_clean - ) - - # =========================================================================== - # Statistical Neighbour Level Page - # =========================================================================== - # User Inputs =============================================================== - stat_n_app_inputs <- appInputsServer("stat_n_inputs", shared_page_inputs) - - # Header - PageHeaderServer("stat_n_header", stat_n_app_inputs, "Statistical Neighbour View") - - # Statistical Neighbour tables ============================================== - # LA statistical neighbours table ------------------------------------------- - StatN_LASNsTableServer( - "stat_n_tables", - stat_n_app_inputs, - bds_metrics, - stat_n_la - ) - - # LA geographic comparison table -------------------------------------------- - StatN_GeogCompTableServer( - "stat_n_tables", - stat_n_app_inputs, - bds_metrics, - stat_n_la - ) - - # Statistics Table ---------------------------------------------------------- - StatN_StatsTableServer( - "stat_n_stats_mod", - stat_n_app_inputs, - bds_metrics, - stat_n_la, - la_names_bds - ) - - # Statistical Neighbour charts ============================================== - # Shared inputs for Statistical Neighbour multi-choice charts - stat_n_shared_inputs <- reactiveValues( - chart_line_input = NULL, - chart_bar_input = NULL - ) - - # Focus line chart ---------------------------------------------------------- - StatN_FocusLineChartServer( - "stat_n_focus_line", - stat_n_app_inputs, - bds_metrics, - stat_n_la, - covid_affected_indicators - ) - - # Multi-choice line chart --------------------------------------------------- - StatN_MultiLineChartServer( - "stat_n_multi_line", - stat_n_app_inputs, - bds_metrics, - stat_n_la, - stat_n_shared_inputs, - covid_affected_indicators - ) - - # Focus bar chart ----------------------------------------------------------- - StatN_FocusBarChartServer( - "stat_n_focus_bar", - stat_n_app_inputs, - bds_metrics, - stat_n_la, - covid_affected_indicators - ) - - # Multi-choice bar chart ---------------------------------------------------- - StatN_MultiBarChartServer( - "stat_n_multi_bar", - stat_n_app_inputs, - bds_metrics, - stat_n_la, - stat_n_shared_inputs, - covid_affected_indicators - ) - - # Statistical Neighbour Metadata ============================================ - LA_LevelMetaServer( - "stat_n_meta", - stat_n_app_inputs$indicator, - metrics_clean - ) - - # =========================================================================== - # All LA Level Page - # =========================================================================== - # User Inputs =============================================================== - all_la_app_inputs <- appInputsServer("all_la_inputs", shared_page_inputs) - - # Header - PageHeaderServer("all_la_header", all_la_app_inputs, "All LA View") - - # All LA tables ============================================================= - # LA and Region table ------------------------------------------------------- - AllLA_TableServer( - "all_la_table", - all_la_app_inputs, - bds_metrics, - la_names_bds - ) - - # All LA Metadata =========================================================== - LA_LevelMetaServer( - "all_la_meta", - all_la_app_inputs$indicator, - metrics_clean - ) - - # User guide ================================================================ - InternalLinkServer( - "la_level_link", - "LA Level", - session - ) - - - # =========================================================================== - # Create Your Own Page - # =========================================================================== - # User Inputs =============================================================== - # Create own main inputs ---------------------------------------------------- - create_inputs <- Create_MainInputsServer("create_inputs", bds_metrics) - - # Year range input ---------------------------------------------------------- - year_input <- YearRangeServer( - "year_range", - bds_metrics, - create_inputs$indicator - ) - - # Logic to create own ======================================================= - # Geog Groupings ------------------------------------------------------------ - geog_groups <- GroupingInputServer( - "geog_groups", - create_inputs, - la_names_bds, - region_names_bds, - stat_n_geog, - stat_n_la - ) - - # Staging Table ============================================================= - # Filtering BDS for staging data -------------------------------------------- - staging_bds <- StagingBDSServer( - "staging_bds", - create_inputs, - geog_groups, - year_input, - bds_metrics - ) - - # Build staging data -------------------------------------------------------- - staging_data <- StagingDataServer( - "staging_data", - create_inputs, - staging_bds, - region_names_bds, - la_names_bds, - stat_n_la - ) - - # Output staging table ------------------------------------------------------ - StagingTableServer( - "staging_table", - create_inputs, - region_names_bds, - la_names_bds, - stat_n_la, - geog_groups, - year_input, - bds_metrics - ) - - # Query Table =============================================================== - # Building query data ------------------------------------------------------- - query_data <- QueryDataServer( - "query_data", - create_inputs, - geog_groups, - year_input, - staging_data - ) - - # Output query table -------------------------------------------------------- - query_table <- QueryTableServer( - "query_table", - query_data - ) - - # Create Own Table ========================================================== - CreateOwnTableServer( - "create_own_table", - query_table, - bds_metrics - ) - - # Create Own Charts ========================================================= - # Line chart ---------------------------------------------------------------- - CreateOwnLineChartServer( - "create_own_line", - query_table, - bds_metrics, - covid_affected_indicators - ) - - # Bar chart ----------------------------------------------------------------- - CreateOwnBarChartServer( - "create_own_bar", - query_table, - bds_metrics, - covid_affected_indicators - ) - - # Extras ==================================================================== - # Copy-to-clipboard pop-up notification - CopyToClipboardPopUpServer("copy-to-clipboard") - - # Stop app ================================================================== - session$onSessionEnded(function() { - shiny::stopApp() - }) -} +# ----------------------------------------------------------------------------- +# This is the server file. +# +# Use it to create interactive elements like tables, charts and text for your +# app. +# +# Anything you create in the server file won't appear in your app until you call +# it in the UI file. This server script gives examples of plots and value boxes +# +# There are many other elements you can add in too, and you can play around with +# their reactivity. The "outputs" section of the shiny cheatsheet has a few +# examples of render calls you can use: +# https://shiny.rstudio.com/images/shiny-cheatsheet.pdf +# +# Find out more about building applications with Shiny here: +# +# http://shiny.rstudio.com/ +# +# ----------------------------------------------------------------------------- +server <- function(input, output, session) { + # Bookmarking =============================================================== + # This uses bookmarking to store input choices in the url. + # All inputs are excluded by default, and inputs can be added explicitly + # in the included_inputs variable below + shiny::observe({ + # Include these inputs for bookmarking + included_inputs <- c( + "la_inputs-la_name", + "la_inputs-topic_name", + "la_inputs-indicator_name", + "navsetpillslist" + ) + + # Exclude all other inputs + excluded_inputs <- setdiff( + names(shiny::reactiveValuesToList(input)), + included_inputs + ) + + # Set the excluded inputs for bookmarking + shiny::setBookmarkExclude(excluded_inputs) + + # Validate topic and indicator consistency + valid_indicators <- bds_metrics |> + dplyr::filter(Topic == input$`la_inputs-topic_name`) |> + dplyr::pull(Measure) + + if (input$`la_inputs-indicator_name` %in% valid_indicators) { + # Trigger bookmarking if topic and indicator are consistent + session$doBookmark() + } else { + # Redirect to a default URL if there is a mismatch + default_url <- site_primary # Replace with your default URL + shiny::updateQueryString(default_url, mode = "replace") + } + }) + + shiny::onBookmarked(function(url) { + # Update the query string with the bookmark URL + shiny::updateQueryString(url, mode = "replace") + }) + + # Dynamically changes window title to be LAIT - page - LA - indicator + # (Selected by user) + shiny::observe({ + if (input$navsetpillslist %in% c("LA Level", "Regional Level")) { + shinytitle::change_window_title( + session, + paste0( + site_title, " - ", + input$navsetpillslist, ": ", + la_app_inputs$la(), ", ", + la_app_inputs$indicator() + ) + ) + } else { + shinytitle::change_window_title( + session, + paste0( + site_title, " - ", + input$navsetpillslist + ) + ) + } + }) + + # Cookies logic ============================================================= + output$cookie_status <- dfeshiny::cookies_banner_server( + "cookie-banner", + input_cookies = shiny::reactive(input$cookies), + parent_session = session, + google_analytics_key = google_analytics_key, + cookies_link_panel = "cookies_panel_ui" + ) + + dfeshiny::cookies_panel_server( + id = "cookie-panel", + input_cookies = shiny::reactive(input$cookies), + google_analytics_key = google_analytics_key + ) + + # =========================================================================== + # Start of LAIT + # =========================================================================== + + # reactiveValues object to store shared input values across pages + shared_page_inputs <- reactiveValues( + la = NULL, + topic = NULL, + indicator = NULL + ) + + # =========================================================================== + # LA Level Page + # =========================================================================== + # User Inputs =============================================================== + la_app_inputs <- appInputsServer("la_inputs", shared_page_inputs) + + # Page header + PageHeaderServer("la_header", la_app_inputs, "Local Authority View") + + # LA level tables =========================================================== + # Main table + la_main_tbl <- LA_LevelTableServer( + "la_table", + la_app_inputs, + bds_metrics, + stat_n_la + ) + + # Stats table + LA_StatsTableServer( + "la_stats", + la_app_inputs, + bds_metrics, + stat_n_la + ) + + # LA level charts =========================================================== + # LA line chart + la_linechart <- LA_LineChartServer( + "la_line_chart", + la_app_inputs, + bds_metrics, + stat_n_la, + covid_affected_indicators + ) + + # LA bar chart + la_barchart <- LA_BarChartServer( + "la_bar_chart", + la_app_inputs, + bds_metrics, + stat_n_la, + covid_affected_indicators + ) + + # LA Metadata =============================================================== + LA_LevelMetaServer( + "la_meta", + la_app_inputs$indicator, + metrics_clean + ) + + # Export values for use in UI tests + shiny::exportTestValues( + la_main_tbl = la_main_tbl(), + la_linechart = la_linechart(), + la_barchart = la_barchart() + ) + + + # =========================================================================== + # Regional Level Page + # =========================================================================== + # User Inputs =============================================================== + region_app_inputs <- appInputsServer("region_inputs", shared_page_inputs) + + # Header + PageHeaderServer("region_header", region_app_inputs, "Regional View") + + # Region tables ============================================================= + # Region LA table ----------------------------------------------------------- + RegionLA_TableServer( + "region_tables", + region_app_inputs, + bds_metrics, + stat_n_geog + ) + + # Region table -------------------------------------------------------------- + Region_TableServer( + "region_tables", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds + ) + + # Region stats table -------------------------------------------------------- + Region_StatsTableServer( + "region_stats_mod", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds + ) + + # Region charts ============================================================= + # Shared inputs for Region multi-choice charts + region_shared_inputs <- reactiveValues( + chart_line_input = NULL, + chart_bar_input = NULL + ) + + # Region focus line chart --------------------------------------------------- + Region_FocusLineChartServer( + "region_focus_line", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds, + covid_affected_indicators + ) + + # Region multi-choice line chart -------------------------------------------- + Region_MultiLineChartServer( + "region_multi_line", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds, + region_shared_inputs, + covid_affected_indicators + ) + + # Region focus bar chart --------------------------------------------------- + Region_FocusBarChartServer( + "region_focus_bar", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds, + covid_affected_indicators + ) + + # Region multi-choice bar chart --------------------------------------------- + Region_MultiBarChartServer( + "region_multi_bar", + region_app_inputs, + bds_metrics, + stat_n_geog, + region_names_bds, + region_shared_inputs, + covid_affected_indicators + ) + + # Region Metadata =========================================================== + LA_LevelMetaServer( + "region_meta", + region_app_inputs$indicator, + metrics_clean + ) + + # =========================================================================== + # Statistical Neighbour Level Page + # =========================================================================== + # User Inputs =============================================================== + stat_n_app_inputs <- appInputsServer("stat_n_inputs", shared_page_inputs) + + # Header + PageHeaderServer("stat_n_header", stat_n_app_inputs, "Statistical Neighbour View") + + # Statistical Neighbour tables ============================================== + # LA statistical neighbours table ------------------------------------------- + StatN_LASNsTableServer( + "stat_n_tables", + stat_n_app_inputs, + bds_metrics, + stat_n_la + ) + + # LA geographic comparison table -------------------------------------------- + StatN_GeogCompTableServer( + "stat_n_tables", + stat_n_app_inputs, + bds_metrics, + stat_n_la + ) + + # Statistics Table ---------------------------------------------------------- + StatN_StatsTableServer( + "stat_n_stats_mod", + stat_n_app_inputs, + bds_metrics, + stat_n_la, + la_names_bds + ) + + # Statistical Neighbour charts ============================================== + # Shared inputs for Statistical Neighbour multi-choice charts + stat_n_shared_inputs <- reactiveValues( + chart_line_input = NULL, + chart_bar_input = NULL + ) + + # Focus line chart ---------------------------------------------------------- + StatN_FocusLineChartServer( + "stat_n_focus_line", + stat_n_app_inputs, + bds_metrics, + stat_n_la, + covid_affected_indicators + ) + + # Multi-choice line chart --------------------------------------------------- + StatN_MultiLineChartServer( + "stat_n_multi_line", + stat_n_app_inputs, + bds_metrics, + stat_n_la, + stat_n_shared_inputs, + covid_affected_indicators + ) + + # Focus bar chart ----------------------------------------------------------- + StatN_FocusBarChartServer( + "stat_n_focus_bar", + stat_n_app_inputs, + bds_metrics, + stat_n_la, + covid_affected_indicators + ) + + # Multi-choice bar chart ---------------------------------------------------- + StatN_MultiBarChartServer( + "stat_n_multi_bar", + stat_n_app_inputs, + bds_metrics, + stat_n_la, + stat_n_shared_inputs, + covid_affected_indicators + ) + + # Statistical Neighbour Metadata ============================================ + LA_LevelMetaServer( + "stat_n_meta", + stat_n_app_inputs$indicator, + metrics_clean + ) + + # =========================================================================== + # All LA Level Page + # =========================================================================== + # User Inputs =============================================================== + all_la_app_inputs <- appInputsServer("all_la_inputs", shared_page_inputs) + + # Header + PageHeaderServer("all_la_header", all_la_app_inputs, "All LA View") + + # All LA tables ============================================================= + # LA and Region table ------------------------------------------------------- + AllLA_TableServer( + "all_la_table", + all_la_app_inputs, + bds_metrics, + la_names_bds + ) + + # All LA Metadata =========================================================== + LA_LevelMetaServer( + "all_la_meta", + all_la_app_inputs$indicator, + metrics_clean + ) + + # User guide ================================================================ + InternalLinkServer( + "la_level_link", + "LA Level", + session + ) + + + # =========================================================================== + # Create Your Own Page + # =========================================================================== + # User Inputs =============================================================== + # Create own main inputs ---------------------------------------------------- + create_inputs <- Create_MainInputsServer("create_inputs", bds_metrics) + + # Year range input ---------------------------------------------------------- + year_input <- YearRangeServer( + "year_range", + bds_metrics, + create_inputs$indicator, + create_inputs$clear_selections + ) + + # Logic to create own ======================================================= + # Geog Groupings ------------------------------------------------------------ + geog_groups <- GroupingInputServer( + "geog_groups", + create_inputs, + la_names_bds, + region_names_bds, + stat_n_geog, + stat_n_la + ) + + # Staging Table ============================================================= + # Filtering BDS for staging data -------------------------------------------- + staging_bds <- StagingBDSServer( + "staging_bds", + create_inputs, + geog_groups, + year_input, + bds_metrics + ) + + # Build staging data -------------------------------------------------------- + staging_data <- StagingDataServer( + "staging_data", + create_inputs, + staging_bds, + region_names_bds, + la_names_bds, + stat_n_la + ) + + # Output staging table ------------------------------------------------------ + StagingTableServer( + "staging_table", + create_inputs, + region_names_bds, + la_names_bds, + stat_n_la, + geog_groups, + year_input, + bds_metrics + ) + + # Query Table =============================================================== + # Building query data ------------------------------------------------------- + query_data <- QueryDataServer( + "query_data", + create_inputs, + geog_groups, + year_input, + staging_data + ) + + # Output query table -------------------------------------------------------- + query_table <- QueryTableServer( + "query_table", + query_data + ) + + # Create Own Table ========================================================== + CreateOwnTableServer( + "create_own_table", + query_table, + bds_metrics + ) + + # Create Own Charts ========================================================= + # Line chart ---------------------------------------------------------------- + CreateOwnLineChartServer( + "create_own_line", + query_table, + bds_metrics, + covid_affected_indicators + ) + + # Bar chart ----------------------------------------------------------------- + CreateOwnBarChartServer( + "create_own_bar", + query_table, + bds_metrics, + covid_affected_indicators + ) + + # Extras ==================================================================== + # Copy-to-clipboard pop-up notification + CopyToClipboardPopUpServer("copy-to-clipboard") + + # Stop app ================================================================== + session$onSessionEnded(function() { + shiny::stopApp() + }) +} diff --git a/ui.R b/ui.R index 312adbc..b49740f 100644 --- a/ui.R +++ b/ui.R @@ -244,12 +244,12 @@ ui <- function(input, output, session) { Create_MainInputsUI("create_inputs")["LA grouping"], Create_MainInputsUI("create_inputs")["Other grouping"], YearRangeUI("year_range"), - Create_MainInputsUI("create_inputs")["Add selection"] + Create_MainInputsUI("create_inputs")["Clear all current selections"] ) ), # Tables ============================================================== - # Staging table ------------------------------------------------------- + # Staging table & Add selections btn ---------------------------------- StagingTableUI("staging_table"), # Query table --------------------------------------------------------- QueryTableUI("query_table"),