-
-
Notifications
You must be signed in to change notification settings - Fork 13
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
introduce decorators for tm_missing_data
#809
introduce decorators for tm_missing_data
#809
Conversation
…1187_decorate_output@main
tm_missing_data
tm_missing_data
This PR contains specific case where there is multiple outputs. We need to think whether we expose N decorators for N outputs, or we expose one decorator parameter and make user to put |
R/tm_missing_data.R
Outdated
|
||
|
||
decorated_summary_plot_q <- srv_transform_teal_data(id = "decorator", data = summary_plot_q, transformators = decorators) | ||
decorated_summary_plot_grob_q <- reactive({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
R/tm_missing_data.R
Outdated
@@ -1029,7 +1053,26 @@ srv_missing_data <- function(id, data, reporter, filter_panel_api, dataname, par | |||
) | |||
}) | |||
|
|||
combination_plot_r <- reactive(combination_plot_q()[["g"]]) | |||
decorated_combination_plot_q <- srv_transform_teal_data(id = "decorator", data = combination_plot_q, transformators = decorators) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@m7pr I converted this PR to the new srv_transform_teal_data
Thanks @averissimo for some updates. unable to find an inherited method for function ‘eval_code’ for signature ‘object = "NULL", code = "{"’ |
…1187_decorate_output@main
I think my example had an issue in the decorator. I should use if (exists('combination_plot_top')) {
combination_plot_top <- combination_plot_top + ggplot2::labs(caption = footnote_str)
} instead if (exists(combination_plot_top)) {
combination_plot_top <- combination_plot_top + ggplot2::labs(caption = footnote_str)
} |
Ok, I updated the example from the opening comment of this PR. Now it's ready to be merged |
There is a problem with this module when it has more than 1 decorator. It doesn't appear in the UI, but an error is thrown on the console. I was investigating this, but couldn't understand last Friday It is especially troubling as:
# tm_missing_data
pkgload::load_all("../teal")
pkgload::load_all(".")
footnote_dec <- teal_transform_module(
label = "Footnote",
ui = function(id) shiny::textInput(shiny::NS(id, "footnote"), "Footnote for Combination Plot", value = "I am a good decorator"),
server = function(id, data) {
moduleServer(id, function(input, output, session) {
logger::log_info("🟢 Footnote called to action!", namespace = "teal.modules.general")
reactive(
within(data(), {
# footnote_str <- footnote
# logger::log_info("🟢 {ls() |> paste(collapse = ', ')}", namespace = "teal.modules.general")
# if (exists("combination_plot_top")) {
# combination_plot_top <- combination_plot_top + ggplot2::labs(caption = paste0(footnote_str, "1"))
# }
# if (exists("combination_plot_bottom")) {
# combination_plot_bottom <- combination_plot_bottom + ggplot2::labs(caption = paste0(footnote_str, "2"))
# }
# if (exists("summary_plot_top")) {
# summary_plot_top <- summary_plot_top + ggplot2::labs(caption = paste0(footnote_str, "3"))
# }
# if (exists("summary_plot_bottom")) {
# summary_plot_bottom <- summary_plot_bottom + ggplot2::labs(caption = paste0(footnote_str, "4"))
# }
# if (exists("by_subject_plot")) {
# by_subject_plot <- by_subject_plot + ggplot2::labs(caption = paste0(footnote_str, "5"))
# }
}, footnote = input$footnote)
)
})
}
)
custom_table_decorator_interactive <- teal_transform_module(
ui = function(id) {
ns <- NS(id)
div(
selectInput(
ns("style"),
"Table Style",
choices = c("Default", "Striped", "Hover"),
selected = "Default"
)
)
},
server = function(id, data) {
moduleServer(id, function(input, output, session) {
reactive({
req(data(), input$style)
within(data(), {
# if (exists("table")) {
# style_str <- style
# logger::log_fatal("has table!! {style_str}", namespace = "teal.modules.general")
# if (style_str == "Striped") {
# table <- DT::formatStyle(
# table,
# columns = attr(table$x, "colnames")[-1],
# target = 'row',
# backgroundColor = '#f9f9f9'
# )
# } else if (style_str == "Hover") {
# table <- DT::formatStyle(
# table,
# columns = attr(table$x, "colnames")[-1],
# target = 'row',
# backgroundColor = '#f0f0f0'
# )
# }
# }
}, style = input$style)
})
})
}
)
# CDISC example data
data <- teal_data()
data <- within(data, {
require(nestcolor)
ADSL <- rADSL
ADRS <- rADRS
})
join_keys(data) <- default_cdisc_join_keys[names(data)]
app <- init(
data = data,
modules = modules(
tm_missing_data(decorators = list(footnote_dec, custom_table_decorator_interactive))
# tm_missing_data()
)
)
if (interactive()) {
shinyApp(app$ui, app$server)
} |
#' @return A flat list with all decorators to include. | ||
#' It can be an empty list if none of the scope exists in `decorators` argument. | ||
#' @keywords internal | ||
subset_decorators <- function(scope, decorators) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After A LOT of debugging I solved the issue on this module and I was rethinking our decision on relying on the same decorators for all "outputs".
I'm proposing we allow 3 types of values in decorators
argument (similar to the initial code from a week and half ago):
list
ofteal_transform_module
(keep current list-like approach)- Named
list
that can allow for customizationslist(default = list(...))
is protected and applies to alllist(summary_plot = list(...))
only applies decorator forsummary_plot
- Also allow named
list
ofteal_transform_module
We could limit to just 1.
and 2.
, or even just 2.
. WDYT?
Why?
It seems odd to have all UIs on tm_missing_data
, in particular, having plot-like decorators UI that do nothing on a table output.
Note: the PR also extracts the qenv
generation from the main shiny module into smaller and logic-only modules. I opted for using modules instead of just passing input
to keep with good Shiny practices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@averissimo yeah, so I think we could meet and rethink. I actually am having still various thoughs on how we should to it, depending on how the module is built. I think the named list of decorators would be the most appriopiate. I wonder how that changes the server logic.
Thanks for working on this module and having this fixed
@@ -381,25 +409,30 @@ encoding_missing_data <- function(id, summary_per_patient = FALSE, ggtheme, data | |||
), | |||
value = FALSE | |||
) | |||
} | |||
}, | |||
ui_decorate_teal_data(ns("dec_summary_plot"), decorators = subset_decorators("summary_plot", decorators)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subset_decorators("summary_plot", decorators)
will return all from default
plus the summary_plot
related.
We can use either the names of the objects, or more generic ones
if (checkmate::test_list(decorators, "teal_transform_module", null.ok = TRUE)) { | ||
decorators <- if (checkmate::test_names(names(decorators), subset.of = c("default", available_decorators))) { | ||
lapply(decorators, list) | ||
} else { | ||
list(default = decorators) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conversion of decorators
object if it is a flat list of teal_transform_module
, it will preserve current behavior.
…1187_decorate_output@main
Part of insightsengineering/teal#1370
Updated working example
Old ~Working~ Example