Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
014ff57
Fix warning from devtools::check()
aureol-le-rocher Mar 2, 2026
34933f5
Merge remote-tracking branch 'origin/master' into fix/devtools-checks
aureol-le-rocher Mar 2, 2026
09e8c60
Convert non-ASCII characters to ASCII-compatible Unicode escapes
aureol-le-rocher Mar 2, 2026
9c96652
declare missing import
aureol-le-rocher Mar 2, 2026
f52ff57
add documentation for data_perm and template_data_geographics dataset
aureol-le-rocher Mar 2, 2026
cdba807
Declare write.csv() in the import
aureol-le-rocher Mar 2, 2026
6ceb065
Fix import statement in rdcAVS-package.R
aureol-le-rocher Mar 2, 2026
0305458
Declare write.csv() in the import
aureol-le-rocher Mar 2, 2026
070b3ec
Declare write.csv() in the import
aureol-le-rocher Mar 2, 2026
052d10e
Replace non-ASCII characters with ASCII equivalents (2)
aureol-le-rocher Mar 2, 2026
ee803fe
resolve date parsing failure for timestamp format
aureol-le-rocher Mar 4, 2026
074f0fc
shiny.fluent task button functions with busy/ready state management
aureol-le-rocher Mar 4, 2026
da863e5
document shiny.fluent task button functions
aureol-le-rocher Mar 4, 2026
cd11b29
load task button JS and CSS globally in UI head
aureol-le-rocher Mar 4, 2026
13099f8
Export shiny.fluent task button functions in the NAMESPACE
aureol-le-rocher Mar 4, 2026
421c06d
replace PrimaryButton with taskButton
aureol-le-rocher Mar 4, 2026
2833418
integrate withTaskButton for busy/ready state management
aureol-le-rocher Mar 4, 2026
5d500f2
Add a brief description of task_buttons( JS and CSS) function in the …
aureol-le-rocher Mar 4, 2026
4a7cedb
bump app version
aureol-le-rocher Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: rdcAVS
Title: SIA Campaign Builder for DRC
Version: 0.0.0.9008
Version: 0.0.0.9009
Authors@R:
person("Mervin Keith", "Cuadera", , "xrg9@cdc.com", role = c("aut", "cre"))
Description: This app assists in creating campaigns and setting permissions for
Expand All @@ -22,22 +22,26 @@ Imports:
foreach,
fs,
future,
ggplot2,
ggpubr,
googledrive,
googlesheets4,
httr,
lubridate,
openxlsx,
pkgload,
progressr,
purrr,
rappdirs,
readr,
scales,
shiny,
shiny.fluent,
shinyFiles,
shinyjs,
stringr,
tidyr
tidyr,
utils
Suggests:
stringi
URL: https://mcuadera.github.io/rdcAVS/
11 changes: 11 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ export(fluent_card)
export(get_campaign_progress)
export(get_sheet_info)
export(icon_btn)
export(taskButton)
export(task_button_css)
export(task_button_js)
export(withTaskButton)
import(bsicons)
import(bslib)
import(dplyr)
import(ggplot2)
import(googledrive)
import(readr)
import(shiny)
Expand Down Expand Up @@ -40,13 +45,18 @@ importFrom(googlesheets4,range_write)
importFrom(httr,POST)
importFrom(httr,add_headers)
importFrom(lubridate,as_date)
importFrom(openxlsx,loadWorkbook)
importFrom(openxlsx,saveWorkbook)
importFrom(openxlsx,writeData)
importFrom(progressr,handlers)
importFrom(progressr,progressor)
importFrom(progressr,with_progress)
importFrom(purrr,map)
importFrom(purrr,pwalk)
importFrom(purrr,walk)
importFrom(rappdirs,user_data_dir)
importFrom(readr,type_convert)
importFrom(scales,percent)
importFrom(shiny.fluent,DatePicker.shinyInput)
importFrom(shiny.fluent,DefaultButton.shinyInput)
importFrom(shiny.fluent,Dropdown.shinyInput)
Expand All @@ -65,3 +75,4 @@ importFrom(shinyjs,show)
importFrom(shinyjs,toggle)
importFrom(shinyjs,useShinyjs)
importFrom(tidyr,pivot_longer)
importFrom(utils,write.csv)
116 changes: 5 additions & 111 deletions R/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#' tabs that creates a campaign, add geographic information, and set Google Drive
#' permissions. Creating a campaign outputs a folder prefixed with "CAMPAGNE_",
#' which contains a hierarchical structure, going from the largest geographic unit (Province)
#' to the lowest geographic unit (Zone de Sant\u00e9). Within the Zone de Sant\u00e9 folder, contains
#' to the lowest geographic unit (Zone de Santé). Within the Zone de Santé folder, contains
#' a template file.
#'
#' @details
Expand All @@ -45,115 +45,9 @@ campagneApp <- function() {
bootswatch = "yeti"
),
tags$head(
tags$style(HTML("
.notification-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 99998;
display: none;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}

.notification-overlay.show {
display: block;
opacity: 1;
}

#shiny-notification-panel {
position: fixed;
top: 50% !important;
left: 50% !important;
right: auto !important;
bottom: auto !important;
transform: translate(-50%, -50%) !important;
width: auto;
max-width: 500px;
z-index: 99999;
}

@keyframes slideDown {
from {
opacity: 0;
transform: translate(-50%, -60%);
}
to {
opacity: 1;
transform: translate(-50%, -50%);
}
}

@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}

.shiny-notification {
background-color: white;
border: none;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
padding: 40px 30px 30px 30px;
text-align: center;
font-size: 16px;
color: #333;
opacity: 1 !important;
min-width: 350px;
position: relative;
animation: slideDown 0.4s ease-out;
}

.shiny-notification::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
border-radius: 12px 12px 0 0;
background: linear-gradient(90deg, #3498db, #2980b9);
}

.shiny-notification-message::before {
background: linear-gradient(90deg, #3498db, #2980b9);
}

.shiny-notification-warning::before {
background: linear-gradient(90deg, #f39c12, #e67e22);
}

.shiny-notification-error::before {
background: linear-gradient(90deg, #e74c3c, #c0392b);
}

.shiny-notification.success-notification::before {
background: linear-gradient(90deg, #27ae60, #229954);
}

.shiny-notification-message,
.shiny-notification-warning,
.shiny-notification-error {
background-color: white;
border-left: none;
}

.shiny-notification .message-text {
color: #555;
line-height: 1.6;
margin-top: 8px;
font-size: 15px;
}"
)
)
),
tags$style(HTML(task_button_css)),
tags$script(HTML(task_button_js))
),
useShinyjs(),
bslib::input_dark_mode(id = "mode"),
downloadButton("download_template", label = "", style = "visibility:hidden;"),
Expand All @@ -178,7 +72,7 @@ campagneApp <- function() {
style = "display:flex; align-items:center; gap:10px; flex-wrap:nowrap;",
imageOutput("drc_cdc_logo", height = "60px"),
h5(
"Portail de création des masques de saisie des campagnes de vaccination en RDC",
"Portail de cr\u00e9ation des masques de saisie des campagnes de vaccination en RDC",
style = "
margin:0;
font-weight:500;
Expand Down
2 changes: 1 addition & 1 deletion R/compile_masques.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ compile_masques <- function(campaign_name) {
})

# Compile all templates for one sheet at a time
withProgress(message = "Compilation des données dans: ",
withProgress(message = "Compilation des donn\u00e9es dans: ",
{
n <- length(tab_names)
for (i in 1:n) {
Expand Down
4 changes: 2 additions & 2 deletions R/compile_masques_antenne.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ compile_masques_antenne <- function(campaign_name) {

# Compile masques
# Compile all templates for one sheet at a time
withProgress(message = "Compilation des données dans: ",
withProgress(message = "Compilation des donn\u00e9es dans: ",
{
n <- length(tab_names)
for (j in 1:n) {
Expand All @@ -67,7 +67,7 @@ compile_masques_antenne <- function(campaign_name) {
}
})
}
showNotification("Masques au niveau des antennes compilés", type = "message")
showNotification("Masques au niveau des antennes compil\u00e9es", type = "message")

return(invisible())
}
2 changes: 1 addition & 1 deletion R/compile_masques_national.R
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ compile_masques_national <- function(campaign_name) {
showNotification("Autorisations requises obtenues.", type = "message")

# Compile all templates for one sheet at a time
withProgress(message = "Compilation des données dans: ",
withProgress(message = "Compilation des donn\u00e9es dans: ",
{
n <- length(tab_names)
for (i in 1:n) {
Expand Down
4 changes: 2 additions & 2 deletions R/compile_masques_province.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ compile_masques_province <- function(campaign_name) {

# Compile masques
# Compile all templates for one sheet at a time
withProgress(message = "Compilation des données dans: ",
withProgress(message = "Compilation des donn\u00e9es dans: ",
{
n <- length(tab_names)
for (j in 1:n) {
Expand All @@ -58,7 +58,7 @@ compile_masques_province <- function(campaign_name) {
}
})
}
showNotification("Masques au niveau des provinces compilés", type = "message")
showNotification("Masques au niveau des provinces compil\u00e9es", type = "message")

return(invisible())
}
2 changes: 1 addition & 1 deletion R/create_campaign_progress_heatmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ create_campaign_progress_heatmap <- function(summary) {
ggplot2::ylab("Aire De Sante") +
ggplot2::xlab("") +
ggplot2::labs(subtitle = paste0("Objectif: Jour 1: 40%, Jour 2: 70%, Jour 3: 100%, Jour 4: 100%\n",
"A risque si à moins de 5 % et en échec si à plus de 5 % de l'objectif")) +
"A risque si \u00e0 moins de 5 % et en \u00e9chec si \u00e0 plus de 5 % de l'objectif")) +
ggplot2::theme(axis.text.x = ggplot2::element_text(size = 14),
axis.text.y = ggplot2::element_text(size = 14),
axis.title.x = ggplot2::element_text(size = 14, face = "bold"),
Expand Down
2 changes: 1 addition & 1 deletion R/create_daily_campaign_progress_heatmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ create_daily_campaign_progress_heatmap <- function(summary) {
ggplot2::ylab("Aire De Sante") +
ggplot2::xlab("") +
ggplot2::labs(subtitle = paste0("Objectif: Jour 1: 40%, Jour 2-3: 30%, Jour 4: 100%\n",
"A risque si à moins de 5 % et en échec si à plus de 5 % de l'objectif")) +
"A risque si \u00e0 moins de 5 % et en \u00e9echec si \u00e0 plus de 5 % de l'objectif")) +
ggplot2::theme(axis.text.x = ggplot2::element_text(size = 14),
axis.text.y = ggplot2::element_text(size = 14),
axis.title.x = ggplot2::element_text(size = 14, face = "bold"),
Expand Down
14 changes: 7 additions & 7 deletions R/create_recovery_heatmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ create_recovery_heatmap <- function(summary) {
cat_0_11 = case_when(
recovery_0_11 == 0 & recovery_0_11_cumulative > 0 & jour %in% c("Jour 2", "Jour 3", "Jour 4") ~ "Aucun changement",
recovery_0_11_cumulative > 0 ~ "Bien",
.default = "Zéro"
.default = "Z\u00e9ro"
),
cat_12_23 = case_when(
recovery_12_23 == 0 & recovery_12_23_cumulative > 0 & jour %in% c("Jour 2", "Jour 3", "Jour 4") ~ "Aucun changement",
recovery_12_23_cumulative > 0 ~ "Bien",
.default = "Zéro"
.default = "Z\u00e9ro"

),
cat_24_59 = case_when(
recovery_24_59 == 0 & recovery_24_59_cumulative > 0 & jour %in% c("Jour 2", "Jour 3", "Jour 4") ~ "Aucun changement",
recovery_24_59_cumulative > 0 ~ "Bien",
.default = "Zéro"
.default = "Z\u00e9ro"
)
) |>
dplyr::mutate(across(all_of(c("cat_0_11", "cat_12_23", "cat_24_59")),
\(x) factor(x, levels = c("Bien", "Aucun changement", "Zéro"))))
\(x) factor(x, levels = c("Bien", "Aucun changement", "Z\u00e9ro"))))

plot_0_11 <- ggplot2::ggplot(plot_data) +
ggplot2::geom_tile(ggplot2::aes(y =aire_de_sante, x = jour, fill = cat_0_11), show.legend = TRUE) +
ggplot2::scale_fill_manual(values = c("Zéro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
ggplot2::scale_fill_manual(values = c("Z\u00e9ro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
name = "Statut") +
ggplot2::geom_text(ggplot2::aes(y = aire_de_sante, x = jour, label = recovery_0_11_cumulative), size = 8) +
ggplot2::theme_void() +
Expand All @@ -42,7 +42,7 @@ create_recovery_heatmap <- function(summary) {

plot_12_23 <- ggplot2::ggplot(plot_data) +
ggplot2::geom_tile(ggplot2::aes(y =aire_de_sante, x = jour, fill = cat_12_23), show.legend = TRUE) +
ggplot2::scale_fill_manual(values = c("Zéro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
ggplot2::scale_fill_manual(values = c("Z\u00e9ro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
name = "Statut") +
ggplot2::geom_text(ggplot2::aes(y = aire_de_sante, x = jour, label = recovery_12_23_cumulative), size = 8) +
ggplot2::theme_void() +
Expand All @@ -60,7 +60,7 @@ create_recovery_heatmap <- function(summary) {

plot_24_59 <- ggplot2::ggplot(plot_data) +
ggplot2::geom_tile(ggplot2::aes(y =aire_de_sante, x = jour, fill = cat_24_59), show.legend = TRUE) +
ggplot2::scale_fill_manual(values = c("Zéro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
ggplot2::scale_fill_manual(values = c("Z\u00e9ro" = "lightgrey", "Bien" = "#006B3E", "Aucun changement" = "#338F65"),
name = "Statut") +
ggplot2::geom_text(ggplot2::aes(y = aire_de_sante, x = jour, label = recovery_24_59_cumulative), size = 8) +
ggplot2::theme_void() +
Expand Down
12 changes: 6 additions & 6 deletions R/create_urban_rural_heatmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ create_urban_rural_heatmap <- function(summary) {
cat_rural = case_when(
between(avg_vax_rural, 1, 99) ~ "Objectif Non Atteint",
avg_vax_rural >= 100 ~ "Bien",
.default = "Zéro"
.default = "Z\u00e9ro"
),
cat_rural = factor(cat_rural, levels = c("Bien", "Objectif Non Atteint", "Zéro")),
cat_rural = factor(cat_rural, levels = c("Bien", "Objectif Non Atteint", "Z\u00e9ro")),
cat_urban = case_when(
between(avg_vax_urban, 1, 199) ~ "Objectif Non Atteint",
avg_vax_urban >= 200 ~ "Bien",
.default = "Zéro"
.default = "Z\u00e9ro"
),
cat_urban = factor(cat_urban, levels = c("Bien", "Objectif Non Atteint", "Zéro")),
cat_urban = factor(cat_urban, levels = c("Bien", "Objectif Non Atteint", "Z\u00e9ro")),
avg_vax_rural = round(avg_vax_rural),
avg_vax_urban = round(avg_vax_urban)
) |>
mutate(across(any_of(c("avg_vax_urban", "avg_vax_rural")), \(x) ifelse(is.na(x), 0, x)))

rural_plot <- ggplot2::ggplot(data = plot_data) +
ggplot2::geom_tile(ggplot2::aes(y =aire_de_sante, x = jour, fill = cat_rural), show.legend = TRUE) +
ggplot2::scale_fill_manual(values = c("Zéro" = "lightgrey", "Bien" = "#006B3E", "Objectif Non Atteint" = "#ED2938"),
ggplot2::scale_fill_manual(values = c("Z\u00e9ro" = "lightgrey", "Bien" = "#006B3E", "Objectif Non Atteint" = "#ED2938"),
name = "Statut") +
ggplot2::geom_text(ggplot2::aes(y = aire_de_sante, x = jour, label = avg_vax_rural), size = 8) +
ggplot2::theme_void() +
Expand All @@ -40,7 +40,7 @@ create_urban_rural_heatmap <- function(summary) {

urban_plot <- ggplot2::ggplot(data = plot_data) +
ggplot2::geom_tile(ggplot2::aes(y =aire_de_sante, x = jour, fill = cat_urban), show.legend = TRUE) +
ggplot2::scale_fill_manual(values = c("Zéro" = "lightgrey", "Bien" = "#006B3E", "Objectif Non Atteint" = "#ED2938"),
ggplot2::scale_fill_manual(values = c("Z\u00e9ro" = "lightgrey", "Bien" = "#006B3E", "Objectif Non Atteint" = "#ED2938"),
name = "Statut") +
ggplot2::geom_text(ggplot2::aes(y = aire_de_sante, x = jour, label = avg_vax_urban), size = 8) +
ggplot2::theme_void() +
Expand Down
Loading