Skip to content

Commit bf40393

Browse files
authored
datanames slot in teal_transform_module (ignore @datanames) (#1334)
ignore `datanames(data)`
1 parent 0812f26 commit bf40393

23 files changed

+278
-255
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export(modules)
2828
export(new_tdata)
2929
export(report_card_template)
3030
export(reporter_previewer_module)
31+
export(set_datanames)
3132
export(show_rcode_modal)
3233
export(srv_teal)
3334
export(srv_teal_with_splash)

NEWS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
* Introduced `teal_transform_module` to provide a way to interactively modify data delivered to `teal_module`'s `server`. #1228
77
* Introduced a new argument `once = FALSE` in `teal_data_module` to possibly reload data during a run time.
88
* Possibility to download lockfile to restore app session for reproducibility. #479
9-
9+
* Introduced a function `set_datanames()` to change a `datanames` of the `teal_module`.
10+
* Datasets which name starts with `.` are ignored when `module`'s `datanames` is set as `"all"`.
1011

1112
### Breaking changes
1213

14+
* Setting `datanames()` on `data` passed to teal application no longer has effect. In order to change `teal_module`'s
15+
`datanames` one should modify `module$datanames`.
1316
* The `landing_popup_module()` needs to be passed as the `landing_popup` argument of `init` instead of being passed as a module of the `modules` argument of `init`.
1417
* `teal` no longer re-export `%>%`. Please load `library(magrittr)` instead or use `|>` from `base`.
1518

R/dummy_functions.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ example_module <- function(label = "example teal module", datanames = "all", tra
2121
checkmate::assert_class(isolate(data()), "teal_data")
2222
moduleServer(id, function(input, output, session) {
2323
datanames_rv <- reactive({
24-
teal.data::datanames(req(data()))
24+
.teal_data_ls(req(data()))
2525
})
2626

2727
observeEvent(datanames_rv(), {

R/init.R

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,16 @@ init <- function(data,
210210

211211
## `data` - `modules`
212212
if (inherits(data, "teal_data")) {
213-
if (length(.teal_data_datanames(data)) == 0) {
213+
if (length(.teal_data_ls(data)) == 0) {
214214
stop("The environment of `data` is empty.")
215215
}
216216

217-
if (!length(teal.data::datanames(data))) {
218-
warning("`data` object has no datanames. Default datanames are set using `teal_data`'s environment.")
219-
}
220-
221-
is_modules_ok <- check_modules_datanames(modules, .teal_data_datanames(data))
217+
is_modules_ok <- check_modules_datanames(modules, .teal_data_ls(data))
222218
if (!isTRUE(is_modules_ok) && length(unlist(extract_transformers(modules))) == 0) {
223219
lapply(is_modules_ok$string, warning, call. = FALSE)
224220
}
225221

226-
is_filter_ok <- check_filter_datanames(filter, .teal_data_datanames(data))
222+
is_filter_ok <- check_filter_datanames(filter, .teal_data_ls(data))
227223
if (!isTRUE(is_filter_ok)) {
228224
warning(is_filter_ok)
229225
# we allow app to continue if applied filters are outside

R/module_data_summary.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ srv_data_summary <- function(id, teal_data) {
6363
summary_table <- reactive({
6464
req(inherits(teal_data(), "teal_data"))
6565

66-
if (length(teal.data::datanames(teal_data())) == 0) {
66+
if (!length(.teal_data_ls(teal_data()))) {
6767
return(NULL)
6868
}
6969

R/module_filter_data.R

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,25 @@ ui_filter_data <- function(id) {
2727
srv_filter_data <- function(id, datasets, active_datanames, data_rv, is_active) {
2828
assert_reactive(datasets)
2929
moduleServer(id, function(input, output, session) {
30+
active_corrected <- reactive(intersect(active_datanames(), datasets()$datanames()))
31+
3032
output$panel <- renderUI({
3133
req(inherits(datasets(), "FilteredData"))
3234
isolate({
3335
# render will be triggered only when FilteredData object changes (not when filters change)
3436
# technically it means that teal_data_module needs to be refreshed
3537
logger::log_debug("srv_filter_panel rendering filter panel.")
36-
if (length(active_datanames())) {
37-
datasets()$srv_active("filters", active_datanames = active_datanames)
38-
# todo: make sure to bump the `teal.slice` version. Please use the branch `669_insertUI@main` in `teal.slice`.
39-
datasets()$ui_active(session$ns("filters"), active_datanames = active_datanames)
38+
if (length(active_corrected())) {
39+
datasets()$srv_active("filters", active_datanames = active_corrected)
40+
datasets()$ui_active(session$ns("filters"), active_datanames = active_corrected)
4041
}
4142
})
4243
})
4344

44-
trigger_data <- .observe_active_filter_changed(datasets, is_active, active_datanames, data_rv)
45+
trigger_data <- .observe_active_filter_changed(datasets, is_active, active_corrected, data_rv)
4546

4647
eventReactive(trigger_data(), {
47-
.make_filtered_teal_data(modules, data = data_rv(), datasets = datasets(), datanames = active_datanames())
48+
.make_filtered_teal_data(modules, data = data_rv(), datasets = datasets(), datanames = active_corrected())
4849
})
4950
})
5051
}

R/module_init_data.R

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ srv_init_data <- function(id, data, modules, filter = teal_slices()) {
107107
)
108108
}
109109

110-
is_filter_ok <- check_filter_datanames(filter, .teal_data_datanames(data_validated()))
110+
is_filter_ok <- check_filter_datanames(filter, .teal_data_ls(data_validated()))
111111
if (!isTRUE(is_filter_ok)) {
112112
showNotification(
113113
"Some filters were not applied because of incompatibility with data. Contact app developer.",
@@ -160,7 +160,6 @@ srv_init_data <- function(id, data, modules, filter = teal_slices()) {
160160
)
161161

162162
tdata@verified <- data@verified
163-
teal.data::datanames(tdata) <- teal.data::datanames(data)
164163
tdata
165164
}
166165

@@ -172,8 +171,7 @@ srv_init_data <- function(id, data, modules, filter = teal_slices()) {
172171
#' @return A character vector with the code lines.
173172
#' @keywords internal
174173
#'
175-
.get_hashes_code <- function(data, datanames = .teal_data_datanames(data)) {
176-
# todo: this should be based on data_rv object not on datasets
174+
.get_hashes_code <- function(data, datanames = .teal_data_ls(data)) {
177175
vapply(
178176
datanames,
179177
function(dataname, datasets) {

R/module_nested_tabs.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ srv_teal_module.teal_module <- function(id,
301301
.resolve_module_datanames <- function(data, modules) {
302302
stopifnot("data_rv must be teal_data object." = inherits(data, "teal_data"))
303303
if (is.null(modules$datanames) || identical(modules$datanames, "all")) {
304-
.teal_data_datanames(data)
304+
.teal_data_ls(data)
305305
} else {
306306
intersect(
307307
include_parent_datanames(modules$datanames, teal.data::join_keys(data)),

R/modules.R

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
setOldClass("teal_module")
2+
setOldClass("teal_modules")
3+
14
#' Create `teal_module` and `teal_modules` objects
25
#'
36
#' @description
@@ -39,25 +42,40 @@
3942
#' - `...` (optional) When provided, `ui_args` elements will be passed to the module named argument
4043
#' or to the `...`.
4144
#' @param filters (`character`) Deprecated. Use `datanames` instead.
42-
#' @param datanames (`character`) A vector with `datanames` that are relevant for the item. The
43-
#' filter panel will automatically update the shown filters to include only
44-
#' filters in the listed datasets. `NULL` will hide the filter panel,
45-
#' and the keyword `"all"` will show filters of all datasets. `datanames` also determines
46-
#' a subset of datasets which are appended to the `data` argument in server function.
45+
#' @param datanames (`character`) Names of the datasets that are relevant for the item.
46+
#' The keyword `"all"` provides all datasets available in `data` passed to `teal` application.
47+
#' `NULL` will hide the filter panel.
4748
#' @param server_args (named `list`) with additional arguments passed on to the server function.
4849
#' @param ui_args (named `list`) with additional arguments passed on to the UI function.
4950
#' @param x (`teal_module` or `teal_modules`) Object to format/print.
5051
#' @param indent (`integer(1)`) Indention level; each nested element is indented one level more.
5152
#' @param transformers (`list` of `teal_data_module`) that will be applied to transform the data.
5253
#' Each transform module UI will appear in the `teal` application, unless the `custom_ui` attribute is set on the list.
53-
#' If so, the module developer is responsible to display the UI in the module itself.
54+
#' If so, the module developer is responsible to display the UI in the module itself. `datanames` of the `transformers`
55+
#' will be added to the `datanames`.
5456
#'
5557
#' When the transformation does not have sufficient input data, the resulting data will fallback
5658
#' to the last successful transform or, in case there are none, to the filtered data.
5759
#' @param ...
5860
#' - For `modules()`: (`teal_module` or `teal_modules`) Objects to wrap into a tab.
5961
#' - For `format()` and `print()`: Arguments passed to other methods.
6062
#'
63+
#' @section `datanames`:
64+
#' The module's `datanames` argument determines a subset of datasets from the `data` object, as specified in the
65+
#' server function argument, to be presented in the module. Datasets displayed in the filter panel will be limited
66+
#' to this subset.
67+
#' When `datanames` is set to `"all"`, all available datasets in the `data` object are considered relevant for the
68+
#' module. However, setting `datanames` argument to `"all"` might include datasets that are irrelevant for the module,
69+
#' for example:
70+
#' - Proxy variables used for modifying columns.
71+
#' - Modified copies of datasets used to create a final dataset.
72+
#' - Connection objects.
73+
#' To prevent these irrelevant datasets from appearing in the module, use the [set_datanames()] function on the
74+
#' [module] or [modules()] to change the `datanames` from `"all"` to specific dataset names. Attempting to change
75+
#' `datanames` values that was not set to `"all"` using [set_datanames()] will be ignored with a warning.
76+
#'
77+
#' Additionally, datasets with names starting with `.` are ignored when `datanames` is set to `"all"`.
78+
#'
6179
#' @return
6280
#' `module()` returns an object of class `teal_module`.
6381
#'
@@ -127,7 +145,7 @@
127145
#' @export
128146
#'
129147
module <- function(label = "module",
130-
server = function(id, ...) moduleServer(id, function(input, output, session) NULL),
148+
server = function(id, data, ...) moduleServer(id, function(input, output, session) NULL),
131149
ui = function(id, ...) tags$p(paste0("This module has no UI (id: ", id, " )")),
132150
filters,
133151
datanames = "all",
@@ -241,14 +259,23 @@ module <- function(label = "module",
241259
}
242260

243261
## `transformers`
244-
checkmate::assert_list(transformers, types = "teal_data_module")
262+
if (inherits(transformers, "teal_transform_module")) {
263+
transformers <- list(transformers)
264+
}
265+
checkmate::assert_list(transformers, types = "teal_transform_module")
266+
transformer_datanames <- unlist(lapply(transformers, attr, "datanames"))
267+
combined_datanames <- if (identical(datanames, "all") || identical(transformer_datanames, "all")) {
268+
"all"
269+
} else {
270+
union(datanames, transformer_datanames)
271+
}
245272

246273
structure(
247274
list(
248275
label = label,
249276
server = server,
250277
ui = ui,
251-
datanames = unique(datanames),
278+
datanames = combined_datanames,
252279
server_args = server_args,
253280
ui_args = ui_args,
254281
transformers = transformers
@@ -313,6 +340,38 @@ format.teal_modules <- function(x, indent = 0, ...) {
313340
)
314341
}
315342

343+
#' @param modules (`teal_module` or `teal_modules`)
344+
#' @rdname teal_modules
345+
#' @examples
346+
#' # change the module's datanames
347+
#' set_datanames(module(datanames = "all"), "a")
348+
#'
349+
#' # change modules' datanames
350+
#' set_datanames(
351+
#' modules(
352+
#' module(datanames = "all"),
353+
#' module(datanames = "a")
354+
#' ),
355+
#' "b"
356+
#' )
357+
#' @export
358+
set_datanames <- function(modules, datanames) {
359+
checkmate::assert_multi_class(modules, c("teal_modules", "teal_module"))
360+
if (inherits(modules, "teal_modules")) {
361+
modules$children <- lapply(modules$children, set_datanames, datanames)
362+
} else {
363+
if (identical(modules$datanames, "all")) {
364+
modules$datanames <- datanames
365+
} else {
366+
warning(
367+
"Not possible to modify datanames of the module ", modules$label,
368+
". set_datanames() can only change datanames if it was set to \"all\".",
369+
call. = FALSE
370+
)
371+
}
372+
}
373+
modules
374+
}
316375

317376
#' @rdname teal_modules
318377
#' @export

R/reporter_previewer_module.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ reporter_previewer_module <- function(label = "Report previewer", server_args =
4141
)
4242
# Module is created with a placeholder label and the label is changed later.
4343
# This is to prevent another module being labeled "Report previewer".
44-
class(module) <- c("teal_module_previewer", class(module))
44+
class(module) <- c(class(module), "teal_module_previewer")
4545
module$label <- label
4646
attr(module, "teal_bookmarkable") <- TRUE
4747
module

0 commit comments

Comments
 (0)