diff --git a/R/dashboard_modules/02-local_authority_district.R b/R/dashboard_modules/02-local_authority_district.R index 207af77..5d62e2a 100644 --- a/R/dashboard_modules/02-local_authority_district.R +++ b/R/dashboard_modules/02-local_authority_district.R @@ -64,12 +64,14 @@ lad_ui <- function(id) { selectizeInput( inputId = NS(id, "delivery_lad"), label = "Search for a delivery LAD", - choices = NULL + choices = NULL, + options = list(dropdownParent = "body") # force dropdown menu to be in front of other objects ), selectizeInput( inputId = NS(id, "learner_home_lad"), label = "Search for a learner home LAD", - choices = NULL + choices = NULL, + options = list(dropdownParent = "body") # force dropdown menu to be in front of other objects ) ) ), @@ -86,11 +88,11 @@ lad_ui <- function(id) { width = "15rem", # Minimum width for each input box before wrapping div( h2("Delivery map"), - leafletOutput(NS(id, "delivery_lad_map")) + leafletOutput(NS(id, "delivery_lad_map"), height = 600) ), div( h2("Learner home map"), - leafletOutput(NS(id, "learner_home_lad_map")) + leafletOutput(NS(id, "learner_home_lad_map"), height = 600) ) ) ), @@ -156,6 +158,22 @@ lad_server <- function(id) { } }) + # User map selection ------------------------------------------------------ + # While the maps themselves are defined elsewhere, if a user selects an LAD from a map, we capture the value here + # and then pass into the dropdown as if the user had selected that LAD from the dropdown itself + # all of the flushing of other values happens automatically when the calculations are rerun + # + # The 'id' that we pull here pulls from what we set as the 'layerId' in the map function + observeEvent(input$delivery_lad_map_shape_click, { + map_selected_delivery_lad <- input$delivery_lad_map_shape_click + updateSelectizeInput(session, "delivery_lad", selected = map_selected_delivery_lad$id) + }) + + observeEvent(input$learner_home_lad_map_shape_click, { + map_selected_learner_home_lad <- input$learner_home_lad_map_shape_click + updateSelectizeInput(session, "learner_home_lad", selected = map_selected_learner_home_lad$id) + }) + # Provider selection ====================================================== # Create the data used for the table on the left you can select providers from prov_selection_table <- reactive({ @@ -221,7 +239,9 @@ lad_server <- function(id) { delivery_lad, summarise, `Number of apprenticeships` = sum(!!sym(firstlow(input$measure)), na.rm = TRUE) - ) + ) %>% + filter(`Number of apprenticeships` != 0) + return(delivery_lad_table) }) @@ -249,7 +269,8 @@ lad_server <- function(id) { learner_home_lad, summarise, `Number of apprenticeships` = sum(!!sym(firstlow(input$measure)), na.rm = TRUE) - ) + ) %>% + filter(`Number of apprenticeships` != 0) return(learner_home_lad_table) }) @@ -260,10 +281,14 @@ lad_server <- function(id) { }) output$learner_home_lad_table <- renderReactable({ + validate(need(nrow(learner_home_lad_table()) > 0, paste0("No ", input$measure, " for these selections."))) + dfe_reactable(learner_home_lad_table()) }) output$delivery_lad_table <- renderReactable({ + validate(need(nrow(delivery_lad_table()) > 0, paste0("No ", input$measure, " for these selections."))) + dfe_reactable(delivery_lad_table()) }) @@ -296,13 +321,26 @@ lad_server <- function(id) { }) # Create the maps themselves ---------------------------------------------- - # dfe_map is defined in R/helper_functions.R + # dfe_lad_map is defined in R/helper_functions.R output$delivery_lad_map <- renderLeaflet({ - dfe_map(delivery_map_data(), input$measure) + validate(need(nrow(delivery_lad_table()) > 0, paste0("No ", input$measure, " for these selections."))) + + dfe_lad_map(delivery_map_data(), input$measure, NS(id, "delivery_lad")) }) output$learner_home_lad_map <- renderLeaflet({ - dfe_map(learner_home_map_data(), input$measure) + validate(need(nrow(learner_home_lad_table()) > 0, paste0("No ", input$measure, " for these selections."))) + + dfe_lad_map(learner_home_map_data(), input$measure, NS(id, "learner_home_lad")) + }) + + # Watch for the reset buttons and clear selection if pressed + observeEvent(input$delivery_lad_reset, { + updateSelectizeInput(session, "delivery_lad", selected = "") + }) + + observeEvent(input$learner_home_lad_reset, { + updateSelectizeInput(session, "learner_home_lad", selected = "") }) # Data download =========================================================== diff --git a/R/helper_functions.R b/R/helper_functions.R index 44616e4..ae72364 100644 --- a/R/helper_functions.R +++ b/R/helper_functions.R @@ -124,11 +124,12 @@ dfe_footer <- function(links_list) { dfe_reactable <- function(data, on_click = NULL, selection = NULL, row_style = NULL, searchable = FALSE) { reactable( data, + # DfE styling highlight = TRUE, borderless = TRUE, showSortIcon = FALSE, - style = list(fontSize = "16px"), + style = list(fontSize = "16px", display = "block"), defaultColDef = colDef(headerClass = "bar-sort-header"), # Customiseable settings @@ -172,8 +173,51 @@ firstlow <- function(x) { x } +# Add a map reset button to a Leaflet map object, using some additional JavaScript +# @param leaf A Leaflet map object +# @param selectize_input_id The ID of the input you want the reset button to clear +# +# Note that if you're working inside a module, you will need to wrap the inputId in the NS function +add_map_reset_button <- function(leaf, selectize_input_id = NULL) { + leaf %>% + # Add a button into the map + addEasyButton( + easyButton( + icon = "ion-refresh", + title = "Reset View", + # When clicking the button, reset the view of the map and clear the selectizeInput + onClick = JS( + # Use of a random number ensures that shiny will always recognise every button click + # without it multiple clicks in quick succession might not be registered / recognised + sprintf( + "function(btn, map){ + map.setView(map._initialCenter, map._initialZoom); + if ('%s' !== 'null') { + Shiny.setInputValue('%s_reset', Math.random()); + } + }", + selectize_input_id, selectize_input_id + ) + ) + ) + ) %>% + # When the map loads, grab its initial centre point values + htmlwidgets::onRender( + JS( + " +function(el, x){ + var map = this; + map.whenReady(function(){ + map._initialCenter = map.getCenter(); + map._initialZoom = map.getZoom(); + }); +}" + ) + ) +} + # Create a map ================================================================ -dfe_map <- function(data, measure) { +dfe_lad_map <- function(data, measure, input_id) { # Set the color scheme and scale pal_fun <- colorNumeric( "Blues", @@ -202,6 +246,7 @@ dfe_map <- function(data, measure) { color = "black", weight = 1, fillColor = pal_fun(data[["Number of apprenticeships"]]), + fillOpacity = 1, highlightOptions = highlightOptions( weight = 5, color = "#666", @@ -214,14 +259,16 @@ dfe_map <- function(data, measure) { textsize = "15px", direction = "auto", bringToFront = TRUE - ) + ), + layerId = ~lad_name # this is what value is returned when a user clicks on a polygon ) %>% # Add a legend to the map addLegend("topright", pal = pal_fun, values = ~ data[["Number of apprenticeships"]], title = firstup(measure) - ) + ) %>% + add_map_reset_button(selectize_input_id = input_id) # add a reset button return(map) } diff --git a/manifest.json b/manifest.json index ffb4dbf..ec95049 100644 --- a/manifest.json +++ b/manifest.json @@ -5208,16 +5208,7 @@ "checksum": "522774462b837ce20ada322ac0531ead" }, ".Rprofile": { - "checksum": "33ff4c22681afdba1f7a1d2031e02d4e" - ".Rprofile": { - "checksum": "cc6536f69353490c080d00aa831c60ba" - }, - ".RDataTmp8": { - "checksum": "32471ff2313e1f4580f7dc87ea91d2a3" - }, - "data/apprenticeships_data_0.parquet": { - "checksum": "2f33fbdc88f41225932c55a6441d7404" - }, + "checksum": "3c36326b9a778eeefe49d3b08bf36291" }, "azure-pipelines.yml": { "checksum": "1dd237db3691665ae9b9b2150087ac75" @@ -5262,13 +5253,13 @@ "checksum": "f3870074cee891ae98f79ecac02f6710" }, "R/dashboard_modules/02-local_authority_district.R": { - "checksum": "9e5d98c77826a9de8548e2f4d2ce9a10" + "checksum": "0268389c68220b82eeeb27f5fda8d3d5" }, "R/dashboard_modules/03-subjects_and_standards.R": { "checksum": "1c123e63c759fd13ae461c59b82f2b4f" }, "R/dashboard_modules/04-learner_characteristics.R": { - "checksum": "46f3d470a3ea4e6b715bcfa2b28181ee" + "checksum": "54470a9762bfff8eb0ef536d99d05084" }, "R/dashboard_modules/05-national_provider_summary.R": { "checksum": "9b7612db529b8909338e5e5f83660b9f" @@ -5295,7 +5286,7 @@ "checksum": "4fb06508719a86445bed410f6640a071" }, "R/helper_functions.R": { - "checksum": "5f1369340c633bca00c3d479d466865f" + "checksum": "5403dc6edd1f198dc97aa9343ad622f5" }, "R/read_data.R": { "checksum": "ce9251d425cf9b81da032673d3096fcc" @@ -5358,7 +5349,7 @@ "checksum": "c23764dae2d73a45a55815d0327be6cb" }, "www/dfe_shiny_gov_style.css": { - "checksum": "2b76f69230c48d584b232375b3c67705" + "checksum": "d36df853777cb37265b4ce44bfdac0bb" }, "www/dfefavicon.png": { "checksum": "179db108199253ed0617024df291473b" diff --git a/www/dfe_shiny_gov_style.css b/www/dfe_shiny_gov_style.css index c02c3d0..c06f69f 100644 --- a/www/dfe_shiny_gov_style.css +++ b/www/dfe_shiny_gov_style.css @@ -351,3 +351,18 @@ html { background-color: #fd0 !important; color: black !important; } + +/* Map reset button CSS ---------------------------------------------------- */ +.leaflet-touch .leaflet-bar button:focus { + outline: 0.188rem solid rgba(0, 0, 0, 0); + color: #0b0c0c; + background-color: #fd0 !important; + box-shadow: 0 -0.125rem #fd0, 0 0.25rem #0b0c0c; +} + +.leaflet-touch .leaflet-bar button:hover { + outline: 0.188rem solid rgba(0, 0, 0, 0); + color: #0b0c0c; + background-color: #fd0 !important; + box-shadow: 0 -0.125rem #fd0, 0 0.25rem #0b0c0c; +} \ No newline at end of file