Skip to content
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

init simple report #23

Merged
merged 51 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
deb145a
init simple report
Polkas Apr 20, 2022
d81155c
add first testServer
Polkas Apr 21, 2022
b6068c8
testServer
Polkas Apr 21, 2022
6f7c05f
styler + lintr
Polkas Apr 21, 2022
65a4a50
utils
Polkas Apr 21, 2022
b5b7886
Merge branch 'main' into 1_simple_app@main
Polkas Apr 21, 2022
88747e3
docs
Polkas Apr 21, 2022
2973923
docs and tests
Polkas Apr 21, 2022
5765dfa
tests
Polkas Apr 21, 2022
856aa1f
extract input
Polkas Apr 22, 2022
67c726f
extract input
Polkas Apr 22, 2022
04f4146
polish
Polkas Apr 22, 2022
f52f090
lintr actions
Polkas Apr 22, 2022
b49cf1c
spelling user interface
Polkas Apr 22, 2022
bc9e614
docs
Polkas Apr 22, 2022
a4f1e25
fix
Polkas Apr 26, 2022
1587e43
fix
Polkas Apr 26, 2022
fed131b
Mahmoud rev
Polkas Apr 26, 2022
b1cd6a7
Mahmoud rev 2
Polkas Apr 26, 2022
2dbf120
Mahmoud rev 2b
Polkas Apr 26, 2022
ba29264
Update R/utils.R
Polkas Apr 26, 2022
b3d132c
Mahmoud rev 2c
Polkas Apr 26, 2022
6dfa710
small update
Polkas Apr 28, 2022
60c80eb
Apply suggestions from code review
Polkas Apr 28, 2022
af9e25b
buttons specified by user (#28)
gogonzo Apr 28, 2022
d7f4f97
docs
Polkas Apr 28, 2022
934e7f5
style
Polkas Apr 28, 2022
d3013ba
revert update
Polkas Apr 28, 2022
2157e0b
Revert "docs"
Polkas Apr 28, 2022
30954da
Revert "buttons specified by user (#28)"
Polkas Apr 28, 2022
073c0f2
callback
Polkas Apr 28, 2022
553bdb3
Apply suggestions from code review
Polkas Apr 28, 2022
0f95dfd
comments
Polkas Apr 28, 2022
6ebb603
style
Polkas Apr 28, 2022
7d96517
docs
Polkas Apr 28, 2022
2951746
docs
Polkas Apr 28, 2022
bfbae65
docs
Polkas Apr 28, 2022
1e23c5d
download fun
Polkas Apr 28, 2022
8746c1a
docs
Polkas Apr 28, 2022
994a86f
tests
Polkas Apr 28, 2022
a05ccef
call back magic, comment
Polkas Apr 28, 2022
eabeb33
no pdf render
Polkas Apr 29, 2022
34200dc
lintr
Polkas Apr 29, 2022
f485b3e
even better
Polkas Apr 29, 2022
be355dd
validate
Polkas Apr 29, 2022
9268853
Merge branch 'main' into 1_simple_app@main
Polkas Apr 29, 2022
a165a36
Apply suggestions from code review
Polkas Apr 29, 2022
61f77cb
Apply suggestions from code review
Polkas Apr 29, 2022
867c673
updates
Polkas Apr 29, 2022
293887f
empty comment
Polkas Apr 29, 2022
a7702f3
docs
Polkas Apr 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
^\.github$
^\.lintr$
^\.pre-commit-config\.yaml$
^doc$
^Meta$
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.Rhistory
docs
inst/doc
/doc/
/Meta/
5 changes: 4 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ Imports:
checkmate,
grid,
R6,
yaml
yaml,
shiny,
shinyWidgets,
zip
Suggests:
ggplot2,
knitr,
Expand Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

export(ReportCard)
export(Reporter)
export(add_card_button_srv)
export(add_card_button_ui)
export(download_report_button_srv)
export(download_report_button_ui)
export(simple_reporter_srv)
export(simple_reporter_ui)
export(TealReportCard)
importFrom(R6,R6Class)
importFrom(checkmate,assert_string)
Expand Down
87 changes: 87 additions & 0 deletions R/AddCardModule.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#' Add Card Button User Interface
#' @description button for adding views/cards to the Report.
#'
#' For more details see the vignette: `vignette("simpleReporter", "teal.reporter")`.
#' @param id `character`
#' @return `shiny::tagList`
#' @export
add_card_button_ui <- function(id) {
ns <- shiny::NS(id)
shiny::tagList(
shiny::tags$button(
id = ns("addReportCardButton"),
type = "button",
class = "btn btn-primary action-button",
`data-val` = shiny::restoreInput(id = ns("addReportCardButton"), default = NULL),
NULL,
"Add Card"
)
)
}

Polkas marked this conversation as resolved.
Show resolved Hide resolved
#' Add Card Button Server
#' @description server for adding views/cards to the Report.
#'
#' For more details see the vignette: `vignette("simpleReporter", "teal.reporter")`.
#' @param id `character`
#' @param reporter `Reporter` instance.
#' @param card_fun `function` which returns a `ReportCard` instance,
Polkas marked this conversation as resolved.
Show resolved Hide resolved
#' the function has at least two arguments `card` and `comment`.
#' @return `shiny::moduleServer`
#' @export
add_card_button_srv <- function(id, reporter, card_fun) {
shiny::moduleServer(
id,
function(input, output, session) {
ns <- session$ns
add_modal <- function(failed = FALSE) {
shiny::modalDialog(
easyClose = TRUE,
shiny::tags$h3("Add the Card to the Report"),
shiny::tags$hr(),
shiny::textInput(
ns("comment"),
"Comment",
value = "The idea behind",
width = "100%"
),
if (failed) {
shiny::tags$div(
shiny::tags$b("Invalid", style = "color: red;")
)
},
footer = shiny::tagList(
shiny::tags$button(
type = "button",
class = "btn btn-primary",
`data-dismiss` = "modal",
`data-bs-dismiss` = "modal",
NULL,
"Cancel"
),
shiny::tags$button(
id = ns("addCardOk"),
Polkas marked this conversation as resolved.
Show resolved Hide resolved
type = "button",
class = "btn btn-primary action-button",
`data-val` = shiny::restoreInput(id = ns("addCardOk"), default = NULL),
NULL,
"Add Card"
)
)
)
}

shiny::observeEvent(input$addReportCardButton, {
shiny::showModal(add_modal())
})

shiny::observeEvent(input$addCardOk, {
Polkas marked this conversation as resolved.
Show resolved Hide resolved
Polkas marked this conversation as resolved.
Show resolved Hide resolved
card <- ReportCard$new()
card_fun(card, input$comment)
checkmate::assert_class(card, "ReportCard")
reporter$append_cards(list(card))
shiny::removeModal()
})
}
)
}
14 changes: 7 additions & 7 deletions R/ContentBlock.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ ContentBlock <- R6::R6Class( # nolint: object_name_linter.
private = list(
content = character(0),

#' @description The copy constructor.
#'
#' @param name `character(1)` the name of the field
#' @param value the value assigned to the field
#'
#' @return the value of the copied field
#'
# @description The copy constructor.
#
# @param name `character(1)` the name of the field
# @param value the value assigned to the field
#
# @return the value of the copied field
#
Polkas marked this conversation as resolved.
Show resolved Hide resolved
deep_clone = function(name, value) {
if (name == "content" && checkmate::test_file_exists(value)) {
extension <- ""
Expand Down
197 changes: 197 additions & 0 deletions R/DownloadModule.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#' Download Button Reporter User Interface
#' @description button for downloading the Report.
#'
#' For more details see the vignette: `vignette("simpleReporter", "teal.reporter")`.
#' @param id `character`
#' @return `shiny::tagList`
#' @export
download_report_button_ui <- function(id) {
ns <- shiny::NS(id)
shiny::tagList(
shiny::tags$button(
id = ns("download_button"),
type = "button",
class = "btn btn-primary action-button",
`data-val` = shiny::restoreInput(id = ns("download_button"), default = NULL),
NULL,
"Download Report"
)
)
}

#' Download Button Server
#' @description server for downloading the Report.
#'
#' For more details see the vignette: `vignette("simpleReporter", "teal.reporter")`.
#' @param id `character`
#' @param reporter `Reporter` instance.
#' @param notification `logical` whether to add a shiny notification about the download process. Default `TRUE`.
#' @param rmd_output `character` vector with `rmarkdown` output types,
#' by default all possible `c("pdf_document", "html_document", "powerpoint_presentation", "word_document")`.
#' @param rmd_yaml_args `named list` vector with `Rmd` `yaml` header fields and their default values.
#' Default `list(author = "NEST", title = "Report", date = Sys.Date(), output = "html_document")`.
#' Please update only values at this moment.
#' @return `shiny::moduleServer`
#' @export
download_report_button_srv <- function(id,
reporter,
notification = TRUE,
rmd_output = c(
"html_document", "pdf_document",
"powerpoint_presentation", "word_document"
),
rmd_yaml_args = list(
author = "NEST", title = "Report",
date = as.character(Sys.Date()), output = "html_document"
)) {
checkmate::assert_class(reporter, "Reporter")
checkmate::assert_flag(notification)
checkmate::assert_subset(rmd_output, c(
"html_document", "pdf_document",
"powerpoint_presentation", "word_document"
))
checkmate::assert_list(rmd_yaml_args, names = "named")
checkmate::assert_true(all(c("author", "title", "date", "output") %in% names(rmd_yaml_args)))

shiny::moduleServer(
id,
function(input, output, session) {
ns <- session$ns
download_modal <- function(failed = FALSE) {
nr_cards <- length(reporter$get_cards())
downb <- shiny::tags$a(
id = ns("download_data"),
class = paste("btn btn-primary shiny-download-link", if (nr_cards) NULL else "disabled"),
style = if (nr_cards) NULL else "pointer-events: none;",
href = "",
target = "_blank",
download = NA,
shiny::icon("download"),
"Download Report"
)
shiny::modalDialog(
easyClose = TRUE,
shiny::tags$h3("Download the Report"),
shiny::tags$hr(),
if (length(reporter$get_cards()) == 0) {
shiny::tags$div(
shiny::tags$p(shiny::tags$strong("No Cards Added"), style = "color: red; margin-bottom:15px;")
)
} else {
shiny::tags$div(
style = "color: green; margin-bottom:15px;",
shiny::tags$p(
shiny::tags$strong(paste("Number of cards: ", nr_cards))
),
)
},
shiny::textInput(ns("author"), label = "Author:", value = rmd_yaml_args$author),
shiny::textInput(ns("title"), label = "Title:", value = rmd_yaml_args$title),
shiny::dateInput(ns("date"), "Date:", value = rmd_yaml_args$date),
shiny::tags$div(
shinyWidgets::pickerInput(
inputId = ns("output"),
label = "Choose a document type: ",
choices = rmd_output,
selected = rmd_yaml_args$output
)
),
if (failed) {
shiny::tags$div(shiny::tags$b("Invalid", style = "color: red;"))
},
footer = shiny::tagList(
shiny::tags$button(
id = ns("reset_reporter"),
type = "button",
style = "float: left;",
class = "btn btn-danger action-button",
`data-val` = shiny::restoreInput(id = ns("reset_reporter"), default = NULL),
NULL,
"Reset Reporter"
),
shiny::tags$button(
type = "button",
class = "btn btn-primary",
`data-dismiss` = "modal",
`data-bs-dismiss` = "modal",
NULL,
"Cancel"
),
downb
)
)
}

shiny::observeEvent(input$download_button, {
shiny::showModal(download_modal())
})

shiny::observeEvent(input$reset_reporter, {
shiny::showModal(
shiny::modalDialog(
shiny::tags$h3("Reset the Report"),
shiny::tags$hr(),
shiny::tags$strong(shiny::tags$p("Are you sure you want to reset the report?")),
footer = shiny::tagList(
shiny::modalButton("Cancel"),
shiny::actionButton(ns("reset_reporter_ok"), "Reset")
)
)
)
})
Polkas marked this conversation as resolved.
Show resolved Hide resolved

shiny::observeEvent(input$reset_reporter_ok, {
reporter$reset()
shiny::removeModal()
})

output$download_data <- shiny::downloadHandler(
filename = function() {
paste("report_", format(Sys.time(), "%y%m%d%H%M%S"), ".zip", sep = "")
},
content = function(file) {
if (notification) {
shiny::showNotification(sprintf("Rendering and Downloading a document."))
}
input_list <- lapply(names(rmd_yaml_args), function(x) input[[x]])
names(input_list) <- names(rmd_yaml_args)
report_render_and_compress(reporter, input_list, file)
},
contentType = "application/zip"
)
}
)
}

#' Render the Report
#' @description render the report and zip the created directory.
#' @param reporter `Reporter` instance.
#' @param input `list` like shiny input converted to a regular list.
#' @param file `character` where to copy the returned directory.
#' @return `file` argument
#' @keywords internal
report_render_and_compress <- function(reporter, input, file = tempdir()) {
checkmate::assert_class(reporter, "Reporter")
checkmate::assert_list(input, names = "named")
checkmate::assert_string(file)

yaml <- list(
author = input$author,
title = input$title,
date = as.character(input$date)
)
if (!is.null(input$output)) {
yaml[["output"]] <- input$output
}
yaml_header <- md_header(yaml::as.yaml(yaml))

renderer <- Renderer$new()
renderer$render(reporter$get_blocks(), yaml_header)

temp_zip_file <- tempfile(fileext = ".zip")
zip::zipr(temp_zip_file, renderer$get_output_dir())
file.copy(temp_zip_file, file)

rm(renderer)
file
}
4 changes: 2 additions & 2 deletions R/Renderer.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Renderer <- R6::R6Class( # nolint: object_name_linter.
#' author = teal.reporter:::yaml_quoted("NEST"),
#' title = teal.reporter:::yaml_quoted("Report"),
#' date = teal.reporter:::yaml_quoted("07/04/2019"),
#' output = list(pdf_document = list(keep_tex = TRUE))
#' output = list(html_document = list(toc = FALSE))
#' )
#'
#' yaml_header <- teal.reporter:::md_header(yaml::as.yaml(yaml_l))
Expand Down Expand Up @@ -103,7 +103,7 @@ Renderer <- R6::R6Class( # nolint: object_name_linter.
#' author = teal.reporter:::yaml_quoted("NEST"),
#' title = teal.reporter:::yaml_quoted("Report"),
#' date = teal.reporter:::yaml_quoted("07/04/2019"),
#' output = list(pdf_document = list(keep_tex = TRUE))
#' output = list(html_document = list(toc = FALSE))
#' )
#'
#' yaml_header <- teal.reporter:::md_header(yaml::as.yaml(yaml_l))
Expand Down
12 changes: 6 additions & 6 deletions R/ReportCard.R
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,12 @@ ReportCard <- R6::R6Class( # nolint: object_name_linter.
content = list(),
chr_converters = list(),

#' @description The copy constructor.
#'
#' @param name the name of the field
#' @param value the value of the field
#' @return the new value of the field
#'
# @description The copy constructor.
#
# @param name the name of the field
# @param value the value of the field
# @return the new value of the field
#
deep_clone = function(name, value) {
if (name == "content") {
lapply(value, function(content_block) {
Expand Down
Loading