Nothing
## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
## ----packages, message=FALSE, warning=FALSE-----------------------------------
library(shiny)
library(bslib)
library(scoutbaR)
library(blockr.core)
## ----custom-plugin-setup, eval = FALSE, echo=FALSE----------------------------
# chr_ply <- function(x, fun, ..., length = 1L, use_names = FALSE) {
# vapply(x, fun, character(length), ..., USE.NAMES = use_names)
# }
#
# #' @keywords internal
# lgl_ply <- function(x, fun, ..., length = 1L, use_names = FALSE) {
# vapply(x, fun, logical(length), ..., USE.NAMES = use_names)
# }
#
# dropNulls <- function(x) {
# x[!lgl_ply(x, is.null)]
# }
#
# blk_icon <- function(category) {
# switch(
# category,
# "data" = "table",
# "file" = "file-import",
# "parse" = "cogs",
# "plot" = "chart-line",
# "transform" = "wand-magic-sparkles",
# "table" = "table"
# )
# }
#
# blk_choices <- function() {
# blk_cats <- sort(
# unique(chr_ply(available_blocks(), \(b) attr(b, "category")))
# )
#
# lapply(blk_cats, \(cat) {
# scout_section(
# label = cat,
# .list = dropNulls(
# unname(
# lapply(available_blocks(), \(choice) {
# if (attr(choice, "category") == cat) {
# scout_action(
# id = attr(choice, "classes")[1],
# label = attr(choice, "name"),
# description = attr(choice, "description"),
# icon = blk_icon(cat)
# )
# }
# })
# )
# )
# )
# })
# }
## flowchart TD
## subgraph board[board]
## subgraph plugins[plugins]
## subgraph manage_blocks[Manage blocks]
## end
## subgraph manage_links[Manage links]
## end
## subgraph manage_stacks[Manage stacks]
## end
## subgraph preserve_board[Preserve board]
## end
## subgraph generate_code[Generate code]
## end
## subgraph notify_user[Notify user]
## end
## subgraph edit_block[Edit block]
## end
## subgraph edit_stack[Edit stack]
## end
## end
## end
## ----eval=FALSE---------------------------------------------------------------
# main_ui <- function(id, board) {
# ns <- NS(id)
# board_ui(
# ns("board"),
# board,
# plugins = board_plugins(
# c(
# "preserve_board",
# "manage_blocks",
# "manage_links",
# "manage_stacks",
# "generate_code",
# "notify_user"
# )
# )
# )
# }
## ----eval=FALSE---------------------------------------------------------------
# main_server <- function(id, board) {
# moduleServer(
# id,
# function(input, output, session) {
# ns <- session$n
#
# app_state <- reactiveValues(
# # App state for module communication
# )
#
# # Board module
# board_server(
# "board",
# board,
# plugins = board_plugins(
# c(
# "preserve_board",
# "manage_blocks",
# "manage_links",
# "manage_stacks",
# "generate_code",
# "notify_user"
# )
# ),
# callbacks = list(),
# parent = app_state
# )
# }
# )
# }
## ----eval=FALSE---------------------------------------------------------------
# board_plugins <- function(which = NULL) {
#
# plugins <- plugins(
# preserve_board(server = ser_deser_server, ui = ser_deser_ui),
# manage_blocks(server = add_rm_block_server, ui = add_rm_block_ui),
# manage_links(server = add_rm_link_server, ui = add_rm_link_ui),
# manage_stacks(server = add_rm_stack_server, ui = add_rm_stack_ui),
# notify_user(server = block_notification_server),
# generate_code(server = gen_code_server, ui = gen_code_ui),
# edit_block(server = edit_block_server, ui = edit_block_ui),
# edit_stack(server = edit_stack_server, ui = edit_stack_ui)
# )
#
# if (is.null(which)) {
# return(plugins)
# }
#
# plugins[which]
# }
## ----eval=FALSE---------------------------------------------------------------
# manage_blocks <- function(server, ui) {
# new_plugin(server, ui, validator = expect_null, class = "manage_blocks")
# }
## ----custom-plugin-ui, eval=FALSE---------------------------------------------
# add_rm_block_ui <- function(id, board) {
# tagList(
# scoutbar(
# NS(id, "scoutbar"),
# placeholder = "Search for a block",
# actions = blk_choices(),
# theme = "dark",
# showRecentSearch = TRUE
# ),
# actionButton(
# NS(id, "add_block"),
# "New block",
# icon = icon("circle-plus"),
# )
# )
# }
## ----eval=FALSE---------------------------------------------------------------
# #' Add/remove block module
# #'
# #' Customizable logic for adding/removing blocks to the board.
# #'
# #' @param id Namespace ID
# #' @param board Reactive values object
# #' @param update Reactive value object to initiate board updates
# #' @param ... Extra arguments passed from parent scope
# #'
# #' @return A [shiny::reactiveValues()] object with components `add` and `rm`,
# #' where `add` may be `NULL` or a `block` object and `rm` be `NULL` or a string
# #' (block ID).
# #'
# #' @rdname add_rm_block
# #' @export
# add_rm_block_server <- function(id, board, update, ...) {
# moduleServer(
# id,
# function(input, output, session) {
# # SERVER LOGIC
#
# NULL
# }
# )
# }
## ----eval=FALSE---------------------------------------------------------------
# add_rm_block_server <- function(id, board, update, ...) {
# moduleServer(
# id,
# function(input, output, session) {
# # Trigger add block
# observeEvent(
# input$add_block,
# {
# update_scoutbar(
# session,
# "scoutbar",
# revealScoutbar = TRUE
# )
# }
# )
#
# NULL
# }
# )
# }
## ----custom-plugin-server, eval=FALSE-----------------------------------------
# add_rm_block_server <- function(id, board, update, ...) {
# moduleServer(
# id,
# function(input, output, session) {
# # Trigger add block
# observeEvent(
# input$add_block,
# {
# update_scoutbar(
# session,
# "scoutbar",
# revealScoutbar = TRUE
# )
# }
# )
#
# observeEvent(input$scoutbar, {
# new_blk <- as_blocks(create_block(input$scoutbar))
# update(
# list(blocks = list(add = new_blk))
# )
# })
#
# NULL
# }
# )
# }
## ----custom-plugin-helpers, eval=FALSE----------------------------------------
# custom_board_plugins <- function(which = NULL) {
# plugins <- plugins(
# manage_blocks(server = add_rm_block_server, ui = add_rm_block_ui)
# )
#
# if (is.null(which)) {
# return(plugins)
# }
#
# plugins[which]
# }
## ----custom-plugin-app, eval=FALSE--------------------------------------------
#| code-fold: true
# main_ui <- function(id, board) {
# ns <- NS(id)
# board_ui(
# ns("board"),
# board,
# plugins = custom_board_plugins(
# c(
# "manage_blocks"
# )
# )
# )
# }
#
# main_server <- function(id, board) {
# moduleServer(
# id,
# function(input, output, session) {
# ns <- session$n
#
# # Board module
# board_server(
# "board",
# board,
# plugins = custom_board_plugins(
# c(
# "manage_blocks"
# )
# ),
# callbacks = list()
# )
# }
# )
# }
#
# board <- new_board()
#
# ui <- page_fluid(
# main_ui("app", board)
# )
#
# server <- function(input, output, session) {
# main_server("app", board)
# }
#
# shinyApp(ui, server)
## ----shinylive_url, echo = FALSE, results = 'asis'----------------------------
# extract the code from knitr code chunks by ID
code <- paste0(
c(
"webr::install(\"blockr.core\", repos = \"https://cynkra.github.io/blockr.webR/\")",
knitr::knit_code$get("packages"),
knitr::knit_code$get("custom-plugin-setup"),
knitr::knit_code$get("custom-plugin-ui"),
knitr::knit_code$get("custom-plugin-server"),
knitr::knit_code$get("custom-plugin-helpers"),
knitr::knit_code$get("custom-plugin-app")
),
collapse = "\n"
)
url <- roxy.shinylive::create_shinylive_url(code, header = FALSE)
## ----shinylive_iframe, echo = FALSE, eval = TRUE------------------------------
shiny::tags$iframe(
class = "border border-5 rounded shadow-lg",
src = url,
style = "zoom: 0.75;",
width = "100%",
height = "1100px"
)
## ----custom-board-ui, eval=FALSE----------------------------------------------
# board_ui.custom_board <- function(id, x, plugins = list(), ...) {
# plugins <- as_plugins(plugins)
# div(
# id = paste0(id, "_board"),
# board_ui(id, plugins[["manage_blocks"]], x),
# div(
# id = paste0(id, "_blocks"),
# block_ui(id, x)
# )
# )
# }
## ----custom-block-ui, eval=FALSE----------------------------------------------
# get_block_registry <- function(x) {
# stopifnot(is_block(x))
# available_blocks()[[strsplit(attr(x, "ctor"), "new_")[[1]][2]]]
# }
#
# block_ui.custom_board <- function(id, x, blocks = NULL, ...) {
# block_card <- function(x, id, ns) {
# id <- paste0("block_", id)
#
# blk_info <- get_block_registry(x)
#
# div(
# class = "m-2",
# id = ns(id),
# shinyNextUI::card(
# variant = "bordered",
# shinyNextUI::card_header(
# className = "d-flex justify-content-between",
# icon(blk_icon(attr(blk_info, "category"))),
# sprintf(
# "Block: %s (id: %s)",
# attr(blk_info, "name"),
# gsub("block_", "", id)
# ),
# shinyNextUI::tooltip(
# icon("info-circle"),
# content = tagList(
# p(
# icon("lightbulb"),
# "How to use this block?",
# ),
# p(attr(blk_info, "description"), ".")
# )
# )
# ),
# shinyNextUI::divider(),
# shinyNextUI::card_body(
# expr_ui(ns(id), x),
# block_ui(ns(id), x)
# ),
# shinyNextUI::divider(),
# shinyNextUI::card_footer(
# sprintf(
# "Type: %s; Package: %s",
# attr(blk_info, "category"),
# attr(blk_info, "package")
# )
# )
# )
# )
# }
#
# stopifnot(is.character(id) && length(id) == 1L)
#
# if (is.null(blocks)) {
# blocks <- board_blocks(x)
# } else if (is.character(blocks)) {
# blocks <- board_blocks(x)[blocks]
# }
#
# stopifnot(is_blocks(blocks))
#
# tagList(
# Map(
# block_card,
# blocks,
# names(blocks),
# MoreArgs = list(ns = NS(id)),
# USE.NAMES = FALSE
# )
# )
# }
## ----custom-plugin-ui-nextui, eval=FALSE--------------------------------------
# add_rm_block_ui <- function(id, board) {
# tagList(
# scoutbar(
# NS(id, "scoutbar"),
# placeholder = "Search for a block",
# actions = blk_choices(),
# theme = "dark",
# showRecentSearch = TRUE
# ),
# shinyNextUI::actionButton(
# NS(id, "add_block"),
# "New block",
# icon = icon("circle-plus"),
# )
# )
# }
## ----custom-ui-app, eval=FALSE------------------------------------------------
#| code-fold: true
# board <- new_board(class = "custom_board")
#
# ui <- nextui_page(
# board_ui(
# "board",
# board,
# plugins = custom_board_plugins(
# c(
# "manage_blocks"
# )
# )
# )
# )
#
# server <- function(input, output, session) {
# board_server(
# "board",
# board,
# plugins = custom_board_plugins(
# c(
# "manage_blocks"
# )
# ),
# callbacks = list()
# )
# }
#
# shinyApp(ui, server)
## ----shinylive2_url, echo = FALSE, results = 'asis'---------------------------
# extract the code from knitr code chunks by ID
code <- paste0(
c(
"webr::install(\"blockr.core\", repos = \"https://cynkra.github.io/blockr.webR/\")",
"library(shiny)",
"library(scoutbaR)",
"library(blockr.core)",
"library(shinyNextUI)",
knitr::knit_code$get("custom-plugin-setup"),
knitr::knit_code$get("custom-plugin-ui-nextui"),
knitr::knit_code$get("custom-plugin-server"),
knitr::knit_code$get("custom-plugin-helpers"),
knitr::knit_code$get("custom-block-ui"),
knitr::knit_code$get("custom-board-ui"),
knitr::knit_code$get("custom-ui-app")
),
collapse = "\n"
)
url <- roxy.shinylive::create_shinylive_url(code, header = FALSE)
## ----shinylive2_iframe, echo = FALSE, eval = TRUE-----------------------------
shiny::tags$iframe(
class = "border border-5 rounded shadow-lg",
src = url,
style = "zoom: 0.75;",
width = "100%",
height = "1100px"
)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.