diff --git a/DESCRIPTION b/DESCRIPTION index da422cf..baf9532 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: iSEEindex Title: iSEE extension for a landing page to a custom collection of data sets -Version: 0.99.12 -Date: 2022-07-05 +Version: 0.99.13 +Date: 2022-07-06 Authors@R: c(person("Kevin", "Rue-Albrecht", email = "kevinrue67@gmail.com", role = c("aut", "cre"), diff --git a/NEWS.md b/NEWS.md index e5a4132..42fec66 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# iSEEindex 0.99.13 + +* Added possibility to inject custom header and footer in landing page. + # iSEEindex 0.99.12 * Added control over inclusion and location of default initial configuration amongst available choices. diff --git a/R/iSEEindex.R b/R/iSEEindex.R index ff62a1a..4dd048d 100644 --- a/R/iSEEindex.R +++ b/R/iSEEindex.R @@ -85,13 +85,14 @@ #' available data sets. #' @param FUN.initial A function that returns a `list` of metadata for #' available initial configuration states. -#' @param available Metadata for available initial configurations, as `data.frame`. #' @param default.add Logical scalar indicating whether a default #' initial configuration should be added as a choice in the Shiny `selectizeInput()`. #' See [iSEEindex()]. #' @param default.position Character scalar indicating whether the default #' initial configuration should be added as the `"first"` or `"last"` option #' in the Shiny `selectizeInput()`. +#' @param body.header UI element to display \emph{above} the main landing page body. +#' @param body.footer UI element to display \emph{below} the main landing page body. #' #' @return An [iSEE::iSEE()] app with a custom landing page using a [BiocFileCache()] to cache a selection of data sets. #' @@ -129,13 +130,13 @@ #' if (interactive()) { #' shiny::runApp(app, port = 1234) #' } -iSEEindex <- function(bfc, FUN.datasets, FUN.initial = NULL, default.add = TRUE, default.position = c("first", "last")) { +iSEEindex <- function(bfc, FUN.datasets, FUN.initial = NULL, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { stopifnot(is(bfc, "BiocFileCache")) if (is.null(FUN.initial)) { FUN.initial <- function() NULL } iSEE( - landingPage=.landing_page(bfc, FUN.datasets, FUN.initial, default.add, default.position), + landingPage=.landing_page(bfc, FUN.datasets, FUN.initial, default.add, default.position, body.header, body.footer), appTitle = sprintf("iSEEindex - v%s", packageVersion("iSEEindex") ) diff --git a/R/landing_page.R b/R/landing_page.R index b91fcc2..39a7921 100644 --- a/R/landing_page.R +++ b/R/landing_page.R @@ -9,6 +9,8 @@ #' @param default.position Character scalar indicating whether the default #' initial configuration should be added as the `"first"` or `"last"` option #' in the Shiny `selectizeInput()`. +#' @param body.header UI element to display \emph{above} the main landing page body. +#' @param body.footer UI element to display \emph{below} the main landing page body. #' #' @return A `function` that defines UI elements and observers for the #' landing page of the app. @@ -22,7 +24,8 @@ #' @importFrom shinyjs disable #' #' @rdname INTERNAL_landing_page -.landing_page <- function(bfc, FUN.datasets, FUN.initial, default.add, default.position) { +.landing_page <- function(bfc, FUN.datasets, FUN.initial, default.add = TRUE, default.position = c("first", "last"), body.header = NULL, body.footer = NULL) { + default.position <- match.arg(default.position) # datasets datasets_available_list <- FUN.datasets() .check_datasets_list(datasets_available_list) @@ -36,6 +39,7 @@ # nocov start output$allPanels <- renderUI({ tagList( + body.header, fluidRow( column(width = 7L, shinydashboard::box(title = "Available Data Sets", @@ -66,7 +70,8 @@ uiOutput(.ui_initial_overview)) ) ) - ) + ), + body.footer ) # tagList }) # renderUI diff --git a/inst/iSEE.png b/inst/iSEE.png new file mode 100644 index 0000000..e496442 Binary files /dev/null and b/inst/iSEE.png differ diff --git a/man/iSEEindex.Rd b/man/iSEEindex.Rd index 69b1b27..fefb5d9 100644 --- a/man/iSEEindex.Rd +++ b/man/iSEEindex.Rd @@ -9,7 +9,9 @@ iSEEindex( FUN.datasets, FUN.initial = NULL, default.add = TRUE, - default.position = c("first", "last") + default.position = c("first", "last"), + body.header = NULL, + body.footer = NULL ) } \arguments{ @@ -29,7 +31,9 @@ See \code{\link[=iSEEindex]{iSEEindex()}}.} initial configuration should be added as the \code{"first"} or \code{"last"} option in the Shiny \code{selectizeInput()}.} -\item{available}{Metadata for available initial configurations, as \code{data.frame}.} +\item{body.header}{UI element to display \emph{above} the main landing page body.} + +\item{body.footer}{UI element to display \emph{below} the main landing page body.} } \value{ An \code{\link[iSEE:iSEE]{iSEE::iSEE()}} app with a custom landing page using a \code{\link[=BiocFileCache]{BiocFileCache()}} to cache a selection of data sets. diff --git a/vignettes/header.Rmd b/vignettes/header.Rmd new file mode 100644 index 0000000..d06cfd0 --- /dev/null +++ b/vignettes/header.Rmd @@ -0,0 +1,222 @@ +--- +title: "Adding a custom header and footer to the landing page" +author: + - name: Kevin Rue-Albrecht + affiliation: + - University of Oxford + email: kevin.rue-albrecht@imm.ox.ac.uk +output: + BiocStyle::html_document: + self_contained: yes + toc: true + toc_float: true + toc_depth: 2 + code_folding: show +date: "`r doc_date()`" +package: "`r pkg_ver('iSEEindex')`" +vignette: > + %\VignetteIndexEntry{Adding custom header and footer to the landing page} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + crop = NULL ## Related to https://stat.ethz.ch/pipermail/bioc-devel/2020-April/016656.html +) +``` + +```{r, eval=!exists("SCREENSHOT"), include=FALSE} +SCREENSHOT <- function(x, ...) knitr::include_graphics(x) +``` + +```{r vignetteSetup, echo=FALSE, message=FALSE, warning = FALSE} +## Track time spent on making the vignette +startTime <- Sys.time() + +## Bib setup +library("RefManageR") + +## Write bibliography information +bib <- c( + R = citation(), + BiocStyle = citation("BiocStyle")[1], + knitr = citation("knitr")[1], + RefManageR = citation("RefManageR")[1], + rmarkdown = citation("rmarkdown")[1], + sessioninfo = citation("sessioninfo")[1], + testthat = citation("testthat")[1], + iSEEindex = citation("iSEEindex")[1] +) +``` + +# Custom header and footer + +## Overview + +By default, `r Biocpkg("iSEEindex")` creates a minimal landing page presenting users with a fluid row that contains two `shinydashboard::box()`: + +- On the left, users can select a data set. +- On the right, users can select an initial configuration and launch the main app interface. + +`r Biocpkg("iSEEindex")` offers the opportunity for app maintainers to add content above (i.e., header) and below (i.e., footer) that row. + +That header and footer space may contain any valid UI element that will be displayed in the application UI *as is*. + +## Implementation + +The function `iSEEindex()` accepts header and footer content through its arguments `body.header=` and `body.footer=`. + +We recommend wrapping header and footer content in `shiny::fluidRow()`, to fit naturally with the main fluid row (see above). + +# Example + +First, let us set up the core elements of a simple application (see `?iSEEindex`). + +```{r, message=FALSE} +library("BiocFileCache") + +## +# BiocFileCache ---- +## + +library(BiocFileCache) +bfc <- BiocFileCache(cache = tempdir()) + +## +# iSEEindex ---- +## + +dataset_fun <- function() { + x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml")) + x$datasets +} + +initial_fun <- function() { + x <- yaml::read_yaml(system.file(package = "iSEEindex", "example.yaml")) + x$initial +} +``` + +Then, we design header and footer content, each wrapped in a `shiny::fluidRow()`. + +```{r, message=FALSE} +library("shiny") +header <- fluidRow(shinydashboard::box(width = 12L, + column(width = 10, + p(strong("Welcome to this demonstration app!")), + p( + "This is an example header that demonstrate how to use the functionality.", + "A great place for branding and intros.", + ), + p("On the right, we demonstrate how other content such as images can be added to this header.") + ), + column(width = 2, img(src="www/iSEE.png", width = "100px", height = "120px")) +)) +footer <- fluidRow(shinydashboard::box(width = 12L, + p("This is a example footer. A great place for copyright statements and outros.", style="text-align: center;"), + p( + "© 2023 iSEE.", + a("Artistic-2.0", href = "https://opensource.org/license/artistic-2-0/"), + style="text-align: center;") + )) +``` + +For the image file to be found, the containing directory must be added to the Shiny resource path as follows: + +```{r, message=FALSE} +library("shiny") +addResourcePath("www", system.file(package = "iSEEindex")) +``` + +Finally, we supply the custom header and footer to `iSEEindex()`. + +```{r, message=FALSE} +library("iSEEindex") +app <- iSEEindex(bfc, dataset_fun, initial_fun, + body.header = header, body.footer = footer +) + +if (interactive()) { + shiny::runApp(app, port = 1234) +} +``` + +```{r, echo=FALSE} +SCREENSHOT("screenshots/header_footer.png", delay=20) +``` + + +# Reproducibility + +The `r Biocpkg("iSEEindex")` package `r Citep(bib[["iSEEindex"]])` was made possible thanks to: + +* R `r Citep(bib[["R"]])` +* `r Biocpkg("BiocStyle")` `r Citep(bib[["BiocStyle"]])` +* `r CRANpkg("knitr")` `r Citep(bib[["knitr"]])` +* `r CRANpkg("RefManageR")` `r Citep(bib[["RefManageR"]])` +* `r CRANpkg("rmarkdown")` `r Citep(bib[["rmarkdown"]])` +* `r CRANpkg("sessioninfo")` `r Citep(bib[["sessioninfo"]])` +* `r CRANpkg("testthat")` `r Citep(bib[["testthat"]])` + +This package was developed using `r BiocStyle::Biocpkg("biocthis")`. + + +Code for creating the vignette + +```{r createVignette, eval=FALSE} +## Create the vignette +library("rmarkdown") +system.time(render("header.Rmd", "BiocStyle::html_document")) + +## Extract the R code +library("knitr") +knit("header.Rmd", tangle = TRUE) +``` + +Date the vignette was generated. + +```{r reproduce1, echo=FALSE} +## Date the vignette was generated +Sys.time() +``` + +Wallclock time spent generating the vignette. + +```{r reproduce2, echo=FALSE} +## Processing time in seconds +totalTime <- diff(c(startTime, Sys.time())) +round(totalTime, digits = 3) +``` + +`R` session information. + +```{r reproduce3, echo=FALSE} +## Session info +library("sessioninfo") +options(width = 100) +session_info() +``` + + + +# Bibliography + +This vignette was generated using `r Biocpkg("BiocStyle")` `r Citep(bib[["BiocStyle"]])` +with `r CRANpkg("knitr")` `r Citep(bib[["knitr"]])` and `r CRANpkg("rmarkdown")` `r Citep(bib[["rmarkdown"]])` running behind the scenes. + +Citations made with `r CRANpkg("RefManageR")` `r Citep(bib[["RefManageR"]])`. + +```{r vignetteBiblio, results = "asis", echo = FALSE, warning = FALSE, message = FALSE} +## Print bibliography +PrintBibliography(bib, .opts = list(hyperlink = "to.doc", style = "html")) +``` + + + +[scheme-wikipedia]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax +[iana-uri]: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml +[amazon-s3]: https://aws.amazon.com/s3/ +[aws-cli]: https://aws.amazon.com/cli/ diff --git a/vignettes/screenshots/header_footer.png b/vignettes/screenshots/header_footer.png new file mode 100644 index 0000000..45283d6 Binary files /dev/null and b/vignettes/screenshots/header_footer.png differ diff --git a/vignettes/screenshots/landing_page.png b/vignettes/screenshots/landing_page.png index 6827d8d..98a2b0f 100644 Binary files a/vignettes/screenshots/landing_page.png and b/vignettes/screenshots/landing_page.png differ