From bc676f8b9b5529615d29b1b7fabbc8880354a64b Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Thu, 20 Aug 2026 15:26:56 -0400 Subject: [PATCH 1/5] Prepare safetyGraphics 2.2.0 for resubmission to CRAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit safetyGraphics was archived from CRAN on 2026-03-25 for requiring the archived package Tendril, via its dependency on safetyCharts. safetyCharts 0.5.0 drops Tendril, but safetyGraphics does not simply follow: the tree has 27 unreleased commits sitting under the same version number CRAN archived, and R CMD check --as-cran refuses it outright. - Bump 2.1.1 -> 2.2.0. CRAN reports "Insufficient package version (submitted: 2.1.1, existing: 2.1.1)" otherwise; the incoming check requires a version strictly greater than the highest one in the CRAN archive. - Drop safetyProfile from Suggests. It has never been on CRAN — no package page, no archive entry — so the check fails with "Package suggested but not available". The patient profile tab is unchanged for anyone who has safetyProfile loaded; it now resolves through getExportedValue() behind the same isNamespaceLoaded() guard the other optional packages use. - Declare cli in Imports. cli::cli_alert_info() was called by the profile tab without cli appearing anywhere in DESCRIPTION, which is a check WARNING. - Document the config argument of homeTab(), safetyGraphicsServer() and safetyGraphicsUI(), which was a check WARNING. - Fix the getChartStatus() example, which was a check ERROR: it called map(), distinct(), filter() and others unqualified, none of which safetyGraphics exports. - Regenerate NAMESPACE. The checked-in copy had drifted from the roxygen comments, importing set_names from purrr rather than rlang. - Drop LazyData: true; there is no data/ directory. - Update nine redirected URLs in the Technical FAQ vignette. - Ignore R/_disable_autoload.R at build time; a leading underscore is not a valid R file name and R CMD build was excluding it with a warning. - Raise the safetyCharts floor to >= 0.5.0, the version that drops Tendril. - Replace cran-comments.md, which claimed "no ERRORs, WARNINGs or NOTEs" on R 4.1.0 and rhub environments that no longer exist. - NEWS.md entry for 2.2.0. Worker: W0084 --- .Rbuildignore | 1 + DESCRIPTION | 9 ++-- NAMESPACE | 4 +- NEWS.md | 30 +++++++++++++ R/getChartStatus.R | 76 +++++++++++++++----------------- R/mod_homeTab.R | 3 ++ R/mod_profileTab.R | 84 ++++++++++++++++++++++++++++-------- R/mod_safetyGraphicsServer.R | 1 + R/mod_safetyGraphicsUI.R | 1 + cran-comments.md | 27 +++++++++--- man/SafetyGraphics.Rd | 23 ++++++++++ man/detectStandard.Rd | 2 +- man/evaluateStandard.Rd | 2 +- man/generateMappingList.Rd | 2 +- man/getChartStatus.Rd | 67 +++++++++++++++++++--------- man/hasColumn.Rd | 2 +- man/hasField.Rd | 2 +- man/homeTab.Rd | 4 ++ man/profileTab.Rd | 15 ++++--- man/profileTabUI.Rd | 14 +++++- man/safetyGraphicsServer.Rd | 2 + man/safetyGraphicsUI.Rd | 2 + man/setMappingListValue.Rd | 2 +- man/textKeysToList.Rd | 2 +- vignettes/TechnicalFAQ.Rmd | 14 +++--- 25 files changed, 278 insertions(+), 113 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index 1429c347..65604bd2 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -21,3 +21,4 @@ ^CRAN-SUBMISSION$ +^R/_disable_autoload\.R$ diff --git a/DESCRIPTION b/DESCRIPTION index a278bb58..04fb297d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: safetyGraphics Title: Interactive Graphics for Monitoring Clinical Trial Safety -Version: 2.1.1 +Version: 2.2.0 Authors@R: c( person("Jeremy", "Wildfire", email = "jwildfire@gmail.com", role = c("cre","aut")), person("Becca", "Krouse", role="aut"), @@ -15,13 +15,11 @@ BugReports: https://github.com/SafetyGraphics/safetyGraphics/issues Depends: R (>= 4.0) License: MIT + file LICENSE Encoding: UTF-8 -LazyData: true -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 Suggests: ggplot2 (>= 3.3.0), knitr (>= 1.34), rmarkdown (>= 2.10), - safetyProfile, shinydashboard (>= 0.7.1), shinytest (>= 1.5.0), testthat (>= 3.0.4), @@ -30,6 +28,7 @@ Suggests: shinybusy (>= 0.2.2), shinyWidgets (>= 0.6.1) Imports: + cli (>= 3.0.0), dplyr (>= 1.0.0), DT (>= 0.19), datamods (>= 1.1.5), @@ -40,7 +39,7 @@ Imports: rclipboard (>= 0.1.3), rlang (>= 0.4.11), safetyData (>= 1.0.0), - safetyCharts (>= 0.3), + safetyCharts (>= 0.5.0), shiny (>= 1.6.0), shinyjs (>= 2.0.0), sortable (>= 0.4.4), diff --git a/NAMESPACE b/NAMESPACE index 725ee710..16b423b4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -59,12 +59,12 @@ import(shiny) import(yaml) importFrom(DT,renderDT) importFrom(magrittr,"%>%") +importFrom(purrr,imap) importFrom(purrr,keep) importFrom(purrr,map) importFrom(purrr,map2) -importFrom(purrr,map_lgl) -importFrom(purrr,set_names) importFrom(rlang,.data) +importFrom(rlang,set_names) importFrom(shiny,dataTableOutput) importFrom(shiny,renderDataTable) importFrom(shinyjs,addClass) diff --git a/NEWS.md b/NEWS.md index 606f5024..f516e6a5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,33 @@ +# safetyGraphics v2.2.0 (Upcoming) + +This is the first release since v2.1.1 and is the release that returns safetyGraphics to CRAN. + +## Back on CRAN + +- safetyGraphics was archived from CRAN on 2026-03-25 with the notice "requires archived package 'Tendril'". It never used `Tendril` itself; it was archived because it imports safetyCharts, which did. +- safetyCharts v0.5.0 removes `Tendril`, so no code change was needed here for the archival itself. The changes below are what the resubmission required. +- The version had to move off 2.1.1. CRAN will not accept a version equal to one already in the archive, and 2.1.1 is the version that was archived. Everything listed under "New since the v2.1.1 CRAN release" has been sitting unreleased under that same number. + +## New since the v2.1.1 CRAN release + +- Optional patient profile tab, backed by the `safetyProfile` package. Clicking a participant id in the header opens the profile; the tab is hidden when `safetyProfile` is not loaded. +- New chart status framework. `getChartStatus()` reports whether a chart has every data mapping it needs, and the charts navigation shows that status in the UI. +- App-level settings support, and `launchBrowser` handling, in `safetyGraphicsApp()`. +- Chart modules refactored to simplify the reactive flow, with chart event listeners added to the widgets. +- `generateMappingList()` now works with `tbl_df`-classed data frames. +- Stray `print()` calls removed from the app. +- Utility source files renamed with a `util-` prefix. + +## Packaging changes for the CRAN resubmission + +- `safetyProfile` has been removed from `Suggests`. It is not on CRAN and never has been, so declaring it made the package uncheckable by CRAN. The patient profile tab still works exactly as before for anyone who has installed and loaded `safetyProfile`; it is now reached through `getExportedValue()` behind the same `isNamespaceLoaded()` guard the other optional packages use. Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`. +- `cli` added to `Imports`. `cli::cli_alert_info()` was already being called by the profile tab without being declared anywhere. +- `LazyData: true` removed. The package has no `data/` directory, so the field was inert. +- The `config` argument is now documented for `homeTab()`, `safetyGraphicsServer()` and `safetyGraphicsUI()`. +- The `getChartStatus()` example has been fixed. It called `map()`, `distinct()`, `filter()` and others without qualifying them, so it failed whenever it was run outside an interactive session with the tidyverse attached. +- `NAMESPACE` regenerated. The checked-in copy had drifted from the roxygen comments: it imported `set_names` from `purrr` rather than `rlang`, and `map_lgl` rather than `imap`. +- Nine external links in the Technical FAQ vignette updated to the addresses they now redirect to. + # safetyGraphics v2.1.1 Resolves a bug that was causing unexpected data filters on initial load. diff --git a/R/getChartStatus.R b/R/getChartStatus.R index 6037729e..041c5f2a 100644 --- a/R/getChartStatus.R +++ b/R/getChartStatus.R @@ -15,53 +15,47 @@ #' #' @examples #' sample_chart <- list( -#' domains=c("aes","dm"), -#' dataSpec=list( -#' aes=c("id_col","custom_col"), -#' dm=c("id_col","test_col") +#' domains = c("aes", "dm"), +#' dataSpec = list( +#' aes = c("id_col", "custom_col"), +#' dm = c("id_col", "test_col") #' ) #' ) -#' +#' #' sample_mapping <- data.frame( -#' domain=c("aes","aes","dm","dm"), -#' text_key=c("id_col","custom_col","id_col","test_col"), -#' current=c("myID","AEcol","myID","dmCol") +#' domain = c("aes", "aes", "dm", "dm"), +#' text_key = c("id_col", "custom_col", "id_col", "test_col"), +#' current = c("myID", "AEcol", "myID", "dmCol") #' ) -#' -#' check <- safetyGraphics:::getChartStatus(chart=sample_chart, mapping=sample_mapping) -#' # check$status=TRUE #' -#' # Add data spec to each chart. -#' charts <- makeChartConfig() %>% -#' map(function(chart) { -#' chart$mapping <- chart$domain %>% -#' map_dfr(function(domain) { -#' do.call( -#' `::`, -#' list( -#' 'safetyCharts', -#' paste0('meta_', domain) -#' ) -#' ) -#' }) %>% -#' distinct(domain, col_key, current = standard_adam) %>% -#' filter(!is.na(current)) %>% -#' select(domain, text_key = col_key, current) -#' -#' chart$dataSpec <- chart$domain %>% -#' map(function(domain) { -#' chart$mapping %>% -#' filter(.data$domain == !!domain) %>% -#' pull(text_key) %>% -#' unique() -#' }) %>% -#' set_names(chart$domain) -#' -#' chart -#' }) +#' check <- safetyGraphics:::getChartStatus( +#' chart = sample_chart, +#' mapping = sample_mapping +#' ) +#' # check$status = TRUE +#' +#' # Add a data spec to each chart, then check them all. +#' charts <- purrr::map(safetyGraphics::makeChartConfig(), function(chart) { +#' chart$mapping <- purrr::map_dfr(chart$domain, function(dom) { +#' getExportedValue("safetyCharts", paste0("meta_", dom)) +#' }) %>% +#' dplyr::distinct(domain, col_key, current = standard_adam) %>% +#' dplyr::filter(!is.na(current)) %>% +#' dplyr::select(domain, text_key = col_key, current) +#' +#' chart$dataSpec <- purrr::map(chart$domain, function(dom) { +#' chart$mapping %>% +#' dplyr::filter(domain == dom) %>% +#' dplyr::pull(text_key) %>% +#' unique() +#' }) %>% +#' rlang::set_names(chart$domain) +#' +#' chart +#' }) +#' +#' checks <- purrr::map(charts, ~ safetyGraphics:::getChartStatus(.x, .x$mapping)) #' -#' checks <- map(charts, ~getChartStatus(.x, .x$mapping)) -#' #' @importFrom purrr imap map #' @importFrom rlang set_names #' diff --git a/R/mod_homeTab.R b/R/mod_homeTab.R index d942bd4e..c5a5b0d2 100644 --- a/R/mod_homeTab.R +++ b/R/mod_homeTab.R @@ -17,6 +17,9 @@ homeTabUI <- function(id) { #' @param input mod input #' @param output mod output #' @param session mod session +#' @param config named list of app configuration options as returned by +#' \code{app_startup()}. `homeTab()` uses the `homeTabPath` and `hexPath` +#' elements. #' #' @export diff --git a/R/mod_profileTab.R b/R/mod_profileTab.R index 9c305358..c7d5f246 100644 --- a/R/mod_profileTab.R +++ b/R/mod_profileTab.R @@ -1,48 +1,76 @@ -#' @title UI for the profile module in safetyProfile::profile_ui +#' @title UI for the optional patient profile module +#' +#' @description +#' Renders the UI for the patient profile module supplied by the `safetyProfile` +#' package. `safetyProfile` is an optional add-on that is not distributed on +#' CRAN; when it is not loaded, this function returns `NULL` and the profile +#' tab is simply absent from the application. +#' +#' Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`, +#' then attach it with `library(safetyProfile)` before starting the app. #' #' @param id module id -#' +#' +#' @return The profile module UI when `safetyProfile` is available, otherwise +#' `NULL`. +#' #' @export -profileTabUI <- function(id){ +profileTabUI <- function(id){ ns <- NS(id) - - if(isNamespaceLoaded("safetyProfile")){ - profile_ui<-profile_ui(ns("profile")) - }else{ - profile_ui<-NULL + + if (!has_safety_profile()) { + return(NULL) } - return(profile_ui) + + profile_ui <- getExportedValue("safetyProfile", "profile_ui") + + return(profile_ui(ns("profile"))) } -#' @title Server for the patient profile in safetyProfile::profile_server +#' @title Server for the optional patient profile module +#' +#' @description +#' Starts the patient profile module supplied by the `safetyProfile` package. +#' `safetyProfile` is an optional add-on that is not distributed on CRAN; when +#' it is not loaded this function returns `NULL` without starting a module, +#' matching `profileTabUI()`, which renders nothing in that case. +#' +#' Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`, +#' then attach it with `library(safetyProfile)` before starting the app. #' #' @param input Shiny input object #' @param output Shiny output object #' @param session Shiny session object #' @param params reactive containing mapping and data -#' @param current_id reactive containing currently selected participant -#' -#' @return current_id +#' +#' @return A reactive containing the currently selected participant id, or +#' `NULL` when `safetyProfile` is not loaded. #' #' @import datamods #' @importFrom shinyjs show hide #' @importFrom shiny renderDataTable -#' +#' #' @export profileTab <- function(input, output, session, params) { - id <- safetyProfile::profile_server( + if (!has_safety_profile()) { + return(NULL) + } + + profile_server <- getExportedValue("safetyProfile", "profile_server") + + id <- profile_server( "profile", params ) observe({ shinyjs::html( - "pt-header", + "pt-header", id(), - asis=TRUE + asis=TRUE ) shinyjs::toggleClass( @@ -54,3 +82,25 @@ profileTab <- function(input, output, session, params) { return(id) } + + +#' Is the optional safetyProfile package available? +#' +#' @description +#' `safetyProfile` supplies the patient profile module. It is not distributed on +#' CRAN, so safetyGraphics treats it as strictly optional and every use of it is +#' routed through this check. +#' +#' Matches the test used for the other optional packages in this application +#' (`listviewer`, `shinybusy`, `shinyWidgets`): the feature appears once the +#' user has attached the package, not merely installed it. +#' +#' @return `TRUE` when the `safetyProfile` namespace is loaded, otherwise +#' `FALSE`. +#' +#' @keywords internal +#' @noRd + +has_safety_profile <- function() { + isNamespaceLoaded("safetyProfile") +} diff --git a/R/mod_safetyGraphicsServer.R b/R/mod_safetyGraphicsServer.R index dae54fa5..45e19c15 100644 --- a/R/mod_safetyGraphicsServer.R +++ b/R/mod_safetyGraphicsServer.R @@ -10,6 +10,7 @@ #' @param mapping current mapping #' @param charts list of charts to include in the app #' @param filterDomain domain used for the data/filter tab. Demographics ("`dm`") is used by default. Using a domain that is not one record per participant is not recommended. +#' @param config named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it. #' #' @import shiny #' @import dplyr diff --git a/R/mod_safetyGraphicsUI.R b/R/mod_safetyGraphicsUI.R index c6ff6051..069dfca5 100644 --- a/R/mod_safetyGraphicsUI.R +++ b/R/mod_safetyGraphicsUI.R @@ -6,6 +6,7 @@ #' @param domainData named list of data.frames to be loaded in to the app. #' @param mapping data.frame specifying the initial values for each data mapping. If no mapping is provided, the app will attempt to generate one via \code{detectStandard()} #' @param standards a list of information regarding data standards. Each list item should use the format returned by safetyGraphics::detectStandard. +#' @param config named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it. #' #' @importFrom shinyjs useShinyjs #' diff --git a/cran-comments.md b/cran-comments.md index cfe28e38..58ff4025 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,11 +1,26 @@ +## Resubmission of an archived package + +safetyGraphics was archived on CRAN on 2026-03-25 because it required the archived package 'Tendril'. It has never used 'Tendril' directly; it was archived because it imports 'safetyCharts', which did. + +'safetyCharts' has been updated to remove 'Tendril' and is back on CRAN. Every dependency of safetyGraphics is now available from CRAN. + +The version is 2.2.0. The last version on CRAN was 2.1.1, so the version had to be increased. This release also carries the work that accumulated between the 2.1.1 release and the archival; see NEWS.md. + +`R CMD check --as-cran` reports "New submission" and "Package was archived on CRAN" in the incoming feasibility check. Both are expected for the resubmission of an archived package, and the reason for the archival is resolved as described above. + +One URL in the Technical FAQ vignette is reported as possibly invalid: + +* https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf returns 403 Forbidden to automated requests. The document is reachable in a browser; hhs.gov rejects non-interactive clients. The other eight URLs previously flagged as moved have been updated to their current addresses. + ## Test environments -* local OS X install, R 4.1.0 -* Fedora Linux, R-devel, clang, gfortran (rhub.io) -* Ubuntu Linux 16.04 LTS, R-release, GCC (rhub.io) -* Windows Server 2008 R2 SP1, R-devel, 32/64 bit (rhub.io) + +* local macOS 14.6.1 (aarch64), R 4.3.3 ## R CMD check results -There were no ERRORs, WARNINGs or NOTEs. + + ## Downstream dependencies -None + +None on CRAN. diff --git a/man/SafetyGraphics.Rd b/man/SafetyGraphics.Rd index 8241bb1e..3a1a5e84 100644 --- a/man/SafetyGraphics.Rd +++ b/man/SafetyGraphics.Rd @@ -2,6 +2,8 @@ % Please edit documentation in R/safetyGraphics.R \docType{package} \name{SafetyGraphics} +\alias{safetyGraphics} +\alias{safetyGraphics-package} \alias{SafetyGraphics} \title{\code{safetyGraphics} package} \description{ @@ -11,5 +13,26 @@ Create Interactive Graphics Related to Clinical Trial Safety Learn more on \href{https://CRAN.R-project.org/package=safetyGraphics}{CRAN} or \href{https://github.com/SafetyGraphics/safetyGraphics}{GitHub} +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/SafetyGraphics/safetyGraphics} + \item Report bugs at \url{https://github.com/SafetyGraphics/safetyGraphics/issues} +} + +} +\author{ +\strong{Maintainer}: Jeremy Wildfire \email{jwildfire@gmail.com} + +Authors: +\itemize{ + \item Becca Krouse + \item Preston Burns + \item Xiao Ni + \item James Buchanan + \item Susan Duke +} + } \keyword{internal} diff --git a/man/detectStandard.Rd b/man/detectStandard.Rd index b627b42c..e2d8a5f8 100644 --- a/man/detectStandard.Rd +++ b/man/detectStandard.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/detectStandard.R +% Please edit documentation in R/util-detectStandard.R \name{detectStandard} \alias{detectStandard} \title{Detect the data standard used for a data set} diff --git a/man/evaluateStandard.Rd b/man/evaluateStandard.Rd index f1ef1c25..3336bc30 100644 --- a/man/evaluateStandard.Rd +++ b/man/evaluateStandard.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/evaluateStandard.R +% Please edit documentation in R/util-evaluateStandard.R \name{evaluateStandard} \alias{evaluateStandard} \title{Evaluate a data set against a data standard} diff --git a/man/generateMappingList.Rd b/man/generateMappingList.Rd index cf9573bf..b75d46b8 100644 --- a/man/generateMappingList.Rd +++ b/man/generateMappingList.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/generateMappingList.R +% Please edit documentation in R/util-generateMappingList.R \name{generateMappingList} \alias{generateMappingList} \title{Convert mapping data.frame to a list} diff --git a/man/getChartStatus.Rd b/man/getChartStatus.Rd index be1a5a86..7d8db0fa 100644 --- a/man/getChartStatus.Rd +++ b/man/getChartStatus.Rd @@ -7,41 +7,66 @@ getChartStatus(chart, mapping) } \arguments{ -\item{chart}{chart object} +\item{chart}{\code{list} chart object} -\item{mapping}{the current mapping data.frame} +\item{mapping}{\code{data.frame} current mapping} } \value{ -a list with \code{status}, \code{domains} and \code{columns} properties -} -\description{ -Checks a chart's status when column-level chart specifications are provided in chart$dataSpec. Note that safetyGraphicsApp() does not allow a \code{mapping} value that is not found in \code{domainData}, so this function only needs to check that an expected parameter exists in \code{mapping} (not that the specified column is found in the loaded data). -} -\details{ -Returns a list, with: +\code{list} Named list with properties: \itemize{ -\item \code{status} (TRUE, FALSE) -\item \code{domains} a list specifying wheter all columns are specified in each domain -\item \code{columns} a list that matches the structure of chart$dataSpec and indicates which variables are available. +\item status \code{logical} +\item domains \code{list} list specifying whether all columns are specified in each domain +\item columns \code{list} list that matches the structure of chart$dataSpec and indicates which variables are available. } } +\description{ +Checks a chart's status when column-level chart specifications are provided in chart$dataSpec. +Note that safetyGraphicsApp() does not allow a \code{mapping} value that is not found in \code{domainData}, +so this function only needs to check that an expected parameter exists in \code{mapping} (not that the +specified column is found in the loaded data). +} \examples{ sample_chart <- list( - domains=c("aes","dm"), - dataSpec=list( - aes=c("id_col","custom_col"), - dm=c("id_col","test_col") + domains = c("aes", "dm"), + dataSpec = list( + aes = c("id_col", "custom_col"), + dm = c("id_col", "test_col") ) ) sample_mapping <- data.frame( - domain=c("aes","aes","dm","dm"), - text_key=c("id_col","custom_col","id_col","test_col"), - current=c("myID","AEcol","myID","dmCol") + domain = c("aes", "aes", "dm", "dm"), + text_key = c("id_col", "custom_col", "id_col", "test_col"), + current = c("myID", "AEcol", "myID", "dmCol") ) -check <- safetyGraphics:::getChartStatus(chart=sample_chart, mapping=sample_mapping) -# check$status=TRUE +check <- safetyGraphics:::getChartStatus( + chart = sample_chart, + mapping = sample_mapping +) +# check$status = TRUE + +# Add a data spec to each chart, then check them all. +charts <- purrr::map(safetyGraphics::makeChartConfig(), function(chart) { + chart$mapping <- purrr::map_dfr(chart$domain, function(dom) { + getExportedValue("safetyCharts", paste0("meta_", dom)) + }) \%>\% + dplyr::distinct(domain, col_key, current = standard_adam) \%>\% + dplyr::filter(!is.na(current)) \%>\% + dplyr::select(domain, text_key = col_key, current) + + chart$dataSpec <- purrr::map(chart$domain, function(dom) { + chart$mapping \%>\% + dplyr::filter(domain == dom) \%>\% + dplyr::pull(text_key) \%>\% + unique() + }) \%>\% + rlang::set_names(chart$domain) + + chart +}) + +checks <- purrr::map(charts, ~ safetyGraphics:::getChartStatus(.x, .x$mapping)) } \keyword{internal} diff --git a/man/hasColumn.Rd b/man/hasColumn.Rd index dc56ef95..b69173f6 100644 --- a/man/hasColumn.Rd +++ b/man/hasColumn.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/hasColumn.R +% Please edit documentation in R/util-hasColumn.R \name{hasColumn} \alias{hasColumn} \title{Check whether a column is found in a data set} diff --git a/man/hasField.Rd b/man/hasField.Rd index 4e0e9412..b15c25e6 100644 --- a/man/hasField.Rd +++ b/man/hasField.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/hasField.R +% Please edit documentation in R/util-hasField.R \name{hasField} \alias{hasField} \title{Check whether a specified field value is found in a data set} diff --git a/man/homeTab.Rd b/man/homeTab.Rd index 08da5ed2..2398a428 100644 --- a/man/homeTab.Rd +++ b/man/homeTab.Rd @@ -12,6 +12,10 @@ homeTab(input, output, session, config) \item{output}{mod output} \item{session}{mod session} + +\item{config}{named list of app configuration options as returned by +\code{app_startup()}. \code{homeTab()} uses the \code{homeTabPath} and \code{hexPath} +elements.} } \description{ Server for the filter module in datamods::filter_data_ui diff --git a/man/profileTab.Rd b/man/profileTab.Rd index d74e9f09..154124e7 100644 --- a/man/profileTab.Rd +++ b/man/profileTab.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/mod_profileTab.R \name{profileTab} \alias{profileTab} -\title{Server for the patient profile in safetyProfile::profile_server} +\title{Server for the optional patient profile module} \usage{ profileTab(input, output, session, params) } @@ -14,12 +14,17 @@ profileTab(input, output, session, params) \item{session}{Shiny session object} \item{params}{reactive containing mapping and data} - -\item{current_id}{reactive containing currently selected participant} } \value{ -current_id +A reactive containing the currently selected participant id, or +\code{NULL} when \code{safetyProfile} is not loaded. } \description{ -Server for the patient profile in safetyProfile::profile_server +Starts the patient profile module supplied by the \code{safetyProfile} package. +\code{safetyProfile} is an optional add-on that is not distributed on CRAN; when +it is not loaded this function returns \code{NULL} without starting a module, +matching \code{profileTabUI()}, which renders nothing in that case. + +Install it with \code{remotes::install_github("SafetyGraphics/safetyProfile")}, +then attach it with \code{library(safetyProfile)} before starting the app. } diff --git a/man/profileTabUI.Rd b/man/profileTabUI.Rd index 0db64c61..ca48edc3 100644 --- a/man/profileTabUI.Rd +++ b/man/profileTabUI.Rd @@ -2,13 +2,23 @@ % Please edit documentation in R/mod_profileTab.R \name{profileTabUI} \alias{profileTabUI} -\title{UI for the profile module in safetyProfile::profile_ui} +\title{UI for the optional patient profile module} \usage{ profileTabUI(id) } \arguments{ \item{id}{module id} } +\value{ +The profile module UI when \code{safetyProfile} is available, otherwise +\code{NULL}. +} \description{ -UI for the profile module in safetyProfile::profile_ui +Renders the UI for the patient profile module supplied by the \code{safetyProfile} +package. \code{safetyProfile} is an optional add-on that is not distributed on +CRAN; when it is not loaded, this function returns \code{NULL} and the profile +tab is simply absent from the application. + +Install it with \code{remotes::install_github("SafetyGraphics/safetyProfile")}, +then attach it with \code{library(safetyProfile)} before starting the app. } diff --git a/man/safetyGraphicsServer.Rd b/man/safetyGraphicsServer.Rd index 8aadddf9..68ee08e3 100644 --- a/man/safetyGraphicsServer.Rd +++ b/man/safetyGraphicsServer.Rd @@ -32,6 +32,8 @@ safetyGraphicsServer( \item{charts}{list of charts to include in the app} \item{filterDomain}{domain used for the data/filter tab. Demographics ("\code{dm}") is used by default. Using a domain that is not one record per participant is not recommended.} + +\item{config}{named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it.} } \description{ This function returns a server function suitable for use in shiny::runApp() diff --git a/man/safetyGraphicsUI.Rd b/man/safetyGraphicsUI.Rd index 19bdbd6a..9839b873 100644 --- a/man/safetyGraphicsUI.Rd +++ b/man/safetyGraphicsUI.Rd @@ -18,6 +18,8 @@ safetyGraphicsUI(id, meta, mapping, domainData, charts, standards, config) \item{charts}{list of charts in the format produced by safetyGraphics::makeChartConfig()} \item{standards}{a list of information regarding data standards. Each list item should use the format returned by safetyGraphics::detectStandard.} + +\item{config}{named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it.} } \description{ UI for the core safetyGraphics app including Home, Mapping, Filter, Charts and Settings modules. diff --git a/man/setMappingListValue.Rd b/man/setMappingListValue.Rd index 8b4942ea..25c3d92c 100644 --- a/man/setMappingListValue.Rd +++ b/man/setMappingListValue.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/setMappingListValue.R +% Please edit documentation in R/util-setMappingListValue.R \name{setMappingListValue} \alias{setMappingListValue} \title{Set the value for a given named parameter} diff --git a/man/textKeysToList.Rd b/man/textKeysToList.Rd index 9a11e91a..933d6a71 100644 --- a/man/textKeysToList.Rd +++ b/man/textKeysToList.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/textKeysToList.R +% Please edit documentation in R/util-textKeysToList.R \name{textKeysToList} \alias{textKeysToList} \title{Helper function to convert keys from text to nested lists} diff --git a/vignettes/TechnicalFAQ.Rmd b/vignettes/TechnicalFAQ.Rmd index bbb32a02..df7a97ec 100644 --- a/vignettes/TechnicalFAQ.Rmd +++ b/vignettes/TechnicalFAQ.Rmd @@ -28,7 +28,7 @@ Whenever new questions come in, we'll update the version of [this FAQ in our wik # Validation, Quality Control and Testing ## Q: Is the safetyGraphics package validated? -**A**: As of the version 2 release, the safetyGraphics package is intended for exploratory use only and is not validated or qualified per [21 CFR Part 11](https://www.fda.gov/regulatory-information/search-fda-guidance-documents/part-11-electronic-records-electronic-signatures-scope-and-application). No warranty or guarantees are included as part of the package. Further, any formal validation should be fit for purpose and follow your organization's procedures. That said, extensive quality checks are built in to the package (see the question below for details) and into many of charts that are included by default. The R Consortium has [guidance on usage of R in Regulated Trials](https://www.r-project.org/doc/R-FDA.pdf) and we also follow the work of [R Validation hub](https://www.pharmar.org/) closely, and may release validation guidance based on the approach described in their [white paper](https://www.pharmar.org/white-paper/) at a future date. +**A**: As of the version 2 release, the safetyGraphics package is intended for exploratory use only and is not validated or qualified per [21 CFR Part 11](https://www.fda.gov/regulatory-information/search-fda-guidance-documents/part-11-electronic-records-electronic-signatures-scope-and-application). No warranty or guarantees are included as part of the package. Further, any formal validation should be fit for purpose and follow your organization's procedures. That said, extensive quality checks are built in to the package (see the question below for details) and into many of charts that are included by default. The R Consortium has [guidance on usage of R in Regulated Trials](https://www.r-project.org/doc/R-FDA.pdf) and we also follow the work of [R Validation hub](https://pharmar.org/) closely, and may release validation guidance based on the approach described in their [white paper](https://pharmar.org/white-paper/) at a future date. ## Q: Can I validate charts created by safetyGraphics? **A**: Study-specific instances of most safetyGraphics charts can be exported either as an R script or as a standalone html report. It may be possible to treat those outputs as standard TLFs (Tables, Listings and Figures) and conduct QC/Validation on them using standard statistical SOPs. Consult with your companies procedures to confirm. @@ -57,13 +57,13 @@ That said, the issues surrounding a 'production' deployment are mostly technical Many of these issues aren't specific to safetyGraphics and may be easier to address for an organization that has experience using R and Shiny in production. [As discussed above](#q-is-the-safetygraphics-package-validated), there is a significant push towards using R for many aspects of clinical trials. We plan to keep safetyGraphics up to date with emerging best practices and will provide supporting documentation whenever possible. -Finally, it is worth noting "Productionize” and “Validate” are slightly different. Joe Cheng (the primary author of Shiny) has a [nice talk](https://www.rstudio.com/resources/rstudioconf-2019/shiny-in-production-principles-practices-and-tools/) on this topic from a software engineering perspective. +Finally, it is worth noting "Productionize” and “Validate” are slightly different. Joe Cheng (the primary author of Shiny) has a [nice talk](https://posit.co/resources/videos/shiny-in-production-principles-practices-and-tools) on this topic from a software engineering perspective. # Use Cases, Data Sources and Deployment ## Q: I can see that the software has the MIT license, so does this essentially mean that any company would be free to use the software without restriction? -**A**: Yes. The package is open source and free to use. Here's a link to the [license](https://github.com/SafetyGraphics/safetyGraphics/blob/dev/LICENSE.md) and a quick [summary](https://tldrlegal.com/license/mit-license) of how it works. +**A**: Yes. The package is open source and free to use. Here's a link to the [license](https://github.com/SafetyGraphics/safetyGraphics/blob/dev/LICENSE.md) and a quick [summary](https://www.tldrlegal.com/license/mit-license) of how it works. ## Q: What are some common use cases for safetyGraphics? @@ -73,7 +73,7 @@ Finally, it is worth noting "Productionize” and “Validate” are slightly di - Analysts and Clinicians evaluating safety signals in completed studies As an open source tool with a flexible data pipeline, many other use cases have been discussed: -- Data review by Data Safety Monitoring Boards ([link](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7833551/pdf/main.pdf)) +- Data review by Data Safety Monitoring Boards ([link](https://pmc.ncbi.nlm.nih.gov/articles/PMC7833551/pdf/main.pdf)) - Visualizing Analysis results data ([link](https://github.com/phuse-org/aesummaries)) - Risk based monitoring @@ -95,7 +95,7 @@ More detail is provided in the [Loading data section of the Introductory vignett Since the safetyGraphics app typically uses data subject to GxP regulations, data security is extremely important and should always be discussed with your organizations IT and regulatory departments before loading any study data in to the application. No warranty or guarantees are included as part of the package. -Just like the discussion regarding [Validation and Quality Control](#validation-quality-control-and-testing), data security requirements are dictated by the intended use of the app and should be fit for purpose. There are many different ways to run shiny applications, and the security implications of each approach varies. For example, having statisticians run the app locally using R Studio is quite different than deploying the app on a service like shinyapps.io. This complexity is all the more reason to discuss with IT. There are many resources - related to data security for clinical trials in general ([1](https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf), [2](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4943495/), [3](https://www.d-wise.com/blog/detailing-the-de-identification-and-data-transparency-boundaries-of-ema-policy-70-and-gdpr)) and discussing data security in shiny ([4](https://www.youtube.com/watch?v=5odJxZj9LE4), +Just like the discussion regarding [Validation and Quality Control](#validation-quality-control-and-testing), data security requirements are dictated by the intended use of the app and should be fit for purpose. There are many different ways to run shiny applications, and the security implications of each approach varies. For example, having statisticians run the app locally using R Studio is quite different than deploying the app on a service like shinyapps.io. This complexity is all the more reason to discuss with IT. There are many resources - related to data security for clinical trials in general ([1](https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf), [2](https://pmc.ncbi.nlm.nih.gov/articles/PMC4943495/), [3](https://web.archive.org/web/20250512155605/https://www.d-wise.com/blog/detailing-the-de-identification-and-data-transparency-boundaries-of-ema-policy-70-and-gdpr)) and discussing data security in shiny ([4](https://www.youtube.com/watch?v=5odJxZj9LE4), [5](https://mastering-shiny.org/scaling-security.html#data)) - that could help to facilitate these discussion. ## Q: How can the safetyGraphics app be shared? @@ -104,13 +104,13 @@ Just like the discussion regarding [Validation and Quality Control](#validation- ## Q: Do you recommend deploying the app to a dedicated server for internal usage? -**A**: It depends a bit on your use-case and how the app is hosted. For example, analysts using the data in an exploratory fashion can probably just run it from RStudio, but if multiple medical monitors using the app for medical monitoring in active studies probably need a more robust (and possibly validated) set up using [Shiny Server](https://github.com/rstudio/shiny-server/blob/master/README.md), [RStudio Connect](https://posit.co/products/enterprise/connect/) or something similar. +**A**: It depends a bit on your use-case and how the app is hosted. For example, analysts using the data in an exploratory fashion can probably just run it from RStudio, but if multiple medical monitors using the app for medical monitoring in active studies probably need a more robust (and possibly validated) set up using [Shiny Server](https://github.com/rstudio/shiny-server/blob/master/README.md), [RStudio Connect](https://posit.co/products/enterprise/connect) or something similar. ## Q: Can I deploy `safetyGraphics` to shinyapps.io to explore trial data from my organization? **A**: We advise against loading non-authorized, private, or non-deidentified patient data outside of your organization's firewall. Consult with your IT and QA first. There is huge risk associated with confidentiality, IP, and patient privacy. Also refer to [ShinyApps.io Chapter 8 Security and Compliance](https://docs.posit.co/shinyapps.io/security-and-compliance.html). -## **Q**: Can I deploy `safetyGraphics` to an internal [RStudio Connect](https://posit.co/products/enterprise/connect/) server? +## **Q**: Can I deploy `safetyGraphics` to an internal [RStudio Connect](https://posit.co/products/enterprise/connect) server? **A**: Yes. The [script below](https://github.com/SafetyGraphics/safetyGraphics/blob/dev/inst/deploy/app.R) should be easy to deploy via the RStudio interface or by running `rsconnect::deployApp()` and can easily be customized to support custom data and charts. From adff382b720325fb522f3a3866e0cd9bd892e548 Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Thu, 20 Aug 2026 15:44:10 -0400 Subject: [PATCH 2/5] Document chartsNavUI()'s return value Audited both packages' Rd files for missing \value against the last CRAN-accepted tarball of each. safetyCharts now has none at all, against two in the accepted 0.3.0. safetyGraphics had 33, of which exactly one -- chartsNavUI -- was added since the accepted 2.1.1. That one is fixed, so this release adds no new gap; the other 32 have CRAN precedent and are left for a separate pass rather than folded into a resubmission. Worker: W0084 --- NEWS.md | 1 + R/mod_chartsNav.R | 3 +++ man/chartsNavUI.Rd | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/NEWS.md b/NEWS.md index f516e6a5..352b9e0c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,6 +27,7 @@ This is the first release since v2.1.1 and is the release that returns safetyGra - The `getChartStatus()` example has been fixed. It called `map()`, `distinct()`, `filter()` and others without qualifying them, so it failed whenever it was run outside an interactive session with the tidyverse attached. - `NAMESPACE` regenerated. The checked-in copy had drifted from the roxygen comments: it imported `set_names` from `purrr` rather than `rlang`, and `map_lgl` rather than `imap`. - Nine external links in the Technical FAQ vignette updated to the addresses they now redirect to. +- `chartsNavUI()` now documents its return value. It was the only function added since the 2.1.1 CRAN release without one; the 32 remaining undocumented return values all shipped in 2.1.1 and are left for a separate pass. # safetyGraphics v2.1.1 diff --git a/R/mod_chartsNav.R b/R/mod_chartsNav.R index d2c3fd76..317ba6d3 100644 --- a/R/mod_chartsNav.R +++ b/R/mod_chartsNav.R @@ -3,6 +3,9 @@ #' @param id module id #' @param chart chart metadata #' +#' @return A `shiny::tabPanel()` for the chart, ready to be added to the +#' application's navbar. +#' #' @export #' diff --git a/man/chartsNavUI.Rd b/man/chartsNavUI.Rd index bc3cea1f..58fc9e03 100644 --- a/man/chartsNavUI.Rd +++ b/man/chartsNavUI.Rd @@ -11,6 +11,10 @@ chartsNavUI(id, chart) \item{chart}{chart metadata} } +\value{ +A \code{shiny::tabPanel()} for the chart, ready to be added to the +application's navbar. +} \description{ Adds a navbar tab that initializes the Chart Module UI } From 820ac6b6164461b5f4015c7c45a7aa01ba2c38dd Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Thu, 20 Aug 2026 15:47:36 -0400 Subject: [PATCH 3/5] Correct two false statements in the NEWS entry Found by an adversarial audit of this branch. - "Stray print() calls removed from the app" was false. The prints removed by 9f90959 had been introduced after the 2.1.1 CRAN release, so relative to what CRAN shipped nothing changed; print(charts) at R/mod_settingsCharts.R:53 is byte-identical to 2.1.1 and is still there. The line is removed rather than the print, because removing it is a behaviour change with CRAN precedent against it being a defect. - The undeclared cli::cli_alert_info() call is in safetyGraphicsServer(), not in the profile tab module. Corrected. Worker: W0084 --- NEWS.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 352b9e0c..492575b3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,13 +15,12 @@ This is the first release since v2.1.1 and is the release that returns safetyGra - App-level settings support, and `launchBrowser` handling, in `safetyGraphicsApp()`. - Chart modules refactored to simplify the reactive flow, with chart event listeners added to the widgets. - `generateMappingList()` now works with `tbl_df`-classed data frames. -- Stray `print()` calls removed from the app. - Utility source files renamed with a `util-` prefix. ## Packaging changes for the CRAN resubmission - `safetyProfile` has been removed from `Suggests`. It is not on CRAN and never has been, so declaring it made the package uncheckable by CRAN. The patient profile tab still works exactly as before for anyone who has installed and loaded `safetyProfile`; it is now reached through `getExportedValue()` behind the same `isNamespaceLoaded()` guard the other optional packages use. Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`. -- `cli` added to `Imports`. `cli::cli_alert_info()` was already being called by the profile tab without being declared anywhere. +- `cli` added to `Imports`. `cli::cli_alert_info()` was already being called in `safetyGraphicsServer()` without being declared anywhere. - `LazyData: true` removed. The package has no `data/` directory, so the field was inert. - The `config` argument is now documented for `homeTab()`, `safetyGraphicsServer()` and `safetyGraphicsUI()`. - The `getChartStatus()` example has been fixed. It called `map()`, `distinct()`, `filter()` and others without qualifying them, so it failed whenever it was run outside an interactive session with the tidyverse attached. From f5cd0405259d1060dc5e0def0253728cd9ccf2ae Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Thu, 20 Aug 2026 15:51:23 -0400 Subject: [PATCH 4/5] Restore profileTab()'s load-on-demand behaviour, and stop cran-comments.md asserting something that is not yet true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both found by an adversarial audit of this branch. - profileTab() had gained an isNamespaceLoaded() guard it never had. The original called safetyProfile::profile_server() unconditionally, and `::` loads an installed namespace on demand — so with safetyProfile installed but not yet loaded, the original started the module and the guarded version returned NULL silently. Guard removed. getExportedValue() was verified to match `::` exactly: it loads an installed-but-unloaded namespace and errors when the package is absent. profileTabUI() keeps its guard, which it always had. - profileTabUI()'s change is a bug fix, not a no-op, and is now documented as one: the original called profile_ui() unqualified, so a loaded-but-unattached safetyProfile produced "could not find function". - cran-comments.md stated "'safetyCharts' has been updated to remove 'Tendril' and is back on CRAN". It is not; it is still archived and has not been submitted. That is the same defect this branch removed from the previous cran-comments.md. Replaced with a blocking HTML comment and fill-in-the-date placeholders so it cannot be pasted into the submission form before it is true. - Tenth redirected URL in the Technical FAQ vignette, missed on the first pass: shiny.rstudio.com/tutorial/written-tutorial/lesson7 now resolves to shiny.posit.co/r/getstarted/shiny-basics/lesson7. NEWS count corrected, and the d-wise link described accurately as an Internet Archive substitute rather than a redirect. Worker: W0084 --- NEWS.md | 5 +++-- R/mod_profileTab.R | 32 ++++++++++++++++---------------- cran-comments.md | 9 +++++++-- man/profileTab.Rd | 18 +++++++++++------- man/profileTabUI.Rd | 6 +++--- vignettes/TechnicalFAQ.Rmd | 2 +- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/NEWS.md b/NEWS.md index 492575b3..faeff6a0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,13 +19,14 @@ This is the first release since v2.1.1 and is the release that returns safetyGra ## Packaging changes for the CRAN resubmission -- `safetyProfile` has been removed from `Suggests`. It is not on CRAN and never has been, so declaring it made the package uncheckable by CRAN. The patient profile tab still works exactly as before for anyone who has installed and loaded `safetyProfile`; it is now reached through `getExportedValue()` behind the same `isNamespaceLoaded()` guard the other optional packages use. Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`. +- `safetyProfile` has been removed from `Suggests`. It is not on CRAN and never has been, so declaring it made the package uncheckable by CRAN. The patient profile tab is unaffected for anyone who has `safetyProfile` installed; it is now reached through `getExportedValue()`, which loads and resolves exactly as `safetyProfile::` did. Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`. +- `profileTabUI()` no longer fails when the `safetyProfile` namespace is loaded but not attached. It previously called `profile_ui()` unqualified, which is only resolvable off the search path, so `loadNamespace("safetyProfile")` without `library()` produced "could not find function". - `cli` added to `Imports`. `cli::cli_alert_info()` was already being called in `safetyGraphicsServer()` without being declared anywhere. - `LazyData: true` removed. The package has no `data/` directory, so the field was inert. - The `config` argument is now documented for `homeTab()`, `safetyGraphicsServer()` and `safetyGraphicsUI()`. - The `getChartStatus()` example has been fixed. It called `map()`, `distinct()`, `filter()` and others without qualifying them, so it failed whenever it was run outside an interactive session with the tidyverse attached. - `NAMESPACE` regenerated. The checked-in copy had drifted from the roxygen comments: it imported `set_names` from `purrr` rather than `rlang`, and `map_lgl` rather than `imap`. -- Nine external links in the Technical FAQ vignette updated to the addresses they now redirect to. +- Ten external links in the Technical FAQ vignette updated. Nine now point at the addresses they were redirecting to; the tenth, a d-wise article that no longer exists, points at its Internet Archive snapshot so the citation still resolves to what was cited. - `chartsNavUI()` now documents its return value. It was the only function added since the 2.1.1 CRAN release without one; the 32 remaining undocumented return values all shipped in 2.1.1 and are left for a separate pass. # safetyGraphics v2.1.1 diff --git a/R/mod_profileTab.R b/R/mod_profileTab.R index c7d5f246..341adef3 100644 --- a/R/mod_profileTab.R +++ b/R/mod_profileTab.R @@ -3,11 +3,11 @@ #' @description #' Renders the UI for the patient profile module supplied by the `safetyProfile` #' package. `safetyProfile` is an optional add-on that is not distributed on -#' CRAN; when it is not loaded, this function returns `NULL` and the profile -#' tab is simply absent from the application. +#' CRAN; when its namespace is not loaded, this function returns `NULL` and the +#' profile tab is simply absent from the application. #' #' Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`, -#' then attach it with `library(safetyProfile)` before starting the app. +#' then load it with `library(safetyProfile)` before starting the app. #' #' @param id module id #' @@ -33,20 +33,24 @@ profileTabUI <- function(id){ #' #' @description #' Starts the patient profile module supplied by the `safetyProfile` package. -#' `safetyProfile` is an optional add-on that is not distributed on CRAN; when -#' it is not loaded this function returns `NULL` without starting a module, -#' matching `profileTabUI()`, which renders nothing in that case. +#' `safetyProfile` is an optional add-on that is not distributed on CRAN. #' -#' Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`, -#' then attach it with `library(safetyProfile)` before starting the app. +#' Install it with `remotes::install_github("SafetyGraphics/safetyProfile")`. +#' +#' @details +#' This function requires `safetyProfile` and raises an error if it is not +#' installed, exactly as calling `safetyProfile::profile_server()` directly +#' would. `safetyGraphicsServer()` only reaches it when the namespace is +#' loaded, so the application never hits that error. It is reached through +#' `getExportedValue()` rather than `::` so that a package CRAN cannot see is +#' not written into safetyGraphics as a hard reference. #' #' @param input Shiny input object #' @param output Shiny output object #' @param session Shiny session object #' @param params reactive containing mapping and data #' -#' @return A reactive containing the currently selected participant id, or -#' `NULL` when `safetyProfile` is not loaded. +#' @return A reactive containing the currently selected participant id. #' #' @import datamods #' @importFrom shinyjs show hide @@ -55,10 +59,6 @@ profileTabUI <- function(id){ #' @export profileTab <- function(input, output, session, params) { - if (!has_safety_profile()) { - return(NULL) - } - profile_server <- getExportedValue("safetyProfile", "profile_server") id <- profile_server( @@ -88,8 +88,8 @@ profileTab <- function(input, output, session, params) { #' #' @description #' `safetyProfile` supplies the patient profile module. It is not distributed on -#' CRAN, so safetyGraphics treats it as strictly optional and every use of it is -#' routed through this check. +#' CRAN, so safetyGraphics treats it as strictly optional and gates the profile +#' tab's UI on this check. #' #' Matches the test used for the other optional packages in this application #' (`listviewer`, `shinybusy`, `shinyWidgets`): the feature appears once the diff --git a/cran-comments.md b/cran-comments.md index 58ff4025..825594df 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -2,7 +2,12 @@ safetyGraphics was archived on CRAN on 2026-03-25 because it required the archived package 'Tendril'. It has never used 'Tendril' directly; it was archived because it imports 'safetyCharts', which did. -'safetyCharts' has been updated to remove 'Tendril' and is back on CRAN. Every dependency of safetyGraphics is now available from CRAN. + + +'safetyCharts' , which removes 'Tendril', was accepted to CRAN on +. Every dependency of safetyGraphics is now available from CRAN. The version is 2.2.0. The last version on CRAN was 2.1.1, so the version had to be increased. This release also carries the work that accumulated between the 2.1.1 release and the archival; see NEWS.md. @@ -10,7 +15,7 @@ The version is 2.2.0. The last version on CRAN was 2.1.1, so the version had to One URL in the Technical FAQ vignette is reported as possibly invalid: -* https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf returns 403 Forbidden to automated requests. The document is reachable in a browser; hhs.gov rejects non-interactive clients. The other eight URLs previously flagged as moved have been updated to their current addresses. +* https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf returns 403 Forbidden. The server rejects automated requests, including from a client sending a full browser user-agent; the link is not dead. The other URLs previously flagged as moved have been updated to their current addresses. ## Test environments diff --git a/man/profileTab.Rd b/man/profileTab.Rd index 154124e7..cf178aa4 100644 --- a/man/profileTab.Rd +++ b/man/profileTab.Rd @@ -16,15 +16,19 @@ profileTab(input, output, session, params) \item{params}{reactive containing mapping and data} } \value{ -A reactive containing the currently selected participant id, or -\code{NULL} when \code{safetyProfile} is not loaded. +A reactive containing the currently selected participant id. } \description{ Starts the patient profile module supplied by the \code{safetyProfile} package. -\code{safetyProfile} is an optional add-on that is not distributed on CRAN; when -it is not loaded this function returns \code{NULL} without starting a module, -matching \code{profileTabUI()}, which renders nothing in that case. +\code{safetyProfile} is an optional add-on that is not distributed on CRAN. -Install it with \code{remotes::install_github("SafetyGraphics/safetyProfile")}, -then attach it with \code{library(safetyProfile)} before starting the app. +Install it with \code{remotes::install_github("SafetyGraphics/safetyProfile")}. +} +\details{ +This function requires \code{safetyProfile} and raises an error if it is not +installed, exactly as calling \code{safetyProfile::profile_server()} directly +would. \code{safetyGraphicsServer()} only reaches it when the namespace is +loaded, so the application never hits that error. It is reached through +\code{getExportedValue()} rather than \code{::} so that a package CRAN cannot see is +not written into safetyGraphics as a hard reference. } diff --git a/man/profileTabUI.Rd b/man/profileTabUI.Rd index ca48edc3..8c1bc62a 100644 --- a/man/profileTabUI.Rd +++ b/man/profileTabUI.Rd @@ -16,9 +16,9 @@ The profile module UI when \code{safetyProfile} is available, otherwise \description{ Renders the UI for the patient profile module supplied by the \code{safetyProfile} package. \code{safetyProfile} is an optional add-on that is not distributed on -CRAN; when it is not loaded, this function returns \code{NULL} and the profile -tab is simply absent from the application. +CRAN; when its namespace is not loaded, this function returns \code{NULL} and the +profile tab is simply absent from the application. Install it with \code{remotes::install_github("SafetyGraphics/safetyProfile")}, -then attach it with \code{library(safetyProfile)} before starting the app. +then load it with \code{library(safetyProfile)} before starting the app. } diff --git a/vignettes/TechnicalFAQ.Rmd b/vignettes/TechnicalFAQ.Rmd index df7a97ec..4ad6d984 100644 --- a/vignettes/TechnicalFAQ.Rmd +++ b/vignettes/TechnicalFAQ.Rmd @@ -100,7 +100,7 @@ Just like the discussion regarding [Validation and Quality Control](#validation- ## Q: How can the safetyGraphics app be shared? -**A**: The safetyGraphics app can be shared using [standard shiny methodology](https://shiny.rstudio.com/tutorial/written-tutorial/lesson7/). More details for specific use cases are given in the next few questions. Charts created by safetyGraphics can also be exported and re-used. Charts created with [htmlwidgets](https://www.htmlwidgets.org/) are especially flexible and can be used in many contexts - including in web applications outside of R. +**A**: The safetyGraphics app can be shared using [standard shiny methodology](https://shiny.posit.co/r/getstarted/shiny-basics/lesson7/). More details for specific use cases are given in the next few questions. Charts created by safetyGraphics can also be exported and re-used. Charts created with [htmlwidgets](https://www.htmlwidgets.org/) are especially flexible and can be used in many contexts - including in web applications outside of R. ## Q: Do you recommend deploying the app to a dedicated server for internal usage? From 2c675e44b5a1a7ad28940a8bfd0fd3fef5bc688b Mon Sep 17 00:00:00 2001 From: Jeremy Wildfire Date: Thu, 20 Aug 2026 15:56:18 -0400 Subject: [PATCH 5/5] Document the return value of every exported function Missing \value is the most common CRAN ask on a new submission, and an archived package is reviewed as one. An audit against the last CRAN-accepted tarball found 32 exported functions with no \value section -- essentially the whole Shiny module layer, plus safetyGraphicsApp(), safetyGraphicsInit(), makeChartParams(), makeChartSummary() and generateMappingList(). All are now documented, from each function's actual terminal expression rather than from its name: UI functions state the UI object they build, module servers that exist for their side effects say so plainly, and the two that return reactives say which reactive. Also pre-empts the reviewer question about safetyProfile in cran-comments.md: it is a GitHub-only package declared in no DESCRIPTION field, and the comment now explains why and invites CRAN to say if they want it handled differently. Worker: W0084 --- NEWS.md | 2 +- R/makeChartParams.R | 4 ++++ R/makeChartSummary.R | 3 +++ R/mod_chartsNav.R | 3 +++ R/mod_chartsTab.R | 6 ++++++ R/mod_filterTab.R | 2 ++ R/mod_homeTab.R | 5 +++++ R/mod_loadCharts.R | 4 ++++ R/mod_loadData.R | 4 ++++ R/mod_mappingColumn.R | 2 ++ R/mod_mappingDomain.R | 2 ++ R/mod_mappingTab.R | 2 ++ R/mod_safetyGraphicsServer.R | 3 +++ R/mod_safetyGraphicsUI.R | 2 ++ R/mod_settingsCharts.R | 5 +++++ R/mod_settingsCode.R | 5 +++++ R/mod_settingsData.R | 5 +++++ R/mod_settingsMapping.R | 5 +++++ R/mod_settingsTab.R | 5 +++++ R/safetyGraphicsApp.R | 3 +++ R/safetyGraphicsInit.R | 3 +++ R/util-generateMappingList.R | 4 ++++ cran-comments.md | 2 ++ man/chartsNav.Rd | 4 ++++ man/chartsTab.Rd | 4 ++++ man/chartsTabUI.Rd | 4 ++++ man/filterTabUI.Rd | 3 +++ man/generateMappingList.Rd | 5 +++++ man/homeTab.Rd | 4 ++++ man/homeTabUI.Rd | 3 +++ man/loadCharts.Rd | 3 +++ man/loadChartsUI.Rd | 3 +++ man/loadData.Rd | 3 +++ man/loadDataUI.Rd | 3 +++ man/makeChartParams.Rd | 5 +++++ man/makeChartSummary.Rd | 4 ++++ man/mappingColumnUI.Rd | 3 +++ man/mappingDomainUI.Rd | 3 +++ man/mappingTabUI.Rd | 3 +++ man/safetyGraphicsApp.Rd | 4 ++++ man/safetyGraphicsInit.Rd | 4 ++++ man/safetyGraphicsServer.Rd | 4 ++++ man/safetyGraphicsUI.Rd | 3 +++ man/settingsCharts.Rd | 4 ++++ man/settingsChartsUI.Rd | 3 +++ man/settingsCode.Rd | 4 ++++ man/settingsCodeUI.Rd | 3 +++ man/settingsData.Rd | 4 ++++ man/settingsDataUI.Rd | 3 +++ man/settingsMapping.Rd | 4 ++++ man/settingsMappingUI.Rd | 3 +++ man/settingsTab.Rd | 4 ++++ man/settingsTabUI.Rd | 3 +++ 53 files changed, 187 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index faeff6a0..a3200926 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,7 +27,7 @@ This is the first release since v2.1.1 and is the release that returns safetyGra - The `getChartStatus()` example has been fixed. It called `map()`, `distinct()`, `filter()` and others without qualifying them, so it failed whenever it was run outside an interactive session with the tidyverse attached. - `NAMESPACE` regenerated. The checked-in copy had drifted from the roxygen comments: it imported `set_names` from `purrr` rather than `rlang`, and `map_lgl` rather than `imap`. - Ten external links in the Technical FAQ vignette updated. Nine now point at the addresses they were redirecting to; the tenth, a d-wise article that no longer exists, points at its Internet Archive snapshot so the citation still resolves to what was cited. -- `chartsNavUI()` now documents its return value. It was the only function added since the 2.1.1 CRAN release without one; the 32 remaining undocumented return values all shipped in 2.1.1 and are left for a separate pass. +- Every exported function now documents its return value. CRAN asks for this on new submissions, and an archived package is reviewed as one; 32 exported functions had no `\value` section, including everything in the module layer. # safetyGraphics v2.1.1 diff --git a/R/makeChartParams.R b/R/makeChartParams.R index ce76c55d..a2181e8c 100644 --- a/R/makeChartParams.R +++ b/R/makeChartParams.R @@ -5,6 +5,10 @@ #' @param chart list containing chart specifications #' @param mapping data frame with current mapping #' +#' +#' @return A named list of parameters for the chart, ready to pass to the chart's +#' rendering function. For `htmlwidget` charts the list is the widget's +#' parameter object, with `data` and JSON-encoded `settings` attached. #' @export makeChartParams <- function(data, chart, mapping){ diff --git a/R/makeChartSummary.R b/R/makeChartSummary.R index 97882fb8..b9209be9 100644 --- a/R/makeChartSummary.R +++ b/R/makeChartSummary.R @@ -6,6 +6,9 @@ #' @param showLinks boolean indicating whether to include links #' @param class character to include as class #' +#' +#' @return A `shiny::div()` summarising the chart: its label, type, data domains, +#' status and, when `showLinks` is `TRUE`, its documentation links. #' @export makeChartSummary<- function(chart, status=NULL, showLinks=TRUE, class="chart-header"){ diff --git a/R/mod_chartsNav.R b/R/mod_chartsNav.R index 317ba6d3..037f285b 100644 --- a/R/mod_chartsNav.R +++ b/R/mod_chartsNav.R @@ -33,6 +33,9 @@ chartsNavUI <- function(id, chart) { #' @param data named list of current data sets (Reactive). #' @param mapping tibble capturing the current data mappings (Reactive). #' +#' +#' @return No return value. Called for its side effect of starting the chart tab +#' module for this navbar entry. #' @export #' diff --git a/R/mod_chartsTab.R b/R/mod_chartsTab.R index b27c1b63..4ed40dc9 100644 --- a/R/mod_chartsTab.R +++ b/R/mod_chartsTab.R @@ -3,6 +3,9 @@ #' @param id module id #' @param chart list containing chart specifications like those returned by \link{makeChartConfig}. #' +#' +#' @return A list of two Shiny UI elements: the chart header and the chart +#' container. #' @importFrom stringr str_to_title #' @importFrom purrr map2 #' @@ -26,6 +29,9 @@ chartsTabUI <- function(id, chart){ #' @param mapping tibble capturing the current data mappings (Reactive). #' @param status chart status (Reactive) #' +#' +#' @return No return value. Called for its side effect of rendering the chart and +#' wiring up its export handlers. #' @export chartsTab <- function(input, output, session, chart, data, mapping, status){ diff --git a/R/mod_filterTab.R b/R/mod_filterTab.R index 0eb8040e..0afc4340 100644 --- a/R/mod_filterTab.R +++ b/R/mod_filterTab.R @@ -2,6 +2,8 @@ #' #' @param id module id #' +#' +#' @return The filter module's Shiny UI. #' @import datamods #' @importFrom shiny dataTableOutput #' diff --git a/R/mod_homeTab.R b/R/mod_homeTab.R index c5a5b0d2..c146b95c 100644 --- a/R/mod_homeTab.R +++ b/R/mod_homeTab.R @@ -2,6 +2,8 @@ #' #' @param id module id #' +#' +#' @return A `shiny::fluidRow()` containing the home tab's layout. #' @export homeTabUI <- function(id) { @@ -21,6 +23,9 @@ homeTabUI <- function(id) { #' \code{app_startup()}. `homeTab()` uses the `homeTabPath` and `hexPath` #' elements. #' +#' +#' @return No return value. Called for its side effect of rendering the home tab's +#' text and hex sticker. #' @export homeTab <- function(input, output, session, config) { diff --git a/R/mod_loadCharts.R b/R/mod_loadCharts.R index 858095a0..8a99045e 100644 --- a/R/mod_loadCharts.R +++ b/R/mod_loadCharts.R @@ -3,6 +3,8 @@ #' @param id module id #' @param charts list containing chart specifications like those returned by \link{makeChartConfig}. #' +#' +#' @return The chart loader's Shiny UI. #' @importFrom purrr keep #' @importFrom sortable bucket_list add_rank_list #' @@ -27,6 +29,8 @@ loadChartsUI <- function(id, charts=makeChartConfig()){ #' @param session Shiny session object #' @param charts list containing chart specifications like those returned by \link{makeChartConfig}. #' +#' +#' @return A `shiny::reactive()` returning the list of charts the user has selected. #' @export loadCharts <- function(input, output, session, charts=makeChartConfig()) { diff --git a/R/mod_loadData.R b/R/mod_loadData.R index 9673952e..f284965c 100644 --- a/R/mod_loadData.R +++ b/R/mod_loadData.R @@ -3,6 +3,8 @@ #' @param id module id #' @param domain character vector with domains to be loaded #' +#' +#' @return The data loader's Shiny UI for one domain. #' @export loadDataUI <- function(id, domain=NULL){ @@ -25,6 +27,8 @@ loadDataUI <- function(id, domain=NULL){ #' @param output Shiny output object #' @param session Shiny session object #' +#' +#' @return A `shiny::reactive()` returning the data frame imported for this domain. #' @export loadData <- function(input, output, session, domain) { diff --git a/R/mod_mappingColumn.R b/R/mod_mappingColumn.R index b9b7ea25..ad7d3c66 100644 --- a/R/mod_mappingColumn.R +++ b/R/mod_mappingColumn.R @@ -5,6 +5,8 @@ #' @param data current data file for the domain #' @param mapping current data mapping for the column (and related fields) +#' +#' @return The Shiny UI for a single column mapping. #' @export mappingColumnUI <- function(id, meta, data, mapping=NULL){ diff --git a/R/mod_mappingDomain.R b/R/mod_mappingDomain.R index 38871694..705a0b9e 100644 --- a/R/mod_mappingDomain.R +++ b/R/mod_mappingDomain.R @@ -5,6 +5,8 @@ #' @param data data file for the domain #' @param mapping current data mapping #' +#' +#' @return The Shiny UI for one data domain's mappings. #' @export mappingDomainUI <- function(id, meta, data, mapping=NULL){ diff --git a/R/mod_mappingTab.R b/R/mod_mappingTab.R index d41bdf52..c15a16a0 100644 --- a/R/mod_mappingTab.R +++ b/R/mod_mappingTab.R @@ -6,6 +6,8 @@ #' @param mappings optional data frame containing stacked mappings for all domains #' @param standards optional list of data standards like the ones generated by \code{detectStandard()} #' +#' +#' @return The Shiny UI for the mapping tab. #' @importFrom stringr str_to_upper #' #' @export diff --git a/R/mod_safetyGraphicsServer.R b/R/mod_safetyGraphicsServer.R index 45e19c15..b5b6563a 100644 --- a/R/mod_safetyGraphicsServer.R +++ b/R/mod_safetyGraphicsServer.R @@ -12,6 +12,9 @@ #' @param filterDomain domain used for the data/filter tab. Demographics ("`dm`") is used by default. Using a domain that is not one record per participant is not recommended. #' @param config named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it. #' +#' +#' @return No return value. Called for its side effect of starting the application's +#' home, mapping, filter, chart and settings modules. #' @import shiny #' @import dplyr #' @importFrom purrr map diff --git a/R/mod_safetyGraphicsUI.R b/R/mod_safetyGraphicsUI.R index 069dfca5..39a7c256 100644 --- a/R/mod_safetyGraphicsUI.R +++ b/R/mod_safetyGraphicsUI.R @@ -8,6 +8,8 @@ #' @param standards a list of information regarding data standards. Each list item should use the format returned by safetyGraphics::detectStandard. #' @param config named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it. #' +#' +#' @return The Shiny UI for the whole application. #' @importFrom shinyjs useShinyjs #' #' @export diff --git a/R/mod_settingsCharts.R b/R/mod_settingsCharts.R index 98fafc9d..98685e2f 100644 --- a/R/mod_settingsCharts.R +++ b/R/mod_settingsCharts.R @@ -2,6 +2,8 @@ #' #' @param id module id #' +#' +#' @return The Shiny UI for the chart settings panel. #' @export settingsChartsUI <- function(id){ @@ -37,6 +39,9 @@ settingsChartsUI <- function(id){ #' @param session Shiny session object #' @param charts list data frame summarizing the charts #' +#' +#' @return No return value. Called for its side effect of rendering the chart +#' configuration as YAML. #' @import dplyr #' #' @export diff --git a/R/mod_settingsCode.R b/R/mod_settingsCode.R index 6280c131..1a0707c3 100644 --- a/R/mod_settingsCode.R +++ b/R/mod_settingsCode.R @@ -2,6 +2,8 @@ #' #' @param id module ID #' +#' +#' @return The Shiny UI for the code settings panel. #' @export settingsCodeUI <- function(id){ @@ -101,6 +103,9 @@ settingsCodeUI <- function(id){ #' @param charts charts #' @param domainData data list #' +#' +#' @return No return value. Called for its side effect of rendering the restart code +#' and registering the app download handler. #' @importFrom utils zip #' #' @export diff --git a/R/mod_settingsData.R b/R/mod_settingsData.R index 8d15aae3..c39ac184 100644 --- a/R/mod_settingsData.R +++ b/R/mod_settingsData.R @@ -4,6 +4,8 @@ #' #' @importFrom DT renderDT +#' +#' @return The Shiny UI for the data settings panel. #' @export settingsDataUI <- function(id){ @@ -26,6 +28,9 @@ settingsDataUI <- function(id){ #' @param session Shiny session object #' @param domains named list of the data.frames for each domain #' +#' +#' @return No return value. Called for its side effect of rendering a preview table +#' for each data domain. #' @export settingsData <- function(input, output, session, domains){ diff --git a/R/mod_settingsMapping.R b/R/mod_settingsMapping.R index 9b1b353e..62817b19 100644 --- a/R/mod_settingsMapping.R +++ b/R/mod_settingsMapping.R @@ -2,6 +2,8 @@ #' #' @param id module id #' +#' +#' @return The Shiny UI for the mapping settings panel. #' @import rclipboard #' #' @export @@ -26,6 +28,9 @@ settingsMappingUI <- function(id){ #' @param metadata Data mapping metadata used for initial loading of app #' @param mapping reactive data frame representing the current metadata mapping. columns = "domain", "text_id" and "current" #' +#' +#' @return No return value. Called for its side effect of rendering the mapping and +#' metadata tables. #' @import rclipboard #' @import yaml #' diff --git a/R/mod_settingsTab.R b/R/mod_settingsTab.R index 380cd13b..04416618 100644 --- a/R/mod_settingsTab.R +++ b/R/mod_settingsTab.R @@ -2,6 +2,8 @@ #' #' @param id module ID #' +#' +#' @return A `shiny::tabsetPanel()` containing the four settings panels. #' @export settingsTabUI <- function(id){ @@ -26,6 +28,9 @@ settingsTabUI <- function(id){ #' @param mapping mapping #' @param charts charts #' +#' +#' @return No return value. Called for its side effect of starting the mapping, +#' data, chart and code settings modules. #' @export settingsTab <- function(input, output, session, domains, metadata, mapping, charts){ diff --git a/R/safetyGraphicsApp.R b/R/safetyGraphicsApp.R index 15525ff4..7eb68ec5 100644 --- a/R/safetyGraphicsApp.R +++ b/R/safetyGraphicsApp.R @@ -13,6 +13,9 @@ #' @param launchBrowser boolean indicating whether to launch the app in a browser. default is false #' @param runNow Should the shiny app object created be run directly? Helpful when writing functions to dispatch to shinyapps, rsconnect, or shinyproxy. #' +#' +#' @return A Shiny app object, invisibly to the caller when `runNow` is `TRUE` +#' because the app is run before it is returned. #' @import shiny #' @import safetyData #' diff --git a/R/safetyGraphicsInit.R b/R/safetyGraphicsInit.R index bd5dc165..48d145f3 100644 --- a/R/safetyGraphicsInit.R +++ b/R/safetyGraphicsInit.R @@ -4,6 +4,9 @@ #' @param delayTime time (in ms) between drawing app UI and starting server. Default set to 1000 (1 second), but could need to be higher on slow machine. #' @param maxFileSize maximum file size in MB allowed for file upload #' +#' +#' @return No return value. Called for its side effect of running the initialisation +#' app, which in turn launches the main application. #' @import shiny #' @importFrom shinyjs hidden hide show delay disabled disable enable #' diff --git a/R/util-generateMappingList.R b/R/util-generateMappingList.R index 53d53374..994b1605 100644 --- a/R/util-generateMappingList.R +++ b/R/util-generateMappingList.R @@ -4,6 +4,10 @@ #' @param domain mapping domain to return (returns all domains as a named list by default) #' @param pull call pull() the value for each parameter - needed for testing only. default: FALSE #' +#' +#' @return A named list of data mappings. When `domain` names a single domain the +#' list holds that domain's mappings; otherwise it is a list of such lists, +#' one per domain. #' @importFrom stringr str_split #' @export diff --git a/cran-comments.md b/cran-comments.md index 825594df..6a060178 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -13,6 +13,8 @@ The version is 2.2.0. The last version on CRAN was 2.1.1, so the version had to `R CMD check --as-cran` reports "New submission" and "Package was archived on CRAN" in the incoming feasibility check. Both are expected for the resubmission of an archived package, and the reason for the archival is resolved as described above. +The package has an optional patient profile tab backed by 'safetyProfile', which is not on CRAN and never has been. It is therefore declared in no DESCRIPTION field: declaring it in Suggests would make the package uncheckable, and there is no repository to name in Additional_repositories. It is reached only through getExportedValue() behind a namespace-loaded guard, so safetyGraphics installs, checks and runs without it; the tab is simply absent. The manual points users at the GitHub repository for anyone who wants it. Please let me know if you would prefer this handled differently. + One URL in the Technical FAQ vignette is reported as possibly invalid: * https://www.hhs.gov/ohrp/sites/default/files/report-privacy-and-health-10-31-19.pdf returns 403 Forbidden. The server rejects automated requests, including from a client sending a full browser user-agent; the link is not dead. The other URLs previously flagged as moved have been updated to their current addresses. diff --git a/man/chartsNav.Rd b/man/chartsNav.Rd index b46e9f65..7799a81d 100644 --- a/man/chartsNav.Rd +++ b/man/chartsNav.Rd @@ -19,6 +19,10 @@ chartsNav(input, output, session, chart, data, mapping) \item{mapping}{tibble capturing the current data mappings (Reactive).} } +\value{ +No return value. Called for its side effect of starting the chart tab +module for this navbar entry. +} \description{ Server for a navbar tab } diff --git a/man/chartsTab.Rd b/man/chartsTab.Rd index 46d4985b..bd90fb22 100644 --- a/man/chartsTab.Rd +++ b/man/chartsTab.Rd @@ -21,6 +21,10 @@ chartsTab(input, output, session, chart, data, mapping, status) \item{status}{chart status (Reactive)} } +\value{ +No return value. Called for its side effect of rendering the chart and +wiring up its export handlers. +} \description{ Server for chart module, designed to be re-used for each chart generated. } diff --git a/man/chartsTabUI.Rd b/man/chartsTabUI.Rd index f27a9aea..5bd69920 100644 --- a/man/chartsTabUI.Rd +++ b/man/chartsTabUI.Rd @@ -11,6 +11,10 @@ chartsTabUI(id, chart) \item{chart}{list containing chart specifications like those returned by \link{makeChartConfig}.} } +\value{ +A list of two Shiny UI elements: the chart header and the chart +container. +} \description{ UI for chart module, designed to be re-used for each chart generated. } diff --git a/man/filterTabUI.Rd b/man/filterTabUI.Rd index 9c0841d5..82e83f08 100644 --- a/man/filterTabUI.Rd +++ b/man/filterTabUI.Rd @@ -9,6 +9,9 @@ filterTabUI(id) \arguments{ \item{id}{module id} } +\value{ +The filter module's Shiny UI. +} \description{ UI for the filter module in datamods::filter_data_ui } diff --git a/man/generateMappingList.Rd b/man/generateMappingList.Rd index b75d46b8..d84c8e7c 100644 --- a/man/generateMappingList.Rd +++ b/man/generateMappingList.Rd @@ -13,6 +13,11 @@ generateMappingList(settingsDF, domain = NULL, pull = FALSE) \item{pull}{call pull() the value for each parameter - needed for testing only. default: FALSE} } +\value{ +A named list of data mappings. When \code{domain} names a single domain the +list holds that domain's mappings; otherwise it is a list of such lists, +one per domain. +} \description{ Convert mapping data.frame to a list } diff --git a/man/homeTab.Rd b/man/homeTab.Rd index 2398a428..c107263f 100644 --- a/man/homeTab.Rd +++ b/man/homeTab.Rd @@ -17,6 +17,10 @@ homeTab(input, output, session, config) \code{app_startup()}. \code{homeTab()} uses the \code{homeTabPath} and \code{hexPath} elements.} } +\value{ +No return value. Called for its side effect of rendering the home tab's +text and hex sticker. +} \description{ Server for the filter module in datamods::filter_data_ui } diff --git a/man/homeTabUI.Rd b/man/homeTabUI.Rd index eb271cfd..7a094c48 100644 --- a/man/homeTabUI.Rd +++ b/man/homeTabUI.Rd @@ -9,6 +9,9 @@ homeTabUI(id) \arguments{ \item{id}{module id} } +\value{ +A \code{shiny::fluidRow()} containing the home tab's layout. +} \description{ UI for the home module } diff --git a/man/loadCharts.Rd b/man/loadCharts.Rd index f05f3d70..5af6f285 100644 --- a/man/loadCharts.Rd +++ b/man/loadCharts.Rd @@ -15,6 +15,9 @@ loadCharts(input, output, session, charts = makeChartConfig()) \item{charts}{list containing chart specifications like those returned by \link{makeChartConfig}.} } +\value{ +A \code{shiny::reactive()} returning the list of charts the user has selected. +} \description{ Server for the chart loading module used in safetyGraphicsInit() } diff --git a/man/loadChartsUI.Rd b/man/loadChartsUI.Rd index 174e180e..c8c110ab 100644 --- a/man/loadChartsUI.Rd +++ b/man/loadChartsUI.Rd @@ -11,6 +11,9 @@ loadChartsUI(id, charts = makeChartConfig()) \item{charts}{list containing chart specifications like those returned by \link{makeChartConfig}.} } +\value{ +The chart loader's Shiny UI. +} \description{ UI for the chart loading module used in safetyGraphicsInit() } diff --git a/man/loadData.Rd b/man/loadData.Rd index d47020a7..3caad445 100644 --- a/man/loadData.Rd +++ b/man/loadData.Rd @@ -15,6 +15,9 @@ loadData(input, output, session, domain) \item{domain}{data domain to be loaded} } +\value{ +A \code{shiny::reactive()} returning the data frame imported for this domain. +} \description{ Server for the data loading module used in safetyGraphicsInit() } diff --git a/man/loadDataUI.Rd b/man/loadDataUI.Rd index 2ed708d8..d407c12a 100644 --- a/man/loadDataUI.Rd +++ b/man/loadDataUI.Rd @@ -11,6 +11,9 @@ loadDataUI(id, domain = NULL) \item{domain}{character vector with domains to be loaded} } +\value{ +The data loader's Shiny UI for one domain. +} \description{ UI for the data loading module used in safetyGraphicsInit() } diff --git a/man/makeChartParams.Rd b/man/makeChartParams.Rd index 09b47c83..3f06b38c 100644 --- a/man/makeChartParams.Rd +++ b/man/makeChartParams.Rd @@ -13,6 +13,11 @@ makeChartParams(data, chart, mapping) \item{mapping}{data frame with current mapping} } +\value{ +A named list of parameters for the chart, ready to pass to the chart's +rendering function. For \code{htmlwidget} charts the list is the widget's +parameter object, with \code{data} and JSON-encoded \code{settings} attached. +} \description{ Updates raw data and mapping for use with a specific chart } diff --git a/man/makeChartSummary.Rd b/man/makeChartSummary.Rd index 1bdda058..fb24b685 100644 --- a/man/makeChartSummary.Rd +++ b/man/makeChartSummary.Rd @@ -20,6 +20,10 @@ makeChartSummary( \item{class}{character to include as class} } +\value{ +A \code{shiny::div()} summarising the chart: its label, type, data domains, +status and, when \code{showLinks} is \code{TRUE}, its documentation links. +} \description{ makes a nicely formatted html summary for a chart object } diff --git a/man/mappingColumnUI.Rd b/man/mappingColumnUI.Rd index d195c9c0..cfd489be 100644 --- a/man/mappingColumnUI.Rd +++ b/man/mappingColumnUI.Rd @@ -15,6 +15,9 @@ mappingColumnUI(id, meta, data, mapping = NULL) \item{mapping}{current data mapping for the column (and related fields)} } +\value{ +The Shiny UI for a single column mapping. +} \description{ UI that facilitates the mapping of a column data (and any associated fields) } diff --git a/man/mappingDomainUI.Rd b/man/mappingDomainUI.Rd index 960372ce..e5c4b648 100644 --- a/man/mappingDomainUI.Rd +++ b/man/mappingDomainUI.Rd @@ -15,6 +15,9 @@ mappingDomainUI(id, meta, data, mapping = NULL) \item{mapping}{current data mapping} } +\value{ +The Shiny UI for one data domain's mappings. +} \description{ UI that facilitates the mapping of a full data domain } diff --git a/man/mappingTabUI.Rd b/man/mappingTabUI.Rd index 08fec487..b1980eec 100644 --- a/man/mappingTabUI.Rd +++ b/man/mappingTabUI.Rd @@ -17,6 +17,9 @@ mappingTabUI(id, meta, domainData, mappings = NULL, standards = NULL) \item{standards}{optional list of data standards like the ones generated by \code{detectStandard()}} } +\value{ +The Shiny UI for the mapping tab. +} \description{ UI for mapping tab covering of all data domains } diff --git a/man/safetyGraphicsApp.Rd b/man/safetyGraphicsApp.Rd index 4936c37a..941ccfa6 100644 --- a/man/safetyGraphicsApp.Rd +++ b/man/safetyGraphicsApp.Rd @@ -46,6 +46,10 @@ safetyGraphicsApp( \item{runNow}{Should the shiny app object created be run directly? Helpful when writing functions to dispatch to shinyapps, rsconnect, or shinyproxy.} } +\value{ +A Shiny app object, invisibly to the caller when \code{runNow} is \code{TRUE} +because the app is run before it is returned. +} \description{ Run the core safetyGraphics App } diff --git a/man/safetyGraphicsInit.Rd b/man/safetyGraphicsInit.Rd index b4ac65b1..9c64fa79 100644 --- a/man/safetyGraphicsInit.Rd +++ b/man/safetyGraphicsInit.Rd @@ -17,6 +17,10 @@ safetyGraphicsInit( \item{maxFileSize}{maximum file size in MB allowed for file upload} } +\value{ +No return value. Called for its side effect of running the initialisation +app, which in turn launches the main application. +} \description{ App to select charts, load data and then initialize the core safetyGraphics app } diff --git a/man/safetyGraphicsServer.Rd b/man/safetyGraphicsServer.Rd index 68ee08e3..3569dc0d 100644 --- a/man/safetyGraphicsServer.Rd +++ b/man/safetyGraphicsServer.Rd @@ -35,6 +35,10 @@ safetyGraphicsServer( \item{config}{named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it.} } +\value{ +No return value. Called for its side effect of starting the application's +home, mapping, filter, chart and settings modules. +} \description{ This function returns a server function suitable for use in shiny::runApp() } diff --git a/man/safetyGraphicsUI.Rd b/man/safetyGraphicsUI.Rd index 9839b873..7dfa5676 100644 --- a/man/safetyGraphicsUI.Rd +++ b/man/safetyGraphicsUI.Rd @@ -21,6 +21,9 @@ safetyGraphicsUI(id, meta, mapping, domainData, charts, standards, config) \item{config}{named list of app configuration options as returned by \code{app_startup()}, passed through to the modules that need it.} } +\value{ +The Shiny UI for the whole application. +} \description{ UI for the core safetyGraphics app including Home, Mapping, Filter, Charts and Settings modules. } diff --git a/man/settingsCharts.Rd b/man/settingsCharts.Rd index f9ed6d3f..5e7fcec7 100644 --- a/man/settingsCharts.Rd +++ b/man/settingsCharts.Rd @@ -15,6 +15,10 @@ settingsCharts(input, output, session, charts) \item{charts}{list data frame summarizing the charts} } +\value{ +No return value. Called for its side effect of rendering the chart +configuration as YAML. +} \description{ Server for settings tab showing details for the charts loaded in the app } diff --git a/man/settingsChartsUI.Rd b/man/settingsChartsUI.Rd index ff68aac0..23e75a98 100644 --- a/man/settingsChartsUI.Rd +++ b/man/settingsChartsUI.Rd @@ -9,6 +9,9 @@ settingsChartsUI(id) \arguments{ \item{id}{module id} } +\value{ +The Shiny UI for the chart settings panel. +} \description{ UI for settings tab showing details for the charts loaded in the app } diff --git a/man/settingsCode.Rd b/man/settingsCode.Rd index 960f3465..db423b99 100644 --- a/man/settingsCode.Rd +++ b/man/settingsCode.Rd @@ -19,6 +19,10 @@ settingsCode(input, output, session, mapping, charts, domainData) \item{domainData}{data list} } +\value{ +No return value. Called for its side effect of rendering the restart code +and registering the app download handler. +} \description{ Server for settings tab providing code to re-start the app with current data/settings } diff --git a/man/settingsCodeUI.Rd b/man/settingsCodeUI.Rd index 7b54f1bc..1f3d62cd 100644 --- a/man/settingsCodeUI.Rd +++ b/man/settingsCodeUI.Rd @@ -9,6 +9,9 @@ settingsCodeUI(id) \arguments{ \item{id}{module ID} } +\value{ +The Shiny UI for the code settings panel. +} \description{ UI for settings tab providing code to re-start the app with current data/settings } diff --git a/man/settingsData.Rd b/man/settingsData.Rd index 745b953a..33fa3f67 100644 --- a/man/settingsData.Rd +++ b/man/settingsData.Rd @@ -15,6 +15,10 @@ settingsData(input, output, session, domains) \item{domains}{named list of the data.frames for each domain} } +\value{ +No return value. Called for its side effect of rendering a preview table +for each data domain. +} \description{ Server for settings tab showing current data } diff --git a/man/settingsDataUI.Rd b/man/settingsDataUI.Rd index 5a814d50..bf6a1274 100644 --- a/man/settingsDataUI.Rd +++ b/man/settingsDataUI.Rd @@ -9,6 +9,9 @@ settingsDataUI(id) \arguments{ \item{id}{module id} } +\value{ +The Shiny UI for the data settings panel. +} \description{ UI for settings tab showing current data } diff --git a/man/settingsMapping.Rd b/man/settingsMapping.Rd index bff64b23..838749b8 100644 --- a/man/settingsMapping.Rd +++ b/man/settingsMapping.Rd @@ -17,6 +17,10 @@ settingsMapping(input, output, session, metadata, mapping) \item{mapping}{reactive data frame representing the current metadata mapping. columns = "domain", "text_id" and "current"} } +\value{ +No return value. Called for its side effect of rendering the mapping and +metadata tables. +} \description{ Server for settings tab showing current mapping } diff --git a/man/settingsMappingUI.Rd b/man/settingsMappingUI.Rd index 3ee17585..38a64efa 100644 --- a/man/settingsMappingUI.Rd +++ b/man/settingsMappingUI.Rd @@ -9,6 +9,9 @@ settingsMappingUI(id) \arguments{ \item{id}{module id} } +\value{ +The Shiny UI for the mapping settings panel. +} \description{ UI for settings tab showing current mapping } diff --git a/man/settingsTab.Rd b/man/settingsTab.Rd index 79875ab4..9fb5a2b4 100644 --- a/man/settingsTab.Rd +++ b/man/settingsTab.Rd @@ -21,6 +21,10 @@ settingsTab(input, output, session, domains, metadata, mapping, charts) \item{charts}{charts} } +\value{ +No return value. Called for its side effect of starting the mapping, +data, chart and code settings modules. +} \description{ Server for the setting page } diff --git a/man/settingsTabUI.Rd b/man/settingsTabUI.Rd index 33df0d70..a8a7eb93 100644 --- a/man/settingsTabUI.Rd +++ b/man/settingsTabUI.Rd @@ -9,6 +9,9 @@ settingsTabUI(id) \arguments{ \item{id}{module ID} } +\value{ +A \code{shiny::tabsetPanel()} containing the four settings panels. +} \description{ UI for the settings tab }