Hello,
I have been trying to generate a plotly image into a pdf with some user reponses in a R shiny app. But I am getting an error:
Error in curl::curl_fetch_disk(url, x$path, handle = handle): SSL peer certificate or SSH remote key was not OK [api.plot.ly]: SSL certificate problem: certificate has expired
Here is a reproducible example:
library(plotly)
library(knitr)
library(webshot)
library(shiny)
ui =
fluidPage(
tabPanel("EisenVerla",
tabsetPanel(id = "Eisen_subtabs",
tabPanel("Self_Assessment",
fluidRow(
column(
width = 7,
div(
style = "border: 1px solid #dddddd; padding: 10px; margin-bottom: 20px",
tags$h4("selfAssesment", style = "text-align: left; font-weight: bold; margin-bottom: 20px;"),
# Questions with consistent spacing
div(
style = "margin-top: 20px;", # Added margin for alignment with criteria
# 1
div(
tags$h5("Enter your response"),
radioButtons("response1", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text1", label = "Comment", placeholder = "Enter text...")
),
# 2
div(
tags$h5("Enter your response"),
radioButtons("response2", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text2", label = "Comment", placeholder = "Enter text...")
),
# 3
div(
tags$h5("Enter your response"),
radioButtons("response3", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text3", label = "Comment", placeholder = "Enter text...")
),
# 4
div(
tags$h5("Enter your response"),
radioButtons("response4", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text4", label = "Comment", placeholder = "Enter text...")
),
# 5
div(
tags$h5("Enter your response"),
radioButtons("response5", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text5", label = "Comment", placeholder = "Enter text...")
),
# 6
div(
tags$h5("Enter your response"),
radioButtons("response6", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
textAreaInput("response_text6", label = "Comment", placeholder = "Enter text...")
)
)
)
),
column(
width = 2,
fluidRow(
column(4,
div(align = "left",
actionButton("export", "Export Plot"),
plotlyOutput("plot_example_1", width = "800px", height = "550px"),
downloadButton("downloadPlot", "Download Plot (PNG)"),
style = "margin-right: 500px;"
),
downloadButton("dnld", "Download PDF Report")
)
)
)
),
mainPanel()
)
)
)
)
server <- function(input, output, session) {
# Compute numeric values for plot inside a reactive expression
numeric_values <- reactive({
sapply(1:6, function(i) {
val <- input[[paste0("response", i)]]
if (is.null(val) || is.na(val)) NA_real_ else as.numeric(val)
})
})
# interactive Plotly plot from user-based response
plot_function <- reactive({
plot_ly(
mode = 'markers+lines',
type = 'scatterpolar',
fill = 'toself',
fillcolor = "rgba(231, 184, 0, 0.5)",
line = list(color = 'rgb(0, 0, 0)'),
marker = list(
symbol = 100,
size = 6,
color = 'rgb(0, 0, 0)',
line = list(color = 'rgb(0, 0, 0)', width = 1)
),
r = numeric_values(), # Use the reactive numeric_values()
theta = c("<b>1</b>", "<b>2</b>", "<b>3</b>", "<b>4</b>", "<b>5</b>", "<b>6</b>")
) |>
layout(
title = list(text = "Self_Assessment", y = 0.99),
polar = list(radialaxis = list(visible = TRUE, range = c(0, 5))),
angularaxis = list(rotation = 90, direction = "clockwise"),
showlegend = FALSE,
margin = list(l = 30, r = 30, b = 30, t = 30),
font = list(size = 9, color = 'black'),
paper_bgcolor = "#B4D9F9",
plot_bgcolor = "#B4D9F9",
width = 400,
height = 300
)
})
output$plot_example_1 <- renderPlotly({
plot_function()
})
# getting user responses
# Combine numeric and text responses into a data frame
user_responses <- reactive({
data.frame(
Question = 1:6,
Numeric_Response = sapply(1:6, function(i) {
input[[paste0("response", i)]]
}),
Text_Response = sapply(1:6, function(i) {
input[[paste0("response_text", i)]]
}),
stringsAsFactors = FALSE
)
})
# download
output$dnld <- downloadHandler(
filename = "report.pdf",
content = function(file) {
# Save the Plotly chart as a PNG file
plotly_IMAGE(plot_function(), format = "png", out_file = "plot_example_1.png")
#orca(plot_function(),"plot_example_1.png")
# Path to the LaTeX template
src <- normalizePath('report.Rnw')
# Temporarily switch to the temp directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rnw', overwrite = TRUE)
# Save the user responses into a temporary file for LaTeX
write.table(
user_responses(),
file = "user_responses.csv",
sep = ",",
row.names = FALSE,
col.names = TRUE
)
# Knit the LaTeX document to PDF
out <- knitr::knit2pdf('report.Rnw', clean = TRUE)
file.rename(out, file)
}
)
}
shinyApp(ui, server)
report.Rnw
\documentclass[10pt,a4paper]{report}
\setlength\parindent{0pt}
\usepackage[margin=0.8in]{geometry}
\usepackage{longtable} % For displaying tables across pages
\begin{document}
% ###################################################### PAGE 1: SUMMARY #######################################################
\begin{center}
\Huge\noindent\textbf{A Dynamic PDF Report}
\end{center}
\vspace{0.5em}
\large{\today}\
\vspace{1em}
% Include the Plotly chart
<<plot_example_1_chart, fig = TRUE , echo = FALSE, warning=FALSE, out.width="100%">>=
plot_function()
@
%\includegraphics{plot_example_1.png}
\vspace{1em}
% ###################################################### PAGE 2: USER RESPONSES #######################################################
\noindent \textbf{User Responses:}
\begin{longtable}{|c|c|p{8cm}|}
\hline
\textbf{Question} & \textbf{Numeric Response} & \textbf{Text Response} \\ \hline
<<response_table, echo=FALSE, results='asis'>>=
responses <- read.csv("user_responses.csv")
for (i in 1:nrow(responses)) {
cat(paste0(responses$Question[i], " & ",
ifelse(is.na(responses$Numeric_Response[i]), "N/A", responses$Numeric_Response[i]), " & ",
responses$Text_Response[i], " \\\\ \\hline\n"))
}
@
\end{longtable}
\end{document}```