Dynamically embed learnr tutorial within Shiny app

I have a Shiny app running on my own Ubuntu server, it runs flawlessly.

Embedded in my app I also include a learnr tutorial. Both the Shiny app (myapp/) and the learnr tutorial (mylearnr/) are inside /srv/shiny-server.

I call the learnr tutorial from within the Shiny app like this:

# UI side:
htmlOutput("practice")

# Server side:
output$practice <- renderUI({
    tags$iframe(
      src="https://myserver.com/shiny/mylearnr/", 
      width="100%", height="100%", frameBorder=0, style="height: 100vh;", scrolling = 'yes'
    )
  })

The problem with the current set-up is that the learnr tutorial being deployed is always the same. The code above just embeds the current HTML file inside /srv/shiny-server/mylearnr in the Shiny app.

I tried to make it such that the Shiny app renders a new learnr tutorial each time it runs, like below. But this gives an error, the learnr tutorial is not rendered, and the Shiny app ends up freezing.

# Server side:
output$practice <- renderUI({
    rmarkdown::render("/../mylearnr/mylearnr.Rmd")   # this did not work
    tags$iframe(
      src="https://myserver.com/shiny/mylearnr/", 
      width="100%", height="100%", frameBorder=0, style="height: 100vh;", scrolling = 'yes'
    )
  })

How can I achieve what I want? Any help appreciated.

Thanks in advance,
bruce

Can you please provide us with the error message?

What is the trigger for re-rendering the Rmd file? Or is it rendered only once on startup?

renderUI needs a updated reactive dependency to run again.

Hi,
Thanks for getting back at me and apologies for the late reply.

Here's the error message:

An error has occurred. Check your logs or contact the app author for clarification.

About your question: I have no trigger, hence it should be the case that the Rmd file is only rendered once per session. That is OK for me. I only want to have different HTML across sessions (users).

The Rmd file renders if I execute the rmarkdown::render() command manually. But I get this error while running the command from the Shiny app. I was wondering whether this could be a permissions problem. The files are in /srv/shiny-server with rw permissions for user and group and r permission for others...

Any suggestions are more than welcome, thanks in advance.

Are you making sure, that for each shiny session a separate HTML file is generated? Otherwise it might be the case, that the file is opened in one session while another tries to overwrite it.

What is written to the log?

I'm sorry I took so long to reply, I am now back on this project.

I considered what you suggested and I see your point. I did not indeed generate different HTMLs per app call. But, that was not easy in my current set up due to permission issues: rmarkdown::render() fails because it has no permission to write to /srv/shiny-server.

To circumvent the problem, I wrote code to render the HTML in a /tmp folder with a randomly generated name. It does create the temp folder, to which I copy the .Rmd file. rmarkdown::render() then does generate an HTML file. However, calling it from my app ends up with a 404 error (" Oops! This Page Could Not Be Found."). There's no Shiny log error file to look at now.

# UI side:
htmlOutput("practice")

# Server side:
output$practice <- renderUI({
    random.name <- "abc123" # to show simpler code here
    dir.create(paste0("/tmp/", random.name))
    
    file.copy(from = "../mylearnr/mylearnr.Rmd", 
              to   = paste0("/tmp/", random.name, "/mylearnr.Rmd"))
    
    rmarkdown::render(paste0("/tmp/", random.name, "/mylearnr.Rmd"))
    # This did create file "/tmp/abc123/mylearnr.html"

    tags$iframe(
      src = paste0("/tmp/", random.name), 
      width="100%", height="100%", frameBorder=0, style="height: 100vh;", scrolling = 'yes'
    )
    # But this gives a 404 error.
  })

What am I still missing?

Just to be sure: is there anything dynamic regarding your learnr tutorial (shiny session-wise)? Or should every client see the same html file? Regarding the temp folders please see this related answer.

Hi @ismirsehregal ,
Well, I think there are some dynamic aspects to the mylearnr.Rmd app. Besides having a few blocks of items, I do use some R code to randomly select some items from each block and to shuffle them up.

I checked the related answer that you forwarded me. I could not see how I could put it to use for my own purposes, unfortunately.

Do you have any specific suggestions?
Thanks a lot for your help.

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.