Skip to content

Commit c4afe54

Browse files
authored
Merge pull request #46 from Boehringer-Ingelheim/dev
Release 2.1.5
2 parents e8d0a2f + ca4b9d8 commit c4afe54

25 files changed

+658
-78
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
- ready_for_review
1111
branches:
1212
- main
13+
- dev
1314
push:
1415
branches:
1516
- main

DESCRIPTION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Package: dv.manager
22
Type: Package
33
Title: DaVinci Module Manager
4-
Version: 2.1.4
4+
Version: 2.1.5
55
Authors@R: c(person("Boehringer-Ingelheim Pharma GmbH & Co.KG", role = c("cph", "fnd")),
6-
person('Sorin', 'Voicu', email = 'sorin.voicu.ext@boehringer-ingelheim.com', role = c('aut')),
7-
person('Luis', 'Morís Fernández', email = 'luis.moris.fernandez@gmail.com', role = c('cre', 'aut')))
6+
person('Luis', 'Morís Fernández', email = 'luis.moris.fernandez@gmail.com', role = c('cre', 'aut')),
7+
person('Sorin', 'Voicu', email = 'sorin.voicu.ext@boehringer-ingelheim.com', role = c('aut')))
88
Description: DaVinci Module Manager.
99
License: Apache License (>= 2)
1010
Imports:

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export(log_use_log)
2020
export(mm_dispatch)
2121
export(mm_resolve_dispatcher)
2222
export(mod_simple)
23+
export(mod_simple2)
2324
export(run_app)
2425
export(simple_UI)
2526
export(simple_server)

NEWS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# dv.manager 2.1.5
2+
3+
- dv.manager dataset filters are now deactivated by default and can be activated by setting `enable_dataset_filter` parameter in `run_app`.
4+
- dv.manager filter hide/shows filters depending on the selected module.
5+
- Empty datasets can be included in the application again.
6+
- Fixed a bug that removed labels from column datasets when data was filtered.
7+
- Module names can no longer be an empty string `''`.
8+
19
# dv.manager 2.1.4
210

311
- Removes leftover title automatic capitalization.

R/aaaa_info_strings.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ TT <- local({
55
"Apply a filter to the dataset and use the resulting subject IDs (default) to consistently filter the rest of datasets."
66

77
DATASET_FILTER <-
8-
"Apply a filter to an specific dataset. Does not impact the rest of datasets."
8+
"Apply a filter to a specific dataset. Does not impact the rest of datasets. Only datasets that are used by the currently selected module are shown in this dataset."
99

1010
poc(
1111
SUBJECT_LEVEL_FILTER = SUBJECT_LEVEL_FILTER,

R/app_server.R

Lines changed: 117 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ app_server <- function(input = NULL, output = NULL, session = NULL) {
5151
"filter_data" = get_config("filter_data"),
5252
"filter_key" = get_config("filter_key"),
5353
"startup_msg" = get_config("startup_msg"),
54-
"reload_period" = get_config("reload_period")
54+
"reload_period" = get_config("reload_period"),
55+
"enable_dataset_filter" = get_config("enable_dataset_filter")
5556
)
5657

5758
app_server_(input, output, session, opts)
@@ -85,13 +86,15 @@ app_server_ <- function(input, output, session, opts) {
8586
)
8687

8788
module_server <- opts[["module_info"]][["server_list"]]
89+
module_meta <- opts[["module_info"]][["meta_list"]]
8890
module_names <- opts[["module_info"]][["module_name_list"]]
8991
module_hierarchy_list <- opts[["module_info"]][["hierarchy_list"]]
9092
data <- opts[["data"]]
9193
filter_data <- opts[["filter_data"]]
9294
filter_key <- opts[["filter_key"]]
9395
startup_msg <- opts[["startup_msg"]]
9496
reload_period <- opts[["reload_period"]]
97+
enable_dataset_filter <- opts[["enable_dataset_filter"]]
9598

9699
datasets_filters_info <- get_dataset_filters_info(data, filter_data)
97100

@@ -131,62 +134,120 @@ app_server_ <- function(input, output, session, opts) {
131134
shiny::reactive(unfiltered_dataset()[[filter_data]])
132135
)
133136

134-
dataset_filters <- local({
135-
l <- vector(mode = "list", length = length(datasets_filters_info))
136-
names(l) <- names(datasets_filters_info)
137-
for (idx in seq_along(datasets_filters_info)) {
138-
l[[idx]] <- local({
139-
curr_dataset_filter_info <- datasets_filters_info[[idx]]
140-
dv.filter::data_filter_server(
141-
curr_dataset_filter_info[["id"]],
142-
shiny::reactive({
143-
unfiltered_dataset()[[curr_dataset_filter_info[["name"]]]] %||% data.frame()
144-
})
145-
)
146-
})
147-
}
148137

149-
l
150-
})
138+
if (enable_dataset_filter) {
139+
log_inform("Dataset filter server")
140+
141+
dataset_filters <- local({
142+
l <- vector(mode = "list", length = length(datasets_filters_info))
143+
names(l) <- names(datasets_filters_info)
144+
for (idx in seq_along(datasets_filters_info)) {
145+
l[[idx]] <- local({
146+
curr_dataset_filter_info <- datasets_filters_info[[idx]]
147+
dv.filter::data_filter_server(
148+
curr_dataset_filter_info[["id"]],
149+
shiny::reactive({
150+
unfiltered_dataset()[[curr_dataset_filter_info[["name"]]]] %||% data.frame()
151+
})
152+
)
153+
})
154+
}
151155

152-
filtered_dataset <- shinymeta::metaReactive({
153-
# dv.filter returns a logical vector. This contemplates the case of empty lists
154-
shiny::req(is.logical(global_filtered_values()))
156+
l
157+
})
155158

156-
# Depend on all datasets
157-
purrr::walk(dataset_filters, ~ .x())
159+
filtered_dataset <- shinymeta::metaReactive({
160+
# dv.filter returns a logical vector. This contemplates the case of empty lists
161+
shiny::req(is.logical(global_filtered_values()))
158162

159-
# We do not react to changed in unfiltered dataset, otherwise when a dataset changes
160-
# We filter the previous dataset which in the best case produces and extra reactive beat
161-
# and in the worst case produces an error in (mvbc)
162-
# We don't want to control the error in (mvbc) because filtered dataset only changes when filter changes
163-
ufds <- shiny::isolate(unfiltered_dataset())
163+
# Depend on all datasets
164+
purrr::walk(dataset_filters, ~ .x())
164165

165-
curr_dataset_filters <- dataset_filters[intersect(names(dataset_filters), names(ufds))]
166+
# We do not react to changed in unfiltered dataset, otherwise when a dataset changes
167+
# We filter the previous dataset which in the best case produces and extra reactive beat
168+
# and in the worst case produces an error in (mvbc)
169+
# We don't want to control the error in (mvbc) because filtered dataset only changes when filter changes
170+
ufds <- shiny::isolate(unfiltered_dataset())
166171

167-
# Current dataset must be logical with length above 0
168-
# Check dataset filters check all datafilters are initialized
169-
purrr::walk(curr_dataset_filters, ~ shiny::req(checkmate::test_logical(.x(), min.len = 1)))
172+
curr_dataset_filters <- dataset_filters[intersect(names(dataset_filters), names(ufds))]
170173

171-
filtered_key_values <- ufds[[filter_data]][[filter_key]][global_filtered_values()]
174+
# Current dataset must be logical with length above 0
175+
# Check dataset filters check all datafilters are initialized
176+
purrr::walk(curr_dataset_filters, ~ shiny::req(checkmate::test_logical(.x(), min.len = 0)))
172177

173-
fds <- ufds
178+
filtered_key_values <- ufds[[filter_data]][[filter_key]][global_filtered_values()]
174179

175-
# Single dataset filtering
176-
fds[names(curr_dataset_filters)] <- purrr::imap(
177-
fds[names(curr_dataset_filters)],
178-
function(val, nm) {
179-
# (mvbc)
180-
fds[[nm]][dataset_filters[[nm]](), , drop = FALSE]
181-
}
182-
)
180+
fds <- ufds
183181

184-
# Global dataset filtering
185-
global_filtered <- purrr::map(
186-
fds,
187-
~ dplyr::filter(.x, .data[[filter_key]] %in% filtered_key_values) # nolint
182+
# Single dataset filtering
183+
fds[names(curr_dataset_filters)] <- purrr::imap(
184+
fds[names(curr_dataset_filters)],
185+
function(val, nm) {
186+
# (mvbc)
187+
labels <- get_lbls(fds[[nm]])
188+
current_fds <- fds[[nm]][dataset_filters[[nm]](), , drop = FALSE]
189+
set_lbls(current_fds, labels)
190+
}
191+
)
192+
193+
# Global dataset filtering
194+
global_filtered <- purrr::map(
195+
fds, function(current_ds) {
196+
mask <- current_ds[[filter_key]] %in% filtered_key_values
197+
labels <- get_lbls(current_ds)
198+
current_ds <- current_ds[mask, , drop = FALSE]
199+
set_lbls(current_ds, labels)
200+
}
201+
)
202+
})
203+
204+
tab_ids <- c("__tabset_0__", names(opts[["module_info"]][["tab_group_names"]]))
205+
shiny::observeEvent(
206+
{
207+
purrr::map(tab_ids, ~ input[[.x]])
208+
},
209+
{
210+
current_tab <- "__tabset_0__"
211+
zero_tabs <- length(input[["__tabset_0__"]]) == 0
212+
if (!zero_tabs) {
213+
while (!current_tab %in% opts[["module_info"]][["module_id_list"]]) {
214+
current_tab <- input[[current_tab]]
215+
}
216+
}
217+
218+
used_ds <- used_datasets[[current_tab]]
219+
all_nm <- names(datasets_filters_info)
220+
if (!zero_tabs && !is.null(used_ds)) {
221+
used_nm <- intersect(used_datasets[[current_tab]], names(datasets_filters_info))
222+
unused_nm <- setdiff(all_nm, used_nm)
223+
} else {
224+
used_nm <- all_nm
225+
unused_nm <- character(0)
226+
}
227+
228+
for (nm in unused_nm) {
229+
shinyjs::hide(datasets_filters_info[[nm]][["id_cont"]])
230+
}
231+
232+
for (nm in used_nm) {
233+
shinyjs::show(datasets_filters_info[[nm]][["id_cont"]])
234+
}
235+
}
188236
)
189-
})
237+
} else {
238+
log_inform("Single filter server")
239+
240+
filtered_dataset <- shinymeta::metaReactive({
241+
# dv.filter returns a logical vector. This contemplates the case of empty lists
242+
shiny::req(is.logical(global_filtered_values()))
243+
log_inform("New filter applied")
244+
filtered_key_values <- unfiltered_dataset()[[filter_data]][[filter_key]][global_filtered_values()] # nolint
245+
purrr::map(
246+
unfiltered_dataset(),
247+
~ dplyr::filter(.x, .data[[filter_key]] %in% filtered_key_values) # nolint
248+
)
249+
})
250+
}
190251

191252
# Prepare module_output argument
192253
module_output_env <- rlang::current_env()
@@ -257,11 +318,20 @@ app_server_ <- function(input, output, session, opts) {
257318
)
258319
)
259320

321+
used_datasets <- list()
322+
260323
module_output <- list()
261324
for (srv in module_server) {
262-
module_output[[srv[["module_id"]]]] <- srv[["server"]](module_args)
325+
mod_id <- srv[["module_id"]]
326+
srv_fun <- srv[["server"]]
327+
328+
module_output[[mod_id]] <- srv_fun(module_args)
329+
used_datasets[[mod_id]] <- module_meta[[mod_id]][["meta"]][["dataset_info"]][["all"]]
263330
}
264331

332+
333+
334+
265335
#### Report modal
266336

267337
# REPORT IS DEACTIVATED

R/app_ui.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ app_ui <- function(request_id) {
2525
data <- get_config("data")
2626
module_info <- get_config("module_info")
2727
filter_data <- get_config("filter_data")
28+
enable_dataset_filter <- get_config("enable_dataset_filter")
2829

2930
log_inform("Initializing HTML template UI")
3031
log_inform(glue::glue("Available modules (N): {length(module_info[[\"ui_list\"]])}"))
@@ -71,7 +72,8 @@ app_ui <- function(request_id) {
7172
dv.filter::data_filter_ui(ns("global_filter"))
7273
)
7374
),
74-
shiny::div(
75+
if (enable_dataset_filter) {
76+
shiny::div(
7577
class = "c-well shiny_filter",
7678
shiny::tags$label(
7779
"Dataset Filter(s)",
@@ -80,6 +82,7 @@ app_ui <- function(request_id) {
8082
),
8183
dataset_filters_ui
8284
)
85+
}
8386
)
8487
)
8588

R/checker.R

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@ check_resolved_modules <- function(resolved_module_list) {
44
log_warn(msg)
55
}
66

7+
if (!all(is.character(resolved_module_list[["module_id_list"]]))) {
8+
msg <- "module_list has at least one module_id that is not of type character"
9+
rlang::abort(msg)
10+
}
11+
712
if (any(duplicated(resolved_module_list[["module_id_list"]]))) {
813
msg <- "module_list has repeated module_ids"
914
rlang::abort(msg)
1015
}
1116

17+
if (any(nchar(resolved_module_list[["module_id_list"]]) == 0)) {
18+
msg <- "module ids must have at least one character"
19+
rlang::abort(msg)
20+
}
21+
1222
if (any(duplicated(resolved_module_list[["module_name_list"]]))) {
1323
msg <- "module_list has repeated module_names"
1424
rlang::abort(msg)

R/run_app.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#' externally.
2727
#' @param reload_period Either a lubridate object to specify a duration
2828
#' or a positive numeric value which is then interpreted as a lubridate duration object in days. By default NULL
29+
#' @param enable_dataset_filter A boolean flag indicating if dataset filters are enabled. The default value is FALSE.
2930
#' @param .launch by default it should always be TRUE. It should only be false for debugging and testing.
3031
#' When TRUE it will return the app. When FALSE it will return the options with which the app will be launched.
3132
#' @inheritParams shiny::shinyApp
@@ -47,6 +48,7 @@ run_app <- function(data = NULL,
4748
azure_options = NULL,
4849
reload_period = NULL,
4950
enableBookmarking = "server", # nolint
51+
enable_dataset_filter = FALSE,
5052
.launch = TRUE) {
5153
check_deprecated_calls(filter_data)
5254

@@ -68,6 +70,7 @@ run_app <- function(data = NULL,
6870
config[["startup_msg"]] <- check_startup_msg(startup_msg)
6971
config[["title"]] <- title
7072
config[["reload_period"]] <- get_reload_period(check_reload_period(reload_period))
73+
config[["enable_dataset_filter"]] <- enable_dataset_filter
7174

7275
check_meta_mtime_attribute(data)
7376

R/tab_group.R

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ resolve_tab_group <- function(x, nm, hierarchy, tab_group_count, nested_hierarch
112112
list(
113113
ui_list = r[["ui_list"]],
114114
server_list = r[["server_list"]],
115+
meta_list = r[["meta_list"]],
115116
module_id_list = r[["module_id_list"]],
116117
module_name_list = r[["module_name_list"]],
117118
tab_label_list = r[["tab_label_list"]],
@@ -132,12 +133,17 @@ resolve_plain <- function(x, nm, hierarchy, nested_hierarchy) {
132133
)
133134

134135
server_list <- list()
135-
136136
server_list[[x[["module_id"]]]] <- list(
137137
server = x[["server"]],
138138
module_id = x[["module_id"]]
139139
)
140140

141+
meta_list <- list()
142+
meta_list[[x[["module_id"]]]] <- list(
143+
meta = x[["meta"]],
144+
module_id = x[["module_id"]]
145+
)
146+
141147
module_id_list <- character(0)
142148
module_id_list[[nm]] <- x[["module_id"]]
143149

@@ -155,6 +161,7 @@ resolve_plain <- function(x, nm, hierarchy, nested_hierarchy) {
155161
r <- list(
156162
ui_list = ui_list,
157163
server_list = server_list,
164+
meta_list = meta_list,
158165
module_id_list = module_id_list,
159166
module_name_list = module_name_list,
160167
hierarchy_list = hierarchy_list,
@@ -173,6 +180,7 @@ resolve_module_list <- function(
173180
)) {
174181
server_list <- list()
175182
ui_list <- list()
183+
meta_list <- list()
176184
module_id_list <- character(0)
177185
module_name_list <- character(0)
178186
tab_group_names <- character(0)
@@ -193,6 +201,7 @@ resolve_module_list <- function(
193201
ui_list <- c(ui_list, r[["ui_list"]])
194202
module_id_list <- c(module_id_list, r[["module_id_list"]])
195203
server_list <- c(server_list, r[["server_list"]])
204+
meta_list <- c(meta_list, r[["meta_list"]])
196205
module_name_list <- c(module_name_list, r[["module_name_list"]])
197206
hierarchy_list <- c(hierarchy_list, r[["hierarchy_list"]])
198207
tab_group_names <- c(tab_group_names, r[["tab_group_names"]])
@@ -202,6 +211,7 @@ resolve_module_list <- function(
202211
res <- list(
203212
ui_list = ui_list,
204213
server_list = server_list,
214+
meta_list = meta_list,
205215
module_id_list = module_id_list,
206216
module_name_list = module_name_list,
207217
hierarchy_list = hierarchy_list,

0 commit comments

Comments
 (0)