From 5aef4d7b44dceb7513a3e7cf859041cf9679c1c6 Mon Sep 17 00:00:00 2001
From: Vedha Viyash <49812166+vedhav@users.noreply.github.com>
Date: Wed, 12 Feb 2025 19:01:38 +0530
Subject: [PATCH] Improve the definition of "transform" in the vignettes
(#1489)
Closes #1475
`Customizing Module Output` vignette is now called `Transform Module
Output`
As we introduce a new term "customize" and it would be best to use the
same term "transform" that we se to transform the `teal_data` object
`Data Transformations as Shiny Module` is now called `Transform Input
Data`
This name was appropriate at the time of writing the vignette when
transformation done using shiny module was only possible in one place,
now that is not the case and we have two places where data is
_transformed_ using shiny module. And from the user's perspective the
main thing showcased in this vignette is about transforming the input
data.
---
R/dummy_functions.R | 2 +-
R/modules.R | 2 +-
R/teal_transform_module.R | 6 +-
_pkgdown.yml | 4 +-
.../teal-transform-module-decorators.drawio | 137 ++++++++++++++++++
...eal-transform-module-transformators.drawio | 134 +++++++++++++++++
man/example_module.Rd | 4 +-
man/module_transform_data.Rd | 2 +-
man/teal_modules.Rd | 2 +-
man/teal_transform_module.Rd | 4 +-
.../teal-transform-module-decorators.svg | 1 +
.../teal-transform-module-transformators.svg | 1 +
...ny-module.Rmd => transform-input-data.Rmd} | 10 +-
...output.Rmd => transform-module-output.Rmd} | 93 ++++++------
14 files changed, 342 insertions(+), 60 deletions(-)
create mode 100644 inst/design/teal-transform-module-decorators.drawio
create mode 100644 inst/design/teal-transform-module-transformators.drawio
create mode 100644 vignettes/images/teal-transform-module-decorators.svg
create mode 100644 vignettes/images/teal-transform-module-transformators.svg
rename vignettes/{data-transform-as-shiny-module.Rmd => transform-input-data.Rmd} (95%)
rename vignettes/{customizing-module-output.Rmd => transform-module-output.Rmd} (80%)
diff --git a/R/dummy_functions.R b/R/dummy_functions.R
index d2a1f48c17..3d447daf3e 100644
--- a/R/dummy_functions.R
+++ b/R/dummy_functions.R
@@ -5,7 +5,7 @@
#' This module creates an object called `object` that can be modified with decorators.
#' The `object` is determined by what's selected in `Choose a dataset` input in UI.
#' The object can be anything that can be handled by `renderPrint()`.
-#' See the `vignette("customizing-module-output", package = "teal")` or [`teal_transform_module`]
+#' See the `vignette("transform-module-output", package = "teal")` or [`teal_transform_module`]
#' to read more about decorators.
#'
#' @inheritParams teal_modules
diff --git a/R/modules.R b/R/modules.R
index 88638af184..92cb31227c 100644
--- a/R/modules.R
+++ b/R/modules.R
@@ -74,7 +74,7 @@ setOldClass("teal_modules")
#' @param ui_args (named `list`) with additional arguments passed on to the UI function.
#' @param x (`teal_module` or `teal_modules`) Object to format/print.
#' @param transformators (`list` of `teal_transform_module`) that will be applied to transform module's data input.
-#' To learn more check `vignette("data-transform-as-shiny-module", package = "teal")`.
+#' To learn more check `vignette("transform-input-data", package = "teal")`.
#'
#' @param ...
#' - For `modules()`: (`teal_module` or `teal_modules`) Objects to wrap into a tab.
diff --git a/R/teal_transform_module.R b/R/teal_transform_module.R
index 1812d6d6b5..71ba28ca1b 100644
--- a/R/teal_transform_module.R
+++ b/R/teal_transform_module.R
@@ -13,7 +13,7 @@
#' The primary advantage of `teal_transform_module` over custom modules is in its error handling, where all warnings and
#' errors are managed by `teal`, allowing developers to focus on transformation logic.
#'
-#' For more details, see the vignette: `vignette("data-transform-as-shiny-module", package = "teal")`.
+#' For more details, see the vignette: `vignette("transform-input-data", package = "teal")`.
#'
#' # Customizing Module Outputs
#'
@@ -23,7 +23,7 @@
#' To manage these `decorators` within your module, use [`ui_transform_teal_data()`] and [`srv_transform_teal_data()`].
#' (For further guidance on managing decorators, refer to `ui_args` and `srv_args` in the vignette documentation.)
#'
-#' See the vignette `vignette("customizing-module-output", package = "teal")` for additional examples.
+#' See the vignette `vignette("transform-module-output", package = "teal")` for additional examples.
#'
#' # `server` as a language
#'
@@ -141,7 +141,7 @@ teal_transform_module <- function(ui = NULL,
"teal_transform_module() ",
"Using eventReactive in teal_transform module server code should be avoided as it ",
"may lead to unexpected behavior. See the vignettes for more information ",
- "(`vignette(\"data-transform-as-shiny-module\", package = \"teal\")`).",
+ "(`vignette(\"transform-input-data\", package = \"teal\")`).",
call. = FALSE
)
}
diff --git a/_pkgdown.yml b/_pkgdown.yml
index 6c34189050..468399619f 100644
--- a/_pkgdown.yml
+++ b/_pkgdown.yml
@@ -62,13 +62,13 @@ articles:
- including-data-in-teal-applications
- data-as-shiny-module
- filter-panel
- - data-transform-as-shiny-module
+ - transform-input-data
- title: Extending `teal`
navbar: Extending `teal`
contents:
- creating-custom-modules
- adding-support-for-reporting
- - customizing-module-output
+ - transform-module-output
- title: Using `teal`
navbar: Using `teal`
contents:
diff --git a/inst/design/teal-transform-module-decorators.drawio b/inst/design/teal-transform-module-decorators.drawio
new file mode 100644
index 0000000000..0a15f30de3
--- /dev/null
+++ b/inst/design/teal-transform-module-decorators.drawio
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inst/design/teal-transform-module-transformators.drawio b/inst/design/teal-transform-module-transformators.drawio
new file mode 100644
index 0000000000..923f827991
--- /dev/null
+++ b/inst/design/teal-transform-module-transformators.drawio
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/man/example_module.Rd b/man/example_module.Rd
index e49df8f22d..7e5251a87a 100644
--- a/man/example_module.Rd
+++ b/man/example_module.Rd
@@ -25,7 +25,7 @@ argument.
}}
\item{transformators}{(\code{list} of \code{teal_transform_module}) that will be applied to transform module's data input.
-To learn more check \code{vignette("data-transform-as-shiny-module", package = "teal")}.}
+To learn more check \code{vignette("transform-input-data", package = "teal")}.}
\item{decorators}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} (\code{list} of \code{teal_transform_module}) optional,
decorator for \code{object} included in the module.}
@@ -40,7 +40,7 @@ A \code{teal} module which can be included in the \code{modules} argument to \co
This module creates an object called \code{object} that can be modified with decorators.
The \code{object} is determined by what's selected in \verb{Choose a dataset} input in UI.
The object can be anything that can be handled by \code{renderPrint()}.
-See the \code{vignette("customizing-module-output", package = "teal")} or \code{\link{teal_transform_module}}
+See the \code{vignette("transform-module-output", package = "teal")} or \code{\link{teal_transform_module}}
to read more about decorators.
}
\examples{
diff --git a/man/module_transform_data.Rd b/man/module_transform_data.Rd
index 0bc78405d0..fca1273403 100644
--- a/man/module_transform_data.Rd
+++ b/man/module_transform_data.Rd
@@ -20,7 +20,7 @@ srv_transform_teal_data(
\item{id}{(\code{character(1)}) \code{shiny} module instance id.}
\item{transformators}{(\code{list} of \code{teal_transform_module}) that will be applied to transform module's data input.
-To learn more check \code{vignette("data-transform-as-shiny-module", package = "teal")}.}
+To learn more check \code{vignette("transform-input-data", package = "teal")}.}
\item{class}{(character(1)) CSS class to be added in the \code{div} wrapper tag.}
diff --git a/man/teal_modules.Rd b/man/teal_modules.Rd
index 1632a4e8cd..5adff2df5e 100644
--- a/man/teal_modules.Rd
+++ b/man/teal_modules.Rd
@@ -85,7 +85,7 @@ argument.
\item{ui_args}{(named \code{list}) with additional arguments passed on to the UI function.}
\item{transformators}{(\code{list} of \code{teal_transform_module}) that will be applied to transform module's data input.
-To learn more check \code{vignette("data-transform-as-shiny-module", package = "teal")}.}
+To learn more check \code{vignette("transform-input-data", package = "teal")}.}
\item{...}{\itemize{
\item For \code{modules()}: (\code{teal_module} or \code{teal_modules}) Objects to wrap into a tab.
diff --git a/man/teal_transform_module.Rd b/man/teal_transform_module.Rd
index 46f0192e31..0c17362429 100644
--- a/man/teal_transform_module.Rd
+++ b/man/teal_transform_module.Rd
@@ -39,7 +39,7 @@ The transformed data is then passed to the \code{server} of \code{\link[=teal_mo
The primary advantage of \code{teal_transform_module} over custom modules is in its error handling, where all warnings and
errors are managed by \code{teal}, allowing developers to focus on transformation logic.
-For more details, see the vignette: \code{vignette("data-transform-as-shiny-module", package = "teal")}.
+For more details, see the vignette: \code{vignette("transform-input-data", package = "teal")}.
}
\section{Customizing Module Outputs}{
@@ -49,7 +49,7 @@ Some \code{\link{teal_modules}} permit developers to inject custom \code{shiny}
To manage these \code{decorators} within your module, use \code{\link[=ui_transform_teal_data]{ui_transform_teal_data()}} and \code{\link[=srv_transform_teal_data]{srv_transform_teal_data()}}.
(For further guidance on managing decorators, refer to \code{ui_args} and \code{srv_args} in the vignette documentation.)
-See the vignette \code{vignette("customizing-module-output", package = "teal")} for additional examples.
+See the vignette \code{vignette("transform-module-output", package = "teal")} for additional examples.
}
\section{\code{server} as a language}{
diff --git a/vignettes/images/teal-transform-module-decorators.svg b/vignettes/images/teal-transform-module-decorators.svg
new file mode 100644
index 0000000000..3b3eb2ca2f
--- /dev/null
+++ b/vignettes/images/teal-transform-module-decorators.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vignettes/images/teal-transform-module-transformators.svg b/vignettes/images/teal-transform-module-transformators.svg
new file mode 100644
index 0000000000..847cfc8337
--- /dev/null
+++ b/vignettes/images/teal-transform-module-transformators.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/vignettes/data-transform-as-shiny-module.Rmd b/vignettes/transform-input-data.Rmd
similarity index 95%
rename from vignettes/data-transform-as-shiny-module.Rmd
rename to vignettes/transform-input-data.Rmd
index 0fd9d03bb0..1cc19d30e5 100644
--- a/vignettes/data-transform-as-shiny-module.Rmd
+++ b/vignettes/transform-input-data.Rmd
@@ -1,11 +1,11 @@
---
-title: "Data Transformations as Shiny Module"
+title: "Transform Input Data"
author: "NEST CoreDev"
output:
rmarkdown::html_vignette:
toc: true
vignette: >
- %\VignetteIndexEntry{Data Transformations as shiny Module}
+ %\VignetteIndexEntry{Transform Input Data}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
@@ -13,7 +13,7 @@ vignette: >
## Introduction
`teal` version `0.16` introduced a new, optional argument in `teal::module`, `transformators`.
-This argument accepts a `list` of `teal_transform_module` objects, which are a special class of `teal_data_module` created using the `teal_transform_module()` function.
+This argument accepts a `list` of `teal_transform_module` objects, which are created using the `teal_transform_module()` function.
`teal_transform_module()` takes `ui` and `server` arguments to create a `shiny` module that encodes data transformations.
When transformators are passed to a module, `teal` will execute data transformations when that module is loaded as well as whenever the original data changes.
@@ -23,6 +23,10 @@ The `ui` elements of the transform module will be added to the filter panel, whi
This vignette describes how to manage custom data transformations in `teal` apps.
+
+
+In this vignette we will focus on using the `teal_transform_module` for transforming the input data using the `transformators` argument in `teal::module` function.
+
## Creating a data transformation module
Let us initialize a simple `teal` app by providing `iris` and `mtcars` as input datasets.
diff --git a/vignettes/customizing-module-output.Rmd b/vignettes/transform-module-output.Rmd
similarity index 80%
rename from vignettes/customizing-module-output.Rmd
rename to vignettes/transform-module-output.Rmd
index cd18778d10..64658fa2f5 100644
--- a/vignettes/customizing-module-output.Rmd
+++ b/vignettes/transform-module-output.Rmd
@@ -1,11 +1,11 @@
---
-title: "Customizing Module Output"
+title: "Transform Module Output"
author: "NEST CoreDev"
output:
rmarkdown::html_vignette:
toc: true
vignette: >
- %\VignetteIndexEntry{Customizing Module Output}
+ %\VignetteIndexEntry{Transform Module Output}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
@@ -19,39 +19,42 @@ library(ggplot2)
## Introduction
The outputs produced by `teal` modules, like graphs or tables, are created by the module developer and look a certain way.
-It is impossible to design an output that will satisfy every possible user, so the form of the output should be considered a default value that can be customized.
-Here we describe the concept of _decoration_, whereby a `teal_transform_module` can modify an output created by a `teal_module`, enabling you to tailor outputs to your specific requirements without rewriting the original module code.
+It is hard to design an output that will satisfy every possible user, so the form of the output should be considered a default value that can be customized.
+In [Transform Input Data](transform-input-data.html) we described how `teal_module`'s input data can be modified using `teal_transform_module`. Here we present how to utilize `teal_transform_module` to modify an output created by a `teal_module`, enabling you to tailor outputs to your specific requirements without rewriting the original module code.
-While it is not required, reading [this vignette](data-transform-as-shiny-module.html) may give you a fuller understanding.
+
+## How to Transform outputs?
-## Decorators
-
-Decorators are created with `teal_transform_module` and thus they are `shiny` modules.
+Custom transformations for the output objects can be created with `teal_transform_module()` and thus they are `shiny` modules.
They are passed to `teal_module` constructors as arguments (see below).
Their server logic will be used to modify objects such as plots or tables that exist in the server function of a `teal_module`.
-A `ui` function can provide interactivity but that is optional, an app developer is free to use decorator modules that do not require user input.
+A `ui` function can provide interactivity but that is optional, an app developer is free to transform outputs objects of a `teal` module that do not require user input.
### Requirements and Limitations
-Using decorators requires the following:
+Transforming `teal` module output requires the following:
1. **Module Support**:
-`teal` will apply decorators to `teal_module` outputs but the module in question must explicitly support this functionality.
-It the responsibility of to the module developer to ensure that decorators can be used.
+`teal` will apply transformations to `teal_module` outputs, but the module in question must explicitly support this functionality.
+It is the responsibility of to the module developer to accept and consume the list of `teal_transform_module`.
2. **Matching Object Names**:
-Decorators will reference variables that exist in the `teal_module` server function and therefore must use the appropriate variable names.
-Module developers are encouraged to provide the relevant names in the module's documentation, otherwise the person writing a decorator must follow the source code.
+Transformations have to reference variables that already exist in the `teal_module` server function and therefore must use the appropriate variable names.
+Think of it as extending the plot/table code that already exists in the module.
+Module developers are encouraged to provide the relevant names in the module's documentation, otherwise the person writing the output transformation must follow the source code.
3. **Maintaining Object Classes**:
-A decorator must not alter the class of the object that it modifies.
+A transformation must not alter the class of the object that it modifies.
This is because a different class may require a different rendering function and that is part of the module structure, which beyond the control of decorators.
+If change of this magnitude is required, it is recommended to create a new module.
+
+## Building Output Transformations (Decorators)
-## Building Decorators
+For simplicity, we will refer to the output transformers as **decorators** in the code examples below.
### Server
-Here we create a simple decorator that does not provide user input.
+Here we create a simple transformator that does not provide any user input.
Knowing that the module contains an object of class `ggplot2` named `plot`, we will modify its title and x-axis title:
```{r static_decorator}
@@ -75,7 +78,7 @@ static_decorator <- teal_transform_module(
### UI
-If decoration requires user input, a `ui` function can be added.
+If the transformation requires a user input, a `ui` function can be added.
Here, the x-axis title is obtained from a `textInput` widget, giving the user some flexibility.
Note how the input values are passed to the `within()` function using its `...` argument.
See `?teal.code::within.qenv` for more examples.
@@ -110,10 +113,10 @@ interactive_decorator <- teal_transform_module(
### Variable Names as Arguments
-The server function of a decorating `teal_transform_module` must conform to the names of the variables that exist in the server function of the decorated `teal_module`.
-Writing a universal decorator that applies to any module is impossible because different modules may use different variable names for their output elements.
-It is possible, however, to create a decorator that will take the relevant variable names as arguments.
-Here, the `output_name` variable name is passed to a decorator, allowing it to work with multiple modules.
+The server function of a transforming `teal_transform_module` must conform to the names of the variables that exist in the server function of the transformed `teal_module`.
+Writing a universal transformator that applies to any module is impossible because different modules may use different variable names for their output elements.
+It is possible, however, to create a transformator that will take the relevant variable names as arguments.
+Here, the `output_name` variable name is passed to a transformator, allowing it to work with multiple modules.
```{r dynamic_decorator}
dynamic_decorator <- function(output_name) {
@@ -147,20 +150,21 @@ dynamic_decorator <- function(output_name) {
Note that when the function is used, `output_name` will be passed a character string but the expression passed to `within` needs a `name`/`symbol`, a language object, hence the argument value must be converted to a `name`.
-## Using Decorators
+## Using Output Transformations (Decorators)
-Decorators are applied to a `teal` module as follows:
+Transformations are applied to a `teal` module as follows:
-1. A list of decorators is passed to the module constructor function (_e.g._ `tm_my_module`).
-2. The module constructor calls the module generator function (`teal::module`) and passes the decorators to the `ui_args` and `server_args` arguments.
-3. The module functions, UI and server, take a list of decorators as arguments and resolve them using `ui_transform_teal_data` and `srv_transform_teal_data`, respectively.
+1. A list of transformations is passed to the module constructor function (_e.g._ `tm_my_module`).
+2. The module constructor calls the module generator function (`teal::module`) and passes the transformations to the `ui_args` and `server_args` arguments.
+3. The module functions, UI and server, take a list of transformations as arguments and resolve them using `ui_transform_teal_data` and `srv_transform_teal_data`, respectively.
Here is a minimal illustration:
```{r pseudo_module, eval = FALSE}
+# styler: off
pseudo_decorated_module <- function(
label = "Pseudo Module with Decorator Support",
- decorators = list() # <--- added block (1)
+ decorators = list() # <--- added block (1)
) {
module(
label = label,
@@ -191,13 +195,14 @@ pseudo_decorated_module <- function(
}
)
}
+# styler: on
```
-The following examples demonstrate various uses of decorators.
+The following examples demonstrate various uses of output transformations.
-### Single Decoration
+### Single Transformation (Decoration)
-In the first example we will apply one decoration to one output.
+In the first example we will apply one transformation to one output.
### Module
@@ -288,7 +293,7 @@ tm_decorated_plot <- function(label = "module", decorators = list()) {
#### Application
-Note that every call to the module constructor (`tm_decorated_plot`) takes a list containing _one_ decorator.
+Note that every call to the module constructor (`tm_decorated_plot`) takes a list containing _one_ transformator.
```{r app_1}
app <- init(
@@ -321,13 +326,13 @@ knitr::include_url(url, height = "800px")
```
-### Decorating Multiple Outputs
+### Transforming Multiple Outputs (Decorators)
-Here we will apply decoration to two outputs in one module.
+Here we will apply transformation to two outputs in one module.
-#### Decorators
+#### Transformators
-The plot decorator adds a user-provided title to a `ggplot2` object.
+The plot transformators adds a user-provided title to a `ggplot2` object.
```{r plot_decorator}
plot_decorator <- teal_transform_module(
@@ -356,7 +361,7 @@ plot_decorator <- teal_transform_module(
)
```
-The table decorator adds a column to a `data.frame`.
+The table transformators adds a column to a `data.frame`.
```{r table_decorator}
table_decorator <- teal_transform_module(
@@ -381,7 +386,7 @@ table_decorator <- teal_transform_module(
The following module uses `ggplot2` to generate a scatter plot, and presents a simple `data.frame` as a summary table.
Code for both outputs is also displayed.
-Note that the module constructor accepts one list of decorators and the decorators are then manually separated in the module functions.
+Note that the module constructor accepts one list of transformations and the transformations are then manually separated in the module functions.
```{r tm_decorated_plot_table}
tm_decorated_plot_table <- function(label = "module with two outputs", decorators = list()) {
@@ -479,7 +484,7 @@ tm_decorated_plot_table <- function(label = "module with two outputs", decorator
#### Application
-Note that a named list of decorators is passed to the module constructor.
+Note that a named list of transformations is passed to the module constructor.
```{r app_2}
app <- init(
@@ -516,14 +521,14 @@ knitr::include_url(url, height = "800px")
## Convenience
-Here we present some ways to work with decorators more conveniently.
+Here we present some ways to work with transformators more conveniently.
These are purely optional.
### Reducing Boilerplate
-The function `make_teal_transform_server` can be used to reduce the amount of boilerplate code when writing new decorators.
+The function `make_teal_transform_server` can be used to reduce the amount of boilerplate code when writing new transformators.
It takes `language` as input and requires you to use `input` object names directly in the expression.
-The following calls yield the same decorator module.
+The following calls yield the same transformator module.
Note that the combination of `my_title = input$x_axis_title` and `xlab(my_title)` is replaced by a simple `xlab(x_axis_table)`.
```{r, eval=FALSE}
teal_transform_module(
@@ -567,9 +572,9 @@ teal_transform_module(
```
-### Multiple Decorators
+### Multiple Transformations
-Consider these constructs to accommodate an arbitrary number of decorators in your module.
+Consider these constructs to accommodate an arbitrary number of transformators in your module.
Note that with this method all decorations will be applied to one output.
```{r, eval=FALSE}
# in the module UI function