shiny::reactlogShow displays error, when running by batch file - r

Setting:
I have one Shiny-App (app.r) from which I want a reactive graph of all reactive elements. In my understanding, one must trigger these elements once before they are shown in the graph. Therefore, I created a Start_App.r which runs the app and records reactive elements and a Navigate_through_App.r-Script which navigates via RSelenium through the App. Because R is busy when running a shiny app, both scripts need to run in different R Sessions. Starting them 'by hand' results in the required reactive graph:
In order to automate the process of starting two R Sessions and executing the scripts, I created a simple Batch-file called Start.bat. It starts the shiny app, the RSelenium browser and navigates through the app as intended.
Problem:
When I run the batch-script, the files recorded by the reactlog-command can't be found on my machine:
It looks like there was a try to create this file (because there is this explicit path), but somehow it does not worked. Any ideas what could cause this problem?
Code:
(All files in the same folder)
app.r
library(shiny)
library(shinyjs)
jscode <- "shinyjs.closeWindow = function() { window.close(); }"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jscode, functions = c("closeWindow")),
actionButton("close", "Close window")
)
server <- function(input, output, session) {
observeEvent(input$close, {
js$closeWindow()
stopApp()
})
}
shinyApp(ui, server)
Start_App.r
#Install & load packages
if (!require("shiny")) install.packages("shiny")
library(shiny)
if (!require("reactlog")) install.packages("reactlog")
library(reactlog)
#tell shiny to log reactivity
#reactlog::reactlog_enable()
options(shiny.reactlog = TRUE)
#run App
runApp(getwd(), host = getOption("shiny.host", "127.0.0.1"), port=7777, launch.browser = TRUE)
#once app has closed, display reactlog from shiny
shiny::reactlogShow()
Navigate_through_App.r:
#Install & load packages
if (!require("RSelenium")) install.packages("RSelenium")
library(RSelenium)
#free all ports
system("taskkill /im java.exe /f", intern=FALSE, ignore.stdout=FALSE)
#Start Selenium and access shiny-app
rD <- rsDriver(port = 4564L, browser = "firefox") # "chrome" / "firefox" is possible
#Assign the client to an object
remDr <- rD[["client"]]
#Open Shiny-App
remDr$navigate("http://127.0.0.1:7777")
#Stop App
#Click button "App beenden & Browser schließen"
webElem <- remDr$findElement(using = 'xpath', value = '//*[#id="close"]')
webElem$clickElement()
Start.bat:
START /HIGH R -e "source('Start_App.r')"
Rscript Navigate_through_App.r
pause

Related

Deploy shiny app that can call runApp() inside application itself (specifically for tabulizer package)

I'm trying to deploy a Shiny app that allows the user to upload a pdf document and extract a table from a selected page. For this I'm using the package tabulizer. A basic reproducible example:
library(shiny)
library(tabulizer)
ui <- fluidPage(
fileInput("report", NULL,buttonLabel = "Upload report"),
numericInput("page","Specify page number",value = 1),
actionButton("extract","Extract"),
verbatimTextOutput("data")
)
server <- function(input, output, session) {
generate_data <- reactive({
req(input$report)
# This locate_area function calls runApp() from the tabulizer package
area <- locate_areas(file = input$report$datapath,
pages = input$page,
widget = "reduced")
table <- extract_tables(file = input$report$datapath,
pages = input$page,
area = area)
return(table)
})%>% bindCache(input$page) %>% bindEvent(input$extract)
output$data <- renderPrint({
# Just for the sake of this example to show it works
generate_data()
})
}
shinyApp(ui = ui, server = server)
If I run this locally, the locate_area() will make the pdf page pop-up on my viewer in RStudio and all is well. However, if I publish the app it doesn't run after clicking the action button. I know the problem comes from the locate_area() as it essentially calls another runApp within the shiny app. I have tried using different widgets for locate_area() to no avail. Does anybody know a way to circumvent this issue?
Judging by the relevant issues - issue 15 and issue 53 - it appears that your best way to go is really to copy the functionality from the original tabulizer function into your own app, as currently the package does not provide an easy integration with other Shiny apps.

Progress bar while running a bat file through shiny app

I am running a lengthy .bat file with an action button in a shiny app. I am able to show the progress bar, however, the progress bar(blue) prints about 10% and sits there for a long time. After the .bat file is finished, then the progress bar quickly moves to 100%. My question is: How can I show the progress bar moving at all times while the .bat file is executing. The code I am using is below but I am not able to provide the .bat file that I am running because it depends on other large files.
library(shiny)
library(shinyWidgets)
library(ggplot2)
library(shinycssloaders)
ui <- fluidPage(titlePanel(h1("Progress Bar Test",align="center")),
mainPanel(
sidebarPanel(
actionButton("buttonId", "Create exe file"))))
server <- function(input, output, session) {
observeEvent(input$buttonId, {
withProgress(message = 'Creating executable',
detail = 'It takes about 30 seconds per year...',{
bat <- shell("mybatchfile.bat,wait=TRUE")
for (i in 1:length(bat)){
incProgress(setProgress(i/length(bat)))
Sys.sleep(2)
}
} )}
)}
# Run the application
shinyApp(ui = ui, server = server)

Start R Shiny app as a background job programmatically

Dean Attali has provided a wonderful example on how to exit elegantly from a Shiny app using a close button which both closes the browser window and ends the Shiny session. Consider the following example (modification of the original code from Dean):
The ui.r:
library(shiny)
library(shinyjs)
jscode <- "shinyjs.closeWindow = function() { window.close(); }"
ui <- fluidPage(
useShinyjs(),
extendShinyjs(text = jscode, functions = c("closeWindow")),
htmlOutput(outputId = "exitHeading"),
actionButton(inputId = "closeGUI", label = "Exit")
)
The server.r:
library(shiny)
library(shinyjs)
server <- function(input, output, session) {
output$exitHeading <- renderText("Press the button below to exit the app")
observeEvent(input$closeGUI, {
js$closeWindow()
stopApp()
})
}
And running the app:
runApp(appDir = "/tmp")
My question is about how to start a Shiny app as a background job programmatically, so that the RStudio console is free for further use (or even start a second Shiny app in parallel) while the app is still running, and then end the job using the exit button from the app above. I am looking for a solution which can be added to a package which contains a Shiny app, like this one.
I have read this and have tried the provided sample app, but it still requires manual intervention by the user.
Can someone assist with this?
So as I mentioned in the comments you can achieve this by using the system which basically runs a terminal command, with the wait and show.output.on.console flags set to FALSE.
system('Rscript file.r', wait=F, show.output.on.console = F)
# if you want to access a file from in a package u need
# also in the source of the package you need to put the
# folder `directory` in `root.of.package/inst`
p <- system.file(file.path("directory", "myfile.r"), package = "my.package")
system(paste0('Rscript "', p, '"'), wait=F)

Shinyapp opens when initiated but does not begin listening. I close browser reopen then the shinyapp observes and reacts to input

So I have a prediction app that uses created datatables. I have all files in same directory. When I run the app in shinyapps, the application displays but the application does not respond to user input (or so it appears). But if I close browser and open again in a minute or so, the application works. The application runs correctly in RStudio.
# Top of global.R
library(data.table)
library (plyr)
library(stringr)
library(tm)
load("ngramd.RData")
nxtwd <- function(input=input) {
input <- tolower(input)
input <- iconv(input, "latin1", "ASCII", sub="")
input <- removePunctuation(input)
# Top portion of server.R
library(shiny)
shinyServer(function(input, output,session) {
observe({
if (nchar(as.character(input$text)) > 0) {
I have also added the load statement above the shinyServer and get the same response.
I am using RStudio and Windows 10.

Shiny open multiple browser tabs

In my Shiny app I want to open several URL's with a short delay between opening.
Here is some example code that works just fine when I run the app in my RStudio.
library(shiny)
URLs <- c("http://www.google.com", "http://www.stackoverflow.com")
ui <- fluidPage(
actionButton(
"click",
"Click here to open several browser tabs"
)
)
server <- function(input, output){
observeEvent(input$click, {
for (i in URLs){
browseURL(i)
Sys.sleep(1) #Short delay of 1 second
}
})
}
shinyApp(ui, server)
However, when I run this app on shinyapps.io, browseURL() doesn't work (as mentioned here).
Does anyone know how to open multiple browser tabs with a short delay between opening them, so that it also works when the app is deployed on shinyapps.io?
Would it be possible with R code or is JavaScript necessary?
This is a pretty old question, but answering in case others stumble upon while searching.
As mentioned in the reference you linked, I think you need to use some JS to accomplish this task. Below is an example of using the shinyjs package to define a shiny compatible browseURL function. Once we have the function defined we add a few lines to the ui and then call it in the server as js$browseURL().
Note that a pop-up blocker might block the effects of opening multiple tabs. Check your blocker settings if things don't seem to work.
library(shiny)
library(shinyjs)
# define js function for opening urls in new tab/window
js_code <- "
shinyjs.browseURL = function(url) {
window.open(url,'_blank');
}
"
URLs <- c("http://www.google.com", "http://www.stackoverflow.com")
ui <- fluidPage(
# set up shiny js to be able to call our browseURL function
useShinyjs(),
extendShinyjs(text = js_code, functions = 'browseURL'),
actionButton(
"click",
"Click here to open several browser tabs"
)
)
server <- function(input, output){
observeEvent(input$click, {
for (i in URLs){
js$browseURL(i)
Sys.sleep(1) #Short delay of 1 second
}
})
}
shinyApp(ui, server)

Resources