From d9614eb37fb6eca9fa4cab0e3477d749a4e7d70e Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Fri, 12 Dec 2025 17:52:27 +0100 Subject: [PATCH] new version --- CITATION.cff | 65 ++++- DESCRIPTION | 10 +- NAMESPACE | 2 +- NEWS.md | 8 + R/app_version.R | 2 +- R/hosted_version.R | 2 +- R/plot-download-module.R | 65 ++++- R/sysdata.rda | Bin 2704 -> 2842 bytes SESSION.md | 24 +- app_docker/Dockerfile | 2 +- app_docker/app.R | 284 ++++++++++++++++++--- app_docker/renv.lock | 163 ++++++++++++ app_docker/translations/translation_da.csv | 2 + app_docker/translations/translation_de.csv | 2 + app_docker/translations/translation_sv.csv | 2 + app_docker/translations/translation_sw.csv | 2 + inst/apps/FreesearchR/app.R | 284 ++++++++++++++++++--- inst/translations/translation_da.csv | 2 + inst/translations/translation_de.csv | 2 + inst/translations/translation_sv.csv | 2 + inst/translations/translation_sw.csv | 2 + man/create-column.Rd | 6 +- renv.lock | 163 ++++++++++++ 23 files changed, 1007 insertions(+), 89 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index a824aac3..947447f8 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,7 +8,7 @@ message: 'To cite package "FreesearchR" in publications use:' type: software license: AGPL-3.0-or-later title: 'FreesearchR: Easy data analysis for clinicians' -version: 25.12.5 +version: 25.12.6 doi: 10.5281/zenodo.14527429 identifiers: - type: url @@ -1140,6 +1140,69 @@ references: email: bradleysaul@fastmail.com year: '2025' doi: 10.32614/CRAN.package.smd +- type: software + title: doconv + abstract: 'doconv: Document Conversion to ''PDF'' or ''PNG''' + notes: Imports + url: https://github.com/ardata-fr/doconv + repository: https://CRAN.R-project.org/package=doconv + authors: + - family-names: Gohel + given-names: David + email: david.gohel@ardata.fr + year: '2025' + doi: 10.32614/CRAN.package.doconv +- type: software + title: locatexec + abstract: 'locatexec: Detection and Localization of Executable Files' + notes: Imports + url: https://github.com/ardata-fr/locatexec + repository: https://CRAN.R-project.org/package=locatexec + authors: + - family-names: Gohel + given-names: David + email: david.gohel@ardata.fr + year: '2025' + doi: 10.32614/CRAN.package.locatexec +- type: software + title: magick + abstract: 'magick: Advanced Graphics and Image-Processing in R' + notes: Imports + url: https://docs.ropensci.org/magick/ + repository: https://CRAN.R-project.org/package=magick + authors: + - family-names: Ooms + given-names: Jeroen + email: jeroenooms@gmail.com + orcid: https://orcid.org/0000-0002-4035-0289 + year: '2025' + doi: 10.32614/CRAN.package.magick +- type: software + title: pdftools + abstract: 'pdftools: Text Extraction, Rendering and Converting of PDF Documents' + notes: Imports + url: https://ropensci.r-universe.dev/pdftools + repository: https://CRAN.R-project.org/package=pdftools + authors: + - family-names: Ooms + given-names: Jeroen + email: jeroenooms@gmail.com + orcid: https://orcid.org/0000-0002-4035-0289 + year: '2025' + doi: 10.32614/CRAN.package.pdftools +- type: software + title: qpdf + abstract: 'qpdf: Split, Combine and Compress PDF Files' + notes: Imports + url: https://docs.ropensci.org/qpdf/ + repository: https://CRAN.R-project.org/package=qpdf + authors: + - family-names: Ooms + given-names: Jeroen + email: jeroenooms@gmail.com + orcid: https://orcid.org/0000-0002-4035-0289 + year: '2025' + doi: 10.32614/CRAN.package.qpdf - type: software title: styler abstract: 'styler: Non-Invasive Pretty Printing of R Code' diff --git a/DESCRIPTION b/DESCRIPTION index 7d7defde..3371445d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: FreesearchR Title: Easy data analysis for clinicians -Version: 25.12.5 +Version: 25.12.6 Authors@R: c( person("Andreas Gammelgaard", "Damsbo",email="agdamsbo@clin.au.dk", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-7559-1154")), @@ -71,7 +71,12 @@ Imports: stRoke, data.table, viridis, - smd + smd, + doconv, + locatexec, + magick, + pdftools, + qpdf Suggests: styler, devtools, @@ -131,6 +136,7 @@ Collate: 'report.R' 'separate_string.R' 'syntax_highlight.R' + 'table-download-module.R' 'theme.R' 'translate.R' 'ui_elements.R' diff --git a/NAMESPACE b/NAMESPACE index 327046f2..dda3937b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,6 +10,7 @@ export(add_class_icon) export(add_sparkline) export(align_axes) export(all_but) +export(allowed_operations) export(append_column) export(append_list) export(argsstring2list) @@ -88,7 +89,6 @@ export(launch_FreesearchR) export(limit_data_size) export(limit_log) export(line_break) -export(list_allowed_operations) export(list_pkg_data) export(m_redcap_readServer) export(m_redcap_readUI) diff --git a/NEWS.md b/NEWS.md index 50c21a23..1feb3778 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,11 @@ +# FreesearchR 25.12.6 + +*NEW* Export missingness table directly. + +*NEW* Updated and slightly extended list of allowed operators for new variable creation. + +*FIX* The exported MS Word documents prompted a warning. I believe that has been fixed, but required several new dependencies. + # FreesearchR 25.12.5 *NEW* Added option to add pairwise differences in discriptive table. diff --git a/R/app_version.R b/R/app_version.R index d3253ba3..098f2ac8 100644 --- a/R/app_version.R +++ b/R/app_version.R @@ -1 +1 @@ -app_version <- function()'25.12.5' +app_version <- function()'25.12.6' diff --git a/R/hosted_version.R b/R/hosted_version.R index 1c023b20..82f879ce 100644 --- a/R/hosted_version.R +++ b/R/hosted_version.R @@ -1 +1 @@ -hosted_version <- function()'v25.12.5-251211' +hosted_version <- function()'v25.12.6-251212' diff --git a/R/plot-download-module.R b/R/plot-download-module.R index 3ab1dc77..4caf94bf 100644 --- a/R/plot-download-module.R +++ b/R/plot-download-module.R @@ -51,12 +51,10 @@ plot_download_server <- function(id, shiny::moduleServer( id = id, module = function(input, output, session) { - # ns <- session$ns - - - output$download_plot <- shiny::downloadHandler( - filename = paste0(file_name, ".", input$plot_type), + filename = function() { + paste0(file_name, ".", input$plot_type) + }, content = function(file) { shiny::withProgress(message = "Saving the plot. Hold on for a moment..", { ggplot2::ggsave( @@ -65,7 +63,8 @@ plot_download_server <- function(id, width = input$plot_width, height = input$plot_height, dpi = 300, - units = "mm", scale = 2 + units = "mm", + scale = 2 ) }) } @@ -73,3 +72,57 @@ plot_download_server <- function(id, } ) } + + +plot_download_demo_app <- function() { + + ui <- bslib::page_fillable( + title = "Plot Download Demo", + bslib::layout_sidebar( + sidebar = bslib::sidebar( + title = "Download Settings", + plot_download_ui(id = "plot_dwn") + ), + bslib::card( + bslib::card_header("Sample Plot"), + shiny::plotOutput("demo_plot", height = "500px") + ) + ) + ) + + server <- function(input, output, session) { + + # Create a sample ggplot + sample_plot <- ggplot2::ggplot(mtcars, ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) + + ggplot2::geom_point(size = 3) + + ggplot2::geom_smooth(method = "lm", se = TRUE) + + ggplot2::labs( + title = "Car Weight vs MPG", + x = "Weight (1000 lbs)", + y = "Miles per Gallon", + color = "Cylinders" + ) + + ggplot2::theme_minimal() + + ggplot2::theme( + plot.title = ggplot2::element_text(size = 16, face = "bold"), + legend.position = "bottom" + ) + + # Display the plot + output$demo_plot <- shiny::renderPlot({ + sample_plot + }) + + # Connect to download module + plot_download_server( + id = "plot_dwn", + data = sample_plot, + file_name = "mtcars_plot" + ) + } + + shiny::shinyApp(ui, server) +} + +# Run the demo +# plot_download_demo_app() diff --git a/R/sysdata.rda b/R/sysdata.rda index 31d74cda07a59213061a29c315a03a1c6bc02cf3..19ccc239cc55ee35e0797899d619ceddab286ce9 100644 GIT binary patch literal 2842 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 KC`ekUtK@)g6%1Pd diff --git a/SESSION.md b/SESSION.md index 7d4f2028..9c16e40e 100644 --- a/SESSION.md +++ b/SESSION.md @@ -11,11 +11,11 @@ |collate |en_US.UTF-8 | |ctype |en_US.UTF-8 | |tz |Europe/Copenhagen | -|date |2025-12-11 | +|date |2025-12-12 | |rstudio |2025.09.2+418 Cucumberleaf Sunflower (desktop) | |pandoc |3.6.4 @ /opt/homebrew/bin/ (via rmarkdown) | |quarto |1.7.30 @ /usr/local/bin/quarto | -|FreesearchR |25.12.5.251211 | +|FreesearchR |25.12.6.251212 | -------------------------------------------------------------------------------- @@ -44,6 +44,7 @@ |cardx |0.3.1 |2025-12-04 |CRAN (R 4.4.3) | |caTools |1.18.3 |2024-09-04 |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.3 |2025-08-18 |CRAN (R 4.4.1) | |class |7.3-23 |2025-01-01 |CRAN (R 4.4.1) | |classInt |0.4-11 |2025-01-08 |CRAN (R 4.4.1) | @@ -53,6 +54,7 @@ |colorspace |2.1-2 |2025-09-22 |CRAN (R 4.4.1) | |commonmark |2.0.0 |2025-07-07 |CRAN (R 4.4.1) | |crayon |1.5.3 |2024-06-20 |CRAN (R 4.4.1) | +|curl |7.0.0 |2025-08-19 |CRAN (R 4.4.1) | |data.table |1.17.8 |2025-07-10 |CRAN (R 4.4.1) | |datamods |1.5.3 |2024-10-02 |CRAN (R 4.4.1) | |datawizard |1.3.0 |2025-10-11 |CRAN (R 4.4.1) | @@ -61,6 +63,7 @@ |devtools |2.4.6 |2025-10-03 |CRAN (R 4.4.1) | |DHARMa |0.4.7 |2024-10-18 |CRAN (R 4.4.1) | |digest |0.6.39 |2025-11-19 |CRAN (R 4.4.3) | +|doconv |0.3.3 |2025-08-18 |CRAN (R 4.4.1) | |doParallel |1.0.17 |2022-02-07 |CRAN (R 4.4.0) | |dplyr |1.1.4 |2023-11-17 |CRAN (R 4.4.0) | |DT |0.34.0 |2025-09-02 |CRAN (R 4.4.1) | @@ -83,7 +86,7 @@ |foreach |1.5.2 |2022-02-02 |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) | -|FreesearchR |25.12.5 |NA |NA | +|FreesearchR |25.12.6 |NA |NA | |fs |1.6.6 |2025-04-12 |CRAN (R 4.4.1) | |gdtools |0.4.4 |2025-10-06 |CRAN (R 4.4.1) | |generics |0.1.4 |2025-05-09 |CRAN (R 4.4.1) | @@ -111,20 +114,25 @@ |iterators |1.0.14 |2022-02-05 |CRAN (R 4.4.1) | |jquerylib |0.1.4 |2021-04-26 |CRAN (R 4.4.0) | |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.4.1 |2025-06-15 |CRAN (R 4.4.1) | |knitr |1.50 |2025-03-16 |CRAN (R 4.4.1) | +|labeling |0.4.3 |2023-08-29 |CRAN (R 4.4.1) | |later |1.4.4 |2025-08-27 |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.8 |2025-11-02 |CRAN (R 4.4.1) | |lme4 |1.1-38 |2025-12-02 |CRAN (R 4.4.3) | +|locatexec |0.1.1 |2021-05-19 |CRAN (R 4.4.0) | |lubridate |1.9.4 |2024-12-08 |CRAN (R 4.4.1) | +|magick |2.9.0 |2025-09-08 |CRAN (R 4.4.1) | |magrittr |2.0.4 |2025-09-12 |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-4 |2025-08-28 |CRAN (R 4.4.1) | |memoise |2.0.1 |2021-11-26 |CRAN (R 4.4.0) | +|mgcv |1.9-4 |2025-11-07 |CRAN (R 4.4.1) | |mime |0.13 |2025-03-17 |CRAN (R 4.4.1) | |minqa |1.2.8 |2024-08-17 |CRAN (R 4.4.1) | |mvtnorm |1.3-3 |2025-01-10 |CRAN (R 4.4.1) | @@ -137,9 +145,11 @@ |openssl |2.3.4 |2025-09-30 |CRAN (R 4.4.1) | |openxlsx2 |1.22 |2025-12-07 |CRAN (R 4.4.3) | |otel |0.2.0 |2025-08-29 |CRAN (R 4.4.1) | +|pak |0.9.1 |2025-12-01 |CRAN (R 4.4.3) | |parameters |0.28.3 |2025-11-25 |CRAN (R 4.4.3) | |patchwork |1.3.2 |2025-08-25 |CRAN (R 4.4.1) | |pbmcapply |1.5.1 |2022-04-28 |CRAN (R 4.4.1) | +|pdftools |3.6.0 |2025-09-10 |CRAN (R 4.4.1) | |performance |0.15.3 |2025-12-01 |CRAN (R 4.4.3) | |phosphoricons |0.2.1 |2024-04-08 |CRAN (R 4.4.0) | |pillar |1.11.1 |2025-09-17 |CRAN (R 4.4.1) | @@ -154,12 +164,18 @@ |proxy |0.4-27 |2022-06-09 |CRAN (R 4.4.1) | |ps |1.9.1 |2025-04-12 |CRAN (R 4.4.1) | |purrr |1.2.0 |2025-11-04 |CRAN (R 4.4.1) | +|qpdf |1.4.1 |2025-07-02 |CRAN (R 4.4.1) | |qqconf |1.3.2 |2023-04-14 |CRAN (R 4.4.0) | |qqplotr |0.0.7 |2025-09-05 |CRAN (R 4.4.1) | |quarto |1.5.1 |2025-09-04 |CRAN (R 4.4.1) | +|R.cache |0.17.0 |2025-05-02 |CRAN (R 4.4.1) | +|R.methodsS3 |1.8.2 |2022-06-13 |CRAN (R 4.4.1) | +|R.oo |1.27.1 |2025-05-02 |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.5.0 |2025-09-02 |CRAN (R 4.4.1) | |rankinPlot |1.1.0 |2023-01-30 |CRAN (R 4.4.0) | +|rappdirs |0.3.3 |2021-01-31 |CRAN (R 4.4.1) | |rbibutils |2.4 |2025-11-07 |CRAN (R 4.4.1) | |RColorBrewer |1.1-3 |2022-04-03 |CRAN (R 4.4.1) | |Rcpp |1.1.0 |2025-07-02 |CRAN (R 4.4.1) | @@ -200,6 +216,7 @@ |stringi |1.8.7 |2025-03-27 |CRAN (R 4.4.1) | |stringr |1.6.0 |2025-11-04 |CRAN (R 4.4.1) | |stRoke |25.9.2 |2025-09-30 |CRAN (R 4.4.1) | +|styler |1.11.0 |2025-10-13 |CRAN (R 4.4.1) | |systemfonts |1.3.1 |2025-10-01 |CRAN (R 4.4.1) | |testthat |3.3.1 |2025-11-25 |CRAN (R 4.4.3) | |textshaping |1.0.4 |2025-10-10 |CRAN (R 4.4.1) | @@ -214,6 +231,7 @@ |tzdb |0.5.0 |2025-03-15 |CRAN (R 4.4.1) | |usethis |3.2.1 |2025-09-06 |CRAN (R 4.4.1) | |uuid |1.2-1 |2024-07-29 |CRAN (R 4.4.1) | +|V8 |8.0.1 |2025-10-10 |CRAN (R 4.4.1) | |vctrs |0.6.5 |2023-12-01 |CRAN (R 4.4.0) | |viridis |0.6.5 |2024-01-29 |CRAN (R 4.4.0) | |viridisLite |0.4.2 |2023-05-02 |CRAN (R 4.4.1) | diff --git a/app_docker/Dockerfile b/app_docker/Dockerfile index e81d0317..c4564945 100644 --- a/app_docker/Dockerfile +++ b/app_docker/Dockerfile @@ -1,5 +1,5 @@ FROM rocker/geospatial:4.4.1 -RUN apt-get update -y && apt-get install -y cmake make libcurl4-openssl-dev libicu-dev libssl-dev pandoc zlib1g-dev libsecret-1-dev libxml2-dev libx11-dev libcairo2-dev libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev libjpeg-dev libpng-dev libtiff-dev libwebp-dev libfftw3-dev && rm -rf /var/lib/apt/lists/* +RUN apt-get update -y && apt-get install -y cmake make libcurl4-openssl-dev libicu-dev libssl-dev pandoc zlib1g-dev libsecret-1-dev libxml2-dev libx11-dev libmagick++-dev gsfonts libjpeg-dev libpoppler-cpp-dev libcairo2-dev libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev libpng-dev libtiff-dev libwebp-dev libfftw3-dev && rm -rf /var/lib/apt/lists/* RUN mkdir -p /usr/local/lib/R/etc/ /usr/lib/R/etc/ RUN echo "options(renv.config.pak.enabled = FALSE, repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl', Ncpus = 4)" | tee /usr/local/lib/R/etc/Rprofile.site | tee /usr/lib/R/etc/Rprofile.site RUN R -e 'install.packages("remotes")' diff --git a/app_docker/app.R b/app_docker/app.R index ab879cf7..24fa4cf6 100644 --- a/app_docker/app.R +++ b/app_docker/app.R @@ -1,7 +1,7 @@ ######## -#### Current file: /var/folders/9l/xbc19wxx0g79jdd2sf_0v291mhwh7f/T//RtmpftDBtp/file7bf3239dee0a.R +#### Current file: /var/folders/9l/xbc19wxx0g79jdd2sf_0v291mhwh7f/T//RtmpaYL5kU/file9c7175d0a25d.R ######## i18n_path <- here::here("translations") @@ -63,7 +63,7 @@ i18n$set_translation_language("en") #### Current file: /Users/au301842/FreesearchR/R//app_version.R ######## -app_version <- function()'25.12.5' +app_version <- function()'25.12.6' ######## @@ -453,9 +453,9 @@ create_column_ui <- function(id) { htmltools::tagList( # datamods:::html_dependency_datamods(), # html_dependency_FreesearchR(), - shiny::tags$head( - shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") - ), + shiny::tags$head( + shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") + ), fluidRow( column( width = 6, @@ -611,35 +611,44 @@ create_column_server <- function(id, #' #' @rdname create-column # @importFrom methods getGroupMembers -list_allowed_operations <- function() { - c( - "(", "c", +allowed_operations <- function() { + list( + "Misc" = c("(", "c",":","~"), # getGroupMembers("Arith"), - c("+", "-", "*", "^", "%%", "%/%", "/"), + "Arithmetics" = c("+", "-", "*", "^", "%%", "%/%", "/"), # getGroupMembers("Compare"), - c("==", ">", "<", "!=", "<=", ">="), + "Compare" = c("==", ">", "<", "!=", "<=", ">="), # getGroupMembers("Logic"), - c("&", "|"), + "Logic" = c("&", "|", "is.na", "ifelse", "any", "all"), # getGroupMembers("Math"), - c( + "Math" = c( "abs", "sign", "sqrt", "ceiling", "floor", "trunc", "cummax", "cummin", "cumprod", "cumsum", "exp", "expm1", "log", "log10", "log2", "log1p", "cos", "cosh", "sin", "sinh", "tan", "tanh", "acos", "acosh", "asin", "asinh", "atan", "atanh", "cospi", "sinpi", - "tanpi", "gamma", "lgamma", "digamma", "trigamma" + "tanpi", "gamma", "lgamma", "digamma", "trigamma", "round", "signif" ), # getGroupMembers("Math2"), - c("round", "signif"), + # c("round", "signif"), # getGroupMembers("Summary"), - c("max", "min", "range", "prod", "sum", "any", "all"), - "pmin", "pmax", "mean", - "paste", "paste0", "substr", "nchar", "trimws", - "gsub", "sub", "grepl", "ifelse", "length", - "as.numeric", "as.character", "as.integer", "as.Date", "as.POSIXct", - "as.factor", "factor" + "Summary" = c( + "max", "min", "range", "prod", "sum", "length", + "pmin", "pmax", "mean" + ), + "Text" = c( + "paste", "paste0", "substr", "nchar", "trimws", + "gsub", "sub", "grepl" + ), + "Class" = c( + "as.numeric", "as.character", "as.integer", "as.Date", "as.POSIXct", + "as.factor", "factor" + ) ) } +list_allowed_operations <- function(data=allowed_operations()) { + Reduce(c,data) +} #' @inheritParams shiny::modalDialog @@ -4442,7 +4451,7 @@ data_types <- function() { #### Current file: /Users/au301842/FreesearchR/R//hosted_version.R ######## -hosted_version <- function()'v25.12.5-251211' +hosted_version <- function()'v25.12.6-251212' ######## @@ -5552,7 +5561,7 @@ data_missings_ui <- function(id, ...) { bslib::accordion_panel( value = "acc_pan_mis", title = "Settings", - icon = bsicons::bs_icon("x-circle"), + icon = bsicons::bs_icon("gear"), shiny::uiOutput(ns("missings_method")), shiny::uiOutput(ns("missings_var")), shiny::helpText(i18n$t("Evaluate missingness by either comparing missing values across variables (optionally grouped by af categorical or dichotomous variable) or compare variables grouped by the missing status (missing or not) of an outcome variable. If there is a significant difference i the missingness, this may cause a bias in you data and should be considered carefully interpreting the data and analyses as data may not be missing at random.")), @@ -5564,6 +5573,16 @@ data_missings_ui <- function(id, ...) { icon = shiny::icon("calculator"), disabled = FALSE ) + ), + do.call( + bslib::accordion_panel, + c( + list( + title = "Download", + icon = bsicons::bs_icon("file-earmark-arrow-down") + ), + table_download_ui(id = ns("tbl_dwn"), title = NULL) + ) ) ) ), @@ -5666,10 +5685,10 @@ data_missings_server <- function(id, tryCatch( { shiny::withProgress(message = i18n$t("Calculating. Hold tight for a moment.."), { - out <- do.call( - compare_missings, - modifyList(parameters, list(data = df_tbl)) - ) + out <- do.call( + compare_missings, + modifyList(parameters, list(data = df_tbl)) + ) }) }, error = function(err) { @@ -5737,6 +5756,13 @@ data_missings_server <- function(id, } ) + + table_download_server( + id = "tbl_dwn", + data = shiny::reactive(rv$table), + file_name = "missings_table" + ) + return(shiny::reactive(rv$table)) } ) @@ -5751,7 +5777,8 @@ missing_demo_app <- function() { title = i18n$t("Missings"), icon = bsicons::bs_icon("x-circle") ), - data_missings_ui(id = "data") + data_missings_ui(id = "data"), + gt::gt_output("table_p") ) ) server <- function(input, output, session) { @@ -5759,7 +5786,15 @@ missing_demo_app <- function() { data_demo[sample(1:32, 10), "cyl"] <- NA data_demo[sample(1:32, 8), "vs"] <- NA - data_missings_server(id = "data", data = data_demo) + rv <- shiny::reactiveValues( + table = NULL + ) + + rv$table <- data_missings_server(id = "data", data = data_demo) + + output$table_p <- gt::render_gt({ + rv$table + }) # visual_summary_server(id = "visual", data = data_demo) @@ -6760,12 +6795,10 @@ plot_download_server <- function(id, shiny::moduleServer( id = id, module = function(input, output, session) { - # ns <- session$ns - - - output$download_plot <- shiny::downloadHandler( - filename = paste0(file_name, ".", input$plot_type), + filename = function() { + paste0(file_name, ".", input$plot_type) + }, content = function(file) { shiny::withProgress(message = "Saving the plot. Hold on for a moment..", { ggplot2::ggsave( @@ -6774,7 +6807,8 @@ plot_download_server <- function(id, width = input$plot_width, height = input$plot_height, dpi = 300, - units = "mm", scale = 2 + units = "mm", + scale = 2 ) }) } @@ -6784,6 +6818,60 @@ plot_download_server <- function(id, } +plot_download_demo_app <- function() { + + ui <- bslib::page_fillable( + title = "Plot Download Demo", + bslib::layout_sidebar( + sidebar = bslib::sidebar( + title = "Download Settings", + plot_download_ui(id = "plot_dwn") + ), + bslib::card( + bslib::card_header("Sample Plot"), + shiny::plotOutput("demo_plot", height = "500px") + ) + ) + ) + + server <- function(input, output, session) { + + # Create a sample ggplot + sample_plot <- ggplot2::ggplot(mtcars, ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) + + ggplot2::geom_point(size = 3) + + ggplot2::geom_smooth(method = "lm", se = TRUE) + + ggplot2::labs( + title = "Car Weight vs MPG", + x = "Weight (1000 lbs)", + y = "Miles per Gallon", + color = "Cylinders" + ) + + ggplot2::theme_minimal() + + ggplot2::theme( + plot.title = ggplot2::element_text(size = 16, face = "bold"), + legend.position = "bottom" + ) + + # Display the plot + output$demo_plot <- shiny::renderPlot({ + sample_plot + }) + + # Connect to download module + plot_download_server( + id = "plot_dwn", + data = sample_plot, + file_name = "mtcars_plot" + ) + } + + shiny::shinyApp(ui, server) +} + +# Run the demo +# plot_download_demo_app() + + ######## #### Current file: /Users/au301842/FreesearchR/R//redcap_read_shiny_module.R ######## @@ -9750,6 +9838,124 @@ html_code_wrap <- function(string, lang = "r") { } +######## +#### Current file: /Users/au301842/FreesearchR/R//table-download-module.R +######## + +table_download_ui <- function(id, title = "Table", ...) { + ns <- shiny::NS(id) + shiny::tagList( + shiny::h4(title), + shiny::helpText(i18n$t("Choose your favourite output file format for further work, and download, when the analyses are done.")), + shiny::br(), + shiny::br(), + shiny::selectInput( + inputId = ns("output_format"), + label = "Output format", + selected = NULL, + choices = list( + "MS Word" = "docx", + "Open document format" = "rtf" + ) + ), + shiny::br(), + shiny::uiOutput(ns("download_button_container")), + # shiny::downloadButton( + # outputId = ns("act_table"), + # label = "Download table", + # icon = shiny::icon("download") + # ), + shiny::br() + ) +} + +table_download_server <- function(id, data, file_name = "table", ...) { + shiny::moduleServer( + id = id, + module = function(input, output, session) { + ns <- session$ns + + output$download_button_container <- shiny::renderUI({ + # Check if data exists and is valid + if (!is.null(data()) && (inherits(data(), "gt_tbl") || inherits(data(), "gtsummary"))) { + shiny::downloadButton( + outputId = ns("act_table"), + label = i18n$t("Download table"), + icon = shiny::icon("download") + ) + } else { + # Return NULL to show nothing + NULL + } + }) + + + output$act_table <- shiny::downloadHandler( + filename = function() { + paste0("report.", input$output_format) + }, + content = function(file) { + shiny::req(data()) + type <- input$output_format + table <- data() + + shiny::withProgress(message = i18n$t("Generating the report. Hold on for a moment.."), { + tryCatch( + { + # browser() + if (inherits(table, "gtsummary")) { + table <- gtsummary::as_gt(table) + } + out <- gt::gtsave( + data = table, + filename = file # Save to the file path provided by downloadHandler + ) + if (type == "docx") { + out |> doconv::docx_update() + } else { + out + } + }, + error = function(err) { + shiny::showNotification(paste0(i18n$t("Error: "), err), type = "error") + } + ) + }) + } + ) + } + ) +} + + +# In your UI +table_download_demo <- function() { + ui <- fluidPage( + table_download_ui(id = "my_table", title = "Download Results") + ) + + # In your server + server <- function(input, output, session) { + # Your data as a reactive + my_table_data <- reactive({ + # This should return a gt or gtsummary table + mtcars |> + gt::gt() |> + gt::tab_header("My Table") + }) + + # Call the module server - THIS IS CRITICAL + table_download_server( + id = "my_table", # Must match the UI id + data = my_table_data # Pass the reactive (without parentheses) + ) + } + shiny::shinyApp(ui, server) +} + +# table_download_demo() + + ######## #### Current file: /Users/au301842/FreesearchR/R//theme.R ######## @@ -13900,7 +14106,7 @@ server <- function(input, output, session) { shiny::withProgress(message = i18n$t("Generating the report. Hold on for a moment.."), { tryCatch( { - rv$list |> + out <- rv$list |> write_rmd( params.args = list( regression.p = rv$list$regression$input$add_regression_p @@ -13908,6 +14114,14 @@ server <- function(input, output, session) { output_format = format, input = file.path(getwd(), "www/report.rmd") ) + + if (type == "docx") { + ## This handles the the following MS Word warning: + ## >> "This document contains fields that may refer to other files." + out |> doconv::docx_update() + } else { + out + } }, error = function(err) { showNotification(paste0(i18n$t("We encountered the following error creating your report: "), err), type = "err") diff --git a/app_docker/renv.lock b/app_docker/renv.lock index 6841ab5e..7d0e3eb6 100644 --- a/app_docker/renv.lock +++ b/app_docker/renv.lock @@ -2556,6 +2556,39 @@ "Maintainer": "Folashade Daniel ", "Repository": "CRAN" }, + "doconv": { + "Package": "doconv", + "Version": "0.3.3", + "Source": "Repository", + "Type": "Package", + "Title": "Document Conversion to 'PDF' or 'PNG'", + "Authors@R": "c( person(\"David\", \"Gohel\", role = c(\"aut\", \"cre\"), email = \"david.gohel@ardata.fr\"), person(given = \"ArData\", role = \"cph\"), person(\"David\", \"Hajage\", role = \"ctb\", comment = \"initial powershell code\") )", + "Description": "It provides the ability to generate images from documents of different types. Three main features are provided: functions for generating document thumbnails, functions for performing visual tests of documents and a function for updating fields and table of contents of a 'Microsoft Word' or 'RTF' document. In order to work, 'LibreOffice' must be installed on the machine and or 'Microsoft Word'. If the latter is available, it can be used to produce PDF documents or images identical to the originals; otherwise, 'LibreOffice' is used and the rendering can be sometimes different from the original documents.", + "License": "MIT + file LICENSE", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "Imports": [ + "magick", + "pdftools", + "locatexec", + "processx", + "tools" + ], + "Depends": [ + "R (>= 4.0.0)" + ], + "Suggests": [ + "tinytest", + "testthat", + "webshot2" + ], + "BugReports": "https://github.com/ardata-fr/doconv/issues", + "SystemRequirements": "LibreOffice, Microsoft Word", + "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], ArData [cph], David Hajage [ctb] (initial powershell code)", + "Maintainer": "David Gohel ", + "Repository": "CRAN" + }, "downlit": { "Package": "downlit", "Version": "0.4.5", @@ -5307,6 +5340,26 @@ "Maintainer": "Achim Zeileis ", "Repository": "CRAN" }, + "locatexec": { + "Package": "locatexec", + "Version": "0.1.1", + "Source": "Repository", + "Type": "Package", + "Title": "Detection and Localization of Executable Files", + "Authors@R": "c( person(\"David\", \"Gohel\", role = c(\"aut\", \"cre\"), email = \"david.gohel@ardata.fr\"), person(given = \"ArData\", role = \"cph\") )", + "Description": "A set of functions to locate some programs available on the user machine. The package provides functions to locate 'Node.js', 'npm', 'LibreOffice', 'Microsoft Word', 'Microsoft PowerPoint', 'Microsoft Excel', 'Python', 'pip', 'Mozilla Firefox' and 'Google Chrome'. User can test the availability of a program with eventually a version and call it with function system2() or system(). This allows the use of a single function to retrieve the path to a program regardless of the operating system and its configuration.", + "License": "MIT + file LICENSE", + "Encoding": "UTF-8", + "RoxygenNote": "7.1.1", + "Imports": [ + "utils" + ], + "BugReports": "https://github.com/ardata-fr/locatexec/issues", + "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], ArData [cph]", + "Maintainer": "David Gohel ", + "Repository": "CRAN" + }, "lubridate": { "Package": "lubridate", "Version": "1.9.4", @@ -5353,6 +5406,54 @@ "Author": "Vitalie Spinu [aut, cre], Garrett Grolemund [aut], Hadley Wickham [aut], Davis Vaughan [ctb], Ian Lyttle [ctb], Imanuel Costigan [ctb], Jason Law [ctb], Doug Mitarotonda [ctb], Joseph Larmarange [ctb], Jonathan Boiser [ctb], Chel Hee Lee [ctb]", "Repository": "CRAN" }, + "magick": { + "Package": "magick", + "Version": "2.9.0", + "Source": "Repository", + "Type": "Package", + "Title": "Advanced Graphics and Image-Processing in R", + "Authors@R": "person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\"))", + "Description": "Bindings to 'ImageMagick': the most comprehensive open-source image processing library available. Supports many common formats (png, jpeg, tiff, pdf, etc) and manipulations (rotate, scale, crop, trim, flip, blur, etc). All operations are vectorized via the Magick++ STL meaning they operate either on a single frame or a series of frames for working with layers, collages, or animation. In RStudio images are automatically previewed when printed to the console, resulting in an interactive editing environment. Also includes a graphics device for creating drawing onto images using pixel coordinates.", + "License": "MIT + file LICENSE", + "URL": "https://docs.ropensci.org/magick/ https://ropensci.r-universe.dev/magick", + "BugReports": "https://github.com/ropensci/magick/issues", + "SystemRequirements": "ImageMagick++: ImageMagick-c++-devel (rpm) or libmagick++-dev (deb)", + "VignetteBuilder": "knitr", + "Depends": [ + "R (>= 4.1.0)" + ], + "Imports": [ + "Rcpp (>= 0.12.12)", + "magrittr", + "curl" + ], + "LinkingTo": [ + "Rcpp" + ], + "Suggests": [ + "av", + "spelling", + "jsonlite", + "methods", + "knitr", + "rmarkdown", + "rsvg", + "webp", + "pdftools", + "ggplot2", + "gapminder", + "IRdisplay", + "tesseract", + "gifski" + ], + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "Language": "en-US", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: )", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "magrittr": { "Package": "magrittr", "Version": "2.0.4", @@ -6221,6 +6322,38 @@ "NeedsCompilation": "yes", "Repository": "CRAN" }, + "pdftools": { + "Package": "pdftools", + "Version": "3.6.0", + "Source": "Repository", + "Type": "Package", + "Title": "Text Extraction, Rendering and Converting of PDF Documents", + "Authors@R": "person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\"))", + "Description": "Utilities based on 'libpoppler' for extracting text, fonts, attachments and metadata from a PDF file. Also supports high quality rendering of PDF documents into PNG, JPEG, TIFF format, or into raw bitmap vectors for further processing in R.", + "License": "MIT + file LICENSE", + "URL": "https://ropensci.r-universe.dev/pdftools, https://docs.ropensci.org/pdftools/", + "BugReports": "https://github.com/ropensci/pdftools/issues", + "SystemRequirements": "Poppler C++ API: libpoppler-cpp-dev (deb) or poppler-cpp-devel (rpm), and poppler-data (rpm/deb) package.", + "Encoding": "UTF-8", + "Imports": [ + "Rcpp (>= 0.12.12)", + "qpdf" + ], + "LinkingTo": [ + "Rcpp" + ], + "Suggests": [ + "png", + "webp", + "tesseract", + "testthat" + ], + "RoxygenNote": "7.3.2", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: )", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "performance": { "Package": "performance", "Version": "0.15.3", @@ -6936,6 +7069,36 @@ "Author": "Matteo Fasiolo [aut, cre], Ben Griffiths [aut], Simon N. Wood [ctb], Margaux Zaffran [ctb], Yannig Goude [ctb], Raphael Nedellec [ctb]", "Repository": "CRAN" }, + "qpdf": { + "Package": "qpdf", + "Version": "1.4.1", + "Source": "Repository", + "Type": "Package", + "Title": "Split, Combine and Compress PDF Files", + "Authors@R": "c(person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Ben\", \"Raymond\", role = \"ctb\"), person(\"Jay Berkenbilt\", role = \"cph\", comment = \"Author of libqpdf\"))", + "Description": "Content-preserving transformations transformations of PDF files such as split, combine, and compress. This package interfaces directly to the 'qpdf' C++ library and does not require any command line utilities. Note that 'qpdf' does not read actual content from PDF files: to extract text and data you need the 'pdftools' package.", + "License": "Apache License 2.0", + "URL": "https://docs.ropensci.org/qpdf/ https://ropensci.r-universe.dev/qpdf", + "BugReports": "https://github.com/ropensci/qpdf/issues", + "Encoding": "UTF-8", + "Imports": [ + "Rcpp", + "askpass", + "curl" + ], + "LinkingTo": [ + "Rcpp" + ], + "RoxygenNote": "7.2.1", + "Suggests": [ + "testthat" + ], + "SystemRequirements": "libjpeg", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: ), Ben Raymond [ctb], Jay Berkenbilt [cph] (Author of libqpdf)", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "qqconf": { "Package": "qqconf", "Version": "1.3.2", diff --git a/app_docker/translations/translation_da.csv b/app_docker/translations/translation_da.csv index a30dba70..945ea908 100644 --- a/app_docker/translations/translation_da.csv +++ b/app_docker/translations/translation_da.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/app_docker/translations/translation_de.csv b/app_docker/translations/translation_de.csv index cb9bed43..5c4e9162 100644 --- a/app_docker/translations/translation_de.csv +++ b/app_docker/translations/translation_de.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/app_docker/translations/translation_sv.csv b/app_docker/translations/translation_sv.csv index 7883585e..5bf08438 100644 --- a/app_docker/translations/translation_sv.csv +++ b/app_docker/translations/translation_sv.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/app_docker/translations/translation_sw.csv b/app_docker/translations/translation_sw.csv index f1e8723a..2fe4651c 100644 --- a/app_docker/translations/translation_sw.csv +++ b/app_docker/translations/translation_sw.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/inst/apps/FreesearchR/app.R b/inst/apps/FreesearchR/app.R index ca34345d..62c12b77 100644 --- a/inst/apps/FreesearchR/app.R +++ b/inst/apps/FreesearchR/app.R @@ -1,7 +1,7 @@ ######## -#### Current file: /var/folders/9l/xbc19wxx0g79jdd2sf_0v291mhwh7f/T//RtmpftDBtp/file7bf313edd9e8.R +#### Current file: /var/folders/9l/xbc19wxx0g79jdd2sf_0v291mhwh7f/T//RtmpaYL5kU/file9c716ca74d18.R ######## i18n_path <- system.file("translations", package = "FreesearchR") @@ -63,7 +63,7 @@ i18n$set_translation_language("en") #### Current file: /Users/au301842/FreesearchR/R//app_version.R ######## -app_version <- function()'25.12.5' +app_version <- function()'25.12.6' ######## @@ -453,9 +453,9 @@ create_column_ui <- function(id) { htmltools::tagList( # datamods:::html_dependency_datamods(), # html_dependency_FreesearchR(), - shiny::tags$head( - shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") - ), + shiny::tags$head( + shiny::tags$link(rel = "stylesheet", type = "text/css", href = "FreesearchR/inst/assets/css/FreesearchR.css") + ), fluidRow( column( width = 6, @@ -611,35 +611,44 @@ create_column_server <- function(id, #' #' @rdname create-column # @importFrom methods getGroupMembers -list_allowed_operations <- function() { - c( - "(", "c", +allowed_operations <- function() { + list( + "Misc" = c("(", "c",":","~"), # getGroupMembers("Arith"), - c("+", "-", "*", "^", "%%", "%/%", "/"), + "Arithmetics" = c("+", "-", "*", "^", "%%", "%/%", "/"), # getGroupMembers("Compare"), - c("==", ">", "<", "!=", "<=", ">="), + "Compare" = c("==", ">", "<", "!=", "<=", ">="), # getGroupMembers("Logic"), - c("&", "|"), + "Logic" = c("&", "|", "is.na", "ifelse", "any", "all"), # getGroupMembers("Math"), - c( + "Math" = c( "abs", "sign", "sqrt", "ceiling", "floor", "trunc", "cummax", "cummin", "cumprod", "cumsum", "exp", "expm1", "log", "log10", "log2", "log1p", "cos", "cosh", "sin", "sinh", "tan", "tanh", "acos", "acosh", "asin", "asinh", "atan", "atanh", "cospi", "sinpi", - "tanpi", "gamma", "lgamma", "digamma", "trigamma" + "tanpi", "gamma", "lgamma", "digamma", "trigamma", "round", "signif" ), # getGroupMembers("Math2"), - c("round", "signif"), + # c("round", "signif"), # getGroupMembers("Summary"), - c("max", "min", "range", "prod", "sum", "any", "all"), - "pmin", "pmax", "mean", - "paste", "paste0", "substr", "nchar", "trimws", - "gsub", "sub", "grepl", "ifelse", "length", - "as.numeric", "as.character", "as.integer", "as.Date", "as.POSIXct", - "as.factor", "factor" + "Summary" = c( + "max", "min", "range", "prod", "sum", "length", + "pmin", "pmax", "mean" + ), + "Text" = c( + "paste", "paste0", "substr", "nchar", "trimws", + "gsub", "sub", "grepl" + ), + "Class" = c( + "as.numeric", "as.character", "as.integer", "as.Date", "as.POSIXct", + "as.factor", "factor" + ) ) } +list_allowed_operations <- function(data=allowed_operations()) { + Reduce(c,data) +} #' @inheritParams shiny::modalDialog @@ -4442,7 +4451,7 @@ data_types <- function() { #### Current file: /Users/au301842/FreesearchR/R//hosted_version.R ######## -hosted_version <- function()'v25.12.5-251211' +hosted_version <- function()'v25.12.6-251212' ######## @@ -5552,7 +5561,7 @@ data_missings_ui <- function(id, ...) { bslib::accordion_panel( value = "acc_pan_mis", title = "Settings", - icon = bsicons::bs_icon("x-circle"), + icon = bsicons::bs_icon("gear"), shiny::uiOutput(ns("missings_method")), shiny::uiOutput(ns("missings_var")), shiny::helpText(i18n$t("Evaluate missingness by either comparing missing values across variables (optionally grouped by af categorical or dichotomous variable) or compare variables grouped by the missing status (missing or not) of an outcome variable. If there is a significant difference i the missingness, this may cause a bias in you data and should be considered carefully interpreting the data and analyses as data may not be missing at random.")), @@ -5564,6 +5573,16 @@ data_missings_ui <- function(id, ...) { icon = shiny::icon("calculator"), disabled = FALSE ) + ), + do.call( + bslib::accordion_panel, + c( + list( + title = "Download", + icon = bsicons::bs_icon("file-earmark-arrow-down") + ), + table_download_ui(id = ns("tbl_dwn"), title = NULL) + ) ) ) ), @@ -5666,10 +5685,10 @@ data_missings_server <- function(id, tryCatch( { shiny::withProgress(message = i18n$t("Calculating. Hold tight for a moment.."), { - out <- do.call( - compare_missings, - modifyList(parameters, list(data = df_tbl)) - ) + out <- do.call( + compare_missings, + modifyList(parameters, list(data = df_tbl)) + ) }) }, error = function(err) { @@ -5737,6 +5756,13 @@ data_missings_server <- function(id, } ) + + table_download_server( + id = "tbl_dwn", + data = shiny::reactive(rv$table), + file_name = "missings_table" + ) + return(shiny::reactive(rv$table)) } ) @@ -5751,7 +5777,8 @@ missing_demo_app <- function() { title = i18n$t("Missings"), icon = bsicons::bs_icon("x-circle") ), - data_missings_ui(id = "data") + data_missings_ui(id = "data"), + gt::gt_output("table_p") ) ) server <- function(input, output, session) { @@ -5759,7 +5786,15 @@ missing_demo_app <- function() { data_demo[sample(1:32, 10), "cyl"] <- NA data_demo[sample(1:32, 8), "vs"] <- NA - data_missings_server(id = "data", data = data_demo) + rv <- shiny::reactiveValues( + table = NULL + ) + + rv$table <- data_missings_server(id = "data", data = data_demo) + + output$table_p <- gt::render_gt({ + rv$table + }) # visual_summary_server(id = "visual", data = data_demo) @@ -6760,12 +6795,10 @@ plot_download_server <- function(id, shiny::moduleServer( id = id, module = function(input, output, session) { - # ns <- session$ns - - - output$download_plot <- shiny::downloadHandler( - filename = paste0(file_name, ".", input$plot_type), + filename = function() { + paste0(file_name, ".", input$plot_type) + }, content = function(file) { shiny::withProgress(message = "Saving the plot. Hold on for a moment..", { ggplot2::ggsave( @@ -6774,7 +6807,8 @@ plot_download_server <- function(id, width = input$plot_width, height = input$plot_height, dpi = 300, - units = "mm", scale = 2 + units = "mm", + scale = 2 ) }) } @@ -6784,6 +6818,60 @@ plot_download_server <- function(id, } +plot_download_demo_app <- function() { + + ui <- bslib::page_fillable( + title = "Plot Download Demo", + bslib::layout_sidebar( + sidebar = bslib::sidebar( + title = "Download Settings", + plot_download_ui(id = "plot_dwn") + ), + bslib::card( + bslib::card_header("Sample Plot"), + shiny::plotOutput("demo_plot", height = "500px") + ) + ) + ) + + server <- function(input, output, session) { + + # Create a sample ggplot + sample_plot <- ggplot2::ggplot(mtcars, ggplot2::aes(x = wt, y = mpg, color = factor(cyl))) + + ggplot2::geom_point(size = 3) + + ggplot2::geom_smooth(method = "lm", se = TRUE) + + ggplot2::labs( + title = "Car Weight vs MPG", + x = "Weight (1000 lbs)", + y = "Miles per Gallon", + color = "Cylinders" + ) + + ggplot2::theme_minimal() + + ggplot2::theme( + plot.title = ggplot2::element_text(size = 16, face = "bold"), + legend.position = "bottom" + ) + + # Display the plot + output$demo_plot <- shiny::renderPlot({ + sample_plot + }) + + # Connect to download module + plot_download_server( + id = "plot_dwn", + data = sample_plot, + file_name = "mtcars_plot" + ) + } + + shiny::shinyApp(ui, server) +} + +# Run the demo +# plot_download_demo_app() + + ######## #### Current file: /Users/au301842/FreesearchR/R//redcap_read_shiny_module.R ######## @@ -9750,6 +9838,124 @@ html_code_wrap <- function(string, lang = "r") { } +######## +#### Current file: /Users/au301842/FreesearchR/R//table-download-module.R +######## + +table_download_ui <- function(id, title = "Table", ...) { + ns <- shiny::NS(id) + shiny::tagList( + shiny::h4(title), + shiny::helpText(i18n$t("Choose your favourite output file format for further work, and download, when the analyses are done.")), + shiny::br(), + shiny::br(), + shiny::selectInput( + inputId = ns("output_format"), + label = "Output format", + selected = NULL, + choices = list( + "MS Word" = "docx", + "Open document format" = "rtf" + ) + ), + shiny::br(), + shiny::uiOutput(ns("download_button_container")), + # shiny::downloadButton( + # outputId = ns("act_table"), + # label = "Download table", + # icon = shiny::icon("download") + # ), + shiny::br() + ) +} + +table_download_server <- function(id, data, file_name = "table", ...) { + shiny::moduleServer( + id = id, + module = function(input, output, session) { + ns <- session$ns + + output$download_button_container <- shiny::renderUI({ + # Check if data exists and is valid + if (!is.null(data()) && (inherits(data(), "gt_tbl") || inherits(data(), "gtsummary"))) { + shiny::downloadButton( + outputId = ns("act_table"), + label = i18n$t("Download table"), + icon = shiny::icon("download") + ) + } else { + # Return NULL to show nothing + NULL + } + }) + + + output$act_table <- shiny::downloadHandler( + filename = function() { + paste0("report.", input$output_format) + }, + content = function(file) { + shiny::req(data()) + type <- input$output_format + table <- data() + + shiny::withProgress(message = i18n$t("Generating the report. Hold on for a moment.."), { + tryCatch( + { + # browser() + if (inherits(table, "gtsummary")) { + table <- gtsummary::as_gt(table) + } + out <- gt::gtsave( + data = table, + filename = file # Save to the file path provided by downloadHandler + ) + if (type == "docx") { + out |> doconv::docx_update() + } else { + out + } + }, + error = function(err) { + shiny::showNotification(paste0(i18n$t("Error: "), err), type = "error") + } + ) + }) + } + ) + } + ) +} + + +# In your UI +table_download_demo <- function() { + ui <- fluidPage( + table_download_ui(id = "my_table", title = "Download Results") + ) + + # In your server + server <- function(input, output, session) { + # Your data as a reactive + my_table_data <- reactive({ + # This should return a gt or gtsummary table + mtcars |> + gt::gt() |> + gt::tab_header("My Table") + }) + + # Call the module server - THIS IS CRITICAL + table_download_server( + id = "my_table", # Must match the UI id + data = my_table_data # Pass the reactive (without parentheses) + ) + } + shiny::shinyApp(ui, server) +} + +# table_download_demo() + + ######## #### Current file: /Users/au301842/FreesearchR/R//theme.R ######## @@ -13900,7 +14106,7 @@ server <- function(input, output, session) { shiny::withProgress(message = i18n$t("Generating the report. Hold on for a moment.."), { tryCatch( { - rv$list |> + out <- rv$list |> write_rmd( params.args = list( regression.p = rv$list$regression$input$add_regression_p @@ -13908,6 +14114,14 @@ server <- function(input, output, session) { output_format = format, input = file.path(getwd(), "www/report.rmd") ) + + if (type == "docx") { + ## This handles the the following MS Word warning: + ## >> "This document contains fields that may refer to other files." + out |> doconv::docx_update() + } else { + out + } }, error = function(err) { showNotification(paste0(i18n$t("We encountered the following error creating your report: "), err), type = "err") diff --git a/inst/translations/translation_da.csv b/inst/translations/translation_da.csv index a30dba70..945ea908 100644 --- a/inst/translations/translation_da.csv +++ b/inst/translations/translation_da.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/inst/translations/translation_de.csv b/inst/translations/translation_de.csv index cb9bed43..5c4e9162 100644 --- a/inst/translations/translation_de.csv +++ b/inst/translations/translation_de.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/inst/translations/translation_sv.csv b/inst/translations/translation_sv.csv index 7883585e..5bf08438 100644 --- a/inst/translations/translation_sv.csv +++ b/inst/translations/translation_sv.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/inst/translations/translation_sw.csv b/inst/translations/translation_sw.csv index f1e8723a..2fe4651c 100644 --- a/inst/translations/translation_sw.csv +++ b/inst/translations/translation_sw.csv @@ -307,3 +307,5 @@ "No outcome measure chosen","No outcome measure chosen" "There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}.","There is a significant difference in data missingness in {n_nonmcar} {ifelse(n_nonmcar==1,'variable','variables')} grouped by the selected outcome/grouping variable {outcome}." "Include group differences","Include group differences" +"Error:","Error:" +"Download table","Download table" diff --git a/man/create-column.Rd b/man/create-column.Rd index e522d9db..85c70757 100644 --- a/man/create-column.Rd +++ b/man/create-column.Rd @@ -4,7 +4,7 @@ \alias{create-column} \alias{create_column_ui} \alias{create_column_server} -\alias{list_allowed_operations} +\alias{allowed_operations} \alias{modal_create_column} \alias{winbox_create_column} \title{Create new column} @@ -17,7 +17,7 @@ create_column_server( allowed_operations = list_allowed_operations() ) -list_allowed_operations() +allowed_operations() modal_create_column( id, @@ -68,7 +68,7 @@ A \code{\link[shiny:reactive]{shiny::reactive()}} function returning the data. This module allow to enter an expression to create a new column in a \code{data.frame}. } \note{ -User can only use a subset of function: (, c, +, -, *, ^, \%\%, \%/\%, /, ==, >, <, !=, <=, >=, &, |, abs, sign, sqrt, ceiling, floor, trunc, cummax, cummin, cumprod, cumsum, exp, expm1, log, log10, log2, log1p, cos, cosh, sin, sinh, tan, tanh, acos, acosh, asin, asinh, atan, atanh, cospi, sinpi, tanpi, gamma, lgamma, digamma, trigamma, round, signif, max, min, range, prod, sum, any, all, pmin, pmax, mean, paste, paste0, substr, nchar, trimws, gsub, sub, grepl, ifelse, length, as.numeric, as.character, as.integer, as.Date, as.POSIXct, as.factor, factor. +User can only use a subset of function: (, c, :, ~, +, -, *, ^, \%\%, \%/\%, /, ==, >, <, !=, <=, >=, &, |, is.na, ifelse, any, all, abs, sign, sqrt, ceiling, floor, trunc, cummax, cummin, cumprod, cumsum, exp, expm1, log, log10, log2, log1p, cos, cosh, sin, sinh, tan, tanh, acos, acosh, asin, asinh, atan, atanh, cospi, sinpi, tanpi, gamma, lgamma, digamma, trigamma, round, signif, max, min, range, prod, sum, length, pmin, pmax, mean, paste, paste0, substr, nchar, trimws, gsub, sub, grepl, as.numeric, as.character, as.integer, as.Date, as.POSIXct, as.factor, factor. You can add more operations using the \code{allowed_operations} argument, for example if you want to allow to use package lubridate, you can do: \if{html}{\out{
}}\preformatted{c(list_allowed_operations(), getNamespaceExports("lubridate")) diff --git a/renv.lock b/renv.lock index 6841ab5e..7d0e3eb6 100644 --- a/renv.lock +++ b/renv.lock @@ -2556,6 +2556,39 @@ "Maintainer": "Folashade Daniel ", "Repository": "CRAN" }, + "doconv": { + "Package": "doconv", + "Version": "0.3.3", + "Source": "Repository", + "Type": "Package", + "Title": "Document Conversion to 'PDF' or 'PNG'", + "Authors@R": "c( person(\"David\", \"Gohel\", role = c(\"aut\", \"cre\"), email = \"david.gohel@ardata.fr\"), person(given = \"ArData\", role = \"cph\"), person(\"David\", \"Hajage\", role = \"ctb\", comment = \"initial powershell code\") )", + "Description": "It provides the ability to generate images from documents of different types. Three main features are provided: functions for generating document thumbnails, functions for performing visual tests of documents and a function for updating fields and table of contents of a 'Microsoft Word' or 'RTF' document. In order to work, 'LibreOffice' must be installed on the machine and or 'Microsoft Word'. If the latter is available, it can be used to produce PDF documents or images identical to the originals; otherwise, 'LibreOffice' is used and the rendering can be sometimes different from the original documents.", + "License": "MIT + file LICENSE", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "Imports": [ + "magick", + "pdftools", + "locatexec", + "processx", + "tools" + ], + "Depends": [ + "R (>= 4.0.0)" + ], + "Suggests": [ + "tinytest", + "testthat", + "webshot2" + ], + "BugReports": "https://github.com/ardata-fr/doconv/issues", + "SystemRequirements": "LibreOffice, Microsoft Word", + "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], ArData [cph], David Hajage [ctb] (initial powershell code)", + "Maintainer": "David Gohel ", + "Repository": "CRAN" + }, "downlit": { "Package": "downlit", "Version": "0.4.5", @@ -5307,6 +5340,26 @@ "Maintainer": "Achim Zeileis ", "Repository": "CRAN" }, + "locatexec": { + "Package": "locatexec", + "Version": "0.1.1", + "Source": "Repository", + "Type": "Package", + "Title": "Detection and Localization of Executable Files", + "Authors@R": "c( person(\"David\", \"Gohel\", role = c(\"aut\", \"cre\"), email = \"david.gohel@ardata.fr\"), person(given = \"ArData\", role = \"cph\") )", + "Description": "A set of functions to locate some programs available on the user machine. The package provides functions to locate 'Node.js', 'npm', 'LibreOffice', 'Microsoft Word', 'Microsoft PowerPoint', 'Microsoft Excel', 'Python', 'pip', 'Mozilla Firefox' and 'Google Chrome'. User can test the availability of a program with eventually a version and call it with function system2() or system(). This allows the use of a single function to retrieve the path to a program regardless of the operating system and its configuration.", + "License": "MIT + file LICENSE", + "Encoding": "UTF-8", + "RoxygenNote": "7.1.1", + "Imports": [ + "utils" + ], + "BugReports": "https://github.com/ardata-fr/locatexec/issues", + "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], ArData [cph]", + "Maintainer": "David Gohel ", + "Repository": "CRAN" + }, "lubridate": { "Package": "lubridate", "Version": "1.9.4", @@ -5353,6 +5406,54 @@ "Author": "Vitalie Spinu [aut, cre], Garrett Grolemund [aut], Hadley Wickham [aut], Davis Vaughan [ctb], Ian Lyttle [ctb], Imanuel Costigan [ctb], Jason Law [ctb], Doug Mitarotonda [ctb], Joseph Larmarange [ctb], Jonathan Boiser [ctb], Chel Hee Lee [ctb]", "Repository": "CRAN" }, + "magick": { + "Package": "magick", + "Version": "2.9.0", + "Source": "Repository", + "Type": "Package", + "Title": "Advanced Graphics and Image-Processing in R", + "Authors@R": "person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\"))", + "Description": "Bindings to 'ImageMagick': the most comprehensive open-source image processing library available. Supports many common formats (png, jpeg, tiff, pdf, etc) and manipulations (rotate, scale, crop, trim, flip, blur, etc). All operations are vectorized via the Magick++ STL meaning they operate either on a single frame or a series of frames for working with layers, collages, or animation. In RStudio images are automatically previewed when printed to the console, resulting in an interactive editing environment. Also includes a graphics device for creating drawing onto images using pixel coordinates.", + "License": "MIT + file LICENSE", + "URL": "https://docs.ropensci.org/magick/ https://ropensci.r-universe.dev/magick", + "BugReports": "https://github.com/ropensci/magick/issues", + "SystemRequirements": "ImageMagick++: ImageMagick-c++-devel (rpm) or libmagick++-dev (deb)", + "VignetteBuilder": "knitr", + "Depends": [ + "R (>= 4.1.0)" + ], + "Imports": [ + "Rcpp (>= 0.12.12)", + "magrittr", + "curl" + ], + "LinkingTo": [ + "Rcpp" + ], + "Suggests": [ + "av", + "spelling", + "jsonlite", + "methods", + "knitr", + "rmarkdown", + "rsvg", + "webp", + "pdftools", + "ggplot2", + "gapminder", + "IRdisplay", + "tesseract", + "gifski" + ], + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "Language": "en-US", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: )", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "magrittr": { "Package": "magrittr", "Version": "2.0.4", @@ -6221,6 +6322,38 @@ "NeedsCompilation": "yes", "Repository": "CRAN" }, + "pdftools": { + "Package": "pdftools", + "Version": "3.6.0", + "Source": "Repository", + "Type": "Package", + "Title": "Text Extraction, Rendering and Converting of PDF Documents", + "Authors@R": "person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\"))", + "Description": "Utilities based on 'libpoppler' for extracting text, fonts, attachments and metadata from a PDF file. Also supports high quality rendering of PDF documents into PNG, JPEG, TIFF format, or into raw bitmap vectors for further processing in R.", + "License": "MIT + file LICENSE", + "URL": "https://ropensci.r-universe.dev/pdftools, https://docs.ropensci.org/pdftools/", + "BugReports": "https://github.com/ropensci/pdftools/issues", + "SystemRequirements": "Poppler C++ API: libpoppler-cpp-dev (deb) or poppler-cpp-devel (rpm), and poppler-data (rpm/deb) package.", + "Encoding": "UTF-8", + "Imports": [ + "Rcpp (>= 0.12.12)", + "qpdf" + ], + "LinkingTo": [ + "Rcpp" + ], + "Suggests": [ + "png", + "webp", + "tesseract", + "testthat" + ], + "RoxygenNote": "7.3.2", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: )", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "performance": { "Package": "performance", "Version": "0.15.3", @@ -6936,6 +7069,36 @@ "Author": "Matteo Fasiolo [aut, cre], Ben Griffiths [aut], Simon N. Wood [ctb], Margaux Zaffran [ctb], Yannig Goude [ctb], Raphael Nedellec [ctb]", "Repository": "CRAN" }, + "qpdf": { + "Package": "qpdf", + "Version": "1.4.1", + "Source": "Repository", + "Type": "Package", + "Title": "Split, Combine and Compress PDF Files", + "Authors@R": "c(person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Ben\", \"Raymond\", role = \"ctb\"), person(\"Jay Berkenbilt\", role = \"cph\", comment = \"Author of libqpdf\"))", + "Description": "Content-preserving transformations transformations of PDF files such as split, combine, and compress. This package interfaces directly to the 'qpdf' C++ library and does not require any command line utilities. Note that 'qpdf' does not read actual content from PDF files: to extract text and data you need the 'pdftools' package.", + "License": "Apache License 2.0", + "URL": "https://docs.ropensci.org/qpdf/ https://ropensci.r-universe.dev/qpdf", + "BugReports": "https://github.com/ropensci/qpdf/issues", + "Encoding": "UTF-8", + "Imports": [ + "Rcpp", + "askpass", + "curl" + ], + "LinkingTo": [ + "Rcpp" + ], + "RoxygenNote": "7.2.1", + "Suggests": [ + "testthat" + ], + "SystemRequirements": "libjpeg", + "NeedsCompilation": "yes", + "Author": "Jeroen Ooms [aut, cre] (ORCID: ), Ben Raymond [ctb], Jay Berkenbilt [cph] (Author of libqpdf)", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, "qqconf": { "Package": "qqconf", "Version": "1.3.2",