Skip to content

Commit

Permalink
Add sidebar and function args. (#285)
Browse files Browse the repository at this point in the history
Add optional arguments to allow users to customize the UI and/or server of the resulting Shiny app. This will allow users to add logging functionality, for example.

tests/testthat/apps/logging/app.R contains an app that creates a logfile, as a proof of concept.
  • Loading branch information
jonthegeek authored Oct 16, 2024
1 parent 0ef27a0 commit af109b8
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 11 deletions.
5 changes: 5 additions & 0 deletions R/aaa-shared.R
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
#' about the participant, and `metric_data` should be a named list of
#' data.frames, each of which contains information related to the named
#' metric.
#' @param fnServer `function` A Shiny server function that takes arguments
#' `input`, `output`, and `session`. This function will be called at the start
#' of the main app server function.
#' @param id `character` The id for this module, widget, or other element.
#' @param intKRIColorCount `integer` A named vector of counts by color.
#' @param intNParticipants `integer` The number of unique participants
Expand Down Expand Up @@ -96,6 +99,8 @@
#' @param strText `character` Text to display.
#' @param strTitle `character` A title to display for the overall app.
#' @param strValue `character` The value of a field.
#' @param tagListSidebar `taglist` An optional [htmltools::tagList()] of
#' additional elements to add to the top of the app sidebar.
#'
#' @name shared-params
#' @keywords internal
Expand Down
8 changes: 7 additions & 1 deletion R/gsmApp_Server.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ gsmApp_Server <- function(
dfMetrics,
dfBounds,
dfAnalyticsInput,
fnFetchParticipantData
fnFetchParticipantData,
fnServer = NULL
) {
# Force evaluation of everything before factory is constructed to avoid
# strange effects from lazy evaluation. See
Expand All @@ -20,7 +21,12 @@ gsmApp_Server <- function(
force(dfBounds)
force(dfAnalyticsInput)
force(fnFetchParticipantData)
force(fnServer)
function(input, output, session) {
if (!is.null(fnServer)) {
fnServer(input, output, session)
}

# Inputs ----
## Initialize ----
dfAnalyticsInput_Unique <- dfAnalyticsInput %>%
Expand Down
11 changes: 9 additions & 2 deletions R/gsmApp_UI.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ gsmApp_UI <- function(
dfMetrics,
dfGroups,
intNParticipants,
strTitle = "GSM Deep Dive"
strTitle = "GSM Deep Dive",
tagListSidebar = NULL
) {
# Transform data for use in lower-level functions. ----
lStudy <- make_lStudy(dfGroups, dfResults)
Expand All @@ -23,6 +24,12 @@ gsmApp_UI <- function(
theme = bslib::bs_theme(version = 5),
fillable = FALSE,
!!!out_MainTabs(dfResults = dfResults, chrMetrics = chrMetrics),
sidebar = out_Sidebar(lStudy, chrMetrics, chrSites, intNParticipants)
sidebar = out_Sidebar(
lStudy,
chrMetrics,
chrSites,
intNParticipants,
tagListSidebar
)
)
}
9 changes: 8 additions & 1 deletion R/out_Sidebar.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
#' @returns A [bslib::sidebar()] with study information, inputs, and the
#' stylesheets and dependencies required to display the app.
#' @keywords internal
out_Sidebar <- function(lStudy, chrMetrics, chrSites, intNParticipants) {
out_Sidebar <- function(
lStudy,
chrMetrics,
chrSites,
intNParticipants,
tagListSidebar = NULL
) {
bslib::sidebar(
width = 400,
id = "sidebar",
tagListSidebar,
shinyjs::useShinyjs(),
htmlDependency_Default_Stylesheet(),
htmlDependency_HighlightTableRow(),
Expand Down
11 changes: 8 additions & 3 deletions R/run_gsm_app.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ run_gsm_app <- function(
dfBounds,
dfAnalyticsInput,
fnFetchParticipantData,
strTitle = "GSM Deep Dive") {
strTitle = "GSM Deep Dive",
tagListSidebar = NULL,
fnServer = NULL
) {
# There's no point launching the app if the data won't work.
dfResults <- validate_dfResults(dfResults)
dfGroups <- validate_dfGroups(dfGroups)
Expand All @@ -42,15 +45,17 @@ run_gsm_app <- function(
dfMetrics = dfMetrics,
dfGroups = dfGroups,
intNParticipants = length(unique(dfAnalyticsInput$SubjectID)),
strTitle = strTitle
strTitle = strTitle,
tagListSidebar = tagListSidebar
),
server = gsmApp_Server(
dfResults = dfResults,
dfGroups = dfGroups,
dfMetrics = dfMetrics,
dfBounds = dfBounds,
dfAnalyticsInput = dfAnalyticsInput,
fnFetchParticipantData = fnFetchParticipantData
fnFetchParticipantData = fnFetchParticipantData,
fnServer = fnServer
)
)
}
Expand Down
7 changes: 6 additions & 1 deletion man/gsmApp_Server.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion man/gsmApp_UI.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion man/out_Sidebar.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion man/run_gsm_app.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions man/shared-params.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions tests/testthat/apps/logging/app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Launch the ShinyApp (Do not remove this comment)
# To deploy, run: rsconnect::deployApp()
# Or use the blue button on top of this file

if (
isTRUE(as.logical(Sys.getenv("TESTTHAT_IS_CHECKING", "false"))) ||
isTRUE(as.logical(Sys.getenv("R_COVR", "false")))
) {
library("gsm.app")
} else {
pkgload::load_all(here::here())
}

group_subset <- c(
"0X001",
"0X021",
"0X103",
"0X159",
"0X161"
)

sample_dfResults_subset <- gsm.app::sample_dfResults %>%
dplyr::filter(GroupID %in% group_subset)
sample_dfAnalyticsInput_subset <- gsm.app::sample_dfAnalyticsInput %>%
dplyr::filter(GroupID %in% group_subset)
sample_dfGroups_subset <- gsm.app::sample_dfGroups %>%
dplyr::filter(
GroupLevel != "Site" | (GroupLevel == "Site" & GroupID %in% group_subset)
)

library(shiny.telemetry)

log_path <- here::here("tests", "testthat", "apps", "logging", "logfile.txt")

telemetry <- shiny.telemetry::Telemetry$new(
data_storage = shiny.telemetry::DataStorageLogFile$new(log_path)
)

gsm.app::run_gsm_app(
dfResults = sample_dfResults_subset,
dfGroups = sample_dfGroups_subset,
dfMetrics = gsm.app::sample_dfMetrics,
dfBounds = gsm.app::sample_dfBounds,
dfAnalyticsInput = sample_dfAnalyticsInput_subset,
fnFetchParticipantData = gsm.app::sample_FetchParticipantData,
tagListSidebar = shiny.telemetry::use_telemetry(),
fnServer = function(input, output, session) {
telemetry$start_session()
}
)
21 changes: 21 additions & 0 deletions tests/testthat/test-gsmApp_Server.R
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,24 @@ test_that("gsmApp_Server triggers reset", {
}
)
})

test_that("gsmApp_Server executes optional server functions", {
server <- gsmApp_Server(
dfResults = sample_dfResults,
dfGroups = sample_dfGroups,
dfMetrics = sample_dfMetrics,
dfBounds = sample_dfBounds,
dfAnalyticsInput = sample_dfAnalyticsInput,
fnFetchParticipantData = sample_FetchParticipantData,
fnServer = function(input, output, session) {
rctv_testVal <<- reactiveVal("testing")
}
)
testServer(
server,
{
expect_s3_class(rctv_testVal, "reactiveVal")
expect_equal(rctv_testVal(), "testing")
}
)
})

0 comments on commit af109b8

Please sign in to comment.