├── _pkgdown.yml
├── .github
├── .gitignore
└── workflows
│ └── R-CMD-check.yaml
├── .Rprofile
├── inst
├── tiny_demo
│ ├── helpfiles
│ │ └── geom_segment-plot.md
│ ├── ui.R
│ └── server.R
├── WORDLIST
└── example_app
│ ├── helpfiles
│ ├── airquality_basic-data.md
│ ├── airquality_basic-plot.md
│ ├── airquality_advanced-data.md
│ └── airquality_advanced-plot.md
│ └── example_app.R
├── renv
├── .gitignore
├── settings.dcf
└── activate.R
├── .gitignore
├── tests
├── testthat.R
├── spelling.R
└── testthat
│ └── test-create_tooltip.R
├── .Rbuildignore
├── R
├── tiny_demo_gui.R
├── download_button.R
├── shinydetails-package.R
├── custom_help_files.R
├── elements_h.R
├── tooltip.R
└── plot_panel.R
├── man
├── run_tiny_demo.Rd
├── shinydetails-package.Rd
├── dt_format.Rd
├── beam_downloadButton.Rd
├── create_help_files_custom.Rd
├── plotOutput_h.Rd
├── tableOutput_h.Rd
├── sliderInput_h.Rd
├── numericInput_h.Rd
├── extract_tt_data_row.Rd
├── flip_ggplot_build.Rd
├── beam_tooltip.Rd
├── beam_plot_panel_UI.Rd
└── beam_plot_panel_SERVER.Rd
├── shinydetails.Rproj
├── README.md
├── DESCRIPTION
├── NAMESPACE
└── renv.lock
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/.Rprofile:
--------------------------------------------------------------------------------
1 | source("renv/activate.R")
2 |
--------------------------------------------------------------------------------
/inst/tiny_demo/helpfiles/geom_segment-plot.md:
--------------------------------------------------------------------------------
1 | lalalalalala
2 |
--------------------------------------------------------------------------------
/renv/.gitignore:
--------------------------------------------------------------------------------
1 | library/
2 | lock/
3 | python/
4 | staging/
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 | docs
6 |
--------------------------------------------------------------------------------
/inst/WORDLIST:
--------------------------------------------------------------------------------
1 | Tooltip
2 | UI
3 | jpeg
4 | png
5 | svg
6 | tabset
7 | tooltip
8 | ui
9 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(shinydetails)
3 |
4 | test_check("shinydetails")
5 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^renv$
2 | ^renv\.lock$
3 | ^.*\.Rproj$
4 | ^\.Rproj\.user$
5 | ^\.github$
6 | ^_pkgdown\.yml$
7 | ^docs$
8 | ^pkgdown$
9 |
--------------------------------------------------------------------------------
/tests/spelling.R:
--------------------------------------------------------------------------------
1 | if(requireNamespace('spelling', quietly = TRUE))
2 | spelling::spell_check_test(vignettes = TRUE, error = FALSE,
3 | skip_on_cran = TRUE)
4 |
--------------------------------------------------------------------------------
/inst/example_app/helpfiles/airquality_basic-data.md:
--------------------------------------------------------------------------------
1 | ### helpfiles/airquality_basic-data.md - Under Development
2 |
3 | ***
4 |
5 |
6 | This help file was generated automatically.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/inst/example_app/helpfiles/airquality_basic-plot.md:
--------------------------------------------------------------------------------
1 | ### helpfiles/airquality_basic-plot.md - Under Development
2 |
3 | ***
4 |
5 |
6 | This help file was generated automatically.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/inst/example_app/helpfiles/airquality_advanced-data.md:
--------------------------------------------------------------------------------
1 | ### helpfiles/airquality_advanced-data.md - Under Development
2 |
3 | ***
4 |
5 |
6 | This help file was generated automatically.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/inst/example_app/helpfiles/airquality_advanced-plot.md:
--------------------------------------------------------------------------------
1 | ### helpfiles/airquality_advanced-plot.md - Under Development
2 |
3 | ***
4 |
5 |
6 | This help file was generated automatically.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/renv/settings.dcf:
--------------------------------------------------------------------------------
1 | external.libraries:
2 | ignored.packages:
3 | package.dependency.fields: Imports, Depends, LinkingTo
4 | r.version:
5 | snapshot.type: implicit
6 | use.cache: TRUE
7 | vcs.ignore.library: TRUE
8 |
--------------------------------------------------------------------------------
/R/tiny_demo_gui.R:
--------------------------------------------------------------------------------
1 | #' @title An example component
2 | #' @description Run an example app using \code{shinydetails}
3 | #' @importFrom shiny runApp
4 | #' @export
5 | run_tiny_demo <- function() {
6 | runApp(system.file("tiny_demo", package = "shinydetails"))
7 | }
8 |
--------------------------------------------------------------------------------
/man/run_tiny_demo.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tiny_demo_gui.R
3 | \name{run_tiny_demo}
4 | \alias{run_tiny_demo}
5 | \title{An example component}
6 | \usage{
7 | run_tiny_demo()
8 | }
9 | \description{
10 | Run an example app using \code{shinydetails}
11 | }
12 |
--------------------------------------------------------------------------------
/man/shinydetails-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/shinydetails-package.R
3 | \docType{package}
4 | \name{shinydetails-package}
5 | \alias{shinydetails-package}
6 | \alias{shinydetails}
7 | \title{shinydetails}
8 | \description{
9 | Useful Shiny stuff.
10 | }
11 |
--------------------------------------------------------------------------------
/shinydetails.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageRoxygenize: rd,collate,namespace,vignette
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://github.com/hadexversum/shinyKrysia/actions)
3 |
4 | ## shinydetails: useful components for Shiny apps
5 |
6 | This package implements a module containing a tabset that is composed of dwo panels with plot and table.
7 |
8 | Development version can be downloaded from Github:
9 |
10 | ```
11 | if (!require(devtools)) {
12 | install.packages('devtools')
13 | }
14 | devtools::install_github("BioGenies/shinydetails")
15 | ```
16 |
--------------------------------------------------------------------------------
/man/dt_format.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/plot_panel.R
3 | \name{dt_format}
4 | \alias{dt_format}
5 | \title{Table widget}
6 | \usage{
7 | dt_format(dat, colnames = colnames(dat))
8 | }
9 | \arguments{
10 | \item{dat}{a data object - a matrix or a data frame.}
11 |
12 | \item{colnames}{Names of columns to display in the table. By default it is
13 | equal to the names of the columns from the \code{dat}. Parameter \code{colnames} is
14 | correspond the argument \code{colnames} from \code{\link[DT]{datatable}}.}
15 | }
16 | \description{
17 | \code{dt_format} is a function for creating a graphical
18 | widget containing a table with download buttons (Excel and CSV).
19 | }
20 | \details{
21 | This function uses \code{\link[DT]{datatable}}.
22 | }
23 |
--------------------------------------------------------------------------------
/R/download_button.R:
--------------------------------------------------------------------------------
1 | #' @title Download button for plot
2 | #' @description Generates download button for a plot with dimensions of 300x400mm.
3 | #' @param id Unique id of download button.
4 | #' @param plot_out Plot to save.
5 | #' @inheritParams ggplot2::ggsave
6 | #' @return \code{generate_downloadButton} returns the output of \code{downloadHandler}
7 | #' for given plot and device.
8 | #' @details This function uses \code{\link[shiny]{downloadHandler}} and \code{\link[ggplot2]{ggsave}}.
9 | #' @export
10 | #' @importFrom ggplot2 ggsave
11 |
12 | beam_downloadButton <- function(id, plot_out, device) {
13 | downloadHandler(filename = paste0(id, "_plot.", device),
14 | content = function(file){
15 | ggsave(file, plot_out, device = device, height = 300,
16 | width = 400, units = "mm")})
17 | }
18 |
--------------------------------------------------------------------------------
/inst/tiny_demo/ui.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 |
3 | shinyUI(fluidPage(mainPanel(
4 | tabsetPanel(tabPanel(title = "geom_segment",
5 | column(width = 3),
6 | column(width = 9,
7 | tabsetPanel_UI("geom_segment"))),
8 | tabPanel("geom_segment",
9 | column(width = 3),
10 | column(width = 9,
11 | tabsetPanel_UI("geom_segment2"))),
12 | tabPanel("geom_point",
13 | column(width = 3),
14 | column(width = 9,
15 | tabsetPanel_UI("geom_point"))),
16 | tabPanel("geom_col",
17 | column(width = 3),
18 | column(width = 9,
19 | tabsetPanel_UI("geom_col")))
20 | )
21 | )))
22 |
--------------------------------------------------------------------------------
/man/beam_downloadButton.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/download_button.R
3 | \name{beam_downloadButton}
4 | \alias{beam_downloadButton}
5 | \title{Download button for plot}
6 | \usage{
7 | beam_downloadButton(id, plot_out, device)
8 | }
9 | \arguments{
10 | \item{id}{Unique id of download button.}
11 |
12 | \item{plot_out}{Plot to save.}
13 |
14 | \item{device}{Device to use. Can either be a device function
15 | (e.g. \code{\link[=png]{png()}}), or one of "eps", "ps", "tex" (pictex),
16 | "pdf", "jpeg", "tiff", "png", "bmp", "svg" or "wmf" (windows only).}
17 | }
18 | \value{
19 | \code{generate_downloadButton} returns the output of \code{downloadHandler}
20 | for given plot and device.
21 | }
22 | \description{
23 | Generates download button for a plot with dimensions of 300x400mm.
24 | }
25 | \details{
26 | This function uses \code{\link[shiny]{downloadHandler}} and \code{\link[ggplot2]{ggsave}}.
27 | }
28 |
--------------------------------------------------------------------------------
/man/create_help_files_custom.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/custom_help_files.R
3 | \name{create_help_files_custom}
4 | \alias{create_help_files_custom}
5 | \title{Creating new help file}
6 | \usage{
7 | create_help_files_custom(
8 | files,
9 | help_dir = "helpfiles",
10 | content = "This helpfile is not finished yet."
11 | )
12 | }
13 | \arguments{
14 | \item{files}{A character vector of names to use in creating help files.}
15 |
16 | \item{help_dir}{A character string of the directory to use for help files.}
17 |
18 | \item{content}{A character string to display in the automatically created help file.}
19 | }
20 | \description{
21 | This function creates help file (unless it already exists) with
22 | custom content.
23 | }
24 | \details{
25 | This function is based on \code{\link[shinyhelper]{create_help_files}} a lot.
26 | The option for providing custom \code{content} is the only improvement.
27 | }
28 |
--------------------------------------------------------------------------------
/man/plotOutput_h.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/elements_h.R
3 | \name{plotOutput_h}
4 | \alias{plotOutput_h}
5 | \title{Plot output with helper}
6 | \usage{
7 | plotOutput_h(outputId, helpfiles = "helpfiles", ...)
8 | }
9 | \arguments{
10 | \item{outputId}{output variable to read the plot/image from.}
11 |
12 | \item{helpfiles}{A character string denoting directory to save empty help files.
13 | Default \code{'helpfiles'}.}
14 |
15 | \item{...}{Optional arguments for \code{plotOutput}.}
16 | }
17 | \description{
18 | Renders plot with helper within an application.
19 | Same as \code{helper(plotOutput(outputId, ...))}. Creates help file and/or
20 | directory if it does not exist.
21 | }
22 | \details{
23 | This function uses \code{\link[shinyhelper]{helper}}.
24 | }
25 | \seealso{
26 | For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
27 | \code{\link[shinydetails]{tableOutput_h}},
28 | \code{\link[shinydetails]{sliderInput_h}}
29 | }
30 |
--------------------------------------------------------------------------------
/man/tableOutput_h.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/elements_h.R
3 | \name{tableOutput_h}
4 | \alias{tableOutput_h}
5 | \title{Table output with helper.}
6 | \usage{
7 | tableOutput_h(outputId, helpfiles = "helpfiles", ...)
8 | }
9 | \arguments{
10 | \item{outputId}{output variable to read the table from}
11 |
12 | \item{helpfiles}{A character string denoting directory to save empty help files.
13 | Default \code{'helpfiles'}.}
14 |
15 | \item{...}{Optional arguments for \code{plotOutput}.}
16 | }
17 | \description{
18 | Renders table with helper within an application. Creates help file and/or
19 | directory if it does not exist.
20 | Same as \code{helper(dataTableOutput(outputId, ...))}
21 | }
22 | \details{
23 | This function uses \code{\link[shinyhelper]{helper}}.
24 | }
25 | \seealso{
26 | For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
27 | \code{\link[shinydetails]{plotOutput_h}}, \code{\link[shinydetails]{sliderInput_h}}
28 | }
29 |
--------------------------------------------------------------------------------
/man/sliderInput_h.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/elements_h.R
3 | \name{sliderInput_h}
4 | \alias{sliderInput_h}
5 | \title{Slider input with helper}
6 | \usage{
7 | sliderInput_h(inputId, helpfiles = "helpfiles", ...)
8 | }
9 | \arguments{
10 | \item{inputId}{The \code{input} slot that will be used to access the value.}
11 |
12 | \item{helpfiles}{A character string denoting directory to save empty help files.
13 | Default \code{'helpfiles'}.}
14 |
15 | \item{...}{Optional arguments for \code{sliderInput}.}
16 | }
17 | \description{
18 | Constructs a slider widget with helper.
19 | Same as \code{helper(sliderInput(outputId, ...))}. Creates help file and/or
20 | directory if it does not exist.
21 | }
22 | \details{
23 | This function uses \code{\link[shinyhelper]{helper}}.
24 | }
25 | \seealso{
26 | For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
27 | \code{\link[shinydetails]{plotOutput_h}}, \code{\link[shinydetails]{tableOutput_h}}
28 | }
29 |
--------------------------------------------------------------------------------
/man/numericInput_h.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/elements_h.R
3 | \name{numericInput_h}
4 | \alias{numericInput_h}
5 | \title{Numeric input with helper.}
6 | \usage{
7 | numericInput_h(inputId, helpfiles = "helpfiles", ...)
8 | }
9 | \arguments{
10 | \item{inputId}{The \code{input} slot that will be used to access the value.}
11 |
12 | \item{helpfiles}{A character string denoting directory to save empty help files.
13 | Default \code{'helpfiles'}.}
14 |
15 | \item{...}{Optional arguments for \code{numericInput}.}
16 | }
17 | \description{
18 | Constructs a numeric input with helper.
19 | Same as \code{helper(numericInput(outputId, ...))}. Creates help file and/or
20 | directory if it does not exist.
21 | }
22 | \details{
23 | This function uses \code{\link[shinyhelper]{helper}}.
24 | }
25 | \seealso{
26 | For more elements with helpers see \code{\link[shinydetails]{plotOutput_h}},
27 | \code{\link[shinydetails]{tableOutput_h}}, \code{\link[shinydetails]{sliderInput_h}}
28 | }
29 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: shinydetails
2 | Type: Package
3 | Title: A collection of useful components for Shiny apps
4 | Version: 0.1.0
5 | Authors@R: c(person("Krystyna", "Grzesiak",
6 | email = "krygrz11@gmail.com",
7 | comment = c(ORCID = "0000-0003-2581-7722"),
8 | role = c("cre", "aut")),
9 | person("Weronika", "Puchala",
10 | email = "puchala.weronika@gmail.com",
11 | comment = c(ORCID = "0000-0003-2163-1429"),
12 | role = c("aut")),
13 | person("Michal", "Burdukiewicz",
14 | email = "michalburdukiewicz@gmail.com",
15 | comment = c(ORCID = "0000-0001-8926-582X"),
16 | role = c("aut")))
17 | Description: More about what it does (maybe more than one line)
18 | Use four spaces when indenting paragraphs within the Description.
19 | License: GPL-3
20 | Imports:
21 | DT,
22 | ggplot2,
23 | shiny,
24 | shinyhelper
25 | Encoding: UTF-8
26 | LazyData: true
27 | RoxygenNote: 7.1.1
28 | Suggests:
29 | testthat,
30 | spelling
31 | Language: en-US
32 |
--------------------------------------------------------------------------------
/R/shinydetails-package.R:
--------------------------------------------------------------------------------
1 | #' shinydetails
2 | #'
3 | #' @description Useful Shiny stuff.
4 | #' @docType package
5 | #' @name shinydetails-package
6 | #' @aliases shinydetails
7 | #' @importFrom ggplot2 ggplot_build
8 | #' @importFrom ggplot2 ggsave
9 | #' @importFrom shiny tabsetPanel
10 | #' @importFrom shiny reactive
11 | #' @importFrom shiny tabPanel
12 | #' @importFrom shiny tagList
13 | #' @importFrom shiny downloadButton
14 | #' @importFrom shiny moduleServer
15 | #' @importFrom shiny plotOutput
16 | #' @importFrom shiny downloadHandler
17 | #' @importFrom shiny sliderInput
18 | #' @importFrom shiny numericInput
19 | #' @importFrom shiny dataTableOutput
20 | #' @importFrom shiny nearPoints
21 | #' @importFrom shiny div
22 | #' @importFrom shiny HTML
23 | #' @importFrom shiny p
24 | #' @importFrom shiny uiOutput
25 | #' @importFrom shiny hoverOpts
26 | #' @importFrom shiny NS
27 | #' @importFrom shiny renderPlot
28 | #' @importFrom shiny renderUI
29 | #' @importFrom shiny br
30 | #' @importFrom shinyhelper helper
31 | #' @importFrom shinyhelper observe_helpers
32 | #' @importFrom shinyhelper create_help_files
33 | #' @importFrom DT datatable
34 | #'
35 | NULL
36 |
--------------------------------------------------------------------------------
/tests/testthat/test-create_tooltip.R:
--------------------------------------------------------------------------------
1 | test_that("right row from data is selected by extract_tt_data_row", {
2 |
3 | library(ggplot2)
4 | data <- data.frame(x = c(1,2,5,6,8),
5 | y = c(3,6,2,8,7),
6 | vx = c(1,1.5,0.8,0.5,1.3),
7 | vy = c(0.2,1.3,1.7,0.8,1.4))
8 | plot <- ggplot() +
9 | geom_segment(data = data,
10 | mapping = aes(x = x, y = y, xend = x + vx, yend = y + vy),
11 | size = 2, color = "blue")
12 |
13 | plot_data <- ggplot_build(plot)[["data"]][[1]]
14 | plot_type = "geom_segment"
15 | tt_range = 1
16 |
17 | hv <- list()
18 | hv[["x"]] <- 5
19 | hv[["y"]] <- 3
20 | result1 <- extract_tt_data_row(hv, plot_data, data, plot_type = plot_type, tt_range = tt_range)
21 | expect_equal(result1, data[3, ])
22 |
23 | hv[["x"]] <- 8
24 | hv[["y"]] <- 2
25 | result2 <- extract_tt_data_row(hv, plot_data, data, plot_type = plot_type, tt_range = tt_range)
26 | expect_equal(nrow(result2), 0)
27 |
28 | hv[["x"]] <- 8
29 | hv[["y"]] <- 7
30 | result3 <- extract_tt_data_row(hv, plot_data, data, plot_type = plot_type, tt_range = tt_range)
31 | expect_equal(result3, data[5, ])
32 | })
33 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(beam_downloadButton)
4 | export(beam_plot_panel_SERVER)
5 | export(beam_plot_panel_UI)
6 | export(beam_tooltip)
7 | export(extract_tt_data_row)
8 | export(flip_ggplot_build)
9 | export(numericInput_h)
10 | export(plotOutput_h)
11 | export(run_tiny_demo)
12 | export(sliderInput_h)
13 | export(tableOutput_h)
14 | importFrom(DT,datatable)
15 | importFrom(DT,renderDataTable)
16 | importFrom(ggplot2,ggplot_build)
17 | importFrom(ggplot2,ggsave)
18 | importFrom(shiny,HTML)
19 | importFrom(shiny,NS)
20 | importFrom(shiny,br)
21 | importFrom(shiny,dataTableOutput)
22 | importFrom(shiny,div)
23 | importFrom(shiny,downloadButton)
24 | importFrom(shiny,downloadHandler)
25 | importFrom(shiny,hoverOpts)
26 | importFrom(shiny,moduleServer)
27 | importFrom(shiny,nearPoints)
28 | importFrom(shiny,numericInput)
29 | importFrom(shiny,p)
30 | importFrom(shiny,plotOutput)
31 | importFrom(shiny,reactive)
32 | importFrom(shiny,renderPlot)
33 | importFrom(shiny,renderUI)
34 | importFrom(shiny,runApp)
35 | importFrom(shiny,sliderInput)
36 | importFrom(shiny,tabPanel)
37 | importFrom(shiny,tabsetPanel)
38 | importFrom(shiny,tagList)
39 | importFrom(shiny,uiOutput)
40 | importFrom(shinyhelper,create_help_files)
41 | importFrom(shinyhelper,helper)
42 | importFrom(shinyhelper,observe_helpers)
43 |
--------------------------------------------------------------------------------
/man/extract_tt_data_row.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tooltip.R
3 | \name{extract_tt_data_row}
4 | \alias{extract_tt_data_row}
5 | \title{Tooltip data}
6 | \usage{
7 | extract_tt_data_row(
8 | hv,
9 | plot_info,
10 | plot_data,
11 | plot_type = "geom_point",
12 | tt_range = 5
13 | )
14 | }
15 | \arguments{
16 | \item{hv}{Hoover.}
17 |
18 | \item{plot_info}{chosen mapping from the \code{data} object from the output of \code{\link[ggplot2]{ggplot_build}} for displayed plot.}
19 |
20 | \item{plot_data}{data on which the ggplot is based}
21 |
22 | \item{plot_type}{Type of plot corresponding to the data from first mapping.
23 | Accepts either \code{'geom_point'}, \code{'geom_segment'}
24 | or \code{'geom_col'}. Default \code{'geom_point'}.}
25 |
26 | \item{tt_range}{A number denoting maximum distance between hoover and objects on the plot.
27 | The row, whose distance to the hoover is less than \code{tt_range} will be selected from the whole data. Default 5.}
28 | }
29 | \value{
30 | \code{prepare_tt_data} returns prepared data frame containing one record.
31 | }
32 | \description{
33 | Prepares data in order that it may be displayed in tooltip.
34 | The row from the data which fits to the hover the most will be selected.
35 | }
36 | \details{
37 | This function filters one row of the imputed data in order that it
38 | corresponds the most to the hoover coordinates.
39 | }
40 |
--------------------------------------------------------------------------------
/R/custom_help_files.R:
--------------------------------------------------------------------------------
1 |
2 | #' @title Creating new help file
3 | #' @description This function creates help file (unless it already exists) with
4 | #' custom content.
5 | #' @inheritParams shinyhelper::create_help_files
6 | #' @param content A character string to display in the automatically created help file.
7 | #' @details This function is based on \code{\link[shinyhelper]{create_help_files}} a lot.
8 | #' The option for providing custom \code{content} is the only improvement.
9 | #'
10 | #'
11 |
12 | create_help_files_custom <- function (files,
13 | help_dir = "helpfiles",
14 | content = "This helpfile is not finished yet.")
15 | {
16 | if (!interactive()) {
17 | message("Must be called from an interactive session")
18 | return(invisible(files))
19 | }
20 | if (!dir.exists(help_dir)) {
21 | message("* Creating directory `", help_dir, "`.")
22 | dir.create(help_dir)
23 | }
24 | files <- file.path(help_dir, paste0(files, ".md"))
25 | new_file <- function(file) {
26 | if (!file.exists(file)) {
27 | file.create(file)
28 | writeLines(text = c(paste("###", file, "- Under Development\n"),
29 | "***\n\n", content, "\n"),
30 | con = file)
31 | }
32 | else {
33 | message("* `", file, "` already exists - not overwriting")
34 | }
35 | }
36 | lapply(files, new_file)
37 | return(invisible(files))
38 | }
39 |
--------------------------------------------------------------------------------
/man/flip_ggplot_build.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/plot_panel.R
3 | \name{flip_ggplot_build}
4 | \alias{flip_ggplot_build}
5 | \title{Ggplot_build for flipped plots}
6 | \usage{
7 | flip_ggplot_build(ggplot_build_data)
8 | }
9 | \arguments{
10 | \item{ggplot_build_data}{output of \code{\link[ggplot2]{ggplot_build}}}
11 | }
12 | \description{
13 | \code{flip_ggplot_build} is a supplementary function for ggplot_build.
14 | Changes ggplot_build output in order to make it compatible with the
15 | plot when coordinates are flipped.
16 | }
17 | \details{
18 | \code{data} from the output of \code{\link[ggplot2]{ggplot_build}} has
19 | names of columns compatible with the mapping. In case when coordinates are flipped,
20 | it is not consistent with the displayed plot. \code{flip_ggplot_build} changes
21 | the names so that coordinates from the output of \code{\link[ggplot2]{ggplot_build}}
22 | are compatible with the plot and returns it. In case when coordinates are not flipped
23 | \code{flip_ggplot_build} returns \code{ggplot_build_data}.
24 | }
25 | \examples{
26 | \dontrun{
27 |
28 | # returns plot info without any change because coordinates are not flipped
29 | p <- ggplot(Orange, aes(x = age, y = circumference, col = Tree)) +
30 | geom_point() +
31 | geom_line()
32 | plot_info <- ggplot_build(p)
33 | flip_ggplot_build(plot_info) # it is the same as plot_info
34 |
35 | # returns plot info with data modified for flipped coordinates
36 | p <- ggplot(Orange, aes(x = age, y = circumference, col = Tree)) +
37 | geom_point() +
38 | geom_line() +
39 | coord_flip()
40 | plot_info <- ggplot_build(p)
41 | flip_ggplot_build(plot_info)
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/man/beam_tooltip.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tooltip.R
3 | \name{beam_tooltip}
4 | \alias{beam_tooltip}
5 | \title{Generate tooltip}
6 | \usage{
7 | beam_tooltip(hv, plot_info, plot_data, plot_type, tt_content, tt_range = 5)
8 | }
9 | \arguments{
10 | \item{hv}{Hoover.}
11 |
12 | \item{plot_info}{chosen mapping from the \code{data} object from the output of \code{\link[ggplot2]{ggplot_build}} for displayed plot.}
13 |
14 | \item{plot_data}{data on which the ggplot is based}
15 |
16 | \item{plot_type}{Type of plot corresponding to the data from first mapping.
17 | Accepts either \code{'geom_point'}, \code{'geom_segment'}
18 | or \code{'geom_col'}. Default \code{'geom_point'}.}
19 |
20 | \item{tt_content}{Optional. If \code{NULL} in the tooltip will be displayed names of
21 | columns with corresponding values from data. One can customize tooltip content
22 | adding parameter \code{tt_content} here. It should be a list of \code{chosen_cols}
23 | and \code{row_text}. To display some values from the data in the content one
24 | should reference to the relevant column from the \code{chosen_cols} and in
25 | \code{row_text} write appropriate type of that variable like in the function
26 | \code{\link[base]{sprintf}} (for example \code{'\%s'} in case when chosen variable
27 | is a character string).}
28 |
29 | \item{tt_range}{A number denoting maximum distance between hoover and objects on the plot.
30 | The row, whose distance to the hoover is less than \code{tt_range} will be selected from the whole data. Default 5.}
31 | }
32 | \description{
33 | Generates tooltip for plot.
34 | }
35 | \details{
36 | This function uses \code{\link[shinydetails]{extract_tt_data_row}}.
37 | }
38 |
--------------------------------------------------------------------------------
/inst/example_app/example_app.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | library(ggplot2)
3 |
4 | ui <- fluidPage(title = "Example app",
5 | beam_plot_panel_UI("airquality_basic"),
6 | beam_plot_panel_UI("airquality_advanced",
7 | tab_plot = "An advanced plot",
8 | tab_table = "An elegant table for an advanced plot",
9 | helpfiles = "custom_helpfiles")
10 | )
11 |
12 | server <- function(input, output, session) {
13 |
14 | airquality_basic_plot <- reactive({
15 | ggplot(airquality, aes(x = Wind, y = Temp, col = as.character(Month))) +
16 | geom_point()
17 | })
18 |
19 | airquality_basic_data <- reactive({
20 | airquality
21 | })
22 |
23 | beam_plot_panel_SERVER("airquality_basic",
24 | plot_out = airquality_basic_plot(),
25 | table_out = airquality_basic_data())
26 |
27 | airquality_advanced_data <- reactive({
28 |
29 | df <- data.frame(aggregate(. ~ Month, airquality, function(x) c(mean = mean(x), sd = sd(x)))[, c(1, 5)])
30 | df[["Month"]] <- month.name[df[["Month"]]]
31 | data.frame(Month = df[["Month"]],
32 | Temp_mean = df$Temp[, 1],
33 | Error = df$Temp[, 2],
34 | Year = 1973)
35 | })
36 |
37 |
38 | airquality_advanced_plot <- reactive({
39 | ggplot(airquality_advanced_data(), aes(y = 0, yend = Temp_mean, x = Month, xend = Month)) +
40 | geom_segment() +
41 | geom_point(mapping = aes(x = Month, y = Temp_mean), size = 3) +
42 | geom_point() +
43 | ylab("average temperature")
44 | })
45 |
46 | beam_plot_panel_SERVER("airquality_advanced",
47 | plot_out = airquality_advanced_plot(),
48 | table_out = airquality_advanced_data(),
49 | plot_type = "geom_segment",
50 | tt_content = list(row_text = c("Date: %s %i",
51 | "Average temperature: %f °F",
52 | "Error: %f",
53 | "Place: La Guardia Airport"),
54 | chosen_cols = c("Month", "Year", "Temp_mean", "Error")))
55 |
56 |
57 |
58 | }
59 |
60 |
61 | shinyApp(ui, server)
62 |
63 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - master
8 | pull_request:
9 | branches:
10 | - main
11 | - master
12 |
13 | name: R-CMD-check
14 |
15 | jobs:
16 | R-CMD-check:
17 | runs-on: ${{ matrix.config.os }}
18 |
19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
20 |
21 | strategy:
22 | fail-fast: false
23 | matrix:
24 | config:
25 | - {os: windows-latest, r: 'release'}
26 | - {os: macOS-latest, r: 'release'}
27 | - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
28 | - {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
29 |
30 | env:
31 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
32 | RSPM: ${{ matrix.config.rspm }}
33 |
34 | steps:
35 | - uses: actions/checkout@v2
36 |
37 | - uses: r-lib/actions/setup-r@v1
38 | with:
39 | r-version: ${{ matrix.config.r }}
40 |
41 | - uses: r-lib/actions/setup-pandoc@v1
42 |
43 | - name: Query dependencies
44 | run: |
45 | install.packages('remotes')
46 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
47 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
48 | shell: Rscript {0}
49 |
50 | - name: Cache R packages
51 | if: runner.os != 'Windows'
52 | uses: actions/cache@v2
53 | with:
54 | path: ${{ env.R_LIBS_USER }}
55 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
56 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
57 |
58 | - name: Install system dependencies
59 | if: runner.os == 'Linux'
60 | run: |
61 | while read -r cmd
62 | do
63 | eval sudo $cmd
64 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))')
65 |
66 | - name: Install dependencies
67 | run: |
68 | remotes::install_deps(dependencies = TRUE)
69 | remotes::install_cran("rcmdcheck")
70 | shell: Rscript {0}
71 |
72 | - name: Check
73 | env:
74 | _R_CHECK_CRAN_INCOMING_REMOTE_: false
75 | run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
76 | shell: Rscript {0}
77 |
78 | - name: Upload check results
79 | if: failure()
80 | uses: actions/upload-artifact@main
81 | with:
82 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results
83 | path: check
84 |
--------------------------------------------------------------------------------
/inst/tiny_demo/server.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | library(shinyhelper)
3 | library(ggplot2)
4 |
5 | server <- shinyServer(function(input, output) {
6 |
7 | observe_helpers(session = getDefaultReactiveDomain(), help_dir = "helpfiles")
8 |
9 | #geom_segment
10 | geom_segment_data <- reactive({
11 | data.frame(mtcars,
12 | car = rownames(mtcars))
13 | })
14 |
15 | geom_segment_plot_out <- reactive({
16 | ggplot(geom_segment_data(), mapping = aes(y = 0,
17 | x = car,
18 | yend = mpg,
19 | xend = car)) +
20 | geom_segment(color = "black") +
21 | geom_point(stat ='identity', fill="black") +
22 | coord_flip()
23 | })
24 |
25 | tabsetPanel_SERVER(id = "geom_segment",
26 | plot_out = geom_segment_plot_out,
27 | table_out = geom_segment_data,
28 | plot_type = "geom_segment",
29 | tt_content = list(row_text = c("Mpg: %f", "Car: %s"),
30 | chosen_cols = c("mpg", "car")))
31 |
32 | #geom_segment
33 | geom_segment_data2 <- reactive({
34 | data.frame(x = c(1,2,5,6,8),
35 | y = c(3,6,2,8,7),
36 | vx = c(1,1.5,0.8,0.5,1.3),
37 | vy = c(0.2,1.3,1.7,0.8,1.4))
38 | })
39 |
40 | geom_segment_plot_out2 <- reactive({
41 | ggplot() +
42 | geom_segment(data = geom_segment_data2(),
43 | mapping = aes(x = x, y = y, xend = x + vx, yend = y + vy),
44 | size = 2, color = "blue")
45 | })
46 |
47 | tabsetPanel_SERVER(id = "geom_segment2",
48 | plot_out = geom_segment_plot_out2,
49 | table_out = geom_segment_data2,
50 | plot_type = "geom_segment",
51 | tt_range = 10)
52 |
53 | #geom_point
54 |
55 | geom_point_data <- reactive({
56 | iris
57 | })
58 |
59 | geom_point_plot <- reactive({
60 | ggplot(geom_point_data(),
61 | aes(x = Sepal.Length, y = Sepal.Width, col = Species)) +
62 | geom_point()
63 | })
64 |
65 | tabsetPanel_SERVER(id = "geom_point",
66 | plot_out = geom_point_plot,
67 | table_out = geom_point_data,
68 | plot_type = "geom_point",
69 | tt_range = 10)
70 |
71 | #geom_bar
72 |
73 | geom_bar_data <- reactive({
74 | data.frame(Sepal.Length = table(cut(iris[["Sepal.Length"]], seq(4, 8, length.out = 10))))
75 | })
76 |
77 | geom_bar_plot <- reactive({
78 | ggplot(geom_bar_data(),
79 | aes(x = Sepal.Length.Var1, y = Sepal.Length.Freq)) +
80 | geom_col()
81 | })
82 |
83 | tabsetPanel_SERVER(id = "geom_col",
84 | plot_out = geom_bar_plot,
85 | table_out = geom_bar_data,
86 | plot_type = "geom_col",
87 | tt_range = 10)
88 |
89 |
90 |
91 | })
92 |
--------------------------------------------------------------------------------
/man/beam_plot_panel_UI.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/plot_panel.R
3 | \name{beam_plot_panel_UI}
4 | \alias{beam_plot_panel_UI}
5 | \title{Creating UI for a Shiny module with plot and data}
6 | \usage{
7 | beam_plot_panel_UI(
8 | id,
9 | tab_plot = paste(id, "plot"),
10 | tab_table = paste(id, "data"),
11 | helpfiles = "helpfiles"
12 | )
13 | }
14 | \arguments{
15 | \item{id}{unique ID name of tabset. The same ID as in the corresponding server for
16 | a module}
17 |
18 | \item{tab_plot}{Character. Title of tab containing plot. Default to
19 | \code{paste(id, "plot")}.}
20 |
21 | \item{tab_table}{Character. Title of tab containing table. Default to
22 | \code{paste(id, "data")}.}
23 |
24 | \item{helpfiles}{A character string denoting directory to save empty help files.
25 | Default \code{'helpfiles'}.}
26 | }
27 | \description{
28 | Creates module's UI for tabset panel containing two tabs - with
29 | plot and an elegant table with data.
30 | }
31 | \details{
32 | Module's UI involves a panel with two tabs. The first tab consists of
33 | displayed plot and three download buttons (png, svg and jpeg). There is also a
34 | compatible with the plot tooltip. The second tab consists of a table
35 | with two download buttons (Excel and CSV). For both table and plot there are
36 | provided helpers. \
37 | For more information see \code{\link[shinydetails]{plotOutput_h}} and
38 | \code{\link[shinydetails]{tableOutput_h}}
39 | }
40 | \examples{
41 | \dontrun{
42 | ui <- fluidPage(title = "Example app",
43 | beam_plot_panel_UI("airquality_basic"),
44 | beam_plot_panel_UI("airquality_advanced",
45 | tab_plot = "An advanced plot",
46 | tab_table = "An elegant table for an advanced plot",
47 | helpfiles = "custom_helpfiles"))
48 |
49 | server <- function(input, output, session) {
50 | airquality_basic_plot <- reactive({
51 | ggplot(airquality, aes(x = Wind, y = Temp, col = as.character(Month))) +
52 | geom_point()
53 | })
54 | airquality_basic_data <- reactive({
55 | airquality
56 | })
57 | beam_plot_panel_SERVER("airquality_basic",
58 | plot_out = airquality_basic_plot(),
59 | table_out = airquality_basic_data())
60 |
61 | airquality_advanced_data <- reactive({
62 | df <- data.frame(aggregate(. ~ Month, airquality, function(x) c(mean = mean(x), sd = sd(x)))[, c(1, 5)])
63 | df[["Month"]] <- month.name[df[["Month"]]]
64 | data.frame(Month = df[["Month"]],
65 | Temp_mean = df$Temp[, 1],
66 | Error = df$Temp[, 2],
67 | Year = 1973)})
68 |
69 | airquality_advanced_plot <- reactive({
70 | ggplot(airquality_advanced_data(), aes(y = 0, yend = Temp_mean, x = Month, xend = Month)) +
71 | geom_segment() +
72 | geom_point(mapping = aes(x = Month, y = Temp_mean), size = 3) +
73 | geom_point() +
74 | ylab("average temperature")
75 | })
76 | beam_plot_panel_SERVER("airquality_advanced",
77 | plot_out = airquality_advanced_plot(),
78 | table_out = airquality_advanced_data(),
79 | plot_type = "geom_segment",
80 | tt_content = list(row_text = c("Date: \%s \%i",
81 | "Average temperature: \%f °F",
82 | "Error: \%f",
83 | "Place: La Guardia Airport"),
84 | chosen_cols = c("Month",
85 | "Year",
86 | "Temp_mean",
87 | "Error"))
88 | )
89 |
90 | }
91 | }
92 | }
93 | \seealso{
94 | To build Shiny module within a Shiny app using \code{beam_plot_panel_UI}
95 | see \code{\link[shinydetails]{beam_plot_panel_SERVER}}.
96 | }
97 |
--------------------------------------------------------------------------------
/R/elements_h.R:
--------------------------------------------------------------------------------
1 |
2 | #' @title Slider input with helper
3 | #' @description Constructs a slider widget with helper.
4 | #' Same as \code{helper(sliderInput(outputId, ...))}. Creates help file and/or
5 | #' directory if it does not exist.
6 | #' @inheritParams shiny::sliderInput
7 | #' @inheritParams plotOutput_h
8 | #' @param ... Optional arguments for \code{sliderInput}.
9 | #' @details This function uses \code{\link[shinyhelper]{helper}}.
10 | #' @seealso For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
11 | #' \code{\link[shinydetails]{plotOutput_h}}, \code{\link[shinydetails]{tableOutput_h}}
12 | #' @export
13 | #'
14 |
15 | sliderInput_h <- function(inputId, helpfiles = "helpfiles", ...) {
16 | suppressMessages({create_help_files_custom(files = inputId,
17 | help_dir = helpfiles)})
18 | helper(sliderInput(inputId, ...),
19 | content = inputId,
20 | type = "markdown")
21 | }
22 |
23 | #' @title Numeric input with helper.
24 | #' @description Constructs a numeric input with helper.
25 | #' Same as \code{helper(numericInput(outputId, ...))}. Creates help file and/or
26 | #' directory if it does not exist.
27 | #' @inheritParams shiny::numericInput
28 | #' @inheritParams plotOutput_h
29 | #' @param ... Optional arguments for \code{numericInput}.
30 | #' @details This function uses \code{\link[shinyhelper]{helper}}.
31 | #' @seealso For more elements with helpers see \code{\link[shinydetails]{plotOutput_h}},
32 | #' \code{\link[shinydetails]{tableOutput_h}}, \code{\link[shinydetails]{sliderInput_h}}
33 | #' @export
34 | #'
35 |
36 | numericInput_h <- function(inputId, helpfiles = "helpfiles", ...) {
37 | suppressMessages({create_help_files_custom(files = inputId,
38 | help_dir = helpfiles)})
39 | helper(numericInput(inputId, ...),
40 | content = inputId,
41 | type = "markdown")
42 | }
43 |
44 |
45 | #' @title Plot output with helper
46 | #' @description Renders plot with helper within an application.
47 | #' Same as \code{helper(plotOutput(outputId, ...))}. Creates help file and/or
48 | #' directory if it does not exist.
49 | #' @inheritParams shiny::plotOutput
50 | #' @param helpfiles A character string denoting directory to save empty help files.
51 | #' Default \code{'helpfiles'}.
52 | #' @param ... Optional arguments for \code{plotOutput}.
53 | #' @details This function uses \code{\link[shinyhelper]{helper}}.
54 | #' @seealso For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
55 | #' \code{\link[shinydetails]{tableOutput_h}},
56 | #' \code{\link[shinydetails]{sliderInput_h}}
57 | #' @export
58 | #'
59 |
60 | plotOutput_h <- function(outputId, helpfiles = "helpfiles", ...) {
61 | suppressMessages({create_help_files_custom(files = outputId,
62 | help_dir = "helpfiles",
63 | content = "This help file was generated automatically.")})
64 | helper(plotOutput(outputId, ...),
65 | content = outputId,
66 | type = "markdown")
67 | }
68 |
69 |
70 | #' @title Table output with helper.
71 | #' @description Renders table with helper within an application. Creates help file and/or
72 | #' directory if it does not exist.
73 | #' Same as \code{helper(dataTableOutput(outputId, ...))}
74 | #' @inheritParams shiny::dataTableOutput
75 | #' @inheritParams plotOutput_h
76 | #' @details This function uses \code{\link[shinyhelper]{helper}}.
77 | #' @seealso For more elements with helpers see \code{\link[shinydetails]{numericInput_h}},
78 | #' \code{\link[shinydetails]{plotOutput_h}}, \code{\link[shinydetails]{sliderInput_h}}
79 | #' @export
80 | #'
81 |
82 |
83 | tableOutput_h <- function(outputId, helpfiles = "helpfiles", ...) {
84 | suppressMessages({create_help_files_custom(files = outputId,
85 | help_dir = "helpfiles",
86 | content = "This help file was generated automatically.")})
87 | helper(DT::dataTableOutput(outputId, ...),
88 | content = outputId,
89 | type = "markdown")
90 | }
91 |
92 |
--------------------------------------------------------------------------------
/R/tooltip.R:
--------------------------------------------------------------------------------
1 |
2 | #' @title Tooltip data
3 | #' @description Prepares data in order that it may be displayed in tooltip.
4 | #' The row from the data which fits to the hover the most will be selected.
5 | #' @param hv Hoover.
6 | #' @param plot_info chosen mapping from the \code{data} object from the output of \code{\link[ggplot2]{ggplot_build}} for displayed plot.
7 | #' @param plot_data data on which the ggplot is based
8 | #' @param plot_type Type of plot corresponding to the data from first mapping.
9 | #' Accepts either \code{'geom_point'}, \code{'geom_segment'}
10 | #' or \code{'geom_col'}. Default \code{'geom_point'}.
11 | #' @param tt_range A number denoting maximum distance between hoover and objects on the plot.
12 | #' The row, whose distance to the hoover is less than \code{tt_range} will be selected from the whole data. Default 5.
13 | #' @return \code{prepare_tt_data} returns prepared data frame containing one record.
14 | #' @details This function filters one row of the imputed data in order that it
15 | #' corresponds the most to the hoover coordinates.
16 | #' @export
17 |
18 |
19 | extract_tt_data_row <- function(hv, plot_info, plot_data, plot_type = "geom_point", tt_range = 5) {
20 |
21 | match.arg(plot_type, c("geom_col", "geom_point", "geom_segment"), several.ok = FALSE)
22 |
23 | switch(plot_type,
24 | geom_col = {
25 | hv_data <- data.frame(x = hv[["x"]],
26 | y = hv[["y"]],
27 | xmin = plot_info[["xmin"]],
28 | xmax = plot_info[["xmax"]],
29 | plot_data)
30 | tt_df <- hv_data[hv_data[["x"]] < hv_data[["xmax"]] &
31 | hv_data[["x"]] >= hv_data[["xmin"]],
32 | !(colnames(hv_data) %in% c("x", "y", "xmax", "xmin"))]
33 | },
34 | geom_point = {
35 | tt_df <- nearPoints(df = plot_data, coordinfo = hv, maxpoints = 1, threshold = tt_range)
36 | },
37 | geom_segment = {
38 | x_start <- plot_info[["x"]]
39 | x_end <- plot_info[["xend"]]
40 | y_start <- plot_info[["y"]]
41 | y_end <- plot_info[["yend"]]
42 | A <- y_start - y_end
43 | B <- x_end - x_start
44 | C <- y_end*(x_start - x_end) - x_end*(y_start - y_end)
45 |
46 | hv_data <- data.frame(dist = abs((hv[["x"]]*A + hv[["y"]]*B + C))/sqrt(A^2 + B^2),
47 | plot_data)
48 |
49 | tt_df <- hv_data[x_start - tt_range <= hv[["x"]] &
50 | x_end + tt_range >= hv[["x"]] &
51 | y_start - tt_range <= hv[["y"]] &
52 | y_end + tt_range >= hv[["y"]] &
53 | hv_data[["dist"]] <= tt_range &
54 | hv_data[["dist"]] == min(hv_data[["dist"]]),
55 | !(colnames(hv_data) %in% c("dist"))]
56 | }
57 | )
58 | tt_df
59 | }
60 |
61 |
62 | #' @title Generate tooltip
63 | #' @description Generates tooltip for plot.
64 | #' @inheritParams extract_tt_data_row
65 | #' @param tt_content Optional. If \code{NULL} in the tooltip will be displayed names of
66 | #' columns with corresponding values from data. One can customize tooltip content
67 | #' adding parameter \code{tt_content} here. It should be a list of \code{chosen_cols}
68 | #' and \code{row_text}. To display some values from the data in the content one
69 | #' should reference to the relevant column from the \code{chosen_cols} and in
70 | #' \code{row_text} write appropriate type of that variable like in the function
71 | #' \code{\link[base]{sprintf}} (for example \code{'\%s'} in case when chosen variable
72 | #' is a character string).
73 | #' @details This function uses \code{\link[shinydetails]{extract_tt_data_row}}.
74 | #' @export
75 | #'
76 |
77 | beam_tooltip <- function(hv, plot_info, plot_data, plot_type, tt_content, tt_range = 5) {
78 |
79 | tt_df <- extract_tt_data_row(hv, plot_info, plot_data, plot_type, tt_range)
80 |
81 | if(nrow(tt_df) != 0) {
82 | tt_pos_adj <- ifelse(hv[["coords_img"]][["x"]]/hv[["range"]][["right"]] < 0.5,
83 | "left", "right")
84 |
85 | tt_pos <- ifelse(hv[["coords_img"]][["x"]]/hv[["range"]][["right"]] < 0.5,
86 | hv[["coords_css"]][["x"]],
87 | hv[["range"]][["right"]]/hv[["img_css_ratio"]][["x"]] - hv[["coords_css"]][["x"]])
88 |
89 | style <- paste0("position:absolute; z-index:1000; background-color: rgba(245, 245, 245, 1); pointer-events: none;",
90 | tt_pos_adj, ":", tt_pos,
91 | "px; top:", hv[["coords_css"]][["y"]], "px; padding: 0px;")
92 |
93 | if(is.null(tt_content)) {
94 | content <- paste(colnames(tt_df), ": ", t(tt_df ), c(rep("
", ncol(tt_df)-1), ""))
95 | }else {
96 | text <- paste(tt_content[["row_text"]],
97 | c(rep("
", length(tt_content[["row_text"]]) - 1), ""),
98 | sep = "", collapse = "")
99 | content <- do.call(sprintf, c(list(text), lapply(tt_content[["chosen_cols"]], function(i) tt_df[[i]])))
100 | }
101 |
102 | div(style = style,
103 | p(HTML(content))
104 | )
105 | }
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/man/beam_plot_panel_SERVER.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/plot_panel.R
3 | \name{beam_plot_panel_SERVER}
4 | \alias{beam_plot_panel_SERVER}
5 | \title{Creating server for a Shiny module with plot and data.}
6 | \usage{
7 | beam_plot_panel_SERVER(
8 | id,
9 | plot_out,
10 | table_out,
11 | plot_type = "geom_point",
12 | tt_content = NULL,
13 | tt_range = 5,
14 | helpfiles = "helpfiles"
15 | )
16 | }
17 | \arguments{
18 | \item{id}{unique Id of tabset panel. The same ID as in the corresponding UI for
19 | a module}
20 |
21 | \item{plot_out}{Plot to display in tab. There will be provided an automatically
22 | generated tooltip compatible with the plot. The items from first mapping will be
23 | connected with tooltip.}
24 |
25 | \item{table_out}{Table to display in tab.}
26 |
27 | \item{plot_type}{Type of plot corresponding to the data from first mapping.
28 | Accepts either \code{'geom_point'}, \code{'geom_segment'}
29 | or \code{'geom_col'}. Default \code{'geom_point'}.}
30 |
31 | \item{tt_content}{Optional. If \code{NULL} in the tooltip will be displayed names of
32 | columns with corresponding values from data. One can customize tooltip content
33 | adding parameter \code{tt_content} here. It should be a list of \code{chosen_cols}
34 | and \code{row_text}. To display some values from the data in the content one
35 | should reference to the relevant column from the \code{chosen_cols} and in
36 | \code{row_text} write appropriate type of that variable like in the function
37 | \code{\link[base]{sprintf}} (for example \code{'\%s'} in case when chosen variable
38 | is a character string).}
39 |
40 | \item{tt_range}{A number denoting maximum distance between hoover and objects on the plot.
41 | The row, whose distance to the hoover is less than \code{tt_range} will be selected from the whole data. Default 5.}
42 |
43 | \item{helpfiles}{A character string denoting directory to save empty help files.
44 | Default \code{'helpfiles'}.}
45 | }
46 | \description{
47 | Creates module server for tabset panel containing two tabs - with
48 | plot and an elegant table with data.
49 | }
50 | \details{
51 | Module's server involves a panel with two tabs. The first tab consists of
52 | displayed plot and three download buttons (png, svg and jpeg). There is also a
53 | compatible with plot tooltip obtained via \code{\link[shinydetails]{beam_tooltip}}.
54 | The second tab consists of a table with two download buttons (Excel and CSV).
55 | The table \code{table_out} before displaying is formatted using
56 | \code{\link[shinydetails]{dt_format}}. For both table and plot there are provided
57 | helpers.
58 | }
59 | \examples{
60 | \dontrun{
61 | ui <- fluidPage(title = "Example app",
62 | beam_plot_panel_UI("airquality_basic"),
63 | beam_plot_panel_UI("airquality_advanced",
64 | tab_plot = "An advanced plot",
65 | tab_table = "An elegant table for an advanced plot",
66 | helpfiles = "custom_helpfiles"))
67 |
68 | server <- function(input, output, session) {
69 | airquality_basic_plot <- reactive({
70 | ggplot(airquality, aes(x = Wind, y = Temp, col = as.character(Month))) +
71 | geom_point()
72 | })
73 | airquality_basic_data <- reactive({
74 | airquality
75 | })
76 | beam_plot_panel_SERVER("airquality_basic",
77 | plot_out = airquality_basic_plot(),
78 | table_out = airquality_basic_data())
79 |
80 | airquality_advanced_data <- reactive({
81 | df <- data.frame(aggregate(. ~ Month, airquality, function(x) c(mean = mean(x), sd = sd(x)))[, c(1, 5)])
82 | df[["Month"]] <- month.name[df[["Month"]]]
83 | data.frame(Month = df[["Month"]],
84 | Temp_mean = df$Temp[, 1],
85 | Error = df$Temp[, 2],
86 | Year = 1973)})
87 |
88 | airquality_advanced_plot <- reactive({
89 | ggplot(airquality_advanced_data(), aes(y = 0, yend = Temp_mean, x = Month, xend = Month)) +
90 | geom_segment() +
91 | geom_point(mapping = aes(x = Month, y = Temp_mean), size = 3) +
92 | geom_point() +
93 | ylab("average temperature")
94 | })
95 | beam_plot_panel_SERVER("airquality_advanced",
96 | plot_out = airquality_advanced_plot(),
97 | table_out = airquality_advanced_data(),
98 | plot_type = "geom_segment",
99 | tt_content = list(row_text = c("Date: \%s \%i",
100 | "Average temperature: \%f °F",
101 | "Error: \%f",
102 | "Place: La Guardia Airport"),
103 | chosen_cols = c("Month",
104 | "Year",
105 | "Temp_mean",
106 | "Error"))
107 | )
108 |
109 | }
110 | }
111 | }
112 | \seealso{
113 | To build Shiny module within a Shiny app using \code{beam_plot_panel_SERVER}
114 | see \code{\link[shinydetails]{beam_plot_panel_UI}}.
115 | }
116 |
--------------------------------------------------------------------------------
/renv/activate.R:
--------------------------------------------------------------------------------
1 |
2 | local({
3 |
4 | # the requested version of renv
5 | version <- "0.12.3"
6 |
7 | # the project directory
8 | project <- getwd()
9 |
10 | # avoid recursion
11 | if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA)))
12 | return(invisible(TRUE))
13 |
14 | # signal that we're loading renv during R startup
15 | Sys.setenv("RENV_R_INITIALIZING" = "true")
16 | on.exit(Sys.unsetenv("RENV_R_INITIALIZING"), add = TRUE)
17 |
18 | # signal that we've consented to use renv
19 | options(renv.consent = TRUE)
20 |
21 | # load the 'utils' package eagerly -- this ensures that renv shims, which
22 | # mask 'utils' packages, will come first on the search path
23 | library(utils, lib.loc = .Library)
24 |
25 | # check to see if renv has already been loaded
26 | if ("renv" %in% loadedNamespaces()) {
27 |
28 | # if renv has already been loaded, and it's the requested version of renv,
29 | # nothing to do
30 | spec <- .getNamespaceInfo(.getNamespace("renv"), "spec")
31 | if (identical(spec[["version"]], version))
32 | return(invisible(TRUE))
33 |
34 | # otherwise, unload and attempt to load the correct version of renv
35 | unloadNamespace("renv")
36 |
37 | }
38 |
39 | # load bootstrap tools
40 | bootstrap <- function(version, library) {
41 |
42 | # read repos (respecting override if set)
43 | repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA)
44 | if (is.na(repos))
45 | repos <- getOption("repos")
46 |
47 | # fix up repos
48 | on.exit(options(repos = repos), add = TRUE)
49 | repos[repos == "@CRAN@"] <- "https://cloud.r-project.org"
50 | options(repos = repos)
51 |
52 | # attempt to download renv
53 | tarball <- tryCatch(renv_bootstrap_download(version), error = identity)
54 | if (inherits(tarball, "error"))
55 | stop("failed to download renv ", version)
56 |
57 | # now attempt to install
58 | status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity)
59 | if (inherits(status, "error"))
60 | stop("failed to install renv ", version)
61 |
62 | }
63 |
64 | renv_bootstrap_download_impl <- function(url, destfile) {
65 |
66 | mode <- "wb"
67 |
68 | # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715
69 | fixup <-
70 | Sys.info()[["sysname"]] == "Windows" &&
71 | substring(url, 1L, 5L) == "file:"
72 |
73 | if (fixup)
74 | mode <- "w+b"
75 |
76 | download.file(
77 | url = url,
78 | destfile = destfile,
79 | mode = mode,
80 | quiet = TRUE
81 | )
82 |
83 | }
84 |
85 | renv_bootstrap_download <- function(version) {
86 |
87 | # if the renv version number has 4 components, assume it must
88 | # be retrieved via github
89 | nv <- numeric_version(version)
90 | components <- unclass(nv)[[1]]
91 |
92 | methods <- if (length(components) == 4L) {
93 | list(renv_bootstrap_download_github)
94 | } else {
95 | list(
96 | renv_bootstrap_download_cran_latest,
97 | renv_bootstrap_download_cran_archive
98 | )
99 | }
100 |
101 | for (method in methods) {
102 | path <- tryCatch(method(version), error = identity)
103 | if (is.character(path) && file.exists(path))
104 | return(path)
105 | }
106 |
107 | stop("failed to download renv ", version)
108 |
109 | }
110 |
111 | renv_bootstrap_download_cran_latest <- function(version) {
112 |
113 | repos <- renv_bootstrap_download_cran_latest_find(version)
114 |
115 | message("* Downloading renv ", version, " from CRAN ... ", appendLF = FALSE)
116 |
117 | info <- tryCatch(
118 | download.packages("renv", repos = repos, destdir = tempdir(), quiet = TRUE),
119 | condition = identity
120 | )
121 |
122 | if (inherits(info, "condition")) {
123 | message("FAILED")
124 | return(FALSE)
125 | }
126 |
127 | message("OK")
128 | info[1, 2]
129 |
130 | }
131 |
132 | renv_bootstrap_download_cran_latest_find <- function(version) {
133 |
134 | # check for renv on CRAN matching this version
135 | all <- unique(c(
136 | getOption("repos"),
137 | getOption("renv.bootstrap.repos", default = "https://cloud.r-project.org")
138 | ))
139 |
140 | for (repos in all) {
141 |
142 | db <- tryCatch(
143 | as.data.frame(available.packages(repos = repos), stringsAsFactors = FALSE),
144 | error = identity
145 | )
146 |
147 | if (inherits(db, "error"))
148 | next
149 |
150 | entry <- db[db$Package %in% "renv" & db$Version %in% version, ]
151 | if (nrow(entry) == 0)
152 | next
153 |
154 | return(repos)
155 |
156 | }
157 |
158 | fmt <- "renv %s is not available from your declared package repositories"
159 | stop(sprintf(fmt, version))
160 |
161 | }
162 |
163 | renv_bootstrap_download_cran_archive <- function(version) {
164 |
165 | name <- sprintf("renv_%s.tar.gz", version)
166 | repos <- getOption("repos")
167 | urls <- file.path(repos, "src/contrib/Archive/renv", name)
168 | destfile <- file.path(tempdir(), name)
169 |
170 | message("* Downloading renv ", version, " from CRAN archive ... ", appendLF = FALSE)
171 |
172 | for (url in urls) {
173 |
174 | status <- tryCatch(
175 | renv_bootstrap_download_impl(url, destfile),
176 | condition = identity
177 | )
178 |
179 | if (identical(status, 0L)) {
180 | message("OK")
181 | return(destfile)
182 | }
183 |
184 | }
185 |
186 | message("FAILED")
187 | return(FALSE)
188 |
189 | }
190 |
191 | renv_bootstrap_download_github <- function(version) {
192 |
193 | enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE")
194 | if (!identical(enabled, "TRUE"))
195 | return(FALSE)
196 |
197 | # prepare download options
198 | pat <- Sys.getenv("GITHUB_PAT")
199 | if (nzchar(Sys.which("curl")) && nzchar(pat)) {
200 | fmt <- "--location --fail --header \"Authorization: token %s\""
201 | extra <- sprintf(fmt, pat)
202 | saved <- options("download.file.method", "download.file.extra")
203 | options(download.file.method = "curl", download.file.extra = extra)
204 | on.exit(do.call(base::options, saved), add = TRUE)
205 | } else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
206 | fmt <- "--header=\"Authorization: token %s\""
207 | extra <- sprintf(fmt, pat)
208 | saved <- options("download.file.method", "download.file.extra")
209 | options(download.file.method = "wget", download.file.extra = extra)
210 | on.exit(do.call(base::options, saved), add = TRUE)
211 | }
212 |
213 | message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE)
214 |
215 | url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version)
216 | name <- sprintf("renv_%s.tar.gz", version)
217 | destfile <- file.path(tempdir(), name)
218 |
219 | status <- tryCatch(
220 | renv_bootstrap_download_impl(url, destfile),
221 | condition = identity
222 | )
223 |
224 | if (!identical(status, 0L)) {
225 | message("FAILED")
226 | return(FALSE)
227 | }
228 |
229 | message("Done!")
230 | return(destfile)
231 |
232 | }
233 |
234 | renv_bootstrap_install <- function(version, tarball, library) {
235 |
236 | # attempt to install it into project library
237 | message("* Installing renv ", version, " ... ", appendLF = FALSE)
238 | dir.create(library, showWarnings = FALSE, recursive = TRUE)
239 |
240 | # invoke using system2 so we can capture and report output
241 | bin <- R.home("bin")
242 | exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
243 | r <- file.path(bin, exe)
244 | args <- c("--vanilla", "CMD", "INSTALL", "-l", shQuote(library), shQuote(tarball))
245 | output <- system2(r, args, stdout = TRUE, stderr = TRUE)
246 | message("Done!")
247 |
248 | # check for successful install
249 | status <- attr(output, "status")
250 | if (is.numeric(status) && !identical(status, 0L)) {
251 | header <- "Error installing renv:"
252 | lines <- paste(rep.int("=", nchar(header)), collapse = "")
253 | text <- c(header, lines, output)
254 | writeLines(text, con = stderr())
255 | }
256 |
257 | status
258 |
259 | }
260 |
261 | renv_bootstrap_prefix <- function() {
262 |
263 | # construct version prefix
264 | version <- paste(R.version$major, R.version$minor, sep = ".")
265 | prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
266 |
267 | # include SVN revision for development versions of R
268 | # (to avoid sharing platform-specific artefacts with released versions of R)
269 | devel <-
270 | identical(R.version[["status"]], "Under development (unstable)") ||
271 | identical(R.version[["nickname"]], "Unsuffered Consequences")
272 |
273 | if (devel)
274 | prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
275 |
276 | # build list of path components
277 | components <- c(prefix, R.version$platform)
278 |
279 | # include prefix if provided by user
280 | prefix <- Sys.getenv("RENV_PATHS_PREFIX")
281 | if (nzchar(prefix))
282 | components <- c(prefix, components)
283 |
284 | # build prefix
285 | paste(components, collapse = "/")
286 |
287 | }
288 |
289 | renv_bootstrap_library_root <- function(project) {
290 |
291 | path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA)
292 | if (!is.na(path))
293 | return(path)
294 |
295 | path <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA)
296 | if (!is.na(path)) {
297 | id <- substring(renv_bootstrap_hash_text(project), 1L, 8L)
298 | name <- paste(basename(project), id, sep = "-")
299 | return(file.path(path, name))
300 | }
301 |
302 | file.path(project, "renv/library")
303 |
304 | }
305 |
306 | renv_bootstrap_validate_version <- function(version) {
307 |
308 | loadedversion <- utils::packageDescription("renv", fields = "Version")
309 | if (version == loadedversion)
310 | return(TRUE)
311 |
312 | # assume four-component versions are from GitHub; three-component
313 | # versions are from CRAN
314 | components <- strsplit(loadedversion, "[.-]")[[1]]
315 | remote <- if (length(components) == 4L)
316 | paste("rstudio/renv", loadedversion, sep = "@")
317 | else
318 | paste("renv", loadedversion, sep = "@")
319 |
320 | fmt <- paste(
321 | "renv %1$s was loaded from project library, but this project is configured to use renv %2$s.",
322 | "Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.",
323 | "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
324 | sep = "\n"
325 | )
326 |
327 | msg <- sprintf(fmt, loadedversion, version, remote)
328 | warning(msg, call. = FALSE)
329 |
330 | FALSE
331 |
332 | }
333 |
334 | renv_bootstrap_hash_text <- function(text) {
335 |
336 | hashfile <- tempfile("renv-hash-")
337 | on.exit(unlink(hashfile), add = TRUE)
338 |
339 | writeLines(text, con = hashfile)
340 | tools::md5sum(hashfile)
341 |
342 | }
343 |
344 | renv_bootstrap_load <- function(project, libpath, version) {
345 |
346 | # try to load renv from the project library
347 | if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE))
348 | return(FALSE)
349 |
350 | # warn if the version of renv loaded does not match
351 | renv_bootstrap_validate_version(version)
352 |
353 | # load the project
354 | renv::load(project)
355 |
356 | TRUE
357 |
358 | }
359 |
360 | # construct path to library root
361 | root <- renv_bootstrap_library_root(project)
362 |
363 | # construct library prefix for platform
364 | prefix <- renv_bootstrap_prefix()
365 |
366 | # construct full libpath
367 | libpath <- file.path(root, prefix)
368 |
369 | # attempt to load
370 | if (renv_bootstrap_load(project, libpath, version))
371 | return(TRUE)
372 |
373 | # load failed; inform user we're about to bootstrap
374 | prefix <- paste("# Bootstrapping renv", version)
375 | postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "")
376 | header <- paste(prefix, postfix)
377 | message(header)
378 |
379 | # perform bootstrap
380 | bootstrap(version, libpath)
381 |
382 | # exit early if we're just testing bootstrap
383 | if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA)))
384 | return(TRUE)
385 |
386 | # try again to load
387 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
388 | message("* Successfully installed and loaded renv ", version, ".")
389 | return(renv::load())
390 | }
391 |
392 | # failed to download or load renv; warn the user
393 | msg <- c(
394 | "Failed to find an renv installation: the project will not be loaded.",
395 | "Use `renv::activate()` to re-initialize the project."
396 | )
397 |
398 | warning(paste(msg, collapse = "\n"), call. = FALSE)
399 |
400 | })
401 |
--------------------------------------------------------------------------------
/R/plot_panel.R:
--------------------------------------------------------------------------------
1 |
2 | #' @title Table widget
3 | #' @description \code{dt_format} is a function for creating a graphical
4 | #' widget containing a table with download buttons (Excel and CSV).
5 | #' @param dat a data object - a matrix or a data frame.
6 | #' @param colnames Names of columns to display in the table. By default it is
7 | #' equal to the names of the columns from the \code{dat}. Parameter \code{colnames} is
8 | #' correspond the argument \code{colnames} from \code{\link[DT]{datatable}}.
9 | #' @details This function uses \code{\link[DT]{datatable}}.
10 | #'
11 |
12 | dt_format <- function(dat, colnames = colnames(dat)) {
13 | datatable(data = dat,
14 | colnames = colnames,
15 | class = "table-bordered table-condensed",
16 | extensions = "Buttons",
17 | options = list(pageLength = 10,
18 | dom = "tBip",
19 | autoWidth = TRUE,
20 | buttons = c("excel", "csv")),
21 | filter = "bottom",
22 | rownames = FALSE)
23 | }
24 |
25 |
26 | #' @title Ggplot_build for flipped plots
27 | #' @description \code{flip_ggplot_build} is a supplementary function for ggplot_build.
28 | #' Changes ggplot_build output in order to make it compatible with the
29 | #' plot when coordinates are flipped.
30 | #' @param ggplot_build_data output of \code{\link[ggplot2]{ggplot_build}}
31 | #' @details \code{data} from the output of \code{\link[ggplot2]{ggplot_build}} has
32 | #' names of columns compatible with the mapping. In case when coordinates are flipped,
33 | #' it is not consistent with the displayed plot. \code{flip_ggplot_build} changes
34 | #' the names so that coordinates from the output of \code{\link[ggplot2]{ggplot_build}}
35 | #' are compatible with the plot and returns it. In case when coordinates are not flipped
36 | #' \code{flip_ggplot_build} returns \code{ggplot_build_data}.
37 | #' @examples
38 | #' \dontrun{
39 | #'
40 | #' # returns plot info without any change because coordinates are not flipped
41 | #' p <- ggplot(Orange, aes(x = age, y = circumference, col = Tree)) +
42 | #' geom_point() +
43 | #' geom_line()
44 | #' plot_info <- ggplot_build(p)
45 | #' flip_ggplot_build(plot_info) # it is the same as plot_info
46 | #'
47 | #' # returns plot info with data modified for flipped coordinates
48 | #' p <- ggplot(Orange, aes(x = age, y = circumference, col = Tree)) +
49 | #' geom_point() +
50 | #' geom_line() +
51 | #' coord_flip()
52 | #' plot_info <- ggplot_build(p)
53 | #' flip_ggplot_build(plot_info)
54 | #' }
55 | #'
56 | #' @export
57 |
58 | flip_ggplot_build <- function(ggplot_build_data){
59 |
60 | if("CoordFlip" %in% class(ggplot_build_data$plot$coordinates)) {
61 |
62 | ggplot_build_data[["data"]] <- lapply(ggplot_build_data[["data"]], function(df) {
63 | df_names <- colnames(df)
64 | names(df) <- sapply(df_names, function(name) {
65 | switch(substr(name, 1, 1),
66 | x = {
67 | substr(name, 1, 1) = "y"
68 | },
69 | y = {
70 | substr(name, 1, 1) = "x"
71 | })
72 | name
73 | })
74 | df
75 | })
76 | }
77 | ggplot_build_data
78 | }
79 |
80 |
81 | #' @title Creating UI for a Shiny module with plot and data
82 | #' @description Creates module's UI for tabset panel containing two tabs - with
83 | #' plot and an elegant table with data.
84 | #' @param id unique ID name of tabset. The same ID as in the corresponding server for
85 | #' a module
86 | #' @param tab_plot Character. Title of tab containing plot. Default to
87 | #' \code{paste(id, "plot")}.
88 | #' @param tab_table Character. Title of tab containing table. Default to
89 | #' \code{paste(id, "data")}.
90 | #' @inheritParams plotOutput_h
91 | #' @details Module's UI involves a panel with two tabs. The first tab consists of
92 | #' displayed plot and three download buttons (png, svg and jpeg). There is also a
93 | #' compatible with the plot tooltip. The second tab consists of a table
94 | #' with two download buttons (Excel and CSV). For both table and plot there are
95 | #' provided helpers. \
96 | #' For more information see \code{\link[shinydetails]{plotOutput_h}} and
97 | #' \code{\link[shinydetails]{tableOutput_h}}
98 | #' @seealso To build Shiny module within a Shiny app using \code{beam_plot_panel_UI}
99 | #' see \code{\link[shinydetails]{beam_plot_panel_SERVER}}.
100 | #' @examples
101 | #' \dontrun{
102 | #' ui <- fluidPage(title = "Example app",
103 | #' beam_plot_panel_UI("airquality_basic"),
104 | #' beam_plot_panel_UI("airquality_advanced",
105 | #' tab_plot = "An advanced plot",
106 | #' tab_table = "An elegant table for an advanced plot",
107 | #' helpfiles = "custom_helpfiles"))
108 | #'
109 | #'server <- function(input, output, session) {
110 | #' airquality_basic_plot <- reactive({
111 | #' ggplot(airquality, aes(x = Wind, y = Temp, col = as.character(Month))) +
112 | #' geom_point()
113 | #' })
114 | #' airquality_basic_data <- reactive({
115 | #' airquality
116 | #' })
117 | #' beam_plot_panel_SERVER("airquality_basic",
118 | #' plot_out = airquality_basic_plot(),
119 | #' table_out = airquality_basic_data())
120 | #'
121 | #' airquality_advanced_data <- reactive({
122 | #' df <- data.frame(aggregate(. ~ Month, airquality, function(x) c(mean = mean(x), sd = sd(x)))[, c(1, 5)])
123 | #' df[["Month"]] <- month.name[df[["Month"]]]
124 | #' data.frame(Month = df[["Month"]],
125 | #' Temp_mean = df$Temp[, 1],
126 | #' Error = df$Temp[, 2],
127 | #' Year = 1973)})
128 | #'
129 | #' airquality_advanced_plot <- reactive({
130 | #' ggplot(airquality_advanced_data(), aes(y = 0, yend = Temp_mean, x = Month, xend = Month)) +
131 | #' geom_segment() +
132 | #' geom_point(mapping = aes(x = Month, y = Temp_mean), size = 3) +
133 | #' geom_point() +
134 | #' ylab("average temperature")
135 | #' })
136 | #' beam_plot_panel_SERVER("airquality_advanced",
137 | #' plot_out = airquality_advanced_plot(),
138 | #' table_out = airquality_advanced_data(),
139 | #' plot_type = "geom_segment",
140 | #' tt_content = list(row_text = c("Date: %s %i",
141 | #' "Average temperature: %f °F",
142 | #' "Error: %f",
143 | #' "Place: La Guardia Airport"),
144 | #' chosen_cols = c("Month",
145 | #' "Year",
146 | #' "Temp_mean",
147 | #' "Error"))
148 | #' )
149 | #'
150 | #'}
151 | #'}
152 | #' @export
153 |
154 | beam_plot_panel_UI <- function(id,
155 | tab_plot = paste(id, "plot"),
156 | tab_table = paste(id, "data"),
157 | helpfiles = "helpfiles") {
158 | ns <- NS(id)
159 | tagList(tabsetPanel(tabPanel(title = tab_plot,
160 | br(),
161 | div(style = "position:relative",
162 | plotOutput_h(outputId = ns("plot"),
163 | hover = hoverOpts(ns("hover"),
164 | delay = 10,
165 | delayType = "debounce"),
166 | helpfiles = helpfiles),
167 | uiOutput(ns("tooltip")),
168 | downloadButton(ns("download_png"), "Download png"),
169 | downloadButton(ns("download_jpeg"), "Download jpeg"),
170 | downloadButton(ns("download_svg"), "Download svg"))
171 | ),
172 | tabPanel(title = tab_table,
173 | tableOutput_h(outputId = ns("data"), helpfiles = helpfiles))))
174 | }
175 |
176 |
177 | #' @title Creating server for a Shiny module with plot and data.
178 | #' @description Creates module server for tabset panel containing two tabs - with
179 | #' plot and an elegant table with data.
180 | #' @param id unique Id of tabset panel. The same ID as in the corresponding UI for
181 | #' a module
182 | #' @param plot_out Plot to display in tab. There will be provided an automatically
183 | #' generated tooltip compatible with the plot. The items from first mapping will be
184 | #' connected with tooltip.
185 | #' @param table_out Table to display in tab.
186 | #' @inheritParams extract_tt_data_row
187 | #' @inheritParams plotOutput_h
188 | #' @inheritParams beam_tooltip
189 | #' @details Module's server involves a panel with two tabs. The first tab consists of
190 | #' displayed plot and three download buttons (png, svg and jpeg). There is also a
191 | #' compatible with plot tooltip obtained via \code{\link[shinydetails]{beam_tooltip}}.
192 | #' The second tab consists of a table with two download buttons (Excel and CSV).
193 | #' The table \code{table_out} before displaying is formatted using
194 | #' \code{\link[shinydetails]{dt_format}}. For both table and plot there are provided
195 | #' helpers.
196 | #' @seealso To build Shiny module within a Shiny app using \code{beam_plot_panel_SERVER}
197 | #' see \code{\link[shinydetails]{beam_plot_panel_UI}}.
198 | #' @examples
199 | #' \dontrun{
200 | #' ui <- fluidPage(title = "Example app",
201 | #' beam_plot_panel_UI("airquality_basic"),
202 | #' beam_plot_panel_UI("airquality_advanced",
203 | #' tab_plot = "An advanced plot",
204 | #' tab_table = "An elegant table for an advanced plot",
205 | #' helpfiles = "custom_helpfiles"))
206 | #'
207 | #'server <- function(input, output, session) {
208 | #' airquality_basic_plot <- reactive({
209 | #' ggplot(airquality, aes(x = Wind, y = Temp, col = as.character(Month))) +
210 | #' geom_point()
211 | #' })
212 | #' airquality_basic_data <- reactive({
213 | #' airquality
214 | #' })
215 | #' beam_plot_panel_SERVER("airquality_basic",
216 | #' plot_out = airquality_basic_plot(),
217 | #' table_out = airquality_basic_data())
218 | #'
219 | #' airquality_advanced_data <- reactive({
220 | #' df <- data.frame(aggregate(. ~ Month, airquality, function(x) c(mean = mean(x), sd = sd(x)))[, c(1, 5)])
221 | #' df[["Month"]] <- month.name[df[["Month"]]]
222 | #' data.frame(Month = df[["Month"]],
223 | #' Temp_mean = df$Temp[, 1],
224 | #' Error = df$Temp[, 2],
225 | #' Year = 1973)})
226 | #'
227 | #' airquality_advanced_plot <- reactive({
228 | #' ggplot(airquality_advanced_data(), aes(y = 0, yend = Temp_mean, x = Month, xend = Month)) +
229 | #' geom_segment() +
230 | #' geom_point(mapping = aes(x = Month, y = Temp_mean), size = 3) +
231 | #' geom_point() +
232 | #' ylab("average temperature")
233 | #' })
234 | #' beam_plot_panel_SERVER("airquality_advanced",
235 | #' plot_out = airquality_advanced_plot(),
236 | #' table_out = airquality_advanced_data(),
237 | #' plot_type = "geom_segment",
238 | #' tt_content = list(row_text = c("Date: %s %i",
239 | #' "Average temperature: %f °F",
240 | #' "Error: %f",
241 | #' "Place: La Guardia Airport"),
242 | #' chosen_cols = c("Month",
243 | #' "Year",
244 | #' "Temp_mean",
245 | #' "Error"))
246 | #' )
247 | #'
248 | #'}
249 | #'}
250 | #' @importFrom DT renderDataTable
251 | #' @export
252 |
253 |
254 | beam_plot_panel_SERVER <- function(id,
255 | plot_out,
256 | table_out,
257 | plot_type = "geom_point",
258 | tt_content = NULL,
259 | tt_range = 5,
260 | helpfiles = "helpfiles") {
261 |
262 | match.arg(plot_type, c("geom_col", "geom_point", "geom_segment"), several.ok = FALSE)
263 |
264 | moduleServer(id, function(input, output, session) {
265 |
266 | shinyhelper::observe_helpers(session = shiny::getDefaultReactiveDomain(),
267 | help_dir = helpfiles)
268 |
269 | output[["plot"]] <- renderPlot({plot_out()})
270 |
271 | plot_info_data <- reactive({
272 | plot_info <- ggplot_build(plot_out())
273 | flip_ggplot_build(plot_info)[["data"]][[1]]
274 | })
275 |
276 | output[["tooltip"]] <- renderUI({
277 | hv = input[["hover"]]
278 | if(!is.null(hv)) {
279 | beam_tooltip(hv, plot_info_data(), table_out(), plot_type, tt_content, tt_range)
280 | }
281 | })
282 |
283 | output[["download_png"]] <- beam_downloadButton(id, plot_out(), "png")
284 | output[["download_jpeg"]] <- beam_downloadButton(id, plot_out(), "jpeg")
285 | output[["download_svg"]] <- beam_downloadButton(id, plot_out(), "svg")
286 |
287 | output[["data"]] <- DT::renderDataTable(server = FALSE, {
288 | dt_format(table_out())
289 | })
290 | })
291 | }
292 |
--------------------------------------------------------------------------------
/renv.lock:
--------------------------------------------------------------------------------
1 | {
2 | "R": {
3 | "Version": "4.0.4",
4 | "Repositories": [
5 | {
6 | "Name": "CRAN",
7 | "URL": "https://cran.rstudio.com"
8 | }
9 | ]
10 | },
11 | "Packages": {
12 | "BH": {
13 | "Package": "BH",
14 | "Version": "1.72.0-3",
15 | "Source": "Repository",
16 | "Repository": "CRAN",
17 | "Hash": "8f9ce74c6417d61f0782cbae5fd2b7b0"
18 | },
19 | "DT": {
20 | "Package": "DT",
21 | "Version": "0.16",
22 | "Source": "Repository",
23 | "Repository": "CRAN",
24 | "Hash": "acac794cc3e393ca65f916e5ced5c1d2"
25 | },
26 | "MASS": {
27 | "Package": "MASS",
28 | "Version": "7.3-53",
29 | "Source": "Repository",
30 | "Repository": "CRAN",
31 | "Hash": "d1bc1c8e9c0ace57ec9ffea01021d45f"
32 | },
33 | "Matrix": {
34 | "Package": "Matrix",
35 | "Version": "1.3-2",
36 | "Source": "Repository",
37 | "Repository": "CRAN",
38 | "Hash": "ff280503079ad8623d3c4b1519b24ea2"
39 | },
40 | "R6": {
41 | "Package": "R6",
42 | "Version": "2.5.0",
43 | "Source": "Repository",
44 | "Repository": "CRAN",
45 | "Hash": "b203113193e70978a696b2809525649d"
46 | },
47 | "RColorBrewer": {
48 | "Package": "RColorBrewer",
49 | "Version": "1.1-2",
50 | "Source": "Repository",
51 | "Repository": "CRAN",
52 | "Hash": "e031418365a7f7a766181ab5a41a5716"
53 | },
54 | "Rcpp": {
55 | "Package": "Rcpp",
56 | "Version": "1.0.5",
57 | "Source": "Repository",
58 | "Repository": "CRAN",
59 | "Hash": "125dc7a0ed375eb68c0ce533b48d291f"
60 | },
61 | "askpass": {
62 | "Package": "askpass",
63 | "Version": "1.1",
64 | "Source": "Repository",
65 | "Repository": "CRAN",
66 | "Hash": "e8a22846fff485f0be3770c2da758713"
67 | },
68 | "assertthat": {
69 | "Package": "assertthat",
70 | "Version": "0.2.1",
71 | "Source": "Repository",
72 | "Repository": "CRAN",
73 | "Hash": "50c838a310445e954bc13f26f26a6ecf"
74 | },
75 | "base64enc": {
76 | "Package": "base64enc",
77 | "Version": "0.1-3",
78 | "Source": "Repository",
79 | "Repository": "CRAN",
80 | "Hash": "543776ae6848fde2f48ff3816d0628bc"
81 | },
82 | "brio": {
83 | "Package": "brio",
84 | "Version": "1.1.1",
85 | "Source": "Repository",
86 | "Repository": "CRAN",
87 | "Hash": "36758510e65a457efeefa50e1e7f0576"
88 | },
89 | "cachem": {
90 | "Package": "cachem",
91 | "Version": "1.0.3",
92 | "Source": "Repository",
93 | "Repository": "CRAN",
94 | "Hash": "803b5d36ec15fe3314905749a5619767"
95 | },
96 | "callr": {
97 | "Package": "callr",
98 | "Version": "3.5.1",
99 | "Source": "Repository",
100 | "Repository": "CRAN",
101 | "Hash": "b7d7f1e926dfcd57c74ce93f5c048e80"
102 | },
103 | "cli": {
104 | "Package": "cli",
105 | "Version": "2.3.0",
106 | "Source": "Repository",
107 | "Repository": "CRAN",
108 | "Hash": "26fb4f0871c8e5b84d77f6dc22f2ee0a"
109 | },
110 | "colorspace": {
111 | "Package": "colorspace",
112 | "Version": "1.4-1",
113 | "Source": "Repository",
114 | "Repository": "CRAN",
115 | "Hash": "6b436e95723d1f0e861224dd9b094dfb"
116 | },
117 | "commonmark": {
118 | "Package": "commonmark",
119 | "Version": "1.7",
120 | "Source": "Repository",
121 | "Repository": "CRAN",
122 | "Hash": "0f22be39ec1d141fd03683c06f3a6e67"
123 | },
124 | "cpp11": {
125 | "Package": "cpp11",
126 | "Version": "0.2.6",
127 | "Source": "Repository",
128 | "Repository": "CRAN",
129 | "Hash": "f08909ebdad90b19d8d3930da4220564"
130 | },
131 | "crayon": {
132 | "Package": "crayon",
133 | "Version": "1.4.1",
134 | "Source": "Repository",
135 | "Repository": "CRAN",
136 | "Hash": "e75525c55c70e5f4f78c9960a4b402e9"
137 | },
138 | "crosstalk": {
139 | "Package": "crosstalk",
140 | "Version": "1.1.0.1",
141 | "Source": "Repository",
142 | "Repository": "CRAN",
143 | "Hash": "ae55f5d7c02f0ab43c58dd050694f2b4"
144 | },
145 | "curl": {
146 | "Package": "curl",
147 | "Version": "4.3",
148 | "Source": "Repository",
149 | "Repository": "CRAN",
150 | "Hash": "2b7d10581cc730804e9ed178c8374bd6"
151 | },
152 | "desc": {
153 | "Package": "desc",
154 | "Version": "1.2.0",
155 | "Source": "Repository",
156 | "Repository": "CRAN",
157 | "Hash": "6c8fe8fa26a23b79949375d372c7b395"
158 | },
159 | "diffobj": {
160 | "Package": "diffobj",
161 | "Version": "0.3.3",
162 | "Source": "Repository",
163 | "Repository": "CRAN",
164 | "Hash": "55fae7ec1418d2a47bd552571673d1af"
165 | },
166 | "digest": {
167 | "Package": "digest",
168 | "Version": "0.6.27",
169 | "Source": "Repository",
170 | "Repository": "CRAN",
171 | "Hash": "a0cbe758a531d054b537d16dff4d58a1"
172 | },
173 | "downlit": {
174 | "Package": "downlit",
175 | "Version": "0.2.1",
176 | "Source": "Repository",
177 | "Repository": "CRAN",
178 | "Hash": "f24f1e44320a978c03050b8403a83793"
179 | },
180 | "ellipsis": {
181 | "Package": "ellipsis",
182 | "Version": "0.3.1",
183 | "Source": "Repository",
184 | "Repository": "CRAN",
185 | "Hash": "fd2844b3a43ae2d27e70ece2df1b4e2a"
186 | },
187 | "evaluate": {
188 | "Package": "evaluate",
189 | "Version": "0.14",
190 | "Source": "Repository",
191 | "Repository": "CRAN",
192 | "Hash": "ec8ca05cffcc70569eaaad8469d2a3a7"
193 | },
194 | "fansi": {
195 | "Package": "fansi",
196 | "Version": "0.4.2",
197 | "Source": "Repository",
198 | "Repository": "CRAN",
199 | "Hash": "fea074fb67fe4c25d47ad09087da847d"
200 | },
201 | "farver": {
202 | "Package": "farver",
203 | "Version": "2.0.3",
204 | "Source": "Repository",
205 | "Repository": "CRAN",
206 | "Hash": "dad6793a5a1f73c8e91f1a1e3e834b05"
207 | },
208 | "fastmap": {
209 | "Package": "fastmap",
210 | "Version": "1.1.0",
211 | "Source": "Repository",
212 | "Repository": "CRAN",
213 | "Hash": "77bd60a6157420d4ffa93b27cf6a58b8"
214 | },
215 | "fs": {
216 | "Package": "fs",
217 | "Version": "1.5.0",
218 | "Source": "Repository",
219 | "Repository": "CRAN",
220 | "Hash": "44594a07a42e5f91fac9f93fda6d0109"
221 | },
222 | "ggplot2": {
223 | "Package": "ggplot2",
224 | "Version": "3.3.2",
225 | "Source": "Repository",
226 | "Repository": "CRAN",
227 | "Hash": "4ded8b439797f7b1693bd3d238d0106b"
228 | },
229 | "glue": {
230 | "Package": "glue",
231 | "Version": "1.4.2",
232 | "Source": "Repository",
233 | "Repository": "CRAN",
234 | "Hash": "6efd734b14c6471cfe443345f3e35e29"
235 | },
236 | "gtable": {
237 | "Package": "gtable",
238 | "Version": "0.3.0",
239 | "Source": "Repository",
240 | "Repository": "CRAN",
241 | "Hash": "ac5c6baf7822ce8732b343f14c072c4d"
242 | },
243 | "highr": {
244 | "Package": "highr",
245 | "Version": "0.8",
246 | "Source": "Repository",
247 | "Repository": "CRAN",
248 | "Hash": "4dc5bb88961e347a0f4d8aad597cbfac"
249 | },
250 | "htmltools": {
251 | "Package": "htmltools",
252 | "Version": "0.5.1.1",
253 | "Source": "Repository",
254 | "Repository": "CRAN",
255 | "Hash": "af2c2531e55df5cf230c4b5444fc973c"
256 | },
257 | "htmlwidgets": {
258 | "Package": "htmlwidgets",
259 | "Version": "1.5.2",
260 | "Source": "Repository",
261 | "Repository": "CRAN",
262 | "Hash": "0aaf56b7960bb066646e1868cadcaf07"
263 | },
264 | "httpuv": {
265 | "Package": "httpuv",
266 | "Version": "1.5.4",
267 | "Source": "Repository",
268 | "Repository": "CRAN",
269 | "Hash": "4e6dabb220b006ccdc3b3b5ff993b205"
270 | },
271 | "httr": {
272 | "Package": "httr",
273 | "Version": "1.4.2",
274 | "Source": "Repository",
275 | "Repository": "CRAN",
276 | "Hash": "a525aba14184fec243f9eaec62fbed43"
277 | },
278 | "hunspell": {
279 | "Package": "hunspell",
280 | "Version": "3.0",
281 | "Source": "Repository",
282 | "Repository": "CRAN",
283 | "Hash": "71e7853d60b6b4ba891d62ede21752e9"
284 | },
285 | "isoband": {
286 | "Package": "isoband",
287 | "Version": "0.2.2",
288 | "Source": "Repository",
289 | "Repository": "CRAN",
290 | "Hash": "6e58bd3d6b3dd82a944cd6f05ade228f"
291 | },
292 | "jsonlite": {
293 | "Package": "jsonlite",
294 | "Version": "1.7.2",
295 | "Source": "Repository",
296 | "Repository": "CRAN",
297 | "Hash": "98138e0994d41508c7a6b84a0600cfcb"
298 | },
299 | "knitr": {
300 | "Package": "knitr",
301 | "Version": "1.31",
302 | "Source": "Repository",
303 | "Repository": "CRAN",
304 | "Hash": "c3994c036d19fc22c5e2a209c8298bfb"
305 | },
306 | "labeling": {
307 | "Package": "labeling",
308 | "Version": "0.3",
309 | "Source": "Repository",
310 | "Repository": "CRAN",
311 | "Hash": "73832978c1de350df58108c745ed0e3e"
312 | },
313 | "later": {
314 | "Package": "later",
315 | "Version": "1.1.0.1",
316 | "Source": "Repository",
317 | "Repository": "CRAN",
318 | "Hash": "d0a62b247165aabf397fded504660d8a"
319 | },
320 | "lattice": {
321 | "Package": "lattice",
322 | "Version": "0.20-41",
323 | "Source": "Repository",
324 | "Repository": "CRAN",
325 | "Hash": "fbd9285028b0263d76d18c95ae51a53d"
326 | },
327 | "lazyeval": {
328 | "Package": "lazyeval",
329 | "Version": "0.2.2",
330 | "Source": "Repository",
331 | "Repository": "CRAN",
332 | "Hash": "d908914ae53b04d4c0c0fd72ecc35370"
333 | },
334 | "lifecycle": {
335 | "Package": "lifecycle",
336 | "Version": "0.2.0",
337 | "Source": "Repository",
338 | "Repository": "CRAN",
339 | "Hash": "361811f31f71f8a617a9a68bf63f1f42"
340 | },
341 | "magrittr": {
342 | "Package": "magrittr",
343 | "Version": "2.0.1",
344 | "Source": "Repository",
345 | "Repository": "CRAN",
346 | "Hash": "41287f1ac7d28a92f0a286ed507928d3"
347 | },
348 | "markdown": {
349 | "Package": "markdown",
350 | "Version": "1.1",
351 | "Source": "Repository",
352 | "Repository": "CRAN",
353 | "Hash": "61e4a10781dd00d7d81dd06ca9b94e95"
354 | },
355 | "memoise": {
356 | "Package": "memoise",
357 | "Version": "2.0.0",
358 | "Source": "Repository",
359 | "Repository": "CRAN",
360 | "Hash": "a0bc51650201a56d00a4798523cc91b3"
361 | },
362 | "mgcv": {
363 | "Package": "mgcv",
364 | "Version": "1.8-33",
365 | "Source": "Repository",
366 | "Repository": "CRAN",
367 | "Hash": "eb7b6439bc6d812eed2cddba5edc6be3"
368 | },
369 | "mime": {
370 | "Package": "mime",
371 | "Version": "0.9",
372 | "Source": "Repository",
373 | "Repository": "CRAN",
374 | "Hash": "e87a35ec73b157552814869f45a63aa3"
375 | },
376 | "munsell": {
377 | "Package": "munsell",
378 | "Version": "0.5.0",
379 | "Source": "Repository",
380 | "Repository": "CRAN",
381 | "Hash": "6dfe8bf774944bd5595785e3229d8771"
382 | },
383 | "nlme": {
384 | "Package": "nlme",
385 | "Version": "3.1-149",
386 | "Source": "Repository",
387 | "Repository": "CRAN",
388 | "Hash": "7c24ab3a1e3afe50388eb2d893aab255"
389 | },
390 | "openssl": {
391 | "Package": "openssl",
392 | "Version": "1.4.3",
393 | "Source": "Repository",
394 | "Repository": "CRAN",
395 | "Hash": "a399e4773075fc2375b71f45fca186c4"
396 | },
397 | "pillar": {
398 | "Package": "pillar",
399 | "Version": "1.4.7",
400 | "Source": "Repository",
401 | "Repository": "CRAN",
402 | "Hash": "3b3dd89b2ee115a8b54e93a34cd546b4"
403 | },
404 | "pkgbuild": {
405 | "Package": "pkgbuild",
406 | "Version": "1.1.0",
407 | "Source": "Repository",
408 | "Repository": "CRAN",
409 | "Hash": "404684bc4e3685007f9720adf13b06c1"
410 | },
411 | "pkgconfig": {
412 | "Package": "pkgconfig",
413 | "Version": "2.0.3",
414 | "Source": "Repository",
415 | "Repository": "CRAN",
416 | "Hash": "01f28d4278f15c76cddbea05899c5d6f"
417 | },
418 | "pkgdown": {
419 | "Package": "pkgdown",
420 | "Version": "1.6.1",
421 | "Source": "Repository",
422 | "Repository": "CRAN",
423 | "Hash": "8896076540d9e9b556a2ec658c81f916"
424 | },
425 | "pkgload": {
426 | "Package": "pkgload",
427 | "Version": "1.1.0",
428 | "Source": "Repository",
429 | "Repository": "CRAN",
430 | "Hash": "b6b150cd4709e0c0c9b5d51ac4376282"
431 | },
432 | "praise": {
433 | "Package": "praise",
434 | "Version": "1.0.0",
435 | "Source": "Repository",
436 | "Repository": "CRAN",
437 | "Hash": "a555924add98c99d2f411e37e7d25e9f"
438 | },
439 | "prettyunits": {
440 | "Package": "prettyunits",
441 | "Version": "1.1.1",
442 | "Source": "Repository",
443 | "Repository": "CRAN",
444 | "Hash": "95ef9167b75dde9d2ccc3c7528393e7e"
445 | },
446 | "processx": {
447 | "Package": "processx",
448 | "Version": "3.4.5",
449 | "Source": "Repository",
450 | "Repository": "CRAN",
451 | "Hash": "22aab6098cb14edd0a5973a8438b569b"
452 | },
453 | "promises": {
454 | "Package": "promises",
455 | "Version": "1.1.1",
456 | "Source": "Repository",
457 | "Repository": "CRAN",
458 | "Hash": "a8730dcbdd19f9047774909f0ec214a4"
459 | },
460 | "ps": {
461 | "Package": "ps",
462 | "Version": "1.5.0",
463 | "Source": "Repository",
464 | "Repository": "CRAN",
465 | "Hash": "ebaed51a03411fd5cfc1e12d9079b353"
466 | },
467 | "purrr": {
468 | "Package": "purrr",
469 | "Version": "0.3.4",
470 | "Source": "Repository",
471 | "Repository": "CRAN",
472 | "Hash": "97def703420c8ab10d8f0e6c72101e02"
473 | },
474 | "ragg": {
475 | "Package": "ragg",
476 | "Version": "0.4.1",
477 | "Source": "Repository",
478 | "Repository": "CRAN",
479 | "Hash": "70bd921f54c3763f3dbec15106118828"
480 | },
481 | "rematch2": {
482 | "Package": "rematch2",
483 | "Version": "2.1.2",
484 | "Source": "Repository",
485 | "Repository": "CRAN",
486 | "Hash": "76c9e04c712a05848ae7a23d2f170a40"
487 | },
488 | "renv": {
489 | "Package": "renv",
490 | "Version": "0.12.3",
491 | "Source": "Repository",
492 | "Repository": "CRAN",
493 | "Hash": "b5510c50c7f31d453c385c7b460af2b9"
494 | },
495 | "rlang": {
496 | "Package": "rlang",
497 | "Version": "0.4.10",
498 | "Source": "Repository",
499 | "Repository": "CRAN",
500 | "Hash": "599df23c40a4fce9c7b4764f28c37857"
501 | },
502 | "rmarkdown": {
503 | "Package": "rmarkdown",
504 | "Version": "2.6",
505 | "Source": "Repository",
506 | "Repository": "CRAN",
507 | "Hash": "bc4bac38960b446c183957bfd563e763"
508 | },
509 | "rprojroot": {
510 | "Package": "rprojroot",
511 | "Version": "2.0.2",
512 | "Source": "Repository",
513 | "Repository": "CRAN",
514 | "Hash": "249d8cd1e74a8f6a26194a91b47f21d1"
515 | },
516 | "rstudioapi": {
517 | "Package": "rstudioapi",
518 | "Version": "0.11",
519 | "Source": "Repository",
520 | "Repository": "CRAN",
521 | "Hash": "33a5b27a03da82ac4b1d43268f80088a"
522 | },
523 | "scales": {
524 | "Package": "scales",
525 | "Version": "1.1.1",
526 | "Source": "Repository",
527 | "Repository": "CRAN",
528 | "Hash": "6f76f71042411426ec8df6c54f34e6dd"
529 | },
530 | "shiny": {
531 | "Package": "shiny",
532 | "Version": "1.5.0",
533 | "Source": "Repository",
534 | "Repository": "CRAN",
535 | "Hash": "ee4ed72d7a5047d9e73cf922ad66e9c9"
536 | },
537 | "shinyhelper": {
538 | "Package": "shinyhelper",
539 | "Version": "0.3.2",
540 | "Source": "Repository",
541 | "Repository": "CRAN",
542 | "Hash": "baef117734d5bd59373a561a15168679"
543 | },
544 | "sourcetools": {
545 | "Package": "sourcetools",
546 | "Version": "0.1.7",
547 | "Source": "Repository",
548 | "Repository": "CRAN",
549 | "Hash": "947e4e02a79effa5d512473e10f41797"
550 | },
551 | "spelling": {
552 | "Package": "spelling",
553 | "Version": "2.2",
554 | "Source": "Repository",
555 | "Repository": "CRAN",
556 | "Hash": "b8c899a5c83f0d897286550481c91798"
557 | },
558 | "stringi": {
559 | "Package": "stringi",
560 | "Version": "1.5.3",
561 | "Source": "Repository",
562 | "Repository": "CRAN",
563 | "Hash": "a063ebea753c92910a4cca7b18bc1f05"
564 | },
565 | "stringr": {
566 | "Package": "stringr",
567 | "Version": "1.4.0",
568 | "Source": "Repository",
569 | "Repository": "CRAN",
570 | "Hash": "0759e6b6c0957edb1311028a49a35e76"
571 | },
572 | "sys": {
573 | "Package": "sys",
574 | "Version": "3.4",
575 | "Source": "Repository",
576 | "Repository": "CRAN",
577 | "Hash": "b227d13e29222b4574486cfcbde077fa"
578 | },
579 | "systemfonts": {
580 | "Package": "systemfonts",
581 | "Version": "1.0.1",
582 | "Source": "Repository",
583 | "Repository": "CRAN",
584 | "Hash": "6e899d7c097698d50ec87b1d8e65f246"
585 | },
586 | "testthat": {
587 | "Package": "testthat",
588 | "Version": "3.0.2",
589 | "Source": "Repository",
590 | "Repository": "CRAN",
591 | "Hash": "495e0434d9305716b6a87031570ce109"
592 | },
593 | "textshaping": {
594 | "Package": "textshaping",
595 | "Version": "0.2.1",
596 | "Source": "Repository",
597 | "Repository": "CRAN",
598 | "Hash": "a34d4aa94ca91a52710b1c0c36bcded6"
599 | },
600 | "tibble": {
601 | "Package": "tibble",
602 | "Version": "3.0.6",
603 | "Source": "Repository",
604 | "Repository": "CRAN",
605 | "Hash": "9c6c10e594f32096ede0c7d373ccbddd"
606 | },
607 | "tinytex": {
608 | "Package": "tinytex",
609 | "Version": "0.29",
610 | "Source": "Repository",
611 | "Repository": "CRAN",
612 | "Hash": "f0b0ba735febac9a8344253ae6fa93f5"
613 | },
614 | "utf8": {
615 | "Package": "utf8",
616 | "Version": "1.1.4",
617 | "Source": "Repository",
618 | "Repository": "CRAN",
619 | "Hash": "4a5081acfb7b81a572e4384a7aaf2af1"
620 | },
621 | "vctrs": {
622 | "Package": "vctrs",
623 | "Version": "0.3.6",
624 | "Source": "Repository",
625 | "Repository": "CRAN",
626 | "Hash": "5cf1957f93076c19fdc81d01409d240b"
627 | },
628 | "viridisLite": {
629 | "Package": "viridisLite",
630 | "Version": "0.3.0",
631 | "Source": "Repository",
632 | "Repository": "CRAN",
633 | "Hash": "ce4f6271baa94776db692f1cb2055bee"
634 | },
635 | "waldo": {
636 | "Package": "waldo",
637 | "Version": "0.2.4",
638 | "Source": "Repository",
639 | "Repository": "CRAN",
640 | "Hash": "29df52c781e572c967f90de9713423c4"
641 | },
642 | "whisker": {
643 | "Package": "whisker",
644 | "Version": "0.4",
645 | "Source": "Repository",
646 | "Repository": "CRAN",
647 | "Hash": "ca970b96d894e90397ed20637a0c1bbe"
648 | },
649 | "withr": {
650 | "Package": "withr",
651 | "Version": "2.4.1",
652 | "Source": "Repository",
653 | "Repository": "CRAN",
654 | "Hash": "caf4781c674ffa549a4676d2d77b13cc"
655 | },
656 | "xfun": {
657 | "Package": "xfun",
658 | "Version": "0.20",
659 | "Source": "Repository",
660 | "Repository": "CRAN",
661 | "Hash": "d7222684dc02327871e3b1da0aba7089"
662 | },
663 | "xml2": {
664 | "Package": "xml2",
665 | "Version": "1.3.2",
666 | "Source": "Repository",
667 | "Repository": "CRAN",
668 | "Hash": "d4d71a75dd3ea9eb5fa28cc21f9585e2"
669 | },
670 | "xtable": {
671 | "Package": "xtable",
672 | "Version": "1.8-4",
673 | "Source": "Repository",
674 | "Repository": "CRAN",
675 | "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2"
676 | },
677 | "yaml": {
678 | "Package": "yaml",
679 | "Version": "2.2.1",
680 | "Source": "Repository",
681 | "Repository": "CRAN",
682 | "Hash": "2826c5d9efb0a88f657c7a679c7106db"
683 | }
684 | }
685 | }
686 |
--------------------------------------------------------------------------------