install.packages("leprechaun")
library(leprechaun)
24 leprechaun
This chapter walks through building a version of the sap
with the leprechaun
framework. The resulting app-package (lap
) is in the 19_leprechaun
branch.
The version/description of leprechaun
used in this Shiny app-package is:
Package | Version | Title | Description |
---|---|---|---|
leprechaun | 1.0.0 | Create Simple 'Shiny' Applications as Packages | Code generator for robust dependency-free 'Shiny' applications in the form of packages. It includes numerous convenience functions to create modules, include utility functions to create common 'Bootstrap' elements, setup a project from the ground-up, and much more. |
After checking out the 19_leprechaun
branch, be sure to load, document, and install the application.
Ctrl/Cmd + Shift + L / D / B
24.1 lap
(a leprechaun
app-package)
lap
exports the movies
data and the standalone app function, run()
.
library(lap)
::run() lap
Launch app with the shinypak
package:
launch('19_leprechaun')
24.2 Set up
Creating a new leprechaun app-package can be done with usethis::create_package()
1 (which we covered in Packages). After your app-package is created, leprechaun::scaffold()
builds the core app files:2
Code files: the code files in new leprechaun
apps include the following:
_disable_autoload.R
: Disablesshiny::loadSupport()
(covered in Launch)assets.R
: includesserveAssets()
for serving JavaScript files,remove_modules()
andget_modules()
for adding/removing modules, and thecollapse_files()
helper function for collapsing files.3input-handlers.R
:leprechaun_handler_df()
andleprechaun_handler_list()
are helper functions for including data and lists “from Websocket”.4leprechaun-utils.R
: includes amake_send_message()
function for “send custom messages to the front-end” with the “namespace carried along”. Read below for demonstration of how this is used.5run.R
: the standalone app function for your leprechaun app (covered in Launch).server.R
&ui.R
are applications primary UI and server functions.zzz.R
is a utility function file that holds the.onLoad()
function for adding external resources (using methods covered in Resources).8
R
├── _disable_autoload.R
├── assets.R
├── input-handlers.R
├── leprechaun-utils.R
├── run.R
├── server.R
├── ui.R
└── zzz.R
1 directory, 8 files
- 1
-
Disables
shiny::loadSupport()
- 2
- Includes functions for serving JavaScript files, adding/removing modules, and collapsing files.
- 3
-
Utility functions for handling
list
s anddata.frame
s
- 4
-
Contains the
make_send_message()
function for ‘send[ing] custom messages to the front-end’ - 5
-
Standalone app function
- 6
-
App primary server function
- 7
-
App primary ui function
- 8
- Includes wrapper for adding external files
- Adding dependencies:
shiny
,bslib
,htmltools
andpkgload
should be added to theDESCRIPTION
withusethis::use_package()
(covered in the Dependencies chapter).
Imports:
bslib,
htmltools,
shiny
Suggests:
pkgload
The lap
folder structure should look familiar if you’ve been following along with the previous chapters. The standard R package files (DESCRIPTION
, NAMESPACE
, and .Rproj
) are accompanied by a .leprechaun
lock file.
lap/
├── .leprechaun
├── DESCRIPTION
├── NAMESPACE
└── sap.Rproj
The initial call to leprechaun::scaffold()
creates the following folders in the inst/
folder (recall that inst/
contents are available when the package is installed).
inst/
├── assets
├── dev
├── img
└── run
└── app.R
5 directories, 1 file
inst/run/app.R
contains a call to leprechaun::build()
, pkgload::load_all()
, then a call to the standalone app function, run()
.9
24.3 Development
Code files: new code files in leprechaun
apps can be created with usethis::use_r()
or with a helper function:
- Create modules with
add_module()
. Modules created withadd_module("name")
will have:10- A module file with a
module_name
prefix (R/module_name.R
)
- A module UI function:
nameUI()
- A module server function:
name_server()
- A module file with a
- Create an
app.R
file withadd_app_file()
. This includes a call topkgload::load_all()
andrun()
.11 - App files:
R/run.R
contains functions for running the app.12 - Add the modules to
R/ui.R
andR/server.R
.
- Utility function:
R/utils_scatter_plot.R
holds thescatter_plot()
utility function.15 - Adding files: The
R/zzz.R
file contains the.onLoad()
function, which wrapssystem.file('img', package = 'lap')
andaddResourcePath()
for including external resources.
R
├── module_plot_display.R
├── module_var_input.R
├── run.R
├── server.R
├── ui.R
└── utils_scatter_plot.R
1 directory, 6 files
24.3.1 Data files
- Including data files: the
movies.RData
data was moved intoinst/extdata
, then loaded intodata/
with the script created withusethis::use_data_raw('movies')
(similar to methods covered in the Data chapter):
data-raw/
└── movies.R
1 directory, 1 file
└── extdata
└── movies.RData
1 directory, 1 file
data
└── movies.rda
1 directory, 1 file
24.3.2 Adding features
The leprechaun
workflow involves a combination of use_
functions that are combined with leprechaun::build()
to add various functionality to your application. I’ll demonstrate three options in the sections below:
24.3.2.1 Use packer
I’ll demo using the make_send_message()
from the JavaScript example on the package website:
- Run
packer::scaffold_leprechaun()
- Don’t be alarmed when calling
packer::scaffold_leprechaun()
downloads multiple folders into the root directory of yourleprechaun
app-package. 16
- Don’t be alarmed when calling
- Run
leprechaun::use_packer()
- Run
leprechaun::build()
This creates inst/tidy-data/packer.R
and inst/assets/index.js
.
inst
├── assets
│ └── index.js
├── dev
│ └── packer.R
├── extdata
│ └── movies.RData
├── img
└── run
└── app.R
Assign the output from make_send_message()
to send_message()
in R/server.R
, then pass the msgId
and text
of the message:
<- function(input, output, session){
server ## New code -->
<- make_send_message(session)
send_message
send_message("show-packer",
text = "this message is from your R/server.R file")
<- var_input_server("vars")
selected_vars
plot_display_server("plot", var_inputs = selected_vars)
## New code <--
}
- 1
-
Create
send_message()
- 2
-
Use
send_message()
to send message the UI.
After loading, documenting, and installing your app-package:
Ctrl/Cmd + Shift + L / D / B
Run the application:
::run() lap
24.3.2.2 Add images
Adding images is simplified with the .onLoad()
function, which I’ll demonstrate by adding the leprechaun.jpg
image file to the UI function.
- Place the
leprechaun.jpg
file ininst/img/
- Add the
img/
path to the code to UI:
$img(
tagssrc = "img/leprechaun.jpg",
height = "25%",
width = "25%")
- run
devtools::load_all()
,devtools::document()
, anddevtools::install()
, then run the application withrun()
:
Ctrl/Cmd + Shift + L / D / B
::run() lap
24.3.2.3 Use Sass
To add Sass styling, I can use leprechaun
’s use_sass()
function
- Run
leprechaun::use_sass()
- a
scss/
folder will be created that contains_core.scss
andmain.scss
scss
├── _core.scss
└── main.scss
1 directory, 2 files
- The original
_core.scss
file is below
html{.error {
color: red
} }
- Change the
color:
fromred
to green (#38B44A
) using$accent: #38B44A;
$accent: #38B44A;
html{
h1 {color: $accent;
} }
- Save this file and run
leprechaun::build()
:17
::build() leprechaun
✔ Running packer.R
✔ Bundled
✔ Running sass.R
- Once again, run
devtools::load_all()
,devtools::document()
, anddevtools::install()
, then run the application withrun()
:
Ctrl/Cmd + Shift + L / D / B
::run() lap
24.3.2.4 New root
folders
It’s important to note that adding features to your leprechaun
app-package will add non-standard directories to the root folder:
├── node_modules/ <- too many sub-folders to list here!
├── package-lock.json
├── package.json
├── scss/
│ ├── _core.scss
│ └── main.scss
├── srcjs/
│ ├── config
│ ├── index.js
│ └── modules
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
These folders are necessary for adding JavaScript/SCSS functionality, so don’t remove them (just make sure they’re added to the .Rbuildignore
/.gitignore
)
24.4 Tests
leprechaun
doesn’t any specific support for testing (like the golem
framework), but we can create tests using any combination of testthat
, testServer()
, and shinytest2
.
24.5 lap
dependencies
It’s also worth noting that using the leprechaun
framework doesn’t add itself as a dependency:
# in the 19_leprechaun branch of sap
::local_deps_explain(deps = 'leprechaun', root = ".") pak
x leprechaun
Recap
Remember to provide a list of fields to
usethis::create_package()
for theDESCRIPTION
file (or edit this manually).↩︎leprechaun::scaffold()
has arguments forui
(fluidPage
ornavbarPage
)bs_version
(bootstrap version) andoverwrite
(if you need to start over).↩︎Link to
R/assets.R
file.↩︎Link to
R/ui.R
file.↩︎Link to
R/server.R
file.↩︎Link to
R/zzz.R
file.↩︎Link to
inst/run/app.R
file.↩︎leprechaun
modules do not have the same naming conventions asgolem
(or that I’ve recommended throughout this book).↩︎pkgload::load_all()
hasreset
set toTRUE
andhelpers
set toFALSE
.↩︎R/run.R
includes functions for running the production (run()
) and development (run_dev()
) version of the application.↩︎make_send_message()
is inR/leprechaun-utils.R
.↩︎assets()
loads the resources called in theR/assets.R
file with theserveAssets()
function.↩︎The same
scatter_plot()
function fromsap
(i.e, imports.data
fromrlang
)↩︎srcjs/
,package-lock.json
,package.json
,webpack.common.js
,webpack.dev.js
andwebpack.prod.js
are added to the.Rbuildignore
(andnode_modules/
is added to the.gitignore
).↩︎The
scss
folder in the root directory is used byleprechaun::build()
to createinst/tidy-data/sass.R
.↩︎