Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@


^CRAN-SUBMISSION$
^R/_disable_autoload\.R$
9 changes: 4 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -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"),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 31 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
# 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.
- 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 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`.
- 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.
- 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

Resolves a bug that was causing unexpected data filters on initial load.
Expand Down
76 changes: 35 additions & 41 deletions R/getChartStatus.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
#'
Expand Down
4 changes: 4 additions & 0 deletions R/makeChartParams.R
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down
3 changes: 3 additions & 0 deletions R/makeChartSummary.R
Original file line number Diff line number Diff line change
Expand Up @@ -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"){
Expand Down
6 changes: 6 additions & 0 deletions R/mod_chartsNav.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
#'

Expand Down Expand Up @@ -30,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
#'

Expand Down
6 changes: 6 additions & 0 deletions R/mod_chartsTab.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
#'
Expand All @@ -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){
Expand Down
2 changes: 2 additions & 0 deletions R/mod_filterTab.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#'
#' @param id module id
#'
#'
#' @return The filter module's Shiny UI.
#' @import datamods
#' @importFrom shiny dataTableOutput
#'
Expand Down
8 changes: 8 additions & 0 deletions R/mod_homeTab.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#'
#' @param id module id
#'
#'
#' @return A `shiny::fluidRow()` containing the home tab's layout.
#' @export

homeTabUI <- function(id) {
Expand All @@ -17,7 +19,13 @@ 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.
#'
#'
#' @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) {
Expand Down
4 changes: 4 additions & 0 deletions R/mod_loadCharts.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
#'
Expand All @@ -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()) {
Expand Down
4 changes: 4 additions & 0 deletions R/mod_loadData.R
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions R/mod_mappingColumn.R
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down
2 changes: 2 additions & 0 deletions R/mod_mappingDomain.R
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down
2 changes: 2 additions & 0 deletions R/mod_mappingTab.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading