diff --git a/.lintr b/.lintr index fe5901b8..b7d87405 100644 --- a/.lintr +++ b/.lintr @@ -6,5 +6,6 @@ linters: linters_with_defaults( ) exclusions: list( "inst/examples/cdisc-plot/example.R", - "inst/sandbox" + "inst/sandbox", + "inst/shinylive" ) diff --git a/DESCRIPTION b/DESCRIPTION index f00e8569..d6ea5083 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -19,7 +19,7 @@ Authors@R: ) Description: A framework for data manipulation and visualization using a web-based point and click user interface. -URL: https://blockr-org.github.io/blockr, https://blockr-org.github.io/blockr/ +URL: https://bristolmyerssquibb.github.io/blockr License: GPL (>= 3) Encoding: UTF-8 Roxygen: list(markdown = TRUE) @@ -32,7 +32,6 @@ Imports: bslib, methods, DT, - blockr.data, htmltools, shinyAce, jsonlite, @@ -42,8 +41,8 @@ Imports: rlang, shinyWidgets Remotes: - blockr-org/blockr.data, - DivadNojnarg/DiagrammeR + DivadNojnarg/DiagrammeR, + BristolMyersSquibb/blockr.data Suggests: knitr, rmarkdown, @@ -55,6 +54,9 @@ Suggests: withr, ggplot2, vdiffr, - palmerpenguins + palmerpenguins, + blockr.data Config/testthat/edition: 3 VignetteBuilder: knitr +Depends: + R (>= 2.10) diff --git a/NAMESPACE b/NAMESPACE index 2e77fa3a..56a41f8a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -152,7 +152,6 @@ export(cat_logger) export(clear_workspace) export(cnd_logger) export(construct_block) -export(create_app_link) export(create_block) export(data_info) export(download_ui) @@ -266,7 +265,6 @@ export(validation_failure) export(value) export(values) export(write_log) -import(blockr.data) import(dplyr) import(shiny) importFrom(htmltools,htmlDependency) diff --git a/R/block-core.R b/R/block-core.R index 8d078a41..076db923 100644 --- a/R/block-core.R +++ b/R/block-core.R @@ -13,7 +13,6 @@ #' @param class Block subclass #' #' @export -#' @import blockr.data #' @import dplyr #' @importFrom stats setNames new_block <- function(fields, expr, name = rand_names(), ..., diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 00000000..42616776 Binary files /dev/null and b/R/sysdata.rda differ diff --git a/R/utils.R b/R/utils.R index 94f07c36..7dce5307 100644 --- a/R/utils.R +++ b/R/utils.R @@ -322,28 +322,25 @@ has_method <- function(x, generic) { #' Create shinylive iframe #' -#' @param app_code base64 app code. You can create it from https://shinylive.io/r -#' by writing code and click on share and copy the link. The code is located at -#' the end of the url. +#' Useful for pkgdown website +#' +#' @param url app url. A shinylive link. #' @param mode How to display the shinylive app. Default to app mode. #' @param header Whether to display the shinylive header. Default to TRUE. -#' -#' @export -create_app_link <- function(app_code, mode = c("app", "editor"), header = TRUE) { +#' @keywords internal +create_app_link <- function(url, mode = c("app", "editor"), header = TRUE) { mode <- match.arg(mode) - app_url <- sprintf( - "https://shinylive.io/r/%s/#code=%s", mode, app_code - ) + if (mode != "editor") url <- gsub("editor", mode, url) if (!header) { - app_url <- paste0(app_url, "&h=0") + url <- paste0(url, "&h=0") } tags$iframe( # To allow the content to fill the full screen card class = "html-fill-item", - src = app_url, + src = url, height = "700", width = "100%", style = "border: 1px solid rgba(0,0,0,0.175); border-radius: .375rem;", @@ -353,6 +350,19 @@ create_app_link <- function(app_code, mode = c("app", "editor"), header = TRUE) ) } +code_chunk <- function(output, language = "r") { + cat(paste0("```", language)) + cat(output) + cat("\n```\n") +} + +print_shinylive_r_code <- function(name) { + path <- system.file(sprintf("shinylive/apps/%s/app.R", name), package = "blockr") + lines <- readLines(path) + to_remove <- grep("webr::", lines) + code_chunk(cat(paste(lines[-to_remove], collapse = "\n"))) +} + get_block_title <- function(x) { registry <- available_blocks() block <- registry[sapply(registry, \(blk) { diff --git a/README.Rmd b/README.Rmd index 62cb16ae..7d4104c2 100644 --- a/README.Rmd +++ b/README.Rmd @@ -28,48 +28,35 @@ library(DiagrammeR) ## Why blockr? -`{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and __code-free__ approach to building data pipelines. It allows users to create __powerful__ data workflows using pre-built __blocks__ that can be easily __connected__, all without writing a single line of code. - -```{r, echo=FALSE, eval=TRUE, message=FALSE} -mermaid(" - flowchart TD - subgraph LR workspace[Workspace] - subgraph stack1[Stack] - direction LR - subgraph input_block[Block 1] - input(Data: dataset, browser, ...) - end - subgraph transform_block[Block 2] - transform(Transform block: filter, select ...) - end - subgraph output_block[Block 3] - output(Result/transform: plot, filter, ...) - end - input_block --> |data| transform_block --> |data| output_block - end - subgraph stack2[Stack 2] - stack1_data[Stack 1 data] --> |data| transform2[Transform] - end - stack1 --> |data| stack2 - subgraph stackn[Stack n] - stacki_data[Stack i data] --> |data| transformn[Transform] --> |data| Visualize - end - stack2 ---> |... data| stackn - end - ", - width = "100%" -) |> - htmlwidgets::onRender( - "function(el, x) { - el.classList.add('text-center') - } - " - ) +`{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and __code-free__ approach to building data pipelines. + +## Who is it for? + +`{blockr}` has 2 main user targets: + +1. On the one hand, it empowers __non technical__ users to create insightful data workflows using pre-built blocks that can be __easily__ connected, all without writing a single line of code. + +Below is a simple pre-built case study involving `{blockr}`. We use the palmerpenguins dataset to find out which femal species has the largest flippers. This tiny dashboard is composed of 4 steps: import the data, filter, create the plot and chose the geometry (points). Within each step (block), the user can change inputs and see the changes propagate in real time. Notice that the filter step requires to press a submit button before moving forward, which prevents the plot from appearing first. This is to prevent long running task from being run unecessarily. You can find more in other vignettes. + +```{r blockr-penguins-stack, echo=FALSE, fig.cap='Penguins app demo', fig.align = 'center', out.width='100%'} +knitr::include_graphics("vignettes/figures/blockr-penguins-stack.png") +``` + +You can of course start with a totally empty dashboard and create your own analysis from scratch. + +2. On the other hand, it provides __developers__ with a set of tools to seamlessly create new blocks, thereby enhancing the entire framework and fostering __collaboration__ within organizations teams. For instance, regarding the previous example, below is what it takes to create such dashboard. + +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +blockr:::print_shinylive_r_code("palmer-penguins") ``` -To get started, we invite you to read this [vignette](https://blockr-org.github.io/blockr/articles/blockr.html). +Note that the `{blockr.ggplot2}` [package](https://github.com/BristolMyersSquibb/blockr.ggplot2) exposes some ready to use blocks as shown above. + +## How to get started? -To get a better idea of `{blockr}` capabilities in various data context, you can look at this [vignette](https://blockr-org.github.io/blockr/articles/blockr_examples.html). +To get started, we invite you to read this [vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr.html). + +To get a better idea of `{blockr}` capabilities in various data context, you can look at this [vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr_examples.html). ## Key features @@ -84,64 +71,7 @@ To get a better idea of `{blockr}` capabilities in various data context, you can You can install the development version of blockr from [GitHub](https://github.com/) with: ```r -pak::pak("blockr-org/blockr") -``` - -## Example: palmer penguins case study - -Below is a simple case study involving `{blockr}`. We use the palmerpenguins dataset to find out which -femal species has the largest flippers. We create 2 custom blocks allowing to create our plot block (see the plot vignette for more details). Note that the `{blockr.ggplot2}` package exposes some ready to use blocks. - -```{r, eval=FALSE} -library(blockr) -library(palmerpenguins) -library(ggplot2) - -new_ggplot_block <- function(col_x = character(), col_y = character(), ...) { - - data_cols <- function(data) colnames(data) - - new_block( - fields = list( - x = new_select_field(col_x, data_cols, type = "name"), - y = new_select_field(col_y, data_cols, type = "name") - ), - expr = quote( - ggplot(mapping = aes(x = .(x), y = .(y))) - ), - class = c("ggplot_block", "plot_block"), - ... - ) -} - -new_geompoint_block <- function(color = character(), shape = character(), ...) { - - data_cols <- function(data) colnames(data$data) - - new_block( - fields = list( - color = new_select_field(color, data_cols, type = "name"), - shape = new_select_field(shape, data_cols, type = "name") - ), - expr = quote( - geom_point(aes(color = .(color), shape = .(shape)), size = 2) - ), - class = c("plot_layer_block", "plot_block"), - ... - ) -} - -stack <- new_stack( - data_block = new_dataset_block("penguins", "palmerpenguins"), - filter_block = new_filter_block("sex", "female"), - plot_block = new_ggplot_block("flipper_length_mm", "body_mass_g"), - layer_block = new_geompoint_block("species", "species") -) -serve_stack(stack) -``` - -```{r blockr-penguins-stack, echo=FALSE, fig.cap='Penguins app demo', fig.align = 'center', out.width='100%'} -knitr::include_graphics("vignettes/figures/blockr-penguins-stack.png") +pak::pak("BristolMyersSquibb/blockr") ``` ## Contribute diff --git a/README.md b/README.md index 71c6ba7c..698dc2b0 100644 --- a/README.md +++ b/README.md @@ -15,48 +15,43 @@ `{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and **code-free** approach to building -data pipelines. It allows users to create **powerful** data workflows -using pre-built **blocks** that can be easily **connected**, all without -writing a single line of code. +data pipelines. -![](man/figures/README-unnamed-chunk-2-1.png) +## Who is it for? -To get started, we invite you to read this -[vignette](https://blockr-org.github.io/blockr/articles/blockr.html). - -To get a better idea of `{blockr}` capabilities in various data context, -you can look at this -[vignette](https://blockr-org.github.io/blockr/articles/blockr_examples.html). +`{blockr}` has 2 main user targets: -## Key features +1. On the one hand, it empowers **non technical** users to create + insightful data workflows using pre-built blocks that can be + **easily** connected, all without writing a single line of code. -1. **User-Friendly Interface**: Build data pipelines with intuitive - interface. -2. **Flexibility**: Easily add, remove, or rearrange blocks in your - pipeline. -3. **Extensibility**: Developers can create custom blocks to extend - functionality. -4. **Reproducibility**: Pipelines created with `blockr` are easily - shareable and reproducible, with exportable code. -5. **Interactivity**: Real-time feedback as you build and modify your - pipeline. +Below is a simple pre-built case study involving `{blockr}`. We use the +palmerpenguins dataset to find out which femal species has the largest +flippers. This tiny dashboard is composed of 4 steps: import the data, +filter, create the plot and chose the geometry (points). Within each +step (block), the user can change inputs and see the changes propagate +in real time. Notice that the filter step requires to press a submit +button before moving forward, which prevents the plot from appearing +first. This is to prevent long running task from being run unecessarily. +You can find more in other vignettes. -## Installation +
-You can install the development version of blockr from -[GitHub](https://github.com/) with: +Penguins app demo +

+Penguins app demo +

-``` r -pak::pak("blockr-org/blockr") -``` +
-## Example: palmer penguins case study +You can of course start with a totally empty dashboard and create your +own analysis from scratch. -Below is a simple case study involving `{blockr}`. We use the -palmerpenguins dataset to find out which femal species has the largest -flippers. We create 2 custom blocks allowing to create our plot block -(see the plot vignette for more details). Note that the -`{blockr.ggplot2}` package exposes some ready to use blocks. +2. On the other hand, it provides **developers** with a set of tools to + seamlessly create new blocks, thereby enhancing the entire framework + and fostering **collaboration** within organizations teams. For + instance, regarding the previous example, below is what it takes to + create such dashboard. ``` r library(blockr) @@ -106,14 +101,40 @@ stack <- new_stack( serve_stack(stack) ``` -
+Note that the `{blockr.ggplot2}` +[package](https://github.com/BristolMyersSquibb/blockr.ggplot2) exposes +some ready to use blocks as shown above. -Penguins app demo -

-Penguins app demo -

+## How to get started? -
+To get started, we invite you to read this +[vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr.html). + +To get a better idea of `{blockr}` capabilities in various data context, +you can look at this +[vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr_examples.html). + +## Key features + +1. **User-Friendly Interface**: Build data pipelines with intuitive + interface. +2. **Flexibility**: Easily add, remove, or rearrange blocks in your + pipeline. +3. **Extensibility**: Developers can create custom blocks to extend + functionality. +4. **Reproducibility**: Pipelines created with `blockr` are easily + shareable and reproducible, with exportable code. +5. **Interactivity**: Real-time feedback as you build and modify your + pipeline. + +## Installation + +You can install the development version of blockr from +[GitHub](https://github.com/) with: + +``` r +pak::pak("BristolMyersSquibb/blockr") +``` ## Contribute diff --git a/_pkgdown.yml b/_pkgdown.yml index ca9d55fd..5e7cd016 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,4 +1,4 @@ -url: https://blockr-org.github.io/blockr/ +url: https://bristolmyerssquibb.github.io/blockr/ home: title: Building blocks for data manipulation and visualization operations. @@ -14,16 +14,23 @@ template: -articles: -- title: User guide - navbar: ~ - contents: - - blockr_examples - - data-blocks - - registry - - plot-block - - new-field - - developer-guide +navbar: + components: + articles: + text: Developer guides + menu: + - text: Data blocks + href: articles/data-blocks.html + - text: Block registry + href: articles/registry.html + - text: How to create a plot block? + href: articles/plot-block.html + - text: How to create a new field? + href: articles/new-field.html + - text: More examples + href: articles/blockr-examples.html + - text: Internals + href: articles/internals.html reference: - title: Fields core elements @@ -201,4 +208,3 @@ news: releases: - text: "blockr 0.0.2" - text: "blockr 0.0.1.9000" - \ No newline at end of file diff --git a/index.Rmd b/index.Rmd index 6444deb2..8417c1f6 100644 --- a/index.Rmd +++ b/index.Rmd @@ -30,48 +30,43 @@ library(DiagrammeR) ## Why blockr? -`{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and __code-free__ approach to building data pipelines. It allows users to create __powerful__ data workflows using pre-built __blocks__ that can be easily __connected__, all without writing a single line of code. - -```{r, echo=FALSE, message=FALSE} -mermaid(" - flowchart TD - subgraph LR workspace[Workspace] - subgraph stack1[Stack] - direction LR - subgraph input_block[Block 1] - input(Data: dataset, browser, ...) - end - subgraph transform_block[Block 2] - transform(Transform block: filter, select ...) - end - subgraph output_block[Block 3] - output(Result/transform: plot, filter, ...) - end - input_block --> |data| transform_block --> |data| output_block - end - subgraph stack2[Stack 2] - stack1_data[Stack 1 data] --> |data| transform2[Transform] - end - stack1 --> |data| stack2 - subgraph stackn[Stack n] - stacki_data[Stack i data] --> |data| transformn[Transform] --> |data| Visualize - end - stack2 ---> |... data| stackn - end - ", - width = "100%" -) |> - htmlwidgets::onRender( - "function(el, x) { - el.classList.add('text-center') - } - " - ) +`{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and __code-free__ approach to building data pipelines. + +## Who is it for? + +`{blockr}` has 2 main user targets: + +1. On the one hand, it empowers __non technical__ users to create insightful data workflows using pre-built blocks that can be __easily__ connected, all without writing a single line of code. + +Below is a simple pre-built case study involving `{blockr}`. We use the palmerpenguins dataset to find out which femal species has the largest flippers. This tiny dashboard is composed of 4 steps: import the data, filter, create the plot and chose the geometry (points). Within each step (block), the user can change inputs and see the changes propagate in real time. Notice that the filter step requires to press a submit button before moving forward, which prevents the plot from appearing first. This is to prevent long running task from being run unecessarily. You can find more in other vignettes. + +```{r, echo=FALSE} +# shinylive container +card( + blockr:::create_app_link( + blockr:::shinylive_links["palmer-penguins"], + "app", + header = FALSE + ), + full_screen = TRUE +) +``` + +You can of course start with a totally empty dashboard and create your own analysis from scratch. + +2. On the other hand, it provides __developers__ with a set of tools to seamlessly create new blocks, thereby enhancing the entire framework and fostering __collaboration__ within organizations teams. For instance, regarding the previous example, below is what it takes to create such dashboard. + +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +blockr:::print_shinylive_r_code("palmer-penguins") ``` -To get started, we invite you to read this [vignette](https://blockr-org.github.io/blockr/articles/blockr.html). +Note that the `{blockr.ggplot2}` [package](https://github.com/BristolMyersSquibb/blockr.ggplot2) exposes some ready to use blocks as shown above. -To get a better idea of `{blockr}` capabilities in various data context, you can look at this [vignette](https://blockr-org.github.io/blockr/articles/blockr_examples.html). +## How to get started? + +To get started, we invite you to read this [vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr.html). + +To get a better idea of `{blockr}` capabilities in various data context, you can look at this [vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr_examples.html). ## Key features @@ -86,71 +81,7 @@ To get a better idea of `{blockr}` capabilities in various data context, you can You can install the development version of blockr from [GitHub](https://github.com/) with: ```r -pak::pak("blockr-org/blockr") -``` - -## Example: palmer penguins case study - -Below is a simple case study involving `{blockr}`. We use the palmerpenguins dataset to find out which -femal species has the largest flippers. We create 2 custom blocks allowing to create our plot block (see the plot vignette for more details). Note that the `{blockr.ggplot2}` package exposes some ready to use blocks. - -
-
- -
- - - - - -
- -```{r, eval=FALSE} -library(blockr) -library(palmerpenguins) -library(ggplot2) - -new_ggplot_block <- function(col_x = character(), col_y = character(), ...) { - - data_cols <- function(data) colnames(data) - - new_block( - fields = list( - x = new_select_field(col_x, data_cols, type = "name"), - y = new_select_field(col_y, data_cols, type = "name") - ), - expr = quote( - ggplot(mapping = aes(x = .(x), y = .(y))) - ), - class = c("ggplot_block", "plot_block"), - ... - ) -} - -new_geompoint_block <- function(color = character(), shape = character(), ...) { - - data_cols <- function(data) colnames(data$data) - - new_block( - fields = list( - color = new_select_field(color, data_cols, type = "name"), - shape = new_select_field(shape, data_cols, type = "name") - ), - expr = quote( - geom_point(aes(color = .(color), shape = .(shape)), size = 2) - ), - class = c("plot_layer_block", "plot_block"), - ... - ) -} - -stack <- new_stack( - data_block = new_dataset_block("penguins", "palmerpenguins"), - filter_block = new_filter_block("sex", "female"), - plot_block = new_ggplot_block("flipper_length_mm", "body_mass_g"), - layer_block = new_geompoint_block("species", "species") -) -serve_stack(stack) +pak::pak("BristolMyersSquibb/blockr") ``` ## Contribute diff --git a/index.md b/index.md index 688c4d74..92a44bf0 100644 --- a/index.md +++ b/index.md @@ -15,69 +15,46 @@ `{blockr}` is an R package designed to democratize data analysis by providing a flexible, intuitive, and **code-free** approach to building -data pipelines. It allows users to create **powerful** data workflows -using pre-built **blocks** that can be easily **connected**, all without -writing a single line of code. +data pipelines. -![](man/figures/README-unnamed-chunk-2-1.png) +## Who is it for? -To get started, we invite you to read this -[vignette](https://blockr-org.github.io/blockr/articles/blockr.html). - -To get a better idea of `{blockr}` capabilities in various data context, -you can look at this -[vignette](https://blockr-org.github.io/blockr/articles/blockr_examples.html). +`{blockr}` has 2 main user targets: -## Key features - -1. **User-Friendly Interface**: Build data pipelines with intuitive - interface. -2. **Flexibility**: Easily add, remove, or rearrange blocks in your - pipeline. -3. **Extensibility**: Developers can create custom blocks to extend - functionality. -4. **Reproducibility**: Pipelines created with `blockr` are easily - shareable and reproducible, with exportable code. -5. **Interactivity**: Real-time feedback as you build and modify your - pipeline. +1. On the one hand, it empowers **non technical** users to create + insightful data workflows using pre-built blocks that can be + **easily** connected, all without writing a single line of code. -## Installation - -You can install the development version of blockr from -[GitHub](https://github.com/) with: - -``` r -pak::pak("blockr-org/blockr") -``` - -## Example: palmer penguins case study - -Below is a simple case study involving `{blockr}`. We use the +Below is a simple pre-built case study involving `{blockr}`. We use the palmerpenguins dataset to find out which femal species has the largest -flippers. We create 2 custom blocks allowing to create our plot block -(see the plot vignette for more details). Note that the -`{blockr.ggplot2}` package exposes some ready to use blocks. - -
- -
- - - +flippers. This tiny dashboard is composed of 4 steps: import the data, +filter, create the plot and chose the geometry (points). Within each +step (block), the user can change inputs and see the changes propagate +in real time. Notice that the filter step requires to press a submit +button before moving forward, which prevents the plot from appearing +first. This is to prevent long running task from being run unecessarily. +You can find more in other vignettes. + +
+
+
- - + -
+You can of course start with a totally empty dashboard and create your +own analysis from scratch. + +2. On the other hand, it provides **developers** with a set of tools to + seamlessly create new blocks, thereby enhancing the entire framework + and fostering **collaboration** within organizations teams. For + instance, regarding the previous example, below is what it takes to + create such dashboard. + ``` r library(blockr) library(palmerpenguins) @@ -126,6 +103,41 @@ stack <- new_stack( serve_stack(stack) ``` +Note that the `{blockr.ggplot2}` +[package](https://github.com/BristolMyersSquibb/blockr.ggplot2) exposes +some ready to use blocks as shown above. + +## How to get started? + +To get started, we invite you to read this +[vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr.html). + +To get a better idea of `{blockr}` capabilities in various data context, +you can look at this +[vignette](https://bristolmyerssquibb.github.io/blockr/articles/blockr_examples.html). + +## Key features + +1. **User-Friendly Interface**: Build data pipelines with intuitive + interface. +2. **Flexibility**: Easily add, remove, or rearrange blocks in your + pipeline. +3. **Extensibility**: Developers can create custom blocks to extend + functionality. +4. **Reproducibility**: Pipelines created with `blockr` are easily + shareable and reproducible, with exportable code. +5. **Interactivity**: Real-time feedback as you build and modify your + pipeline. + +## Installation + +You can install the development version of blockr from +[GitHub](https://github.com/) with: + +``` r +pak::pak("BristolMyersSquibb/blockr") +``` + ## Contribute Easiest is to run `make`, otherwise: diff --git a/inst/shinylive/apps/ae-forest-plot/app.R b/inst/shinylive/apps/ae-forest-plot/app.R new file mode 100644 index 00000000..c778c670 --- /dev/null +++ b/inst/shinylive/apps/ae-forest-plot/app.R @@ -0,0 +1,159 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) +webr::install("blockr.pharmaverseadam", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) +library(dplyr) +library(tidyr) +library(forestplot) +library(blockr.pharmaverseadam) + +# Function to create adverse event forest plot +create_ae_forest_plot <- function(data, usubjid_col, arm_col, aedecod_col, n_events) { + data <- data |> filter(.data[[arm_col]] != "Placebo") + # Convert column names to strings + usubjid_col <- as.character(substitute(usubjid_col)) + arm_col <- as.character(substitute(arm_col)) + aedecod_col <- as.character(substitute(aedecod_col)) + + # Calculate the total number of subjects in each arm + n_subjects <- data |> + select(all_of(c(usubjid_col, arm_col))) |> + distinct() |> + group_by(across(all_of(arm_col))) |> + summarise(n = n(), .groups = "drop") + + # Calculate AE frequencies and proportions + ae_summary <- data |> + group_by(across(all_of(c(arm_col, aedecod_col)))) |> + summarise(n_events = n_distinct(.data[[usubjid_col]]), .groups = "drop") |> + left_join(n_subjects, by = arm_col) |> + mutate(proportion = n_events / n) + + # Select top N most frequent AEs across all arms + top_aes <- ae_summary |> + group_by(across(all_of(aedecod_col))) |> + summarise(total_events = sum(n_events), .groups = "drop") |> + top_n(n_events, total_events) |> + pull(all_of(aedecod_col)) + + # Get unique treatment arms + arms <- unique(data[[arm_col]]) + if (length(arms) != 2) { + stop("This plot requires exactly two treatment arms.") + } + active_arm <- arms[1] + control_arm <- arms[2] + + # Filter for top AEs and calculate relative risk + ae_rr <- ae_summary |> + filter(.data[[aedecod_col]] %in% top_aes) |> + pivot_wider( + id_cols = all_of(aedecod_col), + names_from = all_of(arm_col), + values_from = c(n_events, n, proportion) + ) |> + mutate( + RR = .data[[paste0("proportion_", active_arm)]] / .data[[paste0("proportion_", control_arm)]], + lower_ci = exp(log(RR) - 1.96 * sqrt( + 1 / .data[[paste0("n_events_", active_arm)]] + + 1 / .data[[paste0("n_events_", control_arm)]] - + 1 / .data[[paste0("n_", active_arm)]] - + 1 / .data[[paste0("n_", control_arm)]] + )), + upper_ci = exp(log(RR) + 1.96 * sqrt( + 1 / .data[[paste0("n_events_", active_arm)]] + + 1 / .data[[paste0("n_events_", control_arm)]] - + 1 / .data[[paste0("n_", active_arm)]] - + 1 / .data[[paste0("n_", control_arm)]] + )) + ) + + # Prepare data for forest plot + forest_data <- ae_rr |> + mutate( + label = paste0( + .data[[aedecod_col]], " (", + .data[[paste0("n_events_", active_arm)]], "/", .data[[paste0("n_", active_arm)]], " vs ", + .data[[paste0("n_events_", control_arm)]], "/", .data[[paste0("n_", control_arm)]], ")" + ) + ) + + # Create forest plot + forestplot( + labeltext = cbind( + forest_data$label, + sprintf("%.2f (%.2f-%.2f)", forest_data$RR, forest_data$lower_ci, forest_data$upper_ci) + ), + mean = forest_data$RR, + lower = forest_data$lower_ci, + upper = forest_data$upper_ci, + align = c("l", "r"), + graphwidth = unit(60, "mm"), + cex = 0.9, + lineheight = unit(8, "mm"), + boxsize = 0.35, + col = fpColors(box = "royalblue", line = "darkblue", summary = "royalblue"), + txt_gp = fpTxtGp(label = gpar(cex = 0.9), ticks = gpar(cex = 0.9), xlab = gpar(cex = 0.9)), + xlab = paste("Relative Risk (", active_arm, " / ", control_arm, ")"), + zero = 1, + lwd.zero = 2, + lwd.ci = 2, + xticks = c(0.5, 1, 2, 4), + grid = TRUE, + title = paste("Relative Risk of Adverse Events (", active_arm, " vs ", control_arm, ")") + ) +} + +new_forest_plot_block <- function(...) { + new_block( + fields = list( + usubjid_col = new_select_field( + "USUBJID", + function(data) colnames(data), + multiple = FALSE, + title = "Subject ID Column" + ), + arm_col = new_select_field( + "ACTARM", + function(data) colnames(data), + multiple = FALSE, + title = "Treatment Arm Column" + ), + aedecod_col = new_select_field( + "AEDECOD", + function(data) colnames(data), + multiple = FALSE, + title = "AE Term Column" + ), + n_events = new_numeric_field( + 10, + min = 5, max = 20, step = 1, + title = "Number of Top AEs to Display" + ) + ), + expr = substitute({ + my_fun(data, .(usubjid_col), .(arm_col), .(aedecod_col), .(n_events)) + }, list(my_fun = create_ae_forest_plot)), + class = c("adverse_event_plot_block", "plot_block"), + ... + ) +} + +# Register the custom block +register_block( + new_forest_plot_block, + name = "Adverse Event Forest Plot", + description = "Create a forest plot of adverse events comparing two treatment arms", + classes = c("adverse_event_plot_block", "plot_block"), + input = "data.frame", + output = "plot" +) + +# Create the stack +clinical_trial_stack <- new_stack( + new_adam_block(selected = "adae"), + # filter_in_block(), + new_forest_plot_block() +) + +serve_stack(clinical_trial_stack) diff --git a/inst/shinylive/apps/custom-field/app.R b/inst/shinylive/apps/custom-field/app.R new file mode 100644 index 00000000..808d7ea2 --- /dev/null +++ b/inst/shinylive/apps/custom-field/app.R @@ -0,0 +1,98 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) + +new_slider_field <- function( + value = numeric(), + min = numeric(), + max = numeric(), + step = numeric(), + ...) { + blockr::new_field( + value = value, + min = min, + max = max, + step = step, + ..., + class = "slider_field" + ) +} + +ui_input.slider_field <- function(x, id, name) { + shiny::sliderInput( + blockr::input_ids(x, id), + name, + value = blockr::value(x, "value"), + min = blockr::value(x, "min"), + max = blockr::value(x, "max"), + step = blockr::value(x, "step") + ) +} + +validate_field.slider_field <- function(x) { + val <- value(x) + min <- value(x, "min") + max <- value(x, "max") + step <- value(x, "step") + + validate_number(val) + + if (length(min)) { + validate_number(min, "min") + } + + if (length(max)) { + validate_number(max, "max") + } + + if (length(step)) { + validate_number(step, "step") + } + + NextMethod() +} + +ui_update.slider_field <- function(x, session, id, name) { + updateSliderInput( + session, + blockr::input_ids(x, id), + name, + blockr::value(x), + blockr::value(x, "min"), + blockr::value(x, "max"), + blockr::value(x, "step") + ) +} + +registerS3method("ui_input", "slider_field", ui_input.slider_field) +registerS3method("ui_update", "slider_field", ui_update.slider_field) + +new_slice_block <- function(from = 0, ...) { + + n_rows <- \(data) nrow(data) + + fields <- list( + rows = new_slider_field( + value = from, + min = 0, + max = n_rows, + step = 1, + title = "Select rows" + ) + ) + + new_block( + fields = fields, + expr = quote(dplyr::slice(seq_len(.(rows)))), + name = "Slider slice block", + ..., + class = c("slice_block", "transform_block") + ) +} + +serve_stack( + new_stack( + new_dataset_block("iris"), + new_slice_block(5) + ) +) diff --git a/inst/shinylive/apps/dataset-block/app.R b/inst/shinylive/apps/dataset-block/app.R new file mode 100644 index 00000000..2b56aeb8 --- /dev/null +++ b/inst/shinylive/apps/dataset-block/app.R @@ -0,0 +1,16 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) +custom_data_block <- function(...) { + new_dataset_block( + selected = "lab", + package = "blockr.data", + ... + ) +} + +stack <- new_stack( + custom_data_block, + new_select_block +) +serve_stack(stack) diff --git a/inst/shinylive/apps/empty-stack/app.R b/inst/shinylive/apps/empty-stack/app.R new file mode 100644 index 00000000..00d69061 --- /dev/null +++ b/inst/shinylive/apps/empty-stack/app.R @@ -0,0 +1,11 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos/", "https://repo.r-wasm.org")) #nolint + +library(blockr) +library(blockr.data) +library(blockr.ggplot2) +library(blockr.cardinal) +library(blockr.pharmaverseadam) +library(blockr.pharmaversesdtm) +library(blockr.ggstatsplot) +library(blockr.clinical.timelines) +serve_stack(new_stack(), id = "mystack") diff --git a/inst/shinylive/apps/filesbrowser-block/app.R b/inst/shinylive/apps/filesbrowser-block/app.R new file mode 100644 index 00000000..4e8689b7 --- /dev/null +++ b/inst/shinylive/apps/filesbrowser-block/app.R @@ -0,0 +1,13 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +## file: app.R +library(blockr) + +stack <- new_stack( + new_filesbrowser_block, + new_csv_block, + new_select_block +) +serve_stack(stack) + +## file: penguins.csv diff --git a/inst/shinylive/apps/filesbrowser-block/penguins.csv b/inst/shinylive/apps/filesbrowser-block/penguins.csv new file mode 100644 index 00000000..03e2c584 --- /dev/null +++ b/inst/shinylive/apps/filesbrowser-block/penguins.csv @@ -0,0 +1,345 @@ +"species","island","bill_length_mm","bill_depth_mm","flipper_length_mm","body_mass_g","sex","year" +"Adelie","Torgersen",39.1,18.7,181,3750,"male",2007 +"Adelie","Torgersen",39.5,17.4,186,3800,"female",2007 +"Adelie","Torgersen",40.3,18,195,3250,"female",2007 +"Adelie","Torgersen",NA,NA,NA,NA,NA,2007 +"Adelie","Torgersen",36.7,19.3,193,3450,"female",2007 +"Adelie","Torgersen",39.3,20.6,190,3650,"male",2007 +"Adelie","Torgersen",38.9,17.8,181,3625,"female",2007 +"Adelie","Torgersen",39.2,19.6,195,4675,"male",2007 +"Adelie","Torgersen",34.1,18.1,193,3475,NA,2007 +"Adelie","Torgersen",42,20.2,190,4250,NA,2007 +"Adelie","Torgersen",37.8,17.1,186,3300,NA,2007 +"Adelie","Torgersen",37.8,17.3,180,3700,NA,2007 +"Adelie","Torgersen",41.1,17.6,182,3200,"female",2007 +"Adelie","Torgersen",38.6,21.2,191,3800,"male",2007 +"Adelie","Torgersen",34.6,21.1,198,4400,"male",2007 +"Adelie","Torgersen",36.6,17.8,185,3700,"female",2007 +"Adelie","Torgersen",38.7,19,195,3450,"female",2007 +"Adelie","Torgersen",42.5,20.7,197,4500,"male",2007 +"Adelie","Torgersen",34.4,18.4,184,3325,"female",2007 +"Adelie","Torgersen",46,21.5,194,4200,"male",2007 +"Adelie","Biscoe",37.8,18.3,174,3400,"female",2007 +"Adelie","Biscoe",37.7,18.7,180,3600,"male",2007 +"Adelie","Biscoe",35.9,19.2,189,3800,"female",2007 +"Adelie","Biscoe",38.2,18.1,185,3950,"male",2007 +"Adelie","Biscoe",38.8,17.2,180,3800,"male",2007 +"Adelie","Biscoe",35.3,18.9,187,3800,"female",2007 +"Adelie","Biscoe",40.6,18.6,183,3550,"male",2007 +"Adelie","Biscoe",40.5,17.9,187,3200,"female",2007 +"Adelie","Biscoe",37.9,18.6,172,3150,"female",2007 +"Adelie","Biscoe",40.5,18.9,180,3950,"male",2007 +"Adelie","Dream",39.5,16.7,178,3250,"female",2007 +"Adelie","Dream",37.2,18.1,178,3900,"male",2007 +"Adelie","Dream",39.5,17.8,188,3300,"female",2007 +"Adelie","Dream",40.9,18.9,184,3900,"male",2007 +"Adelie","Dream",36.4,17,195,3325,"female",2007 +"Adelie","Dream",39.2,21.1,196,4150,"male",2007 +"Adelie","Dream",38.8,20,190,3950,"male",2007 +"Adelie","Dream",42.2,18.5,180,3550,"female",2007 +"Adelie","Dream",37.6,19.3,181,3300,"female",2007 +"Adelie","Dream",39.8,19.1,184,4650,"male",2007 +"Adelie","Dream",36.5,18,182,3150,"female",2007 +"Adelie","Dream",40.8,18.4,195,3900,"male",2007 +"Adelie","Dream",36,18.5,186,3100,"female",2007 +"Adelie","Dream",44.1,19.7,196,4400,"male",2007 +"Adelie","Dream",37,16.9,185,3000,"female",2007 +"Adelie","Dream",39.6,18.8,190,4600,"male",2007 +"Adelie","Dream",41.1,19,182,3425,"male",2007 +"Adelie","Dream",37.5,18.9,179,2975,NA,2007 +"Adelie","Dream",36,17.9,190,3450,"female",2007 +"Adelie","Dream",42.3,21.2,191,4150,"male",2007 +"Adelie","Biscoe",39.6,17.7,186,3500,"female",2008 +"Adelie","Biscoe",40.1,18.9,188,4300,"male",2008 +"Adelie","Biscoe",35,17.9,190,3450,"female",2008 +"Adelie","Biscoe",42,19.5,200,4050,"male",2008 +"Adelie","Biscoe",34.5,18.1,187,2900,"female",2008 +"Adelie","Biscoe",41.4,18.6,191,3700,"male",2008 +"Adelie","Biscoe",39,17.5,186,3550,"female",2008 +"Adelie","Biscoe",40.6,18.8,193,3800,"male",2008 +"Adelie","Biscoe",36.5,16.6,181,2850,"female",2008 +"Adelie","Biscoe",37.6,19.1,194,3750,"male",2008 +"Adelie","Biscoe",35.7,16.9,185,3150,"female",2008 +"Adelie","Biscoe",41.3,21.1,195,4400,"male",2008 +"Adelie","Biscoe",37.6,17,185,3600,"female",2008 +"Adelie","Biscoe",41.1,18.2,192,4050,"male",2008 +"Adelie","Biscoe",36.4,17.1,184,2850,"female",2008 +"Adelie","Biscoe",41.6,18,192,3950,"male",2008 +"Adelie","Biscoe",35.5,16.2,195,3350,"female",2008 +"Adelie","Biscoe",41.1,19.1,188,4100,"male",2008 +"Adelie","Torgersen",35.9,16.6,190,3050,"female",2008 +"Adelie","Torgersen",41.8,19.4,198,4450,"male",2008 +"Adelie","Torgersen",33.5,19,190,3600,"female",2008 +"Adelie","Torgersen",39.7,18.4,190,3900,"male",2008 +"Adelie","Torgersen",39.6,17.2,196,3550,"female",2008 +"Adelie","Torgersen",45.8,18.9,197,4150,"male",2008 +"Adelie","Torgersen",35.5,17.5,190,3700,"female",2008 +"Adelie","Torgersen",42.8,18.5,195,4250,"male",2008 +"Adelie","Torgersen",40.9,16.8,191,3700,"female",2008 +"Adelie","Torgersen",37.2,19.4,184,3900,"male",2008 +"Adelie","Torgersen",36.2,16.1,187,3550,"female",2008 +"Adelie","Torgersen",42.1,19.1,195,4000,"male",2008 +"Adelie","Torgersen",34.6,17.2,189,3200,"female",2008 +"Adelie","Torgersen",42.9,17.6,196,4700,"male",2008 +"Adelie","Torgersen",36.7,18.8,187,3800,"female",2008 +"Adelie","Torgersen",35.1,19.4,193,4200,"male",2008 +"Adelie","Dream",37.3,17.8,191,3350,"female",2008 +"Adelie","Dream",41.3,20.3,194,3550,"male",2008 +"Adelie","Dream",36.3,19.5,190,3800,"male",2008 +"Adelie","Dream",36.9,18.6,189,3500,"female",2008 +"Adelie","Dream",38.3,19.2,189,3950,"male",2008 +"Adelie","Dream",38.9,18.8,190,3600,"female",2008 +"Adelie","Dream",35.7,18,202,3550,"female",2008 +"Adelie","Dream",41.1,18.1,205,4300,"male",2008 +"Adelie","Dream",34,17.1,185,3400,"female",2008 +"Adelie","Dream",39.6,18.1,186,4450,"male",2008 +"Adelie","Dream",36.2,17.3,187,3300,"female",2008 +"Adelie","Dream",40.8,18.9,208,4300,"male",2008 +"Adelie","Dream",38.1,18.6,190,3700,"female",2008 +"Adelie","Dream",40.3,18.5,196,4350,"male",2008 +"Adelie","Dream",33.1,16.1,178,2900,"female",2008 +"Adelie","Dream",43.2,18.5,192,4100,"male",2008 +"Adelie","Biscoe",35,17.9,192,3725,"female",2009 +"Adelie","Biscoe",41,20,203,4725,"male",2009 +"Adelie","Biscoe",37.7,16,183,3075,"female",2009 +"Adelie","Biscoe",37.8,20,190,4250,"male",2009 +"Adelie","Biscoe",37.9,18.6,193,2925,"female",2009 +"Adelie","Biscoe",39.7,18.9,184,3550,"male",2009 +"Adelie","Biscoe",38.6,17.2,199,3750,"female",2009 +"Adelie","Biscoe",38.2,20,190,3900,"male",2009 +"Adelie","Biscoe",38.1,17,181,3175,"female",2009 +"Adelie","Biscoe",43.2,19,197,4775,"male",2009 +"Adelie","Biscoe",38.1,16.5,198,3825,"female",2009 +"Adelie","Biscoe",45.6,20.3,191,4600,"male",2009 +"Adelie","Biscoe",39.7,17.7,193,3200,"female",2009 +"Adelie","Biscoe",42.2,19.5,197,4275,"male",2009 +"Adelie","Biscoe",39.6,20.7,191,3900,"female",2009 +"Adelie","Biscoe",42.7,18.3,196,4075,"male",2009 +"Adelie","Torgersen",38.6,17,188,2900,"female",2009 +"Adelie","Torgersen",37.3,20.5,199,3775,"male",2009 +"Adelie","Torgersen",35.7,17,189,3350,"female",2009 +"Adelie","Torgersen",41.1,18.6,189,3325,"male",2009 +"Adelie","Torgersen",36.2,17.2,187,3150,"female",2009 +"Adelie","Torgersen",37.7,19.8,198,3500,"male",2009 +"Adelie","Torgersen",40.2,17,176,3450,"female",2009 +"Adelie","Torgersen",41.4,18.5,202,3875,"male",2009 +"Adelie","Torgersen",35.2,15.9,186,3050,"female",2009 +"Adelie","Torgersen",40.6,19,199,4000,"male",2009 +"Adelie","Torgersen",38.8,17.6,191,3275,"female",2009 +"Adelie","Torgersen",41.5,18.3,195,4300,"male",2009 +"Adelie","Torgersen",39,17.1,191,3050,"female",2009 +"Adelie","Torgersen",44.1,18,210,4000,"male",2009 +"Adelie","Torgersen",38.5,17.9,190,3325,"female",2009 +"Adelie","Torgersen",43.1,19.2,197,3500,"male",2009 +"Adelie","Dream",36.8,18.5,193,3500,"female",2009 +"Adelie","Dream",37.5,18.5,199,4475,"male",2009 +"Adelie","Dream",38.1,17.6,187,3425,"female",2009 +"Adelie","Dream",41.1,17.5,190,3900,"male",2009 +"Adelie","Dream",35.6,17.5,191,3175,"female",2009 +"Adelie","Dream",40.2,20.1,200,3975,"male",2009 +"Adelie","Dream",37,16.5,185,3400,"female",2009 +"Adelie","Dream",39.7,17.9,193,4250,"male",2009 +"Adelie","Dream",40.2,17.1,193,3400,"female",2009 +"Adelie","Dream",40.6,17.2,187,3475,"male",2009 +"Adelie","Dream",32.1,15.5,188,3050,"female",2009 +"Adelie","Dream",40.7,17,190,3725,"male",2009 +"Adelie","Dream",37.3,16.8,192,3000,"female",2009 +"Adelie","Dream",39,18.7,185,3650,"male",2009 +"Adelie","Dream",39.2,18.6,190,4250,"male",2009 +"Adelie","Dream",36.6,18.4,184,3475,"female",2009 +"Adelie","Dream",36,17.8,195,3450,"female",2009 +"Adelie","Dream",37.8,18.1,193,3750,"male",2009 +"Adelie","Dream",36,17.1,187,3700,"female",2009 +"Adelie","Dream",41.5,18.5,201,4000,"male",2009 +"Gentoo","Biscoe",46.1,13.2,211,4500,"female",2007 +"Gentoo","Biscoe",50,16.3,230,5700,"male",2007 +"Gentoo","Biscoe",48.7,14.1,210,4450,"female",2007 +"Gentoo","Biscoe",50,15.2,218,5700,"male",2007 +"Gentoo","Biscoe",47.6,14.5,215,5400,"male",2007 +"Gentoo","Biscoe",46.5,13.5,210,4550,"female",2007 +"Gentoo","Biscoe",45.4,14.6,211,4800,"female",2007 +"Gentoo","Biscoe",46.7,15.3,219,5200,"male",2007 +"Gentoo","Biscoe",43.3,13.4,209,4400,"female",2007 +"Gentoo","Biscoe",46.8,15.4,215,5150,"male",2007 +"Gentoo","Biscoe",40.9,13.7,214,4650,"female",2007 +"Gentoo","Biscoe",49,16.1,216,5550,"male",2007 +"Gentoo","Biscoe",45.5,13.7,214,4650,"female",2007 +"Gentoo","Biscoe",48.4,14.6,213,5850,"male",2007 +"Gentoo","Biscoe",45.8,14.6,210,4200,"female",2007 +"Gentoo","Biscoe",49.3,15.7,217,5850,"male",2007 +"Gentoo","Biscoe",42,13.5,210,4150,"female",2007 +"Gentoo","Biscoe",49.2,15.2,221,6300,"male",2007 +"Gentoo","Biscoe",46.2,14.5,209,4800,"female",2007 +"Gentoo","Biscoe",48.7,15.1,222,5350,"male",2007 +"Gentoo","Biscoe",50.2,14.3,218,5700,"male",2007 +"Gentoo","Biscoe",45.1,14.5,215,5000,"female",2007 +"Gentoo","Biscoe",46.5,14.5,213,4400,"female",2007 +"Gentoo","Biscoe",46.3,15.8,215,5050,"male",2007 +"Gentoo","Biscoe",42.9,13.1,215,5000,"female",2007 +"Gentoo","Biscoe",46.1,15.1,215,5100,"male",2007 +"Gentoo","Biscoe",44.5,14.3,216,4100,NA,2007 +"Gentoo","Biscoe",47.8,15,215,5650,"male",2007 +"Gentoo","Biscoe",48.2,14.3,210,4600,"female",2007 +"Gentoo","Biscoe",50,15.3,220,5550,"male",2007 +"Gentoo","Biscoe",47.3,15.3,222,5250,"male",2007 +"Gentoo","Biscoe",42.8,14.2,209,4700,"female",2007 +"Gentoo","Biscoe",45.1,14.5,207,5050,"female",2007 +"Gentoo","Biscoe",59.6,17,230,6050,"male",2007 +"Gentoo","Biscoe",49.1,14.8,220,5150,"female",2008 +"Gentoo","Biscoe",48.4,16.3,220,5400,"male",2008 +"Gentoo","Biscoe",42.6,13.7,213,4950,"female",2008 +"Gentoo","Biscoe",44.4,17.3,219,5250,"male",2008 +"Gentoo","Biscoe",44,13.6,208,4350,"female",2008 +"Gentoo","Biscoe",48.7,15.7,208,5350,"male",2008 +"Gentoo","Biscoe",42.7,13.7,208,3950,"female",2008 +"Gentoo","Biscoe",49.6,16,225,5700,"male",2008 +"Gentoo","Biscoe",45.3,13.7,210,4300,"female",2008 +"Gentoo","Biscoe",49.6,15,216,4750,"male",2008 +"Gentoo","Biscoe",50.5,15.9,222,5550,"male",2008 +"Gentoo","Biscoe",43.6,13.9,217,4900,"female",2008 +"Gentoo","Biscoe",45.5,13.9,210,4200,"female",2008 +"Gentoo","Biscoe",50.5,15.9,225,5400,"male",2008 +"Gentoo","Biscoe",44.9,13.3,213,5100,"female",2008 +"Gentoo","Biscoe",45.2,15.8,215,5300,"male",2008 +"Gentoo","Biscoe",46.6,14.2,210,4850,"female",2008 +"Gentoo","Biscoe",48.5,14.1,220,5300,"male",2008 +"Gentoo","Biscoe",45.1,14.4,210,4400,"female",2008 +"Gentoo","Biscoe",50.1,15,225,5000,"male",2008 +"Gentoo","Biscoe",46.5,14.4,217,4900,"female",2008 +"Gentoo","Biscoe",45,15.4,220,5050,"male",2008 +"Gentoo","Biscoe",43.8,13.9,208,4300,"female",2008 +"Gentoo","Biscoe",45.5,15,220,5000,"male",2008 +"Gentoo","Biscoe",43.2,14.5,208,4450,"female",2008 +"Gentoo","Biscoe",50.4,15.3,224,5550,"male",2008 +"Gentoo","Biscoe",45.3,13.8,208,4200,"female",2008 +"Gentoo","Biscoe",46.2,14.9,221,5300,"male",2008 +"Gentoo","Biscoe",45.7,13.9,214,4400,"female",2008 +"Gentoo","Biscoe",54.3,15.7,231,5650,"male",2008 +"Gentoo","Biscoe",45.8,14.2,219,4700,"female",2008 +"Gentoo","Biscoe",49.8,16.8,230,5700,"male",2008 +"Gentoo","Biscoe",46.2,14.4,214,4650,NA,2008 +"Gentoo","Biscoe",49.5,16.2,229,5800,"male",2008 +"Gentoo","Biscoe",43.5,14.2,220,4700,"female",2008 +"Gentoo","Biscoe",50.7,15,223,5550,"male",2008 +"Gentoo","Biscoe",47.7,15,216,4750,"female",2008 +"Gentoo","Biscoe",46.4,15.6,221,5000,"male",2008 +"Gentoo","Biscoe",48.2,15.6,221,5100,"male",2008 +"Gentoo","Biscoe",46.5,14.8,217,5200,"female",2008 +"Gentoo","Biscoe",46.4,15,216,4700,"female",2008 +"Gentoo","Biscoe",48.6,16,230,5800,"male",2008 +"Gentoo","Biscoe",47.5,14.2,209,4600,"female",2008 +"Gentoo","Biscoe",51.1,16.3,220,6000,"male",2008 +"Gentoo","Biscoe",45.2,13.8,215,4750,"female",2008 +"Gentoo","Biscoe",45.2,16.4,223,5950,"male",2008 +"Gentoo","Biscoe",49.1,14.5,212,4625,"female",2009 +"Gentoo","Biscoe",52.5,15.6,221,5450,"male",2009 +"Gentoo","Biscoe",47.4,14.6,212,4725,"female",2009 +"Gentoo","Biscoe",50,15.9,224,5350,"male",2009 +"Gentoo","Biscoe",44.9,13.8,212,4750,"female",2009 +"Gentoo","Biscoe",50.8,17.3,228,5600,"male",2009 +"Gentoo","Biscoe",43.4,14.4,218,4600,"female",2009 +"Gentoo","Biscoe",51.3,14.2,218,5300,"male",2009 +"Gentoo","Biscoe",47.5,14,212,4875,"female",2009 +"Gentoo","Biscoe",52.1,17,230,5550,"male",2009 +"Gentoo","Biscoe",47.5,15,218,4950,"female",2009 +"Gentoo","Biscoe",52.2,17.1,228,5400,"male",2009 +"Gentoo","Biscoe",45.5,14.5,212,4750,"female",2009 +"Gentoo","Biscoe",49.5,16.1,224,5650,"male",2009 +"Gentoo","Biscoe",44.5,14.7,214,4850,"female",2009 +"Gentoo","Biscoe",50.8,15.7,226,5200,"male",2009 +"Gentoo","Biscoe",49.4,15.8,216,4925,"male",2009 +"Gentoo","Biscoe",46.9,14.6,222,4875,"female",2009 +"Gentoo","Biscoe",48.4,14.4,203,4625,"female",2009 +"Gentoo","Biscoe",51.1,16.5,225,5250,"male",2009 +"Gentoo","Biscoe",48.5,15,219,4850,"female",2009 +"Gentoo","Biscoe",55.9,17,228,5600,"male",2009 +"Gentoo","Biscoe",47.2,15.5,215,4975,"female",2009 +"Gentoo","Biscoe",49.1,15,228,5500,"male",2009 +"Gentoo","Biscoe",47.3,13.8,216,4725,NA,2009 +"Gentoo","Biscoe",46.8,16.1,215,5500,"male",2009 +"Gentoo","Biscoe",41.7,14.7,210,4700,"female",2009 +"Gentoo","Biscoe",53.4,15.8,219,5500,"male",2009 +"Gentoo","Biscoe",43.3,14,208,4575,"female",2009 +"Gentoo","Biscoe",48.1,15.1,209,5500,"male",2009 +"Gentoo","Biscoe",50.5,15.2,216,5000,"female",2009 +"Gentoo","Biscoe",49.8,15.9,229,5950,"male",2009 +"Gentoo","Biscoe",43.5,15.2,213,4650,"female",2009 +"Gentoo","Biscoe",51.5,16.3,230,5500,"male",2009 +"Gentoo","Biscoe",46.2,14.1,217,4375,"female",2009 +"Gentoo","Biscoe",55.1,16,230,5850,"male",2009 +"Gentoo","Biscoe",44.5,15.7,217,4875,NA,2009 +"Gentoo","Biscoe",48.8,16.2,222,6000,"male",2009 +"Gentoo","Biscoe",47.2,13.7,214,4925,"female",2009 +"Gentoo","Biscoe",NA,NA,NA,NA,NA,2009 +"Gentoo","Biscoe",46.8,14.3,215,4850,"female",2009 +"Gentoo","Biscoe",50.4,15.7,222,5750,"male",2009 +"Gentoo","Biscoe",45.2,14.8,212,5200,"female",2009 +"Gentoo","Biscoe",49.9,16.1,213,5400,"male",2009 +"Chinstrap","Dream",46.5,17.9,192,3500,"female",2007 +"Chinstrap","Dream",50,19.5,196,3900,"male",2007 +"Chinstrap","Dream",51.3,19.2,193,3650,"male",2007 +"Chinstrap","Dream",45.4,18.7,188,3525,"female",2007 +"Chinstrap","Dream",52.7,19.8,197,3725,"male",2007 +"Chinstrap","Dream",45.2,17.8,198,3950,"female",2007 +"Chinstrap","Dream",46.1,18.2,178,3250,"female",2007 +"Chinstrap","Dream",51.3,18.2,197,3750,"male",2007 +"Chinstrap","Dream",46,18.9,195,4150,"female",2007 +"Chinstrap","Dream",51.3,19.9,198,3700,"male",2007 +"Chinstrap","Dream",46.6,17.8,193,3800,"female",2007 +"Chinstrap","Dream",51.7,20.3,194,3775,"male",2007 +"Chinstrap","Dream",47,17.3,185,3700,"female",2007 +"Chinstrap","Dream",52,18.1,201,4050,"male",2007 +"Chinstrap","Dream",45.9,17.1,190,3575,"female",2007 +"Chinstrap","Dream",50.5,19.6,201,4050,"male",2007 +"Chinstrap","Dream",50.3,20,197,3300,"male",2007 +"Chinstrap","Dream",58,17.8,181,3700,"female",2007 +"Chinstrap","Dream",46.4,18.6,190,3450,"female",2007 +"Chinstrap","Dream",49.2,18.2,195,4400,"male",2007 +"Chinstrap","Dream",42.4,17.3,181,3600,"female",2007 +"Chinstrap","Dream",48.5,17.5,191,3400,"male",2007 +"Chinstrap","Dream",43.2,16.6,187,2900,"female",2007 +"Chinstrap","Dream",50.6,19.4,193,3800,"male",2007 +"Chinstrap","Dream",46.7,17.9,195,3300,"female",2007 +"Chinstrap","Dream",52,19,197,4150,"male",2007 +"Chinstrap","Dream",50.5,18.4,200,3400,"female",2008 +"Chinstrap","Dream",49.5,19,200,3800,"male",2008 +"Chinstrap","Dream",46.4,17.8,191,3700,"female",2008 +"Chinstrap","Dream",52.8,20,205,4550,"male",2008 +"Chinstrap","Dream",40.9,16.6,187,3200,"female",2008 +"Chinstrap","Dream",54.2,20.8,201,4300,"male",2008 +"Chinstrap","Dream",42.5,16.7,187,3350,"female",2008 +"Chinstrap","Dream",51,18.8,203,4100,"male",2008 +"Chinstrap","Dream",49.7,18.6,195,3600,"male",2008 +"Chinstrap","Dream",47.5,16.8,199,3900,"female",2008 +"Chinstrap","Dream",47.6,18.3,195,3850,"female",2008 +"Chinstrap","Dream",52,20.7,210,4800,"male",2008 +"Chinstrap","Dream",46.9,16.6,192,2700,"female",2008 +"Chinstrap","Dream",53.5,19.9,205,4500,"male",2008 +"Chinstrap","Dream",49,19.5,210,3950,"male",2008 +"Chinstrap","Dream",46.2,17.5,187,3650,"female",2008 +"Chinstrap","Dream",50.9,19.1,196,3550,"male",2008 +"Chinstrap","Dream",45.5,17,196,3500,"female",2008 +"Chinstrap","Dream",50.9,17.9,196,3675,"female",2009 +"Chinstrap","Dream",50.8,18.5,201,4450,"male",2009 +"Chinstrap","Dream",50.1,17.9,190,3400,"female",2009 +"Chinstrap","Dream",49,19.6,212,4300,"male",2009 +"Chinstrap","Dream",51.5,18.7,187,3250,"male",2009 +"Chinstrap","Dream",49.8,17.3,198,3675,"female",2009 +"Chinstrap","Dream",48.1,16.4,199,3325,"female",2009 +"Chinstrap","Dream",51.4,19,201,3950,"male",2009 +"Chinstrap","Dream",45.7,17.3,193,3600,"female",2009 +"Chinstrap","Dream",50.7,19.7,203,4050,"male",2009 +"Chinstrap","Dream",42.5,17.3,187,3350,"female",2009 +"Chinstrap","Dream",52.2,18.8,197,3450,"male",2009 +"Chinstrap","Dream",45.2,16.6,191,3250,"female",2009 +"Chinstrap","Dream",49.3,19.9,203,4050,"male",2009 +"Chinstrap","Dream",50.2,18.8,202,3800,"male",2009 +"Chinstrap","Dream",45.6,19.4,194,3525,"female",2009 +"Chinstrap","Dream",51.9,19.5,206,3950,"male",2009 +"Chinstrap","Dream",46.8,16.5,189,3650,"female",2009 +"Chinstrap","Dream",45.7,17,195,3650,"female",2009 +"Chinstrap","Dream",55.8,19.8,207,4000,"male",2009 +"Chinstrap","Dream",43.5,18.1,202,3400,"female",2009 +"Chinstrap","Dream",49.6,18.2,193,3775,"male",2009 +"Chinstrap","Dream",50.8,19,210,4100,"male",2009 +"Chinstrap","Dream",50.2,18.7,198,3775,"female",2009 diff --git a/inst/shinylive/apps/ggplot-block/app.R b/inst/shinylive/apps/ggplot-block/app.R new file mode 100644 index 00000000..372d6fd6 --- /dev/null +++ b/inst/shinylive/apps/ggplot-block/app.R @@ -0,0 +1,46 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) +library(palmerpenguins) +library(ggplot2) + +new_ggplot_block <- function(col_x = character(), col_y = character(), ...) { + + data_cols <- function(data) colnames(data) + + new_block( + fields = list( + x = new_select_field(col_x, data_cols, type = "name"), + y = new_select_field(col_y, data_cols, type = "name") + ), + expr = quote( + ggplot(mapping = aes(x = .(x), y = .(y))) + ), + class = c("ggplot_block", "plot_block"), + ... + ) +} + +new_geompoint_block <- function(color = character(), shape = character(), ...) { + + data_cols <- function(data) colnames(data$data) + + new_block( + fields = list( + color = new_select_field(color, data_cols, type = "name"), + shape = new_select_field(shape, data_cols, type = "name") + ), + expr = quote( + geom_point(aes(color = .(color), shape = .(shape)), size = 2) + ), + class = c("plot_layer_block", "plot_block"), + ... + ) +} + +stack <- new_stack( + data_block = new_dataset_block("penguins", "palmerpenguins"), + plot_block = new_ggplot_block("flipper_length_mm", "body_mass_g"), + layer_block = new_geompoint_block("species", "species") +) +serve_stack(stack) diff --git a/inst/shinylive/apps/ode-demo/app.R b/inst/shinylive/apps/ode-demo/app.R new file mode 100644 index 00000000..768d025d --- /dev/null +++ b/inst/shinylive/apps/ode-demo/app.R @@ -0,0 +1,51 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) +webr::install("blockr.ggplot2", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) +library(pracma) +library(blockr.ggplot2) + +new_ode_block <- function(...) { + + lorenz <- function(t, y, parms) { + c( + X = parms[1] * y[1] + y[2] * y[3], + Y = parms[2] * (y[2] - y[3]), + Z = -y[1] * y[2] + parms[3] * y[2] - y[3] + ) + } + + fields <- list( + a = new_numeric_field(-8 / 3, -10, 20), + b = new_numeric_field(-10, -50, 100), + c = new_numeric_field(28, 1, 100) + ) + + new_block( + fields = fields, + expr = substitute( + as.data.frame( + ode45( + fun, + y0 = c(X = 1, Y = 1, Z = 1), + t0 = 0, + tfinal = 100, + parms = c(.(a), .(b), .(c)) + ) + ), + list(fun = lorenz) + ), + ..., + class = c("ode_block", "data_block") + ) +} + +stack <- new_stack( + new_ode_block, + new_ggplot_block( + func = c("x", "y"), + default_columns = c("y.1", "y.2") + ), + new_geompoint_block +) +serve_stack(stack) diff --git a/inst/shinylive/apps/palmer-penguins/app.R b/inst/shinylive/apps/palmer-penguins/app.R new file mode 100644 index 00000000..3fdffe4b --- /dev/null +++ b/inst/shinylive/apps/palmer-penguins/app.R @@ -0,0 +1,47 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos/", "https://repo.r-wasm.org")) #nolint + +library(blockr) +library(palmerpenguins) +library(ggplot2) + +new_ggplot_block <- function(col_x = character(), col_y = character(), ...) { + + data_cols <- function(data) colnames(data) + + new_block( + fields = list( + x = new_select_field(col_x, data_cols, type = "name"), + y = new_select_field(col_y, data_cols, type = "name") + ), + expr = quote( + ggplot(mapping = aes(x = .(x), y = .(y))) + ), + class = c("ggplot_block", "plot_block"), + ... + ) +} + +new_geompoint_block <- function(color = character(), shape = character(), ...) { + + data_cols <- function(data) colnames(data$data) + + new_block( + fields = list( + color = new_select_field(color, data_cols, type = "name"), + shape = new_select_field(shape, data_cols, type = "name") + ), + expr = quote( + geom_point(aes(color = .(color), shape = .(shape)), size = 2) + ), + class = c("plot_layer_block", "plot_block"), + ... + ) +} + +stack <- new_stack( + data_block = new_dataset_block("penguins", "palmerpenguins"), + filter_block = new_filter_block("sex", "female"), + plot_block = new_ggplot_block("flipper_length_mm", "body_mass_g"), + layer_block = new_geompoint_block("species", "species") +) +serve_stack(stack) diff --git a/inst/shinylive/apps/registry-demo/app.R b/inst/shinylive/apps/registry-demo/app.R new file mode 100644 index 00000000..2601680c --- /dev/null +++ b/inst/shinylive/apps/registry-demo/app.R @@ -0,0 +1,29 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) + +new_tail_block <- function(data, n_rows = numeric(), ...) { + + n_rows_max <- function(data) nrow(data) + + new_block( + fields = list( + n_rows = new_numeric_field(n_rows, 1L, n_rows_max) + ), + expr = quote(tail(n = .(n_rows))), + class = c("tail_block", "transform_block"), + ... + ) +} + +register_block( + constructor = new_tail_block, + name = "tail block", + description = "return last n rows", + classes = c("tail_block", "transform_block"), + input = "data.frame", + output = "data.frame" +) + +stack <- new_stack(new_dataset_block) +serve_stack(stack) diff --git a/inst/shinylive/apps/result-block/app.R b/inst/shinylive/apps/result-block/app.R new file mode 100644 index 00000000..0f751fee --- /dev/null +++ b/inst/shinylive/apps/result-block/app.R @@ -0,0 +1,14 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) +library(blockr.data) + +serve_workspace( + stack1 = new_stack( + new_dataset_block("lab", "blockr.data"), + new_select_block(c("STUDYID", "USUBJID")) + ), + stack2 = new_stack(new_result_block), + stack3 = new_stack(new_dataset_block("ae", "blockr.data")), + title = "My workspace" +) diff --git a/inst/shinylive/apps/upload-block/app.R b/inst/shinylive/apps/upload-block/app.R new file mode 100644 index 00000000..513580ca --- /dev/null +++ b/inst/shinylive/apps/upload-block/app.R @@ -0,0 +1,10 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos", "https://repo.r-wasm.org")) + +library(blockr) + +stack <- new_stack( + new_upload_block, + new_csv_block, + new_select_block +) +serve_stack(stack) diff --git a/inst/shinylive/apps/workspace-kitchen-sink/app.R b/inst/shinylive/apps/workspace-kitchen-sink/app.R new file mode 100644 index 00000000..61f271ff --- /dev/null +++ b/inst/shinylive/apps/workspace-kitchen-sink/app.R @@ -0,0 +1,7 @@ +webr::install("blockr", repos = c("https://bristolmyerssquibb.github.io/webr-repos/", "https://repo.r-wasm.org")) #nolint + +library(blockr) + +do.call(set_workspace, args = list(title = "My workspace")) + +serve_workspace(clear = FALSE) diff --git a/inst/shinylive/tools.R b/inst/shinylive/tools.R new file mode 100644 index 00000000..05a2e9c0 --- /dev/null +++ b/inst/shinylive/tools.R @@ -0,0 +1,22 @@ +pak::pak("parmsam/r-shinylive@feat/encode-decode-url") #nolint start + +create_shinylive_links <- function(path) { + + dirs <- list.dirs(path)[-1] + + vapply( + dirs, + shinylive:::url_encode_dir, + FUN.VALUE = character(1) + ) +} + +create_vignettes_links <- function() { + apps_path <- "inst/shinylive/apps" + links <- create_shinylive_links(apps_path) + names(links) <- gsub(sprintf("%s/", apps_path), "", names(links)) + links +} + +shinylive_links <- create_vignettes_links() +usethis::use_data(shinylive_links, internal = TRUE, overwrite = TRUE) #nolint end \ No newline at end of file diff --git a/man/create_app_link.Rd b/man/create_app_link.Rd index ffcf2611..f5587016 100644 --- a/man/create_app_link.Rd +++ b/man/create_app_link.Rd @@ -4,17 +4,16 @@ \alias{create_app_link} \title{Create shinylive iframe} \usage{ -create_app_link(app_code, mode = c("app", "editor"), header = TRUE) +create_app_link(url, mode = c("app", "editor"), header = TRUE) } \arguments{ -\item{app_code}{base64 app code. You can create it from https://shinylive.io/r -by writing code and click on share and copy the link. The code is located at -the end of the url.} +\item{url}{app url. A shinylive link.} \item{mode}{How to display the shinylive app. Default to app mode.} \item{header}{Whether to display the shinylive header. Default to TRUE.} } \description{ -Create shinylive iframe +Useful for pkgdown website } +\keyword{internal} diff --git a/man/figures/README-unnamed-chunk-2-1.png b/man/figures/README-unnamed-chunk-2-1.png index 8a47c897..a4809bfe 100644 Binary files a/man/figures/README-unnamed-chunk-2-1.png and b/man/figures/README-unnamed-chunk-2-1.png differ diff --git a/man/figures/README-unnamed-chunk-3-1.png b/man/figures/README-unnamed-chunk-3-1.png new file mode 100644 index 00000000..a4809bfe Binary files /dev/null and b/man/figures/README-unnamed-chunk-3-1.png differ diff --git a/man/figures/README-unnamed-chunk-4-1.png b/man/figures/README-unnamed-chunk-4-1.png new file mode 100644 index 00000000..a4809bfe Binary files /dev/null and b/man/figures/README-unnamed-chunk-4-1.png differ diff --git a/vignettes/blockr_examples.Rmd b/vignettes/blockr-examples.Rmd similarity index 59% rename from vignettes/blockr_examples.Rmd rename to vignettes/blockr-examples.Rmd index b0077590..2162b02c 100644 --- a/vignettes/blockr_examples.Rmd +++ b/vignettes/blockr-examples.Rmd @@ -1,8 +1,8 @@ --- -title: "Case studies" +title: "5: Case studies" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Case studies} + %\VignetteIndexEntry{5: Case studies} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -15,7 +15,7 @@ knitr::opts_chunk$set(echo = TRUE) ## blockr Across Industries -The flexibility of `blockr` makes it valuable across various industries. Let's explore how it can be applied in different sectors with detailed examples. Somex examples require to create a new field such as the `new_slider_field` described in the corresponding vignette. +The __flexibility__ of `blockr` makes it valuable across various __industries__. Let's explore how it can be applied in different sectors with detailed examples. Some examples require to create a new field such as the `new_slider_field` described in the corresponding [vignette](https://bristolmyerssquibb.github.io/blockr/articles/new-field.html). ```{r slider_block, include=FALSE} # Provided by John, new_range_field not working @@ -209,9 +209,10 @@ This forest plot visualizes the relative risk of adverse events between two trea ```{r, eval=TRUE, echo=FALSE} card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhBeTKwcXLyaphIMGKhaUAwwUABucAzscFAAJrAB4cpqGkG6+kYmooWWNnYOzq7unvRRrQGdIT3hkdGx8YkpaRDp3CyMZQCefAWSa5vbDHsNqNw7DEdbDLt8pCwNVzcnewBmVnCcF0Skr3dTvs+pJiqVylUanVGrA1ukAMQyABiTggBEeJBkpCI6nkUHIMka1VqcBkcGqZBkn3knBkv1I6QIePIAH0oHAWdTvqQWfSZAAecxU1Ho9wQPhNLiyJzsFwAKyeLOI3FkZRgSqIKsJcAacGIDQ1WogLPJFFI7GSMhA6RkMklUAFQvtMgAPgA+KksbjkBh8DD24DANWGgC6IZkAEI1EIAArcKAEehEFI2mSIgDCJGJpHUmqcMAgMmg8GU2JknAYbGs-kLMhl8sVysdhPYGAI4ITPr4sronAcTnIfHrdAVBuVqVTwabgpbbY76Jq3ZcfdIA7gfCnmontfZuv1hubsTnZU7i57K7XG51eqIY63cNrGZ4BCc8YJjlJ2NyRfzdBqMiId5y3lPVzRkNgyQTLRCXKVNjR7OVQOUGdnXdVNbTqbhQI3XgWUAvgNGHUdDVVcpDVSS00NrW0GhYPs0VIPhKLddCZGsBgiCcVAWToPYEw49h2Bw7g8PeDcyPHVJXRY6jgJgCpKzqPhCzUcVklkOwOK4tpAjABoONQFN1kfGR02fV98VJABBABRKl5AARycCgCBYb5CQgBo6QMqwMQ4ScOVleTdmbVCZNtW12M47jeI3JklCEngRPwjRNy1XcbzvbgKOY1igoUuj12NU0yB041aPo9E-QDYAiMbTUw3UmRNOinShH0ohDLAXLZKw94eTlIg2GUlkEKQ2ReNUGD1XHaTWJgAdLL4VAfIYPypuKikwMMIsH1tREAGU4Cw9EsU6mQADkZBgJQc3eRznMpWzlH4hLCV4aaa1tbFuPZZChXZUb8wUnY5tkqKuJ4vj4sE4TRKvPdb3IqSqIiuSCqUr8eBNLadKCkaSvNJqWu0qb2oMlIwbRn6WXFTazXYWQsZEwmLSpiLUFffgkvhjL90k9JU0RABxOAc1RFgnM-Zl4EpNUvs+5sJaliV8SgQM0sa1MWCAvgsIgaxHHEmA2ajGQACZLWtWTOE6zQABUtDoulRBzB6WBpMkAA9O0uLFqBxUgZbNT6MCM20AF9J1Fao2XKQ9ynYYAAEYQ1TYgyA4kS1QTk3gHNtPjP25EvR9KkrDO1AZGejyvIIcy31JeQ3xYao5Do8QApZBgGEPQLgZC1GIveUvF39NWNevfmGvDABSNhZ8rtlvh6tHUFbv4WWoJ5F1Y216u4HSefwvmkfHXA96LWBvk5DiYCm4+xLS9TL8qHhnPYW+iHv9oCdx2QICyBWp1XyYo1ho1XhFBaXBByXywFgKa48uCBlQLEcgAAGTQwDFBrTFCyAInZW4cjVMkMMMgdpIPVsAVBnA4CYKENg0BJB8F4FzJnTUccYCkJDBfWStpRC0AYEqFgU04Be1QHrIg1g+DwMtEKZOGAACcAA2GQAAqcsDk1qCD4RFZO5Dmo1RoRgzQ9NSosNVDHYh5RuEyAANSXzRvoihRi0F0NMTjBmFi2FBw4SQsh5hHF6IMZQlBbj6GQG8YQ2O-jwyBN0U4kJrjaERONAEDOvjs42LDJfVIvC0a2i4qgGowjRHiMkdI2R9iZAKJUeozR2ignOMMRPah4SPGsyiVYzhtiHEJOCS41pxj3FCDMeabxGSs49ICUE20zTQltJSR4gh3TYkyHiQUgp8zkkmNGRMkgmTpmF02duCBgsTIxl8GUUkzpqTlxpDmekqYuScBZM6GcgMe7s1tNApal94x-m4FNYZ9D+kLNPllMMsghAyE0PkzZLTkGLN2ZEzpKzHgxOyTw3ShgAgLJBcs1h0TrFcKhbpGQlRlDSCCfi9pey0WsMmX4rF0KwC4tYbSpZez0kHKmbE1laQwC5NYntNMplmSkheY812zyvg-FdjotGALjrkC9jmdodA2ANEVQUqVby1YABJlUqkvuwFabBSBiSELPDA5tdY2rteYB17xBWyD1faA18C3Vyp5B6gRJTXLeoefqrgBqikBpYOAiKL9ZLwCgCpe53IQ1QE9VgeF-CiCCKmu6w1-qhGBtYuG3uagc2hqLcI9N70WDWATR0MA3BphgCkN1St7E0BaG3g0RwU0JaMWUeg1l8kUiVsTF7Ka6ClGVs2BAOAWg4DVp0D2iADg+AAA5B0wGHaxOgRAvbsBYAAL1JGoCdABmAArCOzU2bUCZlELUfYu6yZNqIDsHgIhnIBGnce3STQGDiA-XAAI+UQrRhfW+7ggGt2yVIGqlk1gq4ltQPbNVwsJHGqmghsoBExHjqUU1R4EgdJYd9KOvDiimpewBZh1BpHcMnvwzGtGVGoB0GBW4zQWBjr4iITILAHdYXoqIZw1lBieXsKyTAAV0G0ZHo4lNZOU7qANAwHJnEahzZKZU65KamnWJqpYERqaGgJ2XpqbITTMgAAsTGIrsSeFNe2WAACqNlK2PFIFhdjtDOPcYxaSfj7BxAASAlZBoxI6gyBsrjQTRLVnlFE5S3SsgmWSek91VMawo7GRndQTkPreSux4iCZs7wRR+T9BgDAVs4JwDywcHVtoR7HQaDpTYnBGsRTqllDadXRrHVApyNy3BtVBKEM5g6zmABCAApAAkgAEWpf0srDExSqy4JaZUxZvgbagLZzZC1vQsAuD+pEVkAAyB03NBI815sDB0QKnUW6ZPMBYhC5MrbaNKvW8uYUG81kbnW0ZCCsume2VksAAFllsIuFGtkge2tuah20Je0B2ClHceKdqa52rs3f6Xdn9Qh7bByevHO9+Z1hCt0Rj77U8z7XtUn1-76IhsteBxFUHNkFs2XTAAeSW3gIJq3RSI-R7mbgqOkdfaga+bH93kSXeu7L76DhFfc5kPbGo99KfvZpyc2XYyyp9YgPmGohn2dA6aQOoJMAIJqDMxUMdGmB3lnIIh8zt31fE7ABdX8-5AJa-OjXMsC26IXCgDsD7tORWVrEStKaTk-jrmtpspk9RWSAz1fSPbGkhwIQPsTY25F88QtL81P+DNTkRQjhjgg8ZBLGc0ESKEHJCaFc3gcRt9JitmBkxFKrYdaxZfOYiLj9haG9w-OoGU2J77d4gPISfPo+8SB1bl-Lwbe8HHhTt59YWIukmiyHJEPqZBxj+LDu03wmQnfWmB9MErCSJtpHyIPreSRkhi8QGAtGqz+yBxk45jyzX4N6xB1A6R1qf51CeJkCd48jd6sIMJFZIG2ZsCczqq-pqwYD3TXzX6cR6ADjPpPI04PgZjP4z6cAJidxojTqGbYxBwsDYzUESDNib6sHiAb59YwjqgNas7kBeRgYwhAYtpCyejeglJsBr5cG2ab456oEghMTpAPh1AMCxycEET0H1wiRMEsFcASDJBgARwhhAA", # nolint - mode = "editor" + blockr:::create_app_link( + blockr:::shinylive_links["ae-forest-plot"], + "editor", + header = FALSE ), full_screen = TRUE ) @@ -231,163 +232,8 @@ Toggle code
-```r -library(dplyr) -library(tidyr) -library(forestplot) -library(blockr.pharmaverseadam) - -# Function to create adverse event forest plot -create_ae_forest_plot <- function(data, usubjid_col, arm_col, aedecod_col, n_events) { - data <- data |> filter(.data[[arm_col]] != "Placebo") - # Convert column names to strings - usubjid_col <- as.character(substitute(usubjid_col)) - arm_col <- as.character(substitute(arm_col)) - aedecod_col <- as.character(substitute(aedecod_col)) - - # Calculate the total number of subjects in each arm - n_subjects <- data |> - select(all_of(c(usubjid_col, arm_col))) |> - distinct() |> - group_by(across(all_of(arm_col))) |> - summarise(n = n(), .groups = "drop") - - # Calculate AE frequencies and proportions - ae_summary <- data |> - group_by(across(all_of(c(arm_col, aedecod_col)))) |> - summarise(n_events = n_distinct(.data[[usubjid_col]]), .groups = "drop") |> - left_join(n_subjects, by = arm_col) |> - mutate(proportion = n_events / n) - - # Select top N most frequent AEs across all arms - top_aes <- ae_summary |> - group_by(across(all_of(aedecod_col))) |> - summarise(total_events = sum(n_events), .groups = "drop") |> - top_n(n_events, total_events) |> - pull(all_of(aedecod_col)) - - # Get unique treatment arms - arms <- unique(data[[arm_col]]) - if (length(arms) != 2) { - stop("This plot requires exactly two treatment arms.") - } - active_arm <- arms[1] - control_arm <- arms[2] - - # Filter for top AEs and calculate relative risk - ae_rr <- ae_summary |> - filter(.data[[aedecod_col]] %in% top_aes) |> - pivot_wider( - id_cols = all_of(aedecod_col), - names_from = all_of(arm_col), - values_from = c(n_events, n, proportion) - ) |> - mutate( - RR = .data[[paste0("proportion_", active_arm)]] / .data[[paste0("proportion_", control_arm)]], - lower_ci = exp(log(RR) - 1.96 * sqrt( - 1 / .data[[paste0("n_events_", active_arm)]] + - 1 / .data[[paste0("n_events_", control_arm)]] - - 1 / .data[[paste0("n_", active_arm)]] - - 1 / .data[[paste0("n_", control_arm)]] - )), - upper_ci = exp(log(RR) + 1.96 * sqrt( - 1 / .data[[paste0("n_events_", active_arm)]] + - 1 / .data[[paste0("n_events_", control_arm)]] - - 1 / .data[[paste0("n_", active_arm)]] - - 1 / .data[[paste0("n_", control_arm)]] - )) - ) - - # Prepare data for forest plot - forest_data <- ae_rr |> - mutate( - label = paste0( - .data[[aedecod_col]], " (", - .data[[paste0("n_events_", active_arm)]], "/", .data[[paste0("n_", active_arm)]], " vs ", - .data[[paste0("n_events_", control_arm)]], "/", .data[[paste0("n_", control_arm)]], ")" - ) - ) - - # Create forest plot - forestplot::forestplot( - labeltext = cbind( - forest_data$label, - sprintf("%.2f (%.2f-%.2f)", forest_data$RR, forest_data$lower_ci, forest_data$upper_ci) - ), - mean = forest_data$RR, - lower = forest_data$lower_ci, - upper = forest_data$upper_ci, - align = c("l", "r"), - graphwidth = unit(60, "mm"), - cex = 0.9, - lineheight = unit(8, "mm"), - boxsize = 0.35, - col = fpColors(box = "royalblue", line = "darkblue", summary = "royalblue"), - txt_gp = fpTxtGp(label = gpar(cex = 0.9), ticks = gpar(cex = 0.9), xlab = gpar(cex = 0.9)), - xlab = paste("Relative Risk (", active_arm, " / ", control_arm, ")"), - zero = 1, - lwd.zero = 2, - lwd.ci = 2, - xticks = c(0.5, 1, 2, 4), - grid = TRUE, - title = paste("Relative Risk of Adverse Events (", active_arm, " vs ", control_arm, ")") - ) -} - -new_forest_plot_block <- function(...) { - new_block( - fields = list( - usubjid_col = new_select_field( - "USUBJID", - function(data) colnames(data), - multiple = FALSE, - title = "Subject ID Column" - ), - arm_col = new_select_field( - "ACTARM", - function(data) colnames(data), - multiple = FALSE, - title = "Treatment Arm Column" - ), - aedecod_col = new_select_field( - "AEDECOD", - function(data) colnames(data), - multiple = FALSE, - title = "AE Term Column" - ), - n_events = new_numeric_field( - 10, - min = 5, max = 20, step = 1, - title = "Number of Top AEs to Display" - ) - ), - expr = quote({ - create_ae_forest_plot(data, .(usubjid_col), .(arm_col), .(aedecod_col), .(n_events)) - }), - class = c("adverse_event_plot_block", "plot_block"), - ... - ) -} - -# Register the custom block -register_block( - new_forest_plot_block, - name = "Adverse Event Forest Plot", - description = "Create a forest plot of adverse events comparing two treatment arms", - category = "plot", - classes = c("adverse_event_plot_block", "plot_block"), - input = "data.frame", - output = "plot" -) - -# Create the stack -clinical_trial_stack <- new_stack( - new_adam_block(selected = "adae"), - # filter_in_block(), - new_forest_plot_block() -) - -serve_stack(clinical_trial_stack) +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +blockr:::print_shinylive_r_code("ae-forest-plot") ```
@@ -753,9 +599,10 @@ In the below example, we implemented the Lorenz attractor and solve it with the ```{r, eval=TRUE, echo=FALSE} card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhBeTKwcXLyaphIMdtaooqQATAHhymoaQbr6RiaihZY2dg7Oru6e9FHVAfUhTeGR0bHxiSlpEOncLIxQDACefAWSM-OLK3yoDFAEMFCbC-s760XWJWXlM+kQcNQA+kQAJnBP6zIAPOYyAGZOCAEUjuCB8DCQ5IyEDpdIyGSieQQABePz+gOBoJIMj4pFky1kqCWMHY0NhEARCLqlKpCIAGqoZMSGKTgABGAC6MgAVDJlhzuQBqfnAcrcvkCgDMnNw8LpMgAmkyWWzxbzcQL1X9pZzknLaXSAFpM8wCrkarXC5kk9jAGWWsXcnX2znyhEzBEAXzhtP+LDg3Feyl+iJYnEEhpkUCZD2eECc8AYLAIT39gdefHMAA5DFLZOZ2QAGWTlIv690yOixx5PBNJlNpgNBrPFgsAVhLMmL5YNdIINfjibgydT6Zb5WzsnZ06L5fld1pcc+LXEkbp4+DTM37D7VLgAA89kz2C5OA4nOR1wrYhhXlAuBh-vt4NeFTI3nAACztt-vgFArIlbvssRZMhojJqDOSpMtBJpQRWUbvqQYFqCWwEKqQ-rQNwsFznu-42qyNTqBCfDHLIGBrPqMhUQQqQYR6GGIe+8wRpiTJIhQKKelSLFUpCGAEeo3CxCRdRgJ+K5mIMYD3lw0kSCkC7pD6sw5Ac4jojIy6cJp17LlJ6xAUutZXKURCkIpa6VpiA61JoB6ycsKQmXS7z-FATjcFZxDcImHDgZoywYOyzkYJUYC8TR8rLtYcBEDAihsFZ6zpDM7AjgAbh8ekSHweXiMkYBepyQA", # nolint - mode = "editor" + blockr:::create_app_link( + blockr:::shinylive_links["ode-demo"], + "editor", + header = FALSE ), full_screen = TRUE ) @@ -775,55 +622,7 @@ Toggle code
-```r -library(blockr) -library(pracma) -library(blockr.ggplot2) - -new_ode_block <- function(...) { - - lorenz <- function (t, y, parms) { - c( - X = parms[1] * y[1] + y[2] * y[3], - Y = parms[2] * (y[2] - y[3]), - Z = -y[1] * y[2] + parms[3] * y[2] - y[3] - ) - } - - fields <- list( - a = new_numeric_field(-8/3, -10, 20), - b = new_numeric_field(-10, -50, 100), - c = new_numeric_field(28, 1, 100) - ) - - new_block( - fields = fields, - expr = substitute( - as.data.frame( - ode45( - fun, - y0 = c(X = 1, Y = 1, Z = 1), - t0 = 0, - tfinal = 100, - parms = c(.(a), .(b), .(c)) - ) - ), - list(fun = lorenz) - ), - ..., - class = c("ode_block", "data_block") - ) -} - -stack <- new_stack( - new_ode_block, - # Coming from blockr.ggplot2 - new_ggplot_block( - func = c("x", "y"), - default_columns = c("y.1", "y.2") - ), - new_geompoint_block -) -serve_stack(stack) +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +blockr:::print_shinylive_r_code("ode-demo") ```
diff --git a/vignettes/blockr.Rmd b/vignettes/blockr.Rmd index 4bd31f29..1bb39e68 100644 --- a/vignettes/blockr.Rmd +++ b/vignettes/blockr.Rmd @@ -31,12 +31,71 @@ note_box <- function(..., color) { ``` ```{r echo=FALSE} -knitr::include_url("https://blockr-org.github.io/useR2024") +knitr::include_url("https://bristolmyerssquibb.github.io/useR2024") ``` -## Get started +# Get started -`{blockr}` provides plug and play blocks which can be used to import, transform and visualize data. +`{blockr}` provides plug and play __blocks__ which can be used to import, transform and visualize data. This guide provides an entry point for end users without extensive coding skills, as well as developers. + +## {blockr} for non coders + +In that case, you likely just want to get started to create your first data pipeline. + +### The user interface + +This is what the `{blockr}` interface looks. We designed it to be like a cooking __recipie__, where blocks correspond to the different __steps__. +Within each block are some __inputs__ that allow you to change parameters. For instance, when you import the data, you may want to select a given dataset or specify a file from your computer or on a server. In figure \@ref(fig:blockr-ui), +the `airquality` dataset is imported. On the top center of the block, you can see information about the number of rows and columns. Then, a filter block is added and target the `Ozone` column. Notice the __validation__ message as the value is missing. The submit button can't be clicked as long as the input is empty, which prevents from triggering errors in downstream blocks. Each block can be collapsed/uncollapsed and removed with the corresponding buttons located on the top right corner. As you can see, we group all related blocks inside a common container, the __stack__, which can also be collapse and removed. + +```{r blockr-ui, echo=FALSE, fig.cap='User Interface Overview', fig.align = 'center', out.width='100%'} +knitr::include_graphics("figures/blockr-ui.png") +``` + +### Starting from scratch + +When you start from scratch, there are actually no blocks in the interface and you have to add them one by one. +To add a new block, you can click on the `+` icon on the stack top right corner. This opens a sidebar on the left side, where it is possible to search for blocks. To make things easier, all the suggested blocks are compatible with the current state of the pipeline. For instance, when the stack is empty, only entry point blocks are suggested, so you can import data. Then, after clicking on the block, the suggestion list changes so you can, for instance, filter data or select only a subset of columns, and more. + +```{r, echo=FALSE} +# shinylive container +card( + blockr:::create_app_link( + blockr:::shinylive_links["empty-stack"], + "app", + header = FALSE + ), + full_screen = TRUE +) +``` + +### Toward a dashboard + +What if you aim at creating a more ambitious pipeline? In that case, you don't need one cooking recipie but multiple, so you can organise your own dinner party. Below is a slightly more complex application, where you can add multiple stacks and connect them together. This are the following step to connect 2 stacks together: + +- Click on "Add stack". +- Add a new dataset block with the default BOD dataset. +- Add a filter block. Target the Time column with values between 1 and 2, then click "submit". You should get only 2 rows. +- Click on "Add stack". +- Add a new result block in this second stack. You should see the same result as in the first stack. + +Doing so, you can build you analysis step by step in a modular way. + +```{r, echo=FALSE} +# shinylive container +card( + blockr:::create_app_link( + blockr:::shinylive_links["workspace-kitchen-sink"], + "app", + header = FALSE + ), + full_screen = TRUE +) +``` + +## {blockr} for developers + +In the following section, we describe the building blocks behind blockr so you can start creating your blocks. ### Introduction @@ -75,7 +134,7 @@ mermaid(" ) ``` -Under the hoods, blocks are composed of __fields__. The latter are translated into shiny inputs used to convey interactivity within the block. As you can see in the below diagram, fields are combined to compute an expression, which eventually leads to a block result after evaluation. For a data block, there is no data input. +Under the hoods, blocks are composed of __fields__. The latter are translated into shiny inputs used to convey __interactivity__ within the block. As you can see in the below diagram, fields are combined to compute an __expression__, which eventually leads to a block __result__ after __evaluation__. For a data block, there is no data input. ```{r, echo=FALSE} mermaid( @@ -148,16 +207,6 @@ mermaid( ) ``` - -### The user interface - -By default, only the last __stack__ block is visible, all others are collapsed. -To preview all block you can set `options("BLOCKR_DEV" = TRUE)`. - -```{r blockr-ui, echo=FALSE, fig.cap='User Interface Overview', fig.align = 'center', out.width='100%'} -knitr::include_graphics("figures/blockr-ui.png") -``` - ### Create a stack To create a __stack__, you call `new_stack()` and feed it all the required __blocks__. @@ -165,6 +214,14 @@ Below is a simple stack providing a dataset selector and a filter operation. `se wrapper to run the corresponding shiny app. Note that with `serve_stack()`, you don't need to worry about specifying any __modules IDs__, they are automatically handled by `{blockr}`. +blocks can be instantiated either by calling their constructor name and passed to the stack: + +```r +stack <- new_stack(new_dataset_block) +``` + +Alternatively, it is possible to create block with specific parameter values, as shown below: + ```r library(blockr) library(blockr.data) @@ -177,112 +234,22 @@ stack <- new_stack( serve_stack(stack) ``` -```{r, eval=TRUE, echo=FALSE} -card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkZWQw5+YWSGAAmUFwlmdl5fKg88AyoFNZObOwl6ZxQEjIAPOYyEHDUAPpDEoIQMjJVAIyqk9MzdVzscKQzVXx73HAE5DUbQl0QPX0BbRJQ1nBXYG3cHTd3HCm46csqgAmDZTWYAMxY3HIDEOogWxG4ThgHDe7C6BBYcH8eBkADceE5sW8AII1OCZOApdIlPYMPFwOZcBbzcTJMAAXwAukA", # nolint - "app", - header = FALSE - ), - full_screen = TRUE -) -``` +By default, only the last __stack__ block is visible, all others are collapsed. +To preview all block you can set `options("BLOCKR_DEV" = TRUE)`. ```{r, eval=TRUE, echo=FALSE} note_box( "You'll notice that some blocks, such as the `filter_block` - have a submit button. The reason was to prevent any expansive task - to run without explicit user approval. That said, this feature is - still very much experimental and might change in the future.", - color = "primary" -) -``` - - -In the next example, we'll see how to create an which can dynamically add or remove blocks. - -### Dynamically add a block - -The stack exposes a helper button to add a block in the top right corner of the card header. -It triggers an [offcanvas](https://getbootstrap.com/docs/5.3/components/offcanvas/) -UI panel, that basically allows one to select any block available in the -registered blocks [vignette](https://blockr-org.github.io/blockr/articles/registry.html). - -As a side note, there's another mechanism that works to add blocks, which we describe in the -following. It is more verbose but allows you to -bring your own custom UI. On the UI side, we call `generate_ui()`, -which is nothing more than calling the stack module UI and `generate_server()` in the Shiny server function. If you leave `id` NULL, -the namespace is automatically handled. To get the list of available blocks, we leverage the `{blockr}` registry namely `available_blocks()` which exposes the -currently registered blocks. You can learn more about the registry in the dedicated -[vignette](https://blockr-org.github.io/blockr/articles/registry.html). -`add_block_ui()` is a UI helper to show a button as well -as the necessary interface to contain the new block choice. -Within an `observer` we listen to the "add block" button. Then, we pass the new block in the `new_block` slot of the `generate_server()` function. -It accepts the name of the block to insert as well as its position in the stack (here we append and leave `NULL`). - -```{r, eval=TRUE, echo=FALSE} -note_box( - "Note that `{blockr.demo}` (https://github.com/blockr-org/block.demo) - utilises `{masonry}` (https://github.com/blockr-org/masonry) to provide - a better user experience, allowing one to drag and drop blocks - within the stack.", + have a submit button. This is to prevent any expansive task + from running without explicit user approval.", color = "primary" ) ``` -```r -library(shiny) -library(blockr) - -stack <- new_stack(new_dataset_block) -shinyApp( - ui = bslib::page_fluid( - add_block_ui(), - generate_ui(stack, id = "mystack") - ), - server = function(input, output, session) { - vals <- reactiveValues(new_block = NULL) - stack <- generate_server( - stack, - id = "mystack", - new_block = reactive(vals$new_block) - ) - - observeEvent(input$add, { - block <- available_blocks()[[input$selected_block]] - # add_block expect the current stack, the block to add and its position - # (NULL is fine for the position, in that case the block will - # go at the end) - vals$new_block <- list(block = block) - }) - } -) -``` - -Blocks can be removed in any context. Keep in mind that a stack can't contain 2 data blocks. - -```{r, eval=TRUE, echo=FALSE} -note_box( - "At the moment, we don't check whether removing a block breaks the pipeline.", - color = "danger" -) -``` - -```{r, eval=TRUE, echo=FALSE} -card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkZWQw5+YWSGAAmUFwl6ZxQEjIAPOYyEHDUAPrNEnwl7HAMAG5w-VyDA+LJYAC+ALpAA", # nolint - "app", - header = FALSE - ), - full_screen = TRUE -) -``` - ### Example with modules -The stack can be nested within modules. This is what we do in -[`{blockr.demo}`](https://github.com/blockr-org/block.demo). +This might be useful if you consider embedding blockr in your own application. +The stack can be nested within modules. ```r library(shiny) @@ -328,27 +295,36 @@ shinyApp(ui, server) ### Connect stacks: the workspace The __workspace__ allows you to create more complex analysis by connecting stacks together and get a dashboard. -To know more about this you can read the following [article](https://blockr-org.github.io/blockr/articles/data-blocks.html#reading-data-from-another-stack). +To know more about this you can read the following [article](https://bristolmyerssquibb.github.io/blockr/articles/data-blocks.html#reading-data-from-another-stack). -```{r, echo=FALSE} -mermaid( - "flowchart TD - subgraph s1[Stack 1] - direction TB - input_s1(Data) - transform_s1(Transform) - input_s1 --> |data| transform_s1 - end - transform_s1 --> |data| input_s2 - subgraph s2[Stack 2] - direction TB - input_s2(Data) - transform_s2(Transform) - output_s2(Visualize) - input_s2 --> |data| transform_s2 --> |data| output_s2 +```{r, echo=FALSE, message=FALSE} +mermaid(" + flowchart TD + subgraph LR workspace[Workspace] + subgraph stack1[Stack] + direction LR + subgraph input_block[Block 1] + input(Data: dataset, browser, ...) + end + subgraph transform_block[Block 2] + transform(Transform block: filter, select ...) + end + subgraph output_block[Block 3] + output(Result/transform: plot, filter, ...) + end + input_block --> |data| transform_block --> |data| output_block + end + subgraph stack2[Stack 2] + stack1_data[Stack 1 data] --> |data| transform2[Transform] + end + stack1 --> |data| stack2 + subgraph stackn[Stack n] + stacki_data[Stack i data] --> |data| transformn[Transform] --> |data| Visualize + end + stack2 ---> |... data| stackn end ", - height = "600px" + width = "100%" ) |> htmlwidgets::onRender( "function(el, x) { diff --git a/vignettes/data-blocks.Rmd b/vignettes/data-blocks.Rmd index 126a9718..d2e02710 100644 --- a/vignettes/data-blocks.Rmd +++ b/vignettes/data-blocks.Rmd @@ -50,32 +50,18 @@ new_dataset_block <- function( The `new_dataset_block()` function defaults to using the base R `datasets` package, but you can supply any valid package containing one or multiple data sets. Here, we use the `{blockr.data}` package to select the `"lab"` data set: -```r -# Define the custom data block -custom_data_block <- function(...) { - new_dataset_block( - selected = "lab", - package = "blockr.data", - ... - ) -} - -stack <- new_stack( - custom_data_block, - new_select_block -) -serve_stack(stack) -``` - -```{r, eval=TRUE, echo=FALSE} +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +# shinylive container card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkQBE6cRDAA+gAmUFxVheIyADzmMgBmTqWk7hB8GIPJMiDpMjIQcNS19bFwpI2iEoIQ4+PscNxwBOQ1qoFg3FB00mNrqFASUNZw+0JNDBh1XKera4MYZyUAvunpnJdmm0JlMqgDlmcyhVqs8oIszLIzpNphstjt4RJ0iUNgwAG5wMFcZbg8TJMDfAC6QA", # nolint + blockr:::create_app_link( + blockr:::shinylive_links["dataset-block"], "app", header = FALSE ), full_screen = TRUE ) + +blockr:::print_shinylive_r_code("dataset-block") ``` ```{r, eval=TRUE, echo=FALSE} @@ -101,26 +87,18 @@ of the four following data __parser__ blocks: If you want to load data from any location on your computer, `new_upload_block()` is what you need. Since the `new_upload_block()` temporarily moves data into a custom location, for security reasons, it might not be always possible. -```r -library(blockr) - -stack <- new_stack( - new_upload_block, - new_csv_block, - new_select_block -) -serve_stack(stack) -``` - -```{r, eval=TRUE, echo=FALSE} +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +# shinylive container card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkQ6ZxQEjIAPOYyEHDUAPrlEoIQMnUNjU6oolAAJo2F4rjpHfVNBOwAbkOiEqPtnU3scNxwBKRzZuklqwzTcM1crS3iyWAAvgC6QA", # nolint + blockr:::create_app_link( + blockr:::shinylive_links["upload-block"], "app", header = FALSE ), full_screen = TRUE ) + +blockr:::print_shinylive_r_code("upload-block") ``` #### Files browser block @@ -143,26 +121,18 @@ In the following demonstration, dummy dataset has been uploaded to the webR file the block. But, you can also upload your own data thanks to the corresponding shinylive feature (upload button). -```r -library(blockr) - -stack <- new_stack( - new_filesbrowser_block, - new_csv_block, - new_select_block -) -serve_stack(stack) -``` - -```{r, eval=TRUE, echo=FALSE} +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +# shinylive container card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkQ6ZxQEjIAPOYyEHDUAPrlEoIQMnUNjQBmLNxw7IxE1OxwDI2F4rjpHfVNBOwAbhOiEtPtnU2j-QSkK2bpJaMMi3DNXK0t4slgAL644NDwVKgU1k5s7BgLi3iEJORKMghOxXgQWANpEIWOxuFAIAATKHCPrcRr9CDWRyNGAwZF0VGNBEKbG45HdTLoMbot6kvF4IR0IgI3I42LsRpJBlgUYAD2RuTgOSE6SEAEFiZk4MiACqJMajUp4ADMAE4MABGXAagAcGAA7NqdVrlfqAKwABmmYBgPGleAATBaLfrRWAJXApbL5QxFdI1Rgzdr9RgACxGgBsuGVOud1u6cFt-WkTpdbo9Xu5cpsCoo0lDFowyqN2tVQeVDst8cTdpTztdSozEO9Od9ebwADkxbguz3u73e6mG+LJc2sz6-SqIwbS0XS8XlaGq0IE0n7bgh+nR+uhNnrLmldH1cWnRgoxrVVblRHlzba4761vPWPrXuD-69argxgdUaTRHK2rNc6zTRttxbfc20PAMHVnc8y1wUMI3Na1gIfUCR2fHcwDfKD-VDTUjUIi8F1DFDB0fMCsIg988FDWDT1gi8rXoqsKIw91wPHVtJ2jENfw1EMtV1KNlWVON2OHTjqO4yDeNNH9v2LXUr31CTu03KjM1fCd20QjViJDc8dVgis4xXGtk3QqSm2w3D5L1KMHQMpjVRNWMrSENCN0ozDtN3XToIIpyDOE1Vf1DAtPLvKyfI42yaLwqcz2-ASdXLNTotXe84psridJ4vSYxnC9S3LJcsss9dNL8l8AsKw96MDHyStVQ0Kui7yauk-ycMC-CwyI8NdXDMTAIsrrfJ6uq+oa-MQuai9w3o8yYuqqaEu5AAhGFiHXBS0rnQTRqioCcu6zbrR29g9v9ENDV1ErY2jCNVsm+L8qEa7bpVM0MC-C8MCYnUvxjVbstii7PrAb6iH2vVgeI9Kj1vd68pkq7drhj9FMEoGjSvDzUPOjbodh-a-uUz8jUNMHKrRp9evJ-NC2MlLdQXM1UZJj6Ma+rH1wLRaQwBnVadTM7IdJvmYYFu7-qI899VMjVbwh9beaZuW6MLINHtFq8y06nn0d6gAReRYH9dU9enB79V-Cs1aqkDTZmi2hXpPj8ce4SHaPN6TcZ93La9gM9f4o1HfE+mg60kPPZZhX9aNUbL2NqXNYTq3kuGh6ELGoMJrj2rsI9nOj3x5ziNVKNQ1VjONbdsvQ5x38nVLQ3ucz5vkXLr2msRvXnuVLnY574OW8TlUjNnKmTRjyWm8nvvW5VdUBPVYSdWWm9G9dlfuX7-1p2Ho0Vedhn46niuhcO4aC-T4mJ+v1fp5eojh9EjVwZd6zD+tMfOiBEwqtTrqdLyJdpo3zDg9acotyzOnHsvV+R816VzZpvFir197-1QYA9B9ca7n2jKxZ+KDS5vwrgpYeyd9RfgdG1IMkkAFCCAR-PGANLykMvlAy6bDCEOjnNXVyWp67dwodA5EzN17s3upGaMlpkEgR1Kw2WN1sY6yRsnHUEVF6QMzqo-B-MNEU2-Fwq8FUl4qLUTIxCrlmoSwLBImxxj1E-VIYtPU29DSMN-u9IxlDtra30oNR68ETSZXIa4oJmNTHW2-F-RRvDDG2JCULTB85oxEwMRrQJUjgnxOSrbdmxoNzpWUehfJ-D3GaO9vBGuo1zS4LitUsmITR4lXgUacsDdrFVLSUU0JJ5QplUQhAtaMSClxI8QpJWPSXr+J5m0mWdiiHbx9qqWCziWmphWVrIZ14wlCVTuUlJeTBkeKIcZUspkjbRIGW4uxnSSmuXLKPSprTLl1PWbObeEUf67OdPsma9kip-QBtOeCV4LTnKmTUsFjUDKbzCeFcZLjHmxPqnJIqypFoWMWZ8vZajEXWyeqiw2gdUluNJbIpWmzRJj36V8ml-U6J-UOlw9qfTcnwuhrSxRwt8WqSWdSrFs0cWNSEYdPWCFWJAotCCuybLEKFkhbjNyfFRUXNZXNGemywk7wDgqpViV5LTiYtOHxySiXApJSqpqoCwpBiiia+1erPH0uBqDCWxcxXTOxbRexdD2a10QlE3lmKA0SqDUch6eo0q0xyWAdWfKZYCs6aAh+xYVpurcewhSylI4XgXnCqNNT2FEJPIWZSqpRpMsjSy8VBbpy1uFdkqlOrm3oKOaLUpoMlHMuJfmnteo23epRnm7t79ip9qwYSoddqR0zr+vGnypkG0pr-k26NlbRm+x8i6-Rkzy3QwLXnJG5VtVpvNj29UbNt7gIxTuitPaLVKRptGY9qbT0y0rYWTlPk9GdpvdnMO3jFady1baxVaj-1HT1LKuuHyHkvrPT2vFwkrXBnbk-P1Xbd2ELxUPW5+kQO-oObMiOyctl8XGlu96qpvmCy1B3J0OblZFxPXFJjTyOnyI1MZBcLouM-p48x+W7crTMXsc+1MvHxXPJFpBkiG4tmie3fJiTsj406PrXJ50Cno3PMct+VyoNmmLotEZmpJmq7Se4Wqcj4m+OHIg4JP80ZBIacY9pxCxHSylnavqFCjatOudme50+pZHYmR8zzGz7ShlLhSqeWtYicGofC4pjp6p7atQXL6hjCW-OD1nLK9qDpQvcey8Z3LqXCz5xNHh4rmdEurPSUI3Tta64iay4Z91kqcbzN1Lh696F2u9QzSGat+KLPVd87qobv0SrxtBih-DIFJugodfu0zup1v0cW+KjN768bA1pjy1rGttvKo9QpfOGrHaDrCwNpbQahZMXtqJKxm2JuDY+wZYaiH13ZIWyV97SVBVMQhQo8SZaXMnYdazQLF4vyuv69ZgHUPioCVniW6MVX4ttex7xIhtDa1Huc7VhFKq1TfjCiaWFMHbtmr0pFJGG4f6qup29pH92QecKg4XKzrPZIfcw7OVytMXs1b54Rmd04ZVZI+SzuDPaQy0NlejsiXHjsK+oe5-HYtSH0bEzT9D79fl41lZShVYuCErrkfik03nRfq6t4WBihZWNxjVODkny7qFwK8VetXQew55fMVk+VmOHcCM9z7E5qnFzjcRwbgeKPzufsXAHm7HvqFCOEn9Yejtmfu4j0ne2wvONx4L7Ao6SvSMx3D9O6hfb43lj3nXyvsjEbQtk-b+vJ9SmGpOtV838vX2K9SmMxcCOLd-o17jdzqoFyWde1j3vHDk8m9NGnxft6rcGS1z5MRSCe9CAAOIUFIEQIg0j0nYY1AF5yYjZeT44jfsg9-H9DKrIJsIuJLgGaBGnLl-rfr-oUlcnqA9CAlzixL9tdgfEqN-nfg-tAXUgAX9AxLqCAWAVfNfpARgTMj8vjgREGM5EGGaBMoQWAGgVAaQYLNFi-o4tzkuAvlNAwSQSYlcn9MNMFFzmIsmp-lJNwX-lcnbNqJTFzl+GaEVnQeIZgYLHispHiuGE6DrgflwcQRIT8k3qrINFQSAVdoobocoUnADHir4hqLvJwRAT-jwbUoLOqqxoJiAZumYY4XoYLCXtqNYVznYTBmIeYUwfmHqAIali-iARUpjiEd4RYeyrjIIc5CxEVqIW6EoWEXRMeNITOM5IaGaLEZvvEegT4fmExHipQewVdhkagaEbwT8uqDDlXM5LgBGMel4WUYkYhGdhQT5OjiIZpjoQkdkYhLAXkaxg6LBGaBtuAaUYwY0euJaD7ARCMr+KAbzg4d0WMSlsJP0cYUosEZkQ0c4fNItAcdEZFNodsYsWcXRK2nke3KrCAeXiUScaMUsRUcnJLocRfn9rlB8TsV8Q8cRH9G4dQYCnEUCXcWsv0bYcIu4fXOpICfUZ8fceGrjNUdQd3u8WicCRiaGAjNqGsQgb0TcQsU4XYtgcIh3FzAZrcVSekjNnkSeNMSAZWAqpSeUXRNKiSfZujmAXUUQeiWsuCfyZQS6K8fYdyT0WaPesGBuMAa9AybKbsVvPye3HSbUcMbBvibCekhEdqI8dMVaDQVsfklkSCcGueAEc5DmvcgCcOiKQSXCccoiXIZyZjpaacXCf4Q1novYT6aKYaSVKukBiAXMQEjCUycll1v6b4oqpOlZsGa6ekgqe4dMdQQQcsjGTyYhDIawTYSxN+rqamQaclhmdUXXBvuAeWbGR4isXrLDtMTMZ4bmfqQ2T8niraQrAUYhC1p-vWfmSlnrHigwuwekWWXmXKbrHkQwoBOaVOvQb6ekgRFYYicWGaFCU6Uui6RWXwT7BylztQZ0R2fuV2cwezARLgSxMUcgVGlaYSYLvAaaZGRaTObseKQiRoewRMkOZ+daSscXhuIuf8XWYBYSSwQRL+e1IOdOZ2SOc2UYXSW8RBYhT0aGHigJOORGVhTccOZhX4S8W+Ucd6ZBWsgFgiZKRFEgQBRhWMSscNDIdMeGPScuU+WKUdNhXhVOdGQxdaUhKsX2W0bMR+QJYSeGawROctP+QhRefmTQUdOGQ6MqFqGaLiehQpURckVXKVGRARRRembjE3qpWaTmf6pxU-sJb+UEX2DulZZWYtO+tMXIcmvxdpbsVUfyQxB3AZTBoRYxY1tIaBVue2ZZauclgJtWeGkGUZcltOMxalqJeBR5SuSGclsSYYU5KJTuVpelWmQlRcYpP2fIYZRJWsolSFc5DWeVZ5YJftk5MAUUeJfVYSZrj5QMeSQFfFY2fuiaR3DghxZFYeZUSVS8brj1RVekjgcaShVuY6flY5VchqdRVztsgBMTvntNf-kIshTlepUgfrstWQWEikRqNsrXruVvm1dSdJi2Q6GxVGRDrdWuT8eNZdfYUZidcsQBh+tMRsZlpvt9SNd2WdUYXgUhDcSDRlX1UdDeVzhsWeYHq9VFRceteMRPrqTDYVY2UXoqWZR4QyTjQeadc2YjQOV9b1VgUIl9oRADSAbQS9QVaTb4cVdUZ9a3izZefmDbHNVMWxZpcdaDYLPCQRDYctPeZ-iTTzXgCsQJCpQ6FGGVUPjtStWEseTVQOUdszT9ecQDCkeyUSVjcLbDT8kaT+T5DmptRXqjXDVho4ouV6cDdTYLILtUYMVTWrVgbDh5gzRpVsTLSOSGC0diQOSbbrSLbzWCaBRsbLqbbjadWoeNTWYBOxEHZhQYdhocfHZHWbSxiVOLWSf5bbdzYpeoU8bIR4YHa7fmKoSSXhaAVtVtrXXRO5uKZodXarXbVgXOYYbgcreBdLa3QOViSJXIYtQnazXXYtLNfab0V7T3csSfnNSeM1bnSjWXZncJW4e1KaM3f9t7csd+U1WafeVPbLeMrPfkR5sbcwhpPLnrW3SZa0bBENZflvbsSHQmYEdrQfenk-fZQOP2CAwA1HaCQJKScYUSYvZ-UBYWElb4uyU3d3XA5JcJc8TMXxXnYnS4cnNndEUuR-QAMJaCfCkAMBoBUIDwsHKYXgboUluikPkOUOoDUPSAAF80XiiQtZ0HMMcAUNUNoLvzblHTNEq5C1QL8OcCsPsNJHA5PTPZm66lSTSOCNsPCMVzyGtQaq0xXXzFMNkMCOyOaMDyzV4ybyOyLXClgBqMmOO63zP5ZX+xOzHFKh2NCMONeyiNUybJ6OqmGMsOeMJ6ONERcIuo6l8NGMyPBNgDsI+OzhcKOwWWSIeMaNePnH0qbwLhDFRNBPpMhPeMGSJliNNJ54oFCBpNyPhofq6gZSMPuPRPqPVPyFES+7n4BONP5PVMpYAzJ6OZN1WaqNNP2OFMcN90KlOgdNcmBPGOxPxM1o+RBZfpbHDPdOmMcN44r6RINOVMjPzOEJVXhLC50UqOzMxMFNxOELiOPRvLjKrPnPNMbO8nunzwLrXVrNzOXOVqC4dUE6p4zNdNfM9NUVQqfp+JuN7PrMZNy1Z7qjZodqAtQvAvPO9GrY0bvK7O2P7PfPoKtOlQXjcqdPIsXMtN91GkSwAspmPOjNXNW5cMMJ+7uXnnYvQtjOgkXqbw7NTUktPMwscklVWhOgurhUEZVOotCzqrGTix1Wssov8tKXe6CtiLI1is4s9N7VzXxq0xzH0W8u0vxMbJSY5p5VpXiv8uhhR7HMXhd6tVyuksSt-MGGqigzwVmvquOuj6U7ZJxVAsOsKtKvFnjF2vmvstotSukZVayuht0taPeWAyMsishsesWtcJsFdzLkxuVpnZ-N76aV6v2t8thsrFpthSMoMn5JZuELEX5yMrRspvFtqrR7cMvQR2b1VsiN-WPSSliJHXM0dtaM+7NuOZyX64DsDxpshTbKqst1+tFuxtFNeJPTizE00sHP0u4wskXiOzIT-21bjvhHERHMutfrKNjsNsLscNA6BZTPJku1zsGvVvou1oLhA0Pnp4Huws6OJk5poXntsuXsvPUZUw6uwOfsCuIyby0x9vtsXuVrmNgv-PO3vv7twfXNiN9kWi-ursPvruDs+wJqg50wkNodW5-QNIPz1pnv9ukdaMGRpuSk8M4f6t4c0Mv3Dygz5vY1ru4tkerZz5cf-vyvFvHmAxSbtSpU0cAeVrxsQZOimSjtSfCeAej1syuTr7lOH0se8f4ebzF2mtKf+uNsEetTJNtvbV3AAC6QAA", # nolint + blockr:::create_app_link( + blockr:::shinylive_links["filesbrowser-block"], "app", header = FALSE ), full_screen = TRUE ) + +blockr:::print_shinylive_r_code("filesbrowser-block") ``` Note that in a later release, we plan to merge `filesbrowser_block()` and `upload_block()` into @@ -176,28 +146,16 @@ a `new_dataset_block()` from which we can select some columns with `new_select_b we can reuse this smaller dataset. If you dynamically add a third stack, you can also select the third stack's output as input to the second stack (it appears in the result block select input). -```r -library(blockr) -library(blockr.data) - -serve_workspace( - stack1 = new_stack( - new_dataset_block("lab", "blockr.data"), - new_select_block(c("STUDYID", "USUBJID")) - ), - stack2 = new_stack(new_result_block), - stack3 = new_stack(new_dataset_block("ae", "blockr.data")), - title = "My workspace" -) -``` - -```{r, eval=TRUE, echo=FALSE} +```{r, results="asis", echo=FALSE, warning=FALSE, comment = ""} +# shinylive container card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDcLIxQDACefKYSDGkZWQw5+YWSGAAmUFwl6exwDABucAD61Fbi7KhQBHCCEDIynAPiAIyqMhBw1B3jEsOjo3MLdVzNpB1VmtxQdAFCVQy19VApuOmrs-OLcNxwBDt7GkIAygAqAKoAIgBNACSf2OYB+Hx+ACEAFIglIlUbJa4jMZcCQAJhm60W6PEfBx8nYTm4r1EEmRNzREwAzNj7kt8TjNrE4GSzJooHAwadzlwESjRqQHE8ZkIALK5GTdBi9fqDITpZJgAC+AF0gA", # nolint + blockr:::create_app_link( + blockr:::shinylive_links["result-block"], "app", header = FALSE ), full_screen = TRUE ) + +blockr:::print_shinylive_r_code("result-block") ``` diff --git a/vignettes/developer-guide.Rmd b/vignettes/internals.Rmd similarity index 98% rename from vignettes/developer-guide.Rmd rename to vignettes/internals.Rmd index 6be8b159..65072a57 100644 --- a/vignettes/developer-guide.Rmd +++ b/vignettes/internals.Rmd @@ -1,8 +1,8 @@ --- -title: "Developer guide" +title: "6: Internals" output: rmarkdown::html_vignette vignette: > - %\VignetteIndexEntry{Developer guide} + %\VignetteIndexEntry{6: Internals} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- diff --git a/vignettes/new-field.Rmd b/vignettes/new-field.Rmd index 17f84ebd..b970b6cd 100644 --- a/vignettes/new-field.Rmd +++ b/vignettes/new-field.Rmd @@ -108,11 +108,13 @@ ui_update.slider_field <- function(x, session, id, name) { We can test our newly created field in a custom block. -```{r, eval=TRUE, echo=FALSE} +```{r, echo=FALSE} +# shinylive container card( - create_app_link( - "NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAdzgCMAnRRASwgGdSoAbbgCgA6YOtyIEA1gyG4ABAzioi7GQF4ZBQWAAWpUqnaIA9IZFjJAWiIMA5hmstSWgK50MLIodqNz8xe2kyQjp6Bsa+RBgM5tRQ7DAYVtZCAJTJAhDp3CyMUAwAnnymEgxpGRAQcNQA+uxZACZwDFUAZixw3HUyADzmMs1OEASk7hCCEDITMgBuPE5wqjIQTvAMLBrJuOmTMjBsC0sra3wbW5MwUAAe+8uNRyfjk5wK14frmw8TGF-JMiCnRZJmBVqq12nUxtsZtw5gsoXN3ttduM1EiEWdLgtzhc0RMnqgFnicTIvhgiQRuLFlGohLUWA0mqCOkJTqUAL7pdJOFhVNioJykDC0+ktNodbq9fqDYYkPjYmR02TQeA-P4PdhaNh5ZhCxoASQgfNIEMmAKYrAN-J5dXYstkdPu2yVcCJcPmalNzFdtsCYFdKSJSIWHsQXrlQiR-tOEyxQdExU9szg3vDl0jHxkeNjZjNodkNPIqBSLPS7LKULpUHIIrBgvqjWrYp6fQGQxGspVpyh4umifbp0DTdzPojYFK0Yxg97YbAWKLaoL3aH+YUc87PArVYOdEafChpVOLGaMj43Ao1kcfCRqV+UZ79UrcCqW53qOHbDnE1LB6PJ7PF6x16qpC651A+T7LNuDCXpceYzqmo6nF+DyHsep4QOeWh8HigG3uWoGbhBO6Ej6eIfjISETAAcnAFykAAsnAjhEOCbIcks3JOKg+FwLWdL1oynRNpKrYynK7BwOw7AjHadSKrAcAdg8nHcQAynWDD6oaxq4hJUkkESwa8padI2nK9pEk6BlxoCIZTg6JrWTmU6wSO9kTMGS5wRcabbB5zkkQWZGsWU8j2E8DAqQAzPATHgkIXI8hapABDS6kNnUAQJUZAo6gyop1KUoUsOFUUxVozGaAlykPilYC5elmUcVxD68cKAn7uUlQ1FkBCPgC3bCdKozNAwRAwAsAAMsgkoppwQFUo3UMoTYCAIfD4VAPwQIt62VptbETAJy29FknDaXIRBLfsXX1QJ50TK6CwjWNRLRnsahTbe45XGo82Lewr0ZguagAIyA8MpCngsQgqe0cBDBdS3MumY4yB1EzAlUALnUdT35QDt40agDALAAjk4RDkOtqDcHkZq0r1WFwKTVRoXwGB8P9qSpBZ8nQ2Aal8STDPzAC0i3iSZIUpJCwaKlax9dZtWkAwUAcM0VgwFjSsIQ8wXpOJDBTI+nBQBIxqY6b5u3pjG3iaQ2tmJoLCrP4o4WTdPWK07ACsqOlMkYCsgAukAA", # nolint - mode = "editor" + blockr:::create_app_link( + blockr:::shinylive_links["custom-field"], + "app", + header = FALSE ), full_screen = TRUE ) @@ -122,7 +124,7 @@ card(