diff --git a/R/module-helpers-prevalence.R b/R/module-helpers-prevalence.R index 631e21e..2f4564d 100644 --- a/R/module-helpers-prevalence.R +++ b/R/module-helpers-prevalence.R @@ -5,39 +5,49 @@ #' #' #' Display input variables dynamically, according to UI for screening -#' -#' -#' @param vars,source,indicator_surv,has_age Input variables collected +#' +#' +#' @param vars,source,indicator_surv,has_age Input variables collected #' from the UI and required to pass to `{mwana}` prevalence functions. -#' +#' #' @param ns A placeholder for Shiny module namespace. #' #' @keywords internal #' #' mod_prevalence_display_input_variables <- function( - vars, source, indicator_surv, has_age, ns) { + vars, + source, + indicator_surv, + has_age, + ns +) { ### Base list input vars ---- inputs <- list( shiny::selectInput( inputId = ns("area1"), label = shiny::tagList( - htmltools::tags$span("Area 1", + htmltools::tags$span( + "Area 1", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$div( - style = "font-size: 0.85em; color: #6c7574;", "(Primary area)" + style = "font-size: 0.85em; color: #6c7574;", + "(Primary area)" ) ), choices = c("", vars) ), - shiny::selectInput(ns("area2"), + shiny::selectInput( + ns("area2"), label = shiny::tagList( - htmltools::tags$span("Area 2", + htmltools::tags$span( + "Area 2", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$div( - style = "font-size: 0.85em; color: #6c7574;", "(Sub-area)" + style = "font-size: 0.85em; color: #6c7574;", + "(Sub-area)" ) ), choices = c("", vars) @@ -45,111 +55,129 @@ mod_prevalence_display_input_variables <- function( shiny::selectInput( inputId = ns("area3"), label = shiny::tagList( - htmltools::tags$span("Area 3", + htmltools::tags$span( + "Area 3", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$div( - style = "font-size: 0.85em; color: #6c7574;", "Sub-area)" + style = "font-size: 0.85em; color: #6c7574;", + "Sub-area)" ) ), choices = c("", vars) - ), + ), shiny::selectInput( inputId = ns("wts"), label = shiny::tagList( - htmltools::tags$span("Survey weights", + htmltools::tags$span( + "Survey weights", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$div( style = "font-size: 0.85em; color: #6c7574;", "Final survey weights for weighted analysis" - ) - ), - choices = c("", vars) - ) + ) + ), + choices = c("", vars) + ) ) #### Conditional inputs depending on source of data ---- if (source == "survey") { - inputs <- c(inputs, list( - if (isTRUE(indicator_surv == "muac")) { - #### Display age ---- - shiny::tagList( + inputs <- c( + inputs, + list( + if (isTRUE(indicator_surv == "muac")) { + #### Display age ---- + shiny::tagList( + shiny::selectInput( + inputId = ns("muac"), + label = shiny::tagList( + htmltools::tags$span( + "MUAC", + style = "font-size: 14px; font-weight: bold;" + ), + htmltools::tags$span("*", style = "color: red;") + ), + choices = c("", vars) + ), + shiny::selectInput( + inputId = ns("age"), + label = shiny::tagList( + htmltools::tags$span( + "Age (months)", + style = "font-size: 14px; font-weight: bold;" + ), + htmltools::tags$span("*", style = "color: red;") + ), + choices = c("", vars) + ) + ) + } + ) + ) + } + + if (source == "screening") { + inputs <- c( + inputs, + list( + shiny::selectInput( + inputId = ns("muac"), + label = shiny::tagList( + htmltools::tags$span( + "MUAC", + style = "font-size: 14px; font-weight: bold;" + ), + htmltools::tags$span("*", style = "color: red;") + ), + choices = c("", vars) + ), + if (isTRUE(has_age == "yes")) { shiny::selectInput( - inputId = ns("muac"), + inputId = ns("age"), label = shiny::tagList( - htmltools::tags$span("MUAC", + htmltools::tags$span( + "Age (months)", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$span("*", style = "color: red;") ), choices = c("", vars) - ), + ) + } else { shiny::selectInput( - inputId = ns("age"), + inputId = ns("age_cat"), label = shiny::tagList( - htmltools::tags$span("Age (months)", + htmltools::tags$span( + "Age categories (6-23 and 24-59)", style = "font-size: 14px; font-weight: bold;" ), htmltools::tags$span("*", style = "color: red;") ), choices = c("", vars) ) - ) - } - )) + } + ) + ) } - if (source == "screening") { - inputs <- c(inputs, list( + # Always add oedema at the end + inputs_vars <- c( + inputs, + list( shiny::selectInput( - inputId = ns("muac"), + inputId = ns("oedema"), label = shiny::tagList( - htmltools::tags$span("MUAC", + htmltools::tags$span( + "Oedema", style = "font-size: 14px; font-weight: bold;" - ), - htmltools::tags$span("*", style = "color: red;") + ) ), choices = c("", vars) - ), - if (isTRUE(has_age == "yes")) { - shiny::selectInput( - inputId = ns("age"), - label = shiny::tagList( - htmltools::tags$span("Age (months)", - style = "font-size: 14px; font-weight: bold;" - ), - htmltools::tags$span("*", style = "color: red;") - ), - choices = c("", vars) - ) - } else { - shiny::selectInput( - inputId = ns("age_cat"), - label = shiny::tagList( - htmltools::tags$span("Age categories (6-23 and 24-59)", - style = "font-size: 14px; font-weight: bold;" - ), - htmltools::tags$span("*", style = "color: red;") - ), - choices = c("", vars) - ) - } - )) - } - - # Always add oedema at the end - inputs_vars <- c(inputs, list( - shiny::selectInput( - inputId = ns("oedema"), - label = shiny::tagList( - htmltools::tags$span("Oedema", - style = "font-size: 14px; font-weight: bold;" - ) - ), - choices = c("", vars) + ) ) - )) + ) inputs_vars } @@ -160,27 +188,42 @@ mod_prevalence_display_input_variables <- function( #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI -#' -#' @param df,wts,oedema,area1,area2,area3 Input variables collected from the UI +#' +#' @param df,wts,oedema,area1,area2,area3 Input variables collected from the UI #' and required to pass to mwana::mw_estimate_prevalence_wfhz(). -#' +#' #' @returns A summary tibble for the descriptive statistics about wasting. #' #' @keywords internal #' #' mod_prevalence_call_wfhz_prev_estimator <- function( - df, wts = NULL, oedema = NULL, - area1, area2, area3) { + df, + wts = NULL, + oedema = NULL, + area1, + area2, + area3 +) { ## Build the grouping variables dynamically ---- dots <- list() - if (!is.null(area1) && nzchar(area1)) dots <- c(dots, list(rlang::sym(area1))) - if (!is.null(area2) && nzchar(area2)) dots <- c(dots, list(rlang::sym(area2))) - if (!is.null(area3) && nzchar(area3)) dots <- c(dots, list(rlang::sym(area3))) + if (!is.null(area1) && nzchar(area1)) { + dots <- c(dots, list(rlang::sym(area1))) + } + if (!is.null(area2) && nzchar(area2)) { + dots <- c(dots, list(rlang::sym(area2))) + } + if (!is.null(area3) && nzchar(area3)) { + dots <- c(dots, list(rlang::sym(area3))) + } ## Determine wt and oedema arguments - only convert to symbol if valid ---- wt_arg <- if (!is.null(wts) && nzchar(wts)) rlang::sym(wts) else NULL - oedema_arg <- if (!is.null(oedema) && nzchar(oedema)) rlang::sym(oedema) else NULL + oedema_arg <- if (!is.null(oedema) && nzchar(oedema)) { + rlang::sym(oedema) + } else { + NULL + } ## Call the function once with dynamic arguments ---- mwana::mw_estimate_prevalence_wfhz( @@ -198,23 +241,36 @@ mod_prevalence_call_wfhz_prev_estimator <- function( #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI #' -#' @param df,age,muac,wts,oedema,area1,area2,area3 Input variables collected +#' @param df,age,muac,wts,oedema,area1,area2,area3 Input variables collected #' from the UI and required to pass to mwana::mw_estimate_prevalence_muac(). -#' -#' @returns A summary tibble for the descriptive statistics about wasting based +#' +#' @returns A summary tibble for the descriptive statistics about wasting based #' on MUAC, with confidence intervals. -#' +#' #' @keywords internal #' #' mod_prevalence_call_muac_prev_estimator <- function( - df, age, muac, wts = NULL, oedema = NULL, - area1, area2, area3) { + df, + age, + muac, + wts = NULL, + oedema = NULL, + area1, + area2, + area3 +) { # Build the grouping variables dynamically ---- dots <- list() - if (nzchar(area1)) dots <- c(dots, list(rlang::sym(area1))) - if (nzchar(area2)) dots <- c(dots, list(rlang::sym(area2))) - if (nzchar(area3)) dots <- c(dots, list(rlang::sym(area3))) + if (nzchar(area1)) { + dots <- c(dots, list(rlang::sym(area1))) + } + if (nzchar(area2)) { + dots <- c(dots, list(rlang::sym(area2))) + } + if (nzchar(area3)) { + dots <- c(dots, list(rlang::sym(area3))) + } # Determine wt and oedema arguments ---- wt_arg <- if (nzchar(wts)) rlang::sym(wts) else NULL @@ -242,17 +298,32 @@ mod_prevalence_call_muac_prev_estimator <- function( #' #' mod_prevalence_call_combined_prev_estimator <- function( - df, wts = NULL, oedema = NULL, - area1, area2, area3) { + df, + wts = NULL, + oedema = NULL, + area1, + area2, + area3 +) { ## Build the grouping variables dynamically ---- dots <- list() - if (!is.null(area1) && nzchar(area1)) dots <- c(dots, list(rlang::sym(area1))) - if (!is.null(area2) && nzchar(area2)) dots <- c(dots, list(rlang::sym(area2))) - if (!is.null(area3) && nzchar(area3)) dots <- c(dots, list(rlang::sym(area3))) + if (!is.null(area1) && nzchar(area1)) { + dots <- c(dots, list(rlang::sym(area1))) + } + if (!is.null(area2) && nzchar(area2)) { + dots <- c(dots, list(rlang::sym(area2))) + } + if (!is.null(area3) && nzchar(area3)) { + dots <- c(dots, list(rlang::sym(area3))) + } ## Determine wt and oedema arguments - only convert to symbol if valid ---- wt_arg <- if (!is.null(wts) && nzchar(wts)) rlang::sym(wts) else NULL - oedema_arg <- if (!is.null(oedema) && nzchar(oedema)) rlang::sym(oedema) else NULL + oedema_arg <- if (!is.null(oedema) && nzchar(oedema)) { + rlang::sym(oedema) + } else { + NULL + } ## Call the function once with dynamic arguments ---- mwana::mw_estimate_prevalence_combined( @@ -269,23 +340,37 @@ mod_prevalence_call_combined_prev_estimator <- function( #' #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI -#' -#' @param df,age,muac,oedema,area1,area2,area3 Input variables collected -#' from the UI and required to pass to mwana::mw_estimate_prevalence_screening(). +#' +#' @param df,age,muac,oedema,area1,area2,area3 Input variables collected +#' from the UI and required to pass to mwana::mw_estimate_prevalence_screening(). # -#' @returns A summary tibble for the descriptive statistics about wasting based +#' @returns A summary tibble for the descriptive statistics about wasting based #' on MUAC, with no confidence intervals. #' #' @keywords internal #' #' mod_prevalence_call_prev_estimator_screening <- function( - df, age, muac, oedema = NULL, - area1, area2, area3) { + df, + age, + muac, + oedema = NULL, + area1, + area2, + area3 +) { dots <- list() - if (nzchar(area1)) dots <- c(dots, list(rlang::sym(area1))) else NULL - if (nzchar(area2)) dots <- c(dots, list(rlang::sym(area2))) - if (nzchar(area3)) dots <- c(dots, list(rlang::sym(area3))) + if (nzchar(area1)) { + dots <- c(dots, list(rlang::sym(area1))) + } else { + NULL + } + if (nzchar(area2)) { + dots <- c(dots, list(rlang::sym(area2))) + } + if (nzchar(area3)) { + dots <- c(dots, list(rlang::sym(area3))) + } df <- dplyr::mutate(df, muac = !!rlang::sym(muac) * 10) @@ -317,21 +402,35 @@ mod_prevalence_call_prev_estimator_screening <- function( #' Invoke mwana's prevalence functions from within module server according to #' user specifications in the UI #' -#' @param df,age_cat,muac,oedema,area1,area2,area3 Input variables collected +#' @param df,age_cat,muac,oedema,area1,area2,area3 Input variables collected #' from the UI and required to pass to mwana::mw_estimate_prevalence_screening2() -#' -#' @returns A summary tibble for the descriptive statistics about wasting based +#' +#' @returns A summary tibble for the descriptive statistics about wasting based #' on MUAC, with no confidence intervals. #' #' @keywords internal #' mod_prevalence_call_prev_estimator_screening2 <- function( - df, age_cat, muac, oedema = NULL, - area1, area2, area3) { + df, + age_cat, + muac, + oedema = NULL, + area1, + area2, + area3 +) { dots <- list() - if (nzchar(area1)) dots <- c(dots, list(rlang::sym(area1))) else NULL - if (nzchar(area2)) dots <- c(dots, list(rlang::sym(area2))) - if (nzchar(area3)) dots <- c(dots, list(rlang::sym(area3))) + if (nzchar(area1)) { + dots <- c(dots, list(rlang::sym(area1))) + } else { + NULL + } + if (nzchar(area2)) { + dots <- c(dots, list(rlang::sym(area2))) + } + if (nzchar(area3)) { + dots <- c(dots, list(rlang::sym(area3))) + } # Create the call - pass oedema as NULL or as a symbol if (nzchar(oedema)) { @@ -358,25 +457,28 @@ mod_prevalence_call_prev_estimator_screening2 <- function( #' #' #' Neat prevalence output from survey -#' +#' #' @param df data.frame containing the prevalence results. #' @param .type A choice from which the prevalence is derived. -#' -#' @returns A tibble object of the same length and width as df, with column +#' +#' @returns A tibble object of the same length and width as df, with column #' names and values formatted for clarity and readability. -#' +#' #' @keywords internal #' #' mod_prevalence_neat_output_survey <- function( - df, - .type = c("wfhz", "muac", "combined")) { + df, + .type = c("wfhz", "muac", "combined") +) { df <- dplyr::mutate( .data = df, dplyr::across( .cols = dplyr::ends_with(c("am_p", "am_p_low", "am_p_upp")), .fns = scales::label_percent( - accuracy = 0.1, suffix = "%", decimal.mark = "." + accuracy = 0.1, + suffix = "%", + decimal.mark = "." ) ) ) @@ -429,12 +531,12 @@ mod_prevalence_neat_output_survey <- function( #' -#' +#' #' Neat prevalence output from survey -#' +#' #' @param df data.frame containing the prevalence results. -#' -#' @returns A tibble object of the same length and width as df, with column +#' +#' @returns A tibble object of the same length and width as df, with column #' names and values formatted for clarity and readability. #' #' @keywords internal diff --git a/inst/app/ui.R b/inst/app/ui.R index 23e0352..36e1689 100644 --- a/inst/app/ui.R +++ b/inst/app/ui.R @@ -18,35 +18,41 @@ library(rlang) ui <- tagList( ### Link up with custom .css file ---- tags$head( - tags$link(rel = "stylesheet", type = "text/css", href = "custom.css") # external stylesheet + tags$meta(charset = "UTF-8"), + tags$meta(name = "description", content = "mwana App"), + tags$title("mwana App"), + tags$link(rel = "stylesheet", type = "text/css", href = "custom.css"), # external stylesheet + tags$link(rel = "icon", href = "logo.png"), ), page_navbar( title = tags$div( - style = "display: flex; align-items: center; justify-content: space-between; width: 100%;", + class = "page-navbar", ### Left side: app name and logo ---- tags$div( - style = "display: flex; align-items: center;", - tags$span("mwana", - style = "margin-right: 10px; font-family: Arial, sans-serif; font-size: 50px;" + class = "brand", + tags$span( + class = "brand-span", + "mwana", ), tags$a( href = "https://mphimo.github.io/mwana/", + target = "_blank", tags$span( - tags$img(src = "logo.png", height = "40px"), - style = "margin-right: 20px;" + tags$img(src = "logo.png"), ) ) ), ### Right side: app version ---- - tags$span(paste0( - "App v", utils::packageVersion("mwanaApp"), - " | Eng: mwana v", utils::packageVersion("mwana") - ), - id = "app-version", - style = "font-size: 12.5px; color: rgba(255, 255, 255, 0.4); - position: fixed; top: 40px; right: 20px;" + tags$span( + class = "app-version", + paste0( + "App v", + utils::packageVersion("mwanaApp"), + " | Eng: mwana v", + utils::packageVersion("mwana") + ) ) ), @@ -59,7 +65,7 @@ ui <- tagList( ### Left sidebar for contents ---- layout_sidebar( sidebar = tags$div( - style = "padding: 1rem;", + class = "table-contents", tags$h4("Contents"), tags$h6(tags$a(href = "#sec1", "Welcome")), tags$h6(tags$a(href = "#sec2", "Data Upload")), @@ -84,16 +90,17 @@ ui <- tagList( ##### Left side: title + subtitle stacked ---- tags$div( style = "display: flex; flex-direction: column;", - tags$h3( - style = "marging: 0; font-weight: bold;", - "A seamless graphical interface to the mwana R package for data + tags$h3( + style = "marging: 0; font-weight: bold;", + "A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and prevalence estimation of wasting" - ) - ), + ) + ), ##### Right side: logo ---- tags$a( href = "https://mphimo.github.io/mwana/", + target = "_blank", tags$img( src = "logo.png", height = "160px", @@ -102,123 +109,133 @@ ui <- tagList( ) ) ) - ), + ), - #### Welcome message ---- - tags$div( - id = "sec1", - style = "text-align: justify;", - tags$hr(), - tags$p( - " + #### Welcome message ---- + tags$div( + id = "sec1", + style = "text-align: justify;", + tags$hr(), + tags$p( + " This app is a lightweight, field-ready application thoughtful designed to seamlessly streamline plausibility checks and wasting prevalence estimation of child anthropometric data, by automating key steps of the R package ", - tags$a( - href = "https://mphimo.github.io/mwana/", - tags$code("mwana") - ), "for non-R users." + tags$a( + href = "https://mphimo.github.io/mwana/", + target = "_blank", + tags$code("mwana") ), - tags$p( - "The app is divided in five easy-to-navigate tabs, apart from + "for non-R users." + ), + tags$p( + "The app is divided in five easy-to-navigate tabs, apart from the Home - where you at right now.", - tags$ol( - tags$li(tags$b("Data Upload")), - tags$li(tags$b("Data Wrangling")), - tags$li(tags$b("Plausibility Check")), - tags$li(tags$b("Prevalence Analysis")), - tags$li(tags$b("IPC Check")) - ) - ), - tags$hr(), + tags$ol( + tags$li(tags$b("Data Upload")), + tags$li(tags$b("Data Wrangling")), + tags$li(tags$b("Plausibility Check")), + tags$li(tags$b("Prevalence Analysis")), + tags$li(tags$b("IPC Check")) + ) + ), + tags$hr(), - ##### Briefly describe each tab ---- - tags$div( - id = "sec2", - style = "text-align: justify;", + ##### Briefly describe each tab ---- + tags$div( + id = "sec2", + style = "text-align: justify;", - ###### Data Upload tab ---- - tags$p(tags$b("Data Upload")), - tags$p( - " + ###### Data Upload tab ---- + tags$p(tags$b("Data Upload")), + tags$p( + " This is where the workflow begins. Upload the dataset saved in a comma-separated-value format (.csv); this is the only accepted format. Click on the 'Browse' button to locate the file to be uploaded from your computer; it is as simple as that. Once uploaded, the first 20 rows will be priviewed on the right side. " - ), - tags$ul( - tags$li( - tags$b("Data requirements"), - tags$p( - " + ), + tags$ul( + tags$li( + tags$b("Data requirements"), + tags$p( + " The data to be uploaded must have been tidy up in accordance - to the below-described app's", tags$b("input file"), "and", - tags$b("input variable"), "requirements: + to the below-described app's", + tags$b("input file"), + "and", + tags$b("input variable"), + "requirements: " - ), - tags$ul( - tags$li( - tags$b("Input file requirements"), - tags$ul( - tags$li( - tags$b("File naming:"), "the file name must use + ), + tags$ul( + tags$li( + tags$b("Input file requirements"), + tags$ul( + tags$li( + tags$b("File naming:"), + "the file name must use underscore ( _ ) to separate words. Hyphen ( - ) or simple spaces will lead to errors along the uploading process. Consider the following naming example:", - tags$em("my_file_to_upload.csv") - ) + tags$em("my_file_to_upload.csv") ) - ), - tags$br(), - tags$li( - tags$b("Input variable requirements"), - tags$ul( - tags$li( - tags$b("Age:"), "values must be in months. The variable name + ) + ), + tags$br(), + tags$li( + tags$b("Input variable requirements"), + tags$ul( + tags$li( + tags$b("Age:"), + "values must be in months. The variable name must be written in lowercase ('age')." - ), - tags$li( - tags$b("Sex:"), "values must be given in 'm' for boys and 'f' + ), + tags$li( + tags$b("Sex:"), + "values must be given in 'm' for boys and 'f' for girls." - ), - tags$li( - tags$b("MUAC:"), "values must be in millimetres. Ensure there + ), + tags$li( + tags$b("MUAC:"), + "values must be in millimetres. Ensure there are no strange numbers, such as '130.1'. The presence of decimal places will raise error in the data wrangling tab and hault the app." - ), - tags$li( - tags$b("Oedema:"), "values must be given in 'y' for yes, + ), + tags$li( + tags$b("Oedema:"), + "values must be given in 'y' for yes, and 'n' for no." - ) ) ) ) ) ) - ), - tags$hr(), + ) + ), + tags$hr(), - ###### Data Wrangling tab ---- - tags$div( - id = "sec3", - style = "text-align: justify;", - tags$p(tags$b("Data Wrangling")), - tags$p( - " + ###### Data Wrangling tab ---- + tags$div( + id = "sec3", + style = "text-align: justify;", + tags$p(tags$b("Data Wrangling")), + tags$p( + " Wrangle the dataset for downstream workflow. For this, different wrangling methods are given. Upon completion, this tab's output becomes available in subsequent tabs; therefore, the wrangling method selected herein should match the intended analysis. " - ), - tags$p( - " + ), + tags$p( + " Under the hood, the wrangling process consists in calculating age in months and excluding all records that fall under six months and over 59.99 months. Then, it computes z-scores - if @@ -226,19 +243,27 @@ ui <- tagList( based on the SMART flagging criteria - for z-scores. For MUAC, when age in months is not available, values under 100 and over 200 millimetres are considered as outliers. At the the end, two new - columns get added into the dataset:", tags$code("wfhz"), "and", - tags$code("flag_wfhz"), "for weight-for-heigh z-scores and flagged + columns get added into the dataset:", + tags$code("wfhz"), + "and", + tags$code("flag_wfhz"), + "for weight-for-heigh z-scores and flagged records, respectively. Moreover, when working with MUAC and when - age is available, the following columns get added:", tags$code("mfaz"), - "and", tags$code("flag_mfaz"), "for MUAC-for-age z-scores and flagged + age is available, the following columns get added:", + tags$code("mfaz"), + "and", + tags$code("flag_mfaz"), + "for MUAC-for-age z-scores and flagged records, respectively. Finally, when age is not available, only one - column gets added:", tags$code("flag_muac"), "which indicates + column gets added:", + tags$code("flag_muac"), + "which indicates the flagged records based on the above-mentioned criterion. " - ), - tags$p( - " + ), + tags$p( + " Once the wrangling process is completed, a preview of the output is displayed on the right side of the tab, wherein the first 20 rows are shown. You can get a full view of the entire dataset by @@ -246,17 +271,17 @@ ui <- tagList( thereafter look for the file in the 'downloads' folder on your computer. " - ) - ), - tags$hr(), + ) + ), + tags$hr(), - ###### Plausibility Check tab ---- - tags$div( - id = "sec4", - style = "text-align: justify;", - tags$p(tags$b("Plausibility Check")), - tags$p( - "As above-described, this tab depends on the previous tab. + ###### Plausibility Check tab ---- + tags$div( + id = "sec4", + style = "text-align: justify;", + tags$p(tags$b("Plausibility Check")), + tags$p( + "As above-described, this tab depends on the previous tab. Select the same method as in the data wrangling. Thereafter, supply the input fields with the corresponding variables from the dataset. For this, a dropdown list of the variable @@ -265,36 +290,43 @@ ui <- tagList( The app lets you get the plausibility checks results grouped by different categories - up to a maximum of three. For this, - supply the grouping variables to", tags$code("Area 1"), - tags$code("Area 2"), "and", tags$code("Area 3") - ), - tags$p(tags$em( - "For example: In your dataset, there are the following + supply the grouping variables to", + tags$code("Area 1"), + tags$code("Area 2"), + "and", + tags$code("Area 3") + ), + tags$p(tags$em( + "For example: In your dataset, there are the following indentifying variables: 'state', 'county', and 'team'. You wish to get the plausibility check results grouped by province, then by county and then you also wish to check the results by survey teams that worked in each county and provinces. You can achieve this simply by supplying 'province' to", - tags$code("Area 1"), "'county' to", tags$code("Area 2"), - "and 'team' to", tags$code("Area 3"), "." - )), - tags$p( - " + tags$code("Area 1"), + "'county' to", + tags$code("Area 2"), + "and 'team' to", + tags$code("Area 3"), + "." + )), + tags$p( + " Upon completion, you can download the results into Excel by clicking on the 'Download Results' button found at the bottom-right side of the tab. " - ) - ), - tags$hr(), + ) + ), + tags$hr(), - ###### Prevalence Analysis tab ---- - tags$div( - id = "sec5", - style = "text-align: justify;", - tags$p(tags$b("Prevalence Analysis")), - tags$p( - " + ###### Prevalence Analysis tab ---- + tags$div( + id = "sec5", + style = "text-align: justify;", + tags$p(tags$b("Prevalence Analysis")), + tags$p( + " As afore-mentioned, this tab depends on the data wrangling. The app lets you estimate prevalence derived from survey and screening. Therefore, the first step is to select the @@ -304,77 +336,92 @@ ui <- tagList( or resort to a fallback - when 'No' is selected. In the latter case, you must have a variable called", - tags$code("age_cat"), ".", "This should have the following + tags$code("age_cat"), + ".", + "This should have the following categories: '6-23' for each record wherein age is between 6 and 23 months, and '24-59' for when age is between 24 and 59 monts. - This must be done before uploading the data.", "The", - tags$code("age_cat"), "variable is supplied to the ", - tags$code("Age categories (6-23 and 24-59)"), "input field. + This must be done before uploading the data.", + "The", + tags$code("age_cat"), + "variable is supplied to the ", + tags$code("Age categories (6-23 and 24-59)"), + "input field. This ensures that MUAC-based prevalence gets age-weighted - whenever there is excess of children in the 6-23' category.", "Read more", - tags$a("here", href = "https://mphimo.github.io/mwana/dev/reference/age_ratio.html"), - "and", tags$a("here", href = "https://mphimo.github.io/mwana/dev/articles/prevalence.html#sec-prevalence-muac"), - "." + whenever there is excess of children in the 6-23' category.", + "Read more", + tags$a( + "here", + href = "https://mphimo.github.io/mwana/reference/age_ratio.html", + target = "_blank", ), - tags$p( - " + "and", + tags$a( + "here", + href = "https://mphimo.github.io/mwana/articles/prevalence.html#sec-prevalence-muac", + target = "_blank", + ), + "." + ), + tags$p( + " Thereafter, the next step is to select the method to define acute malnutrition. Then, supply the input variables as required. " - ), - tags$p( - " + ), + tags$p( + " You can also group the analysis by different groups, as explained in the plausibility check section. Follow the same guide provided therein. " - ) - ), - tags$hr(), + ) + ), + tags$hr(), - ###### IPC Check tab ---- - tags$div( - id = "sec6", - style = "text-align: justify;", - tags$p(tags$b("IPC Check")), - tags$p( - " + ###### IPC Check tab ---- + tags$div( + id = "sec6", + style = "text-align: justify;", + tags$p(tags$b("IPC Check")), + tags$p( + " This lets you check whether the IPC Acute Malnutrition evidence requirements for outcome data have been met or not. It checks against survey, screening and sentinel sites data source-related requirements, in accordance with the IPC protocols. " - ), - tags$p( - " + ), + tags$p( + " This tab depends on the 'Upload Data' tab; this means that you can check the requirements even before the wrangling the data. " - ) - ), - tags$hr(), - tags$div( - id = "sec7", - style = "text-align: justify;", - tags$p(tags$b("Authorship")), - tags$p( - "This app was developed and is maintained by Tomás Zaba." - ) - ), - tags$hr(), - tags$div( - id = "sec8", - style = "text-align: justify;", - tags$p(tags$b("License")), - tags$p( - "This app is licensed under the GPL (>=3) license." - ) + ) + ), + tags$hr(), + tags$div( + id = "sec7", + style = "text-align: justify;", + tags$p(tags$b("Authorship")), + tags$p( + "This app was developed and is maintained by Tomás Zaba." + ) + ), + tags$hr(), + tags$div( + id = "sec8", + style = "text-align: justify;", + tags$p(tags$b("License")), + tags$p( + "This app is licensed under the GPL (>=3) license." ) ) ) ) ) + ) ), ## ---- Tab 2: Data Upload --------------------------------------------------- @@ -412,4 +459,4 @@ ui <- tagList( mwanaApp:::module_ui_ipccheck(id = "ipc_check") ) ) -) \ No newline at end of file +) diff --git a/inst/app/www/custom.css b/inst/app/www/custom.css index 75f7a22..8d0574e 100644 --- a/inst/app/www/custom.css +++ b/inst/app/www/custom.css @@ -1,30 +1,116 @@ -/* Global background */ +/* Import Roboto Font from Google Fonts */ + +@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"); + + +/* ---- Global background --------------------------------------------------- */ + + body { - color: rgb(68, 68, 68); background-color: #f9fdfb; - font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", - "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + color: rgb(68, 68, 68); +} + +p, +li, +h6, +h4, +h3, +b, +h6, +span { + font-family: Roboto, Arial, sans-serif, "Helvetica Neue"; +} + + +/* ---- Navigation bar ------------------------------------------------------ */ + + +/* Navbar container */ +nav, +nav .container-fluid { + background-color: #004225; + margin-top: -1rem; + height: 90px; + width: 100vw; + border: none; + margin: 0; + padding: 0; +} + +/* Brand (name and logo) */ + +.page-navbar { + align-items: center; + display: flex; + justify-content: space-between; + width: 100%; + padding-right: 30px; + height: 50px; + color: rgba(255, 255, 255, 0.7); +} + +/* Brand name */ + +.brand, +.brand-span { + margin-right: 10px; + margin-top: 12px; + font-family: Roboto, Arial, Helvetica, sans-serif; + font-size: 50px; + display: flex; + align-items: center; + color: rgba(255, 255, 255, 0.7); +} + +/* Logo */ + +a span { + margin-right: 20px; +} + +a span img { + height: 40px; + margin-right: 20px; + margin-left: 0px; + margin-top: 12px; } +/* Tab list elements */ -/* Navbar brand text */ -.navbar-brand span { - box-sizing: border-box; +.nav-link { color: rgba(255, 255, 255, 0.7); - color-scheme: dark; - cursor: auto; - display: inline; - font-size: 21.25px; - font-weight: 400; height: auto; - line-height: 31.875px; - text-align: start; - text-underline-offset: 3px; - text-wrap-mode: nowrap; - white-space-collapse: collapse; - width: auto; + font-family: Roboto; + font-size: 15px; +} + +/* Emphasise active tab */ + +.navbar-nav .nav-link.active { + color: rgba(255, 255, 255, 0.7); +} + +/* Target tab lists on hover */ + +.nav-link:hover { + color: rgba(209, 197, 226, 0.8); +} + +/* App version */ + +.app-version { + font-size: 12.5px; + color: rgba(255, 255, 255, 0.3); + position: fixed; + top: 60px; + right: 20px; + font-family: Roboto, Arial, Helvetica, sans-serif; } + +/* ---- Progress bar -------------------------------------------------------- */ + + /* Data upload progress bar */ span.btn.btn-default.btn-file { fill: #004225 !important; @@ -37,60 +123,24 @@ span.btn.btn-default.btn-file { background-color: #004225 !important; } -/* Navbar container */ -.navbar { - background-color: #004225 !important; - --bs-navbar-active-color: rgb(209, 197, 226, 0.8); /* active tab */ - /* --bs-nav-link-color: rgba(255, 255, 255, 0.7); */ - color: rgba(255, 255, 255, 0.7); - border-bottom: 2px solid #13b955; - align-items: center; - box-sizing: border-box; - color-scheme: light; - column-gap: 0px; - flex-direction: column; - display: flex; - flex-wrap: nowrap; - font-size: 17px; - font-weight: 400; height: 83.78125px; - justify-content: flex-start; - line-height: 25.5px; - padding-bottom: 20.4px; - padding-left: 17px; - padding-right: 17px; - padding-top: 20.4px; - position: relative; - text-align: start; - width: 1920px; -} -/* Highlight colour on hover */ -.navbar-nav { - --bs-nav-link-color: rgba(255, 255, 255, 0.7); - --bs-nav-link-hover-color: rgba(209, 197, 226, 0.8); -} +/* ---- Radio Buttons ------------------------------------------------------- */ -/* Panel headers or section titles */ -h1, h2, h3 { - color:rgb(68, 68, 68); -} -/* Set table of content's font-size to 15px */ -h6 { - font-size: 15px; -} - -/* Radio button labels */ -#wrangle_data-wrangle, #ipc_check-ipccheck, #plausible-method, -#prevalence-amn_method_survey, #prevalence-amn_method_screening, +/* Radio button labels */ +#wrangle_data-wrangle, +#ipc_check-ipccheck, +#plausible-method, +#prevalence-amn_method_survey, +#prevalence-amn_method_screening, #prevalence-source label { font-size: 14px; } /* Buttons */ .btn-primary { - background-color: #004225 !important; - border-color: #004225 !important; + background-color: #004225 !important; + border-color: #004225 !important; } .btn-primary:hover { @@ -99,21 +149,24 @@ h6 { } /* Radio buttons */ -.form-check-input:checked, -.shiny-input-container .checkbox input:checked, -.shiny-input-container .checkbox-inline input:checked, -.shiny-input-container .radio input:checked, +.form-check-input:checked, +.shiny-input-container .checkbox input:checked, +.shiny-input-container .checkbox-inline input:checked, +.shiny-input-container .radio input:checked, .shiny-input-container .radio-inline input:checked { - background-color:#004225; - border-color:#004225 + background-color: #004225; + border-color: #004225 } -/* Pagination */ -.page-link.active, -.active > .page-link { - z-index: 3; - color: var(--bs-pagination-active-color); - background-color:#004225; - border-color:#004225; -} +/* ---- Pagination ---------------------------------------------------------- */ + +/* Pagination of table under view data */ + +.page-link.active, +.active>.page-link { + z-index: 3; + color: var(--bs-pagination-active-color); + background-color: #004225; + border-color: #004225; +} \ No newline at end of file diff --git a/man/mwanaApp-package.Rd b/man/mwanaApp-package.Rd index 180f19b..e514e8e 100644 --- a/man/mwanaApp-package.Rd +++ b/man/mwanaApp-package.Rd @@ -6,7 +6,7 @@ \alias{mwanaApp-package} \title{mwanaApp: mwana GUI} \description{ -A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and prevalence estimation. +A seamless graphical interface to the mwana R package for data wrangling, plausibility checks, and prevalence estimation of wasting. } \seealso{ Useful links: