From 747670bb576723fc459ea65dfacc5ff23790de26 Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Fri, 31 Oct 2025 11:39:44 +0100 Subject: [PATCH] rendering --- DESCRIPTION | 1 + NAMESPACE | 4 ++ NEWS.md | 6 +- R/hosted_version.R | 2 +- R/separate_string.R | 123 ++++++++++++++++++++++++++++++++-------- R/sysdata.rda | Bin 2806 -> 2840 bytes SESSION.md | 8 ++- man/compare_missings.Rd | 2 +- man/split-string.Rd | 44 ++++++++++++++ 9 files changed, 161 insertions(+), 29 deletions(-) create mode 100644 man/split-string.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 1c3b44e8..bb7e367e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -112,6 +112,7 @@ Collate: 'launch_FreesearchR.R' 'missings-module.R' 'plot-download-module.R' + 'plot_bar.R' 'plot_box.R' 'plot_euler.R' 'plot_hbar.R' diff --git a/NAMESPACE b/NAMESPACE index 1544994a..127b112c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -100,12 +100,14 @@ export(missings_apex_plot) export(missings_validate) export(modal_create_column) export(modal_cut_variable) +export(modal_string_split) export(modal_update_factor) export(modal_visual_summary) export(modify_qmd) export(names2val) export(overview_vars) export(pipe_string) +export(plot_bar_single) export(plot_box) export(plot_box_single) export(plot_euler) @@ -137,6 +139,8 @@ export(show_data) export(simple_snake) export(sort_by) export(specify_qmd_format) +export(string_split_server) +export(string_split_ui) export(subset_types) export(supported_functions) export(supported_plots) diff --git a/NEWS.md b/NEWS.md index 5658b0c6..1345a963 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,10 @@ # FreesearchR 25.10.5 -*NEW* New character/text split function available. A selection of delimiters are recognised and selectable. Function only available if splittable variables are present. This was the last big function to implement after workshops at Jitimai in Zanzibar. +*NEW* New character/text split function available. A selection of delimiters are recognised and selectable. Function only available if splittable variables are present. + +*NEW* Distribution plotting for factors have been much improved including two new bar plot styles and removing options better suited for continuous data. + +These were the last major functions to be implemented after workshops at Jitimai in Zanzibar City, Zanzibar during October 2025. # FreesearchR 25.10.4 diff --git a/R/hosted_version.R b/R/hosted_version.R index b917069a..125f33e1 100644 --- a/R/hosted_version.R +++ b/R/hosted_version.R @@ -1 +1 @@ -hosted_version <- function()'v25.10.5-251030' +hosted_version <- function()'v25.10.5-251031' diff --git a/R/separate_string.R b/R/separate_string.R index 38a243bb..0aa64e6c 100644 --- a/R/separate_string.R +++ b/R/separate_string.R @@ -1,3 +1,12 @@ +#' String split module based on tidyr::separate_ +#' +#' @param id id +#' +#' @returns A shiny ui module +#' @export +#' +#' @name split-string +#' string_split_ui <- function(id) { ns <- NS(id) tagList( @@ -26,17 +35,17 @@ string_split_ui <- function(id) { ), shiny::fluidRow( column( - width = 3, + width = 4, shiny::h4(i18n$t("Original data")), - shiny::tableOutput(outputId = ns("orig_data")) + toastui::datagridOutput2(outputId = ns("orig_data")) + # DT::DTOutput(outputId = ns("orig_data_3")) # This doesn't render... # toastui::datagridOutput2(outputId = ns("orig_data_2")) ), - column(width = 1), column( width = 8, shiny::h4(i18n$t("Preview of result")), - shiny::tableOutput(outputId = ns("new_data")) + toastui::datagridOutput2(outputId = ns("new_data")) ) ), actionButton( @@ -50,11 +59,18 @@ string_split_ui <- function(id) { +#' @param data_r reactive data +#' +#' @returns shiny module server +#' @export +#' +#' @name split-string +#' string_split_server <- function(id, data_r = reactive(NULL)) { moduleServer( id, function(input, output, session) { - rv <- reactiveValues(data = NULL, temp = NULL, out=NULL) + rv <- reactiveValues(data = NULL, target=NULL, temp = NULL, out=NULL) ns <- session$ns @@ -80,6 +96,8 @@ string_split_server <- function(id, data_r = reactive(NULL)) { }, logical(1)) vars_num <- names(vars_num)[vars_num] + req(length(vars_num)>0) + output$variable <- shiny::renderUI( columnSelectInput( inputId = ns("variable"), @@ -103,6 +121,7 @@ string_split_server <- function(id, data_r = reactive(NULL)) { req(input$variable) # browser() + req(input$variable %in% names(rv$data)) # req({ # any(apply(data_r(),2,is_splittable)) # }) @@ -180,36 +199,46 @@ string_split_server <- function(id, data_r = reactive(NULL)) { ## Toastui would not render the original data, so the solution was to go ## with native table rendering, which works, but doesn't please the eye - output$orig_data <- shiny::renderTable({ - req(data_r()) - req(input$variable) - data <- data_r() |> - dplyr::select(tidyselect::all_of(input$variable)) - # browser() - head(data, 10) - }) - - # output$orig_data_2 <- toastui::renderDatagrid2({ + # output$orig_data <- shiny::renderTable({ # req(data_r()) # req(input$variable) # data <- data_r() |> # dplyr::select(tidyselect::all_of(input$variable)) # # browser() - # toastui::datagrid(head(data, 10)) + # head(data, 10) # }) + output$orig_data <- toastui::renderDatagrid2({ + req(data_r()) + req(input$variable) + req(hasName(rv$data, input$variable)) - output$new_data <- shiny::renderTable({ + data <- data_r() |> + dplyr::select(tidyselect::all_of(input$variable)) |> + head(30) |> + dplyr::mutate(row=dplyr::row_number()) |> + dplyr::select(row,tidyselect::everything()) + # browser() + toastui::datagrid( + data = data, + rowHeight = 40, + colwidths = "guess", + theme = "default", + bodyHeight = "auto", + pagination = 10) + }) + + output$new_data <- toastui::renderDatagrid2({ shiny::req(rv$temp) data <- rv$temp - head(data, 10) - # toastui::datagrid( - # data = head(data, 100), - # colwidths = "guess", - # theme = "default", - # bodyHeight = "auto", pagination = 10 - # ) + toastui::datagrid( + data = head(data, 30), + rowHeight = 40, + colwidths = "guess", + theme = "default", + bodyHeight = "auto", pagination = 10 + ) }) data_split_r <- reactive({ @@ -256,6 +285,15 @@ string_split_server <- function(id, data_r = reactive(NULL)) { } +#' @param title Modal title +#' @param easyClose easyClose +#' @param size size +#' @param footer footer +#' +#' @returns shiny modal +#' @export +#' +#' @name split-string modal_string_split <- function(id, title = i18n$t("Split character string"), easyClose = TRUE, @@ -373,3 +411,40 @@ is_splittable <- function(data) { FALSE } } + +# mtcars |> simple_dt() +simple_dt <- function(data,...){ + headerCallbackRemoveHeaderFooter <- c( + "function(thead, data, start, end, display){", + " $('th', thead).css('display', 'none');", + "}" + ) + + DT::datatable( + data, + options = list( + dom = "t", + ordering = FALSE, + paging = FALSE, + searching = FALSE, + # headerCallback = DT::JS(headerCallbackRemoveHeaderFooter), + columnDefs = list( + list( + targets = 1, + render = DT::JS( + "function(data, type, row, meta) {", + "return type === 'display' && data.length > 10 ?", + "'' + data.substr(0, 10) + '...' : data;", + "}"))) + ), + selection = 'none', + callback = DT::JS( + "$('table.dataTable.no-footer').css('border-bottom', 'none');" + ), + class = 'row-border', + escape = FALSE, + rownames = FALSE, + # width = 500, + filter = "none" + ) +} diff --git a/R/sysdata.rda b/R/sysdata.rda index 874a0e2297416fdb7283f22b1d3cec161dda7ffb..d6694eef104dd8c498804324a18967f6806622ef 100644 GIT binary patch literal 2840 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 literal 2806 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 IYTy?GfTFY+Pyhe` diff --git a/SESSION.md b/SESSION.md index 97445267..756f93cd 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-10-30 | +|date |2025-10-31 | |rstudio |2025.05.0+496 Mariposa Orchid (desktop) | |pandoc |3.6.4 @ /opt/homebrew/bin/ (via rmarkdown) | |quarto |1.7.30 @ /usr/local/bin/quarto | -|FreesearchR |25.10.5.251030 | +|FreesearchR |25.10.5.251031 | -------------------------------------------------------------------------------- @@ -118,12 +118,15 @@ |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.2 |2025-04-08 |RSPM (R 4.4.0) | |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) | |lubridate |1.9.4 |2024-12-08 |CRAN (R 4.4.1) | |magrittr |2.0.3 |2022-03-30 |RSPM (R 4.4.0) | +|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 |RSPM (R 4.4.0) | |memoise |2.0.1 |2021-11-26 |CRAN (R 4.4.0) | @@ -225,6 +228,7 @@ |uuid |1.2-1 |2024-07-29 |CRAN (R 4.4.1) | |V8 |6.0.6 |2025-08-18 |CRAN (R 4.4.1) | |vctrs |0.6.5 |2023-12-01 |CRAN (R 4.4.0) | +|viridisLite |0.4.2 |2023-05-02 |CRAN (R 4.4.1) | |vroom |1.6.5 |2023-12-05 |CRAN (R 4.4.0) | |withr |3.0.2 |2024-10-28 |CRAN (R 4.4.1) | |writexl |1.5.4 |2025-04-15 |CRAN (R 4.4.1) | diff --git a/man/compare_missings.Rd b/man/compare_missings.Rd index 8950200c..d7c412d0 100644 --- a/man/compare_missings.Rd +++ b/man/compare_missings.Rd @@ -4,7 +4,7 @@ \alias{compare_missings} \title{Pairwise comparison of missings across covariables} \usage{ -compare_missings(data, by_var) +compare_missings(data, by_var, max_level = 20) } \arguments{ \item{data}{data frame} diff --git a/man/split-string.Rd b/man/split-string.Rd new file mode 100644 index 00000000..7bf65a68 --- /dev/null +++ b/man/split-string.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/separate_string.R +\name{split-string} +\alias{split-string} +\alias{string_split_ui} +\alias{string_split_server} +\alias{modal_string_split} +\title{String split module based on tidyr::separate_} +\usage{ +string_split_ui(id) + +string_split_server(id, data_r = reactive(NULL)) + +modal_string_split( + id, + title = i18n$t("Split character string"), + easyClose = TRUE, + size = "xl", + footer = NULL +) +} +\arguments{ +\item{id}{id} + +\item{data_r}{reactive data} + +\item{title}{Modal title} + +\item{easyClose}{easyClose} + +\item{size}{size} + +\item{footer}{footer} +} +\value{ +A shiny ui module + +shiny module server + +shiny modal +} +\description{ +String split module based on tidyr::separate_ +}