diff --git a/.Rbuildignore b/.Rbuildignore index 0739872e..982a1d70 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -27,3 +27,4 @@ vignettes/x0* ^doc$ ^Meta$ ^CRAN-SUBMISSION$ +^scripts$ diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 08b6cee3..2458444b 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -4,7 +4,7 @@ on: push: branches: [main, master] pull_request: - branches: [main, master, for_cranny] + branches: [main, master, devel] release: types: [published] workflow_dispatch: diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION new file mode 100644 index 00000000..3e5e6caa --- /dev/null +++ b/CRAN-SUBMISSION @@ -0,0 +1,3 @@ +Version: 0.2.0 +Date: 2023-02-03 16:27:30 UTC +SHA: d30f87b5819d7624f7ef1a8527430cbe747255ce diff --git a/DESCRIPTION b/DESCRIPTION index 5ece4c08..64f6f707 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,37 +1,37 @@ Package: tidyCDISC Title: Quick Table Generation & Exploratory Analyses on ADaM-Ish Datasets -Version: 0.1.1 +Version: 0.2.0 Authors@R: c( - person("Aaron", "Clark", , "clark.aaronchris@gmail.com", - role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0123-0970")), + person("Aaron", "Clark", , "clark.aaronchris@gmail.com", role = c("aut", "cre"), + comment = c(ORCID = "0000-0002-0123-0970")), + person("Jeff", "Thompson", , "jeff.thompson51317@gmail.com", role = "aut"), + person("Teresa", "Wilson", , "teresadwilson@gmail.com", role = "aut"), person("Nate", "Mockler", , "nate.mockler@biogen.com", role = c("ccp", "led")), person("Maya", "Gans", , "maya.gans@biogen.com", role = "aut"), person("Robert", "Krajcik", , "robert.krajcik@biogen.com", role = "ctb"), person("Marly", "Gotti", , "marly.cormar@biogen.com", role = "ctb"), - person(given = "Jeff", family = "Thompson", - email = "jeff.thompson51317@gmail.com", role = "ctb"), person("Biogen", "Inc", role = "cph") ) Description: Provides users a quick exploratory dive into common visualizations without writing a single line of code given the users - data follows the Analysis Data Model (ADaM) standards put forth by - the Clinical Data Interchange Standards Consortium - (CDISC) . Prominent modules/ features of the application are the Table - Generator, Population Explorer, and the Individual Explorer. The Table - Generator allows users to drag and drop variables and desired statistics - (frequencies, means, ANOVA, t-test, and other summary statistics) into - bins that automagically create stunning tables with validated - information. The Population Explorer offers various plots to visualize - general trends in the population from various vantage points. Plot - modules currently include scatter plot, spaghetti plot, box plot, - histogram, means plot, and bar plot. Each plot type allows the user to - plot uploaded variables against one another, and dissect the - population by filtering out certain subjects. Last, the Individual - Explorer establishes a cohesive patient narrative, allowing the user - to interact with patient metrics (params) by visit or plotting - important patient events on a timeline. All modules allow for concise - filtering & downloading bulk outputs into html or pdf formats to save - for later. + data follows the Analysis Data Model (ADaM) standards put forth by the + Clinical Data Interchange Standards Consortium (CDISC) + . Prominent modules/ features of the + application are the Table Generator, Population Explorer, and the + Individual Explorer. The Table Generator allows users to drag and drop + variables and desired statistics (frequencies, means, ANOVA, t-test, + and other summary statistics) into bins that automagically create + stunning tables with validated information. The Population Explorer + offers various plots to visualize general trends in the population + from various vantage points. Plot modules currently include scatter + plot, spaghetti plot, box plot, histogram, means plot, and bar plot. + Each plot type allows the user to plot uploaded variables against one + another, and dissect the population by filtering out certain subjects. + Last, the Individual Explorer establishes a cohesive patient + narrative, allowing the user to interact with patient metrics (params) + by visit or plotting important patient events on a timeline. All + modules allow for concise filtering & downloading bulk outputs into + html or pdf formats to save for later. License: AGPL (>= 3) URL: https://Biogen-Inc.github.io/tidyCDISC/ BugReports: https://github.com/Biogen-Inc/tidyCDISC/issues @@ -65,11 +65,11 @@ Imports: tippy (== 0.1.0) Suggests: knitr, - pkgdown, spelling, testthat +VignetteBuilder: + knitr Encoding: UTF-8 Language: en-US LazyData: true RoxygenNote: 7.2.0 -VignetteBuilder: knitr diff --git a/NEWS.md b/NEWS.md index a0e4bded..3e386936 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,23 +1,31 @@ + +# tidyCDISC 0.2.0 (CRAN Release) + +* Added RTF export option for download from the Table Generator. +* Cleaned up JS to 'standard analyses' drop down. +* Created "ALL" as dropdown option for 'standard analysis' Table 41 instead of auto populating all available weeks in the drop zone. +* added protocol / study id in prominent location on each tab +* designed `ATPT` variable integration in the Table Generator (when present in data) +* added `OS Health` & `riskmetric` badges to the `README` +* engineered more user-friendly function to create the table generator output from the block data +* ensured Table Generator output automatically updates the table name when a 'standard analysis' is selected +* Fixed some Population Explorer filtering issues +* Added an `app.R` file so that shiny app can be ran directly from `shiny::runGitHub()` or `runUrl()` + + # tidyCDISC 0.1.1 * automated a footnote with **Source** and **Run Date** in table generation - * allowed custom user-defined footnotes - * allowed the selection of 'All' when a time/visit-based statistic is chosen in the table generator - * cleaned up downloadable R Script to replicate table generator output - * fixed bug where `data_from` was erroneously listed as a grouping option in the population explorer # tidyCDISC 0.1.0 (CRAN Release) * cleaning up `devtools::check()` & preparing for CRAN release. - * unfortunately, had to revert back to importing `tippy 0.1.0` since it is the latest available version on CRAN and CRAN pkgs cannot depend on package versions under development. - * created a new toggle on the `Data` tab that allows users to select which CDISC pilot study data sources they wish to use in the app. - * Minor bug improvements # tidyCDISC 0.0.4 @@ -44,20 +52,20 @@ This release (PR #65) performs a lot of functions, testing on many non-pilot ADS This release adds meat to the previous skeleton version of `tidyCDISC`. The initial development release was intended to be a "bare bones" platform that could serve as a foundation to build a great clinical data exploratory tool. Version `0.0.1` enriches the user experience by adding useful & commonly needed features for analysis. For more on this release, see [the announcement](https://biogen-inc.github.io/tidyCDISC/articles/Blog.html#announcing-tidycdisc-0-0-1-1) on our blog. -- Major Features added, by tab: - - **Table Generator** - - New "STAT Blocks", such as `Y FREQ`, `MAX FREQ`, `NON-MISSING`, and a pair of `NESTED FREQ` blocks - - Interact with `ADAE` - - 17 new 'standard analysis' tables in the `ADAE` and `ADLB` space. - - An R Script download-er to reproduce analysis performed in the app - - **Population Explorer** - - New Chart types - - line plot - means over time - - Heat map - endpoint correlations - - Kaplan Meier Curve (when `TTE` class data uploaded) -- Upgraded `pkgdown` site documentation to be more robust and hassle-free for developers -- Depends on updated version of IDEAFilter (>= 0.1.0.9000) -- Squashed bugs and other minor improvements +* Major Features added, by tab: + * **Table Generator** + * New "STAT Blocks", such as `Y FREQ`, `MAX FREQ`, `NON-MISSING`, and a pair of `NESTED FREQ` blocks + * Interact with `ADAE` + * 17 new 'standard analysis' tables in the `ADAE` and `ADLB` space. + * An R Script download-er to reproduce analysis performed in the app + * **Population Explorer** + * New Chart types + * line plot - means over time + * Heat map - endpoint correlations + * Kaplan Meier Curve (when `TTE` class data uploaded) +* Upgraded `pkgdown` site documentation to be more robust and hassle-free for developers +* Depends on updated version of IDEAFilter (>= 0.1.0.9000) +* Squashed bugs and other minor improvements # tidyCDISC 0.0.0.9000 diff --git a/R/data-phuse_TDF_ADaM.R b/R/data-phuse_TDF_ADaM.R index c2377d91..16e6fd18 100644 --- a/R/data-phuse_TDF_ADaM.R +++ b/R/data-phuse_TDF_ADaM.R @@ -5,7 +5,6 @@ #' #' @source , downloaded 2020-06-17 #' @format Data frame with 254 features and 51 fields -#' "adsl" @@ -16,7 +15,6 @@ #' @source , downloaded 2020-06-17 #' #' @format Data frame with 32,740 features and 58 fields -#' "adlbc" @@ -27,7 +25,6 @@ #' @source , downloaded 2020-06-17 #' #' @format Data frame with 32,139 features and 34 fields -#' "advs" @@ -38,7 +35,6 @@ #' @source , downloaded 2020-06-17 #' #' @format Data frame with 32,139 features and 34 fields -#' "adae" @@ -49,5 +45,4 @@ #' @source , downloaded 2021-01-26 #' #' @format Data frame with 32,740 features and 58 fields -#' "adtte" \ No newline at end of file diff --git a/R/golem_utils_ui.R b/R/golem_utils_ui.R index 7bd04769..38ef4672 100644 --- a/R/golem_utils_ui.R +++ b/R/golem_utils_ui.R @@ -246,40 +246,47 @@ col_12 <- function(...){ column(12, ...) } +#' @noRd #' @importFrom shiny column col_10 <- function(...){ column(10, ...) } +#' @noRd #' @importFrom shiny column col_8 <- function(...){ column(8, ...) } +#' @noRd #' @importFrom shiny column col_6 <- function(...){ column(6, ...) } +#' @noRd #' @importFrom shiny column col_4 <- function(...){ column(4, ...) } +#' @noRd #' @importFrom shiny column col_3 <- function(...){ column(3, ...) } +#' @noRd #' @importFrom shiny column col_2 <- function(...){ column(2, ...) } +#' @noRd #' @importFrom shiny column col_1 <- function(...){ column(1, ...) diff --git a/R/mod_dataComplyRules_fct_helpers.R b/R/mod_dataComplyRules_fct_helpers.R index 37f0ac0c..a866ed36 100644 --- a/R/mod_dataComplyRules_fct_helpers.R +++ b/R/mod_dataComplyRules_fct_helpers.R @@ -79,7 +79,7 @@ df_incl_rules <- #' #' @family dataComply Functions #' @keywords internal -#' +#' @noRd gather_rules <- function(input, output, session, all_df_rules = list(error = c(""), warn = c("") ), expl_rules = list( list(error = c(""), warn = c("")) ), diff --git a/R/mod_dataUpload.R b/R/mod_dataUpload.R index 575ac51d..e247fa3e 100644 --- a/R/mod_dataUpload.R +++ b/R/mod_dataUpload.R @@ -33,6 +33,7 @@ mod_dataUpload_ui <- function(id){ tooltip = shinyWidgets::tooltipOptions(title = "Click to change pilot data selections!") )) ), + div(uiOutput(ns("study_data_upload")), style = "padding-left: 20px", class = "studyid"), fluidRow( style = "padding: 20px", column(3, @@ -167,6 +168,12 @@ mod_dataUpload_server <- function(input, output, session){ paste0("Warning: data uploaded from multiple studies: ", paste(studies(), collapse = " & ")) }) + output$study_data_upload <- renderUI({ + req(studies()) + study_ids <- paste(studies(), collapse = " & ") + h4(paste("Study ID: ", study_ids)) + }) + # upon a dataset being uploaded and selected, generate data preview output$datapreview_header <- renderUI({ data_selected() diff --git a/R/mod_indvExpPatEvents.R b/R/mod_indvExpPatEvents.R index 2bf1af56..6473367c 100644 --- a/R/mod_indvExpPatEvents.R +++ b/R/mod_indvExpPatEvents.R @@ -104,12 +104,12 @@ mod_indvExpPatEvents_server <- function(input, output, session, shinyjs::show(id = "eventsPlot") if("MH_" %in% substr(uni_rec$DOMAIN,1,3)){ - tab <- uni_rec %>% select(-START, -END, -DOMAIN) + tab <- uni_rec %>% select(EVENTTYP, tab_st, tab_en, DECODE) date_cols <- c("Start of Event","End of Event") } else{ date_cols <- "Date of Event" - tab <- uni_rec %>% select(-END, -tab_st, -tab_en, -DOMAIN) + tab <- uni_rec %>% select(EVENTTYP, START, DECODE) } output$eventsTable <- DT::renderDataTable(server = FALSE, { # This allows for downloading entire data set diff --git a/R/mod_indvExp_fct_buildEvents.R b/R/mod_indvExp_fct_buildEvents.R index b23fb9e5..23d7138c 100644 --- a/R/mod_indvExp_fct_buildEvents.R +++ b/R/mod_indvExp_fct_buildEvents.R @@ -89,10 +89,10 @@ build_events <- function( tab_st = ifelse(as.character(START) == "", NA_character_, as.character(START)), # disp chr in DT tab_en = ifelse(as.character(END) == "", NA_character_, as.character(END)) # disp chr in DT ) %>% - distinct(USUBJID, EVENTTYP, START, END, - tab_st, - tab_en, - DECODE, DOMAIN)%>% + distinct(USUBJID, START, + DECODE, EVENTTYP, + DOMAIN, END, + tab_st, tab_en)%>% select(-starts_with("DS")) diff --git a/R/mod_indvExp_srv.R b/R/mod_indvExp_srv.R index 7ce931b5..b066e235 100644 --- a/R/mod_indvExp_srv.R +++ b/R/mod_indvExp_srv.R @@ -39,6 +39,14 @@ mod_indvExp_server <- function(input, output, session, datafile){ } }) + output$study_indv_exp <- renderUI({ + req(datafile()) + + studies <- unique(unlist(lapply(datafile(), `[[`, "STUDYID"))) + study_ids <- paste(studies, collapse = " & ") + h4(paste("Study ID: ", study_ids)) + }) + # Only select data that starts with AD followed by one or more alphanumerics or underscore my_loaded_adams <- reactive({ req(!is.null(datafile())) diff --git a/R/mod_indvExp_ui.R b/R/mod_indvExp_ui.R index 0418b5ce..c23bfcd6 100644 --- a/R/mod_indvExp_ui.R +++ b/R/mod_indvExp_ui.R @@ -25,6 +25,7 @@ mod_indvExp_ui <- function(id){ tagList( h1("Individual Explorer", align = "center"), br(), br(), br(), + div(uiOutput(ns("study_indv_exp")), style = "padding-bottom: 20px", class = "studyid"), fluidRow( column(3, wellPanel( diff --git a/R/mod_popExp.R b/R/mod_popExp.R index d2e7eae0..7d4fe778 100644 --- a/R/mod_popExp.R +++ b/R/mod_popExp.R @@ -26,6 +26,18 @@ mod_popExp_server <- function(input, output, session, datafile) { } }) + output$study_pop_exp <- renderUI({ + req(datafile()) + + studies <- unique(unlist(lapply(datafile(), `[[`, "STUDYID"))) + study_ids <- paste(studies, collapse = " & ") + h4(paste("Study ID: ", study_ids)) + }) + + col_list <- eventReactive(datafile(), { + map(datafile(), colnames) + }) + # show/hide checkboxes depending on radiobutton selection process <- eventReactive(datafile(), { @@ -155,12 +167,11 @@ mod_popExp_server <- function(input, output, session, datafile) { # Data to provide IDEAFilter feed_filter <- reactive({ - if(input$apply_filters == TRUE){ - req(input$filter_df) - all_data() %>% subset(data_from %in% input$filter_df) - } else { - all_data() - } + all_data() %>% subset(data_from %in% input$filter_df) + }) + + filter_cols <- reactive({ + col_list()[input$filter_df] %>% unlist() }) # Data NOT provided to IDEAFilter... will need to subset later @@ -173,16 +184,31 @@ mod_popExp_server <- function(input, output, session, datafile) { }) # Call IDEAFilter Module - filtered_data <- callModule( + filters <- callModule( IDEAFilter::shiny_data_filter, "data_filter", # whatever you named the widget - data = feed_filter, # the name of your pre-processed data + data = reactive(feed_filter()[filter_cols()]), # the name of your pre-processed data verbose = FALSE) + filtered_data <- eventReactive(filters(), { + if (input$apply_filters == FALSE) { + all_data() + } else if (any(regexpr("%>%",capture.output(attr(filters(), "code"))) > 0)) { + attr(filters(), "code") %>% + capture.output() %>% + paste(collapse = "") %>% + str_replace("^.*?(%>%)", "feed_filter\\(\\) \\1") %>% + rlang::parse_expr() %>% + rlang::eval_tidy() + } else { + feed_filter() + } + }) + # Update datset, depending on apply_filters or filtered_data() changing dataset <- eventReactive(list(input$apply_filters,filtered_data()), { - if (!is.null(filtered_data()) && input$apply_filters == TRUE ) { + if (input$apply_filters == TRUE && !is.null(filtered_data())) { req(input$filter_df) # needed 100% as this can be slow to update, causing an error @@ -268,10 +294,10 @@ mod_popExp_server <- function(input, output, session, datafile) { # Output text string of what was filtered in IDEAFilter widget/ module output$applied_filters <- renderUI({ req( - any(regexpr("%>%",capture.output(attr(filtered_data(), "code"))) > 0) + any(regexpr("%>%",capture.output(attr(filters(), "code"))) > 0) & input$apply_filters == TRUE ) - filters_in_english(filtered_data()) + filters_in_english(filters()) }) p_data <- diff --git a/R/mod_popExp_ui.R b/R/mod_popExp_ui.R index 6ddc90b6..4c77178f 100644 --- a/R/mod_popExp_ui.R +++ b/R/mod_popExp_ui.R @@ -28,6 +28,7 @@ mod_popExp_ui <- function(id, label = "Population Explorer"){ h1("Population Explorer", align = "center"), br(), br(), br(), + div(uiOutput(ns("study_pop_exp")), class = "studyid"), fluidRow( column(width = 3, div(id = "pop_cic_adv_filtering", class="filter-accordion", diff --git a/R/mod_tableGen.R b/R/mod_tableGen.R index 6a937f93..7893ee6c 100644 --- a/R/mod_tableGen.R +++ b/R/mod_tableGen.R @@ -32,6 +32,14 @@ mod_tableGen_server <- function(input, output, session, datafile = reactive(NULL tg_guide$init()$start() }) + output$study_table_gen <- renderUI({ + req(datafile()) + + studies <- unique(unlist(lapply(datafile(), `[[`, "STUDYID"))) + study_ids <- paste(studies, collapse = " & ") + h4(paste("Study ID: ", study_ids)) + }) + output$stan_recipe_ui <- renderUI({ HTML(paste(' - - - - ` - } + +function selectRecipeBlock(newid, df, selection, values = '') { + return `
+ + + +
` +} // this is used for combining block rows (on either the Var or STAT agg // side) scanning through the array, and appends to the html above @@ -42,77 +34,59 @@ function combineRows(block_array, df) { return(t) } - -/* -// this similar to combineRows above, but will add additional array into -// the mix and loops through that too, creating a var block for every combo -// between the two arrays. Depracated. -function multiplyCombineRows(var_block, df, select_input) { - let t = [] - var_block.forEach(function (blk) { - select_input.forEach(function () { - t.push(simpleRecipeRowBlock(blk, df)) - }); - }); - t= t.join("") - return(t) -} +/** + * Create dropdown menu from the array of AVISIT values +* @param {avisit} the text and value of the option */ - - -/* -// this is selecting one stat block (that contains a selectInput) -// and then scans sets the selection options/choices to only have one -// value - one stat block per option choices. For example, it can Create -// a mean block for every week that exists in the study. Helpful for -// table 41 style tables of lab actuals by param and week or PK style -// tables. Depracated. -function oneAgg_eachOption(var_block, agg_stat, df, select_input) { - let t = []; - var_block.forEach(function () { - select_input.forEach(function (sel_input) { - t.push(selectRecipeBlock(agg_stat, df, sel_input)); - }); - }); - t= t.join(""); - return(t); +function createOption(opt) { + return `` } -*/ - // The following function creates a stat block for every var block on // the LHS, and creates a dropdown. The var_block and select_input arrays // must be of the same length. Used for Table 41. -function oneAgg_combineSelects(var_block, agg_stat, df, select_input) { +function oneAgg_combineSelects(var_block, agg_stat, df, select_options) { let t = Array(var_block.length); for(var i = 0; i < var_block.length; i += 1){ - t.push(selectRecipeBlock(agg_stat, df, select_input[i])) + t.push(selectRecipeBlock(agg_stat, df, "ALL", select_options)) }; t= t.join("") return(t) } - - // These are called arrays -demography_rows = ["AGEGR1", "AGE", "SEX", "ETHNIC", "RACE", "HEIGHTBL", "WEIGHTBL"] -demography_agg = ["FREQ", "MEAN", "FREQ", "FREQ", "FREQ", "MEAN", "MEAN"] +const demography_rows = ["AGEGR1", "AGE", "SEX", "ETHNIC", "RACE", "HEIGHTBL", "WEIGHTBL"] +const demography_agg = ["FREQ", "MEAN", "FREQ", "FREQ", "FREQ", "MEAN", "MEAN"] + +const ae18_rows = ["AOCCFL", "AESEV", "AESER","DTHDT"] +const ae18_agg = ["Y_FREQ", "MAX_FREQ", "Y_FREQ", "NON_MISSING"] -ae18_rows = ["AOCCFL", "AESEV", "AESER","DTHDT"] -ae18_agg = ["Y_FREQ", "MAX_FREQ", "Y_FREQ", "NON_MISSING"] +const soc_pt_rows = ["AOCCFL", "AEBODSYS"] +const soc_pt_agg = ["Y_FREQ", "NESTED_FREQ_DSC"] +const soc_pt_sel = ["NONE", "AEDECOD"] -soc_pt_rows = ["AOCCFL", "AEBODSYS"] -soc_pt_agg = ["Y_FREQ", "NESTED_FREQ_DSC"] -soc_pt_sel = ["NONE", "AEDECOD"] +let bc_obj = null; +Shiny.addCustomMessageHandler('adlbc', function(adlbc) { + bc_obj = adlbc; +}); +let he_obj = null; +Shiny.addCustomMessageHandler('adlbh', function(adlbh) { + he_obj = adlbh; +}); +let ur_obj = null; +Shiny.addCustomMessageHandler('adlbu', function(adlbu) { + ur_obj = adlbu; +}) +$(document).on('click', '#RECIPE', function(){ /* Create custom block recipes to automatically populate when selected */ - $("#RECIPE").bind("change", function(event, ui) { - var publisher = $("#RECIPE").val(); - if (publisher === "Table 3: Accounting of Subjects") { - +$("#RECIPE").bind("change", function(event, ui) { + let publisher = $("#RECIPE").val(); + switch(publisher) { + case "Table 3: Accounting of Subjects": document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(simpleRecipeRowBlock("RANDFL", "ADSL"))); $("#droppable_blocks").append($(simpleRecipeRowBlock("SAFFL", "ADSL"))); @@ -124,110 +98,84 @@ soc_pt_sel = ["NONE", "AEDECOD"] $("#droppable_agg").append($(simpleRecipeRowBlock("FREQ", "ADSL"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_ABC", "ADSL", "DCTREAS"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_ABC", "ADSL", "DCSREAS"))); - } else if (publisher === "Table 5: Demography") { + break; + case "Table 5: Demography": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(combineRows(demography_agg, "ADSL"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(combineRows(demography_rows, "ADSL"))); - - - } else if (publisher === "Table 18: Overall summary of adverse events") { + break; + case "Table 18: Overall summary of adverse events": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(combineRows(ae18_agg, "ADAE"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(combineRows(ae18_rows, "ADAE"))); - - - } else if (publisher === "Table 20: Adverse events by system organ class and preferred term sorted by alphabetical order") { + break; + case "Table 20: Adverse events by system organ class and preferred term sorted by alphabetical order": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(simpleRecipeRowBlock("NON_MISSING", "ADAE"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_ABC", "ADAE", "AEDECOD"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(simpleRecipeRowBlock("USUBJID", "ADAE"))); $("#droppable_blocks").append($(simpleRecipeRowBlock("AEBODSYS", "ADAE"))); - - - } - else if (["Table 19: Adverse events by system organ class and preferred term sorted by decreasing frequency", - "Table 25: Severe adverse events by system organ class and preferred term", - "Table 29: Related adverse events by system organ class and preferred term", - "Table 30: Serious adverse events by system organ class and preferred term", - "Table 33: Related serious adverse events by system organ class and preferred term", - "Table 34: Adverse events that led to discontinuation of study treatment by system organ class and preferred term", - "Table 36: Adverse events that led to withdrawl from study by system organ class and preferred term", - "Table 38: Adverse events that led to drug interrupted, dose reduced, or dose increased by system organ class and preferred term"].includes(publisher)) { - + break; + case "Table 19: Adverse events by system organ class and preferred term sorted by decreasing frequency": + case "Table 25: Severe adverse events by system organ class and preferred term": + case "Table 29: Related adverse events by system organ class and preferred term": + case "Table 30: Serious adverse events by system organ class and preferred term": + case "Table 33: Related serious adverse events by system organ class and preferred term": + case "Table 34: Adverse events that led to discontinuation of study treatment by system organ class and preferred term": + case "Table 36: Adverse events that led to withdrawal from study by system organ class and preferred term": + case "Table 38: Adverse events that led to drug interrupted, dose reduced, or dose increased by system organ class and preferred term": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(simpleRecipeRowBlock("NON_MISSING", "ADAE"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_DSC", "ADAE", "AEDECOD"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(simpleRecipeRowBlock("USUBJID", "ADAE"))); $("#droppable_blocks").append($(simpleRecipeRowBlock("AEBODSYS", "ADAE"))); - - - } else if (publisher === "Table 21: Adverse events by system organ class") { + break; + case "Table 21: Adverse events by system organ class": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(simpleRecipeRowBlock("NON_MISSING", "ADAE"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_DSC", "ADAE", "NONE"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(simpleRecipeRowBlock("USUBJID", "ADAE"))); $("#droppable_blocks").append($(simpleRecipeRowBlock("AEBODSYS", "ADAE"))); - - - } else if (["Table 23: Adverse events by preferred term", - "Table 26: Severe adverse events by preferred term", - "Table 31: Serious adverse events by preferred term"].includes(publisher)) { + break; + case "Table 23: Adverse events by preferred term": + case "Table 26: Severe adverse events by preferred term": + case "Table 31: Serious adverse events by preferred term": document.getElementById("droppable_agg").innerHTML = ""; $("#droppable_agg").append($(simpleRecipeRowBlock("NON_MISSING", "ADAE"))); $("#droppable_agg").append($(selectRecipeBlock("NESTED_FREQ_DSC", "ADAE", "NONE"))); document.getElementById("droppable_blocks").innerHTML = ""; $("#droppable_blocks").append($(simpleRecipeRowBlock("USUBJID", "ADAE"))); $("#droppable_blocks").append($(simpleRecipeRowBlock("AEDECOD", "ADAE"))); - - } else if (publisher === "Table 41: Blood Chemistry actual values by visit"){ - - c_params = Object.values(bc); - c_weeks = Object.values(bc_wks); - document.getElementById("droppable_agg").innerHTML = ""; - //$("#droppable_agg").append($(oneAgg_eachOption(c_params,"MEAN","ADLB",weeks))); - $("#droppable_agg").append($(oneAgg_combineSelects(c_params,"MEAN","ADLB",c_weeks))); - document.getElementById("droppable_blocks").innerHTML = ""; - //$("#droppable_blocks").append($(multiplyCombineRows(c_params, "ADLB", weeks))); - $("#droppable_blocks").append($(combineRows(c_params, "ADLB"))); - - } else if (publisher === "Table 41: Hematology actual values by visit"){ - - h_params = Object.values(he); - h_weeks = Object.values(he_wks); - document.getElementById("droppable_agg").innerHTML = ""; - //$("#droppable_agg").append($(oneAgg_eachOption(h_params,"MEAN","ADLB",weeks))); - $("#droppable_agg").append($(oneAgg_combineSelects(h_params,"MEAN","ADLB",h_weeks))); - document.getElementById("droppable_blocks").innerHTML = ""; - //$("#droppable_blocks").append($(multiplyCombineRows(h_params, "ADLB", weeks))); - $("#droppable_blocks").append($(combineRows(h_params, "ADLB"))); - - } else if (publisher === "Table 41: Urinalysis actual values by visit"){ - - //document.getElementById("droppable_agg").innerHTML = ""; - //$("#droppable_agg").append($(combineRows(demography_agg, "ADSL"))); - //document.getElementById("droppable_blocks").innerHTML = ""; - //$("#droppable_blocks").append($(combineRows(demography_rows, "ADSL"))); - u_params = Object.values(ur); - u_weeks = Object.values(ur_wks); - document.getElementById("droppable_agg").innerHTML = ""; - //$("#droppable_agg").append($(oneAgg_eachOption(u_params,"MEAN","ADLB",weeks))); - $("#droppable_agg").append($(oneAgg_combineSelects(u_params,"MEAN","ADLB",u_weeks))); - document.getElementById("droppable_blocks").innerHTML = ""; - //$("#droppable_blocks").append($(multiplyCombineRows(u_params, "ADLB", weeks))); - $("#droppable_blocks").append($(combineRows(u_params, "ADLB"))); - - } else { + break; + case "Table 41: Blood Chemistry actual values by visit": + let select_opts = `${bc_obj.weeks.map(createOption).join("")}` document.getElementById("droppable_agg").innerHTML = ""; + $("#droppable_agg").append($(oneAgg_combineSelects(bc_obj.params, "MEAN", "ADLB", select_opts))); document.getElementById("droppable_blocks").innerHTML = ""; - } - }); - - + $("#droppable_blocks").append($(combineRows(bc_obj.params, "ADLB"))); + break; + case "Table 41: Hematology actual values by visit": + document.getElementById("droppable_agg").innerHTML = ""; + $("#droppable_agg").append($(oneAgg_combineSelects(he_obj.params,"MEAN","ADLB",he_obj.weeks))); + document.getElementById("droppable_blocks").innerHTML = ""; + $("#droppable_blocks").append($(combineRows(he_obj.params, "ADLB"))); + break; + case "Table 41: Urinalysis actual values by visit": + document.getElementById("droppable_agg").innerHTML = ""; + $("#droppable_agg").append($(oneAgg_combineSelects(ur_obj.params,"MEAN","ADLB",ur_obj.weeks))); + document.getElementById("droppable_blocks").innerHTML = ""; + $("#droppable_blocks").append($(combineRows(ur_obj.params, "ADLB"))); + break; + default: + document.getElementById("droppable_agg").innerHTML = ""; + document.getElementById("droppable_blocks").innerHTML = ""; + } +}); $('select#RECIPE').change(function() { var selectedDropdown = $(this).children('option:selected').val() @@ -236,11 +184,3 @@ $('select#RECIPE').change(function() { }); // $(document).on('click', '#RECIPE' }); // $document.ready() - -}); // end of adlbu_params -}); // end of adlbh_params -}); // end of adlbc_params -}); // end of urin weeks -}); // end of hema weeks -}); // end of chem weeks - diff --git a/inst/app/www/script.js b/inst/app/www/script.js index ba0f64b2..8b445dd8 100644 --- a/inst/app/www/script.js +++ b/inst/app/www/script.js @@ -33,16 +33,18 @@ $( document ).ready(function() { var str = ""; $('#' + id).each(function() { txt = $(this).text() - df = $(this).attr("class").split(" ")[1] - val = $(this).parent().find("select").children("option:selected").val() + df = $(this).attr("class").split(" ")[1] + grp = $(this).parent().find(":selected").parent().attr("label") + val = $(this).parent().find(":selected").val() lst = []; if (val === "ALL") { - for (let i = 2; i < $(this).parent().find("select").children().length; i++) { - lst.push($(this).parent().find("select").children()[i].text); + for (let i = 0; i < $(this).parent().find(":selected").parent().children().length; i++) { + if (["NONE", "ALL"].includes($(this).parent().find(":selected").parent().children()[i].text)) { continue; } + lst.push($(this).parent().find(":selected").parent().children()[i].text); } } str += `${df}*${txt.replace(" ", "")}*${val} + `.replace(/\r?\n|\r/g, "") - obj.numbers.push({txt,df,val,lst}) + obj.numbers.push({txt,df,grp,val,lst}) }) // currently return a string seperated by + // and blocks must be one word - this is very fragile! @@ -226,9 +228,9 @@ Shiny.addCustomMessageHandler('my_weeks', function(df) { * @param {newid} the new, unique id of the dropped block * @param {label} the name of the new block */ - function selectBlock(newid, label, values) { + function selectBlock(newid, label, values, df = "") { return `
- +