Skip to content

Commit

Permalink
Dev all la (#27)
Browse files Browse the repository at this point in the history
* Feat: Added first modules for stat neigh page, LA sns table is working in the stat neigh dev app mod. Updated current year mod to handle long and wide data

* Feat: Added stats table to stat neigh mod

* Feat: Added multi choice charts to stat neigh mod, as well as MAJOR input function that shares inputs between charts

* Feat: Adding focus bar chart to stat neigh mod and dev app mod

* Feat: Stat neigh page added to ui and server

* Fix: Missing stat neigh chart input UI, now back in

* Chore: Roxygen comments for stat neigh table mod

* Chore: Roxygen comments for stat neigh charts mod

* Styles: Setting dropdown options in multi-choice chart inputs so that the dropdowns overlay

* Fix: stat neigh metadata was pointing at region page

* Fix: LAs with no SNs not being handled correctly in stat neigh logic

* Chore: More efficient stat neigh chart input

* Chore: Trying to workout reactivity issue in stat neigh chart inputs

* Tests: Updated la charts test for new LA inputs selector name

* Chore: Stat neigh navset in ui had same id as region

* Chore: Updating logic of the dependency between chart inputs in Stat neigh plots

* Fix: Chart input dependency no longer looping in stat neigh due to delay with later

* Chore: Adding error plot to deal with no data cases (such as Cumberland having no data and no SNs)

* Chore: Changed x-axes to not overlap and edited all ggiraph widths to be 8.5 so labels fit

* Chore: No longer card within a card in Regional, some minor sorting of card layout too, more needed

* Chore: No longer card within a card in Regional, some minor sorting of card layout too, more needed

* Chore: Updated shared inputs logic in stat neigh dev app, could spend some time figuring out simplest logic

* Tests: Updated la charts screenshots

* Chore: Attempt to deal with sidebars in multi-choice charts

* Chore: Move stat neigh dev scripts into seperate folder in dev/

* Feat: Started logic for all LA table

* Tests: Updated la screenshot tests

* Feat: Added basic code logic to create all LAs LA and Region table, also updated calc_diff so set Values to NA

* Feat: All LAs now in a dev app, updated dfeshiny, new css to hide reactable headers and minor improvements

* Feat: Using chart title as table header in all LA dev app

* Feat: Setup module script for all LA and module dev app

* Feat: Working all LA module, some effort to try and improve widths of table headers, not much luck

* Feat: All LA modules added to main app

* Chore: Increasing min width of dfe reactable columns so headers fit better

* Feat: Added download tables feature in all LA dev app

* Feat: Download now has option to be csv or xlsx, how Cam suggested

* Feat: Download data moduled addedto all la mods

* Chore: Adding roxygen comments for all LA mods and download mod

* Chore: Roxygen comments for new fns and linting

* Chore: Added roxygen comments for All LA fns that filter the table ready for region or LA

* Feat: Added downloads to LA level tables

* Chore: Removing download data option from stats table LA

* Feat: Can download static ggiraph charts

* Feat: Download name appears correctly (slight lag when changing topic)

* Chore: Removed reactivity from generate_csv and renamed to be more appropriate for wide range of files

* Chore: Updated download module so download_name param pastes together inside fn

* Fix: Updating download data server modules with new download_name parameter handling

* Feat: Can save ggiraph at standalone html with full interactivity

* Feat: Now able to download line chart as html with interactivity from the app

* Feat: Added bar chart download in for LA level, also fixed reactivity issue within download due to use of reactive values

* Tests: Fixing tests for new updates to code, including donwload logic which needs to not be placed last in a server or is returned

* Fix: Trying to sort out order of sort in reactable, messy but working

* Chore: Removed custom pretty_num fn and replaced with updated dfeR pretty_num

* Chore: Updating reactable formatting fns, applied to all LA page

* Chore: Updated reactable fromatting cols for LA lvl page

* Feat: Adding new reactable formatting to region page, also playing around with card display with main and stats table

* Feat: Adding new reactable formatting to stat neigh page, also playing around with card display with main and stats table

* Fix: Adding dfeR prefix to pretty_num fn in pretty_num table

* Chore: Adding div well back to region stats table

* Chore: Updating linting
  • Loading branch information
JT-39 authored Oct 15, 2024
1 parent 8354c19 commit 75bcb48
Show file tree
Hide file tree
Showing 34 changed files with 2,062 additions and 595 deletions.
257 changes: 257 additions & 0 deletions 02_dev/all_la_dev_app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
# Load global
source(here::here("global.R"))

# Load functions
list.files("R/", full.names = TRUE) |>
(\(x) {
x[grepl("fn_", x)]
})() |>
purrr::walk(source)

# UI
ui_dev <- bslib::page_fillable(

## Custom CSS =============================================================
shiny::includeCSS(here::here("www/dfe_shiny_gov_style.css")),

# Tab header ==============================================================
h1("All Local Authorities"),
div(
class = "well",
style = "overflow-y: visible;",
bslib::layout_column_wrap(
width = "15rem", # Minimum width for each input box before wrapping
shiny::selectInput(
inputId = "la_input",
label = "Change Authority:",
choices = la_names_bds
),
shiny::selectInput(
inputId = "topic_input",
label = "Topic:",
choices = metric_topics
),
shiny::selectInput(
inputId = "indicator",
label = NULL,
choices = metric_names
)
)
),
div(
class = "well",
style = "overflow-y: visible;",
bslib::navset_card_tab(
id = "all_la_table_tabs",
bslib::nav_panel(
"Tables",
bslib::card_header(
shiny::uiOutput("all_la_table_name"),
style = "text-align: center;"
),
reactable::reactableOutput("all_la_la_table"),
div(
style = "border-top: 2px solid black; padding-top: 2.5rem;", # Add black border between the tables
reactable::reactableOutput("all_la_region_table")
)
),
bslib::nav_panel(
"Download data",
shinyGovstyle::radio_button_Input(
inputId = "file_type",
label = h2("Choose download file format"),
hint_label = paste0(
"This will download all data related to the providers and options selected.",
" The XLSX format is designed for use in Microsoft Excel."
),
choices = c("CSV (Up to 5.47 MB)", "XLSX (Up to 1.75 MB)"),
selected = "CSV (Up to 5.47 MB)"
),
shiny::downloadButton(
"la_download",
label = "Download LA table",
class = "gov-uk-button",
icon = NULL
),
shiny::downloadButton(
"region_download",
label = "Download Region table",
class = "gov-uk-button",
icon = NULL
)
)
)
)
)



# Server
server_dev <- function(input, output, session) {
# Input ----------------------------------
# Using the server to power to the provider dropdown for increased speed
shiny::observeEvent(input$topic_input, {
# Get indicator choices for selected topic
filtered_topic_bds <- bds_metrics |>
dplyr::filter(
Topic == input$topic_input
) |>
pull_uniques("Measure")

updateSelectInput(
session = session,
inputId = "indicator",
label = "Indicator:",
choices = filtered_topic_bds
)
})


# Region LA Level table ----------------------------------
# Filter for selected topic and indicator
# Define filtered_bds outside of observeEvent
filtered_bds <- reactiveValues(data = NULL)

observeEvent(input$indicator, {
# Region LA Level table ----------------------------------
# Filter for selected topic and indicator
filtered_bds$data <- bds_metrics |>
dplyr::filter(
Topic == input$topic_input,
Measure == input$indicator,
!is.na(Years)
)
})

# All LA formatted table
all_la_table <- reactive({
# All LAs long data
all_la_long <- filtered_bds$data |>
dplyr::select(`LA Number`, `LA and Regions`, Years, Years_num, values_num, Values)

# Difference between last two years
all_la_diff <- all_la_long |>
calculate_change_from_prev_yr()

# Get polarity of indicator
indicator_polarity <- filtered_bds$data |>
pull_uniques("Polarity")

# Get latest rank, ties are set to min & NA vals to NA rank
all_la_ranked <- filtered_bds$data |>
filter_la_regions(la_names_bds, latest = TRUE) |>
dplyr::mutate(
Rank = dplyr::case_when(
is.na(values_num) ~ NA,
# Rank in descending order
indicator_polarity == "High" ~ rank(-values_num, ties.method = "min", na.last = TRUE),
# Rank in ascending order
indicator_polarity == "Low" ~ rank(values_num, ties.method = "min", na.last = TRUE)
)
) |>
dplyr::select(`LA and Regions`, Rank)

# Convert to wide format and join rank column
all_la_long |>
rbind(all_la_diff) |>
tidyr::pivot_wider(
id_cols = c("LA Number", "LA and Regions"),
names_from = Years,
values_from = values_num,
)
})

# All LA Level LA table -----------------------------------------------------
output$all_la_la_table <- reactable::renderReactable({
# Filter for LAs and arrange by alphabetical order
all_la_la_table <- all_la_table() |>
filter_la_data_all_la(la_names_bds)

# Output table
dfe_reactable(
all_la_la_table,
# Create the reactable with specific column alignments
columns = utils::modifyList(
format_num_reactable_cols(
all_la_la_table,
get_indicator_dps(filtered_bds$data),
num_exclude = "LA Number",
categorical = "Rank"
),
set_custom_default_col_widths()
),
rowStyle = function(index) {
highlight_selected_row(index, all_la_la_table, input$la_input)
},
pagination = FALSE
)
})

# All LA Level Region table -------------------------------------------------
output$all_la_region_table <- reactable::renderReactable({
# Filter and prepare Region table
all_la_region_table <- all_la_table() |>
filter_region_data_all_la(la_names_bds)

# Get region of LA
all_la_region <- stat_n_la |>
dplyr::filter(`LA Name` == input$la_input) |>
pull_uniques("GOReg") |>
clean_ldn_region(filtered_bds$data)

# Output table
dfe_reactable(
all_la_region_table,
# Create the reactable with specific column alignments
columns = utils::modifyList(
format_num_reactable_cols(
all_la_region_table,
get_indicator_dps(filtered_bds$data),
num_exclude = "LA Number"
),
set_custom_default_col_widths()
),
rowStyle = function(index) {
highlight_selected_row(index, all_la_region_table, all_la_region)
},
pagination = FALSE,
class = "hidden-column-headers"
)
})

# Download tables
# Store the table and export file in reactive values
la_local <- reactiveValues(export_file = NULL, data = NULL, file_type = NULL, file_name = NULL)
region_local <- reactiveValues(export_file = NULL, data = NULL, file_type = NULL, file_name = NULL)

# Observe when input$file_type or all_la_table is updated and create relevant file
observeEvent(c(input$file_type, all_la_table()), {
# Setting parameters
la_local$file_type <- input$file_type
la_local$file_name <- "AllLA_LA_table"

# LA table
la_local$data <- all_la_table() |>
filter_la_data_all_la(la_names_bds)

generate_download_file(la_local$data, input$file_type)

# Region table
region_local$data <- all_la_table() |>
filter_region_data_all_la(la_names_bds)

generate_download_file(region_local$data, input$file_type)
})

# Download handlers
output$la_download <- create_download_handler(la_local)
output$region_download <- create_download_handler(region_local)

# Get chart title for All LA table name
output$all_la_table_name <- shiny::renderUI({
filtered_bds$data |>
pull_uniques("Chart_title")
})
}

shiny::shinyApp(ui_dev, server_dev)
60 changes: 60 additions & 0 deletions 02_dev/all_la_dev_app_mod.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Load global
source(here::here("global.R"))

# Load functions
list.files("R/", full.names = TRUE) |>
(\(x) {
x[grepl("fn_", x)]
})() |>
purrr::walk(source)

# Load modules
list.files("R/lait_modules/", full.names = TRUE) |>
purrr::walk(source)


# UI
ui_mod <- bslib::page_fillable(
## Custom CSS ===============================================================
shiny::includeCSS(here::here("www/dfe_shiny_gov_style.css")),

# Tab header ================================================================
h1("All Local Authorities"),


# Start of app =============================================================
appInputsUI("all_la_inputs"),

# LA Level Table ------------------------------------------------------------
AllLA_TableUI("all_la_table")
)


# Server
server_mod <- function(input, output, session) {
# Getting inputs ===========================================================
# reactiveValues object to store shared input values across pages
shared_values <- reactiveValues(
la = NULL,
topic = NULL,
indicator = NULL,
chart_line_input = NULL,
chart_bar_input = NULL
)

# Extract selected LA, Topic and Indicator
app_inputs <- appInputsServer("all_la_inputs", shared_values)


# LA and Region table -------------------------------------------------------
AllLA_TableServer(
"all_la_table",
app_inputs,
bds_metrics,
la_names_bds
)
}


# Run app
shinyApp(ui_mod, server_mod)
Loading

0 comments on commit 75bcb48

Please sign in to comment.