The Report previewer is an advanced shiny module designed for visualization, editing, and downloading of report cards. It extended the base modules introduced in the simpleReporter vignette, enhancing interactivity and user engagement with report content.
The report previewer is now implemented as a modal dialog that opens when a preview button is clicked, providing a streamlined user experience without requiring separate tabs.
The five essential steps for implementing the report previewer include integrating it within a shiny application. Key code segments are highlighted in ### REPORTER code blocks.
card and comment. This function must return a ReportCard object. The ReportCard object should be built step by step, assuming that it is empty at the beginning.
comment argument is provided, it should be added to the card. If not, it should be added automatically at the end of the card.card argument is provided, the ReportCard instance should be automatically created for the user. If not, the function should create the card itself. Please note that the document page’s design is up to the developer’s imagination.
Reporter instance and the function to create the ReportCard instance.The code added to introduce the reporter is wrapped in the ### REPORTER code blocks.
First, load the required packages:
A basic shiny app with the previewer module:
ui <- bslib::page_fluid(
sidebarLayout(
sidebarPanel(
uiOutput("encoding")
),
mainPanel(
tabsetPanel(
id = "tabs",
tabPanel("Plot", plotOutput("dist_plot")),
tabPanel("Table", verbatimTextOutput("table")),
tabPanel("Table DataFrame", verbatimTextOutput("table2")),
tabPanel("Table DataTable", dataTableOutput("table3"))
)
)
)
)
server <- function(input, output, session) {
output$encoding <- renderUI({
shiny::tagList(
### REPORTER
teal.reporter::add_card_button_ui("add_reporter", label = "Add Report Card"),
teal.reporter::preview_report_button_ui("previewer"),
###
if (input$tabs == "Plot") {
sliderInput(
"binwidth",
"binwidth",
min = 2,
max = 10,
value = 8
)
} else if (input$tabs %in% c("Table", "Table DataFrame", "Table DataTable")) {
selectInput(
"stat",
label = "Statistic",
choices = c("mean", "median", "sd"),
"mean"
)
} else {
NULL
}
)
})
plot <- reactive({
req(input$binwidth)
x <- mtcars$mpg
ggplot(data = mtcars, aes(x = mpg)) +
geom_histogram(binwidth = input$binwidth)
})
output$dist_plot <- renderPlot(plot())
table <- reactive({
req(input$stat)
lyt <- basic_table() %>%
split_rows_by("Month", label_pos = "visible") %>%
analyze("Ozone", afun = eval(str2expression(input$stat)))
build_table(lyt, airquality)
})
output$table <- renderPrint(table())
table2 <- reactive({
req(input$stat)
data <- aggregate(
airquality[, c("Ozone"), drop = FALSE], list(Month = airquality$Month), get(input$stat),
na.rm = TRUE
)
colnames(data) <- c("Month", input$stat)
data
})
output$table2 <- renderPrint(print.data.frame(table2()))
output$table3 <- renderDataTable(table2())
### REPORTER
reporter <- Reporter$new()
# Optionally set reporter id to e.g. secure report reload only for the same app
# The id is added to the downloaded file name.
reporter$set_id("myappid")
card_fun <- function(card = ReportCard$new(), comment) {
if (input$tabs == "Plot") {
card$set_name("Plot Module")
card$append_text("My plot", "header2")
card$append_plot(plot())
card$append_rcode(
paste(
c(
"x <- mtcars$mpg",
"ggplot2::ggplot(data = mtcars, ggplot2::aes(x = mpg)) +",
paste0("ggplot2::geom_histogram(binwidth = ", input$binwidth, ")")
),
collapse = "\n"
),
echo = TRUE,
eval = FALSE
)
} else if (input$tabs == "Table") {
card$set_name("Table Module rtables")
card$append_text("My rtables", "header2")
card$append_table(table())
card$append_rcode(
paste(
c(
"lyt <- rtables::basic_table() %>%",
'rtables::split_rows_by("Month", label_pos = "visible") %>%',
paste0('rtables::analyze("Ozone", afun = ', input$stat, ")"),
"rtables::build_table(lyt, airquality)"
),
collapse = "\n"
),
echo = TRUE,
eval = FALSE
)
} else if (input$tabs %in% c("Table DataFrame", "Table DataTable")) {
card$set_name("Table Module DF")
card$append_text("My Table DF", "header2")
card$append_table(table2())
# Here r code added as a regular verbatim text
card$append_text(
paste0(
c(
'data <- aggregate(airquality[, c("Ozone"), drop = FALSE], list(Month = airquality$Month), ',
input$stat,
", na.rm = TRUE)\n",
'colnames(data) <- c("Month", ', paste0('"', input$stat, '"'), ")\n",
"data"
),
collapse = ""
), "verbatim"
)
}
if (!comment == "") {
card$append_text("Comment", "header3")
card$append_text(comment)
}
card
}
teal.reporter::add_card_button_srv("add_reporter", reporter = reporter, card_fun = card_fun)
teal.reporter::preview_report_button_srv("previewer", reporter)
###
}
shinyApp(ui = ui, server = server)