diff --git a/02_dev/la_level_page/la_dev_app.R b/02_dev/la_level_page/la_dev_app.R index 0fff532..29f6a7b 100644 --- a/02_dev/la_level_page/la_dev_app.R +++ b/02_dev/la_level_page/la_dev_app.R @@ -432,6 +432,8 @@ server_dev <- function(input, output, session) { # Build plot la_line_chart <- la_long() |> + # Set geog orders so selected LA is on top of plot + reorder_la_regions(reverse = TRUE) |> ggplot2::ggplot() + ggiraph::geom_line_interactive( ggplot2::aes( @@ -460,8 +462,9 @@ server_dev <- function(input, output, session) { format_axes(la_long()) + set_plot_colours(la_long(), focus_group = input$la_input) + set_plot_labs(filtered_bds$data) + - custom_theme() - + custom_theme() + + # Revert order of the legend so goes from right to left + ggplot2::guides(color = ggplot2::guide_legend(reverse = TRUE)) # Creating vertical geoms to make vertical hover tooltip vertical_hover <- lapply( diff --git a/02_dev/la_level_page/la_page_features_workshop.R b/02_dev/la_level_page/la_page_features_workshop.R index 8208201..5697c5d 100644 --- a/02_dev/la_level_page/la_page_features_workshop.R +++ b/02_dev/la_level_page/la_page_features_workshop.R @@ -264,7 +264,7 @@ dfe_reactable( `Latest National Rank` = reactable::colDef( header = add_tooltip_to_reactcol( "Latest National Rank", - "Rank 1 is always the best performer" + "Rank 1 is always best/top" ) ), Polarity = reactable::colDef(show = FALSE) @@ -281,6 +281,8 @@ covid_plot_line <- calculate_covid_plot(la_long, covid_affected, "line") # Plot la_line_chart <- la_long |> + # Set geog orders so selected LA is on top of plot + reorder_la_regions(reverse = TRUE) |> ggplot2::ggplot() + # Only show point data where line won't appear (NAs) ggplot2::geom_point( @@ -309,7 +311,7 @@ la_line_chart <- la_long |> # Add COVID plot if indicator affected add_covid_elements(covid_plot_line) + format_axes(la_long) + - set_plot_colours(la_long, focus_group = selected_la) + + set_plot_colours(la_long, "colour", focus_group = selected_la) + set_plot_labs(filtered_bds) + custom_theme() diff --git a/02_dev/stat_n_level_page/stat_neigh_dev_app.R b/02_dev/stat_n_level_page/stat_neigh_dev_app.R index cb16cba..bb33ecc 100644 --- a/02_dev/stat_n_level_page/stat_neigh_dev_app.R +++ b/02_dev/stat_n_level_page/stat_neigh_dev_app.R @@ -402,7 +402,7 @@ server_dev <- function(input, output, session) { `Latest National Rank` = reactable::colDef( header = add_tooltip_to_reactcol( "Latest National Rank", - "Rank 1 is always the best performer" + "Rank 1 is always best/top" ) ), Polarity = reactable::colDef(show = FALSE) diff --git a/R/fn_plotting.R b/R/fn_plotting.R index f04cd44..ab493c3 100644 --- a/R/fn_plotting.R +++ b/R/fn_plotting.R @@ -51,14 +51,14 @@ get_yaxis_title <- function(data_full) { #' This function retrieves the title for the X-axis based on the `Year_Type` #' column of the provided dataset. If there is only one unique value for #' `Year_Type`, the title will be formatted with line breaks. If there are -#' multiple unique values, a generic "Plain Years" label is used. +#' multiple unique values, a generic "Mixed Year Types" label is used. #' #' @param data_full A data frame containing the `Year_Type` column, which will #' be used to determine the X-axis title. #' #' @return A character string representing the X-axis title. This can either #' be the value of `Year_Type` formatted with line breaks or the string -#' "Plain Years" if there are multiple unique values. +#' "Mixed Year Types" if there are multiple unique values. #' #' @details The function uses `pull_uniques` to extract unique values from #' the `Year_Type` column. If a single unique value is found, it formats @@ -79,7 +79,7 @@ get_xaxis_title <- function(data_full) { if (length(x_axis_title) == 1) { add_line_breaks(x_axis_title) } else { - "Plain Years" + "Mixed Year Types" } } @@ -934,10 +934,11 @@ generic_ggiraph_options <- function(...) { #' reordered_data <- reorder_la_regions(chart_data, factor_order) #' print(reordered_data) #' -reorder_la_regions <- function(chart_data, factor_order, ...) { +reorder_la_regions <- function(chart_data, factor_order = NULL, reverse = FALSE, ...) { chart_data |> dplyr::mutate( - `LA and Regions` = forcats::fct_relevel(`LA and Regions`, factor_order, ...) + `LA and Regions` = forcats::fct_relevel(`LA and Regions`, factor_order, ...), + `LA and Regions` = if (reverse) forcats::fct_rev(`LA and Regions`) else `LA and Regions` ) |> dplyr::arrange(`LA and Regions`) } diff --git a/R/lait_modules/mod_create_own_table.R b/R/lait_modules/mod_create_own_table.R index 5856ae8..a8f5bc7 100644 --- a/R/lait_modules/mod_create_own_table.R +++ b/R/lait_modules/mod_create_own_table.R @@ -292,7 +292,7 @@ StagingTableServer <- function(id, format_num_reactable_cols( staging_data(), get_indicator_dps(staging_bds()), - num_exclude = c("LA Number", "Measure") + num_exclude = c("LA Number", "Topic", "Measure") ), list( set_custom_default_col_widths( diff --git a/R/lait_modules/mod_la_lvl_charts.R b/R/lait_modules/mod_la_lvl_charts.R index cdd610b..e897969 100644 --- a/R/lait_modules/mod_la_lvl_charts.R +++ b/R/lait_modules/mod_la_lvl_charts.R @@ -102,6 +102,8 @@ LA_LineChartServer <- function(id, # Build plot la_long() |> + # Set geog orders so selected LA is on top of plot + reorder_la_regions(reverse = TRUE) |> ggplot2::ggplot() + ggiraph::geom_line_interactive( ggplot2::aes( @@ -130,7 +132,9 @@ LA_LineChartServer <- function(id, format_axes(la_long()) + set_plot_colours(la_long(), "colour", app_inputs$la()) + set_plot_labs(filtered_bds()) + - custom_theme() + custom_theme() + + # Revert order of the legend so goes from right to left + ggplot2::guides(color = ggplot2::guide_legend(reverse = TRUE)) }) # Build interactive line chart diff --git a/R/lait_modules/mod_la_lvl_metadata.R b/R/lait_modules/mod_la_lvl_metadata.R index e3934d2..fd890fa 100644 --- a/R/lait_modules/mod_la_lvl_metadata.R +++ b/R/lait_modules/mod_la_lvl_metadata.R @@ -1,145 +1,147 @@ -# 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) - } - - # Handle metadata that is text by converting newlines to
tags - if (is.character(metadata)) { - metadata <- gsub("\r\n|\n", "
", metadata) - 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) + 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 diff --git a/R/lait_modules/mod_la_lvl_table.R b/R/lait_modules/mod_la_lvl_table.R index 574c463..bc98a6a 100644 --- a/R/lait_modules/mod_la_lvl_table.R +++ b/R/lait_modules/mod_la_lvl_table.R @@ -363,7 +363,7 @@ LA_StatsTableServer <- function(id, app_inputs, bds_metrics, stat_n_la) { `Latest National Rank` = reactable::colDef( header = add_tooltip_to_reactcol( "Latest National Rank", - "Rank 1 is always the best performer" + "Rank 1 is always best/top" ) ), Polarity = reactable::colDef(show = FALSE) diff --git a/R/lait_modules/mod_stat_n_table.R b/R/lait_modules/mod_stat_n_table.R index 4c21279..3a9625b 100644 --- a/R/lait_modules/mod_stat_n_table.R +++ b/R/lait_modules/mod_stat_n_table.R @@ -278,7 +278,7 @@ StatN_TablesUI <- function(id) { ), br(), # Statistical Neighbour Statistics Table ------------------------------ - StatN_StatsTableUI("stat_n_stats_mod"), + StatN_StatsTableUI("stat_n_stats_mod") ), bslib::nav_panel( "Download", @@ -682,7 +682,7 @@ StatN_StatsTableServer <- function(id, `Latest National Rank` = reactable::colDef( header = add_tooltip_to_reactcol( "Latest National Rank", - "Rank 1 is always the best performer" + "Rank 1 is always best/top" ) ), Polarity = reactable::colDef(show = FALSE) diff --git a/server.R b/server.R index 38554af..a52c144 100644 --- a/server.R +++ b/server.R @@ -19,30 +19,32 @@ # ----------------------------------------------------------------------------- server <- function(input, output, session) { # Bookmarking =============================================================== - # The template uses bookmarking to store input choices in the url. You can - # exclude specific inputs (for example extra info created for a datatable - # or plotly chart) using the list below, but it will need updating to match - # any entries in your own dashboard's bookmarking url that you don't want - # including. - shiny::setBookmarkExclude(c( - "cookies", "link_to_app_content_tab", - "tabBenchmark_rows_current", "tabBenchmark_rows_all", - "tabBenchmark_columns_selected", "tabBenchmark_cell_clicked", - "tabBenchmark_cells_selected", "tabBenchmark_search", - "tabBenchmark_rows_selected", "tabBenchmark_row_last_clicked", - "tabBenchmark_state", - "plotly_relayout-A", - "plotly_click-A", "plotly_hover-A", "plotly_afterplot-A", - ".clientValue-default-plotlyCrosstalkOpts" - )) - + # 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({ - # Trigger this observer every time an input changes - shiny::reactiveValuesToList(input) + # Include these inputs + included_inputs <- c( + "la_inputs-la_name", + "la_inputs-topic_name", + "navsetpillslist" + ) + + # Exclude all inputs except the specified ones + excluded_inputs <- setdiff( + names(shiny::reactiveValuesToList(input)), + included_inputs + ) + + # Set the excluded inputs for bookmarking + shiny::setBookmarkExclude(excluded_inputs) + + # Trigger bookmarking whenever relevant inputs change session$doBookmark() }) shiny::onBookmarked(function(url) { + # Update the query string with the bookmark URL shiny::updateQueryString(url) }) diff --git a/tests/testthat/_snaps/windows-4.4/UI-mod_la_lvl_table/la-charts-la_line_chart.png b/tests/testthat/_snaps/windows-4.4/UI-mod_la_lvl_table/la-charts-la_line_chart.png index a5eb05b..5b93213 100644 Binary files a/tests/testthat/_snaps/windows-4.4/UI-mod_la_lvl_table/la-charts-la_line_chart.png and b/tests/testthat/_snaps/windows-4.4/UI-mod_la_lvl_table/la-charts-la_line_chart.png differ diff --git a/ui.R b/ui.R index 635a0b5..312adbc 100644 --- a/ui.R +++ b/ui.R @@ -186,8 +186,6 @@ ui <- function(input, output, session) { # Statistical Neighbour tables ======================================== StatN_TablesUI("stat_n_tables"), - # Statistical Neighbour Statistics Table ---------------------------- - StatN_StatsTableUI("stat_n_stats_table"), # Statistical Neighbour charts ======================================== div(