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

Docs (or helper functions?) on consuming Plumber APIs in R, Shiny and RMarkdown/Quarto #901

Open
slodge opened this issue Jan 12, 2023 · 2 comments
Labels
difficulty: intermediate Enterprising community members could help docs Related to documentation only effort: low < 1 day of work help wanted Solution is well-specified enough that any community member could fix

Comments

@slodge
Copy link

slodge commented Jan 12, 2023

I've been trying to explain to people inside my team how we will use Plumber APIs inside our other R code.

So far we've used a fork copy of [https://github.com/bergant/rapiclient] with some auth additions which I think will make R calling plumber APIs pretty straight-forward.

I am, however, struggling a bit with "good practice" when it comes to consuming anything except text and JSON inside e.g. Shiny and RMarkdown.

For example, I've been trying to use a PNG plot output today in a Shiny app. I've coded that into an app which an imageOutput like:

  iv_api <- ApiClient::api_get_plumber_api("demo_charts")

  output$iv_plot <- renderImage({
    req(input$which_security)
    Log("renderImage", input$which_security)
    width  <- session$clientData$output_iv_plot_width
    height <- session$clientData$output_iv_plot_height
    Log("renderImage", input$which_analyst, input$which_security, width, height)
    req(width)
    req(height)
    
    Log("Fetching")
    please_wait <- quickUdsDialog(paste0("Please wait... loading chart for ", input$which_security), 
                                            label="Loading",
                                            overlay_dismiss = FALSE,
                                            escape_dismiss = FALSE,
                                            closable = FALSE, 
                                            open = TRUE)
    on.exit({ hideUdsDialog(please_wait) })
    
    magic_resolution <- 96
    pngChart <- iv_api$Generate_Chart_for_analyst(input$which_security, width = width/magic_resolution, height = height/magic_resolution)
    
    # Use a temp file to save the output (It would have been more efficient for the PNG to never have been read in the first place!)
    outfile <- tempfile(fileext='.png')
    png::writePNG(pngChart, outfile)
    
    # Return a list containing the temporary file
    list(src = outfile,
         width = width,
         height = height,
         alt = paste0("Chart for ", input$which_security, " for ", input$which_analyst)
    )
  }, deleteFile = TRUE)

Note: I know this isn't optimal... still plenty to tweak and experiment with - would like to get the file saving direct into the httr::GET ideally... just fighting the rapiclient wrapper

The feature request here is: I think it'd be useful for the plumber docs to have a section on how to make Shiny apps and markdowns that interally use plumber requests for json data, for png's, for svg's and for htmlwidget's...

I also think it might be useful to add some helper functions to some library somewhere too - e.g. most of the above renderImage could be hidden away I think (especially if #897 provides a standard way of specifying image sizes)

@slodge
Copy link
Author

slodge commented Jan 13, 2023

For RMarkdown today I've been using chunk code a bit like:

\```{r fig.width=7, fig.height=5}

width <- knitr::opts_current$get("fig.width")
height <- knitr::opts_current$get("fig.height")

plot_counter_private <- 0
plot_counter <- function() {
  plot_counter_private <<- plot_counter_private + 1
  plot_counter_private
}

png_chart <- iv_api$Create_PNG_Chart_for(params, width = width, height = height)
#this is not a good path... what should we use? How do we get this into the _files folder? :/
#plot_path <- knitr::fig_path("iv_chart.png", knitr::opts_current, plot_counter())
plot_path <- paste0("iv_chart_", plot_counter(), ".png")
png::writePNG(png_chart, plot_path)
knitr::include_graphics(plot_path)

\```

It seems to work... but I've failed (so far) to work out how to do a loop of multiple charts (maybe I have to call child RMDs) and I'd also love to get these generated charts into the "files" knit directory...

Would be good to get some recommended practice here for how to call plumber based PNG/SVG charts and htmlwidgets in order to embed them in RMarkdowns (and soon in Quarto - but right now we've got lots built around RMarkdown and can't move yet)

A helper function or two might also help here - it's a bit ugly that every client markdown has to repeat the width/height/plot code? (Will work on this internally)

@meztez meztez added difficulty: intermediate Enterprising community members could help effort: low < 1 day of work docs Related to documentation only help wanted Solution is well-specified enough that any community member could fix labels Nov 24, 2023
@slodge
Copy link
Author

slodge commented Nov 25, 2023

Leaving this open for maintainers to decide if/when to implement. Happy for them to close it if required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: intermediate Enterprising community members could help docs Related to documentation only effort: low < 1 day of work help wanted Solution is well-specified enough that any community member could fix
Projects
None yet
Development

No branches or pull requests

2 participants