From 6663a16454164da60946876ec4561bcbc3e6d838 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 09:37:09 +0200 Subject: [PATCH 01/16] Add col_select param and calc number of stars --- R/columns.R | 7 ++++++- R/tabulator.R | 5 ++++- examples/data_url.R | 7 +++++++ man/set_formatter_star.Rd | 5 +++-- man/tabulator.Rd | 4 ++++ 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 examples/data_url.R diff --git a/R/columns.R b/R/columns.R index 8dfa8dd..66c08d7 100644 --- a/R/columns.R +++ b/R/columns.R @@ -193,9 +193,14 @@ set_formatter_link <- function( #' Star Rating Formatter #' @inheritParams set_formatter_html #' @param number_of_stars The maximum number of stars to be displayed. +#' If set to \code{NA}, the maximum value of the column is used. #' @example examples/formatters/formatter_star.R #' @export -set_formatter_star <- function(widget, column, number_of_stars, hoz_align = "center") { +set_formatter_star <- function(widget, column, number_of_stars = NA, hoz_align = "center") { + if (is.na(number_of_stars)) { + number_of_stars <- max(widget$x$data[column]) + } + col_update <- list( formatter = "star", formatterParams = list(stars = number_of_stars), diff --git a/R/tabulator.R b/R/tabulator.R index 9ef2613..92f91bd 100644 --- a/R/tabulator.R +++ b/R/tabulator.R @@ -8,6 +8,8 @@ #' @param sheetjs (bool): Whether to add sheetjs (\url{https://sheetjs.com/}) dependency, #' which is needed for xlsx downloads. #' @param theme (character): Theme to apply to the table. +#' @param col_select (character vector) Columns to select. +#' Passed to \code{\link[readr]{read_csv}} if \code{data} is a file name. #' @param width Width of the widget. #' @param height Height of the widget. #' @param element_id The unique ID of the widget. @@ -21,6 +23,7 @@ tabulator <- function( editable = FALSE, sheetjs = FALSE, theme = c("default", "midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui"), + col_select = NULL, width = NULL, height = NULL, element_id = NULL, @@ -28,7 +31,7 @@ tabulator <- function( if (is.null(options)) options <- list() if (is.character(data)) { - data <- readr::read_csv(data, show_col_types = FALSE) + data <- readr::read_csv(data, show_col_types = FALSE, col_select = !!col_select) } # TODO: Use Pipe, but then we need to set required R Version to > 4.1 diff --git a/examples/data_url.R b/examples/data_url.R new file mode 100644 index 0000000..9fbd693 --- /dev/null +++ b/examples/data_url.R @@ -0,0 +1,7 @@ +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +# tabulator(data_url) +tabulator(data_url, col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived")) |> + set_formatter_star("Pclass") |> + set_formatter_tick_cross("Survived") |> + set_formatter_progress("Fare", legend = TRUE, legend_align = "left") diff --git a/man/set_formatter_star.Rd b/man/set_formatter_star.Rd index a605529..638d32f 100644 --- a/man/set_formatter_star.Rd +++ b/man/set_formatter_star.Rd @@ -4,14 +4,15 @@ \alias{set_formatter_star} \title{Star Rating Formatter} \usage{ -set_formatter_star(widget, column, number_of_stars, hoz_align = "center") +set_formatter_star(widget, column, number_of_stars = NA, hoz_align = "center") } \arguments{ \item{widget}{(\code{\link{tabulator}}) A tabulator widget.} \item{column}{(character): The column the formatter is applied to.} -\item{number_of_stars}{The maximum number of stars to be displayed.} +\item{number_of_stars}{The maximum number of stars to be displayed. +If set to \code{NA}, the maximum value of the column is used.} \item{hoz_align}{(character): The horizontal alignment of the column.} } diff --git a/man/tabulator.Rd b/man/tabulator.Rd index b065b50..d292fba 100644 --- a/man/tabulator.Rd +++ b/man/tabulator.Rd @@ -11,6 +11,7 @@ tabulator( sheetjs = FALSE, theme = c("default", "midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui"), + col_select = NULL, width = NULL, height = NULL, element_id = NULL, @@ -30,6 +31,9 @@ which is needed for xlsx downloads.} \item{theme}{(character): Theme to apply to the table.} +\item{col_select}{(character vector) Columns to select. +Passed to \code{\link[readr]{read_csv}} if \code{data} is a file name.} + \item{width}{Width of the widget.} \item{height}{Height of the widget.} From fb9aaf9e3e3eb1edefa7520989c497e1f1980530 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 09:53:44 +0200 Subject: [PATCH 02/16] Update README --- DESCRIPTION | 3 ++- README.Rmd | 24 +++++++++++++++--------- README.md | 25 +++++++++++++++++-------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 34a5106..056afd7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,7 +9,8 @@ Authors@R: c( ) Maintainer: Stefan Kuethe Description: Provides R bindings for 'Tabulator JS' . - Makes it a breeze to create beautiful interactive tables. + Makes it a breeze to create highly customizable interactive tables in markdown documents + and Shiny applications. URL: https://github.com/eodaGmbH/rtabulator https://eodagmbh.github.io/rtabulator/ diff --git a/README.Rmd b/README.Rmd index b510347..453e196 100644 --- a/README.Rmd +++ b/README.Rmd @@ -17,22 +17,28 @@ knitr::opts_chunk$set( [![R-CMD-check](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml) +[![CRAN status](https://www.r-pkg.org/badges/version/rtabulator)](https://CRAN.R-project.org/package=rtabulator) +[![Tabulator](https://img.shields.io/badge/Tabulator-v6.2.5-blue.svg)](https://github.com/olifolkerd/tabulator/releases/tag/6.2.5) -The goal of rtabulator is to make it a breeze creating beautiful and reactive tables using -[Tabulator JS](https://tabulator.info/) +The goal of rtabulator is to make it a breeze creating beautiful and interactive tables in markdown documents and Shiny application using [Tabulator JS](https://tabulator.info/). ## Features -* Filters +* Filtering * Grouping -* Multiple column formatters (images, html, progress bar, ...) -* Multiple themes +* Editing +* Input validation +* History with undo and redo actions +* Pagination +* Layout +* Column formatters +* Column calculations * Multi column headers -* Spreadsheet mode supporting multiple sheets -* Cell editing supporting validation -* Downloads (json, csv, xlsx) -* Interactivity +* Packaged themes +* Spreadsheets supporting multiple sheets +* Download data +* Freeze data ## Installation diff --git a/README.md b/README.md index 83395c2..7906014 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,31 @@ [![R-CMD-check](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/eodaGmbH/rtabulator/actions/workflows/R-CMD-check.yaml) +[![CRAN +status](https://www.r-pkg.org/badges/version/rtabulator)](https://CRAN.R-project.org/package=rtabulator) +[![Tabulator](https://img.shields.io/badge/Tabulator-v6.2.5-blue.svg)](https://github.com/olifolkerd/tabulator/releases/tag/6.2.5) The goal of rtabulator is to make it a breeze creating beautiful and -reactive tables using [Tabulator JS](https://tabulator.info/) +interactive tables in markdown documents and Shiny application using +[Tabulator JS](https://tabulator.info/). ## Features -- Filters +- Filtering - Grouping -- Multiple column formatters (images, html, progress bar, …) -- Multiple themes +- Editing +- Input validation +- History with undo and redo actions +- Pagination +- Layout +- Column formatters +- Column calculations - Multi column headers -- Spreadsheet mode supporting multiple sheets -- Cell editing supporting validation -- Downloads (json, csv, xlsx) -- Interactivity +- Packaged themes +- Spreadsheets supporting multiple sheets +- Download data +- Freeze data ## Installation From 81c3bd674f18668cfec51727c7dcea147523de87 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 10:41:47 +0200 Subject: [PATCH 03/16] Add calculation func --- NAMESPACE | 1 + R/columns.R | 19 +++++++++++++++++++ examples/data_url.R | 11 +++++++++-- man/set_top_calc.Rd | 23 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 man/set_top_calc.Rd diff --git a/NAMESPACE b/NAMESPACE index ee40f28..6bb9ccf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,6 +22,7 @@ export(set_formatter_toggle_switch) export(set_formatter_traffic_light) export(set_header_filter) export(set_multi_column_header) +export(set_top_calc) export(tabulator) export(tabulatorContext) export(tabulatorOutput) diff --git a/R/columns.R b/R/columns.R index 66c08d7..79d7381 100644 --- a/R/columns.R +++ b/R/columns.R @@ -405,6 +405,25 @@ set_header_filter <- function(widget, columns = NULL) { return(widget) } +#' Add a calculation to a column +#' @inheritParams set_formatter_html +#' @param func (character): The calculation function to be applied. +#' @export +set_top_calc <- function( + widget, + column, + func = c("avg", "max", "min", "sum", "count", "unique"), + precision = 2) { + col_update <- list(topCalc = match.arg(func), topCalcParams = list(precision = precision)) + modify_col_def(widget, column, col_update) +} + +# #' @export +set_bottom_calc <- function(widget, column) { + +} + + # Generics modify_col_def <- function(widget, column, col_update) { diff --git a/examples/data_url.R b/examples/data_url.R index 9fbd693..d3c4181 100644 --- a/examples/data_url.R +++ b/examples/data_url.R @@ -1,7 +1,14 @@ data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" # tabulator(data_url) -tabulator(data_url, col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived")) |> +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), + pagination = T, + column_calcs = "both" +) |> set_formatter_star("Pclass") |> set_formatter_tick_cross("Survived") |> - set_formatter_progress("Fare", legend = TRUE, legend_align = "left") + set_formatter_progress("Fare", legend = TRUE, legend_align = "right", hoz_align = "right") |> + set_top_calc("Fare", func = "avg") |> + set_top_calc("Pclass", func = "unique") diff --git a/man/set_top_calc.Rd b/man/set_top_calc.Rd new file mode 100644 index 0000000..82caa2a --- /dev/null +++ b/man/set_top_calc.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_top_calc} +\alias{set_top_calc} +\title{Add a calculation to a column} +\usage{ +set_top_calc( + widget, + column, + func = c("avg", "max", "min", "sum", "count", "unique"), + precision = 2 +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the formatter is applied to.} + +\item{func}{(character): The calculation function to be applied.} +} +\description{ +Add a calculation to a column +} From 95c8ecbf05eb370802f05e981ad77c66eb97b4f7 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 12:10:34 +0200 Subject: [PATCH 04/16] Refactor calc func --- NAMESPACE | 2 +- R/columns.R | 21 +++++++++++---------- examples/data_url.R | 5 ++--- man/set_calculation.Rd | 40 ++++++++++++++++++++++++++++++++++++++++ man/set_top_calc.Rd | 23 ----------------------- 5 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 man/set_calculation.Rd delete mode 100644 man/set_top_calc.Rd diff --git a/NAMESPACE b/NAMESPACE index 6bb9ccf..d54b369 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,6 +6,7 @@ export(delete_selected_rows) export(list_to_data_frame) export(redo) export(renderTabulator) +export(set_calculation) export(set_column_editor) export(set_formatter_color) export(set_formatter_datetime) @@ -22,7 +23,6 @@ export(set_formatter_toggle_switch) export(set_formatter_traffic_light) export(set_header_filter) export(set_multi_column_header) -export(set_top_calc) export(tabulator) export(tabulatorContext) export(tabulatorOutput) diff --git a/R/columns.R b/R/columns.R index 79d7381..0013b4b 100644 --- a/R/columns.R +++ b/R/columns.R @@ -407,23 +407,24 @@ set_header_filter <- function(widget, columns = NULL) { #' Add a calculation to a column #' @inheritParams set_formatter_html -#' @param func (character): The calculation function to be applied. +#' @param column (character): The column the \code{func} is applied to. +#' @param func (character): The calculation function to be applied +#' to the values of the \code{column}. +#' @example examples/data_url.R #' @export -set_top_calc <- function( +set_calculation <- function( widget, column, func = c("avg", "max", "min", "sum", "count", "unique"), - precision = 2) { - col_update <- list(topCalc = match.arg(func), topCalcParams = list(precision = precision)) + precision = 2, + pos = c("top", "bottom")) { + # Body + pos <- match.arg(pos) + col_update <- list(match.arg(func), list(precision = precision)) + names(col_update) <- c(paste0(pos, "Calc"), paste0(pos, "CalcParams")) modify_col_def(widget, column, col_update) } -# #' @export -set_bottom_calc <- function(widget, column) { - -} - - # Generics modify_col_def <- function(widget, column, col_update) { diff --git a/examples/data_url.R b/examples/data_url.R index d3c4181..f271dcc 100644 --- a/examples/data_url.R +++ b/examples/data_url.R @@ -1,6 +1,5 @@ data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" -# tabulator(data_url) tabulator( data_url, col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), @@ -10,5 +9,5 @@ tabulator( set_formatter_star("Pclass") |> set_formatter_tick_cross("Survived") |> set_formatter_progress("Fare", legend = TRUE, legend_align = "right", hoz_align = "right") |> - set_top_calc("Fare", func = "avg") |> - set_top_calc("Pclass", func = "unique") + set_calculation("Fare", func = "avg") |> + set_calculation("Pclass", func = "unique", pos = "bottom") diff --git a/man/set_calculation.Rd b/man/set_calculation.Rd new file mode 100644 index 0000000..547f0da --- /dev/null +++ b/man/set_calculation.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_calculation} +\alias{set_calculation} +\title{Add a calculation to a column} +\usage{ +set_calculation( + widget, + column, + func = c("avg", "max", "min", "sum", "count", "unique"), + precision = 2, + pos = c("top", "bottom") +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the \code{func} is applied to.} + +\item{func}{(character): The calculation function to be applied +to the values of the \code{column}.} +} +\description{ +Add a calculation to a column +} +\examples{ +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), + pagination = T, + column_calcs = "both" +) |> + set_formatter_star("Pclass") |> + set_formatter_tick_cross("Survived") |> + set_formatter_progress("Fare", legend = TRUE, legend_align = "right", hoz_align = "right") |> + set_calculation("Fare", func = "avg") |> + set_calculation("Pclass", func = "unique", pos = "bottom") +} diff --git a/man/set_top_calc.Rd b/man/set_top_calc.Rd deleted file mode 100644 index 82caa2a..0000000 --- a/man/set_top_calc.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/columns.R -\name{set_top_calc} -\alias{set_top_calc} -\title{Add a calculation to a column} -\usage{ -set_top_calc( - widget, - column, - func = c("avg", "max", "min", "sum", "count", "unique"), - precision = 2 -) -} -\arguments{ -\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} - -\item{column}{(character): The column the formatter is applied to.} - -\item{func}{(character): The calculation function to be applied.} -} -\description{ -Add a calculation to a column -} From c9a2802810451922298f576baaa3b920f2f6e0e6 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 13:53:39 +0200 Subject: [PATCH 05/16] Fix docs --- DESCRIPTION | 1 + R/columns.R | 3 +++ R/experimental.R | 15 +++++++++++++++ R/tabulator.R | 6 +++++- _pkgdown.yml | 4 ++++ examples/data_url.R | 3 +-- man/set_calculation.Rd | 8 ++++++-- vignettes/articles/rtabulator.Rmd | 2 +- 8 files changed, 36 insertions(+), 6 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 056afd7..020397f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,6 +21,7 @@ LazyData: true RoxygenNote: 7.3.2 Imports: glue, + htmltools, htmlwidgets, purrr, readr, diff --git a/R/columns.R b/R/columns.R index 0013b4b..77fd974 100644 --- a/R/columns.R +++ b/R/columns.R @@ -410,6 +410,9 @@ set_header_filter <- function(widget, columns = NULL) { #' @param column (character): The column the \code{func} is applied to. #' @param func (character): The calculation function to be applied #' to the values of the \code{column}. +#' @param precision (integer) The number of decimals to display. +#' Set to \code{FALSE} to display all decimals. +#' @param pos (character): Position at which calculated values are displayed. #' @example examples/data_url.R #' @export set_calculation <- function( diff --git a/R/experimental.R b/R/experimental.R index f59f6bb..7772220 100644 --- a/R/experimental.R +++ b/R/experimental.R @@ -31,3 +31,18 @@ find_column <- function(widget, column) { return(column_def) } + +# Themes #### + +get_theme_dependeny <- function( + theme = c("midnight", "modern", "simple", "site", "bootstrap3", "bootstrap4", "bootstrap5", "bulma", "materialize", "semanticui")) { + # Body + theme <- match.arg(theme) + htmltools::htmlDependency( + name = "tabulator-theme", + version = "6.2.5", + src = system.file("htmlwidgets/libs/tabulator", package = "rtabulator"), + stylesheet = glue::glue("tabulator_{theme}.min.css"), + all_files = FALSE + ) +} diff --git a/R/tabulator.R b/R/tabulator.R index 92f91bd..dd883a9 100644 --- a/R/tabulator.R +++ b/R/tabulator.R @@ -50,7 +50,8 @@ tabulator <- function( } theme <- match.arg(theme) - stylesheet_text <- ifelse(theme == "default", NA, read_tabulator_theme(theme)) + # stylesheet_text <- ifelse(theme == "default", NA, read_tabulator_theme(theme)) + stylesheet_text <- NA x <- list( data = data, @@ -60,6 +61,9 @@ tabulator <- function( # TODO: Make it optional when datetime formatter is called dependencies <- list(luxon_dependency) + if (theme != "default") { + dependencies <- c(dependencies, list(get_theme_dependeny(theme))) + } if (sheetjs) { dependencies <- c(dependencies, list(sheetjs_dependency)) diff --git a/_pkgdown.yml b/_pkgdown.yml index 448e27e..b70723d 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -19,6 +19,10 @@ reference: contents: - starts_with("set_formatter") + - title: Calculations + contents: + - set_calculation + - title: Shiny Integration contents: - rtabulator-shiny diff --git a/examples/data_url.R b/examples/data_url.R index f271dcc..52dd673 100644 --- a/examples/data_url.R +++ b/examples/data_url.R @@ -3,8 +3,7 @@ data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw tabulator( data_url, col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), - pagination = T, - column_calcs = "both" + pagination = TRUE ) |> set_formatter_star("Pclass") |> set_formatter_tick_cross("Survived") |> diff --git a/man/set_calculation.Rd b/man/set_calculation.Rd index 547f0da..e398899 100644 --- a/man/set_calculation.Rd +++ b/man/set_calculation.Rd @@ -19,6 +19,11 @@ set_calculation( \item{func}{(character): The calculation function to be applied to the values of the \code{column}.} + +\item{precision}{(integer) The number of decimals to display. +Set to \code{FALSE} to display all decimals.} + +\item{pos}{(character): Position at which calculated values are displayed.} } \description{ Add a calculation to a column @@ -29,8 +34,7 @@ data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw tabulator( data_url, col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived"), - pagination = T, - column_calcs = "both" + pagination = TRUE ) |> set_formatter_star("Pclass") |> set_formatter_tick_cross("Survived") |> diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index 3927663..720f88f 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -44,7 +44,7 @@ tabulator(USArrests, setup) ## Column Formatters -To customize your columns the easiest way is to use the `set_formatter_*` functions: +To customize your columns the easiest way is to use the `set_formatter_*()` functions: ```{r} tabulator(airquality) |> From b77f476ed4dfc1cceafe3b2d75a8bbc07b032b76 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 18:46:40 +0200 Subject: [PATCH 06/16] Add code to skip luxon dep --- R/tabulator.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/tabulator.R b/R/tabulator.R index dd883a9..8308aba 100644 --- a/R/tabulator.R +++ b/R/tabulator.R @@ -61,6 +61,7 @@ tabulator <- function( # TODO: Make it optional when datetime formatter is called dependencies <- list(luxon_dependency) + # dependencies <- list() if (theme != "default") { dependencies <- c(dependencies, list(get_theme_dependeny(theme))) } From 424494fee48de9c4b3fed0709ed766ec18f00db0 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sat, 14 Sep 2024 23:41:01 +0200 Subject: [PATCH 07/16] Add new header filter func --- R/columns.R | 30 ++++++++++++++++++++++++++++++ examples/misc/header_filter.R | 5 ++++- vignettes/articles/rtabulator.Rmd | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/R/columns.R b/R/columns.R index 77fd974..8212191 100644 --- a/R/columns.R +++ b/R/columns.R @@ -392,6 +392,7 @@ set_column_editor <- function(widget, columns, type = c("input", "number")) { #' If set to \code{NULL}, the editor is applied to all columns. #' @example examples/misc/header_filter.R #' @export +# TODO: Rename to set_default_header_filter set_header_filter <- function(widget, columns = NULL) { if (is.null(columns)) { columns <- colnames(widget$x$data) @@ -399,12 +400,41 @@ set_header_filter <- function(widget, columns = NULL) { col_update <- list(headerFilter = TRUE) for (column in columns) { + # TODO: Use new set_header_filter func here widget <- modify_col_def(widget, column, col_update) } return(widget) } +set_header_filter2 <- function( + widget, + column, + type = c("input", "number", "list", "tickCross"), + func = c("like"), + values_lookup = TRUE, + clearable = TRUE, + placeholder = NULL) { + # Body + if (is.null(type)) { + type <- ifelse(is.numeric(widget$x$data[, column]), "number", "input") + } else { + type <- match.arg(type) + } + + header_filter_params <- compact(list( + clearable = clearable, + valuesLookup = values_lookup + )) + col_update <- list( + headerFilter = type, + headerFilterPlaceholder = placeholder, + headerFilterFunc = func, + headerFilterParams = header_filter_params + ) + modify_col_def(widget, column, col_update) +} + #' Add a calculation to a column #' @inheritParams set_formatter_html #' @param column (character): The column the \code{func} is applied to. diff --git a/examples/misc/header_filter.R b/examples/misc/header_filter.R index 6661b5d..3ca79af 100644 --- a/examples/misc/header_filter.R +++ b/examples/misc/header_filter.R @@ -5,4 +5,7 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter() + set_header_filter2("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter2("first_name", placeholder = "Fran") |> + set_header_filter2("last_name", type = "li") + # set_header_filter() diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index 9f2f8aa..ebde9cf 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -89,7 +89,7 @@ sheets <- list( spreadsheet_def(title = "Lee", data = spreadsheet_data), spreadsheet_def(title = "Morgan", data = list()) # Empty spreadsheet ) -setup = tabulator_options( +setup <- tabulator_options( spreadsheet = TRUE, spreadsheet_sheets = sheets, spreadsheet_sheet_tabs = TRUE, From de3b105de40606892808686bc6a694954f28d9e0 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 00:00:12 +0200 Subject: [PATCH 08/16] Add func to add tooltip to column --- NAMESPACE | 1 + R/columns.R | 9 +++++++++ examples/misc/tooltip.R | 3 +++ man/set_header_filter.Rd | 5 ++++- man/set_tooltip.Rd | 21 +++++++++++++++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 examples/misc/tooltip.R create mode 100644 man/set_tooltip.Rd diff --git a/NAMESPACE b/NAMESPACE index cb11365..a4ad81d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -23,6 +23,7 @@ export(set_formatter_toggle_switch) export(set_formatter_traffic_light) export(set_header_filter) export(set_multi_column_header) +export(set_tooltip) export(spreadsheet_def) export(tabulator) export(tabulatorContext) diff --git a/R/columns.R b/R/columns.R index 8212191..cde85a5 100644 --- a/R/columns.R +++ b/R/columns.R @@ -435,6 +435,15 @@ set_header_filter2 <- function( modify_col_def(widget, column, col_update) } + +#' Add a tooltip to a column +#' @inheritParams set_formatter_html +#' @example examples/misc/tooltip.R +#' @export +set_tooltip <- function(widget, column) { + modify_col_def(widget, column, list(tooltip = TRUE)) +} + #' Add a calculation to a column #' @inheritParams set_formatter_html #' @param column (character): The column the \code{func} is applied to. diff --git a/examples/misc/tooltip.R b/examples/misc/tooltip.R new file mode 100644 index 0000000..75d9300 --- /dev/null +++ b/examples/misc/tooltip.R @@ -0,0 +1,3 @@ +tabulator(airquality) |> + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") diff --git a/man/set_header_filter.Rd b/man/set_header_filter.Rd index d8bd8b5..7f21b5f 100644 --- a/man/set_header_filter.Rd +++ b/man/set_header_filter.Rd @@ -23,5 +23,8 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter() + set_header_filter2("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter2("first_name", placeholder = "Fran") |> + set_header_filter2("last_name", type = "li") + # set_header_filter() } diff --git a/man/set_tooltip.Rd b/man/set_tooltip.Rd new file mode 100644 index 0000000..1c25ab4 --- /dev/null +++ b/man/set_tooltip.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_tooltip} +\alias{set_tooltip} +\title{Add a tooltip to a column} +\usage{ +set_tooltip(widget, column) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the formatter is applied to.} +} +\description{ +Add a tooltip to a column +} +\examples{ +tabulator(airquality) |> + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") +} From af7c96ecc800b5ebd8f0bfd31edddfd28e3cac24 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 00:03:28 +0200 Subject: [PATCH 09/16] Update docs --- _pkgdown.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_pkgdown.yml b/_pkgdown.yml index e64ada9..51d178e 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -23,6 +23,10 @@ reference: contents: - set_calculation + - title: Misc + contents: + - set_tooltip + - title: Shiny Integration contents: - rtabulator-shiny From c2e678c30fedff92f503d5b64edb27694b173d00 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 00:30:06 +0200 Subject: [PATCH 10/16] Add func to set column defaults --- NAMESPACE | 1 + R/columns.R | 20 ++++++++++++++++++++ _pkgdown.yml | 1 + examples/column_defaults.R | 2 ++ 4 files changed, 24 insertions(+) create mode 100644 examples/column_defaults.R diff --git a/NAMESPACE b/NAMESPACE index a4ad81d..257f265 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,6 +7,7 @@ export(list_to_data_frame) export(redo) export(renderTabulator) export(set_calculation) +export(set_column_defaults) export(set_column_editor) export(set_formatter_color) export(set_formatter_datetime) diff --git a/R/columns.R b/R/columns.R index cde85a5..0736054 100644 --- a/R/columns.R +++ b/R/columns.R @@ -444,6 +444,26 @@ set_tooltip <- function(widget, column) { modify_col_def(widget, column, list(tooltip = TRUE)) } +#' @export +set_column_defaults <- function( + widget, + editor = FALSE, + header_filter = FALSE, + header_sort = TRUE, + tooltip = TRUE, + width = NULL, + ...) { + widget$x$options$columnDefaults <- compact(list( + editor = editor, + headerFilter = header_filter, + headerSort = header_sort, + tooltip = tooltip, + width = width, + ... + )) + return(widget) +} + #' Add a calculation to a column #' @inheritParams set_formatter_html #' @param column (character): The column the \code{func} is applied to. diff --git a/_pkgdown.yml b/_pkgdown.yml index 51d178e..21b9570 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -26,6 +26,7 @@ reference: - title: Misc contents: - set_tooltip + - set_column_defaults - title: Shiny Integration contents: diff --git a/examples/column_defaults.R b/examples/column_defaults.R new file mode 100644 index 0000000..fb69828 --- /dev/null +++ b/examples/column_defaults.R @@ -0,0 +1,2 @@ +tabulator(iris) |> + set_column_defaults() From a39f01666847ac2ec87230194580856974ade025 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 13:09:23 +0200 Subject: [PATCH 11/16] Add 'for_each_col' func --- NAMESPACE | 1 + R/columns.R | 72 ++++++++++++++++++++----------- _pkgdown.yml | 2 +- examples/column_defaults.R | 8 +++- examples/for_each_col.R | 4 ++ examples/misc/header_filter.R | 7 ++- man/for_each_col.Rd | 27 ++++++++++++ man/set_column_defaults.Rd | 47 ++++++++++++++++++++ man/set_header_filter.Rd | 34 +++++++++++---- man/set_tooltip.Rd | 4 +- vignettes/articles/rtabulator.Rmd | 3 +- 11 files changed, 165 insertions(+), 44 deletions(-) create mode 100644 examples/for_each_col.R create mode 100644 man/for_each_col.Rd create mode 100644 man/set_column_defaults.Rd diff --git a/NAMESPACE b/NAMESPACE index 257f265..415215f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ export(add_row) export(create_columns) export(delete_selected_rows) +export(for_each_col) export(list_to_data_frame) export(redo) export(renderTabulator) diff --git a/R/columns.R b/R/columns.R index 0736054..baad8b5 100644 --- a/R/columns.R +++ b/R/columns.R @@ -3,6 +3,7 @@ #' @param editor (bool): Whether to make columns editable. #' @param filter (bool): Whether to add a header filter to the columns. #' @export +# TODO: We do not need to export this func anymore create_columns <- function(data, editor = FALSE, filter = FALSE) { data <- fix_colnames(data) dtype_is_numeric <- sapply(data, is.numeric) @@ -40,6 +41,7 @@ set_auto_id <- function(data) { } # TODO: Add possibility to add editor to specific columns only +# TODO: Check if func is obsolete add_editor_to_columns <- function(columns, data) { dtype_is_numeric <- sapply(data, is.numeric) for (index in 1:length(columns)) { @@ -49,14 +51,35 @@ add_editor_to_columns <- function(columns, data) { return(columns) } +# TODO: Check if func is obsolete add_filter_to_columns <- function(columns) { for (index in 1:length(columns)) { - columns[[index]]$headerFilter <- TRUE # detects column type automatically + columns[[index]]$headerFilter <- TRUE # detects column type automatically if editor type is set } return(columns) } +#' Apply a column setter function to multiple columns +#' @inheritParams set_formatter_html +#' @param columns (character vector): The columns the column setter function (\code{.f}) is applied to. +#' If set to \code{NULL} it is applied to all columns. +#' @param .f (function): The column setter function that updates the column settings. +#' @param ... Arguments that are passed to \code{.f}. +#' @example examples/for_each_col.R +#' @export +for_each_col <- function(widget, columns = NULL, .f, ...) { + if (is.null(columns)) columns <- colnames(widget$x$data) + + args <- list(...) + + for (column in columns) { + widget <- do.call(.f, c(list(widget = widget, column = column), args)) + } + + return(widget) +} + # Formatters #### #' HTML Formatter @@ -209,7 +232,6 @@ set_formatter_star <- function(widget, column, number_of_stars = NA, hoz_align = modify_col_def(widget, column, col_update) } - #' Progress Formatter #' @inheritParams set_formatter_html #' @param min (numeric): The minimum value for progress bar. @@ -386,32 +408,20 @@ set_column_editor <- function(widget, columns, type = c("input", "number")) { return(widget) } -#' Add header filter -#' @inheritParams set_column_editor -#' @param columns (character vector): Columns the editor is applied to. -#' If set to \code{NULL}, the editor is applied to all columns. +#' Add header filter to column +#' @inheritParams set_formatter_html +#' @param type (character): The type of the filter. +#' @param values_lookup (bool): Whether to use unique column values for the list filter. +#' @param func (character): The filter function. +#' @param clearable (bool): Whether to display a cross to clear the filter. +#' @param placeholder (character): Text that is displayed when no filter is set. #' @example examples/misc/header_filter.R #' @export -# TODO: Rename to set_default_header_filter -set_header_filter <- function(widget, columns = NULL) { - if (is.null(columns)) { - columns <- colnames(widget$x$data) - } - - col_update <- list(headerFilter = TRUE) - for (column in columns) { - # TODO: Use new set_header_filter func here - widget <- modify_col_def(widget, column, col_update) - } - - return(widget) -} - -set_header_filter2 <- function( +set_header_filter <- function( widget, column, type = c("input", "number", "list", "tickCross"), - func = c("like"), + func = c("like", "=", ">", ">=", "<", "<="), values_lookup = TRUE, clearable = TRUE, placeholder = NULL) { @@ -435,8 +445,7 @@ set_header_filter2 <- function( modify_col_def(widget, column, col_update) } - -#' Add a tooltip to a column +#' Add tooltip to column #' @inheritParams set_formatter_html #' @example examples/misc/tooltip.R #' @export @@ -444,6 +453,19 @@ set_tooltip <- function(widget, column) { modify_col_def(widget, column, list(tooltip = TRUE)) } + +#' Set column defaults +#' @inheritParams set_formatter_html +#' @param editor (character, bool): One of \code{"input"} or \code{"number"}. +#' If set to \code{FALSE} cells are not editable. +#' @param header_filter (character, bool): One of \code{"input"} or \code{"number"}. +#' Set to \code{FALSE} to disable header filters. +#' @param header_sort (bool): Whether to enable header sorting. +#' @param tooltip (bool): Whether to show tooltips displaying the cell value. +#' @param width (integer): Fixed width of columns. +#' @param ... Additional settings. +#' @seealso \url{https://tabulator.info/docs/6.2/columns#defaults} +#' @example examples/column_defaults.R #' @export set_column_defaults <- function( widget, diff --git a/_pkgdown.yml b/_pkgdown.yml index 21b9570..73ac373 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -12,6 +12,7 @@ reference: - set_column_editor - set_header_filter - set_multi_column_header + - set_column_defaults - title: Column Formatters desc: > @@ -26,7 +27,6 @@ reference: - title: Misc contents: - set_tooltip - - set_column_defaults - title: Shiny Integration contents: diff --git a/examples/column_defaults.R b/examples/column_defaults.R index fb69828..8c1e950 100644 --- a/examples/column_defaults.R +++ b/examples/column_defaults.R @@ -1,2 +1,6 @@ -tabulator(iris) |> - set_column_defaults() +tabulator(iris, theme = "simple") |> + set_column_defaults( + header_filter = TRUE, + header_sort = FALSE, + tooltip = TRUE + ) diff --git a/examples/for_each_col.R b/examples/for_each_col.R new file mode 100644 index 0000000..3685c14 --- /dev/null +++ b/examples/for_each_col.R @@ -0,0 +1,4 @@ +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col(numeric_cols, .f = set_header_filter, type = "number", func = "<=") diff --git a/examples/misc/header_filter.R b/examples/misc/header_filter.R index 3ca79af..77a67a9 100644 --- a/examples/misc/header_filter.R +++ b/examples/misc/header_filter.R @@ -5,7 +5,6 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter2("age", type = NULL ,func = "<=", placeholder = "max age") |> - set_header_filter2("first_name", placeholder = "Fran") |> - set_header_filter2("last_name", type = "li") - # set_header_filter() + set_header_filter("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter("first_name", placeholder = "Fran") |> + set_header_filter("last_name", type = "list") diff --git a/man/for_each_col.Rd b/man/for_each_col.Rd new file mode 100644 index 0000000..13a27db --- /dev/null +++ b/man/for_each_col.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{for_each_col} +\alias{for_each_col} +\title{Apply a column setter function to multiple columns} +\usage{ +for_each_col(widget, columns = NULL, .f, ...) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{columns}{(character vector): The columns the column setter function (\code{.f}) is applied to. +If set to \code{NULL} it is applied to all columns.} + +\item{.f}{(function): The column setter function that updates the column settings.} + +\item{...}{Arguments that are passed to \code{.f}.} +} +\description{ +Apply a column setter function to multiple columns +} +\examples{ +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col(numeric_cols, .f = set_header_filter, type = "number", func = "<=") +} diff --git a/man/set_column_defaults.Rd b/man/set_column_defaults.Rd new file mode 100644 index 0000000..ee1fe55 --- /dev/null +++ b/man/set_column_defaults.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_column_defaults} +\alias{set_column_defaults} +\title{Set column defaults} +\usage{ +set_column_defaults( + widget, + editor = FALSE, + header_filter = FALSE, + header_sort = TRUE, + tooltip = TRUE, + width = NULL, + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{editor}{(character, bool): One of \code{"input"} or \code{"number"}. +If set to \code{FALSE} cells are not editable.} + +\item{header_filter}{(character, bool): One of \code{"input"} or \code{"number"}. +Set to \code{FALSE} to disable header filters.} + +\item{header_sort}{(bool): Whether to enable header sorting.} + +\item{tooltip}{(bool): Whether to show tooltips displaying the cell value.} + +\item{width}{(integer): Fixed width of columns.} + +\item{...}{Additional settings.} +} +\description{ +Set column defaults +} +\examples{ +tabulator(iris, theme = "simple") |> + set_column_defaults( + header_filter = TRUE, + header_sort = FALSE, + tooltip = TRUE + ) +} +\seealso{ +\url{https://tabulator.info/docs/6.2/columns#defaults} +} diff --git a/man/set_header_filter.Rd b/man/set_header_filter.Rd index 7f21b5f..df32067 100644 --- a/man/set_header_filter.Rd +++ b/man/set_header_filter.Rd @@ -2,18 +2,35 @@ % Please edit documentation in R/columns.R \name{set_header_filter} \alias{set_header_filter} -\title{Add header filter} +\title{Add header filter to column} \usage{ -set_header_filter(widget, columns = NULL) +set_header_filter( + widget, + column, + type = c("input", "number", "list", "tickCross"), + func = c("like", "=", ">", ">=", "<", "<="), + values_lookup = TRUE, + clearable = TRUE, + placeholder = NULL +) } \arguments{ \item{widget}{(\code{\link{tabulator}}) A tabulator widget.} -\item{columns}{(character vector): Columns the editor is applied to. -If set to \code{NULL}, the editor is applied to all columns.} +\item{column}{(character): The column the formatter is applied to.} + +\item{type}{(character): The type of the filter.} + +\item{func}{(character): The filter function.} + +\item{values_lookup}{(bool): Whether to use unique column values for the list filter.} + +\item{clearable}{(bool): Whether to display a cross to clear the filter.} + +\item{placeholder}{(character): Text that is displayed when no filter is set.} } \description{ -Add header filter +Add header filter to column } \examples{ data <- data.frame( @@ -23,8 +40,7 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter2("age", type = NULL ,func = "<=", placeholder = "max age") |> - set_header_filter2("first_name", placeholder = "Fran") |> - set_header_filter2("last_name", type = "li") - # set_header_filter() + set_header_filter("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter("first_name", placeholder = "Fran") |> + set_header_filter("last_name", type = "list") } diff --git a/man/set_tooltip.Rd b/man/set_tooltip.Rd index 1c25ab4..a1b78b9 100644 --- a/man/set_tooltip.Rd +++ b/man/set_tooltip.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/columns.R \name{set_tooltip} \alias{set_tooltip} -\title{Add a tooltip to a column} +\title{Add tooltip to column} \usage{ set_tooltip(widget, column) } @@ -12,7 +12,7 @@ set_tooltip(widget, column) \item{column}{(character): The column the formatter is applied to.} } \description{ -Add a tooltip to a column +Add tooltip to column } \examples{ tabulator(airquality) |> diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index ebde9cf..1fa2268 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -62,7 +62,8 @@ headers <- list( ) tabulator(iris) |> - set_multi_column_header(headers) + set_multi_column_header(headers) |> + set_hea ``` ## Spreadsheets From 98049dd1f588f7edd7a42578d787f2d6e9b6b9d7 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 19:19:15 +0200 Subject: [PATCH 12/16] Update DESCRIPTION --- DESCRIPTION | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 020397f..c003d32 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,15 +1,15 @@ Package: rtabulator Type: Package Title: R Bindings for Tabulator JS -Version: 0.1.1 -Date: 2024-09-13 +Version: 0.1.1.9000 +Date: 2024-09-15 Authors@R: c( person("Stefan", "Kuethe", email = "crazycapivara@gmail.com", role = c("aut", "cre")), person("Nico", "Friess", email = "nico.friess@eoda.de", role = c("aut")) ) Maintainer: Stefan Kuethe Description: Provides R bindings for 'Tabulator JS' . - Makes it a breeze to create highly customizable interactive tables in markdown documents + Makes it a breeze to create highly customisable interactive tables in markdown documents and Shiny applications. URL: https://github.com/eodaGmbH/rtabulator From aca0820b54225b63f9d880d6ac5c20f61669cb7b Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 19:22:16 +0200 Subject: [PATCH 13/16] Add Tabulator JS license --- inst/htmlwidgets/libs/tabulator/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 inst/htmlwidgets/libs/tabulator/LICENSE diff --git a/inst/htmlwidgets/libs/tabulator/LICENSE b/inst/htmlwidgets/libs/tabulator/LICENSE new file mode 100644 index 0000000..85fb142 --- /dev/null +++ b/inst/htmlwidgets/libs/tabulator/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-2024 Oli Folkerd + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From d9f94f892695ad40e0f55ad9c0bc079b7ba20499 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Sun, 15 Sep 2024 20:47:30 +0200 Subject: [PATCH 14/16] Update Get started vignette --- _pkgdown.yml | 1 + vignettes/articles/rtabulator.Rmd | 55 +++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/_pkgdown.yml b/_pkgdown.yml index 73ac373..a91bcb8 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -27,6 +27,7 @@ reference: - title: Misc contents: - set_tooltip + - for_each_col - title: Shiny Integration contents: diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index 1fa2268..4693279 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -27,10 +27,33 @@ tabulator(airquality) In this case, the column definitions are automatically created for you. The horizontal alignment for character columns is set to _left_ while numeric columns are aligned _right_. +It is also possible to pass pass a data URL: + +```{r} +data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + +tabulator( + data_url, + col_select = c("PassengerId", "Name", "Pclass", "Fare", "Survived") +) +``` + ## Setup Options With `tabulator_options()` you can customize your table (or spreadsheet): +```{r} +setup <- tabulator_options( + row_height = 50, + selectable_rows = FALSE, + edit_trigger_event = "click" +) + +tabulator(iris, setup, editable = TRUE) +``` + +## Pagination + ```{r} setup <- tabulator_options( pagination = TRUE, @@ -48,7 +71,26 @@ To customize your columns, the easiest way is to use the `set_formatter_*()` fun ```{r} tabulator(airquality) |> set_formatter_progress("Temp", legend = TRUE, legend_align = "left") |> - set_formatter_traffic_light("Ozone") + set_formatter_traffic_light("Ozone") |> + set_tooltip("Ozone") +``` + +With `for_each_col()` you can apply a formatter to multiple columns: + +```{r} +numeric_cols <- c("Sepal_Length", "Sepal_Width", "Petal_Length", "Petal_Width") + +tabulator(iris) |> + for_each_col( + numeric_cols, + set_formatter_progress, + legend = TRUE, + legend_align = "left", + min = 0, + max = 10, + color = c("yellow", "orange", "green") + ) |> + for_each_col(numeric_cols, set_tooltip) ``` ## Multi Column headers @@ -62,10 +104,17 @@ headers <- list( ) tabulator(iris) |> - set_multi_column_header(headers) |> - set_hea + set_header_filter("Species", "list", placeholder = "Select Species") |> + set_multi_column_header(headers) ``` +*** +**Note** + +If further functions update the column definitions, `set_multi_column_header()` must be the last one. Therefore, in the example above `set_header_filter()` is called before we set the multi column header. + +*** + ## Spreadsheets To create an empty spreadsheet just pass an empty list as `data` parameter and `spreadsheet = TRUE` to `tabulator()`: From 8b464d0196b18ef1752e813da6c78f40077d1ee0 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Mon, 16 Sep 2024 00:17:30 +0200 Subject: [PATCH 15/16] Add more flexible 'set_editor' func --- NAMESPACE | 2 +- R/columns.R | 39 +++++++++++++++++++---- R/experimental.R | 8 +++++ _pkgdown.yml | 3 +- examples/editors.R | 18 +++++++++++ examples/misc/header_filter.R | 2 +- man/set_column_editor.Rd | 29 ----------------- man/set_editor.Rd | 53 +++++++++++++++++++++++++++++++ man/set_header_filter.Rd | 2 +- vignettes/articles/rtabulator.Rmd | 31 ++++++++++++++++++ 10 files changed, 147 insertions(+), 40 deletions(-) create mode 100644 examples/editors.R delete mode 100644 man/set_column_editor.Rd create mode 100644 man/set_editor.Rd diff --git a/NAMESPACE b/NAMESPACE index 415215f..f6c44cf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,7 +9,7 @@ export(redo) export(renderTabulator) export(set_calculation) export(set_column_defaults) -export(set_column_editor) +export(set_editor) export(set_formatter_color) export(set_formatter_datetime) export(set_formatter_html) diff --git a/R/columns.R b/R/columns.R index baad8b5..2025513 100644 --- a/R/columns.R +++ b/R/columns.R @@ -393,12 +393,12 @@ set_formatter_traffic_light <- function( # Other -#' Make columns editable -#' @inheritParams set_formatter_html -#' @param columns (character vector): Columns the editor is applied to. -#' @param type (character): Either \code{input} or \code{number}. -#' @example examples/formatters/column_editor.R -#' @export +# TODO: Deprecated +# #' Make columns editable +# #' @inheritParams set_formatter_html +# #' @param columns (character vector): Columns the editor is applied to. +# #' @param type (character): Either \code{input} or \code{number}. +# #' @example examples/formatters/column_editor.R set_column_editor <- function(widget, columns, type = c("input", "number")) { col_update <- list(editor = match.arg(type)) for (column in columns) { @@ -408,6 +408,33 @@ set_column_editor <- function(widget, columns, type = c("input", "number")) { return(widget) } +#' Set editor +#' @inheritParams set_formatter_html +#' @param editor (character): The editor type. +#' @param validator (character vector): One or more validators to validate user input. +#' @param ... Optional editor parameters depending on the selected editor. +#' @seealso +#' \url{https://tabulator.info/docs/6.2/edit} for available editors +#' \url{https://tabulator.info/docs/6.2/validate} for available validators. +#' @example examples/editors.R +#' @export +set_editor <- function( + widget, + column, + editor = c("input", "textarea", "number", "range", + "tickCross", "star", "progress", "date", "time", "datetime", "list"), + validator = NULL, + ...) { + # Body + col_update <- list(editor = match.arg(editor), validator = validator) + editor_params <- list(...) + if (length(editor_params) > 0) { + col_update$editorParams <- keys_to_camel_case(compact(editor_params)) + } + + modify_col_def(widget, column, col_update) +} + #' Add header filter to column #' @inheritParams set_formatter_html #' @param type (character): The type of the filter. diff --git a/R/experimental.R b/R/experimental.R index 7772220..36cbc3d 100644 --- a/R/experimental.R +++ b/R/experimental.R @@ -46,3 +46,11 @@ get_theme_dependeny <- function( all_files = FALSE ) } + +# Data #### + +titanic <- function(col_select = NULL) { + titanic_data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + + readr::read_csv(titanic_data_url, col_select = !!col_select, show_col_types = FALSE) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index a91bcb8..5bd1b66 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -9,7 +9,7 @@ reference: contents: - tabulator - tabulator_options - - set_column_editor + - set_editor - set_header_filter - set_multi_column_header - set_column_defaults @@ -48,4 +48,3 @@ reference: - spreadsheet_def - list_to_data_frame - create_columns - diff --git a/examples/editors.R b/examples/editors.R new file mode 100644 index 0000000..f6c0e5f --- /dev/null +++ b/examples/editors.R @@ -0,0 +1,18 @@ +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) diff --git a/examples/misc/header_filter.R b/examples/misc/header_filter.R index 77a67a9..56622cb 100644 --- a/examples/misc/header_filter.R +++ b/examples/misc/header_filter.R @@ -5,6 +5,6 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter("age", type = NULL, func = "<=", placeholder = "max age") |> set_header_filter("first_name", placeholder = "Fran") |> set_header_filter("last_name", type = "list") diff --git a/man/set_column_editor.Rd b/man/set_column_editor.Rd deleted file mode 100644 index c34ccfd..0000000 --- a/man/set_column_editor.Rd +++ /dev/null @@ -1,29 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/columns.R -\name{set_column_editor} -\alias{set_column_editor} -\title{Make columns editable} -\usage{ -set_column_editor(widget, columns, type = c("input", "number")) -} -\arguments{ -\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} - -\item{columns}{(character vector): Columns the editor is applied to.} - -\item{type}{(character): Either \code{input} or \code{number}.} -} -\description{ -Make columns editable -} -\examples{ -data <- data.frame( - age = c(10, 20, 40), - first_name = c("Franz", "Ferdinand", "Julia"), - last_name = c("Young", "Bowie", "Blackey") -) - -tabulator(data, width = 500) |> - set_column_editor(c("first_name", "last_name")) |> - set_column_editor("age", type = "number") -} diff --git a/man/set_editor.Rd b/man/set_editor.Rd new file mode 100644 index 0000000..a527cb3 --- /dev/null +++ b/man/set_editor.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/columns.R +\name{set_editor} +\alias{set_editor} +\title{Set editor} +\usage{ +set_editor( + widget, + column, + editor = c("input", "textarea", "number", "range", "tickCross", "star", "progress", + "date", "time", "datetime", "list"), + validator = NULL, + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{column}{(character): The column the formatter is applied to.} + +\item{editor}{(character): The editor type.} + +\item{validator}{(character vector): One or more validators to validate user input.} + +\item{...}{Optional editor parameters depending on the selected editor.} +} +\description{ +Set editor +} +\examples{ +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) +} +\seealso{ +\url{https://tabulator.info/docs/6.2/edit} for available editors + \url{https://tabulator.info/docs/6.2/validate} for available validators. +} diff --git a/man/set_header_filter.Rd b/man/set_header_filter.Rd index df32067..332b61a 100644 --- a/man/set_header_filter.Rd +++ b/man/set_header_filter.Rd @@ -40,7 +40,7 @@ data <- data.frame( ) tabulator(data) |> - set_header_filter("age", type = NULL ,func = "<=", placeholder = "max age") |> + set_header_filter("age", type = NULL, func = "<=", placeholder = "max age") |> set_header_filter("first_name", placeholder = "Fran") |> set_header_filter("last_name", type = "list") } diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index 4693279..8b0130c 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -115,6 +115,37 @@ If further functions update the column definitions, `set_multi_column_header()` *** +## Editors + +Set `editable = TRUE` to make all columns of the table editable. In this case, the editor for numeric columns is set to `number` and all others to `input`. + +```{r} +setup <- tabulator_options(edit_trigger_event = "click") + +tabulator(iris, setup, editable = TRUE) +``` + +To customize editor settings and validate user input use `set_editor()`: + +```{r} +tabulator(iris[, c(2, 5)], setup) |> + set_editor( + column = "Species", + editor = "list", + values_lookup = "active", + clearable = TRUE, + autocomplete = TRUE + ) |> + set_editor( + column = "Sepal_Width", + editor = "number", + min = 0, + max = 10, + step = 0.1, + validator = c("min:0", "max:10") + ) +``` + ## Spreadsheets To create an empty spreadsheet just pass an empty list as `data` parameter and `spreadsheet = TRUE` to `tabulator()`: From 12640cb0f2c5155d5b4e6ddc2c915ec0eb6304f3 Mon Sep 17 00:00:00 2001 From: Stefan Kuethe Date: Mon, 16 Sep 2024 09:51:15 +0200 Subject: [PATCH 16/16] Add some helper funcs and update docs --- NAMESPACE | 2 ++ R/columns.R | 6 ++-- R/data.R | 10 +++++++ R/experimental.R | 8 ------ R/tabulator_options.R | 48 ++++++++++++++++++++++++++++++- _pkgdown.yml | 19 ++++++++---- man/set_option_group_by.Rd | 31 ++++++++++++++++++++ man/tabulator_options.Rd | 11 ++++++- man/titanic.Rd | 14 +++++++++ vignettes/articles/rtabulator.Rmd | 45 +++++++++++++++++++++++++++++ 10 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 R/data.R create mode 100644 man/set_option_group_by.Rd create mode 100644 man/titanic.Rd diff --git a/NAMESPACE b/NAMESPACE index f6c44cf..135544f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -25,12 +25,14 @@ export(set_formatter_toggle_switch) export(set_formatter_traffic_light) export(set_header_filter) export(set_multi_column_header) +export(set_option_group_by) export(set_tooltip) export(spreadsheet_def) export(tabulator) export(tabulatorContext) export(tabulatorOutput) export(tabulator_options) +export(titanic) export(trigger_download) export(trigger_get_data) export(trigger_get_spreadsheet_data) diff --git a/R/columns.R b/R/columns.R index 2025513..cb211d0 100644 --- a/R/columns.R +++ b/R/columns.R @@ -421,8 +421,10 @@ set_column_editor <- function(widget, columns, type = c("input", "number")) { set_editor <- function( widget, column, - editor = c("input", "textarea", "number", "range", - "tickCross", "star", "progress", "date", "time", "datetime", "list"), + editor = c( + "input", "textarea", "number", "range", + "tickCross", "star", "progress", "date", "time", "datetime", "list" + ), validator = NULL, ...) { # Body diff --git a/R/data.R b/R/data.R new file mode 100644 index 0000000..c6df733 --- /dev/null +++ b/R/data.R @@ -0,0 +1,10 @@ +# Data #### + +#' Titanic data set +#' @param col_select (character vector): Columns to select. +#' @export +titanic <- function(col_select = NULL) { + titanic_data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" + + readr::read_csv(titanic_data_url, col_select = !!col_select, show_col_types = FALSE) +} diff --git a/R/experimental.R b/R/experimental.R index 36cbc3d..7772220 100644 --- a/R/experimental.R +++ b/R/experimental.R @@ -46,11 +46,3 @@ get_theme_dependeny <- function( all_files = FALSE ) } - -# Data #### - -titanic <- function(col_select = NULL) { - titanic_data_url <- "https://raw.githubusercontent.com/eodaGmbH/rtabulator/main/data-raw/titanic.csv" - - readr::read_csv(titanic_data_url, col_select = !!col_select, show_col_types = FALSE) -} diff --git a/R/tabulator_options.R b/R/tabulator_options.R index 0bb2be7..8fff97c 100644 --- a/R/tabulator_options.R +++ b/R/tabulator_options.R @@ -14,7 +14,12 @@ #' @param resizable_rows (bool): Allow user to resize rows. #' @param frozen_rows (numeric): Number of frozen rows. #' @param index (character): Field to be used as the unique index for each row. -#' @param group_by (character): Field to group rows by. +#' @param group_by (character vector): Field to group rows by. Pass multiple values +#' for multi level grouping. +#' @param group_start_open (bool vector): Open state of groups when grouping is enabled. +#' The length of the vector depends on the number of levels set with \code{group_by}. +#' @param group_toggle_element (character, bool): One of \code{arrow} or \code{header}. +#' Set to \code{FALSE} to disable toggling at all. #' @param edit_trigger_event (character): Event that triggers a cell edit. #' @param selectable_rows (character, bool, integer) Set to \code{FALSE} to disble row selection. #' If set to \code{TRUE} you can select as many rows as you want. @@ -54,6 +59,8 @@ tabulator_options <- function( index = "id", # Row Grouping group_by = NULL, + group_start_open = TRUE, + group_toggle_element = NULL, # Editing edit_trigger_event = c("dblclick", "click", "focus"), # Selection @@ -88,3 +95,42 @@ default_spreadsheet_options <- list( ), spreadsheet_column_definition = list(editor = "input") ) + +# TODO: Helper function to set pagination +set_option_pagination <- function( + widget, + pagination = FALSE, + pagination_size = 10, + pagination_size_selector = FALSE, + pagination_add_row = c("page", "table"), + ...) { + return(widget) +} + +#' Set group by option +#' @inheritParams set_formatter_html +#' @inheritParams tabulator_options +#' @export +set_option_group_by <- function( + widget, + group_by, + group_start_open = TRUE, + group_toggle_element = "header", + ...) { + # return(widget) + options_update <- list( + groupBy = group_by, + groupStartOpen = group_start_open, + groupToggleElement = group_toggle_element, + ... + ) + modify_tabulator_options(widget, options_update) +} + +modify_tabulator_options <- function(widget, options) { + widget$x$options <- utils::modifyList( + widget$x$options, + keys_to_camel_case(compact(options)) + ) + return(widget) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 5bd1b66..768d2fd 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -9,10 +9,18 @@ reference: contents: - tabulator - tabulator_options + - set_option_group_by + + - title: Column Settings + desc: > + Functions to update the default column settings + contents: + - set_column_defaults - set_editor - set_header_filter - set_multi_column_header - - set_column_defaults + - set_tooltip + - for_each_col - title: Column Formatters desc: > @@ -24,11 +32,6 @@ reference: contents: - set_calculation - - title: Misc - contents: - - set_tooltip - - for_each_col - - title: Shiny Integration contents: - rtabulator-shiny @@ -48,3 +51,7 @@ reference: - spreadsheet_def - list_to_data_frame - create_columns + + - title: Data Sets + contents: + - titanic diff --git a/man/set_option_group_by.Rd b/man/set_option_group_by.Rd new file mode 100644 index 0000000..888a0b4 --- /dev/null +++ b/man/set_option_group_by.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tabulator_options.R +\name{set_option_group_by} +\alias{set_option_group_by} +\title{Set group by option} +\usage{ +set_option_group_by( + widget, + group_by, + group_start_open = TRUE, + group_toggle_element = "header", + ... +) +} +\arguments{ +\item{widget}{(\code{\link{tabulator}}) A tabulator widget.} + +\item{group_by}{(character vector): Field to group rows by. Pass multiple values +for multi level grouping.} + +\item{group_start_open}{(bool vector): Open state of groups when grouping is enabled. +The length of the vector depends on the number of levels set with \code{group_by}.} + +\item{group_toggle_element}{(character, bool): One of \code{arrow} or \code{header}. +Set to \code{FALSE} to disable toggling at all.} + +\item{...}{Further options.} +} +\description{ +Set group by option +} diff --git a/man/tabulator_options.Rd b/man/tabulator_options.Rd index 010a369..e8a1c53 100644 --- a/man/tabulator_options.Rd +++ b/man/tabulator_options.Rd @@ -19,6 +19,8 @@ tabulator_options( frozen_rows = NULL, index = "id", group_by = NULL, + group_start_open = TRUE, + group_toggle_element = NULL, edit_trigger_event = c("dblclick", "click", "focus"), selectable_rows = "highlight", pagination = FALSE, @@ -63,7 +65,14 @@ the width of the Tabulator element.} \item{index}{(character): Field to be used as the unique index for each row.} -\item{group_by}{(character): Field to group rows by.} +\item{group_by}{(character vector): Field to group rows by. Pass multiple values +for multi level grouping.} + +\item{group_start_open}{(bool vector): Open state of groups when grouping is enabled. +The length of the vector depends on the number of levels set with \code{group_by}.} + +\item{group_toggle_element}{(character, bool): One of \code{arrow} or \code{header}. +Set to \code{FALSE} to disable toggling at all.} \item{edit_trigger_event}{(character): Event that triggers a cell edit.} diff --git a/man/titanic.Rd b/man/titanic.Rd new file mode 100644 index 0000000..6fee7de --- /dev/null +++ b/man/titanic.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\name{titanic} +\alias{titanic} +\title{Titanic data set} +\usage{ +titanic(col_select = NULL) +} +\arguments{ +\item{col_select}{(character vector): Columns to select.} +} +\description{ +Titanic data set +} diff --git a/vignettes/articles/rtabulator.Rmd b/vignettes/articles/rtabulator.Rmd index 8b0130c..f7f4536 100644 --- a/vignettes/articles/rtabulator.Rmd +++ b/vignettes/articles/rtabulator.Rmd @@ -109,12 +109,57 @@ tabulator(iris) |> ``` *** + **Note** If further functions update the column definitions, `set_multi_column_header()` must be the last one. Therefore, in the example above `set_header_filter()` is called before we set the multi column header. *** +## Groupings + +```{r} +setup <- tabulator_options( + group_by = c("Pclass"), + group_start_open = FALSE, + group_toggle_element = "header" +) + +titanic_df <- titanic(c("Pclass", "Sex", "Age", "Survived")) + +tabulator(titanic_df, setup) |> + set_formatter_traffic_light("Survived", color = c("red", "green")) +``` + +Multi level grouping is done by passing a vector as `group_by` parameter: + +```{r} +setup <- tabulator_options( + group_by = c("Sex", "Pclass"), + group_start_open = c(TRUE, FALSE) +) + +tabulator(titanic_df, setup) +``` + +*** + +**Note** + +You can also use `set_option_group_by()` to set the group by options. + +*** + +## Calculations + +With `set_calculation()` you can add calculations to the top or bottom of columns: + +```{r} +tabulator(iris[4:5]) |> + set_calculation("Petal_Width", "avg", pos = "top") |> + set_calculation("Petal_Width", "max", precision = 1, pos = "bottom") +``` + ## Editors Set `editable = TRUE` to make all columns of the table editable. In this case, the editor for numeric columns is set to `number` and all others to `input`.