From 1e85fd347f0766290b65392781c7ca9b7ff8176b Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Wed, 30 Apr 2025 10:02:29 +0200 Subject: [PATCH 1/6] reset outputs on updated data --- R/app_version.R | 2 +- R/data_plots.R | 20 ++- R/regression-module.R | 123 +++++++------ R/sysdata.rda | Bin 1932 -> 2358 bytes SESSION.md | 307 +++++++++++++++++++-------------- inst/apps/FreesearchR/app.R | 179 ++++++++++++------- inst/apps/FreesearchR/server.R | 29 +++- 7 files changed, 409 insertions(+), 251 deletions(-) diff --git a/R/app_version.R b/R/app_version.R index 84fbc45c..33d76317 100644 --- a/R/app_version.R +++ b/R/app_version.R @@ -1 +1 @@ -app_version <- function()'v25.4.4.250429' +app_version <- function()'v25.4.4.250430' diff --git a/R/data_plots.R b/R/data_plots.R index d93b0ead..51fc249c 100644 --- a/R/data_plots.R +++ b/R/data_plots.R @@ -351,9 +351,25 @@ data_visuals_server <- function(id, prismCodeBlock(paste0("#Plotting\n", rv$code)) }) + shiny::observeEvent( + list( + data() + ), + { + shiny::req(data()) + + rv$plot <- NULL + } + ) + output$plot <- shiny::renderPlot({ - shiny::req(rv$plot) - rv$plot + # shiny::req(rv$plot) + # rv$plot + if (!is.null(rv$plot)) { + rv$plot + } else { + return(NULL) + } }) output$download_plot <- shiny::downloadHandler( diff --git a/R/regression-module.R b/R/regression-module.R index 6cd4aea0..c131f30c 100644 --- a/R/regression-module.R +++ b/R/regression-module.R @@ -331,10 +331,10 @@ regression_server <- function(id, "Multivariable" = "regression_model_list" ) |> lapply(\(.fun){ - parameters=list( + parameters <- list( data = data_r()[regression_vars()], - outcome.str = input$outcome_var, - fun.descr = input$regression_type + outcome.str = input$outcome_var, + fun.descr = input$regression_type ) do.call( @@ -413,49 +413,68 @@ regression_server <- function(id, shiny::req(rv$check_plot) shiny::req(input$plot_checks) - p <- rv$check_plot() + - # patchwork::wrap_plots() + - patchwork::plot_annotation(title = "Multivariable regression model checks") + ## Print checks if a regression table is present + if (!is.null(rv$list$regression$tables)) { + p <- rv$check_plot() + + # patchwork::wrap_plots() + + patchwork::plot_annotation(title = "Multivariable regression model checks") - layout <- sapply(seq_len(length(p)), \(.x){ - patchwork::area(.x, 1) - }) - - out <- p + patchwork::plot_layout(design = Reduce(c, layout)) - - index <- match( - input$plot_checks, - sapply(rv$check_plot(), \(.i){ - get_ggplot_label(.i, "title") + layout <- sapply(seq_len(length(p)), \(.x){ + patchwork::area(.x, 1) }) - ) - ls <- list() + p_list <- p + patchwork::plot_layout(design = Reduce(c, layout)) - for (i in index) { - p <- out[[i]] + - ggplot2::theme(axis.text = ggplot2::element_text(size = 10), - axis.title = ggplot2::element_text(size = 12), - legend.text = ggplot2::element_text(size = 12), - plot.subtitle = ggplot2::element_text(size = 12), - plot.title = ggplot2::element_text(size = 18)) - ls <- c(ls, list(p)) - } - # browser() - tryCatch( - { - patchwork::wrap_plots(ls, ncol = if (length(ls) == 1) 1 else 2) - }, - error = function(err) { - showNotification(err, type = "err") + index <- match( + input$plot_checks, + sapply(rv$check_plot(), \(.i){ + get_ggplot_label(.i, "title") + }) + ) + + ls <- list() + + for (i in index) { + p <- p_list[[i]] + + ggplot2::theme( + axis.text = ggplot2::element_text(size = 10), + axis.title = ggplot2::element_text(size = 12), + legend.text = ggplot2::element_text(size = 12), + plot.subtitle = ggplot2::element_text(size = 12), + plot.title = ggplot2::element_text(size = 18) + ) + ls <- c(ls, list(p)) } - ) + # browser() + tryCatch( + { + out <- patchwork::wrap_plots(ls, ncol = if (length(ls) == 1) 1 else 2) + }, + error = function(err) { + showNotification(err, type = "err") + } + ) + + out + } else { + return(NULL) + } }, alt = "Assumptions testing of the multivariable regression model" ) -### Creating the regression table + shiny::observeEvent( + list( + data_r(), + regression_vars() + ), + { + rv$list$regression$tables <- NULL + } + ) + + ### Creating the regression table shiny::observeEvent( input$load, { @@ -475,9 +494,9 @@ regression_server <- function(id, purrr::map(\(.x){ do.call( regression_table, - append_list(.x,parameters,"x") + append_list(.x, parameters, "x") ) -}) + }) # if (input$add_regression_p == "no") { # out <- out |> @@ -490,16 +509,18 @@ regression_server <- function(id, # } rv$list$regression$models |> - purrr::imap(\(.x,.i){ + purrr::imap(\(.x, .i){ rv$list$regression$models[[.i]][["code_table"]] <- paste( - .x$code, - expression_string(rlang::call2(.fn = "regression_table",!!!parameters,.ns = "FreesearchR"),assign.str=NULL),sep="|>\n") + .x$code, + expression_string(rlang::call2(.fn = "regression_table", !!!parameters, .ns = "FreesearchR"), assign.str = NULL), + sep = "|>\n" + ) }) list( rv$code$import, - rlang::call2(.fn = "select",!!!list(input$import_var),.ns = "dplyr"), - rlang::call2(.fn = "default_parsing",.ns = "FreesearchR") + rlang::call2(.fn = "select", !!!list(input$import_var), .ns = "dplyr"), + rlang::call2(.fn = "default_parsing", .ns = "FreesearchR") ) |> merge_expression() |> expression_string() @@ -519,11 +540,15 @@ regression_server <- function(id, ) output$table2 <- gt::render_gt({ - shiny::req(rv$list$regression$tables) - rv$list$regression$tables |> - tbl_merge() |> - gtsummary::as_gt() |> - gt::tab_header(gt::md(glue::glue("**Table 2: {rv$list$regression$params$descr}**"))) + ## Print checks if a regression table is present + if (!is.null(rv$list$regression$tables)) { + rv$list$regression$tables |> + tbl_merge() |> + gtsummary::as_gt() |> + gt::tab_header(gt::md(glue::glue("**Table 2: {rv$list$regression$params$descr}**"))) + } else { + return(NULL) + } }) ############################################################################## @@ -619,5 +644,3 @@ regression_server <- function(id, } ) } - - diff --git a/R/sysdata.rda b/R/sysdata.rda index cef8f94e026cd891e68d2988d5d9c0cdd5a78e85..d77ab95cb016bf329440288de556030464f3378c 100644 GIT binary patch literal 2358 zcmV-63CZ?CT4*^jL0KkKSqB*{(*PCUf6)K`Xaz!l|KNXX-@w2B|L{Nn00;;H;0j+p z-b8!D;Bh5JfkO`pEO#%T75lqSrlnj6X0qQg~^#-ZwrhrVNB|k}l zsivmMGBjw=000^Q0icQLkV;Sk)Ea0Wpa1|g000000Va|pDxaz3k5qaMOivWh+9m-E zMuvdM^%*q6Fd0c1sgNcCKTwS_X@fvOG-wPH5IsFaF$76XL_J0k05s8~C#V_#000dJ zjDTdpE^-r0qeTpcDnizz6fngFP7l3{l|;JY8U78;jGGzjpc)(g?hW%8p4g@`OHvgK z9VA?5m(BY?l9Uob1c|5wt{BqO+gR0p{{pr&hZn6d0=0Yft}id?U-fHDO3(Mk9zM58 z&a!cQl4f8WjCm{MQkJF~>5Rmbl1#iX#gm^Bh-fSvv)v$&V$Q7;))*3;YK$m)7Fj!0 z)X;&4x+&ckI?cAzzSdEf?W_CC@pS|D+9=LztnIX}6Tq)E;>8#wg(;_#n6ft{QD2#U zy7|XLjBvR)X&Xy&nv>Bxib$YpHU~J2F+0o4wh~YH_ku0=Ki(}fV`fG%WmGRE403f% zj<>C3bRRm>WvVBP+g?CzZXnsdo%op=rYc0qJSz$~wU=s9m!}A`prKqDkuOqUqsg{- zdd^-BTFX4cNui=dRp`9lT)br3hs(xd^HiADYVbu|MCL=tl;lJ*YXBhi8xYJjOm(`c zvnAD94OW)qHo+Z}Ho0TV#lzXj%FfZatU8r`YAlL|j7I)8hP}0COb+Z+5a~`nKEBR@sdG= z0Yp@SAfT{ORxCyfBv6V$NU=c}EJRUcSst%Pp11i+AI}VAdn(hOutq2uz3(&&2Pjml z;-QQ%MFUAh;fCF{rjswGhV{cRt(Na9_?d!Zp)|v6=c}`f#*LW5y4B4z z7%I5iYiyyDrFAgT2|PpwyNQ@6G9kDFF4uFJu!CH%6LSV0j!G{;mJc-exPT!bt}$7; zlNW0Z1wITTUo2f#iC9x{W||skW^@R}Ow%jhE_BW{vHgzw+E$G5?+Q`GSJyghy}JBS^`4<)Pu>ng^hYL!nbL<1t}3MfCm!H4iX_XJ&1 z>Lr+&HD-*8Pvfm&r^4bN7mNwe5J(~kl}?% zQQ>=(?X(3K{L;RMI2fVB0Ydcebl>2%wXKyH@te`0V1h(sQH(?mEt7Ux5fVzln_vOa`?X7-@(hoE^V={to%AT?X4=+v&IYt_YiLnhZ^<~5dVC55$_+Y6qJJ! z1$ylbuEr90j!~+ndmpl1EPxKV9zJzL09KIB%1RFvO|d$aRhh9+mgNbvD0k@_M6@@Q zdbhYzMOGdwS?P~Z{`l`gR#>-e(I1?w5Y>seB*E-e#f*ie5!okao$AGR8g5+LF``2 z)Ymc;Txt)@aE-hHhb^Z2i3w}iGEy%hlZKo(g0W;=#*G<@g$GO6YHA~uVc{#5C0d2H zGlSMmSh(aXaFx3^<*L}QV`D`Wwfu*7K8Om4Tu~JlLMEn6Dj_On_oatS_b#jEK{(WU zlr1SB3BX)ALZ>XVgA-1YrRE@8%ASzD-gF0kcE+|3kze1eN|SYAL8ATeCbAO}1y}H5eG;T(Vp@V`ud%E`S5fw#-z%MvYqrOhoxdSNVeM*F3B6j_tIF{kEx3Y`YmbtFz zU}Uj0$cZ0+9<{b1u@G1Vaa|!5I6C5T8!TeYb)_PU>JPF8XM&N!xsI&b$;4<^THj}Z zq;bU>_4X_b)UI&nk92 zgE&im0h);&wm#0od2@UL$aZ=o9-bOuO%S~KU8fkN1#0DJga~f((IKAeVSX$FYK7@} zCrq>E+Cfz8^t-KqEh?Tj_invnwes?W3UeOs9FogGm86j`1BIBtZE|Ml0)^$gcQvppl_x4zP2*xzI3KnYF%rIwQK{ComZj|ij+d8g$f*( zWLR@z@USKW%Vokr@VHco?W#QNeQ`ZC4M*PFr9l|=F;tR4^nG zvC#S8dq@E%Y#=}w1R$hAMGydhumZ4>Ne|&50n&g-W46-vbyeHq$ZvQ+aKfPO?%}hB zRNu$Wga9qKT1mwqu|PqB!5FeA3JMD#q*$vKMHE;)_l>_hdDQa*3?5dS>>jwa!nN~1BhH(j%nhHnJhco3Cj2^7dyDLA1hfrgACF`P|6?we)U6k=2< zgvBP_2_i^ZB%CRR?{x)pGNw~s` z7jalgC}KqPcG-WFL!IQ@~ZSbUtY!>3ag)=$f~+H z>+RcSzXs1lxr<(@yj(xS!MIOV4n_QZn<-K^5FakTK>R)LNf8e($AelO`3~_|E0oCj z)=BJB{$#I#{nmx~KNV zSUa%v%r9kYQ2p(7Zon&ZgogYdCY~Xvg7gVQZ6k6izx79g^fz*KC(=6h-nLkK@Y!M$uYAV8EEh0PsUTxUT)T;;{#WQ(&hU=oc4G!$B6VM8eCV;c0XbgjCJ zn<&Vs6j_cmI;d*c<@fWa9SSTjiX1SqY%MkCjfe{gBs#Eaq!ZUdTLxD))05_faI+`} zO?YI98iXLlkymv{s8=D{Sm~yTPJsk$%6%Xt_uN$nnr%v9M|_b-Or7u|azO(% lapply(\(.fun){ - parameters=list( + parameters <- list( data = data_r()[regression_vars()], - outcome.str = input$outcome_var, - fun.descr = input$regression_type + outcome.str = input$outcome_var, + fun.descr = input$regression_type ) do.call( @@ -7452,49 +7468,68 @@ regression_server <- function(id, shiny::req(rv$check_plot) shiny::req(input$plot_checks) - p <- rv$check_plot() + - # patchwork::wrap_plots() + - patchwork::plot_annotation(title = "Multivariable regression model checks") + ## Print checks if a regression table is present + if (!is.null(rv$list$regression$tables)) { + p <- rv$check_plot() + + # patchwork::wrap_plots() + + patchwork::plot_annotation(title = "Multivariable regression model checks") - layout <- sapply(seq_len(length(p)), \(.x){ - patchwork::area(.x, 1) - }) - - out <- p + patchwork::plot_layout(design = Reduce(c, layout)) - - index <- match( - input$plot_checks, - sapply(rv$check_plot(), \(.i){ - get_ggplot_label(.i, "title") + layout <- sapply(seq_len(length(p)), \(.x){ + patchwork::area(.x, 1) }) - ) - ls <- list() + p_list <- p + patchwork::plot_layout(design = Reduce(c, layout)) - for (i in index) { - p <- out[[i]] + - ggplot2::theme(axis.text = ggplot2::element_text(size = 10), - axis.title = ggplot2::element_text(size = 12), - legend.text = ggplot2::element_text(size = 12), - plot.subtitle = ggplot2::element_text(size = 12), - plot.title = ggplot2::element_text(size = 18)) - ls <- c(ls, list(p)) - } - # browser() - tryCatch( - { - patchwork::wrap_plots(ls, ncol = if (length(ls) == 1) 1 else 2) - }, - error = function(err) { - showNotification(err, type = "err") + index <- match( + input$plot_checks, + sapply(rv$check_plot(), \(.i){ + get_ggplot_label(.i, "title") + }) + ) + + ls <- list() + + for (i in index) { + p <- p_list[[i]] + + ggplot2::theme( + axis.text = ggplot2::element_text(size = 10), + axis.title = ggplot2::element_text(size = 12), + legend.text = ggplot2::element_text(size = 12), + plot.subtitle = ggplot2::element_text(size = 12), + plot.title = ggplot2::element_text(size = 18) + ) + ls <- c(ls, list(p)) } - ) + # browser() + tryCatch( + { + out <- patchwork::wrap_plots(ls, ncol = if (length(ls) == 1) 1 else 2) + }, + error = function(err) { + showNotification(err, type = "err") + } + ) + + out + } else { + return(NULL) + } }, alt = "Assumptions testing of the multivariable regression model" ) -### Creating the regression table + shiny::observeEvent( + list( + data_r(), + regression_vars() + ), + { + rv$list$regression$tables <- NULL + } + ) + + ### Creating the regression table shiny::observeEvent( input$load, { @@ -7514,9 +7549,9 @@ regression_server <- function(id, purrr::map(\(.x){ do.call( regression_table, - append_list(.x,parameters,"x") + append_list(.x, parameters, "x") ) -}) + }) # if (input$add_regression_p == "no") { # out <- out |> @@ -7529,16 +7564,18 @@ regression_server <- function(id, # } rv$list$regression$models |> - purrr::imap(\(.x,.i){ + purrr::imap(\(.x, .i){ rv$list$regression$models[[.i]][["code_table"]] <- paste( - .x$code, - expression_string(rlang::call2(.fn = "regression_table",!!!parameters,.ns = "FreesearchR"),assign.str=NULL),sep="|>\n") + .x$code, + expression_string(rlang::call2(.fn = "regression_table", !!!parameters, .ns = "FreesearchR"), assign.str = NULL), + sep = "|>\n" + ) }) list( rv$code$import, - rlang::call2(.fn = "select",!!!list(input$import_var),.ns = "dplyr"), - rlang::call2(.fn = "default_parsing",.ns = "FreesearchR") + rlang::call2(.fn = "select", !!!list(input$import_var), .ns = "dplyr"), + rlang::call2(.fn = "default_parsing", .ns = "FreesearchR") ) |> merge_expression() |> expression_string() @@ -7558,11 +7595,15 @@ regression_server <- function(id, ) output$table2 <- gt::render_gt({ - shiny::req(rv$list$regression$tables) - rv$list$regression$tables |> - tbl_merge() |> - gtsummary::as_gt() |> - gt::tab_header(gt::md(glue::glue("**Table 2: {rv$list$regression$params$descr}**"))) + ## Print checks if a regression table is present + if (!is.null(rv$list$regression$tables)) { + rv$list$regression$tables |> + tbl_merge() |> + gtsummary::as_gt() |> + gt::tab_header(gt::md(glue::glue("**Table 2: {rv$list$regression$params$descr}**"))) + } else { + return(NULL) + } }) ############################################################################## @@ -7660,8 +7701,6 @@ regression_server <- function(id, } - - ######## #### Current file: /Users/au301842/FreesearchR/R//report.R ######## @@ -9678,10 +9717,13 @@ dark <- custom_theme( ui <- bslib::page_fixed( prismDependencies, prismRDependency, + ## Basic Umami page tracking shiny::tags$head( includeHTML(("www/umami-app.html")), tags$link(rel = "stylesheet", type = "text/css", href = "style.css")), - tags$head(tags$link(rel="shortcut icon", href="favicon.svg")), + ## This adds the actual favicon + ## png and ico versions are kept for compatibility + shiny::tags$head(tags$link(rel="shortcut icon", href="favicon.svg")), title = "FreesearchR", theme = light, shiny::useBusyIndicators(), @@ -9751,7 +9793,7 @@ library(gtsummary) data(starwars) data(mtcars) mtcars_date <- mtcars |> append_column(as.Date(sample(1:365, nrow(mtcars))), "rand_dates") -mtcars_date$date <- as.Date(sample(seq_len(365),nrow(mtcars))) +mtcars_date$date <- as.Date(sample(seq_len(365), nrow(mtcars))) data(trial) @@ -10182,6 +10224,20 @@ server <- function(input, output, session) { )) }) + ## Evaluation table/plots reset on data change + ## This does not work (!?) + shiny::observeEvent( + list( + rv$data_filtered + ), + { + shiny::req(rv$data_filtered) + + rv$list$table1 <- NULL + rv$regression <- NULL + } + ) + ############################################################################## ######### @@ -10243,6 +10299,7 @@ server <- function(input, output, session) { ## Just a note to self ## This is a very rewarding couple of lines marking new insights to dynamically rendering code shiny::observe({ + shiny::req(rv$regression) rv$regression()$regression$models |> purrr::imap(\(.x, .i){ output[[paste0("code_", tolower(.i))]] <- shiny::renderUI({ prismCodeBlock(paste0(paste("#", .i, "regression model\n"), .x$code_table)) @@ -10319,11 +10376,13 @@ server <- function(input, output, session) { }) output$table1 <- gt::render_gt({ - shiny::req(rv$list$table1) - - rv$list$table1 |> - gtsummary::as_gt() |> - gt::tab_header(gt::md("**Table 1: Baseline Characteristics**")) + if (!is.null(rv$list$table1)) { + rv$list$table1 |> + gtsummary::as_gt() |> + gt::tab_header(gt::md("**Table 1: Baseline Characteristics**")) + } else { + return(NULL) + } }) data_correlations_server( diff --git a/inst/apps/FreesearchR/server.R b/inst/apps/FreesearchR/server.R index 25fd8384..fdc7f4e9 100644 --- a/inst/apps/FreesearchR/server.R +++ b/inst/apps/FreesearchR/server.R @@ -33,7 +33,7 @@ library(gtsummary) data(starwars) data(mtcars) mtcars_date <- mtcars |> append_column(as.Date(sample(1:365, nrow(mtcars))), "rand_dates") -mtcars_date$date <- as.Date(sample(seq_len(365),nrow(mtcars))) +mtcars_date$date <- as.Date(sample(seq_len(365), nrow(mtcars))) data(trial) @@ -464,6 +464,20 @@ server <- function(input, output, session) { )) }) + ## Evaluation table/plots reset on data change + ## This does not work (!?) + shiny::observeEvent( + list( + rv$data_filtered + ), + { + shiny::req(rv$data_filtered) + + rv$list$table1 <- NULL + rv$regression <- NULL + } + ) + ############################################################################## ######### @@ -525,6 +539,7 @@ server <- function(input, output, session) { ## Just a note to self ## This is a very rewarding couple of lines marking new insights to dynamically rendering code shiny::observe({ + shiny::req(rv$regression) rv$regression()$regression$models |> purrr::imap(\(.x, .i){ output[[paste0("code_", tolower(.i))]] <- shiny::renderUI({ prismCodeBlock(paste0(paste("#", .i, "regression model\n"), .x$code_table)) @@ -601,11 +616,13 @@ server <- function(input, output, session) { }) output$table1 <- gt::render_gt({ - shiny::req(rv$list$table1) - - rv$list$table1 |> - gtsummary::as_gt() |> - gt::tab_header(gt::md("**Table 1: Baseline Characteristics**")) + if (!is.null(rv$list$table1)) { + rv$list$table1 |> + gtsummary::as_gt() |> + gt::tab_header(gt::md("**Table 1: Baseline Characteristics**")) + } else { + return(NULL) + } }) data_correlations_server( From e144f9aeb9acd43550cad5ad331d307f445961fe Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Wed, 30 Apr 2025 10:16:45 +0200 Subject: [PATCH 2/6] clearer instructions to run locally --- README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 10d809f8..b0367e13 100644 --- a/README.md +++ b/README.md @@ -23,23 +23,27 @@ This app has the following simple goals: 1. ease quick data overview and basic visualisations for any clinical researcher -## Install locally +## Run locally on your own machine -The ***FreesearchR***-tool can also be launched locally. Any data.frame available in the global environment will be accessible from the interface. +The ***FreesearchR*** app can also run on your own machine with no data transmitted anywhere. Any data.frame available in the global environment will be accessible from the interface. Just follow the below steps: -``` -require("devtools") -devtools::install_github("agdamsbo/FreesearchR") -library(FreesearchR) -# By loading mtcars to the environment, it will be available -# in the interface like any other data.frame -data(mtcars) -launch_FreesearchR() -``` +1. **Requirement:** You need to have [*R* installed](https://www.r-project.org/) and possibly an editor like [RStudio](https://posit.co/download/rstudio-desktop/). + +1. Then open the *R* console and copy/paste the following code, that will install the `{devtools}` package and then the `{FreesearchR}` *R*-package with its dependencies: + + ``` + require("devtools") + devtools::install_github("agdamsbo/FreesearchR") + library(FreesearchR) + # By loading mtcars to the environment, it will be available + # in the interface like any other data.frame + data(mtcars) + launch_FreesearchR() + ``` ## Code of Conduct -Please note that the ***FreesearchR*** project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. +Please note that the ***FreesearchR*** project is published with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. ## Acknowledgements From 2379cecbca935e34d468080df4f24e83120ac9f9 Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Wed, 30 Apr 2025 13:02:26 +0200 Subject: [PATCH 3/6] resturicturing to remove tracking from local app --- .Rbuildignore | 2 + .gitignore | 2 + inst/apps/FreesearchR/app.R | 70 +- inst/apps/FreesearchR/launch.R | 1 - .../shinyapps.io/agdamsbo/FreesearchR.dcf | 10 - .../shinyapps.io/agdamsbo/freesearcheR.dcf | 10 - .../shinyapps.io/agdamsbo/webResearch.dcf | 10 - .../cognitiveindex/freesearcheR_dev.dcf | 10 - .../cognitiveindex/freesearcheR_extra.dcf | 10 - inst/apps/FreesearchR/server.R | 764 ------------------ inst/apps/FreesearchR/ui.R | 16 +- inst/apps/FreesearchR/www/umami-app.html | 1 - 12 files changed, 61 insertions(+), 845 deletions(-) delete mode 100644 inst/apps/FreesearchR/launch.R delete mode 100644 inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/FreesearchR.dcf delete mode 100644 inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/freesearcheR.dcf delete mode 100644 inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf delete mode 100644 inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_dev.dcf delete mode 100644 inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_extra.dcf delete mode 100644 inst/apps/FreesearchR/server.R delete mode 100644 inst/apps/FreesearchR/www/umami-app.html diff --git a/.Rbuildignore b/.Rbuildignore index 7db599ed..50c93d4e 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -13,3 +13,5 @@ ^pkgdown$ ^data-raw$ ^CITATION\.cff$ +^app_hosted$ +^app$ diff --git a/.gitignore b/.gitignore index 8e58845e..6201650b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ inst/shiny-examples/casting/functions.R functions.R docs inst/doc +app_hosted +app diff --git a/inst/apps/FreesearchR/app.R b/inst/apps/FreesearchR/app.R index 1c7f8491..347b471c 100644 --- a/inst/apps/FreesearchR/app.R +++ b/inst/apps/FreesearchR/app.R @@ -1,7 +1,7 @@ ######## -#### Current file: /Users/au301842/FreesearchR/inst/apps/FreesearchR/functions.R +#### Current file: /Users/au301842/FreesearchR/app/functions.R ######## @@ -7521,8 +7521,7 @@ regression_server <- function(id, shiny::observeEvent( list( - data_r(), - regression_vars() + data_r() ), { rv$list$regression$tables <- NULL @@ -7537,6 +7536,7 @@ regression_server <- function(id, ## To avoid plotting old models on fail/error rv$list$regression$tables <- NULL + # browser() tryCatch( { parameters <- list( @@ -7572,17 +7572,9 @@ regression_server <- function(id, ) }) - list( - rv$code$import, - rlang::call2(.fn = "select", !!!list(input$import_var), .ns = "dplyr"), - rlang::call2(.fn = "default_parsing", .ns = "FreesearchR") - ) |> - merge_expression() |> - expression_string() - rv$list$regression$tables <- out - rv$list$input <- input + }, warning = function(warn) { showNotification(paste0(warn), type = "warning") @@ -7694,7 +7686,7 @@ regression_server <- function(id, ############################################################################## return(shiny::reactive({ - return(rv$list) + rv$list })) } ) @@ -7880,7 +7872,7 @@ FreesearchR_colors <- function(choose = NULL) { fg = "#000000" ) if (!is.null(choose)) { - out[choose] + unname(out[choose]) } else { out } @@ -9201,7 +9193,17 @@ grepl_fix <- function(data, pattern, type = c("prefix", "infix", "suffix")) { ######## -#### Current file: /Users/au301842/FreesearchR/inst/apps/FreesearchR/ui.R +#### Current file: /Users/au301842/FreesearchR/dev/header_include.R +######## + +header_include <- function(){ + shiny::tags$head( + tags$link(rel = "stylesheet", type = "text/css", href = "style.css")) +} + + +######## +#### Current file: /Users/au301842/FreesearchR/app/ui.R ######## # ns <- NS(id) @@ -9717,10 +9719,7 @@ dark <- custom_theme( ui <- bslib::page_fixed( prismDependencies, prismRDependency, - ## Basic Umami page tracking - shiny::tags$head( - includeHTML(("www/umami-app.html")), - tags$link(rel = "stylesheet", type = "text/css", href = "style.css")), + header_include(), ## This adds the actual favicon ## png and ico versions are kept for compatibility shiny::tags$head(tags$link(rel="shortcut icon", href="favicon.svg")), @@ -9743,7 +9742,7 @@ ui <- bslib::page_fixed( style = "background-color: #14131326; padding: 4px; text-align: center; bottom: 0; width: 100%;", shiny::p( style = "margin: 1", - "Data is only stored for analyses and deleted when the app is closed." + "Data is only stored for analyses and deleted when the app is closed.", shiny::markdown("Consider [running ***FreesearchR*** locally](https://agdamsbo.github.io/FreesearchR/#run-locally-on-your-own-machine) if working with sensitive data.") ), shiny::p( style = "margin: 1; color: #888;", @@ -9754,8 +9753,9 @@ ui <- bslib::page_fixed( ) + ######## -#### Current file: /Users/au301842/FreesearchR/inst/apps/FreesearchR/server.R +#### Current file: /Users/au301842/FreesearchR/app/server.R ######## library(readr) @@ -9839,7 +9839,7 @@ server <- function(input, output, session) { rv <- shiny::reactiveValues( list = list(), - regression = list(), + regression = NULL, ds = NULL, local_temp = NULL, ready = NULL, @@ -10234,7 +10234,7 @@ server <- function(input, output, session) { shiny::req(rv$data_filtered) rv$list$table1 <- NULL - rv$regression <- NULL + # rv$regression <- NULL } ) @@ -10414,6 +10414,22 @@ server <- function(input, output, session) { rv$regression <- regression_server("regression", data = shiny::reactive(rv$list$data)) + # shiny::observeEvent(rv$regression, { + # browser() + # if (shiny::is.reactive(rv$regression)) { + # rv$list$regression <- rv$regression() + # } else { + # rv$list$regression <- rv$regression + # } + # # rv$list$regression <- rv$regression() + # }) + + # output$regression_models <- renderText({ + # req(rv$list$regression) + # browser() + # names(rv$list$regression) + # }) + ############################################################################## ######### ######### Page navigation @@ -10464,6 +10480,7 @@ server <- function(input, output, session) { paste0("report.", input$output_type) }), content = function(file, type = input$output_type) { + # browser() # shiny::req(rv$list$regression) ## Notification is not progressing ## Presumably due to missing @@ -10472,6 +10489,11 @@ server <- function(input, output, session) { format <- ifelse(type == "docx", "word_document", "odt_document") # browser() + # if (shiny::is.reactive(rv$regression)){ + # rv$list$regression <- rv$regression() + # } + + # rv$list$regression <- rv$regression() rv$list$regression <- rv$regression() shiny::withProgress(message = "Generating the report. Hold on for a moment..", { @@ -10525,7 +10547,7 @@ server <- function(input, output, session) { ######## -#### Current file: /Users/au301842/FreesearchR/inst/apps/FreesearchR/launch.R +#### Current file: /Users/au301842/FreesearchR/app/launch.R ######## shinyApp(ui, server) diff --git a/inst/apps/FreesearchR/launch.R b/inst/apps/FreesearchR/launch.R deleted file mode 100644 index 739d7781..00000000 --- a/inst/apps/FreesearchR/launch.R +++ /dev/null @@ -1 +0,0 @@ -shinyApp(ui, server) diff --git a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/FreesearchR.dcf b/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/FreesearchR.dcf deleted file mode 100644 index b42b77a5..00000000 --- a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/FreesearchR.dcf +++ /dev/null @@ -1,10 +0,0 @@ -name: FreesearchR -title: -username: agdamsbo -account: agdamsbo -server: shinyapps.io -hostUrl: https://api.shinyapps.io/v1 -appId: 14600805 -bundleId: 10199884 -url: https://agdamsbo.shinyapps.io/FreesearchR/ -version: 1 diff --git a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/freesearcheR.dcf b/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/freesearcheR.dcf deleted file mode 100644 index dd1b9615..00000000 --- a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/freesearcheR.dcf +++ /dev/null @@ -1,10 +0,0 @@ -name: freesearcheR -title: -username: agdamsbo -account: agdamsbo -server: shinyapps.io -hostUrl: https://api.shinyapps.io/v1 -appId: 13611288 -bundleId: 10164589 -url: https://agdamsbo.shinyapps.io/freesearcheR/ -version: 1 diff --git a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf b/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf deleted file mode 100644 index 6fa449ff..00000000 --- a/inst/apps/FreesearchR/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf +++ /dev/null @@ -1,10 +0,0 @@ -name: webResearch -title: -username: agdamsbo -account: agdamsbo -server: shinyapps.io -hostUrl: https://api.shinyapps.io/v1 -appId: 13276335 -bundleId: 9436643 -url: https://agdamsbo.shinyapps.io/webResearch/ -version: 1 diff --git a/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_dev.dcf b/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_dev.dcf deleted file mode 100644 index ab5be8e1..00000000 --- a/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_dev.dcf +++ /dev/null @@ -1,10 +0,0 @@ -name: freesearcheR_dev -title: -username: cognitiveindex -account: cognitiveindex -server: shinyapps.io -hostUrl: https://api.shinyapps.io/v1 -appId: 13786206 -bundleId: 9688582 -url: https://cognitiveindex.shinyapps.io/freesearcheR_dev/ -version: 1 diff --git a/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_extra.dcf b/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_extra.dcf deleted file mode 100644 index befa5713..00000000 --- a/inst/apps/FreesearchR/rsconnect/shinyapps.io/cognitiveindex/freesearcheR_extra.dcf +++ /dev/null @@ -1,10 +0,0 @@ -name: freesearcheR_extra -title: -username: cognitiveindex -account: cognitiveindex -server: shinyapps.io -hostUrl: https://api.shinyapps.io/v1 -appId: 13622743 -bundleId: 9544828 -url: https://cognitiveindex.shinyapps.io/freesearcheR_extra/ -version: 1 diff --git a/inst/apps/FreesearchR/server.R b/inst/apps/FreesearchR/server.R deleted file mode 100644 index fdc7f4e9..00000000 --- a/inst/apps/FreesearchR/server.R +++ /dev/null @@ -1,764 +0,0 @@ -library(readr) -library(MASS) -library(stats) -library(gt) -# library(openxlsx2) -library(haven) -library(readODS) -require(shiny) -library(bslib) -library(assertthat) -library(dplyr) -library(quarto) -library(here) -library(broom) -library(broom.helpers) -# library(REDCapCAST) -library(easystats) -# library(esquisse) -library(patchwork) -library(DHARMa) -library(apexcharter) -library(toastui) -library(datamods) -library(IDEAFilter) -library(shinyWidgets) -library(DT) -library(data.table) -library(gtsummary) -# library(FreesearchR) - -# source("functions.R") - -data(starwars) -data(mtcars) -mtcars_date <- mtcars |> append_column(as.Date(sample(1:365, nrow(mtcars))), "rand_dates") -mtcars_date$date <- as.Date(sample(seq_len(365), nrow(mtcars))) -data(trial) - - -# light <- custom_theme() -# -# dark <- custom_theme(bg = "#000",fg="#fff") - - -server <- function(input, output, session) { - ## Listing files in www in session start to keep when ending and removing - ## everything else. - files.to.keep <- list.files("www/") - - output$docs_file <- shiny::renderUI({ - # shiny::includeHTML("www/docs.html") - shiny::HTML(readLines("www/docs.html")) - }) - - ############################################################################## - ######### - ######### Night mode (just very popular, not really needed) - ######### - ############################################################################## - - # observeEvent(input$dark_mode,{ - # session$setCurrentTheme( - # if (isTRUE(input$dark_mode)) dark else light - # )}) - - # observe({ - # if(input$dark_mode==TRUE) - # session$setCurrentTheme(bs_theme_update(theme = custom_theme(version = 5))) - # if(input$dark_mode==FALSE) - # session$setCurrentTheme(bs_theme_update(theme = custom_theme(version = 5, bg = "#000",fg="#fff"))) - # }) - - - ############################################################################## - ######### - ######### Setting reactive values - ######### - ############################################################################## - - rv <- shiny::reactiveValues( - list = list(), - regression = list(), - ds = NULL, - local_temp = NULL, - ready = NULL, - test = "no", - data_original = NULL, - data_temp = NULL, - data = NULL, - data_variables = NULL, - data_filtered = NULL, - models = NULL, - code = list() - ) - - ############################################################################## - ######### - ######### Data import section - ######### - ############################################################################## - - data_file <- import_file_server( - id = "file_import", - show_data_in = "popup", - trigger_return = "change", - return_class = "data.frame" - ) - - shiny::observeEvent(data_file$data(), { - shiny::req(data_file$data()) - rv$data_temp <- data_file$data() - rv$code <- modifyList(x = rv$code, list(import = data_file$code())) - }) - - from_redcap <- m_redcap_readServer( - id = "redcap_import" - ) - - shiny::observeEvent(from_redcap$data(), { - rv$data_temp <- from_redcap$data() - rv$code <- modifyList(x = rv$code, list(import = from_redcap$code())) - }) - - ## This is used to ensure the reactive data is retrieved - output$redcap_prev <- DT::renderDT( - { - DT::datatable(head(from_redcap$data(), 5), - caption = "First 5 observations" - ) - }, - server = TRUE - ) - - from_env <- datamods::import_globalenv_server( - id = "env", - trigger_return = "change", - btn_show_data = FALSE, - reset = reactive(input$hidden) - ) - - shiny::observeEvent(from_env$data(), { - shiny::req(from_env$data()) - - rv$data_temp <- from_env$data() - rv$code <- modifyList(x = rv$code, list(import = from_env$name())) - }) - - output$import_var <- shiny::renderUI({ - shiny::req(rv$data_temp) - - preselect <- names(rv$data_temp)[sapply(rv$data_temp, missing_fraction) <= input$complete_cutoff / 100] - - shinyWidgets::virtualSelectInput( - inputId = "import_var", - label = "Select variables to include", - selected = preselect, - choices = names(rv$data_temp), - updateOn = "change", - multiple = TRUE, - search = TRUE, - showValueAsTags = TRUE - ) - }) - - output$data_loaded <- shiny::reactive({ - !is.null(rv$data_temp) - }) - - shiny::observeEvent(input$source, { - rv$data_temp <- NULL - }) - - shiny::outputOptions(output, "data_loaded", suspendWhenHidden = FALSE) - - shiny::observeEvent( - eventExpr = list( - input$import_var, - input$complete_cutoff, - rv$data_temp - ), - handlerExpr = { - shiny::req(rv$data_temp) - shiny::req(input$import_var) - # browser() - temp_data <- rv$data_temp - if (all(input$import_var %in% names(temp_data))) { - temp_data <- temp_data |> dplyr::select(input$import_var) - } - - rv$data_original <- temp_data |> - default_parsing() - - rv$code$import <- rv$code$import |> - expression_string(assign.str = "df <-") - - rv$code$format <- list( - "df", - rlang::expr(dplyr::select(dplyr::all_of(!!input$import_var))), - rlang::call2(.fn = "default_parsing", .ns = "FreesearchR") - ) |> - lapply(expression_string) |> - pipe_string() |> - expression_string(assign.str = "df <-") - - rv$code$filter <- NULL - rv$code$modify <- NULL - }, ignoreNULL = FALSE - ) - - output$data_info_import <- shiny::renderUI({ - shiny::req(rv$data_original) - data_description(rv$data_original) - }) - - ## Activating action buttons on data imported - shiny::observeEvent(rv$data_original, { - if (is.null(rv$data_original) | NROW(rv$data_original) == 0) { - shiny::updateActionButton(inputId = "act_start", disabled = TRUE) - shiny::updateActionButton(inputId = "modal_browse", disabled = TRUE) - shiny::updateActionButton(inputId = "act_eval", disabled = TRUE) - } else { - shiny::updateActionButton(inputId = "act_start", disabled = FALSE) - shiny::updateActionButton(inputId = "modal_browse", disabled = FALSE) - shiny::updateActionButton(inputId = "act_eval", disabled = FALSE) - } - }) - - ############################################################################## - ######### - ######### Data modification section - ######### - ############################################################################## - - shiny::observeEvent( - eventExpr = list( - rv$data_original - ), - handlerExpr = { - shiny::req(rv$data_original) - - rv$data <- rv$data_original - } - ) - - ## For now this solution work, but I would prefer to solve this with the above - shiny::observeEvent(input$reset_confirm, - { - if (isTRUE(input$reset_confirm)) { - shiny::req(rv$data_original) - rv$data <- rv$data_original - rv$code$filter <- NULL - rv$code$variables <- NULL - rv$code$modify <- NULL - } - }, - ignoreNULL = TRUE - ) - - - shiny::observeEvent(input$data_reset, { - shinyWidgets::ask_confirmation( - cancelOnDismiss = TRUE, - inputId = "reset_confirm", - title = "Please confirm data reset?", - type = "warning" - ) - }) - - - ######### - ######### Modifications - ######### - - ## Using modified version of the datamods::cut_variable_server function - ## Further modifications are needed to have cut/bin options based on class of variable - ## Could be defined server-side - - output$data_info <- shiny::renderUI({ - shiny::req(data_filter()) - data_description(data_filter(), "The filtered data") - }) - - ######### Create factor - - shiny::observeEvent( - input$modal_cut, - modal_cut_variable("modal_cut", title = "Create new factor") - ) - - data_modal_cut <- cut_variable_server( - id = "modal_cut", - data_r = shiny::reactive(rv$data) - ) - - shiny::observeEvent(data_modal_cut(), { - rv$data <- data_modal_cut() - rv$code$modify[[length(rv$code$modify) + 1]] <- attr(rv$data, "code") - }) - - ######### Modify factor - - shiny::observeEvent( - input$modal_update, - datamods::modal_update_factor(id = "modal_update", title = "Reorder factor levels") - ) - - data_modal_update <- datamods::update_factor_server( - id = "modal_update", - data_r = reactive(rv$data) - ) - - shiny::observeEvent(data_modal_update(), { - shiny::removeModal() - rv$data <- data_modal_update() - rv$code$modify[[length(rv$code$modify) + 1]] <- attr(rv$data, "code") - }) - - ######### Create column - - shiny::observeEvent( - input$modal_column, - modal_create_column( - id = "modal_column", - footer = shiny::markdown("This window is aimed at advanced users and require some *R*-experience!"), - title = "Create new variables" - ) - ) - data_modal_r <- create_column_server( - id = "modal_column", - data_r = reactive(rv$data) - ) - shiny::observeEvent( - data_modal_r(), - { - rv$data <- data_modal_r() - rv$code$modify[[length(rv$code$modify) + 1]] <- attr(rv$data, "code") - } - ) - - ######### Subset, rename, reclass - - updated_data <- update_variables_server( - id = "modal_variables", - data = shiny::reactive(rv$data), - return_data_on_init = FALSE - ) - - shiny::observeEvent(updated_data(), { - rv$data <- updated_data() - rv$code$modify[[length(rv$code$modify) + 1]] <- attr(rv$data, "code") - }) - - ### Column filter - ### Completely implemented, but it takes a little considering where in the - ### data flow to implement, as it will act destructively on previous - ### manipulations - - output$column_filter <- shiny::renderUI({ - shiny::req(rv$data) - # c("dichotomous", "ordinal", "categorical", "datatime", "continuous") - shinyWidgets::virtualSelectInput( - inputId = "column_filter", - label = "Select variable types to include", - selected = unique(data_type(rv$data)), - choices = unique(data_type(rv$data)), - updateOn = "change", - multiple = TRUE, - search = FALSE, - showValueAsTags = TRUE - ) - }) - - shiny::observe({ - # shiny::req(input$column_filter) - out <- data_type_filter(rv$data, input$column_filter) - rv$data_variables <- out - if (!is.null(input$column_filter)) { - rv$code$variables <- attr(out, "code") - } - # rv$code$modify[[length(rv$code$modify) + 1]] <- attr(rv$data, "code") - }) - - - ######### Data filter - # IDEAFilter has the least cluttered UI, but might have a License issue - # Consider using shinyDataFilter, though not on CRAN - data_filter <- IDEAFilter::IDEAFilter("data_filter", - data = shiny::reactive(rv$data_variables), - verbose = TRUE - ) - - shiny::observeEvent( - list( - shiny::reactive(rv$data_variables), - shiny::reactive(rv$data_original), - data_filter(), - # regression_vars(), - input$complete_cutoff - ), - { - ### Save filtered data - rv$data_filtered <- data_filter() - - ### Save filtered data - ### without empty factor levels - rv$list$data <- data_filter() |> - REDCapCAST::fct_drop() |> - (\(.x){ - .x[!sapply(.x, is.character)] - })() - - ## This looks messy!! But it works as intended for now - - out <- gsub( - "filter", "dplyr::filter", - gsub( - "\\s{2,}", " ", - paste0( - capture.output(attr(rv$data_filtered, "code")), - collapse = " " - ) - ) - ) - - out <- strsplit(out, "%>%") |> - unlist() |> - (\(.x){ - paste(c("df <- df", .x[-1], "REDCapCAST::fct_drop()"), - collapse = "|> \n " - ) - })() - - rv$code <- append_list(data = out, list = rv$code, index = "filter") - } - ) - - ######### Data preview - - ### Overview - - data_summary_server( - id = "data_summary", - data = shiny::reactive({ - rv$data_filtered - }), - color.main = "#2A004E", - color.sec = "#C62300", - pagination = 10 - ) - - observeEvent(input$modal_browse, { - show_data(REDCapCAST::fct_drop(rv$data_filtered), title = "Uploaded data overview", type = "modal") - }) - - output$original_str <- renderPrint({ - str(rv$data_original) - }) - - output$modified_str <- renderPrint({ - str(as.data.frame(rv$data_filtered) |> - REDCapCAST::set_attr( - label = NULL, - attr = "code" - )) - }) - - ## Evaluation table/plots reset on data change - ## This does not work (!?) - shiny::observeEvent( - list( - rv$data_filtered - ), - { - shiny::req(rv$data_filtered) - - rv$list$table1 <- NULL - rv$regression <- NULL - } - ) - - - ############################################################################## - ######### - ######### Code export - ######### - ############################################################################## - - ## This really should be collapsed to only one call, but I'll leave it for now - ## as a working example of dynamically defining outputs and rendering. - - # output$code_import <- shiny::renderPrint({ - # shiny::req(rv$code$import) - # cat(c("#Data import\n", rv$code$import)) - # }) - - output$code_import <- shiny::renderUI({ - prismCodeBlock(paste0("#Data import\n", rv$code$import)) - }) - - output$code_import <- shiny::renderUI({ - prismCodeBlock(paste0("#Data import formatting\n", rv$code$format)) - }) - - output$code_data <- shiny::renderUI({ - shiny::req(rv$code$modify) - # browser() - ## This will create three lines for each modification - # ls <- rv$code$modify - ## This will remove all non-unique entries - # ls <- rv$code$modify |> unique() - ## This will only remove all non-repeating entries - ls <- rv$code$modify[!is_identical_to_previous(rv$code$modify)] - - out <- ls |> - lapply(expression_string) |> - pipe_string() |> - expression_string(assign.str = "df <- df |>\n") - - prismCodeBlock(paste0("#Data modifications\n", out)) - }) - - output$code_variables <- shiny::renderUI({ - shiny::req(rv$code$variables) - out <- expression_string(rv$code$variables, assign.str = "df <- df |>\n") - prismCodeBlock(paste0("#Variables filter\n", out)) - }) - - output$code_filter <- shiny::renderUI({ - shiny::req(rv$code$filter) - prismCodeBlock(paste0("#Data filter\n", rv$code$filter)) - }) - - output$code_table1 <- shiny::renderUI({ - shiny::req(rv$code$table1) - prismCodeBlock(paste0("#Data characteristics table\n", rv$code$table1)) - }) - - - ## Just a note to self - ## This is a very rewarding couple of lines marking new insights to dynamically rendering code - shiny::observe({ - shiny::req(rv$regression) - rv$regression()$regression$models |> purrr::imap(\(.x, .i){ - output[[paste0("code_", tolower(.i))]] <- shiny::renderUI({ - prismCodeBlock(paste0(paste("#", .i, "regression model\n"), .x$code_table)) - }) - }) - }) - - - ############################################################################## - ######### - ######### Data analyses Inputs - ######### - ############################################################################## - - output$strat_var <- shiny::renderUI({ - columnSelectInput( - inputId = "strat_var", - selected = "none", - label = "Select variable to stratify baseline", - data = shiny::reactive(rv$data_filtered)(), - col_subset = c( - "none", - names(rv$data_filtered)[unlist(lapply(rv$data_filtered, data_type)) %in% c("dichotomous", "categorical", "ordinal")] - ) - ) - }) - - ############################################################################## - ######### - ######### Descriptive evaluations - ######### - ############################################################################## - - - output$data_info_nochar <- shiny::renderUI({ - shiny::req(rv$list$data) - data_description(rv$list$data, data_text = "The dataset without text variables") - }) - - shiny::observeEvent( - list( - input$act_eval - ), - { - shiny::req(input$strat_var) - shiny::req(rv$list$data) - - parameters <- list( - by.var = input$strat_var, - add.p = input$add_p == "yes", - add.overall = TRUE - ) - - shiny::withProgress(message = "Creating the table. Hold on for a moment..", { - rv$list$table1 <- rlang::exec(create_baseline, !!!append_list(rv$list$data, parameters, "data")) - }) - - rv$code$table1 <- glue::glue("FreesearchR::create_baseline(data,{list2str(parameters)})") - } - ) - - output$outcome_var_cor <- shiny::renderUI({ - columnSelectInput( - inputId = "outcome_var_cor", - selected = "none", - data = rv$list$data, - label = "Select outcome variable", - col_subset = c( - "none", - colnames(rv$list$data) - ), - multiple = FALSE - ) - }) - - output$table1 <- gt::render_gt({ - if (!is.null(rv$list$table1)) { - rv$list$table1 |> - gtsummary::as_gt() |> - gt::tab_header(gt::md("**Table 1: Baseline Characteristics**")) - } else { - return(NULL) - } - }) - - data_correlations_server( - id = "correlations", - data = shiny::reactive({ - shiny::req(rv$list$data) - out <- rv$list$data - if (!is.null(input$outcome_var_cor) && input$outcome_var_cor != "none") { - out <- out[!names(out) %in% input$outcome_var_cor] - } - out - }), - cutoff = shiny::reactive(input$cor_cutoff) - ) - - ############################################################################## - ######### - ######### Data visuals - ######### - ############################################################################## - - pl <- data_visuals_server("visuals", data = shiny::reactive(rv$list$data)) - - ############################################################################## - ######### - ######### Regression model analyses - ######### - ############################################################################## - - rv$regression <- regression_server("regression", data = shiny::reactive(rv$list$data)) - - ############################################################################## - ######### - ######### Page navigation - ######### - ############################################################################## - - shiny::observeEvent(input$act_start, { - bslib::nav_select(id = "main_panel", selected = "Data") - }) - - ############################################################################## - ######### - ######### Reactivity - ######### - ############################################################################## - - output$uploaded <- shiny::reactive({ - if (is.null(rv$ds)) { - "no" - } else { - "yes" - } - }) - - shiny::outputOptions(output, "uploaded", suspendWhenHidden = FALSE) - - output$ready <- shiny::reactive({ - if (is.null(rv$ready)) { - "no" - } else { - "yes" - } - }) - - shiny::outputOptions(output, "ready", suspendWhenHidden = FALSE) - - ############################################################################## - ######### - ######### Downloads - ######### - ############################################################################## - - # Could be rendered with other tables or should show progress - # Investigate quarto render problems - # On temp file handling: https://github.com/quarto-dev/quarto-cli/issues/3992 - output$report <- downloadHandler( - filename = shiny::reactive({ - paste0("report.", input$output_type) - }), - content = function(file, type = input$output_type) { - # shiny::req(rv$list$regression) - ## Notification is not progressing - ## Presumably due to missing - # browser() - # Simplified for .rmd output attempt - format <- ifelse(type == "docx", "word_document", "odt_document") - - # browser() - rv$list$regression <- rv$regression() - - shiny::withProgress(message = "Generating the report. Hold on for a moment..", { - tryCatch( - { - rv$list |> - write_rmd( - output_format = format, - input = file.path(getwd(), "www/report.rmd") - ) - }, - error = function(err) { - showNotification(paste0("We encountered the following error creating your report: ", err), type = "err") - } - ) - }) - file.rename(paste0("www/report.", type), file) - } - ) - - output$data_modified <- downloadHandler( - filename = shiny::reactive({ - paste0("modified_data.", input$data_type) - }), - content = function(file, type = input$data_type) { - if (type == "rds") { - readr::write_rds(rv$list$data, file = file) - } else if (type == "dta") { - haven::write_dta(as.data.frame(rv$list$data), path = file) - } else if (type == "csv") { - readr::write_csv(rv$list$data, file = file) - } - } - ) - - ############################################################################## - ######### - ######### Clearing the session on end - ######### - ############################################################################## - - session$onSessionEnded(function() { - cat("Session Ended\n") - files <- list.files("www/") - lapply(files[!files %in% files.to.keep], \(.x){ - unlink(paste0("www/", .x), recursive = FALSE) - print(paste(.x, "deleted")) - }) - }) -} diff --git a/inst/apps/FreesearchR/ui.R b/inst/apps/FreesearchR/ui.R index 3e792943..d1a7259a 100644 --- a/inst/apps/FreesearchR/ui.R +++ b/inst/apps/FreesearchR/ui.R @@ -508,13 +508,10 @@ dark <- custom_theme( # Fonts to consider: # https://webdesignerdepot.com/17-open-source-fonts-youll-actually-love/ -ui <- bslib::page_fixed( +ui_list <- shiny::tagList( prismDependencies, prismRDependency, - ## Basic Umami page tracking - shiny::tags$head( - includeHTML(("www/umami-app.html")), - tags$link(rel = "stylesheet", type = "text/css", href = "style.css")), + header_include(), ## This adds the actual favicon ## png and ico versions are kept for compatibility shiny::tags$head(tags$link(rel="shortcut icon", href="favicon.svg")), @@ -546,3 +543,12 @@ ui <- bslib::page_fixed( ) ) ) + +# ui_list <- shiny::tagAppendChild(ui_list,list( +# ## Basic Umami page tracking +# shiny::tags$head(includeHTML("www/umami-app.html")) +# # shiny::tags$head(shiny::tags$script(rel="defer", src="https://analytics.gdamsbo.dk/script.js", "data-website-id"="e7d4e13a-5824-4778-bbc0-8f92fb08303a")) +# )) + +ui <- do.call( + bslib::page_fixed,ui_list) diff --git a/inst/apps/FreesearchR/www/umami-app.html b/inst/apps/FreesearchR/www/umami-app.html deleted file mode 100644 index 1270d512..00000000 --- a/inst/apps/FreesearchR/www/umami-app.html +++ /dev/null @@ -1 +0,0 @@ - From e64f9c5d17601d2ebf76d910f32ff1f93c9e9542 Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Wed, 30 Apr 2025 13:03:20 +0200 Subject: [PATCH 4/6] cleaning --- R/regression-module.R | 13 +- R/sysdata.rda | Bin 2358 -> 1981 bytes R/theme.R | 2 +- README.md | 2 + SESSION.md | 307 ++++++++++++++++++------------------------ 5 files changed, 140 insertions(+), 184 deletions(-) diff --git a/R/regression-module.R b/R/regression-module.R index c131f30c..57806bde 100644 --- a/R/regression-module.R +++ b/R/regression-module.R @@ -482,6 +482,7 @@ regression_server <- function(id, ## To avoid plotting old models on fail/error rv$list$regression$tables <- NULL + # browser() tryCatch( { parameters <- list( @@ -517,17 +518,9 @@ regression_server <- function(id, ) }) - list( - rv$code$import, - rlang::call2(.fn = "select", !!!list(input$import_var), .ns = "dplyr"), - rlang::call2(.fn = "default_parsing", .ns = "FreesearchR") - ) |> - merge_expression() |> - expression_string() - rv$list$regression$tables <- out - rv$list$input <- input + }, warning = function(warn) { showNotification(paste0(warn), type = "warning") @@ -639,7 +632,7 @@ regression_server <- function(id, ############################################################################## return(shiny::reactive({ - return(rv$list) + rv$list })) } ) diff --git a/R/sysdata.rda b/R/sysdata.rda index d77ab95cb016bf329440288de556030464f3378c..91626ca2d4f1d5bfc7229c1edc4eb0d8daa2e59c 100644 GIT binary patch literal 1981 zcmV;u2SWHlT4*^jL0KkKS(>O5J^&FY|G@wMXaz!l|KNXXpTNKW|MWxv2m#;-e;mZO zs5qmr9RW9@igv_K8ksakLn-MngCjy@3Vx^_kPL=^(dh<;k5T0YiK*xbpea8owJ|5D zWpLVdM2{ios^pgncWQm4oIGu>= zx28SKFsLC_VE`c2WQu5*sYi46W4WRYRFyy{!CZ zoOM|2t(QYzW$#2YX6{+BbomB~g_jju*vwnPW*zSAQ>9czG78}4s$xzhR&R}wGpiV6 zhK`|v8?9GDs}AQA7}aTnNmraiVzV-syhU10W&&_DNtUrR^5K~%=qD2J-778dRJl;0k z>C;ZwVS@2#wvf(pU=}vQwR&uty6dj3$)kaa0-B+fbCkvIA*OXqM!GmUQwfJDlr&Ac z8k*$83!6qUOw!w0bTEr}mhDQJ7%fHx5QyHu$r)7`$rfRpVr6A0P)$wFj7Ujg<2O#O z09a%yH}TPxjVV^FS!7LS3!^cMn5|L((kM(s0Z6EUmrQKBXC~~^bEeoxOLl{%6A`x= zxmtqJhXJiJ)KrNiBvGURQ6!2KfkDb`Tto)kBM}j0(p2Or7N|ynhoH~^2{1%VTq%*3 zv~q=`q9!5cY*kbe;Swf62#hs}(P~(*XB&KuSud-rs`iuV?@$2XYEq(z3=x(zPNqPZ z7bsPWJ|Otd5yClhFj!feFk&n|Oxz|}-hgZd5s&~$0N%(=sRKaX$%HZ3#=UeYS6XW% zgu!M+vW%`RQH`~@O6`W`MI$VrS~eCkEH~U^>`KE1@QmwFg=7(kka^k$^a?W0Sceo2 zuMQg7N;OMSv`Q&qa}DrGnpEm>?PTMjFIR*&{KO%Zge9b-Qit13zF-*3##%2^jWb2#|1r*=R2m%=X z7JG6>EjRP^Dl^BU551)G%QS$1H97v5w(SA{?6=wo0-Vy~o^Kbj?~JSJv8b=h)!;et z6|-FLRoxytDMfA|Jox%Y=iTZeA?4q~dB?5fIg3H=P}%qt)1y)^lD~_Js|)+VL@zuH zWZB9v1vg0vg`1UH<}p=z1pe8gjQ9uHmCq%0R-Tu3FZaPO(*D)1A)6$~Fncq;;u0v2 z2-#g#%0n*8G$aH!oNPM@ne9I}WR+<+Q_(c(-7`jQ>et9wT@*;%IXJi<8*S2C2&M(B z*0Qvmx=D>kK_UclO_IN8Z#3VLgiYDPvy-%0q#d*mQY*$s2U+}O4Jcnw&cv0)1&Kwx z9K;#ttU`Qu->xvQUfJH+`Hpy_ii!E&Vrq)e2&RZxAWWLZLt~%@;)+~m zcA~Rxy@{rgr8=1^z9ZS1V7bj$tj#|e}MH&)ZgTe~}mC_^Y(8AO4_T#u!;#o9AJQl*S@ngpem9R literal 2358 zcmV-63CZ?CT4*^jL0KkKSqB*{(*PCUf6)K`Xaz!l|KNXX-@w2B|L{Nn00;;H;0j+p z-b8!D;Bh5JfkO`pEO#%T75lqSrlnj6X0qQg~^#-ZwrhrVNB|k}l zsivmMGBjw=000^Q0icQLkV;Sk)Ea0Wpa1|g000000Va|pDxaz3k5qaMOivWh+9m-E zMuvdM^%*q6Fd0c1sgNcCKTwS_X@fvOG-wPH5IsFaF$76XL_J0k05s8~C#V_#000dJ zjDTdpE^-r0qeTpcDnizz6fngFP7l3{l|;JY8U78;jGGzjpc)(g?hW%8p4g@`OHvgK z9VA?5m(BY?l9Uob1c|5wt{BqO+gR0p{{pr&hZn6d0=0Yft}id?U-fHDO3(Mk9zM58 z&a!cQl4f8WjCm{MQkJF~>5Rmbl1#iX#gm^Bh-fSvv)v$&V$Q7;))*3;YK$m)7Fj!0 z)X;&4x+&ckI?cAzzSdEf?W_CC@pS|D+9=LztnIX}6Tq)E;>8#wg(;_#n6ft{QD2#U zy7|XLjBvR)X&Xy&nv>Bxib$YpHU~J2F+0o4wh~YH_ku0=Ki(}fV`fG%WmGRE403f% zj<>C3bRRm>WvVBP+g?CzZXnsdo%op=rYc0qJSz$~wU=s9m!}A`prKqDkuOqUqsg{- zdd^-BTFX4cNui=dRp`9lT)br3hs(xd^HiADYVbu|MCL=tl;lJ*YXBhi8xYJjOm(`c zvnAD94OW)qHo+Z}Ho0TV#lzXj%FfZatU8r`YAlL|j7I)8hP}0COb+Z+5a~`nKEBR@sdG= z0Yp@SAfT{ORxCyfBv6V$NU=c}EJRUcSst%Pp11i+AI}VAdn(hOutq2uz3(&&2Pjml z;-QQ%MFUAh;fCF{rjswGhV{cRt(Na9_?d!Zp)|v6=c}`f#*LW5y4B4z z7%I5iYiyyDrFAgT2|PpwyNQ@6G9kDFF4uFJu!CH%6LSV0j!G{;mJc-exPT!bt}$7; zlNW0Z1wITTUo2f#iC9x{W||skW^@R}Ow%jhE_BW{vHgzw+E$G5?+Q`GSJyghy}JBS^`4<)Pu>ng^hYL!nbL<1t}3MfCm!H4iX_XJ&1 z>Lr+&HD-*8Pvfm&r^4bN7mNwe5J(~kl}?% zQQ>=(?X(3K{L;RMI2fVB0Ydcebl>2%wXKyH@te`0V1h(sQH(?mEt7Ux5fVzln_vOa`?X7-@(hoE^V={to%AT?X4=+v&IYt_YiLnhZ^<~5dVC55$_+Y6qJJ! z1$ylbuEr90j!~+ndmpl1EPxKV9zJzL09KIB%1RFvO|d$aRhh9+mgNbvD0k@_M6@@Q zdbhYzMOGdwS?P~Z{`l`gR#>-e(I1?w5Y>seB*E-e#f*ie5!okao$AGR8g5+LF``2 z)Ymc;Txt)@aE-hHhb^Z2i3w}iGEy%hlZKo(g0W;=#*G<@g$GO6YHA~uVc{#5C0d2H zGlSMmSh(aXaFx3^<*L}QV`D`Wwfu*7K8Om4Tu~JlLMEn6Dj_On_oatS_b#jEK{(WU zlr1SB3BX)ALZ>XVgA-1YrRE@8%ASzD-gF0kcE+|3kze1eN|SYAL8ATeCbAO}1y}H5eG;T(Vp@V`ud%E`S5fw#-z%MvYqrOhoxdSNVeM*F3B6j_tIF{kEx3Y`YmbtFz zU}Uj0$cZ0+9<{b1u@G1Vaa|!5I6C5T8!TeYb)_PU>JPF8XM&N!xsI&b$;4<^THj}Z zq;bU>_4X_b)UI&nk92 zgE&im0h);&wm#0od2@UL$aZ=o9-bOuO%S~KU8fkN1#0DJga~f((IKAeVSX$FYK7@} zCrq>E+Cfz8^t-KqEh?Tj_invnwes?W3UeOs9FogGm86j`1BIBtZE|Ml0)^$gcQvppl_x4zP2*xzI3KnYF%rIwQK{ComZj|ij+d8g$f*( zWLR@z@USKW%Vokr@VHco?W#QNeQ` Date: Wed, 30 Apr 2025 13:39:20 +0200 Subject: [PATCH 5/6] version bump --- CITATION.cff | 2 +- DESCRIPTION | 2 +- NEWS.md | 8 ++++++++ R/app_version.R | 2 +- R/sysdata.rda | Bin 1981 -> 2338 bytes SESSION.md | 39 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 772834b5..27be40e0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -9,7 +9,7 @@ type: software license: AGPL-3.0-or-later title: 'FreesearchR: A free and open-source browser based data analysis tool for researchers with publication ready output' -version: 25.4.4 +version: 25.4.5 doi: 10.5281/zenodo.14527429 abstract: Easily evaluate and analysis clinical health data in your browser on a server or on your own device. Import data from multiple sources, summarise, modify and diff --git a/DESCRIPTION b/DESCRIPTION index ecafe43e..1832158a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FreesearchR Title: A free and open-source browser based data analysis tool for researchers with publication ready output -Version: 25.4.4 +Version: 25.4.5 Authors@R: c( person("Andreas Gammelgaard", "Damsbo",email="agdamsbo@clin.au.dk", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-7559-1154")), diff --git a/NEWS.md b/NEWS.md index 4336c49e..4de9b76d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,11 @@ +# FreesearchR 25.4.5 + +- *BUG*: Regression results and code not returned correctly + +- *IMPROVED*: analyses results are reset on data change + +- *NEW*: app usage tracking only in hosted app. README updated to reflect. + # FreesearchR 25.4.4 Minor updates in docs and easier citation. diff --git a/R/app_version.R b/R/app_version.R index 33d76317..6d74916b 100644 --- a/R/app_version.R +++ b/R/app_version.R @@ -1 +1 @@ -app_version <- function()'v25.4.4.250430' +app_version <- function()'v25.4.5.250430' diff --git a/R/sysdata.rda b/R/sysdata.rda index 91626ca2d4f1d5bfc7229c1edc4eb0d8daa2e59c..c616cb82b274a6909a75b1fb291520a57a44275b 100644 GIT binary patch literal 2338 zcmV+-3ElQWT4*^jL0KkKS@-*{1OOGF|Iq*cXaz!l|KNXXpTNKW|L{Nn03Zkf;0iw* zu0rA9aR;YCAPL}lB)x_a!&5*6G%_ZGO-yJhsPcx7NB}g@$n=9Ihm;za1VN}Nnqm{k zH9#~0h%^8I4FC;P|4kJL0jKJQnlxwzKmn#hKmZ1SXat%_gpg`Xm?j~hWH16^2ATsv z&>A$;9Av>XG8q{eG&BLA$ie}j(WXNX&;b;LQxUW#riPgYPZVexXc_=%h-sroh=V0j zHt`q<8Yo^a$VyU3C|3xgogbI; z2+V)i_)>=KxIsB%34*meC>!zhYX%_O9V)ZPYVFb@PN@GVgr)`q0Au< zGa42f2913x6W_1ff2EEdy_yOKlBqmJau-bpmFr2#0W2f2D#MvC1I+7*oQl+2qZ=c_ZNzLZj&Tcc=m}~Q5fc0%WhH3QD8@_Yy~DR|wAx`pL&*sh4>fm}f;z#&ODU677)Nr@r7Z{yap%=_*J>>Zm{Lu; z&Ud$F_vqEvW^|=)nJVu}-boZt667V#O^NHq&>m<|5XK4$LIR9Hz(f%QB8rg+B%u&h z=7do-pa5Coi5Bx9iI3~Vcr}0xh(QA-{>`6BRd;_*6hysxW)f-6mpR4{u)61fz-DkLs1pgn$07LrOVS@%f|B#F5_Kwc;ayFHI>WC8J6zmM-9^C*Ey??MN?Xrd6?x_mg_F_ zgJ!AE28{@=fCV7{w0UaRhc~|3!yB$C&h?X4uKRJW4lfP5abp4lpk5ghJclUFX^bQ& zVT`u^DA1_&YUt6LZ~O>(44+*N_D9L2j?AkXjjLD6&;fy~Y863e=!eJgo|C3KcQCUP zCalqsMyg1hY{gTMaiH255P?Am1k(+c_+bG{1{fggH*;~ zn66qV#+J7dy%Vz{k)8)8NLr&wVhTkjT+iT@n87=s2zizStRf)B2$Qw?&OpmRw6e>l z2Zm56C1gge~` zA7F$a&hHJJ^+USe$mx1Ym8(UBAke~ch8m)a{NGK|>b5DswxHF9RN;#Q(eytre}|XK zCj~Z2tS((RXgl8Ym)Rvx6Q@UXlo$xNzN*!MC8h*ttTJYlkj=5{k{mfZ%caw{QeMZ;#YOL&v|Rj&SwRK_Wn} zO6iJ;9E179>Sv_Nh*=HI22ASoAJ;A3+HMpntYsF;JbhjmYh~DyUVN<1@^Z zQn{(~c35kP;e1%s_c3C=2G`OgCv6te7Ke^6Ect4^`$5TIwH*j6ili!~-;zYO7bV9K z3wl^#uh0&d@=ES1B6p3q!bq`h+cF+=+7w0VLs&y$Sq96%>S3(HA<9g!iQ?qlNVz5N~RN)VJdGFIXjw)Z%V0^;TQv>dCelF zKr5kj>j$cVuBWdopzpy&i@5XaqVfJ1Cx@yyW1J7mv)9aJqVt)E9614XA#so@dNS#* zy=9njZ1XU4wtKv@wm}sOPO2XZ8E44KJ5n&9B%p?v?tYpHxyS~POL@|$qk?3{U0R_v znN7>Lf>tdIgOUpJzJUu6;OP^MqO|O(2o2{zrY||qp(f=_^WEl{=F?7<^qSf{XUABM z1gBC#xRjH@M^L)7CL>{!Kn@5l%M{8?8Q2)KgA#+i6 z(MOQ*E{>%1XC3>i!HsG2(|nAKv#@33ghJ@D)RdV>J z*{004C9hE@CvE|C;AE?-uD9#5WTn5R&En;R=eKK?&V1>B**CJm?iy#KITUe%oh#L< zkg>c}9kQ;;X4jX4In46t%H4*`tm{|<)_+e1Vi=eL0t;wV%L9DbbhvE@!)%4FgpEqmnuxjWAIKj`0?JUJQ2&d$BAh5l Id;Qk}01iV?fdBvi literal 1981 zcmV;u2SWHlT4*^jL0KkKS(>O5J^&FY|G@wMXaz!l|KNXXpTNKW|MWxv2m#;-e;mZO zs5qmr9RW9@igv_K8ksakLn-MngCjy@3Vx^_kPL=^(dh<;k5T0YiK*xbpea8owJ|5D zWpLVdM2{ios^pgncWQm4oIGu>= zx28SKFsLC_VE`c2WQu5*sYi46W4WRYRFyy{!CZ zoOM|2t(QYzW$#2YX6{+BbomB~g_jju*vwnPW*zSAQ>9czG78}4s$xzhR&R}wGpiV6 zhK`|v8?9GDs}AQA7}aTnNmraiVzV-syhU10W&&_DNtUrR^5K~%=qD2J-778dRJl;0k z>C;ZwVS@2#wvf(pU=}vQwR&uty6dj3$)kaa0-B+fbCkvIA*OXqM!GmUQwfJDlr&Ac z8k*$83!6qUOw!w0bTEr}mhDQJ7%fHx5QyHu$r)7`$rfRpVr6A0P)$wFj7Ujg<2O#O z09a%yH}TPxjVV^FS!7LS3!^cMn5|L((kM(s0Z6EUmrQKBXC~~^bEeoxOLl{%6A`x= zxmtqJhXJiJ)KrNiBvGURQ6!2KfkDb`Tto)kBM}j0(p2Or7N|ynhoH~^2{1%VTq%*3 zv~q=`q9!5cY*kbe;Swf62#hs}(P~(*XB&KuSud-rs`iuV?@$2XYEq(z3=x(zPNqPZ z7bsPWJ|Otd5yClhFj!feFk&n|Oxz|}-hgZd5s&~$0N%(=sRKaX$%HZ3#=UeYS6XW% zgu!M+vW%`RQH`~@O6`W`MI$VrS~eCkEH~U^>`KE1@QmwFg=7(kka^k$^a?W0Sceo2 zuMQg7N;OMSv`Q&qa}DrGnpEm>?PTMjFIR*&{KO%Zge9b-Qit13zF-*3##%2^jWb2#|1r*=R2m%=X z7JG6>EjRP^Dl^BU551)G%QS$1H97v5w(SA{?6=wo0-Vy~o^Kbj?~JSJv8b=h)!;et z6|-FLRoxytDMfA|Jox%Y=iTZeA?4q~dB?5fIg3H=P}%qt)1y)^lD~_Js|)+VL@zuH zWZB9v1vg0vg`1UH<}p=z1pe8gjQ9uHmCq%0R-Tu3FZaPO(*D)1A)6$~Fncq;;u0v2 z2-#g#%0n*8G$aH!oNPM@ne9I}WR+<+Q_(c(-7`jQ>et9wT@*;%IXJi<8*S2C2&M(B z*0Qvmx=D>kK_UclO_IN8Z#3VLgiYDPvy-%0q#d*mQY*$s2U+}O4Jcnw&cv0)1&Kwx z9K;#ttU`Qu->xvQUfJH+`Hpy_ii!E&Vrq)e2&RZxAWWLZLt~%@;)+~m zcA~Rxy@{rgr8=1^z9ZS1V7bj$tj#|e}MH&)ZgTe~}mC_^Y(8AO4_T#u!;#o9AJQl*S@ngpem9R diff --git a/SESSION.md b/SESSION.md index fc373248..16b1535e 100644 --- a/SESSION.md +++ b/SESSION.md @@ -15,7 +15,7 @@ |rstudio |2024.12.1+563 Kousa Dogwood (desktop) | |pandoc |3.6.4 @ /opt/homebrew/bin/ (via rmarkdown) | |quarto |1.6.40 @ /usr/local/bin/quarto | -|FreesearchR |25.4.4.250430 | +|FreesearchR |25.4.5.250430 | -------------------------------------------------------------------------------- @@ -24,8 +24,10 @@ |package |loadedversion |date |source | |:-------------|:-------------|:----------|:--------------| |apexcharter |0.4.4 |2024-09-06 |CRAN (R 4.4.1) | +|askpass |1.2.1 |2024-10-04 |CRAN (R 4.4.1) | |assertthat |0.2.1 |2019-03-21 |CRAN (R 4.4.1) | |backports |1.5.0 |2024-05-23 |CRAN (R 4.4.1) | +|base64enc |0.1-3 |2015-07-28 |CRAN (R 4.4.1) | |bayestestR |0.15.3 |2025-04-28 |CRAN (R 4.4.1) | |bit |4.6.0 |2025-03-06 |CRAN (R 4.4.1) | |bit64 |4.6.0-1 |2025-01-16 |CRAN (R 4.4.1) | @@ -35,11 +37,15 @@ |bsicons |0.1.2 |2023-11-04 |CRAN (R 4.4.0) | |bslib |0.9.0 |2025-01-30 |CRAN (R 4.4.1) | |cachem |1.1.0 |2024-05-16 |CRAN (R 4.4.1) | +|cards |0.6.0 |2025-04-11 |CRAN (R 4.4.1) | |cellranger |1.1.0 |2016-07-27 |CRAN (R 4.4.0) | |cffr |1.2.0 |2025-01-25 |CRAN (R 4.4.1) | +|checkmate |2.3.2 |2024-07-29 |CRAN (R 4.4.0) | |class |7.3-23 |2025-01-01 |CRAN (R 4.4.1) | |classInt |0.4-11 |2025-01-08 |CRAN (R 4.4.1) | |cli |3.6.5 |2025-04-23 |CRAN (R 4.4.1) | +|cluster |2.1.8.1 |2025-03-12 |CRAN (R 4.4.1) | +|colorspace |2.1-1 |2024-07-26 |CRAN (R 4.4.1) | |commonmark |1.9.5 |2025-03-17 |CRAN (R 4.4.1) | |correlation |0.8.7 |2025-03-03 |CRAN (R 4.4.1) | |crayon |1.5.3 |2024-06-20 |CRAN (R 4.4.1) | @@ -63,16 +69,23 @@ |fastmap |1.2.0 |2024-05-15 |CRAN (R 4.4.1) | |fontawesome |0.5.3 |2024-11-16 |CRAN (R 4.4.1) | |forcats |1.0.0 |2023-01-29 |CRAN (R 4.4.0) | +|foreign |0.8-90 |2025-03-31 |CRAN (R 4.4.1) | +|Formula |1.2-5 |2023-02-24 |CRAN (R 4.4.1) | |fs |1.6.6 |2025-04-12 |CRAN (R 4.4.1) | |generics |0.1.3 |2022-07-05 |CRAN (R 4.4.1) | +|ggcorrplot |0.1.4.1 |2023-09-05 |CRAN (R 4.4.0) | |ggplot2 |3.5.2 |2025-04-09 |CRAN (R 4.4.1) | +|ggstats |0.9.0 |2025-03-10 |CRAN (R 4.4.1) | |glue |1.8.0 |2024-09-30 |CRAN (R 4.4.1) | +|gridExtra |2.3 |2017-09-09 |CRAN (R 4.4.1) | |gt |1.0.0 |2025-04-05 |CRAN (R 4.4.1) | |gtable |0.3.6 |2024-10-25 |CRAN (R 4.4.1) | |gtsummary |2.2.0 |2025-04-14 |CRAN (R 4.4.1) | |haven |2.5.4 |2023-11-30 |CRAN (R 4.4.0) | |here |1.0.1 |2020-12-13 |CRAN (R 4.4.1) | +|Hmisc |5.2-3 |2025-03-16 |CRAN (R 4.4.1) | |hms |1.1.3 |2023-03-21 |CRAN (R 4.4.0) | +|htmlTable |2.4.3 |2024-07-21 |CRAN (R 4.4.0) | |htmltools |0.5.8.1 |2024-04-04 |CRAN (R 4.4.1) | |htmlwidgets |1.6.4 |2023-12-06 |CRAN (R 4.4.0) | |httpuv |1.6.16 |2025-04-16 |CRAN (R 4.4.1) | @@ -82,12 +95,17 @@ |jsonlite |2.0.0 |2025-03-27 |CRAN (R 4.4.1) | |jsonvalidate |1.5.0 |2025-02-07 |CRAN (R 4.4.1) | |KernSmooth |2.23-26 |2025-01-01 |CRAN (R 4.4.1) | +|keyring |1.3.2 |2023-12-11 |CRAN (R 4.4.0) | |knitr |1.50 |2025-03-16 |CRAN (R 4.4.1) | +|labeling |0.4.3 |2023-08-29 |CRAN (R 4.4.1) | +|labelled |2.14.0 |2025-01-08 |CRAN (R 4.4.1) | |later |1.4.2 |2025-04-08 |CRAN (R 4.4.1) | |lattice |0.22-7 |2025-04-02 |CRAN (R 4.4.1) | |lifecycle |1.0.4 |2023-11-07 |CRAN (R 4.4.1) | +|litedown |0.7 |2025-04-08 |CRAN (R 4.4.1) | |lme4 |1.1-37 |2025-03-26 |CRAN (R 4.4.1) | |magrittr |2.0.3 |2022-03-30 |CRAN (R 4.4.1) | +|markdown |2.0 |2025-03-23 |CRAN (R 4.4.1) | |MASS |7.3-65 |2025-02-28 |CRAN (R 4.4.1) | |Matrix |1.7-3 |2025-03-11 |CRAN (R 4.4.1) | |memoise |2.0.1 |2021-11-26 |CRAN (R 4.4.0) | @@ -97,6 +115,9 @@ |modelbased |0.10.0 |2025-03-10 |CRAN (R 4.4.1) | |nlme |3.1-168 |2025-03-31 |CRAN (R 4.4.1) | |nloptr |2.2.1 |2025-03-17 |CRAN (R 4.4.1) | +|nnet |7.3-20 |2025-01-01 |CRAN (R 4.4.1) | +|openssl |2.3.2 |2025-02-03 |CRAN (R 4.4.1) | +|openxlsx2 |1.15 |2025-04-25 |CRAN (R 4.4.1) | |parameters |0.24.2 |2025-03-04 |CRAN (R 4.4.1) | |patchwork |1.3.0 |2024-09-16 |CRAN (R 4.4.1) | |performance |0.13.0 |2025-01-15 |CRAN (R 4.4.1) | @@ -105,6 +126,7 @@ |pkgbuild |1.4.7 |2025-03-24 |CRAN (R 4.4.1) | |pkgconfig |2.0.3 |2019-09-22 |CRAN (R 4.4.1) | |pkgload |1.4.0 |2024-06-28 |CRAN (R 4.4.0) | +|plyr |1.8.9 |2023-10-02 |CRAN (R 4.4.1) | |processx |3.8.6 |2025-02-21 |CRAN (R 4.4.1) | |profvis |0.4.0 |2024-09-20 |CRAN (R 4.4.1) | |promises |1.3.2 |2024-11-28 |CRAN (R 4.4.1) | @@ -112,7 +134,12 @@ |ps |1.9.1 |2025-04-12 |CRAN (R 4.4.1) | |purrr |1.0.4 |2025-02-05 |CRAN (R 4.4.1) | |quarto |1.4.4 |2024-07-20 |CRAN (R 4.4.0) | +|R.cache |0.16.0 |2022-07-21 |CRAN (R 4.4.0) | +|R.methodsS3 |1.8.2 |2022-06-13 |CRAN (R 4.4.1) | +|R.oo |1.27.0 |2024-11-01 |CRAN (R 4.4.1) | +|R.utils |2.13.0 |2025-02-24 |CRAN (R 4.4.1) | |R6 |2.6.1 |2025-02-15 |CRAN (R 4.4.1) | +|ragg |1.4.0 |2025-04-10 |CRAN (R 4.4.1) | |rbibutils |2.3 |2024-10-04 |CRAN (R 4.4.1) | |RColorBrewer |1.1-3 |2022-04-03 |CRAN (R 4.4.1) | |Rcpp |1.0.14 |2025-01-12 |CRAN (R 4.4.1) | @@ -121,13 +148,17 @@ |readODS |2.3.2 |2025-01-13 |CRAN (R 4.4.1) | |readr |2.1.5 |2024-01-10 |CRAN (R 4.4.0) | |readxl |1.4.5 |2025-03-07 |CRAN (R 4.4.1) | +|REDCapCAST |25.3.2 |2025-03-10 |CRAN (R 4.4.1) | +|REDCapR |1.4.0 |2025-01-11 |CRAN (R 4.4.1) | |reformulas |0.4.0 |2024-11-03 |CRAN (R 4.4.1) | |remotes |2.5.0 |2024-03-17 |CRAN (R 4.4.1) | |renv |1.1.4 |2025-03-20 |CRAN (R 4.4.1) | |report |0.6.1 |2025-02-07 |CRAN (R 4.4.1) | +|reshape2 |1.4.4 |2020-04-09 |CRAN (R 4.4.0) | |rio |1.2.3 |2024-09-25 |CRAN (R 4.4.1) | |rlang |1.1.6 |2025-04-11 |CRAN (R 4.4.1) | |rmarkdown |2.29 |2024-11-04 |CRAN (R 4.4.1) | +|rpart |4.1.24 |2025-01-07 |CRAN (R 4.4.1) | |rprojroot |2.0.4 |2023-11-05 |CRAN (R 4.4.1) | |rsconnect |1.3.4 |2025-01-22 |CRAN (R 4.4.1) | |rstudioapi |0.17.1 |2024-10-22 |CRAN (R 4.4.1) | @@ -139,6 +170,11 @@ |shinybusy |0.3.3 |2024-03-09 |CRAN (R 4.4.0) | |shinyTime |1.0.3 |2022-08-19 |CRAN (R 4.4.0) | |shinyWidgets |0.9.0 |2025-02-21 |CRAN (R 4.4.1) | +|stringi |1.8.7 |2025-03-27 |CRAN (R 4.4.1) | +|stringr |1.5.1 |2023-11-14 |CRAN (R 4.4.0) | +|styler |1.10.3 |2024-04-07 |CRAN (R 4.4.0) | +|systemfonts |1.2.2 |2025-04-04 |CRAN (R 4.4.1) | +|textshaping |1.0.0 |2025-01-20 |CRAN (R 4.4.1) | |tibble |3.2.1 |2023-03-20 |CRAN (R 4.4.0) | |tidyr |1.3.1 |2024-01-24 |CRAN (R 4.4.1) | |tidyselect |1.2.1 |2024-03-11 |CRAN (R 4.4.0) | @@ -155,3 +191,4 @@ |xml2 |1.3.8 |2025-03-14 |CRAN (R 4.4.1) | |xtable |1.8-4 |2019-04-21 |CRAN (R 4.4.1) | |yaml |2.3.10 |2024-07-26 |CRAN (R 4.4.1) | +|zip |2.3.2 |2025-02-01 |CRAN (R 4.4.1) | From 4d4403d5e5189824753f7ed2048f0a5084dace7b Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Wed, 30 Apr 2025 13:41:57 +0200 Subject: [PATCH 6/6] session updated --- R/sysdata.rda | Bin 2338 -> 2381 bytes SESSION.md | 7 +++++++ 2 files changed, 7 insertions(+) diff --git a/R/sysdata.rda b/R/sysdata.rda index c616cb82b274a6909a75b1fb291520a57a44275b..e6434994b0882740a8634f98a1500d38e07e9b06 100644 GIT binary patch literal 2381 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 Id;Qk}01iV?fdBvi diff --git a/SESSION.md b/SESSION.md index 16b1535e..33e6cc5e 100644 --- a/SESSION.md +++ b/SESSION.md @@ -49,6 +49,7 @@ |commonmark |1.9.5 |2025-03-17 |CRAN (R 4.4.1) | |correlation |0.8.7 |2025-03-03 |CRAN (R 4.4.1) | |crayon |1.5.3 |2024-06-20 |CRAN (R 4.4.1) | +|credentials |2.0.2 |2024-10-04 |CRAN (R 4.4.1) | |crosstalk |1.2.1 |2023-11-23 |CRAN (R 4.4.0) | |curl |6.2.2 |2025-03-24 |CRAN (R 4.4.1) | |data.table |1.17.0 |2025-02-22 |CRAN (R 4.4.1) | @@ -73,9 +74,12 @@ |Formula |1.2-5 |2023-02-24 |CRAN (R 4.4.1) | |fs |1.6.6 |2025-04-12 |CRAN (R 4.4.1) | |generics |0.1.3 |2022-07-05 |CRAN (R 4.4.1) | +|gert |2.1.5 |2025-03-25 |CRAN (R 4.4.1) | |ggcorrplot |0.1.4.1 |2023-09-05 |CRAN (R 4.4.0) | |ggplot2 |3.5.2 |2025-04-09 |CRAN (R 4.4.1) | |ggstats |0.9.0 |2025-03-10 |CRAN (R 4.4.1) | +|gh |1.4.1 |2024-03-28 |CRAN (R 4.4.0) | +|gitcreds |0.1.2 |2022-09-08 |CRAN (R 4.4.1) | |glue |1.8.0 |2024-09-30 |CRAN (R 4.4.1) | |gridExtra |2.3 |2017-09-09 |CRAN (R 4.4.1) | |gt |1.0.0 |2025-04-05 |CRAN (R 4.4.1) | @@ -89,6 +93,7 @@ |htmltools |0.5.8.1 |2024-04-04 |CRAN (R 4.4.1) | |htmlwidgets |1.6.4 |2023-12-06 |CRAN (R 4.4.0) | |httpuv |1.6.16 |2025-04-16 |CRAN (R 4.4.1) | +|httr2 |1.1.2 |2025-03-26 |CRAN (R 4.4.1) | |IDEAFilter |0.2.0 |2024-04-15 |CRAN (R 4.4.0) | |insight |1.2.0 |2025-04-22 |CRAN (R 4.4.1) | |jquerylib |0.1.4 |2021-04-26 |CRAN (R 4.4.0) | @@ -140,6 +145,7 @@ |R.utils |2.13.0 |2025-02-24 |CRAN (R 4.4.1) | |R6 |2.6.1 |2025-02-15 |CRAN (R 4.4.1) | |ragg |1.4.0 |2025-04-10 |CRAN (R 4.4.1) | +|rappdirs |0.3.3 |2021-01-31 |CRAN (R 4.4.1) | |rbibutils |2.3 |2024-10-04 |CRAN (R 4.4.1) | |RColorBrewer |1.1-3 |2022-04-03 |CRAN (R 4.4.1) | |Rcpp |1.0.14 |2025-01-12 |CRAN (R 4.4.1) | @@ -173,6 +179,7 @@ |stringi |1.8.7 |2025-03-27 |CRAN (R 4.4.1) | |stringr |1.5.1 |2023-11-14 |CRAN (R 4.4.0) | |styler |1.10.3 |2024-04-07 |CRAN (R 4.4.0) | +|sys |3.4.3 |2024-10-04 |CRAN (R 4.4.1) | |systemfonts |1.2.2 |2025-04-04 |CRAN (R 4.4.1) | |textshaping |1.0.0 |2025-01-20 |CRAN (R 4.4.1) | |tibble |3.2.1 |2023-03-20 |CRAN (R 4.4.0) |