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

add reporter #635

Merged
merged 28 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Imports:
styler,
teal.code,
teal.logger,
teal.reporter,
teal.slice,
utils
Suggests:
Expand Down Expand Up @@ -78,6 +79,7 @@ Collate:
'module_teal.R'
'module_teal_with_splash.R'
'modules_debugging.R'
'reporter_previewer_module.R'
'show_rcode_modal.R'
'teal.R'
'utils.R'
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export(init)
export(log_app_usage)
export(module)
export(modules)
export(reporter_previewer_module)
export(root_modules)
export(show_rcode_modal)
export(srv_teal_with_splash)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# teal 0.11.0.9006

### Enhancments

* Added new function `reporter_previewer_module` to wrap the `teal.reporter` package previewer functionality as a `teal` module.
* `teal` now supports `modules` which include reporting. If any `module` which supports reporting is included then a `reporter_previewer_module` is included.

### Breaking changes
* Deprecated `bookmarkableShinyApp`. In future releases the `teal` framework will stop supporting shiny bookmarking (which has not officially been supported); it may be officially supported in the future. Note the filter panel in `teal.slice` retains its ability to save and restore its state if used in a standalone `shiny` app with bookmarking.

Expand Down
34 changes: 17 additions & 17 deletions R/module_nested_tabs.R
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,13 @@ ui_nested_tabs.teal_modules <- function(id, modules, datasets, depth = 0L) {
ui_nested_tabs.teal_module <- function(id, modules, datasets, depth = 0L) {
stopifnot(is(datasets, "FilteredData"))
args <- isolate(teal.transform::resolve_delayed(modules$ui_args, datasets))
args <- c(list(id = id, datasets = datasets), args)
tags$div(
id = id,
class = "teal_module",
tagList(
if (depth >= 2L) div(style = "margin-top: 1.5rem;"),
do.call(
modules$ui,
c(list(id = id, datasets = datasets), args)
)
do.call(modules$ui, args)
)
)
}
Expand Down Expand Up @@ -122,22 +120,23 @@ ui_nested_tabs.teal_module <- function(id, modules, datasets, depth = 0L) {
#'
#' @return `reactive` which returns the active module that corresponds to the selected tab
#' @keywords internal
srv_nested_tabs <- function(id, datasets, modules) {
srv_nested_tabs <- function(id, datasets, modules, reporter) {
stopifnot(inherits(datasets, "FilteredData"))
stopifnot(inherits(reporter, "Reporter"))
UseMethod("srv_nested_tabs", modules)
}

#' @rdname srv_nested_tabs
#' @export
#' @keywords internal
srv_nested_tabs.default <- function(id, datasets, modules) {
srv_nested_tabs.default <- function(id, datasets, modules, reporter) {
stop("Modules class not supported: ", paste(class(modules), collapse = " "))
}

#' @rdname srv_nested_tabs
#' @export
#' @keywords internal
srv_nested_tabs.teal_modules <- function(id, datasets, modules) {
srv_nested_tabs.teal_modules <- function(id, datasets, modules, reporter) {
moduleServer(id = id, module = function(input, output, session) {
logger::log_trace(
paste(
Expand All @@ -147,7 +146,7 @@ srv_nested_tabs.teal_modules <- function(id, datasets, modules) {
)
)
modules_reactive <- sapply(names(modules$children), USE.NAMES = TRUE, function(id) {
srv_nested_tabs(id = id, datasets = datasets, modules = modules$children[[id]])
srv_nested_tabs(id = id, datasets = datasets, modules = modules$children[[id]], reporter = reporter)
})

get_active_module <- reactive({
Expand All @@ -168,7 +167,7 @@ srv_nested_tabs.teal_modules <- function(id, datasets, modules) {
#' @rdname srv_nested_tabs
#' @export
#' @keywords internal
srv_nested_tabs.teal_module <- function(id, datasets, modules) {
srv_nested_tabs.teal_module <- function(id, datasets, modules, reporter) {
logger::log_trace(
paste(
"srv_nested_tabs.teal_module initializing the module with:",
Expand All @@ -179,16 +178,17 @@ srv_nested_tabs.teal_module <- function(id, datasets, modules) {

modules$server_args <- teal.transform::resolve_delayed(modules$server_args, datasets)
is_module_server <- isTRUE("id" %in% names(formals(modules$server)))

args <- c(list(id = id, datasets = datasets), modules$server_args)
if (modules$use_reporter) {
args <- c(args, list(reporter = reporter))
}

if (is_module_server) {
do.call(modules$server, c(list(id = id, datasets = datasets), modules$server_args))
do.call(modules$server, args)
} else {
do.call(
callModule,
c(
list(module = modules$server, id = id, datasets = datasets),
modules$server_args
)
)
args <- c(args, list(module = modules$server))
do.call(callModule, args)
}
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
reactive(modules)
}
4 changes: 2 additions & 2 deletions R/module_tabs_with_filters.R
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ ui_tabs_with_filters <- function(id, modules, datasets) {
#' details see [`teal.slice::FilteredData`].
#' @return `reactive` currently selected active_module
#' @keywords internal
srv_tabs_with_filters <- function(id, datasets, modules, filter) {
srv_tabs_with_filters <- function(id, datasets, modules, reporter, filter) {
stopifnot(is(datasets, "FilteredData"))
moduleServer(id, function(input, output, session) {
logger::log_trace(
"srv_tabs_with_filters initializing the module with datasets { paste(datasets$datanames(), collapse = ' ') }."
)
active_module <- srv_nested_tabs(id = "root", datasets = datasets, modules = modules)
active_module <- srv_nested_tabs(id = "root", datasets = datasets, modules = modules, reporter = reporter)

active_datanames <- eventReactive(
eventExpr = active_module(),
Expand Down
15 changes: 14 additions & 1 deletion R/module_teal.R
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ srv_teal <- function(id, modules, raw_data, filter = list()) {
datasets
})


reporter <- teal.reporter::Reporter$new()

if (use_reporter(modules)) {
modules <- append_module(modules, reporter_previewer_module())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This needs to be done before ui_tabs_with_filters (~ 20 lines below) so that the previewer ui is appended before being called

}

# Replace splash / welcome screen once data is loaded ----
# ignoreNULL to not trigger at the beginning when data is NULL
# just handle it once because data obtained through delayed loading should
Expand All @@ -209,7 +216,11 @@ srv_teal <- function(id, modules, raw_data, filter = list()) {
where = "beforeEnd",
# we put it into a div, so it can easily be removed as a whole, also when it is a tagList (and not
# just the first item of the tagList)
ui = div(ui_tabs_with_filters(session$ns("main_ui"), modules = modules, datasets = datasets_reactive())),
ui = div(ui_tabs_with_filters(
session$ns("main_ui"),
modules = modules,
datasets = datasets_reactive())
),
# needed so that the UI inputs are available and can be immediately updated, otherwise, updating may not
# have any effect as they are ignored when not present, see note in `module_add_filter_variable.R`
immediate = TRUE
Expand All @@ -218,13 +229,15 @@ srv_teal <- function(id, modules, raw_data, filter = list()) {
# switching filter to bookmarked state
if (!is.null(saved_datasets_state())) filter <- saved_datasets_state()


# must make sure that this is only executed once as modules assume their observers are only
# registered once (calling server functions twice would trigger observers twice each time)
# `once = TRUE` ensures this
active_module <- srv_tabs_with_filters(
id = "main_ui",
datasets = datasets_reactive(),
modules = modules,
reporter = reporter,
filter = filter
)
return(active_module)
Expand Down
29 changes: 28 additions & 1 deletion R/modules.R
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,32 @@ modules <- function(..., label = "root") {
}


append_module <- function(modules, module) {
# TODO validation
modules$children <- c(modules$children, list(module))
labels <- vapply(modules$children, function(submodule) submodule$label, character(1))
names(modules$children) <- make.unique(gsub("[^[:alnum:]]", "_", tolower(labels)), sep = "_")
Copy link
Contributor

Choose a reason for hiding this comment

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

In what capacity are the names of the modules used in teal?

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you plan on testing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My suspicion is it is to do with knowing which module is active so that a signal can be sent to the filter panel when they change. @gogonzo ?

Do you plan on testing this?

Erm, This is copied from the modules function we'll see

Copy link
Contributor Author

Choose a reason for hiding this comment

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

test written let me know if you want more

modules
}


use_reporter <- function(modules) {
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
UseMethod("use_reporter", modules)
}

use_reporter.default <- function(modules) {
stop("use_reporter function not implemented for this object")
}

use_reporter.teal_modules <- function(modules) {
any(unlist(lapply(modules$children, function(x) use_reporter(x))))
}

use_reporter.teal_module <- function(modules) {
modules$use_reporter
}


#' Deprecated: Creates the root modules container
#'
#' @description `r lifecycle::badge("deprecated")`
Expand Down Expand Up @@ -249,7 +275,8 @@ module <- function(label, server, ui, filters, server_args = NULL, ui_args = NUL
list(
label = label,
server = server, ui = ui, filters = filters,
server_args = server_args, ui_args = ui_args
server_args = server_args, ui_args = ui_args,
use_reporter = "reporter" %in% server_main_args
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
),
class = "teal_module"
)
Expand Down
17 changes: 17 additions & 0 deletions R/reporter_previewer_module.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#' @export
reporter_previewer_module <- function(label = "Report previewer") {

srv <- function(id, datasets, reporter, ...){
teal.reporter::reporter_previewer_srv(id, reporter, ...)
}

ui <- function(id, datasets, ...){
teal.reporter::reporter_previewer_ui(id, ...)
}

module(
label = label,
server = srv, ui = ui,
server_args = list(), ui_args = list(), filters = NULL
nikolas-burkoff marked this conversation as resolved.
Show resolved Hide resolved
)
}
8 changes: 4 additions & 4 deletions man/srv_nested_tabs.Rd

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

2 changes: 1 addition & 1 deletion man/srv_tabs_with_filters.Rd

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

3 changes: 3 additions & 0 deletions staged_dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ upstream_repos:
insightsengineering/teal.logger:
repo: insightsengineering/teal.logger
host: https://github.com
insightsengineering/teal.reporter:
repo: insightsengineering/teal.reporter
host: https://github.com
insightsengineering/scda:
repo: insightsengineering/scda
host: https://github.com
Expand Down