Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rename qenv #733

Merged
merged 21 commits into from
Sep 22, 2022
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ Collate:
'modules_debugging.R'
'reporter_previewer_module.R'
'show_rcode_modal.R'
'tdata.R'
'teal.R'
'utils.R'
'validations.R'
Expand Down
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Generated by roxygen2: do not edit by hand

S3method(get_code,default)
S3method(get_code,tdata)
S3method(get_join_keys,default)
S3method(get_join_keys,tdata)
S3method(is_arg_used,"function")
S3method(is_arg_used,default)
S3method(is_arg_used,teal_module)
Expand All @@ -20,17 +24,21 @@ export(.log)
export(bookmarkableShinyApp)
export(default_filter)
export(example_module)
export(get_code)
export(get_join_keys)
export(get_rcode)
export(get_rcode_srv)
export(get_rcode_ui)
export(init)
export(log_app_usage)
export(module)
export(modules)
export(new_tdata)
export(reporter_previewer_module)
export(root_modules)
export(show_rcode_modal)
export(srv_teal_with_splash)
export(tdata2env)
export(ui_teal_with_splash)
export(validate_has_data)
export(validate_has_elements)
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
### Enhancements

* Added option to choose which variables can be filtered in the filter panel by using the `filterable` attributes for the per-dataset lists in the `filter` argument of `init`.
* `teal_module` having `data` argument in its arguments will receive a list of reactive filter data with `"code"` and `"join_keys"` attributes.
* `teal_module` having `data` argument in its arguments of type `tdata`. Modules receive this object (a list of reactive filter data with `"code"` and `"join_keys"` attributes).
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
* Updated the internals of `module_teal` to reflect changes in `teal.slice`.
* `teal_module` having `filter_panel_api` argument in its arguments will receive a `FilterPanelAPI` object.

Expand Down
1 change: 1 addition & 0 deletions R/example_module.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ example_module <- function(label = "example teal module") {
module(
label,
server = function(id, data) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
output$text <- renderPrint(data[[input$dataname]]())
})
Expand Down
11 changes: 3 additions & 8 deletions R/module_nested_tabs.R
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ srv_nested_tabs.teal_module <- function(id, datasets, modules, reporter) {
reactive(modules)
}

#' Convert `FilteredData` to reactive list of data
#' Convert `FilteredData` to reactive list of data of type `tdata`.
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
#'
#' Converts `FilteredData` object to list of data containing datasets needed for specific module.
#' Converts `FilteredData` object to `tdata` object containing datasets needed for specific module.
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
#' Please note that if module needs dataset which has a parent, then parent will be also returned.
#'
#' @param module (`teal_module`) module where needed filters are taken from
Expand All @@ -255,10 +255,5 @@ srv_nested_tabs.teal_module <- function(id, datasets, modules, reporter) {
}
)

# code from previous stages
attr(data, "code") <- get_datasets_code(datanames, datasets)

# join_keys
attr(data, "join_keys") <- datasets$get_join_keys()
data
new_tdata(data, reactive(get_datasets_code(datanames, datasets)), datasets$get_join_keys())
}
18 changes: 8 additions & 10 deletions R/modules_debugging.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
#' and avoids session restarts!
#'
#' @param label `character` label of module
#' @param active_datanames `character vector` datanames shown in filter panel;
#' can be `"all"` to mean all available datasets
#' @keywords internal
#'
#' @examples
Expand All @@ -34,19 +32,19 @@
#' ),
#' header = "Simple teal app"
#' )
#' \dontrun{
#' shinyApp(app$ui, app$server)
#' if (interactive()) {
#' shinyApp(app$ui, app$server)
#' }
filter_calls_module <- function(label = "Filter Calls Module", active_datanames = "all") { # nolint
filter_calls_module <- function(label = "Filter Calls Module") { # nolint
checkmate::assert_string(label)
checkmate::check_character(active_datanames, min.len = 1, any.missing = FALSE)

module(
label = label,
server = function(input, output, session, datasets) {
server = function(input, output, session, data) {
checkmate::assert_class(data, "tdata")

output$filter_calls <- renderText({
active_datanames <- datasets$handle_active_datanames(active_datanames)
teal.slice::get_filter_expr(datasets, datanames = active_datanames)
get_code(data)
})
},
ui = function(id, ...) {
Expand All @@ -56,6 +54,6 @@ filter_calls_module <- function(label = "Filter Calls Module", active_datanames
verbatimTextOutput(ns("filter_calls"))
)
},
filters = active_datanames
filters = "all"
)
}
52 changes: 52 additions & 0 deletions R/tdata.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#' @export
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some tests for these functions will be nice.
Please add roxygen2 docs as are exported.

tdata2env could give bad error outside the reactive context, should we use isolate or add some validation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup all coming 👍

new_tdata <- function(data, code, join_keys) {

#validation here

# code from previous stages
attr(data, "code") <- code

# join_keys
attr(data, "join_keys") <- join_keys

# set class
class(data) <- c("tdata", class(data))
data
}

#' @export
tdata2env <- function(data) { # nolint
#validation

list2env(lapply(data, function(x) if (is.reactive(x)) x() else x))
}

#' @export
get_code <- function(data) {
UseMethod("get_code", data)
}

#' @export
get_join_keys <- function(data) {
UseMethod("get_join_keys", data)
}

#' @export
get_code.tdata <- function(data) {
attr(data, "code")()
}

#' @export
get_join_keys.tdata <- function(data) {
attr(data, "join_keys")
}

#' @export
get_join_keys.default <- function(data) {
stop("get_join_keys function not implemented for this object")
}

#' @export
get_code.default <- function(data) {
stop("get_code function not implemented for this object")
}
4 changes: 2 additions & 2 deletions man/dot-datasets_to_data.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions man/filter_calls_module.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions vignettes/adding-support-for-reporting.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ teal_example_module <- function(label = "example teal module") {
module(
label,
server = function(id, data) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
output$text <- renderPrint(data[[input$dataname]]())
})
Expand Down Expand Up @@ -65,14 +66,14 @@ if (interactive()) shinyApp(app$ui, app$server)

## Add support for Reporting
### Change the declaration of the server function
The first step is to add another argument to the server function declaration - `reporter`. This needs to be the third
argument to the server function inside the `teal.module` call. See below:
The first step is to add another argument to the server function declaration - `reporter`. See below:
```{r}
example_module_with_reporting <- function(label = "example teal module") {
checkmate::assert_string(label)
module(
label,
server = function(id, data, reporter) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
output$text <- renderPrint(data[[input$dataname]]())
})
Expand Down Expand Up @@ -115,6 +116,7 @@ example_module_with_reporting <- function(label = "example teal module") {
module(
label,
server = function(id, data, reporter) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
teal.reporter::simple_reporter_srv(
id = "reporter",
Expand Down Expand Up @@ -177,6 +179,7 @@ example_module_with_reporting <- function(label = "example teal module") {
module(
label,
server = function(id, data, reporter) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
teal.reporter::simple_reporter_srv(id = "simpleReporter", reporter = reporter, card_fun = custom_function)
output$text <- renderPrint(data[[input$dataname]]())
Expand Down Expand Up @@ -244,6 +247,7 @@ example_reporter_module <- function(label = "Example") {
label,
server = function(id, data, reporter, filter_panel_api) {
with_filter <- !missing(filter_panel_api) && inherits(filter_panel_api, "FilterPanelApi")
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
dat <- reactive(data[[input$dataname]]())
output$nrow_ui <- renderUI({
Expand All @@ -253,7 +257,7 @@ example_reporter_module <- function(label = "Example") {
table_q <- reactive({
req(input$nrow)

teal.code::new_quosure(env = data) %>%
teal.code::new_qenv(tdata2env(data), code = get_code(data)) %>%
teal.code::eval_code(
substitute(
result <- head(data, nrows),
Expand Down
13 changes: 8 additions & 5 deletions vignettes/creating-custom-modules.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ example_module <- function(label = "example teal module") {
module(
label,
server = function(id, data) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {
output$text <- renderPrint(data[[input$dataname]]())
})
Expand Down Expand Up @@ -70,7 +71,8 @@ function(id,
```

When used inside a teal application called with `teal::init` the `data` argument is a named list of reactive data.frames
containing the data after having been filtered through the filter panel.
containing the data after having been filtered through the filter panel. It is of type `tdata` and can be created using
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
the `new_tdata` function.

## A More Complicated Example

Expand Down Expand Up @@ -114,25 +116,26 @@ ui_histogram_example <- function(id, histogram_var) {
# histogram_var is a teal.transform::data_extract_spec object
# specifying which columns of which datasets users can choose
srv_histogram_example <- function(id, data, histogram_var) {
checkmate::assert_class(data, "tdata")
moduleServer(id, function(input, output, session) {

# get the selected dataset and column from the UI
extracted <- teal.transform::data_extract_srv(
id = "histogram_var",
datasets = data,
data_extract_spec = histogram_var,
join_keys = attr(data, "join_keys")
join_keys = get_join_keys(data)
)

dataname <- reactive(extracted()$dataname)
selected <- reactive(extracted()$select)

# the reactive which adds the code to plot the histogram into the quosure
# the reactive which adds the code to plot the histogram into the qenv
plot_code_q <- reactive({
validate(need(length(selected) == 1, "Please select a variable"))

# take the filtered data from the data object and add it into the quosure environment
teal.code::new_quosure(env = data) %>%
# take the filtered data from the data object and add it into the qenv environment
teal.code::new_qenv(tdata2env(data), code = get_code(data)) %>%
teal.code::eval_code(
substitute(
expr = p <- hist(dataname[, selected]),
Expand Down