Skip to content

Conversation

@averissimo
Copy link
Contributor

@averissimo averissimo commented Nov 5, 2025

Pull Request

Thanks to @StefanThoma's for working on the first prototype

Changes description

  • Adds rmarkdown module
  • Renders the output to module UI and to Reporter
  • Source code is not verified as it adds a comment on how to render it
  • Adds download button to get the original Rmd file
    • Option in module to enable or disable this functionality
    • downloaded Rmd has module's data included (data pre-processing + filter)
  • Uses extra_transform parameter to add "generic decorators" to the top of the UI
    • name is temporary
  • Ensure figures are displayed properly in reporter (PDF output)
  • Avoid encoding images to base64 (mayb keep it in raw or equivalent)

To discuss

  • Should we render the .R to get all the R code from the report and add it to the code of the qenv?
  • [limitation] Use of markdown when rendering doesn't print title nor author
    • Rendering it on the page breaks teal
    • Wrapping in iframe doesn't extend full height and then creates strange reports
  • Should we use transformers to add extra input / data manipulation
    • Or keep a parameters that allows to add transforms (for example extra inputs) to the module by the app developer

(topics below added from conversation with @gogonzo )

  • should teal_report contain markdown elements?
  • should teal_data evaluate rmarkdown::render() and include this to @code
  • should markdown be evaluated with rmarkdown::render(envir = <qenv>) instead of params = list()?
    • visibility concern here on developing the Rmd

App (same 2nd one in example, but with download = TRUE)

pkgload::load_all("../teal.modules.general")

data <- teal_data()
data <- within(data, {
  CO2 <- CO2
  CO2[["primary_key"]] <- seq_len(nrow(CO2))
})
join_keys(data) <- join_keys(join_key("CO2", "CO2", "primary_key"))

static_decorator <- teal_transform_module(
  label = "N Cols selector",
  ui = function(id) {
    ns <- NS(id)
    tags$div(
      numericInput(ns("n_rows"), "Show n rows", value = 5, min = 0, max = 200, step = 5)
    )
  },
  server = function(id, data) {
    moduleServer(id, function(input, output, session) {
      reactive({
        req(data())
        within(data(), {
          n_rows <- n_rows_value
        }, n_rows_value = input$n_rows)
      })
    })
  }
)

app <- init(
  data = data,
  modules = modules(
    tm_rmarkdown(
      label = "RMarkdown Module",
      rmd_content = readLines(system.file(file.path("sample_files", "co2_example.Rmd"), package = "teal.modules.general")),
      allow_download = TRUE,
      extra_transform = list(static_decorator)
    )
  )
) |> shiny::runApp()

@averissimo averissimo added the core label Nov 5, 2025
@gogonzo gogonzo self-assigned this Nov 6, 2025
@averissimo averissimo marked this pull request as ready for review November 6, 2025 12:59
@averissimo
Copy link
Contributor Author

Marked as ready to review to start the discussion

@github-actions
Copy link
Contributor

github-actions bot commented Nov 6, 2025

badge

Code Coverage Summary

Filename                      Stmts    Miss  Cover    Missing
--------------------------  -------  ------  -------  -------------------------------------------
R/tm_a_pca.R                    864     864  0.00%    141-1132
R/tm_a_regression.R             751     751  0.00%    180-1027
R/tm_data_table.R               200     200  0.00%    100-348
R/tm_file_viewer.R              172     172  0.00%    47-254
R/tm_front_page.R               143     132  7.69%    77-246
R/tm_g_association.R            320     320  0.00%    161-547
R/tm_g_bivariate.R              664     406  38.86%   332-786, 827, 932, 949, 967, 978-1000
R/tm_g_distribution.R          1106    1106  0.00%    156-1404
R/tm_g_response.R               345     345  0.00%    179-594
R/tm_g_scatterplot.R            709     709  0.00%    261-1065
R/tm_g_scatterplotmatrix.R      272     253  6.99%    200-501, 562, 576
R/tm_missing_data.R            1080    1080  0.00%    124-1380
R/tm_outliers.R                1029    1029  0.00%    162-1341
R/tm_rmarkdown.R                154      68  55.84%   144-196, 225-240, 284-285, 345-368
R/tm_t_crosstable.R             263     263  0.00%    177-482
R/tm_variable_browser.R         887     881  0.68%    89-1113, 1164-1347
R/utils.R                       185     120  35.14%   87-250, 279-305, 317-326, 331, 345-364, 453
R/zzz.R                           2       2  0.00%    2-3
TOTAL                          9146    8701  4.87%

Diff against main

Filename            Stmts    Miss  Cover
----------------  -------  ------  -------
R/tm_rmarkdown.R     +154     +68  +55.84%
TOTAL                +154     +68  +0.87%

Results for commit: d2df067

Minimum allowed coverage is 80%

♻️ This comment has been updated with latest results

Copy link
Contributor

@gogonzo gogonzo left a comment

Choose a reason for hiding this comment

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

Shouldn't both documets be reproducible?

  • document downloaded from tm_rmarkdown
  • document downloaded via reporter

@gogonzo
Copy link
Contributor

gogonzo commented Nov 6, 2025

Key questions:

  1. What app-user should be able to download in tm_markdown
  • Should this document be reproducible and contain pre-processing, filter-panel and transformator code? Should this document contain outputs?
  • I don't think that app-user should receive the same file as app-developer provides do the tm_markdown. app-developer uses rmd file just as a template to handle data, produce outputs (plots and tables) and produce final document by specifying document: html_document/md_document/etc.. App-user thought receives document which content is controlled by app-developer - this could be markdown file containing/not containing code-chunks, html-file, pdf file etc.
  1. What should be added to the teal_card (reporter)
  • html/md content as single teal_card element?
  • md content converted to teal_card elements (multiple elements)?
  • rmarkdown::render() call (this is a joke - markdown::render inside of markdown file would be crazy)
  • nothing

@StefanThoma
Copy link

StefanThoma commented Nov 7, 2025 via email

@averissimo
Copy link
Contributor Author

@StefanThoma that's one of our goals with this PR. It's now possible for HTML output, the other formats are a WIP, but I believe we'll make it happen

@llrs-roche llrs-roche mentioned this pull request Nov 18, 2025
32 tasks
@github-actions
Copy link
Contributor

github-actions bot commented Nov 20, 2025

Unit Tests Summary

  1 files   24 suites   15m 33s ⏱️
158 tests 150 ✅ 5 💤 2 ❌ 1 🔥
480 runs  471 ✅ 5 💤 3 ❌ 1 🔥

For more details on these failures and errors, see this check.

Results for commit d2df067.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 20, 2025

Unit Test Performance Difference

Test Suite $Status$ Time on main $±Time$ $±Tests$ $±Skipped$ $±Failures$ $±Errors$
shinytest2-tm_a_pca 💔 $137.41$ $+6.73$ $0$ $0$ $0$ $0$
shinytest2-tm_a_regression 💔 $64.61$ $+4.30$ $0$ $0$ $0$ $0$
shinytest2-tm_data_table 💔 $25.80$ $+2.38$ $0$ $0$ $0$ $0$
shinytest2-tm_file_viewer 💚 $31.42$ $-2.79$ $-1$ $0$ $+3$ $+1$
shinytest2-tm_front_page 💔 $24.25$ $+1.78$ $0$ $0$ $0$ $0$
shinytest2-tm_g_bivariate 💔 $87.40$ $+3.67$ $0$ $0$ $0$ $0$
shinytest2-tm_g_distribution 💔 $55.98$ $+3.18$ $0$ $0$ $0$ $0$
shinytest2-tm_g_response 💔 $35.12$ $+2.35$ $0$ $0$ $0$ $0$
shinytest2-tm_g_scatterplot 💔 $70.55$ $+3.97$ $0$ $0$ $0$ $0$
shinytest2-tm_g_scatterplotmatrix 💔 $31.73$ $+2.39$ $0$ $0$ $0$ $0$
shinytest2-tm_misssing_data 💔 $58.57$ $+4.31$ $0$ $0$ $0$ $0$
shinytest2-tm_outliers 💔 $138.01$ $+10.52$ $0$ $0$ $0$ $0$
shinytest2-tm_t_crosstable 💔 $36.78$ $+2.24$ $0$ $0$ $0$ $0$
shinytest2-tm_variable_browser 💔 $78.95$ $+5.61$ $0$ $0$ $0$ $0$
tm_rmarkdown 👶 $+0.32$ $+4$ $0$ $0$ $0$
Additional test case details
Test Suite $Status$ Time on main $±Time$ Test Case
examples 👶 $+0.01$ example_dot_markdown_internal.Rd
examples 👶 $+0.01$ example_is_tab_active_js.Rd
examples 👶 $+0.10$ example_tm_rmarkdown.Rd
shinytest2-tm_a_pca 💔 $30.61$ $+1.05$ e2e_tm_a_pca_Changing_output_encodings_of_plot_type_hides_and_shows_options.
shinytest2-tm_file_viewer 💚 $8.29$ $-3.93$ e2e_tm_file_viewer_Shows_selected_image_file
shinytest2-tm_g_bivariate 💔 $34.25$ $+1.51$ e2e_tm_g_bivariate_Setting_encoding_inputs_produces_outputs_without_validation_errors.
shinytest2-tm_g_distribution 💔 $20.05$ $+1.42$ e2e_tm_g_distribution_Histogram_encoding_inputs_produce_output_without_validation_errors.
shinytest2-tm_g_scatterplot 💔 $34.41$ $+1.57$ e2e_tm_g_scatterplot_The_encoding_inputs_are_set_without_validation_errors.
shinytest2-tm_outliers 💔 $12.78$ $+1.22$ e2e_tm_outliers_Data_extract_spec_elements_are_initialized_with_the_default_values_specified_by_outlier_var_and_categorical_var_argument.
shinytest2-tm_outliers 💔 $29.70$ $+1.64$ e2e_tm_outliers_Outlier_definition_text_and_range_are_displayed_properly_depending_on_method.
shinytest2-tm_outliers 💔 $14.42$ $+1.44$ e2e_tm_outliers_Outliers_summary_table_is_displayed_with_proper_content.
shinytest2-tm_outliers 💔 $19.93$ $+1.08$ e2e_tm_outliers_Plot_type_is_hidden_when_Boxplot_tab_is_not_selected.
shinytest2-tm_variable_browser 💔 $12.01$ $+1.05$ e2e_tm_variable_browser_Selecting_treat_variable_as_factor_changes_the_table_headers.
shinytest2-tm_variable_browser 💔 $19.01$ $+1.10$ e2e_tm_variable_browser_changing_plot_setting_encodings_doesn_t_show_errors.
tm_rmarkdown 👶 $+0.09$ srv_rmarkdown_renders_expected_html
tm_rmarkdown 👶 $+0.16$ srv_rmarkdown_renders_number_of_rows_of_my_data_to_markdown_file
tm_rmarkdown 👶 $+0.07$ srv_rmarkdown_returns_a_teal.reporter_reactive

Results for commit 82ed11b

♻️ This comment has been updated with latest results.

@averissimo averissimo requested a review from a team November 20, 2025 11:56
Copy link

@osenan osenan left a comment

Choose a reason for hiding this comment

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

Is it possible to create unit tests for srv_markdown? With testServer I think it has complex enough server logic to implement them.
Also check if other exported funcions we can create uni test.
I tested the app, based on examples. It looks ok:
image
But the markdown text is written by he teal_developr right? Are not the users who can add/remove markdown text

@averissimo averissimo requested a review from osenan November 21, 2025 18:28
@averissimo
Copy link
Contributor Author

@osenan I've added tests and I think I addressed your comments.

Let's have a new round of review :-)

Copy link

@osenan osenan left a comment

Choose a reason for hiding this comment

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

Thanks for the tests. I have run them locally and they pass. They do not pass in CI due to e2e tests.
They are also very useful. There is a lintr error, we could ignore the lint for names in that line.

@averissimo averissimo merged commit d95dd67 into main Nov 25, 2025
27 of 29 checks passed
@averissimo averissimo deleted the 675-rmarkdown_module branch November 25, 2025 13:22
@github-actions github-actions bot locked and limited conversation to collaborators Nov 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants