Skip to content

[Bug]: plot with settings does not support bootstrap 4 and 5 #245

@Polkas

Description

@Polkas

What happened?

The modal widget in plot with settings is too narrow for bootstrap 4 and 5.
We will be happy to solve that.
Please write if you are welcome for our collabo.

image

image

Reproducible Example for Safety app (line plot Module):

# We set bootsrap 5
options("teal.bs_theme" = bslib::bs_theme(version = "5"))

library(teal.modules.general)
library(teal.modules.clinical)
options(shiny.useragg = FALSE)

## Data reproducible code ----
data <- teal_data()
data <- within(data, {
    library(random.cdisc.data)
    library(dplyr)
    library(nestcolor)
    # optional libraries
    library(sparkline)
    
    ADSL <- radsl(seed = 1)
    ADAE <- radae(ADSL, seed = 1)
    ADAETTE <- radaette(ADSL, seed = 1)
    ADAETTE <- ADAETTE %>%
        mutate(is_event = case_when(
            grepl("TOT", .data$PARAMCD, fixed = TRUE) ~ TRUE,
            TRUE ~ CNSR == 0
        )) %>%
        mutate(n_events = case_when(
            grepl("TOT", .data$PARAMCD, fixed = TRUE) ~ as.integer(.data$AVAL),
            TRUE ~ as.integer(is_event)
        )) %>%
        teal.data::col_relabel(is_event = "Is an Event") %>%
        teal.data::col_relabel(n_events = "Number of Events")
    ADAETTE_AE <-
        filter(ADAETTE, grepl("TOT", .data$PARAMCD, fixed = TRUE)) %>% select(-"AVAL")
    ADAETTE_OTH <-
        filter(ADAETTE, !(grepl("TOT", .data$PARAMCD, fixed = TRUE)))
    
    ADAETTE_TTE <- ADAETTE %>%
        filter(PARAMCD == "AEREPTTE") %>%
        select(USUBJID, ARM, ARMCD, AVAL)
    
    ADAETTE_AE <-
        full_join(ADAETTE_AE, ADAETTE_TTE, by = c("USUBJID", "ARM", "ARMCD"))
    ADAETTE <- rbind(ADAETTE_AE, ADAETTE_OTH)
    
    ADEX <- radex(ADSL, seed = 1)
    ADEX_labels <- teal.data::col_labels(ADEX, fill = FALSE)
    # Below steps are done to simulate data with TDURD parameter as it is not in the ADEX data from `random.cdisc.data` package
    set.seed(1, kind = "Mersenne-Twister")
    ADEX <- ADEX %>%
        distinct(USUBJID, .keep_all = TRUE) %>%
        mutate(
            PARAMCD = "TDURD",
            PARAM = "Overall duration (days)",
            AVAL = sample(
                x = seq(1, 200),
                size = n(),
                replace = TRUE
            ),
            AVALU = "Days",
            PARCAT1 = "OVERALL"
        ) %>%
        bind_rows(ADEX)
    ADEX <- ADEX %>%
        filter(PARCAT1 == "OVERALL" &
                   PARAMCD %in% c("TDOSE", "TNDOSE", "TDURD"))
    teal.data::col_labels(ADEX) <- ADEX_labels
    
    ADLB <- radlb(ADSL, seed = 1)
    
    ADEG <- radeg(ADSL, seed = 1)
    
    # For real data, ADVS needs some preprocessing like group different ANRIND and BNRIND into abnormal
    ADVS <- radvs(ADSL, seed = 1) %>%
        mutate(ONTRTFL = ifelse(AVISIT %in% c("SCREENING", "BASELINE"), "", "Y")) %>%
        teal.data::col_relabel(ONTRTFL = "On Treatment Record Flag") %>%
        mutate(ANRIND = as.character(ANRIND), BNRIND = as.character(BNRIND)) %>%
        mutate(
            ANRIND = case_when(
                ANRIND == "HIGH HIGH" ~ "HIGH",
                ANRIND == "LOW LOW" ~ "LOW",
                TRUE ~ ANRIND
            ),
            BNRIND = case_when(
                BNRIND == "HIGH HIGH" ~ "HIGH",
                BNRIND == "LOW LOW" ~ "LOW",
                TRUE ~ BNRIND
            )
        )
    
    ADCM <- radcm(ADSL, seed = 1) %>% mutate(CMSEQ = as.integer(CMSEQ))
    
    # Add study-specific pre-processing: convert arm, param and visit variables to factors
    # Sample code:
    # ADSL$ACTARM <- factor(ADSL$ACTARM)
    # ADAE$AETOXGR <- factor(ADAE$AETOXGR)
    # ADLB <- ADLB %>%
    #   tern::df_explicit_na(omit_columns = setdiff(names(ADLB), c("PARAM", "PARAMCD", "AVISIT") ))
    # ADEX <- ADEX %>%
    #   tern::df_explicit_na(omit_columns = setdiff(names(ADEX), c("PARAM", "PARAMCD", "PARCAT2") ))
    
    # define study-specific analysis subgroups and baskets from ADAE
    add_event_flags <- function(dat) {
        dat %>%
            dplyr::mutate(
                TMPFL_SER = AESER == "Y",
                TMPFL_REL = AEREL == "Y",
                TMPFL_GR5 = AETOXGR == "5",
                TMP_SMQ01 = !is.na(SMQ01NAM),
                TMP_SMQ02 = !is.na(SMQ02NAM),
                TMP_CQ01 = !is.na(CQ01NAM)
            ) %>%
            teal.data::col_relabel(
                TMPFL_SER = "Serious AE",
                TMPFL_REL = "Related AE",
                TMPFL_GR5 = "Grade 5 AE",
                TMP_SMQ01 = aesi_label(dat$SMQ01NAM, dat$SMQ01SC),
                TMP_SMQ02 = aesi_label(dat$SMQ02NAM, dat$SMQ02SC),
                TMP_CQ01 = aesi_label(dat$CQ01NAM)
            )
    }
    
    ADAE <- ADAE %>%
        add_event_flags()
})

datanames <- c("ADSL", "ADAE", "ADAETTE", "ADEX", "ADLB", "ADEG", "ADVS", "ADCM")
datanames(data) <- datanames
join_keys(data) <- default_cdisc_join_keys[datanames]

## App configuration ----
ADSL <- data[["ADSL"]]
ADAE <- data[["ADAE"]]
ADAETTE <- data[["ADAETTE"]]
ADEX <- data[["ADEX"]]
ADLB <- data[["ADLB"]]
ADEG <- data[["ADEG"]]
ADVS <- data[["ADVS"]]
ADCM <- data[["ADCM"]]

arm_vars <- c("ACTARMCD", "ACTARM")

## Create variable type lists
date_vars_adsl <-
    names(ADSL)[vapply(ADSL, function(x) {
        inherits(x, c("Date", "POSIXct", "POSIXlt"))
    }, logical(1))]
demog_vars_adsl <-
    names(ADSL)[!(names(ADSL) %in% c("USUBJID", "STUDYID", date_vars_adsl))]



cs_arm_var <-
    choices_selected(
        choices = variable_choices(ADSL, subset = arm_vars),
        selected = "ACTARM"
    )

ae_anl_vars <- names(ADAE)[startsWith(names(ADAE), "TMPFL_")]
# flag variables for AE baskets; set to NULL if not applicable to study
aesi_vars <-
    names(ADAE)[startsWith(names(ADAE), "TMP_SMQ") |
                    startsWith(names(ADAE), "TMP_CQ")]

## App header and footer ----
nest_logo <- "https://raw.githubusercontent.com/insightsengineering/hex-stickers/main/PNG/nest.png"
app_source <- "https://github.com/insightsengineering/teal.gallery/tree/main/safety"
gh_issues_page <- "https://github.com/insightsengineering/teal.gallery/issues"

header <- tags$span(
    style = "display: flex; align-items: center; justify-content: space-between; margin: 10px 0 10px 0;",
    tags$span("My first teal app", style = "font-size: 30px;"),
    tags$span(
        style = "display: flex; align-items: center;",
        tags$img(src = nest_logo, alt = "NEST logo", height = "45px", style = "margin-right:10px;"),
        tags$span(style = "font-size: 24px;", "NEST @ Roche")
    )
)

footer <- tags$p(
    "This teal app is brought to you by the NEST Team at Roche/Genentech.
        For more information, please visit:",
    tags$a(href = app_source, target = "_blank", "Source Code"), ", ",
    tags$a(href = gh_issues_page, target = "_blank", "Report Issues")
)

## Setup App
app <- teal::init(
    data = data,
    title = build_app_title("Safety Analysis Teal Demo App", nest_logo),
    header = header,
    footer = footer,
    # Set initial filter state as safety-evaluable population
    filter = teal_slices(
        count_type = "all",
        teal_slice(dataname = "ADSL", varname = "SAFFL", selected = "Y"),
        teal_slice(dataname = "ADSL", varname = "SEX"),
        teal_slice(dataname = "ADSL", varname = "AGE"),
        teal_slice(dataname = "ADLB", varname = "AVAL"),
        # default filter
        teal_slice(dataname = "ADEX", varname = "AVAL"),
        # default filter
        teal_slice(dataname = "ADEG", varname = "AVAL")
    ),
    modules = modules(
        tm_front_page(
            label = "App Info",
            header_text = c("Info about input data source" = "This app uses CDISC ADaM datasets randomly generated by `random.cdisc.data` R packages"),
            tables = list(`NEST packages used in this demo app` = data.frame(
                Packages = c(
                    "teal.modules.general",
                    "teal.modules.clinical",
                    "random.cdisc.data"
                )
            ))
        ),
        tm_data_table("Data Table"),
        tm_variable_browser("Variable Browser"),
        tm_t_summary(
            label = "Demographic Table",
            dataname = "ADSL",
            arm_var = cs_arm_var,
            summarize_vars = choices_selected(
                choices = variable_choices(ADSL, demog_vars_adsl),
                selected = c("SEX", "AGE", "RACE")
            )
        ),
        modules(
            label = "Adverse Events",
            tm_t_events_summary(
                label = "AE Summary",
                dataname = "ADAE",
                arm_var = cs_arm_var,
                flag_var_anl = choices_selected(
                    choices = variable_choices("ADAE", ae_anl_vars),
                    selected = ae_anl_vars,
                    keep_order = TRUE
                ),
                flag_var_aesi = choices_selected(
                    choices = variable_choices("ADAE", aesi_vars),
                    selected = aesi_vars,
                    keep_order = TRUE
                ),
                add_total = TRUE
            ),
            tm_t_events(
                label = "AE by Term",
                dataname = "ADAE",
                arm_var = cs_arm_var,
                llt = choices_selected(
                    choices = variable_choices(ADAE, c("AETERM", "AEDECOD")),
                    selected = c("AEDECOD")
                ),
                hlt = choices_selected(
                    choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")),
                    selected = "AEBODSYS"
                ),
                add_total = TRUE,
                event_type = "adverse event"
            ),
            tm_t_events_by_grade(
                label = "AE Table by Grade",
                dataname = "ADAE",
                arm_var = cs_arm_var,
                llt = choices_selected(
                    choices = variable_choices(ADAE, c("AEDECOD")),
                    selected = c("AEDECOD")
                ),
                hlt = choices_selected(
                    choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")),
                    selected = "AEBODSYS"
                ),
                grade = choices_selected(
                    choices = variable_choices(ADAE, c("AETOXGR")),
                    selected = "AETOXGR"
                ),
                add_total = TRUE
            ),
            tm_t_events_patyear(
                label = "AE Rates Adjusted for Patient-Years at Risk",
                dataname = "ADAETTE",
                arm_var = cs_arm_var,
                paramcd = choices_selected(
                    choices = value_choices(ADAETTE, "PARAMCD", "PARAM"),
                    selected = "AETTE1"
                ),
                events_var = choices_selected(
                    choices = variable_choices(ADAETTE, "n_events"),
                    selected = "n_events",
                    fixed = TRUE
                )
            ),
            tm_t_smq(
                label = "Adverse Events by SMQ Table",
                dataname = "ADAE",
                arm_var = choices_selected(
                    choices = variable_choices(ADSL, subset = c(arm_vars, "SEX")),
                    selected = "ACTARM"
                ),
                add_total = FALSE,
                baskets = choices_selected(
                    choices = variable_choices(ADAE, subset = grep("^(SMQ|CQ).*NAM$", names(ADAE), value = TRUE)),
                    selected = grep("^(SMQ|CQ).*NAM$", names(ADAE), value = TRUE)
                ),
                scopes = choices_selected(
                    choices = variable_choices(ADAE, subset = grep("^SMQ.*SC$", names(ADAE), value = TRUE)),
                    selected = grep("^SMQ.*SC$", names(ADAE), value = TRUE),
                    fixed = TRUE
                ),
                llt = choices_selected(
                    choices = variable_choices(ADAE, subset = c("AEDECOD")),
                    selected = "AEDECOD"
                )
            )
        ),
        modules(
            label = "Lab Tables",
            tm_t_summary_by(
                label = "Labs Summary",
                dataname = "ADLB",
                arm_var = cs_arm_var,
                by_vars = choices_selected(
                    choices = variable_choices(ADLB, c("PARAM", "AVISIT")),
                    selected = c("PARAM", "AVISIT"),
                    fixed = TRUE
                ),
                summarize_vars = choices_selected(
                    choices = variable_choices(ADLB, c("AVAL", "CHG")),
                    selected = c("AVAL")
                ),
                paramcd = choices_selected(
                    choices = value_choices(ADLB, "PARAMCD", "PARAM"),
                    selected = "ALT"
                )
            ),
            tm_t_shift_by_grade(
                label = "Grade Laboratory Abnormality Table",
                dataname = "ADLB",
                arm_var = cs_arm_var,
                paramcd = choices_selected(
                    choices = value_choices(ADLB, "PARAMCD", "PARAM"),
                    selected = "ALT"
                ),
                worst_flag_var = choices_selected(
                    choices = variable_choices(ADLB, subset = c(
                        "WGRLOVFL", "WGRLOFL", "WGRHIVFL", "WGRHIFL"
                    )),
                    selected = c("WGRLOVFL")
                ),
                worst_flag_indicator = choices_selected(
                    value_choices(ADLB, "WGRLOVFL"),
                    selected = "Y",
                    fixed = TRUE
                ),
                anl_toxgrade_var = choices_selected(
                    choices = variable_choices(ADLB, subset = c("ATOXGR")),
                    selected = c("ATOXGR"),
                    fixed = TRUE
                ),
                base_toxgrade_var = choices_selected(
                    choices = variable_choices(ADLB, subset = c("BTOXGR")),
                    selected = c("BTOXGR"),
                    fixed = TRUE
                ),
                add_total = FALSE
            ),
            tm_t_abnormality_by_worst_grade(
                label = "Laboratory test results with highest grade post-baseline",
                dataname = "ADLB",
                arm_var = choices_selected(
                    choices = variable_choices(ADSL, subset = c("ARM", "ARMCD")),
                    selected = "ARM"
                ),
                paramcd = choices_selected(
                    choices = value_choices(ADLB, "PARAMCD", "PARAM"),
                    selected = c("ALT", "CRP", "IGA")
                ),
                add_total = FALSE
            )
        ),
        modules(
            label = "Exposure",
            tm_t_summary_by(
                label = "Exposure Summary",
                dataname = "ADEX",
                arm_var = cs_arm_var,
                by_vars = choices_selected(
                    choices = variable_choices(ADEX, c("PARCAT2", "PARAM")),
                    selected = c("PARCAT2", "PARAM"),
                    fixed = TRUE
                ),
                summarize_vars = choices_selected(
                    choices = variable_choices(ADEX, "AVAL"),
                    selected = c("AVAL"),
                    fixed = TRUE
                ),
                paramcd = choices_selected(
                    choices = value_choices(ADEX, "PARAMCD", "PARAM"),
                    selected = "TDOSE"
                ),
                denominator = choices_selected(
                    choices = c("n", "N", "omit"),
                    selected = "n"
                )
            ),
            tm_t_exposure(
                label = "Duration of Exposure Table",
                dataname = "ADEX",
                paramcd = choices_selected(
                    choices = value_choices(ADEX, "PARAMCD", "PARAM"),
                    selected = "TDURD",
                    fixed = TRUE
                ),
                col_by_var = choices_selected(
                    choices = variable_choices(ADEX, subset = c(arm_vars, "SEX")),
                    selected = "SEX"
                ),
                row_by_var = choices_selected(
                    choices = variable_choices(
                        ADEX,
                        subset = c("RACE", "REGION1", "STRATA1", "SEX")
                    ),
                    selected = "RACE"
                ),
                parcat = choices_selected(
                    choices = value_choices(ADEX, "PARCAT2"),
                    selected = "Drug A"
                ),
                add_total = FALSE
            )
        ),
        tm_t_abnormality(
            label = "Vital Signs Abnormality",
            dataname = "ADVS",
            arm_var = cs_arm_var,
            id_var = choices_selected(
                choices = variable_choices(ADSL, subset = "USUBJID"),
                selected = "USUBJID",
                fixed = TRUE
            ),
            by_vars = choices_selected(
                choices = variable_choices(ADVS, subset = c("PARAM", "AVISIT")),
                selected = c("PARAM"),
                keep_order = TRUE
            ),
            grade = choices_selected(
                choices = variable_choices(ADVS, subset = "ANRIND"),
                selected = "ANRIND",
                fixed = TRUE
            ),
            abnormal = list(low = "LOW", high = "HIGH")
        ),
        tm_t_mult_events(
            label = "Concomitant Medication",
            dataname = "ADCM",
            arm_var = cs_arm_var,
            seq_var = choices_selected("CMSEQ", selected = "CMSEQ", fixed = TRUE),
            hlt = choices_selected(
                choices = variable_choices(ADCM, c(
                    "ATC1", "ATC2", "ATC3", "ATC4"
                )),
                selected = "ATC2"
            ),
            llt = choices_selected(
                choices = variable_choices(ADCM, c("CMDECOD")),
                selected = "CMDECOD",
                fixed = TRUE
            ),
            add_total = TRUE,
            event_type = "treatment"
        ),
        tm_t_shift_by_arm(
            label = "ECG Shift Table by Arm",
            dataname = "ADEG",
            arm_var = cs_arm_var,
            paramcd = choices_selected(value_choices(ADEG, "PARAMCD"),
                                       selected = "HR"
            ),
            visit_var = choices_selected(value_choices(ADEG, "AVISIT"),
                                         selected = "POST-BASELINE MINIMUM"
            ),
            aval_var = choices_selected(
                variable_choices(ADEG, subset = "ANRIND"),
                selected = "ANRIND",
                fixed = TRUE
            ),
            baseline_var = choices_selected(
                variable_choices(ADEG, subset = "BNRIND"),
                selected = "BNRIND",
                fixed = TRUE
            )
        ),
        tm_g_lineplot(
            label = "Line Plot",
            dataname = "ADLB",
            strata = cs_arm_var,
            x = choices_selected(variable_choices(ADLB, "AVISIT"), "AVISIT", fixed = TRUE),
            y = choices_selected(variable_choices(ADLB, c(
                "AVAL", "BASE", "CHG", "PCHG"
            )), "AVAL"),
            y_unit = choices_selected(variable_choices(ADLB, "AVALU"), "AVALU", fixed = TRUE),
            paramcd = choices_selected(variable_choices(ADLB, "PARAMCD"), "PARAMCD", fixed = TRUE),
            param = choices_selected(value_choices(ADLB, "PARAMCD", "PARAM"), "ALT"),
            plot_height = c(1000L, 200L, 4000L)
        )
    )
)

shinyApp(app$ui, app$server)

sessionInfo()

R version 4.2.2 (2022-10-31)

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

other attached packages:
 [1] efficacy_0.1.0              DT_0.32                     shinyWidgets_0.8.1         
 [4] teal.widgets_0.4.2          ggforce_0.4.2               forcats_1.0.0              
 [7] tidyr_1.3.1                 sparkline_2.0               nestcolor_0.1.2            
[10] dplyr_1.1.4                 random.cdisc.data_0.3.15    teal.modules.clinical_0.9.0
[13] tern_0.9.3                  rtables_0.6.6               magrittr_2.0.3             
[16] formatters_0.5.5            teal.modules.general_0.3.0  teal.transform_0.5.0       
[19] teal_0.15.2                 teal.slice_0.5.0            teal.data_0.5.0            
[22] teal.code_0.5.0             shiny_1.8.0                 ggmosaic_0.3.3             
[25] ggplot2_3.5.0              

loaded via a namespace (and not attached):
  [1] backports_1.4.1       Hmisc_5.1-2           lazyeval_0.2.2        splines_4.2.2        
  [5] crosstalk_1.2.1       teal.logger_0.1.3     usethis_2.2.3         TH.data_1.1-2        
  [9] tern.gee_0.1.3        digest_0.6.34         htmltools_0.5.7       fansi_1.0.6          
 [13] checkmate_2.3.1       memoise_2.0.1         cluster_2.1.4         remotes_2.4.2.1      
 [17] sandwich_3.1-0        timechange_0.3.0      colorspace_2.1-0      ggrepel_0.9.5        
 [21] haven_2.5.4           rbibutils_2.2.16      xfun_0.42             crayon_1.5.2         
 [25] jsonlite_1.8.8        survival_3.4-0        zoo_1.8-12            glue_1.7.0           
 [29] geepack_1.3.10        polyclip_1.10-6       gtable_0.3.4          emmeans_1.10.0       
 [33] pkgbuild_1.4.3        scales_1.3.0          mvtnorm_1.2-4         miniUI_0.1.1.1       
 [37] Rcpp_1.0.12           viridisLite_0.4.2     xtable_1.8-4          htmlTable_2.4.2      
 [41] foreign_0.8-83        Formula_1.2-5         profvis_0.3.8         htmlwidgets_1.6.4    
 [45] httr_1.4.7            ellipsis_0.3.2        urlchecker_1.0.1      pkgconfig_2.0.3      
 [49] farver_2.1.1          nnet_7.3-18           sass_0.4.8            utf8_1.2.4           
 [53] labeling_0.4.3        tidyselect_1.2.0      rlang_1.1.3           later_1.3.2          
 [57] munsell_0.5.0         tools_4.2.2           cachem_1.0.8          cli_3.6.2            
 [61] generics_0.1.3        devtools_2.4.5        broom_1.0.5           evaluate_0.23        
 [65] stringr_1.5.1         fastmap_1.1.1         yaml_2.3.8            knitr_1.45           
 [69] fs_1.6.3              shinycssloaders_1.0.0 purrr_1.0.2           teal.reporter_0.3.0  
 [73] nlme_3.1-160          mime_0.12             compiler_4.2.2        rstudioapi_0.15.0    
 [77] plotly_4.10.4         tibble_3.2.1          tweenr_2.0.3          bslib_0.6.1          
 [81] stringi_1.8.3         desc_1.4.3            logger_0.2.2          lattice_0.20-45      
 [85] Matrix_1.6-5          shinyjs_2.1.0         vctrs_0.6.5           pillar_1.9.0         
 [89] lifecycle_1.0.4       BiocManager_1.30.22   Rdpack_2.6            jquerylib_0.1.4      
 [93] estimability_1.4.1    cowplot_1.1.3         data.table_1.15.0     httpuv_1.6.14        
 [97] R6_2.5.1              promises_1.2.1        renv_1.0.4            gridExtra_2.3        
[101] sessioninfo_1.2.2     codetools_0.2-18      MASS_7.3-58.1         pkgload_1.3.4        
[105] fontawesome_0.5.2     rprojroot_2.0.4       withr_3.0.0           multcomp_1.4-25      
[109] hms_1.1.3             shinyvalidate_0.1.3   grid_4.2.2            rpart_4.1.19         
[113] rmarkdown_2.25        lubridate_1.9.3       base64enc_0.1-3

Relevant log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct.

Contribution Guidelines

  • I agree to follow this project's Contribution Guidelines.

Security Policy

  • I agree to follow this project's Security Policy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions