# Module globals
reportFileNames <- GetReportFileNames()
reportNames <- names(reportFileNames)
skipWidgetParamNames <- c("AdjustedData", "Artifacts", "nsdf")
# User interface
createReportsUI <- function(id)
{
ns <- NS(id)
tagList(
div(style = "margin-top: 15px"),
box(
width = 12,
title = "Create report",
solidHeader = FALSE,
collapsible = TRUE,
status = "primary",
fluidRow(
column(6,
selectInput(ns("select"),
label = NULL,
choices = reportNames,
selected = 1,
selectize = TRUE)),
column(6,
actionLink(ns("openParamsDlg"), "Edit parameters"),
style = "padding-top: 7px"),
column(12,
uiOutput(ns("rerunInfo")),
actionButton(ns("createReportBtn"), "Create",
style = "background-color: #69b023; color: white"),
shinyjs::disabled(actionButton(ns("cancelReportBtn"), "Cancel"))
)
)),
uiOutput(ns("report"))
)
}
# Server logic
createReports <- function(input, output, session, appStatus)
{
ns <- session$ns
# Make "task" behave like a reactive value
makeReactiveBinding("reportTask")
reportTask <- NULL
# Store reactive values
vals <- reactiveValues(selectedReportName = NULL,
reportParamsWidgets = list(),
reportParams = list(),
reportParamsFull = list())
invalidateReport <- function() {
appStatus$Report <- NULL
}
adjustedDataAvailable <- reactive({
# !is.null(appStatus$AdjustedData)
TRUE
})
observe({
if (adjustedDataAvailable()) {
shinyjs::enable("createReportBtn")
} else {
shinyjs::disable("createReportBtn")
}
})
# Get selected report name on change
observeEvent(input[["select"]], {
vals$selectedReportName <- req(input$select)
# Populate widgets with default values for a next dialog open
reportFileName <- reportFileNames[vals$selectedReportName]
if (file.exists(reportFileName)) {
reportMdLines <- readLines(reportFileName, warn = FALSE)
paramSpecs <- knitr::knit_params(reportMdLines)
vals$reportParams[[vals$selectedReportName]] <-
GetReportDefaultParams(params = paramSpecs,
skipParamNames = skipWidgetParamNames)
vals$reportParamsWidgets <-
GetParamWidgets(paramSpecs,
params = vals$reportParams[[vals$selectedReportName]],
skipParamNames = skipWidgetParamNames,
ns = ns)
vals$reportParamsFull <- list()
}
})
# Output adjustment parameters when selected adjustments changed
output[["reportParams"]] <- renderUI({
vals$reportParamsWidgets
})
# EVENT: Button "Open parameters dialog" clicked
observeEvent(input[["openParamsDlg"]], {
showModal(modalDialog(
title = "Edit report parameters",
uiOutput(ns("reportParams")),
easyClose = FALSE,
footer = tagList(
actionButton(ns("paramsDlgOk"), "OK", style = "background-color: #69b023; color: white"),
modalButton("Cancel")
)
))
})
observeEvent(input[["paramsDlgOk"]], {
reportParams <- list()
for (paramName in names(vals$reportParamsWidgets)) {
reportParams[[paramName]] <- input[[paramName]]
}
vals$reportParams[[vals$selectedReportName]] <- reportParams
# Populate widgets with updated values for a next dialog open
reportFileName <- reportFileNames[vals$selectedReportName]
if (file.exists(reportFileName)) {
reportMdLines <- readLines(reportFileName, warn = FALSE)
paramSpecs <- knitr::knit_params(reportMdLines)
vals$reportParamsWidgets <-
GetParamWidgets(paramSpecs,
params = vals$reportParams[[vals$selectedReportName]],
skipParamNames = skipWidgetParamNames,
ns = session$ns)
}
invalidateReport()
removeModal()
})
output[["rerunInfo"]] <- renderUI({
adjustedDataAvailable <- adjustedDataAvailable()
if (!adjustedDataAvailable) {
return(p("Adjusted data is not available for report. Please, re-run adjustments first."))
} else if (IsEmptyString(appStatus$Report)) {
return(p("Adjusted data or report parameters have changed. Please, re-create the report."))
} else {
return(NULL)
}
})
# EVENT: Button "Create report" clicked
observeEvent(input[["createReportBtn"]], {
# adjustedData <- req(appStatus$AdjustedData)
adjustedData <- appStatus$AdjustedData
fileName <- appStatus$FileName
diagYearRangeApply <- appStatus$DiagYearRangeApply
diagYearRange <- appStatus$DiagYearRange
shinyjs::disable("createReportBtn")
shinyjs::enable("cancelReportBtn")
appStatus$Report <- ""
# Show progress message during task start
prog <- Progress$new(session)
prog$set(message = "Creating report...", value = 0.5)
# Define parameters
if (vals$selectedReportName == 'Main Report') {
params <- append(list(AdjustedData = adjustedData),
vals$reportParams[[vals$selectedReportName]])
} else {
params <- vals$reportParams[[vals$selectedReportName]]
}
if (isLinux) {
reportTask <<- CreateTask({
if (vals$selectedReportName == 'Main Report') {
params <- GetMainReportArtifacts(params)
params <- modifyList(params,
list(Artifacts =
list(FileName = fileName,
DiagYearRange = diagYearRange,
DiagYearRangeApply = diagYearRangeApply)))
}
report <- RenderReportToHTML(reportFileNames[vals$selectedReportName],
params = params)
list(Report = report,
Params = params)
})
} else {
reportTask <<- CreateTask(function(params, fileName, diagYearRange, diagYearRangeApply, reportFileName) {
params <- hivEstimatesAccuracy::GetMainReportArtifacts(params)
params <- modifyList(params,
list(Artifacts =
list(FileName = fileName,
DiagYearRange = diagYearRange,
DiagYearRangeApply = diagYearRangeApply)))
report <- hivEstimatesAccuracy::RenderReportToHTML(reportFileName, params = params)
list(Report = report,
Params = params)
},
args = list(params,
fileName,
diagYearRange,
diagYearRangeApply,
reportFileNames[vals$selectedReportName]))
}
o <- observe({
# Only proceed when the task is completed (this could mean success,
# failure, or cancellation)
req(reportTask$completed())
endTime <- Sys.time()
taskResults <- reportTask$result()
if (is.list(taskResults)) {
appStatus$Report <- taskResults$Report
# Store parameters for reuse when downloading
vals$reportParamsFull <- taskResults$Params
}
reportTask <<- NULL
# This observer only runs once
o$destroy()
# Close the progress indicator and update button state
prog$close()
shinyjs::enable("createReportBtn")
shinyjs::disable("cancelReportBtn")
})
})
# EVENT: Button "Run adjustments" clicked
observeEvent(input[["cancelReportBtn"]], {
req(reportTask)$cancel()
})
# Output report when it has changed
output[["report"]] <- renderUI({
# Respond to report change
report <- req(appStatus$Report)
if (!is.null(report)) {
isolate({
ns <- session$ns
# Get adjusted data details
reportDiv <-
div(id = "reportDiv",
downloadButton(ns("downloadHtmlReport"), "Download as HTML"),
downloadButton(ns("downloadPdfReport"), "Download as PDF"),
downloadButton(ns("downloadLatexReport"), "Download as Latex"),
downloadButton(ns("downloadWordReport"), "Download as Word"),
report
)
reportHTML <- box(
width = 12,
title = "Report",
solidHeader = FALSE,
collapsible = TRUE,
status = "warning",
reportDiv)
return(reportHTML)
})
}
})
# Define report download handler
reportDownloadHandler <- function(format) {
fileExtension <- switch(format,
"html_document" = "html",
"pdf_document" = "pdf",
"latex_document" = "zip",
"word_document" = "docx",
"txt")
downloadHandler(
filename = function() {
fileName <- sprintf("%s_%s.%s",
vals$selectedReportName,
GetTimeStamp(),
fileExtension)
return(fileName)
},
content = function(file) {
withProgress(message = "Creating report",
detail = "The report file will be available for download shortly.",
value = 0, {
params <- vals$reportParamsFull
setProgress(0.2)
# Knit the document, passing in the "data" list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
RenderReportToFile(reportFilePath = reportFileNames[vals$selectedReportName],
format = format,
params = params,
outputFilePath = file)
setProgress(1)
})
}
)
}
# Respond to report download button clicks
output[["downloadHtmlReport"]] <- reportDownloadHandler("html_document")
output[["downloadPdfReport"]] <- reportDownloadHandler("pdf_document")
output[["downloadLatexReport"]] <- reportDownloadHandler("latex_document")
output[["downloadWordReport"]] <- reportDownloadHandler("word_document")
return(NULL)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.