Currently three main styles:
- Autocomplete
- e.g. github copilot, windsurf
- Inline "ghost text" as you type
- Sometimes amazingly good; often pretty useless
- Need to train yourself to ignore spurious suggestions
| error404 = paste0( | |
| "<!DOCTYPE html>", | |
| "<html lang=\"en\">", | |
| "<head>", | |
| " <meta charset=\"UTF-8\">", | |
| " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">", | |
| " <title>Resources not found</title>", | |
| "</head>", | |
| "<body>", | |
| " <div class=\"main\">", |
| library(shiny) | |
| library(reactable) | |
| library(dplyr) | |
| ui <- fluidPage( | |
| actionButton(inputId = "edit", | |
| label = "Edit"), | |
| reactableOutput("table") | |
| ) |
| # How to call the new (as of 2023-03-01) ChatGTP API from R | |
| # Get your API key over here: https://platform.openai.com/ | |
| api_key <- "sk-5-your-actual-api-key-Fvau6" # Don't share this! 😅 | |
| library(httr) | |
| library(stringr) | |
| # Calls the ChatGTP API with the given promps and returns the answer | |
| ask_chatgtp <- function(prompt) { | |
| response <- POST( |
| # Just copy paste your "library" statements here using {datapasta}: | |
| packages <- c( | |
| "library(shiny)", "library(bs4Dash)", "library(shinyjs)", | |
| "library(shinyWidgets)", "library(firebase)", "library(glue)", | |
| "library(DBI)", "library(RPostgres)", "library(lubridate)", | |
| "library(htmlwidgets)", "library(shinybusy)" | |
| ) | |
| # rm "library()" leaving bare pkg chars: | |
| pkg_nms <- gsub(pattern = "library\\(", replacement = "", x = packages) |> |
| fileInputArea <- function(inputId, label, multiple = FALSE, accept = NULL, | |
| width = NULL, buttonLabel = "Browse...", placeholder = "No file selected") { | |
| restoredValue <- restoreInput(id = inputId, default = NULL) | |
| # Catch potential edge case - ensure that it's either NULL or a data frame. | |
| if (!is.null(restoredValue) && !is.data.frame(restoredValue)) { | |
| warning("Restored value for ", inputId, " has incorrect format.") | |
| restoredValue <- NULL | |
| } |
| switchInput <- function(inputId, label, value = FALSE, disabled = FALSE, width = NULL) { | |
| value <- shiny::restoreInput(id = inputId, default = value) | |
| inputTag <- htmltools::tags$input(id = inputId, type = "checkbox", role = "switch", class = "form-check-input") | |
| if (!is.null(value) && value) { | |
| inputTag$attribs$checked <- NA | |
| } | |
| if (!is.null(disabled) && disabled) { | |
| inputTag$attribs$disabled <- NA | |
| } | |
| htmltools::tags$div( |
As often happens, I found the official documentation and forum answers to be "close, but no cigar", and so had to experiment a little to get things working.
The main problem for me was a lack of concrete configuration examples. That's not entirely GitHub's fault: having migrated from Google Domains to Namecheap in the middle of this project, I was once again reminded of how many different ways there are to do things in the name service universe [1].
Although you'd think the simplest setup would be to merely configure for the subdomain case (https://www.example.com), in my experience using the apex domain (https://example.com) instead resulted in fewer complications.
So here's my recipe for using a custom domain with GitHub pages where Namecheap is the DNS provider:
(This post was motivated by a talk by @jnolis at CascadiaRConf 2021)
Recent versions of Shiny have an undocumented feature for handling POST requests that are not associated with any specific Shiny session. (Note that this functionality is missing our normal level of polish; it's a fairly low-level hook that I needed to make some things possible, but doesn't make anything easy.)
In a nutshell, it works by replacing your traditional ui object with a function(req), and then marking that function with an attribute indicating that it knows how to handle both GET and POST:
library(shiny)| positions <- data.frame(pos = c("QB","RB","WR","TE"), | |
| posdesc = c("Quarterback","Running Back","Wide Receiver","Tight End")) | |
| shinyWidgets::pickerInput( | |
| inputId = 'positions', | |
| label = 'position', | |
| choices = positions$pos, | |
| selected = positions$pos, | |
| multiple = TRUE, | |
| options = list( |