Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.2 #722

Open
wants to merge 40 commits into
base: main
Choose a base branch
from
Open

v2.2 #722

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
82c0182
create getChartStatus() and add basic tests. #562
jwildfire Apr 17, 2022
da59bf3
starting on UI updates
jwildfire Apr 18, 2022
08e5fca
Merge branch 'dev' into fix-562
jwildfire May 23, 2022
3df73c5
Update R/getChartStatus.R
jwildfire May 23, 2022
4919803
refactor chart modules to simplify reactive flow
jwildfire May 24, 2022
c68d0be
add basic UI for chart status
jwildfire May 24, 2022
44bf28f
clear checks
jwildfire May 25, 2022
ff39083
server/ui params
jwildfire May 25, 2022
caca325
more ui updates
jwildfire Jun 2, 2022
ae5a37d
fix #692: add app-level settings
samussiah Jun 24, 2022
bc29c84
handle launchBrowser
samussiah Jun 24, 2022
c2c78ed
Merge pull request #699 from SafetyGraphics/main
jwildfire Dec 13, 2022
8979f42
Merge pull request #702 from SafetyGraphics/main
jwildfire Feb 2, 2023
0dd5377
basic profile integraion. #701
jwildfire Feb 2, 2023
c3fd0ff
update module call
jwildfire Feb 15, 2023
3c05b2e
add header showing selected participant
jwildfire Feb 16, 2023
0ba8d12
add chart event listeners and refactor widgets
samussiah Feb 24, 2023
f5094e3
document()
samussiah Feb 24, 2023
dc71c65
minor tweaks. re-run docs
jwildfire Mar 8, 2023
b64a38e
Merge branch 'dev' into fix-692
jwildfire Mar 8, 2023
be38a98
Merge pull request #693 from SafetyGraphics/fix-692
jwildfire Mar 8, 2023
46c0d5c
Merge pull request #706 from SafetyGraphics/fix-701-enhanced
jwildfire Mar 8, 2023
273e3bc
merge dev
jwildfire Mar 8, 2023
5cbedc7
fix merge conflict
jwildfire Mar 8, 2023
d38cc0f
make patProfile optional
jwildfire Mar 8, 2023
699c7d0
click pt id in header to show profile tab
jwildfire Mar 9, 2023
f9f5a50
merge dev
samussiah Mar 13, 2023
5ee1129
charts nav isn't working
samussiah Mar 13, 2023
9207f46
fix bug introduced in merge with dev
samussiah Mar 13, 2023
0610e25
add util- prefix to a few files
samussiah Mar 14, 2023
5accaf9
update generateMappingList to work with tbl_df-classed data frames
samussiah Mar 14, 2023
9f90959
remove `print`s
samussiah Mar 14, 2023
c95f77d
Merge pull request #670 from SafetyGraphics/fix-562
samussiah Mar 14, 2023
23c25ab
merge dev
samussiah Mar 15, 2023
b34bca0
Merge pull request #703 from SafetyGraphics/fix-701
samussiah Mar 15, 2023
530c54a
fix #716
samussiah May 5, 2023
f602cdc
Merge pull request #717 from SafetyGraphics/fix-716
samussiah May 8, 2023
5c1654c
remove header
jwildfire Jun 16, 2023
69ca2ff
update id selector css
jwildfire Jun 16, 2023
87f180e
Merge pull request #721 from SafetyGraphics/fix-720
samussiah Sep 14, 2023
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
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ Depends: R (>= 4.0)
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.2.1
RoxygenNote: 7.2.3
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 Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
export("%>%")
export(app_startup)
export(chartsNav)
export(chartsNavUI)
export(chartsTab)
export(chartsTabUI)
export(detectStandard)
Expand Down Expand Up @@ -32,6 +33,8 @@ export(mappingSelectUI)
export(mappingTab)
export(mappingTabUI)
export(prepareChart)
export(profileTab)
export(profileTabUI)
export(safetyGraphicsApp)
export(safetyGraphicsInit)
export(safetyGraphicsServer)
Expand Down Expand Up @@ -59,6 +62,8 @@ importFrom(magrittr,"%>%")
importFrom(purrr,keep)
importFrom(purrr,map)
importFrom(purrr,map2)
importFrom(purrr,map_lgl)
importFrom(purrr,set_names)
importFrom(rlang,.data)
importFrom(shiny,dataTableOutput)
importFrom(shiny,renderDataTable)
Expand All @@ -72,6 +77,7 @@ importFrom(shinyjs,hide)
importFrom(shinyjs,html)
importFrom(shinyjs,removeClass)
importFrom(shinyjs,show)
importFrom(shinyjs,toggleClass)
importFrom(shinyjs,useShinyjs)
importFrom(sortable,add_rank_list)
importFrom(sortable,bucket_list)
Expand Down
25 changes: 18 additions & 7 deletions R/app_startup.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#' @param autoMapping boolean indicating whether the app should attempt to automatically detect data standards and generate mappings for the data provided. Values specified in the `mapping` parameter overwrite automatically generated mappings when both are found. Defaults to true.
#' @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 chartSettingsPaths path(s) where customization functions are saved relative to your working directory. All charts can have initialization (e.g. myChart_Init.R) and static charts can have charting functions (e.g. myGraphic_Chart.R). All R files in this folder are sourced and files with the correct naming convention are linked to the chart. See the Custom Charts vignette for more details.
#'
#' @param appName character string defining the name of the app (default = "safetyGraphics")
#' @param hexPath path to image file with a hex or other logo. safetyGraphics hex used by default.
#' @param homeTabPath path to html content to be used on the home page. default is a summary of the safetyGraphics framework.
#'
#' @return List of elements for used to initialize the shiny app with the following parameters
#' \itemize{
Expand All @@ -21,7 +23,13 @@
#' }
#'
#' @export
app_startup<-function(domainData=NULL, meta=NULL, charts=NULL, mapping=NULL, autoMapping=NULL, filterDomain=NULL, chartSettingsPaths=NULL){
app_startup<-function(domainData=NULL, meta=NULL, charts=NULL, mapping=NULL, autoMapping=NULL, filterDomain=NULL, chartSettingsPaths=NULL, appName=NULL, hexPath=NULL, homeTabPath=NULL){

# Set defaults for app name, hex and home page content.
if (!is.character(appName)) appName <- 'safetyGraphics'
if (!is.character(hexPath) || !file.exists(hexPath)) hexPath <- system.file("resources/safetyGraphicsHex.png", package = "safetyGraphics")
if (!is.character(homeTabPath) || !file.exists(homeTabPath)) homeTabPath <- system.file('resources/safetyGraphicsHomeTab.html', package = 'safetyGraphics')

# If charts are not provided, load them from chartSettingsPath or the safetyCharts package
if(is.null(charts)){
if(is.null(chartSettingsPaths)){
Expand All @@ -47,18 +55,18 @@ app_startup<-function(domainData=NULL, meta=NULL, charts=NULL, mapping=NULL, aut
message("- Dropped ", length(envDrops), " chart(s) with `env` paramter missing or not set to 'safetyGraphics': ",paste(names(envDrops), collapse=", "))
}
charts <- charts %>% purrr::keep(~.x$envValid)

#Drop charts if data for required domain(s) is not found
domainDrops <- charts %>% purrr::keep(~(!all(.x$domain %in% names(domainData))))
if(length(domainDrops)>0){
message("- Dropped ", length(domainDrops), " chart(s) with missing data domains: ", paste(names(domainDrops), collapse=", "))
}
charts <- charts %>% purrr::keep(~all(.x$domain %in% names(domainData)))

# sort charts based on order
chartOrder <- order(charts %>% map_dbl(~.x$order) %>% unlist())
charts <- charts[chartOrder]

message("- Initializing app with ",length(charts), " chart(s).")

# Set filterDomain to NULL if specified domain doesn't exist
Expand All @@ -81,8 +89,11 @@ app_startup<-function(domainData=NULL, meta=NULL, charts=NULL, mapping=NULL, aut
domainData=domainData,
mapping=mappingObj$mapping,
standards=mappingObj$standard,
filterDomain=filterDomain
filterDomain=filterDomain,
appName=appName,
hexPath=hexPath,
homeTabPath = homeTabPath
)

return(config)
}
}
120 changes: 120 additions & 0 deletions R/getChartStatus.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#' Check the status of a chart based on the current mapping
#'
#' Checks a chart's status when column-level chart specifications are provided in chart$dataSpec.
#' Note that safetyGraphicsApp() does not allow a `mapping` value that is not found in `domainData`,
#' so this function only needs to check that an expected parameter exists in `mapping` (not that the
#' specified column is found in the loaded data).
#'
#' @param chart `list` chart object
#' @param mapping `data.frame` current mapping
#'
#' @return `list` Named list with properties:
#' - status `logical`
#' - domains `list` list specifying whether all columns are specified in each domain
#' - columns `list` list that matches the structure of chart$dataSpec and indicates which variables are available.
#'
#' @examples
#' sample_chart <- list(
#' 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")
#' )
#'
#' 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
#' })
#'
#' checks <- map(charts, ~getChartStatus(.x, .x$mapping))
#'
#' @importFrom purrr imap map
#' @importFrom rlang set_names
#'
#' @keywords internal
getChartStatus <- function(chart, mapping){
stopifnot(
"Can't get status since chart does not have dataSpec associated."=hasName(chart, 'dataSpec')
)

# check to see whether each individual column has a mapping defined
missingCols<-c()
colStatus <- names(chart$dataSpec) %>% map(function(domain){
domainMapping <- generateMappingList(settingsDF=mapping, domain=domain)
requiredCols <- chart$dataSpec[[domain]]
colStatus <- requiredCols %>% map(function(col){
if(hasName(domainMapping,col)){
status<-case_when(
domainMapping[[col]]=='' ~ FALSE,
is.na(domainMapping[[col]]) ~ FALSE,
is.character(domainMapping[[col]]) ~ TRUE
)
} else{
status<-FALSE
}
return(status)
}) %>% set_names(requiredCols)
return(colStatus)
})%>% set_names(names(chart$dataSpec))

# check to see whether all columns in a domain were valid
domainStatus <- colStatus %>%
map(~all(unlist(.x))) %>%
set_names(names(colStatus))

# check to see whether all columns in all domains were valid
status <- ifelse(all(unlist(domainStatus)),TRUE, FALSE)

# make a text summary
if(status){
summary <- "All required mappings found"
}else{
missingCols <- colStatus %>% imap(function(cols,domain){
missingDomainCols <- cols %>% imap(function(status, col){
if(status){
return(NULL)
}else{
return(paste0(domain,"$",col))
}
})
return(missingDomainCols)
})
summary<- paste0("Missing Mappings: ",paste(unlist(missingCols),collapse=","))
}

return(list(chart=chart$name, columns=colStatus, domains=domainStatus, status=status, summary=summary))
}
26 changes: 21 additions & 5 deletions R/makeChartSummary.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@
#' @description makes a nicely formatted html summary for a chart object
#'
#' @param chart list containing chart specifications
#' @param status (optional) chart status from `getChartStatus`. Default is NULL.
#' @param showLinks boolean indicating whether to include links
#' @param class character to include as class
#'
#' @export

makeChartSummary<- function(chart, showLinks=TRUE, class="chart-header"){
makeChartSummary<- function(chart, status=NULL, showLinks=TRUE, class="chart-header"){

if(!is.null(status)){
if(status$status){
status <- div(class="status", tags$small("Status"), tags$i(class="fa fa-check-circle", style="color: green"),title=status$summary)
}else{
status <- div(class="status", tags$small("Status"), tags$i(class="fa fa-times-circle", style="color: red"),title=status$summary)
}
}else{
status <- NULL
}

if(utils::hasName(chart,"links")){
links<-purrr::map2(
chart$links,
Expand All @@ -23,24 +35,28 @@ makeChartSummary<- function(chart, showLinks=TRUE, class="chart-header"){
}else{
links<-NULL
}

labelDiv<-div(tags$small("Chart"),chart$label)
typeDiv<-div(tags$small("Type"), chart$type)
dataDiv<-div(tags$small("Data Domain"), paste(chart$domain,collapse=" "))

labelDiv<-div(class="name", tags$small("Chart"),chart$label)
typeDiv<-div(class="type", tags$small("Type"), chart$type)
dataDiv<-div(class="domain", tags$small("Data Domain"), paste(chart$domain,collapse=" "))

class <- c('chart-summary',class)

if(showLinks){
summary<-div(
labelDiv,
typeDiv,
dataDiv,
links,
status,
class=class
)
} else {
summary<-div(
labelDiv,
typeDiv,
dataDiv,
status,
class=class
)
}
Expand Down
71 changes: 57 additions & 14 deletions R/mod_chartsNav.R
Original file line number Diff line number Diff line change
@@ -1,22 +1,65 @@
#' Adds a navbar tab that initializes the Chart Module UI
#'
#' @param chart chart metadata
#' @param ns namespace
#' @param id module id
#' @param chart chart metadata
#'
#' @export
#'

chartsNav <- function(chart,ns){
appendTab(
inputId = "safetyGraphicsApp",
menuName = "Charts",
tab = tabPanel(
title = makeChartSummary(chart, showLinks=FALSE, class="chart-nav"),
value = chart$name,
chartsTabUI(
id=ns(chart$name),
chart=chart
)
chartsNavUI <- function(id, chart) {
ns <- NS(id)

panel<-tabPanel(
title = uiOutput(ns("tabTitle")),
value = chart$name,
chartsTabUI(
id=ns("chart"),
chart=chart
)
)
}

return(panel)
}

#' Server for a navbar tab
#'
#' @param input Input objects from module namespace
#' @param output Output objects from module namespace
#' @param session An environment that can be used to access information and functionality relating to the session
#' @param chart list containing a safetyGraphics chart object like those returned by \link{makeChartConfig}.
#' @param data named list of current data sets (Reactive).
#' @param mapping tibble capturing the current data mappings (Reactive).
#'
#' @export
#'

chartsNav<-function(input, output, session, chart, data, mapping){
ns <- session$ns

chartStatus <- reactive({
if(hasName(chart, 'dataSpec')){
status<-getChartStatus(chart, mapping())
}else{
status<-NULL
}
return(status)
})

output$tabTitle <- renderUI({
makeChartSummary(
chart,
status=chartStatus(),
showLinks=FALSE,
class="chart-nav"
)
})

callModule(
module=chartsTab,
id='chart',
chart=chart,
data=data,
mapping=mapping,
status=chartStatus
)
}
Loading
Loading