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

Add support for R Shiny with webR #51

Merged
merged 21 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b032bf9
Setup COOP/COEP/CORP HTTP headers for isolation
georgestagg Jul 24, 2023
9d638b3
Add webR to node dependencies
georgestagg Jul 24, 2023
e428c85
Initial setup of React hook for webR
georgestagg Jul 24, 2023
b44c422
Add infrastructure for webR httpuv communication
georgestagg Jul 24, 2023
0bffff5
Init pyodide/webR engine based on runApp arg
georgestagg Jul 25, 2023
8997f36
Support for webR in the Terminal component
georgestagg Jul 25, 2023
4147a98
Set up Viewer for running webR httpuv server
georgestagg Jul 25, 2023
6a066ab
Detect Shiny for R code using file extensions
georgestagg Jul 25, 2023
8910d78
Partially handle webR for OutputCell component
georgestagg Jul 25, 2023
adc3f32
Handle interrupting R code using Ctrl-C
georgestagg Jul 26, 2023
0870759
Setup examples for R and Python
georgestagg Jul 26, 2023
e739e53
Show R and Python examples based on Wasm engine
georgestagg Jul 26, 2023
a318ef0
Enable wasm engine to be selected at build time
georgestagg Jul 26, 2023
1194ed6
Create httpuv object and invoke callbacks directly
georgestagg Aug 21, 2023
a9e327f
Update webR to 0.2.0
georgestagg Aug 21, 2023
b9b0057
Only insert COI headers if requested in URL param
georgestagg Aug 21, 2023
e92dfa9
Support R blocks and apps in addition to Python
georgestagg Aug 22, 2023
456b7bf
Don't show the "reformat code" button for webR
georgestagg Jul 26, 2023
81f92b9
Fix file downloading in R Shiny apps
georgestagg Aug 22, 2023
289a32f
Fix download button in R download example
georgestagg Aug 21, 2023
0be3512
Reorganise examples/index.json hierarchy
georgestagg Sep 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
packages \
quarto quartoserve \
clean-packages clean distclean \
test test-watch
test test-watch webr

.DEFAULT_GOAL := help

Expand Down Expand Up @@ -93,6 +93,7 @@ submodules-pull:
all: node_modules \
$(BUILD_DIR)/shinylive/style-resets.css \
$(BUILD_DIR)/shinylive/pyodide \
$(BUILD_DIR)/shinylive/webr \
src/pyodide/pyodide.js \
src/pyodide/pyodide.d.ts \
pyodide_packages_local \
Expand Down Expand Up @@ -126,6 +127,11 @@ $(BUILD_DIR)/shinylive/pyodide:
curl -L https://github.com/pyodide/pyodide/releases/download/$(PYODIDE_VERSION)/$(PYODIDE_DIST_FILENAME) \
| tar --exclude "*test*.tar" --exclude "node_modules" -xvj

$(BUILD_DIR)/shinylive/webr: webr
webr:
mkdir -p $(BUILD_DIR)/shinylive/webr
cp -r node_modules/webr/dist/. $(BUILD_DIR)/shinylive/webr

# Copy pyodide.js and .d.ts to src/pyodide/. This is a little weird in that in
# `make all`, it comes after downloading pyodide. In the future we may be able
# to use a pyodide node module, but the one currently on npm is a bit out of
Expand Down Expand Up @@ -206,6 +212,18 @@ serve:
serve-prod:
node_modules/.bin/tsx scripts/build.ts --serve --prod

# Build JS resources (with minification) with webR as the default engine
buildjs-prod-r:
node_modules/.bin/tsx scripts/build.ts --prod --r

# Build and serve (with minification) with webR as the default engine
serve-prod-r:
node_modules/.bin/tsx scripts/build.ts --serve --prod --r

# Build and serve with webR as the default engine
serve-r:
node_modules/.bin/tsx scripts/build.ts --serve --r


# Build htmltools, shiny, and shinywidgets. This target must be run manually after
# updating the package submodules; it will not run automatically with `make all`
Expand Down
184 changes: 105 additions & 79 deletions examples/index.json
Original file line number Diff line number Diff line change
@@ -1,87 +1,113 @@
[
{
"category": "Basic",
"apps": ["basic_app", "app_with_plot"]
},
{
"category": "Featured",
"apps": [
"cpuinfo",
"orbit",
"regularization",
"wordle",
"plotly",
"ipyleaflet",
"camera"
]
},
{
"category": "Intermediate",
"apps": [
"multiple_source_files",
"read_local_csv_file",
"file_upload",
"file_download",
"insert_ui",
"input_update",
"modules",
"extra_packages",
"static_content",
"fetch",
"ipywidgets"
]
},
{
"category": "Inputs",
"apps": [
"input_text",
"input_numeric",
"input_slider",
"input_checkbox",
"input_switch",
"input_checkbox_group",
"input_select",
"input_radio",
"input_text_area",
"input_date",
"input_date_range",
"input_password"
]
},
{
"category": "Outputs",
"apps": [
"output_text",
"output_text_verbatim",
"output_ui",
"output_plot",
"output_table",
"output_data_frame_grid"
"engine": "python",
georgestagg marked this conversation as resolved.
Show resolved Hide resolved
"examples": [
{
"category": "Basic",
"apps": ["basic_app", "app_with_plot"]
},
{
"category": "Featured",
"apps": [
"cpuinfo",
"orbit",
"regularization",
"wordle",
"plotly",
"ipyleaflet",
"camera"
]
},
{
"category": "Intermediate",
"apps": [
"multiple_source_files",
"read_local_csv_file",
"file_upload",
"file_download",
"insert_ui",
"input_update",
"modules",
"extra_packages",
"static_content",
"fetch",
"ipywidgets"
]
},
{
"category": "Inputs",
"apps": [
"input_text",
"input_numeric",
"input_slider",
"input_checkbox",
"input_switch",
"input_checkbox_group",
"input_select",
"input_radio",
"input_text_area",
"input_date",
"input_date_range",
"input_password"
]
},
{
"category": "Outputs",
"apps": [
"output_text",
"output_text_verbatim",
"output_ui",
"output_plot",
"output_table",
"output_data_frame_grid"
]
},
{
"category": "Layout",
"apps": ["shinyswatch", "layout_sidebar", "layout_two_column"]
},
{
"category": "Reactivity",
"apps": [
"reactive_event",
"reactive_effect",
"reactive_calc",
"reactive_value"
]
},
{
"category": "Interactive plots",
"apps": [
"plot_interact_basic",
"plot_interact_select",
"plot_interact_exclude"
]
},
{
"category": "Non-Apps",
"apps": ["hello_world"]
}
]
},
{
"category": "Layout",
"apps": ["shinyswatch", "layout_sidebar", "layout_two_column"]
},
{
"category": "Reactivity",
"apps": [
"reactive_event",
"reactive_effect",
"reactive_calc",
"reactive_value"
"engine": "r",
"examples": [
{
"category": "R examples",
"apps": [
"001-hello",
"002-text",
"003-reactivity",
"004-mpg",
"005-sliders",
"006-tabsets",
"007-widgets",
"008-html",
"009-upload",
"010-download",
"011-timer"
]
}
]
},
{
"category": "Interactive plots",
"apps": [
"plot_interact_basic",
"plot_interact_select",
"plot_interact_exclude"
]
},
{
"category": "Non-Apps",
"apps": ["hello_world"]
}
]
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions examples/r/001-hello/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Title: Hello Shiny!
Author: RStudio, Inc.
AuthorUrl: http://www.rstudio.com/
License: MIT
DisplayMode: Showcase
Tags: getting-started
Type: Shiny
3 changes: 3 additions & 0 deletions examples/r/001-hello/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This small Shiny application demonstrates Shiny's automatic UI updates.

Move the *Number of bins* slider and notice how the `renderPlot` expression is automatically re-evaluated when its dependant, `input$bins`, changes, causing a histogram with a new number of bins to be rendered.
1 change: 1 addition & 0 deletions examples/r/001-hello/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello Shiny!
59 changes: 59 additions & 0 deletions examples/r/001-hello/app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
library(shiny)

# Define UI for app that draws a histogram ----
ui <- fluidPage(

# App title ----
titlePanel("Hello Shiny!"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Slider for the number of bins ----
sliderInput(inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30)

),

# Main panel for displaying outputs ----
mainPanel(

# Output: Histogram ----
plotOutput(outputId = "distPlot")

)
)
)

# Define server logic required to draw a histogram ----
server <- function(input, output) {

# Histogram of the Old Faithful Geyser Data ----
# with requested number of bins
# This expression that generates a histogram is wrapped in a call
# to renderPlot to indicate that:
#
# 1. It is "reactive" and therefore should be automatically
# re-executed when inputs (input$bins) change
# 2. Its output type is a plot
output$distPlot <- renderPlot({

x <- faithful$waiting
bins <- seq(min(x), max(x), length.out = input$bins + 1)

hist(x, breaks = bins, col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times")

})

}

# Create Shiny app ----
shinyApp(ui = ui, server = server)
8 changes: 8 additions & 0 deletions examples/r/002-text/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Title: Shiny Text
Author: RStudio, Inc.
AuthorUrl: http://www.rstudio.com/
License: MIT
DisplayMode: Showcase
Tags: getting-started
Type: Shiny

1 change: 1 addition & 0 deletions examples/r/002-text/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This example demonstrates output of raw text from R using the `renderPrint` function in `server` and the `verbatimTextOutput` function in `ui`. In this case, a textual summary of the data is shown using R's built-in `summary` function.
1 change: 1 addition & 0 deletions examples/r/002-text/about.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Shiny Text
64 changes: 64 additions & 0 deletions examples/r/002-text/app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
library(shiny)

# Define UI for dataset viewer app ----
ui <- fluidPage(

# App title ----
titlePanel("Shiny Text"),

# Sidebar layout with a input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Selector for choosing dataset ----
selectInput(inputId = "dataset",
label = "Choose a dataset:",
choices = c("rock", "pressure", "cars")),

# Input: Numeric entry for number of obs to view ----
numericInput(inputId = "obs",
label = "Number of observations to view:",
value = 10)
),

# Main panel for displaying outputs ----
mainPanel(

# Output: Verbatim text for data summary ----
verbatimTextOutput("summary"),

# Output: HTML table with requested number of observations ----
tableOutput("view")

)
)
)

# Define server logic to summarize and view selected dataset ----
server <- function(input, output) {

# Return the requested dataset ----
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})

# Generate a summary of the dataset ----
output$summary <- renderPrint({
dataset <- datasetInput()
summary(dataset)
})

# Show the first "n" observations ----
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})

}

# Create Shiny app ----
shinyApp(ui = ui, server = server)
Loading