--- title: "Create a static shiny app" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{export_static_app} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Introduction This vignette shows how to create static *Shiny apps* using the `OmopViewer` package. These static shiny apps are separated projects with their own `ui`, `server`, `global` and files to pre-process the results that later can easily later be customised and deployed. This functionality is adequate if what you are willing is to deploy a shiny, customise it later and/or be able to access this shiny app in the future. If what you want is to visualise the data briefly and you do not need to access to the shiny in the future, edit it or deploy it maybe the [Dynamic app](dynamic_app.Rmd) functionality is what are you searching for. ## Loading Necessary Libraries and Data In this vignette we will use simply to packages: ```{r} library(OmopViewer) library(omopgenerics, warn.conflicts = FALSE) library(shiny) ``` We'll use the `omopViewerResults` mock data from this package for illustration: ```{r} # Inspect the structure of the sample data summary(omopViewerResults) ``` ## Subsetting the Data For this example, we'll use a subset of the data containing specific result types: ```{r} result <- omopViewerResults |> filterSettings( result_type %in% c("summarise_omop_snapshot", "summarise_characteristics", "incidence") ) ``` This filters the `omopViewerResults` data to include only entries where result_type is one of "summarise_omop_snapshot", "summarise_characteristics", or "incidence". ```{r} summary(result) ``` ## Generating the Shiny App The exportStaticApp function generates a Shiny app from the prepared data. Using the default parameters, it only requires a directory to save the app and the processed data (a object): ```{r} dir <- tempdir() exportStaticApp(result = result, directory = dir) ``` Note that by default if executed in an interactive environment like *R Studio* the project will be opened in a separated window. Use `open = FALSE` if you do not wish to open the shiny app after generating it. ### Generated shiny app See that this created a new project **shiny** in the specified directory along with some files: ```{r} cat(list.files(path = here::here(dir, "shiny"), recursive = TRUE), sep = "\n") ``` - `background.R` is only generated if background argument is set to `TRUE` and is used to customise the landing page of the shiny app. - `data` folder contains the raw result object `results.csv` and the script to process the data `preprocess.R`. - `funcitons.R` contains several functions that are used internally in the shiny app. - `global.R`, `ui.R`, and `server.R` define the shiny app itself. - `www` contains images and logos used in the shiny app, by default `hds_logo.svg` and `ohdsi_logo.svg`. ## Panels generated (panelDetails) The shiny generated contained a total of 3 panels, this was determined by the argument `panelDetails`. Each element in `panelDetails` will be used to create a different panel in the shiny app. The package contains in total `r length(omopViewerPanels)` predefined panels: ```{r} omopViewerPanels ``` Each panel is associated with a determined `result_type` as showed in the print. By default, the function `panelDetailsFromResult()` groups the results by `result_type` and displays each `result_type` in a separate panel, if a pre-build panel does not exist for that `result_type` then the *default* panel is used. In our case we have pre-build panels that are: ```{r} panelDetailsFromResult(result = result) ``` ### Understanding Panel Details (panelDetails) Each panel’s entry contains key information: 1. Icon: Defines the icon displayed next to the panel, helping to visually distinguish between the different types of panels (e.g., clipboard-list, chart-line ...). 2. Data: the fields used in data will be passed to `filterSettings()` function to determine the data that will be included in that panel. Usually `result_type` is the most common way (e.g. `panelDetails$data <- list(result_type = "incidence")`), but other fields can be used for example: `panelDetails$data <- list(result_type = "incidence", denominator_age_group = c("0 to 19", "20 to 39"))` would only include the results obtained by the following code: ```{r, eval=FALSE} result |> filterSettings( result_type == "incidence" & denominator_age_group %in% c("0 to 19", "20 to 39") ) ``` 3. Filters: Filters (filters + automatic_filters) that allow users to refine the results within each panel. Each panel has its own defaults. For example, the default incidence panel includes automatic_filters: "settings", "variable_name" and filters: "cdm_name". This means that there will be a field for any column in settings, and variable_name and cdm_name columns. 4. Content: Defines the types of content displayed in the panel, such as tables (DT, gt, reactable, ...) and plots (ui, ggplot2, plotly, ...). For example, the `summarise_omop_snapshot` panel includes a table displaying the snapshot data and a gt table generated from that snapshot data. All of these elements - icon, data, filters, and content - can be customised by the user if needed. See more details in the **customised_panels** vignette. ## Panel Structure (omopViewerPanels) The arrangement of panels within the app is controlled by the `panelStructure` variable. This variable determines how panels are grouped into logical sections or tabs within the Shiny app. By default, the different panels are grouped by the package the produced the result object. In this case *OmopSketch*, *CohortCharacteristics* and *IncidencePrevalence* respectively. ### Customise panelStructure ```{r, eval=FALSE} ps1 <- list( grp_1 = c("summarise_omop_snapshot", "incidence"), grp_2 = c("summarise_characteristics") ) exportStaticApp(result = result, directory = tempdir(), panelStructure = ps1) ``` This custom `panelStructure` groups the "summarise_omop_snapshot" and "incidence" result types together in grp_1, while placing the "summarise_characteristics" result type in grp_2. You can pass this custom structure to `exportStaticApp` to organize the panels according to your preference.