├── .github
├── .gitignore
└── workflows
│ ├── pr-commands.yaml
│ └── R-CMD-check.yaml
├── vignettes
├── .gitignore
└── truelle.Rmd
├── LICENSE
├── inst
├── WORDLIST
├── app
│ └── www
│ │ ├── favicon.ico
│ │ ├── shiny-fluent.png
│ │ ├── shiny-semantic.png
│ │ ├── semantic-dashboard.png
│ │ └── shinyMobile.svg
├── golem-config.yml
├── templates_server
│ ├── shinyMobile_tabs.R
│ ├── shinydashboard.R
│ ├── semantic.dashboard.R
│ ├── shiny.fluent.R
│ ├── shinyMobile_simple.R
│ ├── shinyMobile_split.R
│ ├── shiny.semantic.R
│ ├── shinymaterial.R
│ └── bs4Dash.R
└── templates_ui
│ ├── shiny.semantic.R
│ ├── shiny.fluent.R
│ ├── shinydashboard.R
│ ├── semantic.dashboard.R
│ ├── shinymaterial.R
│ ├── shinyMobile_simple.R
│ ├── shinyMobile_split.R
│ ├── shinyMobile_tabs.R
│ └── bs4Dash.R
├── tests
├── testthat.R
├── testthat
│ ├── test-app.R
│ └── test-golem-recommended.R
└── spelling.R
├── NEWS.md
├── .gitignore
├── man
├── figures
│ ├── truelle-output.png
│ ├── truelle-project-type.png
│ ├── truelle-ui-template.png
│ ├── golem-package-structure.png
│ ├── truelle-package-options.png
│ └── truelle-project-engine.png
├── createRadioOptions.Rd
├── radio.Rd
└── run_app.Rd
├── .Rbuildignore
├── dev
├── run_dev.R
├── 03_deploy.R
├── 01_start.R
└── 02_dev.R
├── truelle.Rproj
├── NAMESPACE
├── R
├── run_app.R
├── golem_utils_server.R
├── app_config.R
├── utils_helpers.R
├── golem_utils_ui.R
├── app_ui.R
└── app_server.R
├── DESCRIPTION
├── LICENSE.md
├── README.md
├── README.Rmd
└── CODE_OF_CONDUCT.md
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2021
2 | COPYRIGHT HOLDER: David Granjon
3 |
--------------------------------------------------------------------------------
/inst/WORDLIST:
--------------------------------------------------------------------------------
1 | Lifecycle
2 | github
3 | golem
4 | https
5 | reactR
6 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(truelle)
3 |
4 | test_check("truelle")
5 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | # truelle 0.0.0.9000
2 |
3 | * Added a `NEWS.md` file to track changes to the package.
4 |
--------------------------------------------------------------------------------
/inst/app/www/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/inst/app/www/favicon.ico
--------------------------------------------------------------------------------
/tests/testthat/test-app.R:
--------------------------------------------------------------------------------
1 | test_that("multiplication works", {
2 | expect_equal(2 * 2, 4)
3 | })
4 |
--------------------------------------------------------------------------------
/inst/app/www/shiny-fluent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/inst/app/www/shiny-fluent.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .Rdata
4 | .httr-oauth
5 | .DS_Store
6 | inst/doc
7 | /doc/
8 | /Meta/
9 |
--------------------------------------------------------------------------------
/inst/app/www/shiny-semantic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/inst/app/www/shiny-semantic.png
--------------------------------------------------------------------------------
/man/figures/truelle-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/truelle-output.png
--------------------------------------------------------------------------------
/inst/app/www/semantic-dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/inst/app/www/semantic-dashboard.png
--------------------------------------------------------------------------------
/man/figures/truelle-project-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/truelle-project-type.png
--------------------------------------------------------------------------------
/man/figures/truelle-ui-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/truelle-ui-template.png
--------------------------------------------------------------------------------
/man/figures/golem-package-structure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/golem-package-structure.png
--------------------------------------------------------------------------------
/man/figures/truelle-package-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/truelle-package-options.png
--------------------------------------------------------------------------------
/man/figures/truelle-project-engine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RinteRface/truelle/HEAD/man/figures/truelle-project-engine.png
--------------------------------------------------------------------------------
/inst/golem-config.yml:
--------------------------------------------------------------------------------
1 | default:
2 | golem_name: truelle
3 | golem_version: 0.0.0.9000
4 | app_prod: no
5 | production:
6 | app_prod: yes
7 | dev:
8 | golem_wd: !expr here::here()
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 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | ^data-raw$
4 | dev_history.R
5 | ^dev$
6 | $run_dev.*
7 | ^LICENSE\.md$
8 | ^README\.Rmd$
9 | ^CODE_OF_CONDUCT\.md$
10 | ^doc$
11 | ^Meta$
12 | ^\.github$
13 |
--------------------------------------------------------------------------------
/inst/templates_server/shinyMobile_tabs.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinyMobile
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$val <- renderPrint(input$stepper)
10 | }
--------------------------------------------------------------------------------
/dev/run_dev.R:
--------------------------------------------------------------------------------
1 | # Set options here
2 | options(golem.app.prod = FALSE) # TRUE = production mode, FALSE = development mode
3 |
4 | # Detach all loaded packages and clean your environment
5 | golem::detach_all_attached()
6 | # rm(list=ls(all.names = TRUE))
7 |
8 | # Document and reload your package
9 | golem::document_and_reload()
10 |
11 | # Run the application
12 | run_app()
13 |
--------------------------------------------------------------------------------
/inst/templates_server/shinydashboard.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinydashboard
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$plot1 <- renderPlot(
10 | hist(rnorm(input$slider))
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/inst/templates_server/semantic.dashboard.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import semantic.dashboard
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$plot1 <- renderPlot(
10 | hist(rnorm(input$slider))
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/inst/templates_server/shiny.fluent.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shiny.fluent
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$sliderValue <- renderText({
10 | sprintf("Value: %s", input$slider)
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/vignettes/truelle.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "truelle"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{truelle}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | ---
9 |
10 | ```{r, include = FALSE}
11 | knitr::opts_chunk$set(
12 | collapse = TRUE,
13 | comment = "#>"
14 | )
15 | ```
16 |
17 | ```{r setup}
18 | library(truelle)
19 | ```
20 |
--------------------------------------------------------------------------------
/inst/templates_server/shinyMobile_simple.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinyMobile
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$data <- renderTable({
10 | mtcars[, c("mpg", input$variable), drop = FALSE]
11 | }, rownames = TRUE)
12 | }
--------------------------------------------------------------------------------
/truelle.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: XeLaTeX
14 |
15 | BuildType: Package
16 | PackageUseDevtools: Yes
17 | PackageInstallArgs: --no-multiarch --with-keep.source
18 | PackageRoxygenize: rd,collate,namespace
19 |
--------------------------------------------------------------------------------
/inst/templates_server/shinyMobile_split.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinyMobile
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$selected_tab <- renderUI({
10 | HTML(paste0("Selected tab: ", strong(input$menu)))
11 | })
12 |
13 | output$distPlot <- renderPlot({
14 | dist <- rnorm(input$obs)
15 | hist(dist)
16 | })
17 | }
--------------------------------------------------------------------------------
/man/createRadioOptions.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils_helpers.R
3 | \name{createRadioOptions}
4 | \alias{createRadioOptions}
5 | \title{Generates a list of option for \link{f7Radio}}
6 | \usage{
7 | createRadioOptions(choices, selected, inputId)
8 | }
9 | \arguments{
10 | \item{choices}{List of choices.}
11 |
12 | \item{selected}{Selected value}
13 |
14 | \item{inputId}{Radio input id.}
15 | }
16 | \description{
17 | Generates a list of option for \link{f7Radio}
18 | }
19 | \keyword{internal}
20 |
--------------------------------------------------------------------------------
/man/radio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils_helpers.R
3 | \name{f7Radio}
4 | \alias{f7Radio}
5 | \title{Modified Framework7 radio input}
6 | \usage{
7 | f7Radio(inputId, label, choices = NULL, selected = NULL)
8 | }
9 | \arguments{
10 | \item{inputId}{Radio input id.}
11 |
12 | \item{label}{Radio label}
13 |
14 | \item{choices}{List of choices. Must be a nested list.}
15 |
16 | \item{selected}{Selected element. NULL by default.}
17 | }
18 | \description{
19 | \code{f7Radio} creates a radio button input.
20 | }
21 |
--------------------------------------------------------------------------------
/inst/templates_server/shiny.semantic.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shiny.semantic
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | observeEvent(input$button, {
10 | modal <- create_modal(
11 | modal(
12 | id = "simple-modal",
13 | header = h2("Important message"),
14 | "This is an important message!"
15 | ),
16 | show = TRUE,
17 | session = getDefaultReactiveDomain()
18 | )
19 | showModal(modal, session = getDefaultReactiveDomain())
20 | })
21 | }
22 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(f7Radio)
4 | export(run_app)
5 | import(shiny)
6 | import(shinyMobile)
7 | importFrom(callr,r_bg)
8 | importFrom(golem,activate_js)
9 | importFrom(golem,add_resource_path)
10 | importFrom(golem,bundle_resources)
11 | importFrom(golem,favicon)
12 | importFrom(golem,with_golem_options)
13 | importFrom(jsonlite,toJSON)
14 | importFrom(rclipboard,rclipboardSetup)
15 | importFrom(shiny,HTML)
16 | importFrom(shiny,column)
17 | importFrom(shiny,shinyApp)
18 | importFrom(shiny,tagAppendAttributes)
19 | importFrom(shiny,tagList)
20 | importFrom(shiny,tags)
21 | importFrom(shinyAce,aceEditor)
22 | importFrom(shinyAce,updateAceEditor)
23 |
--------------------------------------------------------------------------------
/tests/testthat/test-golem-recommended.R:
--------------------------------------------------------------------------------
1 | test_that("app ui", {
2 | ui <- app_ui()
3 | golem::expect_shinytaglist(ui)
4 | # Check that formals have not been removed
5 | fmls <- formals(app_ui)
6 | for (i in c("request")){
7 | expect_true(i %in% names(fmls))
8 | }
9 | })
10 |
11 | test_that("app server", {
12 | server <- app_server
13 | expect_is(server, "function")
14 | # Check that formals have not been removed
15 | fmls <- formals(app_server)
16 | for (i in c("input", "output", "session")){
17 | expect_true(i %in% names(fmls))
18 | }
19 | })
20 |
21 | # Configure this test to fit your need
22 | test_that(
23 | "app launches",{
24 | golem::expect_running(sleep = 5)
25 | }
26 | )
27 |
--------------------------------------------------------------------------------
/R/run_app.R:
--------------------------------------------------------------------------------
1 | #' Run the Shiny Application
2 | #'
3 | #' @param ... arguments to pass to golem_opts.
4 | #' See `?golem::get_golem_options` for more details.
5 | #' @inheritParams shiny::shinyApp
6 | #'
7 | #' @export
8 | #' @importFrom shiny shinyApp
9 | #' @importFrom golem with_golem_options
10 | run_app <- function(
11 | onStart = NULL,
12 | options = list(),
13 | enableBookmarking = NULL,
14 | uiPattern = "/",
15 | ...
16 | ) {
17 | with_golem_options(
18 | app = runGadget(shinyApp(
19 | ui = app_ui,
20 | server = app_server,
21 | onStart = onStart,
22 | options = options,
23 | enableBookmarking = enableBookmarking,
24 | uiPattern = uiPattern
25 | )),
26 | golem_opts = list(...)
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: truelle
2 | Title: Build tools for {golem}, {packer}, {reactR} and {shiny}
3 | Version: 0.0.0.9000
4 | Authors@R: person('David', 'Granjon', email = 'dgranjon@ymail.com', role = c('cre', 'aut'))
5 | Description: Easily setup a {golem}, {packer}, {reactR} and {shiny} project
6 | with an intuitive Gadget. Perfect if you don't have good memory.
7 | License: MIT + file LICENSE
8 | Imports:
9 | callr,
10 | config (>= 0.3.1),
11 | golem (>= 0.3.1),
12 | jsonlite,
13 | processx,
14 | rclipboard,
15 | rlang,
16 | shiny (>= 1.6.0),
17 | shinyAce,
18 | shinyMobile
19 | Encoding: UTF-8
20 | LazyData: true
21 | RoxygenNote: 7.1.1
22 | Suggests:
23 | rmarkdown,
24 | knitr,
25 | spelling,
26 | testthat (>= 3.0.0)
27 | Config/testthat/edition: 3
28 | Language: en-US
29 | VignetteBuilder: knitr
30 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2021 David Granjon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/R/golem_utils_server.R:
--------------------------------------------------------------------------------
1 | #' Inverted versions of in, is.null and is.na
2 | #'
3 | #' @noRd
4 | #'
5 | #' @examples
6 | #' 1 %not_in% 1:10
7 | #' not_null(NULL)
8 | `%not_in%` <- Negate(`%in%`)
9 |
10 | not_null <- Negate(is.null)
11 |
12 | not_na <- Negate(is.na)
13 |
14 | #' Removes the null from a vector
15 | #'
16 | #' @noRd
17 | #'
18 | #' @example
19 | #' drop_nulls(list(1, NULL, 2))
20 | drop_nulls <- function(x){
21 | x[!sapply(x, is.null)]
22 | }
23 |
24 | #' If x is `NULL`, return y, otherwise return x
25 | #'
26 | #' @param x,y Two elements to test, one potentially `NULL`
27 | #'
28 | #' @noRd
29 | #'
30 | #' @examples
31 | #' NULL %||% 1
32 | "%||%" <- function(x, y){
33 | if (is.null(x)) {
34 | y
35 | } else {
36 | x
37 | }
38 | }
39 |
40 | #' If x is `NA`, return y, otherwise return x
41 | #'
42 | #' @param x,y Two elements to test, one potentially `NA`
43 | #'
44 | #' @noRd
45 | #'
46 | #' @examples
47 | #' NA %||% 1
48 | "%|NA|%" <- function(x, y){
49 | if (is.na(x)) {
50 | y
51 | } else {
52 | x
53 | }
54 | }
55 |
56 | #' Typing reactiveValues is too long
57 | #'
58 | #' @inheritParams reactiveValues
59 | #' @inheritParams reactiveValuesToList
60 | #'
61 | #' @noRd
62 | rv <- shiny::reactiveValues
63 | rvtl <- shiny::reactiveValuesToList
64 |
65 |
--------------------------------------------------------------------------------
/R/app_config.R:
--------------------------------------------------------------------------------
1 | #' Access files in the current app
2 | #'
3 | #' NOTE: If you manually change your package name in the DESCRIPTION,
4 | #' don't forget to change it here too, and in the config file.
5 | #' For a safer name change mechanism, use the `golem::set_golem_name()` function.
6 | #'
7 | #' @param ... character vectors, specifying subdirectory and file(s)
8 | #' within your package. The default, none, returns the root of the app.
9 | #'
10 | #' @noRd
11 | app_sys <- function(...){
12 | system.file(..., package = "truelle")
13 | }
14 |
15 |
16 | #' Read App Config
17 | #'
18 | #' @param value Value to retrieve from the config file.
19 | #' @param config GOLEM_CONFIG_ACTIVE value. If unset, R_CONFIG_ACTIVE.
20 | #' If unset, "default".
21 | #' @param use_parent Logical, scan the parent directory for config file.
22 | #'
23 | #' @noRd
24 | get_golem_config <- function(
25 | value,
26 | config = Sys.getenv(
27 | "GOLEM_CONFIG_ACTIVE",
28 | Sys.getenv(
29 | "R_CONFIG_ACTIVE",
30 | "default"
31 | )
32 | ),
33 | use_parent = TRUE
34 | ){
35 | config::get(
36 | value = value,
37 | config = config,
38 | # Modify this if your config file is somewhere else:
39 | file = app_sys("golem-config.yml"),
40 | use_parent = use_parent
41 | )
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/dev/03_deploy.R:
--------------------------------------------------------------------------------
1 | # Building a Prod-Ready, Robust Shiny Application.
2 | #
3 | # README: each step of the dev files is optional, and you don't have to
4 | # fill every dev scripts before getting started.
5 | # 01_start.R should be filled at start.
6 | # 02_dev.R should be used to keep track of your development during the project.
7 | # 03_deploy.R should be used once you need to deploy your app.
8 | #
9 | #
10 | ######################################
11 | #### CURRENT FILE: DEPLOY SCRIPT #####
12 | ######################################
13 |
14 | # Test your app
15 |
16 | ## Run checks ----
17 | ## Check the package before sending to prod
18 | devtools::check()
19 | rhub::check_for_cran()
20 |
21 | # Deploy
22 |
23 | ## Local, CRAN or Package Manager ----
24 | ## This will build a tar.gz that can be installed locally,
25 | ## sent to CRAN, or to a package manager
26 | devtools::build()
27 |
28 | ## RStudio ----
29 | ## If you want to deploy on RStudio related platforms
30 | golem::add_rstudioconnect_file()
31 | golem::add_shinyappsio_file()
32 | golem::add_shinyserver_file()
33 |
34 | ## Docker ----
35 | ## If you want to deploy via a generic Dockerfile
36 | golem::add_dockerfile()
37 |
38 | ## If you want to deploy to ShinyProxy
39 | golem::add_dockerfile_shinyproxy()
40 |
41 | ## If you want to deploy to Heroku
42 | golem::add_dockerfile_heroku()
43 |
--------------------------------------------------------------------------------
/inst/templates_server/shinymaterial.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinymaterial
7 | #' @import ggplot2
8 | #' @noRd
9 | app_server <- function( input, output, session ) {
10 | output$mtcars_plot <- renderPlot({
11 | plot_output <-
12 | ggplot(
13 | mtcars,
14 | aes(
15 | x = hp,
16 | y = mpg
17 | )
18 | ) +
19 | xlab("Horse Power") +
20 | ylab("Miles Per Gallon") +
21 | geom_point() +
22 | theme(
23 | text = element_text(size = 16)
24 | )
25 |
26 | if(input$facet_cyl){
27 | plot_output <-
28 | plot_output +
29 | facet_wrap(
30 | "cyl"
31 | )
32 | }
33 |
34 | if(input$trend_line){
35 | plot_output <-
36 | plot_output +
37 | stat_smooth(
38 | method = "lm",
39 | se = FALSE
40 | )
41 | }
42 |
43 | if(input$plot_theme == "light"){
44 | plot_output <-
45 | plot_output +
46 | theme_light(base_size = 20)
47 | } else if(input$plot_theme == "dark"){
48 | plot_output <-
49 | plot_output +
50 | theme_dark(base_size = 20)
51 | }
52 |
53 | plot_output
54 | })
55 | }
56 |
--------------------------------------------------------------------------------
/inst/templates_ui/shiny.semantic.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Semantic UI template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shiny.semantic
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | semanticPage(
15 | div(
16 | class = "ui raised segment",
17 | div(
18 | a(class="ui green ribbon label", "Link"),
19 | p("Lorem ipsum, lorem ipsum, lorem ipsum"),
20 | progress("progress", percent = 24, label = "{percent}% complete"),
21 | actionButton("button", "Click me!")
22 | )
23 | )
24 | )
25 | )
26 | }
27 |
28 |
29 | #' Add external Resources to the Application
30 | #'
31 | #' This function is internally used to add external
32 | #' resources inside the Shiny application.
33 | #'
34 | #' @import shiny
35 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
36 | #' @noRd
37 | golem_add_external_resources <- function(){
38 |
39 | add_resource_path(
40 | 'www', app_sys('app/www')
41 | )
42 |
43 | tags$head(
44 | favicon(),
45 | bundle_resources(
46 | path = app_sys('app/www'),
47 | app_title = 'My app'
48 | )
49 | # Add here other external resources
50 | # for example, you can add shinyalert::useShinyalert()
51 | )
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/inst/templates_server/bs4Dash.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import bs4Dash
7 | #' @noRd
8 | app_server <- function( input, output, session ) {
9 | output$plot <- renderPlot({
10 | req(!input$mybox$collapsed)
11 | plot(rnorm(200))
12 | })
13 |
14 | output$box_state <- renderText({
15 | state <- if (input$mybox$collapsed) "collapsed" else "uncollapsed"
16 | paste("My box is", state)
17 | })
18 |
19 | observeEvent(input$toggle_box, {
20 | updateBox("mybox", action = "toggle")
21 | })
22 |
23 | observeEvent(input$remove_box, {
24 | updateBox("mybox", action = "remove")
25 | })
26 |
27 | observeEvent(input$restore_box, {
28 | updateBox("mybox", action = "restore")
29 | })
30 |
31 | observeEvent(input$update_box, {
32 | updateBox(
33 | "mybox",
34 | action = "update",
35 | options = list(
36 | title = h2("New title", dashboardBadge(1, color = "primary")),
37 | status = "danger",
38 | solidHeader = TRUE,
39 | width = 4
40 | )
41 | )
42 | })
43 |
44 | observeEvent(input$mybox$visible, {
45 | collapsed <- if (input$mybox$collapsed) "collapsed" else "uncollapsed"
46 | visible <- if (input$mybox$visible) "visible" else "hidden"
47 | message <- paste("My box is", collapsed, "and", visible)
48 | toast(
49 | title = message,
50 | options = list(
51 | autohide = TRUE,
52 | class = "bg-pink",
53 | position = "topRight"
54 | )
55 | )
56 | })
57 | }
58 |
--------------------------------------------------------------------------------
/man/run_app.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/run_app.R
3 | \name{run_app}
4 | \alias{run_app}
5 | \title{Run the Shiny Application}
6 | \usage{
7 | run_app(
8 | onStart = NULL,
9 | options = list(),
10 | enableBookmarking = NULL,
11 | uiPattern = "/",
12 | ...
13 | )
14 | }
15 | \arguments{
16 | \item{onStart}{A function that will be called before the app is actually run.
17 | This is only needed for \code{shinyAppObj}, since in the \code{shinyAppDir}
18 | case, a \code{global.R} file can be used for this purpose.}
19 |
20 | \item{options}{Named options that should be passed to the \code{runApp} call
21 | (these can be any of the following: "port", "launch.browser", "host", "quiet",
22 | "display.mode" and "test.mode"). You can also specify \code{width} and
23 | \code{height} parameters which provide a hint to the embedding environment
24 | about the ideal height/width for the app.}
25 |
26 | \item{enableBookmarking}{Can be one of \code{"url"}, \code{"server"}, or
27 | \code{"disable"}. The default value, \code{NULL}, will respect the setting from
28 | any previous calls to \code{\link[shiny:enableBookmarking]{enableBookmarking()}}. See \code{\link[shiny:enableBookmarking]{enableBookmarking()}}
29 | for more information on bookmarking your app.}
30 |
31 | \item{uiPattern}{A regular expression that will be applied to each \code{GET}
32 | request to determine whether the \code{ui} should be used to handle the
33 | request. Note that the entire request path must match the regular
34 | expression in order for the match to be considered successful.}
35 |
36 | \item{...}{arguments to pass to golem_opts.
37 | See `?golem::get_golem_options` for more details.}
38 | }
39 | \description{
40 | Run the Shiny Application
41 | }
42 |
--------------------------------------------------------------------------------
/inst/templates_ui/shiny.fluent.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Fluent React UI template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shiny.fluent
9 | #' @importFrom glue glue
10 | #' @noRd
11 | app_ui <- function(request) {
12 | tagList(
13 | # Leave this function for adding external resources
14 | golem_add_external_resources(),
15 | fluentPage(
16 | tags$style(".card { padding: 28px; margin-bottom: 28px; }"),
17 | makeCard(
18 | title = Text(variant = "xxLarge", "Hello world!"),
19 | content = tagList(
20 | Slider.shinyInput("slider", value = 42, min = -100, max = 100),
21 | textOutput("sliderValue")
22 | ),
23 | size = 4,
24 | style = "max-height: 320px;"
25 | )
26 |
27 | )
28 | )
29 | }
30 |
31 |
32 | makeCard <- function(title, content, size = 12, style = "") {
33 | div(
34 | class = glue("card ms-depth-8 ms-sm{size} ms-xl{size}"),
35 | style = style,
36 | Stack(
37 | tokens = list(childrenGap = 5),
38 | Text(variant = "large", title, block = TRUE),
39 | content
40 | )
41 | )
42 | }
43 |
44 |
45 | #' Add external Resources to the Application
46 | #'
47 | #' This function is internally used to add external
48 | #' resources inside the Shiny application.
49 | #'
50 | #' @import shiny
51 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
52 | #' @noRd
53 | golem_add_external_resources <- function(){
54 |
55 | add_resource_path(
56 | 'www', app_sys('app/www')
57 | )
58 |
59 | tags$head(
60 | favicon(),
61 | bundle_resources(
62 | path = app_sys('app/www'),
63 | app_title = 'My app'
64 | )
65 | # Add here other external resources
66 | # for example, you can add shinyalert::useShinyalert()
67 | )
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # truelle
5 |
6 |
10 |
11 | The goal of `{truelle}` is to provide a GUI to the `{golem}` package and
12 | many more.
13 |
14 | ## Installation
15 |
16 | You can install the released version of truelle from
17 | [CRAN](https://CRAN.R-project.org) with:
18 |
19 | ``` r
20 | remotes::install_github("RinteRface/truelle")
21 | ```
22 |
23 | ## Workflow example
24 |
25 | This is a basic example which shows you how to start the `{truelle}`
26 | GUI:
27 |
28 | ``` r
29 | library(truelle)
30 | run_app()
31 | ```
32 |
33 | ### Step 1: project type
34 |
35 | Select **Package** and choose the `{golem}` engine.
36 |
37 | 
38 |
39 | ### Step 2: options
40 |
41 | Provide a valid package path and review project options.
42 |
43 |
44 |
45 | ### Step 3: UI layout
46 |
47 | Select the Shiny layout of your choice.
48 |
49 |
50 |
51 | ### Step 4: code output
52 |
53 | Click on the 🎮 button or copy/paste 📸 the code to your terminal…
54 |
55 | 
56 |
57 | ### Step 5: develop
58 |
59 | - Open the new project.
60 | - Run `devtools::load_all()`.
61 | - Enjoy …
62 |
63 | ## Disclaimer
64 |
65 | For now, only the `{golem}` workflow is supported.
66 |
--------------------------------------------------------------------------------
/.github/workflows/pr-commands.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | issue_comment:
3 | types: [created]
4 | name: Commands
5 | jobs:
6 | document:
7 | if: startsWith(github.event.comment.body, '/document')
8 | name: document
9 | runs-on: macOS-latest
10 | env:
11 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: r-lib/actions/pr-fetch@v1
15 | with:
16 | repo-token: ${{ secrets.GITHUB_TOKEN }}
17 | - uses: r-lib/actions/setup-r@v1
18 | - name: Install dependencies
19 | run: Rscript -e 'install.packages(c("remotes", "roxygen2"))' -e 'remotes::install_deps(dependencies = TRUE)'
20 | - name: Document
21 | run: Rscript -e 'roxygen2::roxygenise()'
22 | - name: commit
23 | run: |
24 | git config --local user.email "actions@github.com"
25 | git config --local user.name "GitHub Actions"
26 | git add man/\* NAMESPACE
27 | git commit -m 'Document'
28 | - uses: r-lib/actions/pr-push@v1
29 | with:
30 | repo-token: ${{ secrets.GITHUB_TOKEN }}
31 | style:
32 | if: startsWith(github.event.comment.body, '/style')
33 | name: style
34 | runs-on: macOS-latest
35 | env:
36 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
37 | steps:
38 | - uses: actions/checkout@v2
39 | - uses: r-lib/actions/pr-fetch@v1
40 | with:
41 | repo-token: ${{ secrets.GITHUB_TOKEN }}
42 | - uses: r-lib/actions/setup-r@v1
43 | - name: Install dependencies
44 | run: Rscript -e 'install.packages("styler")'
45 | - name: Style
46 | run: Rscript -e 'styler::style_pkg()'
47 | - name: commit
48 | run: |
49 | git config --local user.email "actions@github.com"
50 | git config --local user.name "GitHub Actions"
51 | git add \*.R
52 | git commit -m 'Style'
53 | - uses: r-lib/actions/pr-push@v1
54 | with:
55 | repo-token: ${{ secrets.GITHUB_TOKEN }}
56 |
--------------------------------------------------------------------------------
/inst/templates_ui/shinydashboard.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Bootstrap 3 dashboard template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shinydashboard
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | dashboardPage(
15 | dashboardHeader(),
16 | dashboardSidebar(
17 | sidebarMenu(
18 | menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
19 | menuItem("Widgets", tabName = "widgets", icon = icon("th"))
20 | )
21 | ),
22 | dashboardBody(
23 | tabItems(
24 | # First tab content
25 | tabItem(
26 | tabName = "dashboard",
27 | fluidRow(
28 | box(plotOutput("plot1", height = 250)),
29 | box(
30 | title = "Controls",
31 | sliderInput("slider", "Number of observations:", 1, 100, 50)
32 | )
33 | )
34 | ),
35 |
36 | # Second tab content
37 | tabItem(tabName = "widgets", h2("Widgets tab content")
38 | )
39 | )
40 | )
41 | )
42 | )
43 | }
44 |
45 |
46 |
47 |
48 |
49 | #' Add external Resources to the Application
50 | #'
51 | #' This function is internally used to add external
52 | #' resources inside the Shiny application.
53 | #'
54 | #' @import shiny
55 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
56 | #' @noRd
57 | golem_add_external_resources <- function(){
58 |
59 | add_resource_path(
60 | 'www', app_sys('app/www')
61 | )
62 |
63 | tags$head(
64 | favicon(),
65 | bundle_resources(
66 | path = app_sys('app/www'),
67 | app_title = 'My app'
68 | )
69 | # Add here other external resources
70 | # for example, you can add shinyalert::useShinyalert()
71 | )
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/inst/templates_ui/semantic.dashboard.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Semantic dashboard template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import semantic.dashboard
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | dashboardPage(
15 | dashboardHeader(),
16 | dashboardSidebar(
17 | sidebarMenu(
18 | menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
19 | menuItem("Widgets", tabName = "widgets", icon = icon("th"))
20 | )
21 | ),
22 | dashboardBody(
23 | tabItems(
24 | # First tab content
25 | tabItem(
26 | tabName = "dashboard",
27 | fluidRow(
28 | box(plotOutput("plot1", height = 250)),
29 | box(
30 | title = "Controls",
31 | sliderInput("slider", "Number of observations:", 1, 100, 50)
32 | )
33 | )
34 | ),
35 |
36 | # Second tab content
37 | tabItem(tabName = "widgets", h2("Widgets tab content")
38 | )
39 | )
40 | )
41 | )
42 | )
43 | }
44 |
45 |
46 |
47 |
48 |
49 | #' Add external Resources to the Application
50 | #'
51 | #' This function is internally used to add external
52 | #' resources inside the Shiny application.
53 | #'
54 | #' @import shiny
55 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
56 | #' @noRd
57 | golem_add_external_resources <- function(){
58 |
59 | add_resource_path(
60 | 'www', app_sys('app/www')
61 | )
62 |
63 | tags$head(
64 | favicon(),
65 | bundle_resources(
66 | path = app_sys('app/www'),
67 | app_title = 'My app'
68 | )
69 | # Add here other external resources
70 | # for example, you can add shinyalert::useShinyalert()
71 | )
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/inst/templates_ui/shinymaterial.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Materialize CSS template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shinymaterial
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | material_page(
15 | title = "shinymaterial",
16 | tags$br(),
17 | material_row(
18 | material_column(
19 | width = 2,
20 | material_card(
21 | title = "",
22 | depth = 4,
23 | tags$p("By Cylinder"),
24 | material_switch(
25 | input_id = "facet_cyl",
26 | off_label = "No",
27 | on_label = "Yes",
28 | initial_value = TRUE
29 | ),
30 | tags$p("Include Trend Line"),
31 | material_switch(
32 | input_id = "trend_line",
33 | off_label = "No",
34 | on_label = "Yes"
35 | ),
36 | material_radio_button(
37 | input_id = "plot_theme",
38 | label = "Theme",
39 | choices =
40 | c("Light" = "light",
41 | "Dark" = "dark")
42 | )
43 | )
44 | ),
45 | material_column(
46 | width = 9,
47 | material_card(
48 | title = "Power vs Efficiency",
49 | depth = 4,
50 | plotOutput("mtcars_plot")
51 | )
52 | )
53 | )
54 | )
55 | )
56 | }
57 |
58 |
59 | #' Add external Resources to the Application
60 | #'
61 | #' This function is internally used to add external
62 | #' resources inside the Shiny application.
63 | #'
64 | #' @import shiny
65 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
66 | #' @noRd
67 | golem_add_external_resources <- function(){
68 |
69 | add_resource_path(
70 | 'www', app_sys('app/www')
71 | )
72 |
73 | tags$head(
74 | favicon(),
75 | bundle_resources(
76 | path = app_sys('app/www'),
77 | app_title = 'My app'
78 | )
79 | # Add here other external resources
80 | # for example, you can add shinyalert::useShinyalert()
81 | )
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/README.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | output: github_document
3 | ---
4 |
5 |
6 |
7 | ```{r, include = FALSE}
8 | knitr::opts_chunk$set(
9 | collapse = TRUE,
10 | comment = "#>",
11 | #fig.path = "man/figures/README-",
12 | out.width = "100%"
13 | )
14 | ```
15 |
16 | # truelle
17 |
18 |
22 |
23 | The goal of `{truelle}` is to provide a GUI to the `{golem}` package and many more.
24 |
25 | ## Installation
26 |
27 | You can install the released version of truelle from [CRAN](https://CRAN.R-project.org) with:
28 |
29 | ``` r
30 | remotes::install_github("RinteRface/truelle")
31 | ```
32 |
33 | ## Workflow example
34 |
35 | This is a basic example which shows you how to start the `{truelle}` GUI:
36 |
37 | ```{r, eval=FALSE, example}
38 | library(truelle)
39 | run_app()
40 | ```
41 |
42 | ### Step 1: project type
43 |
44 | Select __Package__ and choose the `{golem}` engine.
45 |
46 | ```{r, echo = FALSE, fig.show="hold", out.width="50%"}
47 | knitr::include_graphics("man/figures/truelle-project-type.png")
48 | knitr::include_graphics("man/figures/truelle-project-engine.png")
49 | ```
50 |
51 | ### Step 2: options
52 |
53 | Provide a valid package path and review project options.
54 |
55 | ```{r, echo = FALSE, out.width='50%', fig.align='center'}
56 | knitr::include_graphics("man/figures/truelle-package-options.png")
57 | ```
58 |
59 |
60 | ### Step 3: UI layout
61 |
62 | Select the Shiny layout of your choice.
63 |
64 | ```{r, echo = FALSE, out.width='50%', fig.align='center'}
65 | knitr::include_graphics("man/figures/truelle-ui-template.png")
66 | ```
67 |
68 |
69 | ### Step 4: code output
70 |
71 | Click on the `r emo::ji("play")` button or copy/paste `r emo::ji("photo")` the code to your terminal...
72 |
73 | ```{r, echo = FALSE, fig.show="hold", out.width="50%"}
74 | knitr::include_graphics("man/figures/truelle-output.png")
75 | knitr::include_graphics("man/figures/golem-package-structure.png")
76 | ```
77 |
78 |
79 | ### Step 5: develop
80 |
81 | - Open the new project.
82 | - Run `devtools::load_all()`.
83 | - Enjoy ...
84 |
85 | ## Disclaimer
86 |
87 | For now, only the `{golem}` workflow is supported.
--------------------------------------------------------------------------------
/dev/01_start.R:
--------------------------------------------------------------------------------
1 | # Building a Prod-Ready, Robust Shiny Application.
2 | #
3 | # README: each step of the dev files is optional, and you don't have to
4 | # fill every dev scripts before getting started.
5 | # 01_start.R should be filled at start.
6 | # 02_dev.R should be used to keep track of your development during the project.
7 | # 03_deploy.R should be used once you need to deploy your app.
8 | #
9 | #
10 | ########################################
11 | #### CURRENT FILE: ON START SCRIPT #####
12 | ########################################
13 |
14 | ## Fill the DESCRIPTION ----
15 | ## Add meta data about your application
16 | ##
17 | ## /!\ Note: if you want to change the name of your app during development,
18 | ## either re-run this function, call golem::set_golem_name(), or don't forget
19 | ## to change the name in the app_sys() function in app_config.R /!\
20 | ##
21 | golem::fill_desc(
22 | pkg_name = "truelle", # The Name of the package containing the App
23 | pkg_title = "Build tools for {golem}, {packer}, {reactR} and {shiny}", # The Title of the package containing the App
24 | pkg_description = "Easily setup a {golem}, {packer}, {reactR} and {shiny} project
25 | with an intuitive Gadget. Perfect if you don't have good memory.", # The Description of the package containing the App
26 | author_first_name = "David", # Your First Name
27 | author_last_name = "Granjon", # Your Last Name
28 | author_email = "dgranjon@ymail.com", # Your Email
29 | repo_url = NULL # The URL of the GitHub Repo (optional)
30 | )
31 |
32 | ## Set {golem} options ----
33 | golem::set_golem_options()
34 |
35 | ## Create Common Files ----
36 | ## See ?usethis for more information
37 | usethis::use_mit_license( "David Granjon" ) # You can set another license here
38 | usethis::use_readme_rmd( open = FALSE )
39 | usethis::use_code_of_conduct()
40 | usethis::use_lifecycle_badge( "Experimental" )
41 | usethis::use_news_md( open = FALSE )
42 |
43 | ## Use git ----
44 | usethis::use_git()
45 |
46 | ## Init Testing Infrastructure ----
47 | ## Create a template for tests
48 | golem::use_recommended_tests()
49 |
50 | ## Use Recommended Packages ----
51 | golem::use_recommended_deps()
52 |
53 | ## Favicon ----
54 | # If you want to change the favicon (default is golem's one)
55 | golem::use_favicon() # path = "path/to/ico". Can be an online file.
56 | golem::remove_favicon()
57 |
58 | ## Add helper functions ----
59 | golem::use_utils_ui()
60 | golem::use_utils_server()
61 |
62 | # You're now set! ----
63 |
64 | # go to dev/02_dev.R
65 | rstudioapi::navigateToFile( "dev/02_dev.R" )
66 |
67 |
--------------------------------------------------------------------------------
/inst/templates_ui/shinyMobile_simple.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' shinyMobile single layout template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shinyMobile
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | f7Page(
15 | allowPWA = FALSE,
16 | options = list(
17 | theme = c("ios", "md", "auto", "aurora"),
18 | dark = TRUE,
19 | filled = FALSE,
20 | color = "#007aff",
21 | touch = list(
22 | tapHold = TRUE,
23 | tapHoldDelay = 750,
24 | iosTouchRipple = FALSE
25 | ),
26 | iosTranslucentBars = FALSE,
27 | navbar = list(
28 | iosCenterTitle = TRUE,
29 | hideOnPageScroll = TRUE
30 | ),
31 | toolbar = list(hideOnPageScroll = FALSE),
32 | pullToRefresh = FALSE
33 | ),
34 | title = "My app",
35 | f7SingleLayout(
36 | navbar = f7Navbar(
37 | title = "Single Layout",
38 | hairline = TRUE,
39 | shadow = TRUE
40 | ),
41 | toolbar = f7Toolbar(
42 | position = "bottom",
43 | f7Link(label = "Link 1", href = "https://www.google.com"),
44 | f7Link(label = "Link 2", href = "https://www.google.com")
45 | ),
46 | # main content
47 | f7Shadow(
48 | intensity = 16,
49 | hover = TRUE,
50 | f7Card(
51 | title = "Card header",
52 | f7CheckboxGroup(
53 | inputId = "variable",
54 | label = "Choose a variable:",
55 | choices = colnames(mtcars)[-1],
56 | selected = NULL
57 | ),
58 | tableOutput("data")
59 | )
60 | )
61 | )
62 | )
63 | )
64 | }
65 |
66 |
67 |
68 |
69 |
70 | #' Add external Resources to the Application
71 | #'
72 | #' This function is internally used to add external
73 | #' resources inside the Shiny application.
74 | #'
75 | #' @import shiny
76 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
77 | #' @noRd
78 | golem_add_external_resources <- function(){
79 |
80 | add_resource_path(
81 | 'www', app_sys('app/www')
82 | )
83 |
84 | tags$head(
85 | favicon(),
86 | bundle_resources(
87 | path = app_sys('app/www'),
88 | app_title = 'My app'
89 | )
90 | # Add here other external resources
91 | # for example, you can add shinyalert::useShinyalert()
92 | )
93 | }
94 |
--------------------------------------------------------------------------------
/dev/02_dev.R:
--------------------------------------------------------------------------------
1 | # Building a Prod-Ready, Robust Shiny Application.
2 | #
3 | # README: each step of the dev files is optional, and you don't have to
4 | # fill every dev scripts before getting started.
5 | # 01_start.R should be filled at start.
6 | # 02_dev.R should be used to keep track of your development during the project.
7 | # 03_deploy.R should be used once you need to deploy your app.
8 | #
9 | #
10 | ###################################
11 | #### CURRENT FILE: DEV SCRIPT #####
12 | ###################################
13 |
14 | # Engineering
15 |
16 | ## Dependencies ----
17 | ## Add one line by package you want to add as dependency
18 | usethis::use_package( "thinkr" )
19 |
20 | ## Add modules ----
21 | ## Create a module infrastructure in R/
22 | golem::add_module( name = "name_of_module1" ) # Name of the module
23 | golem::add_module( name = "name_of_module2" ) # Name of the module
24 |
25 | ## Add helper functions ----
26 | ## Creates fct_* and utils_*
27 | golem::add_fct( "helpers" )
28 | golem::add_utils( "helpers" )
29 |
30 | ## External resources
31 | ## Creates .js and .css files at inst/app/www
32 | golem::add_js_file( "script" )
33 | golem::add_js_handler( "handlers" )
34 | golem::add_css_file( "custom" )
35 |
36 | ## Add internal datasets ----
37 | ## If you have data in your package
38 | usethis::use_data_raw( name = "my_dataset", open = FALSE )
39 |
40 | ## Tests ----
41 | ## Add one line by test you want to create
42 | usethis::use_test( "app" )
43 |
44 | # Documentation
45 |
46 | ## Vignette ----
47 | usethis::use_vignette("truelle")
48 | devtools::build_vignettes()
49 |
50 | ## Code Coverage----
51 | ## Set the code coverage service ("codecov" or "coveralls")
52 | usethis::use_coverage()
53 |
54 | # Create a summary readme for the testthat subdirectory
55 | covrpage::covrpage()
56 |
57 | ## CI ----
58 | ## Use this part of the script if you need to set up a CI
59 | ## service for your application
60 | ##
61 | ## (You'll need GitHub there)
62 | usethis::use_github()
63 |
64 | # GitHub Actions
65 | usethis::use_github_action()
66 | # Chose one of the three
67 | # See https://usethis.r-lib.org/reference/use_github_action.html
68 | usethis::use_github_action_check_release()
69 | usethis::use_github_action_check_standard()
70 | usethis::use_github_action_check_full()
71 | # Add action for PR
72 | usethis::use_github_action_pr_commands()
73 |
74 | # Travis CI
75 | usethis::use_travis()
76 | usethis::use_travis_badge()
77 |
78 | # AppVeyor
79 | usethis::use_appveyor()
80 | usethis::use_appveyor_badge()
81 |
82 | # Circle CI
83 | usethis::use_circleci()
84 | usethis::use_circleci_badge()
85 |
86 | # Jenkins
87 | usethis::use_jenkins()
88 |
89 | # GitLab CI
90 | usethis::use_gitlab_ci()
91 |
92 | # You're now set! ----
93 | # go to dev/03_deploy.R
94 | rstudioapi::navigateToFile("dev/03_deploy.R")
95 |
96 |
--------------------------------------------------------------------------------
/inst/templates_ui/shinyMobile_split.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' shinyMobile split layout template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shinyMobile
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | f7Page(
15 | allowPWA = FALSE,
16 | options = list(
17 | theme = c("ios", "md", "auto", "aurora"),
18 | dark = TRUE,
19 | filled = FALSE,
20 | color = "#007aff",
21 | touch = list(
22 | tapHold = TRUE,
23 | tapHoldDelay = 750,
24 | iosTouchRipple = FALSE
25 | ),
26 | iosTranslucentBars = FALSE,
27 | navbar = list(
28 | iosCenterTitle = TRUE,
29 | hideOnPageScroll = TRUE
30 | ),
31 | toolbar = list(hideOnPageScroll = FALSE),
32 | pullToRefresh = FALSE
33 | ),
34 | title = "My app",
35 | f7SplitLayout(
36 | sidebar = f7Panel(
37 | id = "sidebar",
38 | title = "Sidebar",
39 | side = "left",
40 | theme = "dark",
41 | f7PanelMenu(
42 | id = "menu",
43 | f7PanelItem(
44 | tabName = "tab1",
45 | title = "Tab 1",
46 | icon = f7Icon("envelope"),
47 | active = TRUE
48 | ),
49 | f7PanelItem(
50 | tabName = "tab2",
51 | title = "Tab 2",
52 | icon = f7Icon("house")
53 | )
54 | ),
55 | uiOutput("selected_tab")
56 | ),
57 | navbar = f7Navbar(
58 | title = "Split Layout",
59 | hairline = FALSE,
60 | shadow = TRUE
61 | ),
62 | toolbar = f7Toolbar(
63 | position = "bottom",
64 | f7Link(label = "Link 1", href = "https://www.google.com"),
65 | f7Link(label = "Link 2", href = "https://www.google.com")
66 | ),
67 | # main content
68 | f7Items(
69 | f7Item(
70 | tabName = "tab1",
71 | f7Slider("obs", "Number of observations:",
72 | min = 0, max = 1000, value = 500
73 | ),
74 | plotOutput("distPlot")
75 | ),
76 | f7Item(tabName = "tab2", "Tab 2 content")
77 | )
78 | )
79 | )
80 | )
81 | }
82 |
83 |
84 |
85 |
86 |
87 | #' Add external Resources to the Application
88 | #'
89 | #' This function is internally used to add external
90 | #' resources inside the Shiny application.
91 | #'
92 | #' @import shiny
93 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
94 | #' @noRd
95 | golem_add_external_resources <- function(){
96 |
97 | add_resource_path(
98 | 'www', app_sys('app/www')
99 | )
100 |
101 | tags$head(
102 | favicon(),
103 | bundle_resources(
104 | path = app_sys('app/www'),
105 | app_title = 'My app'
106 | )
107 | # Add here other external resources
108 | # for example, you can add shinyalert::useShinyalert()
109 | )
110 | }
111 |
--------------------------------------------------------------------------------
/inst/templates_ui/shinyMobile_tabs.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' shinyMobile tabs layout template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import shinyMobile
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | f7Page(
15 | allowPWA = FALSE,
16 | options = list(
17 | theme = c("ios", "md", "auto", "aurora"),
18 | dark = TRUE,
19 | filled = FALSE,
20 | color = "#007aff",
21 | touch = list(
22 | tapHold = TRUE,
23 | tapHoldDelay = 750,
24 | iosTouchRipple = FALSE
25 | ),
26 | iosTranslucentBars = FALSE,
27 | navbar = list(
28 | iosCenterTitle = TRUE,
29 | hideOnPageScroll = TRUE
30 | ),
31 | toolbar = list(hideOnPageScroll = FALSE),
32 | pullToRefresh = FALSE
33 | ),
34 | title = "My app",
35 | f7TabLayout(
36 | panels = tagList(
37 | f7Panel(
38 | title = "Left Panel",
39 | side = "left",
40 | theme = "light",
41 | "Blabla",
42 | effect = "cover"
43 | ),
44 | f7Panel(
45 | title = "Right Panel",
46 | side = "right",
47 | theme = "dark",
48 | "Blabla",
49 | effect = "reveal"
50 | )
51 | ),
52 | navbar = f7Navbar(
53 | title = "Tabs",
54 | hairline = TRUE,
55 | shadow = TRUE,
56 | leftPanel = TRUE,
57 | rightPanel = TRUE
58 | ),
59 | f7Tabs(
60 | animated = TRUE,
61 | f7Tab(
62 | tabName = "Tab 1",
63 | icon = f7Icon("folder"),
64 | active = TRUE,
65 | f7Stepper(
66 | inputId = "stepper",
67 | label = "My stepper",
68 | min = 0,
69 | max = 10,
70 | size = "small",
71 | value = 4,
72 | wraps = TRUE,
73 | autorepeat = TRUE,
74 | rounded = FALSE,
75 | raised = FALSE,
76 | manual = FALSE
77 | ),
78 | verbatimTextOutput("val")
79 | ),
80 | f7Tab(
81 | tabName = "Tab 2",
82 | icon = f7Icon("keyboard"),
83 | active = FALSE,
84 | "Tab 2"
85 | ),
86 | f7Tab(
87 | tabName = "Tab 3",
88 | icon = f7Icon("layers_alt"),
89 | active = FALSE,
90 | "Tab 3"
91 | )
92 | )
93 | )
94 | )
95 | )
96 | }
97 |
98 |
99 |
100 |
101 |
102 | #' Add external Resources to the Application
103 | #'
104 | #' This function is internally used to add external
105 | #' resources inside the Shiny application.
106 | #'
107 | #' @import shiny
108 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
109 | #' @noRd
110 | golem_add_external_resources <- function(){
111 |
112 | add_resource_path(
113 | 'www', app_sys('app/www')
114 | )
115 |
116 | tags$head(
117 | favicon(),
118 | bundle_resources(
119 | path = app_sys('app/www'),
120 | app_title = 'My app'
121 | )
122 | # Add here other external resources
123 | # for example, you can add shinyalert::useShinyalert()
124 | )
125 | }
126 |
--------------------------------------------------------------------------------
/inst/templates_ui/bs4Dash.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' Bootstrap 4 dashboard template
4 | #'
5 | #' @param request Internal parameter for `{shiny}`.
6 | #' DO NOT REMOVE.
7 | #' @import shiny
8 | #' @import bs4Dash
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | dashboardPage(
15 | title = "Basic Dashboard",
16 | fullscreen = TRUE,
17 | header = dashboardHeader(
18 | title = dashboardBrand(
19 | title = "bs4Dash",
20 | color = "primary",
21 | href = "https://www.google.fr",
22 | image = "https://adminlte.io/themes/AdminLTE/dist/img/user2-160x160.jpg",
23 | ),
24 | skin = "light",
25 | status = "white",
26 | border = TRUE,
27 | sidebarIcon = icon("bars"),
28 | controlbarIcon = icon("th"),
29 | fixed = FALSE
30 | ),
31 | sidebar = dashboardSidebar(
32 | skin = "light",
33 | status = "primary",
34 | elevation = 3,
35 | sidebarUserPanel(
36 | image = "https://image.flaticon.com/icons/svg/1149/1149168.svg",
37 | name = "Welcome Onboard!"
38 | ),
39 | sidebarMenu(
40 | sidebarHeader("Header 1"),
41 | menuItem(
42 | "Item 1",
43 | tabName = "item1",
44 | icon = icon("sliders")
45 | ),
46 | menuItem(
47 | "Item 2",
48 | tabName = "item2",
49 | icon = icon("id-card")
50 | )
51 | )
52 | ),
53 | controlbar = dashboardControlbar(
54 | skin = "light",
55 | pinned = TRUE,
56 | collapsed = FALSE,
57 | overlay = FALSE,
58 | controlbarMenu(
59 | id = "controlbarmenu",
60 | controlbarItem(
61 | title = "Item 1",
62 | "Item 1"
63 | ),
64 | controlbarItem(
65 | "Item 2",
66 | "Simple text"
67 | )
68 | )
69 | ),
70 | footer = dashboardFooter(
71 | left = a(
72 | href = "https://twitter.com/divadnojnarg",
73 | target = "_blank", "@DivadNojnarg"
74 | ),
75 | right = "2021"
76 | ),
77 | body = dashboardBody(
78 | tabItems(
79 | tabItem(
80 | tabName = "item1",
81 | tags$style("body { background-color: ghostwhite}"),
82 | fluidRow(
83 | actionButton("toggle_box", "Toggle Box"),
84 | actionButton("remove_box", "Remove Box", class = "bg-danger"),
85 | actionButton("restore_box", "Restore Box", class = "bg-success"),
86 | actionButton("update_box", "Update Box", class = "bg-primary")
87 | ),
88 | br(),
89 | box(
90 | title = textOutput("box_state"),
91 | "Box body",
92 | id = "mybox",
93 | collapsible = TRUE,
94 | closable = TRUE,
95 | plotOutput("plot")
96 | )
97 | ),
98 | tabItem(
99 | tabName = "item2",
100 | "Body content 2"
101 | )
102 | )
103 | )
104 | )
105 | )
106 | }
107 |
108 |
109 |
110 |
111 |
112 | #' Add external Resources to the Application
113 | #'
114 | #' This function is internally used to add external
115 | #' resources inside the Shiny application.
116 | #'
117 | #' @import shiny
118 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
119 | #' @noRd
120 | golem_add_external_resources <- function(){
121 |
122 | add_resource_path(
123 | 'www', app_sys('app/www')
124 | )
125 |
126 | tags$head(
127 | favicon(),
128 | bundle_resources(
129 | path = app_sys('app/www'),
130 | app_title = 'My app'
131 | )
132 | # Add here other external resources
133 | # for example, you can add shinyalert::useShinyalert()
134 | )
135 | }
136 |
137 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # NOTE: This workflow is overkill for most R packages
2 | # check-standard.yaml is likely a better choice
3 | # usethis::use_github_action("check-standard") will install it.
4 | #
5 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
6 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
7 | on:
8 | push:
9 | branches:
10 | - main
11 | - master
12 | pull_request:
13 | branches:
14 | - main
15 | - master
16 |
17 | name: R-CMD-check
18 |
19 | jobs:
20 | R-CMD-check:
21 | runs-on: ${{ matrix.config.os }}
22 |
23 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
24 |
25 | strategy:
26 | fail-fast: false
27 | matrix:
28 | config:
29 | - {os: macOS-latest, r: 'release'}
30 | - {os: windows-latest, r: 'release'}
31 | - {os: windows-latest, r: '3.6', rspm: "https://packagemanager.rstudio.com/cran/latest"}
32 | - {os: ubuntu-18.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest", http-user-agent: "R/4.0.0 (ubuntu-18.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions" }
33 | - {os: ubuntu-18.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
34 | - {os: ubuntu-18.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
35 | - {os: ubuntu-18.04, r: '3.6', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
36 | - {os: ubuntu-18.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
37 | - {os: ubuntu-18.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest"}
38 |
39 | env:
40 | RSPM: ${{ matrix.config.rspm }}
41 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
42 |
43 | steps:
44 | - uses: actions/checkout@v2
45 |
46 | - uses: r-lib/actions/setup-r@v1
47 | id: install-r
48 | with:
49 | r-version: ${{ matrix.config.r }}
50 | http-user-agent: ${{ matrix.config.http-user-agent }}
51 |
52 | - uses: r-lib/actions/setup-pandoc@v1
53 |
54 | - name: Install pak and query dependencies
55 | run: |
56 | install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")
57 | saveRDS(pak::pkg_deps("local::.", dependencies = TRUE), ".github/r-depends.rds")
58 | shell: Rscript {0}
59 |
60 | - name: Restore R package cache
61 | uses: actions/cache@v2
62 | with:
63 | path: |
64 | ${{ env.R_LIBS_USER }}/*
65 | !${{ env.R_LIBS_USER }}/pak
66 | key: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-${{ hashFiles('.github/r-depends.rds') }}
67 | restore-keys: ${{ matrix.config.os }}-${{ steps.install-r.outputs.installed-r-version }}-1-
68 |
69 | - name: Install system dependencies
70 | if: runner.os == 'Linux'
71 | run: |
72 | pak::local_system_requirements(execute = TRUE)
73 | pak::pkg_system_requirements("rcmdcheck", execute = TRUE)
74 | shell: Rscript {0}
75 |
76 | - name: Install dependencies
77 | run: |
78 | pak::local_install_dev_deps(upgrade = TRUE)
79 | pak::pkg_install("rcmdcheck")
80 | shell: Rscript {0}
81 |
82 | - name: Session info
83 | run: |
84 | options(width = 100)
85 | pkgs <- installed.packages()[, "Package"]
86 | sessioninfo::session_info(pkgs, include_base = TRUE)
87 | shell: Rscript {0}
88 |
89 | - name: Check
90 | env:
91 | _R_CHECK_CRAN_INCOMING_: false
92 | run: |
93 | options(crayon.enabled = TRUE)
94 | rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
95 | shell: Rscript {0}
96 |
97 | - name: Show testthat output
98 | if: always()
99 | run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true
100 | shell: bash
101 |
102 | - name: Upload check results
103 | if: failure()
104 | uses: actions/upload-artifact@main
105 | with:
106 | name: ${{ matrix.config.os }}-r${{ matrix.config.r }}-results
107 | path: check
108 |
109 | - name: Don't use tar from old Rtools to store the cache
110 | if: ${{ runner.os == 'Windows' && startsWith(steps.install-r.outputs.installed-r-version, '3.6' ) }}
111 | shell: bash
112 | run: echo "C:/Program Files/Git/usr/bin" >> $GITHUB_PATH
113 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards
42 | of acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies
54 | when an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail
56 | address, posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at [INSERT CONTACT
63 | METHOD]. All complaints will be reviewed and investigated promptly and fairly.
64 |
65 | All community leaders are obligated to respect the privacy and security of the
66 | reporter of any incident.
67 |
68 | ## Enforcement Guidelines
69 |
70 | Community leaders will follow these Community Impact Guidelines in determining
71 | the consequences for any action they deem in violation of this Code of Conduct:
72 |
73 | ### 1. Correction
74 |
75 | **Community Impact**: Use of inappropriate language or other behavior deemed
76 | unprofessional or unwelcome in the community.
77 |
78 | **Consequence**: A private, written warning from community leaders, providing
79 | clarity around the nature of the violation and an explanation of why the
80 | behavior was inappropriate. A public apology may be requested.
81 |
82 | ### 2. Warning
83 |
84 | **Community Impact**: A violation through a single incident or series of
85 | actions.
86 |
87 | **Consequence**: A warning with consequences for continued behavior. No
88 | interaction with the people involved, including unsolicited interaction with
89 | those enforcing the Code of Conduct, for a specified period of time. This
90 | includes avoiding interactions in community spaces as well as external channels
91 | like social media. Violating these terms may lead to a temporary or permanent
92 | ban.
93 |
94 | ### 3. Temporary Ban
95 |
96 | **Community Impact**: A serious violation of community standards, including
97 | sustained inappropriate behavior.
98 |
99 | **Consequence**: A temporary ban from any sort of interaction or public
100 | communication with the community for a specified period of time. No public or
101 | private interaction with the people involved, including unsolicited interaction
102 | with those enforcing the Code of Conduct, is allowed during this period.
103 | Violating these terms may lead to a permanent ban.
104 |
105 | ### 4. Permanent Ban
106 |
107 | **Community Impact**: Demonstrating a pattern of violation of community
108 | standards, including sustained inappropriate behavior, harassment of an
109 | individual, or aggression toward or disparagement of classes of individuals.
110 |
111 | **Consequence**: A permanent ban from any sort of public interaction within the
112 | community.
113 |
114 | ## Attribution
115 |
116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117 | version 2.0,
118 | available at https://www.contributor-covenant.org/version/2/0/
119 | code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at https://
128 | www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/R/utils_helpers.R:
--------------------------------------------------------------------------------
1 | pkg_description_fields <- list(
2 | pkg_name = "shinyexample", # The Name of the package containing the App
3 | pkg_title = "PKG_TITLE", # The Title of the package containing the App
4 | pkg_description = "PKG_DESC.", # The Description of the package containing the App
5 | author_first_name = "AUTHOR_FIRST", # Your First Name
6 | author_last_name = "AUTHOR_LAST", # Your Last Name
7 | author_email = "AUTHOR@MAIL.COM", # Your Email
8 | repo_url = NULL
9 | )
10 |
11 | usethis_commons <- list(
12 | project = " usethis::use_rstudio()",
13 | license = ' usethis::use_mit_license( "Golem User" )',
14 | readme = " usethis::use_readme_rmd( open = FALSE )",
15 | coc = " usethis::use_code_of_conduct()",
16 | lifecycle = ' usethis::use_lifecycle_badge( "Experimental" )',
17 | news = " usethis::use_news_md( open = FALSE )",
18 | data = " usethis::use_data_raw()",
19 | git = " usethis::use_git()"
20 | )
21 |
22 |
23 | webdev_commons <- list(
24 | input_binding = paste0(
25 | " golem::add_js_input_binding( \n",
26 | ' "myInputBinding", \n',
27 | " initialize = FALSE, \n",
28 | " dev = FALSE, \n",
29 | ' events = list(name = "click", rate_policy = FALSE) \n',
30 | " )",
31 | collapse = "\n"
32 | ),
33 | output_binding = ' golem::add_js_output_binding("myOutputBinding")',
34 | js_handler = ' golem::add_js_handler("script")',
35 | simple_js = ' golem::add_js_file("script")',
36 | simple_css = ' golem::add_css_file("custom")'
37 | )
38 |
39 | jobs <- list()
40 |
41 | run_text <- function(code) eval(parse(text = code))
42 |
43 |
44 | # dropNulls
45 | dropNulls <- function(x) {
46 | x[!vapply(x, is.null, FUN.VALUE = logical(1))]
47 | }
48 |
49 | # transform list to char
50 | list_2_char <- function(l, prefix, input) {
51 | temp <- lapply(seq_along(l), function(i) {
52 | if (input[[paste0(prefix, names(l)[[i]])]]) {
53 | l[[i]]
54 | }
55 | }) %>%
56 | dropNulls() %>%
57 | paste0(collapse = "\n")
58 |
59 | if (nchar(temp) > 0) temp <- paste0(temp, "\n \n", collapse = "\n")
60 | temp
61 | }
62 |
63 |
64 | # Copy a file template to the R folder to
65 | # replace the default app_ui.R provided by {golem}
66 | add_ui_template <- function(template) {
67 |
68 | pkg_to_import <- strsplit(template, "_")[[1]][1]
69 |
70 | paste0(
71 | ' unlink("R/app_ui.R", TRUE, TRUE) \n',
72 | ' file.copy( \n',
73 | ' system.file( \n',
74 | ' "templates_ui/', template, '.R", \n',
75 | ' package = "truelle" \n',
76 | ' ), \n',
77 | ' "R/app_ui.R" \n',
78 | ' ) \n',
79 | ' unlink("R/app_server.R", TRUE, TRUE) \n',
80 | ' file.copy( \n',
81 | ' system.file( \n',
82 | ' "templates_server/', template, '.R", \n',
83 | ' package = "truelle" \n',
84 | ' ), \n',
85 | ' "R/app_server.R" \n',
86 | ' ) \n',
87 | if (pkg_to_import != "golem") ' usethis::use_package("', pkg_to_import, '") \n',
88 | ' devtools::document() \n',
89 | collapse = "\n"
90 | )
91 | }
92 |
93 |
94 | #' Modified Framework7 radio input
95 | #'
96 | #' \code{f7Radio} creates a radio button input.
97 | #'
98 | #' @param inputId Radio input id.
99 | #' @param label Radio label
100 | #' @param choices List of choices. Must be a nested list.
101 | #' @param selected Selected element. NULL by default.
102 | #'
103 | #' @export
104 | #' @rdname radio
105 | f7Radio <- function(inputId, label, choices = NULL, selected = NULL) {
106 |
107 | shiny::tagList(
108 | shiny::tags$div(
109 | class = "block-title",
110 | label
111 | ),
112 | shiny::tags$div(
113 | class = "list media-list shiny-input-radiogroup",
114 | id = inputId,
115 | createRadioOptions(choices, selected, inputId)
116 | )
117 | )
118 |
119 | }
120 |
121 |
122 | #' Generates a list of option for \link{f7Radio}
123 | #'
124 | #' @param choices List of choices.
125 | #' @param selected Selected value
126 | #' @param inputId Radio input id.
127 | #'
128 | #' @keywords internal
129 | createRadioOptions <- function(choices, selected, inputId) {
130 | titles <- unlist(lapply(seq_along(choices), function (c) choices[[c]]$title))
131 | selectedPosition <- if (!is.null(selected)) match(selected, titles) else NULL
132 |
133 | choicesTag <- lapply(X = seq_along(choices), function(i) {
134 | shiny::tags$li(
135 | shiny::tags$label(
136 | class = "item-radio item-radio-icon-start item-content",
137 | shiny::tags$input(
138 | type = "radio",
139 | name = inputId,
140 | value = choices[[i]]$title
141 | ),
142 | shiny::tags$i(class = "icon icon-radio"),
143 | shiny::tags$div(
144 | class = "item-inner",
145 | shiny::tags$div(
146 | class = "item-title-row",
147 | shiny::tags$div(class="item-title", choices[[i]]$title),
148 | shiny::tags$div(
149 | class = "item-after item-media",
150 | choices[[i]]$image
151 | )
152 | ),
153 | shiny::tags$div(class = "item-subtitle", choices[[i]]$subtitle),
154 | shiny::tags$div(class = "item-text", choices[[i]]$text)
155 | )
156 | )
157 | )
158 | })
159 |
160 | if (!is.null(selected)) choicesTag[[selectedPosition]]$children[[1]]$children[[1]]$attribs[["checked"]] <- NA
161 |
162 | shiny::tags$ul(choicesTag)
163 | }
164 |
165 |
166 | # Custom clipboard button
167 | rclipButton <- function (inputId, label, clipText, icon = NULL, modal = FALSE)
168 | {
169 |
170 | el <- a(
171 | id = inputId,
172 | class = "button button-small action-button display-flex margin-left-half",
173 | tagList(label, icon)
174 | )
175 | el$attribs$`data-clipboard-text` <- clipText
176 | tagList(
177 | el,
178 | if (modal) {
179 | tags$script(
180 | sprintf(
181 | "new ClipboardJS(\".button\", { container: document.getElementById(\"%s\") } ); ",
182 | inputId
183 | )
184 | )
185 | }
186 | else {
187 | tags$script(
188 | sprintf(
189 | "new ClipboardJS(\".button\", document.getElementById(\"%s\") );",
190 | inputId
191 | )
192 | )
193 | }
194 | )
195 | }
--------------------------------------------------------------------------------
/R/golem_utils_ui.R:
--------------------------------------------------------------------------------
1 | #' Turn an R list into an HTML list
2 | #'
3 | #' @param list An R list
4 | #' @param class a class for the list
5 | #'
6 | #' @return an HTML list
7 | #' @noRd
8 | #'
9 | #' @examples
10 | #' list_to_li(c("a","b"))
11 | #'
12 | #' @importFrom shiny tags tagAppendAttributes tagList
13 | list_to_li <- function(list, class = NULL){
14 | if (is.null(class)){
15 | tagList(
16 | lapply(
17 | list,
18 | tags$li
19 | )
20 | )
21 | } else {
22 | res <- lapply(
23 | list,
24 | tags$li
25 | )
26 | res <- lapply(
27 | res,
28 | function(x) {
29 | tagAppendAttributes(
30 | x,
31 | class = class
32 | )
33 | }
34 | )
35 | tagList(res)
36 | }
37 |
38 | }
39 | #' Turn an R list into corresponding HTML paragraph tags
40 | #'
41 | #' @param list an R list
42 | #' @param class a class for the paragraph tags
43 | #'
44 | #' @return An HTML tag
45 | #' @noRd
46 | #'
47 | #' @examples
48 | #' list_to_p(c("This is the first paragraph", "this is the second paragraph"))
49 | #'
50 | #' @importFrom shiny tags tagAppendAttributes tagList
51 | #'
52 | list_to_p <- function(list, class = NULL){
53 | if (is.null(class)){
54 | tagList(
55 | lapply(
56 | list,
57 | tags$p
58 | )
59 | )
60 | } else {
61 | res <- lapply(
62 | list,
63 | tags$p
64 | )
65 | res <- lapply(
66 | res,
67 | function(x) {
68 | tagAppendAttributes(
69 | x,
70 | class = class
71 | )
72 | }
73 | )
74 | tagList(res)
75 | }
76 |
77 | }
78 |
79 | #' @importFrom shiny tags tagAppendAttributes tagList
80 | named_to_li <- function(list, class = NULL){
81 | if(is.null(class)){
82 | res <- mapply(
83 | function(x, y){
84 | tags$li(
85 | HTML(
86 | sprintf("%s: %s", y, x)
87 | )
88 | )
89 | },
90 | list,
91 | names(list),
92 | SIMPLIFY = FALSE
93 | )
94 | tagList(res)
95 | } else {
96 | res <- mapply(
97 | function(x, y){
98 | tags$li(
99 | HTML(
100 | sprintf("%s: %s", y, x)
101 | )
102 | )
103 | },
104 | list,
105 | names(list),
106 | SIMPLIFY = FALSE
107 | )
108 | res <- lapply(
109 | res,
110 | function(x) {
111 | tagAppendAttributes(
112 | x,
113 | class = class
114 | )
115 | }
116 | )
117 | tagList(res)
118 | }
119 | }
120 |
121 | #' Remove a tag attribute
122 | #'
123 | #' @param tag the tag
124 | #' @param ... the attributes to remove
125 | #'
126 | #' @return a new tag
127 | #' @noRd
128 | #'
129 | #' @examples
130 | #' a <- shiny::tags$p(src = "plop", "pouet")
131 | #' tagRemoveAttributes(a, "src")
132 | tagRemoveAttributes <- function(tag, ...) {
133 | attrs <- as.character(list(...))
134 | for (i in seq_along(attrs)) {
135 | tag$attribs[[ attrs[i] ]] <- NULL
136 | }
137 | tag
138 | }
139 |
140 | #' Hide or display a tag
141 | #'
142 | #' @param tag the tag
143 | #'
144 | #' @return a tag
145 | #' @noRd
146 | #'
147 | #' @examples
148 | #' ## Hide
149 | #' a <- shiny::tags$p(src = "plop", "pouet")
150 | #' undisplay(a)
151 | #' b <- shiny::actionButton("go_filter", "go")
152 | #' undisplay(b)
153 | #'
154 | #' @importFrom shiny tagList
155 | undisplay <- function(tag) {
156 | # if not already hidden
157 | if (
158 | !is.null(tag$attribs$style) &&
159 | !grepl("display:\\s+none", tag$attribs$style)
160 | ) {
161 | tag$attribs$style <- paste(
162 | "display: none;",
163 | tag$attribs$style
164 | )
165 | } else {
166 | tag$attribs$style <- "display: none;"
167 | }
168 | tag
169 | }
170 |
171 | #' @importFrom shiny tagList
172 | display <- function(tag) {
173 | if (
174 | !is.null(tag$attribs$style) &&
175 | grepl("display:\\s+none", tag$attribs$style)
176 | ) {
177 | tag$attribs$style <- gsub(
178 | "(\\s)*display:(\\s)*none(\\s)*(;)*(\\s)*",
179 | "",
180 | tag$attribs$style
181 | )
182 | }
183 | tag
184 | }
185 |
186 | #' Hide an elements by calling jquery hide on it
187 | #'
188 | #' @param id the id of the element to hide
189 | #'
190 | #' @noRd
191 | #'
192 | #' @importFrom shiny tags
193 | jq_hide <- function(id) {
194 | tags$script(sprintf("$('#%s').hide()", id))
195 | }
196 |
197 | #' Add a red star at the end of the text
198 | #'
199 | #' Adds a red star at the end of the text
200 | #' (for example for indicating mandatory fields).
201 | #'
202 | #' @param text the HTLM text to put before the red star
203 | #'
204 | #' @return an html element
205 | #' @noRd
206 | #'
207 | #' @examples
208 | #' with_red_star("Enter your name here")
209 | #'
210 | #' @importFrom shiny tags HTML
211 | with_red_star <- function(text) {
212 | shiny::tags$span(
213 | HTML(
214 | paste0(
215 | text,
216 | shiny::tags$span(
217 | style = "color:red", "*"
218 | )
219 | )
220 | )
221 | )
222 | }
223 |
224 |
225 |
226 | #' Repeat tags$br
227 | #'
228 | #' @param times the number of br to return
229 | #'
230 | #' @return the number of br specified in times
231 | #' @noRd
232 | #'
233 | #' @examples
234 | #' rep_br(5)
235 | #'
236 | #' @importFrom shiny HTML
237 | rep_br <- function(times = 1) {
238 | HTML(rep("
", times = times))
239 | }
240 |
241 | #' Create an url
242 | #'
243 | #' @param url the URL
244 | #' @param text the text to display
245 | #'
246 | #' @return an a tag
247 | #' @noRd
248 | #'
249 | #' @examples
250 | #' enurl("https://www.thinkr.fr", "ThinkR")
251 | #'
252 | #' @importFrom shiny tags
253 | enurl <- function(url, text){
254 | tags$a(href = url, text)
255 | }
256 |
257 | #' Columns wrappers
258 | #'
259 | #' These are convenient wrappers around
260 | #' `column(12, ...)`, `column(6, ...)`, `column(4, ...)`...
261 | #'
262 | #' @noRd
263 | #'
264 | #' @importFrom shiny column
265 | col_12 <- function(...){
266 | column(12, ...)
267 | }
268 |
269 | #' @importFrom shiny column
270 | col_10 <- function(...){
271 | column(10, ...)
272 | }
273 |
274 | #' @importFrom shiny column
275 | col_8 <- function(...){
276 | column(8, ...)
277 | }
278 |
279 | #' @importFrom shiny column
280 | col_6 <- function(...){
281 | column(6, ...)
282 | }
283 |
284 |
285 | #' @importFrom shiny column
286 | col_4 <- function(...){
287 | column(4, ...)
288 | }
289 |
290 |
291 | #' @importFrom shiny column
292 | col_3 <- function(...){
293 | column(3, ...)
294 | }
295 |
296 |
297 | #' @importFrom shiny column
298 | col_2 <- function(...){
299 | column(2, ...)
300 | }
301 |
302 |
303 | #' @importFrom shiny column
304 | col_1 <- function(...){
305 | column(1, ...)
306 | }
307 |
308 |
309 |
310 | #' Make the current tag behave like an action button
311 | #'
312 | #' Only works with compatible tags like button or links
313 | #'
314 | #' @param tag Any compatible tag.
315 | #' @param inputId Unique id. This will host the input value to be used
316 | #' on the server side.
317 | #'
318 | #' @return The modified tag with an extra id and the action button class.
319 | #' @noRd
320 | #'
321 | #' @examples
322 | #' if (interactive()) {
323 | #' library(shiny)
324 | #'
325 | #' link <- a(href = "#", "My super link", style = "color: lightblue;")
326 | #'
327 | #' ui <- fluidPage(
328 | #' make_action_button(link, inputId = "mylink")
329 | #' )
330 | #'
331 | #' server <- function(input, output, session) {
332 | #' observeEvent(input$mylink, {
333 | #' showNotification("Pouic!")
334 | #' })
335 | #' }
336 | #'
337 | #' shinyApp(ui, server)
338 | #'
339 | #' }
340 | make_action_button <- function(tag, inputId = NULL) {
341 | # some obvious checks
342 | if (!inherits(tag, "shiny.tag")) stop("Must provide a shiny tag.")
343 | if (!is.null(tag$attribs$class)) {
344 | if (grep("action-button", tag$attribs$class)) {
345 | stop("tag is already an action button")
346 | }
347 | }
348 | if (is.null(inputId) && is.null(tag$attribs$id)) {
349 | stop("tag does not have any id. Please use inputId to be able to
350 | access it on the server side.")
351 | }
352 |
353 | # handle id
354 | if (!is.null(inputId)) {
355 | if (!is.null(tag$attribs$id)) {
356 | warning(
357 | paste(
358 | "tag already has an id. Please use input$",
359 | tag$attribs$id,
360 | "to access it from the server side. inputId will be ignored."
361 | )
362 | )
363 | } else {
364 | tag$attribs$id <- inputId
365 | }
366 | }
367 |
368 | # handle class
369 | if (is.null(tag$attribs$class)) {
370 | tag$attribs$class <- "action-button"
371 | } else {
372 | tag$attribs$class <- paste(tag$attribs$class, "action-button")
373 | }
374 | # return tag
375 | tag
376 | }
377 |
378 |
379 | # UNCOMMENT AND USE
380 | #
381 | # usethis::use_package("markdown")
382 | # usethis::use_package("rmarkdown")
383 | #
384 | # To use this part of the UI
385 | #
386 | #' #' Include Content From a File
387 | #' #'
388 | #' #' Load rendered RMarkdown from a file and turn into HTML.
389 | #' #'
390 | #' #' @rdname includeRMarkdown
391 | #' #' @export
392 | #' #'
393 | #' #' @importFrom rmarkdown render
394 | #' #' @importFrom markdown markdownToHTML
395 | #' #' @importFrom shiny HTML
396 | #' includeRMarkdown <- function(path){
397 | #'
398 | #' md <- tempfile(fileext = '.md')
399 | #'
400 | #' on.exit(unlink(md),add = TRUE)
401 | #'
402 | #' rmarkdown::render(
403 | #' path,
404 | #' output_format = 'md_document',
405 | #' output_dir = tempdir(),
406 | #' output_file = md,quiet = TRUE
407 | #' )
408 | #'
409 | #' html <- markdown::markdownToHTML(md, fragment.only = TRUE)
410 | #'
411 | #' Encoding(html) <- "UTF-8"
412 | #'
413 | #' return(HTML(html))
414 | #' }
415 |
--------------------------------------------------------------------------------
/R/app_ui.R:
--------------------------------------------------------------------------------
1 | #' The application User-Interface
2 | #'
3 | #' @param request Internal parameter for `{shiny}`.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinyMobile
7 | #' @importFrom shinyAce aceEditor
8 | #' @importFrom rclipboard rclipboardSetup
9 | #' @noRd
10 | app_ui <- function(request) {
11 | tagList(
12 | # Leave this function for adding external resources
13 | golem_add_external_resources(),
14 | # Your application UI logic
15 | f7Page(
16 | options = list(
17 | theme = "md",
18 | dark = TRUE,
19 | filled = FALSE,
20 | color = "#007aff",
21 | touch = list(
22 | tapHold = TRUE,
23 | tapHoldDelay = 750,
24 | iosTouchRipple = FALSE
25 | ),
26 | iosTranslucentBars = FALSE,
27 | navbar = list(
28 | iosCenterTitle = TRUE,
29 | hideNavOnPageScroll = TRUE,
30 | mdCenterTitle = TRUE
31 | ),
32 | toolbar = list(
33 | hideNavOnPageScroll = FALSE
34 | ),
35 | pullToRefresh = FALSE
36 | ),
37 | title = "{truelle}",
38 | f7TabLayout(
39 | #panels = tagList(
40 | # f7Panel(title = "Left Panel", side = "left", theme = "light", "Blabla", effect = "cover"),
41 | # f7Panel(title = "Right Panel", side = "right", theme = "dark", "Blabla", effect = "cover")
42 | #),
43 | navbar = f7Navbar(
44 | title = "{truelle}",
45 | hairline = TRUE,
46 | shadow = TRUE,
47 | subNavbar = f7SubNavbar(
48 | f7Flex(
49 | f7Back(targetId = "widget_nav"),
50 | f7Next(targetId = "widget_nav"),
51 | a(
52 | href = "#",
53 | id = "close_app",
54 | class = "button button-small action-button display-flex margin-left-half",
55 | f7Icon("xmark_circle")
56 | ),
57 | a(
58 | class = "button button-small action-button display-flex margin-left-half",
59 | id = "run_code_output",
60 | f7Icon("play")
61 | ),
62 | uiOutput("clip_button"),
63 | a(
64 | class = "button button-small display-flex margin-left-half",
65 | id = "theme_switch",
66 | f7Icon("sun_max")
67 | )
68 | )
69 | )
70 | ),
71 | f7Tabs(
72 | id = "widget_nav",
73 | animated = TRUE,
74 | f7Tab(
75 | tabName = "Home",
76 | icon = f7Icon("house"),
77 | active = TRUE,
78 | rclipboardSetup(),
79 | tags$head(
80 | tags$script(
81 | "$(function() {
82 | Shiny.addCustomMessageHandler('toggle_project_type', function(message) {
83 | if (message === 'placeholder') {
84 | $('#engine_type').hide();
85 | $('#engine_type').siblings().last().hide();
86 | } else {
87 | $('#engine_type').show();
88 | $('#engine_type').siblings().last().show();
89 | }
90 | $()
91 | });
92 |
93 | Shiny.addCustomMessageHandler('toggle_run_button', function(message) {
94 | if (message) {
95 | $('#run_code_output').children().show();
96 | $('#clip_button').show();
97 | } else {
98 | $('#run_code_output').children().hide();
99 | $('#clip_button').hide();
100 | }
101 | });
102 |
103 | $(document).one('shiny:connected', function() {
104 | var isDark = $('html').hasClass('theme-dark');
105 | Shiny.setInputValue('is_dark', isDark);
106 | });
107 |
108 | $('#theme_switch').on('click', function() {
109 | var isDark = $('html').hasClass('theme-dark');
110 | if (isDark) {
111 | $(this).find('.f7-icons').html('moon_fill');
112 | $('html').removeClass('theme-dark');
113 | } else {
114 | $(this).find('.f7-icons').html('sun_max');
115 | $('html').addClass('theme-dark');
116 | }
117 | Shiny.setInputValue('is_dark', !isDark, {priority: 'event'});
118 | })
119 | });"
120 | )
121 | ),
122 |
123 | f7Select(
124 | inputId = "project_type",
125 | label = "Project Type",
126 | choices = c(
127 | "Select a project type" = "placeholder",
128 | "Package" = "package",
129 | "Simple app" = "simple",
130 | "Extension" = "extension"
131 | ),
132 | selected = NULL
133 | ),
134 | shinyMobile::f7Radio(
135 | inputId = "engine_type",
136 | label = "Select an engine",
137 | choices = NULL
138 | )
139 | ),
140 | f7Tab(
141 | tabName = "Configuration",
142 | icon = f7Icon("gear"),
143 | uiOutput("config_steps")
144 | ),
145 | f7Tab(
146 | tabName = "Template",
147 | icon = f7Icon("paintbrush"),
148 | truelle::f7Radio(
149 | inputId = "selected_template",
150 | label = "Selected template",
151 | selected = "golem_default",
152 | choices = list(
153 | default = list(
154 | title = "golem_default",
155 | subtitle = "{golem} default template",
156 | text = "Best choice if you don't know where to start.",
157 | image = img(
158 | src = "www/golem.svg",
159 | width = "40px",
160 | height = "40px"
161 | )
162 | ),
163 | shinyMobile_simple = list(
164 | title = "shinyMobile_simple",
165 | subtitle = "Simplest {shinyMobile} template",
166 | text = "Ideal for simple apps with one page content.",
167 | image = img(
168 | src = "www/shinyMobile.svg",
169 | width = "40px",
170 | height = "40px"
171 | )
172 | ),
173 | shinyMobile_tabs = list(
174 | title = "shinyMobile_tabs",
175 | subtitle = "Tabs layout for {shinyMobile}",
176 | text = "Ideal for complex apps with multi tabs content.
177 | Perfect for mobile devices.",
178 | image = img(
179 | src = "www/shinyMobile.svg",
180 | width = "40px",
181 | height = "40px"
182 | )
183 | ),
184 | shinyMobile_split = list(
185 | title = "shinyMobile_split",
186 | subtitle = "Split layout for {shinyMobile}",
187 | text = "Ideal for complex apps with multi tabs content.
188 | Perfect for larger mobile devices such as tablets.",
189 | image = img(
190 | src = "www/shinyMobile.svg",
191 | width = "40px",
192 | height = "40px"
193 | )
194 | ),
195 | bs4Dash = list(
196 | title = "bs4Dash",
197 | subtitle = "Bootstrap 4 dashboard template",
198 | text = "Ideal to build modern apps without losing the {shinydashboard} spirit.",
199 | image = img(
200 | src = "www/bs4Dash.svg",
201 | width = "40px",
202 | height = "40px"
203 | )
204 | ),
205 | shinydashboard = list(
206 | title = "shinydashboard",
207 | subtitle = "Bootstrap 3 dashboard template",
208 | text = "The well know {shinydashboard} template.",
209 | image = NULL
210 | ),
211 | shiny_fluent = list(
212 | title = "shiny.fluent",
213 | subtitle = "Microsoft Fluent UI for {shiny}",
214 | text = "React-based user interface kit for {shiny}.",
215 | image = img(
216 | src = "www/shiny-fluent.png",
217 | width = "40px",
218 | height = "40px"
219 | )
220 | ),
221 | shiny_material = list(
222 | title = "shinymaterial",
223 | subtitle = "Materialize CSS for {shiny}",
224 | text = "Material design UI kit for {shiny}.",
225 | image = NULL
226 | ),
227 | shiny_semantic = list(
228 | title = "shiny.semantic",
229 | subtitle = "Formantic UI for {shiny}",
230 | text = "Formantic UI toolkit for {shiny}.",
231 | image = img(
232 | src = "www/shiny-semantic.png",
233 | width = "40px",
234 | height = "40px"
235 | )
236 | ),
237 | semantic_dashboard = list(
238 | title = "semantic.dashboard",
239 | subtitle = "Formantic dashboard UI for {shiny}",
240 | text = "Dashboard template powered by the Formantic UI toolkit for {shiny}.",
241 | image = img(
242 | src = "www/semantic-dashboard.png",
243 | width = "40px",
244 | height = "40px"
245 | )
246 | )
247 | )
248 | )
249 | ),
250 | f7Tab(
251 | tabName = "Output",
252 | icon = f7Icon("document_text"),
253 | aceEditor(
254 | outputId = "code_output",
255 | value = "",
256 | mode = "r"
257 | )
258 | )
259 | )
260 | )
261 | )
262 | )
263 | }
264 |
265 | #' Add external Resources to the Application
266 | #'
267 | #' This function is internally used to add external
268 | #' resources inside the Shiny application.
269 | #'
270 | #' @import shiny
271 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
272 | #' @noRd
273 | golem_add_external_resources <- function(){
274 |
275 | add_resource_path(
276 | 'www', app_sys('app/www')
277 | )
278 |
279 | tags$head(
280 | favicon(),
281 | bundle_resources(
282 | path = app_sys('app/www'),
283 | app_title = '{truelle}'
284 | )
285 | # Add here other external resources
286 | # for example, you can add shinyalert::useShinyalert()
287 | )
288 | }
289 |
290 |
--------------------------------------------------------------------------------
/R/app_server.R:
--------------------------------------------------------------------------------
1 | #' The application server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @import shinyMobile
7 | #' @importFrom shinyAce updateAceEditor
8 | #' @importFrom callr r_bg
9 | #' @importFrom jsonlite toJSON
10 | #' @noRd
11 | app_server <- function( input, output, session ) {
12 |
13 | # Tooltip for golem option
14 | observeEvent({
15 | req(input$engine_type)
16 | }, {
17 | addF7Tooltip(
18 | selector = "#engine_type > ul > li:nth-child(1) > label > div > div",
19 | options = list(
20 | text = "{golem} allows to develop production ready shiny apps ..."
21 | )
22 | )
23 | })
24 |
25 |
26 | observeEvent(input$project_type, {
27 | session$sendCustomMessage("toggle_project_type", input$project_type)
28 | })
29 |
30 | observeEvent(c(input$package_path, input$project_type), {
31 | cond <- (input$project_type != "placeholder" && nchar(input$package_path) > 0)
32 | session$sendCustomMessage(
33 | "toggle_run_button",
34 | toJSON(cond, auto_unbox = TRUE)
35 | )
36 | })
37 |
38 | observeEvent(input$widget_nav,{
39 | if (input$project_type == "placeholder" && (
40 | input$widget_nav == "Configuration" ||
41 | input$widget_nav == "Output"
42 | )) {
43 | f7Toast(
44 | text = "You can't do this now.",
45 | position = "center"
46 | )
47 | }
48 | })
49 |
50 | observeEvent(input$project_type, {
51 | choices <- if (input$project_type == "package") {
52 | c(
53 | "{golem}" = "golem",
54 | "{packer}" = "packer",
55 | "{reactR}" = "reactr"
56 | )
57 | }
58 | updateF7Radio("engine_type", choices = choices)
59 | })
60 |
61 | #observeEvent(input$engine_type, {
62 | # updateF7Tabs("widget_nav", selected = "Configuration")
63 | #})
64 |
65 | output$config_steps <- renderUI({
66 | req(input$engine_type)
67 | steps <- if (input$engine_type == "golem") {
68 | f7Block(
69 | inset = TRUE,
70 | f7AccordionItem(
71 | title = div(class = "text-color-blue", "Package path"),
72 | open = TRUE,
73 | f7Text(
74 | inputId = "package_path",
75 | label = "",
76 | value = "",
77 | placeholder = "package path"
78 | )
79 | ),
80 | f7AccordionItem(
81 | title = div(class = "text-color-blue", "Metadata"),
82 | f7Block(
83 | inset = TRUE,
84 | strong = TRUE,
85 | f7Toggle(
86 | inputId = "edit_description",
87 | label = "Edit description",
88 | checked = FALSE
89 | )
90 | )
91 | ),
92 | f7AccordionItem(
93 | title = div(class = "text-color-blue", "{usethis} commons"),
94 | # common usethis tasks
95 | lapply(seq_along(usethis_commons), function(i) {
96 | f7Block(
97 | inset = TRUE,
98 | strong = TRUE,
99 | f7Toggle(
100 | inputId = paste0("set_usethis_", names(usethis_commons)[[i]]),
101 | label = names(usethis_commons)[[i]],
102 | checked = TRUE
103 | ),
104 | br()
105 | )
106 | })
107 |
108 | ),
109 | # Bug with interactivity... check what we can do ...
110 | #f7AccordionItem(
111 | # title = "{testthat} commons",
112 | # f7Toggle(
113 | # inputId = "allow_recommended_tests",
114 | # label = "Recommanded tests",
115 | # checked = FALSE
116 | # )
117 | #),
118 | f7AccordionItem(
119 | title = div(class = "text-color-blue", "Dependencies"),
120 | f7Block(
121 | inset = TRUE,
122 | strong = TRUE,
123 | f7Toggle(
124 | inputId = "use_recommended_deps",
125 | label = "Add recommended deps",
126 | checked = TRUE
127 | )
128 | )
129 | ),
130 | f7AccordionItem(
131 | title = div(class = "text-color-blue", "{golem} utils"),
132 | f7Block(
133 | inset = TRUE,
134 | strong = TRUE,
135 | f7Toggle(
136 | inputId = "use_golem_utils",
137 | label = "Allow utils",
138 | checked = TRUE
139 | )
140 | )
141 | ),
142 | f7AccordionItem(
143 | title = div(class = "text-color-blue", "Shiny modules"),
144 | f7Block(
145 | inset = TRUE,
146 | strong = TRUE,
147 | f7Toggle(
148 | inputId = "add_module_skeleton",
149 | label = "Add module",
150 | checked = TRUE
151 | )
152 | )
153 | ),
154 | f7AccordionItem(
155 | title = div(class = "text-color-blue", "Web dev tools"),
156 | lapply(seq_along(webdev_commons), function(i) {
157 | f7Block(
158 | inset = TRUE,
159 | strong = TRUE,
160 | f7Toggle(
161 | inputId = paste0("create_golem_", names(webdev_commons)[[i]]),
162 | label = names(webdev_commons)[[i]],
163 | checked = TRUE
164 | ),
165 | br()
166 | )
167 | }),
168 | f7TextArea(
169 | inputId = "css_template",
170 | label = "CSS template",
171 | value = paste0(
172 | "function(path, ...){ \n",
173 | " # Define a CSS template \n",
174 | " write_there <- function(...){ \n",
175 | " write(..., file = path, append = TRUE) \n",
176 | " } \n",
177 |
178 | ' write_there("body {") \n',
179 | ' write_there(" background-color:white;") \n',
180 | ' write_there("}") \n',
181 | " }",
182 | collapse = "\n"
183 | )
184 | ),
185 | f7TextArea(
186 | inputId = "js_template",
187 | label = "JS template",
188 | value = NULL
189 | )
190 | ),
191 | f7AccordionItem(
192 | title = div(class = "text-color-blue", "Other options"),
193 | f7Block(
194 | inset = TRUE,
195 | strong = TRUE,
196 | f7Toggle(
197 | inputId = "set_golem_options",
198 | label = "Golem options",
199 | checked = FALSE
200 | )
201 | )
202 | )
203 | )
204 | }
205 | if (!is.null(steps)) {
206 | tagList(
207 | f7Accordion(
208 | id = "config_step",
209 | multiCollapse = TRUE,
210 | steps
211 | ),
212 | f7Card(
213 | title = "Customize {golem} hooks",
214 | p("Enter any extra configuration you want to have in your
215 | project", class = "text-color-blue"),
216 | br(),
217 | f7TextArea(
218 | inputId = "custom_golem_hook",
219 | label = "Custom hook",
220 | value = NULL
221 | )
222 | )
223 | )
224 | }
225 | })
226 |
227 | # End-user info for package path
228 | observeEvent({
229 | input$package_path
230 | }, {
231 |
232 | is_golem <- file.exists(file.path(input$package_path, "inst/golem-config.yml"))
233 | if (is_golem) {
234 | f7Dialog(
235 | title = "Oupps",
236 | text = "Package already exists here! Please use another path",
237 | type = "alert"
238 | )
239 | updateF7Text("package_path", value = "")
240 | } else {
241 | validateF7Input(
242 | inputId = "package_path",
243 | pattern = "*",
244 | info = "Package path like ~/Desktop/myPackage",
245 | error = "Path cannot be empty!"
246 | )
247 | }
248 | })
249 |
250 | observeEvent({
251 | input$custom_golem_hook
252 | }, {
253 | validateF7Input(
254 | inputId = "custom_golem_hook",
255 | info = "A {golem} hook is a function run at package creation.",
256 | )
257 | })
258 |
259 | # Insert text description fields if enabled
260 | observeEvent(input$edit_description, {
261 | if (input$edit_description) {
262 | insertUI(
263 | selector = "#edit_description",
264 | where = "afterEnd",
265 | ui = div(
266 | id = "package_description_div",
267 | lapply(seq_along(pkg_description_fields), function(i) {
268 | f7Text(
269 | inputId = names(pkg_description_fields)[[i]],
270 | label = strsplit(names(pkg_description_fields)[[i]], "_")[[1]][2],
271 | value = pkg_description_fields[[i]]
272 | )
273 | })
274 | )
275 | )
276 | } else {
277 | removeUI("#package_description_div")
278 | }
279 | })
280 |
281 | # Update custom hook based on many options
282 | observeEvent({
283 | req(input$engine_type == "golem")
284 | req(input$package_path)
285 | c(
286 | input$package_path,
287 | input$edit_description,
288 | input$set_golem_options,
289 | #input$allow_recommended_tests,
290 | input$use_golem_utils,
291 | input$use_recommended_deps,
292 | input$add_module_skeleton,
293 | input$css_template,
294 | input$js_template,
295 | input$selected_template,
296 | eval(parse(text = paste0("input$create_golem_", names(webdev_commons)))),
297 | eval(parse(text = paste0("input$set_usethis_", names(usethis_commons)))),
298 | eval(parse(text = paste0("input$", names(pkg_description_fields))))
299 | )
300 | },
301 | {
302 | if (nchar(input$css_template) > 0) {
303 | webdev_commons[["simple_css"]] <- paste0(
304 | ' golem::add_css_file( \n',
305 | ' "custom_css", \n',
306 | " template = ", input$css_template, "\n",
307 | ' )',
308 | collapse = "\n"
309 | )
310 | }
311 |
312 | if (nchar(input$js_template) > 0) {
313 | webdev_commons[["simple_js"]] <- paste0(
314 | ' golem::add_js_file( \n',
315 | ' "custom_js", \n',
316 | " template = ", input$js_template, "\n",
317 | ' )',
318 | collapse = "\n"
319 | )
320 | }
321 |
322 | web_dev_tasks <- list_2_char(webdev_commons, "create_golem_", input)
323 | usethis_tasks <- list_2_char(usethis_commons, "set_usethis_", input)
324 |
325 | temp_val <- paste0(
326 | "function(path, package_name, ...) { \n",
327 | if (input$edit_description) {
328 | paste0(
329 | ' golem::fill_desc( \n',
330 | ' pkg_name = "', input[[names(pkg_description_fields)[[1]]]], '", \n',
331 | ' pkg_title = "', input[[names(pkg_description_fields)[[2]]]], '", \n',
332 | ' pkg_description = "', input[[names(pkg_description_fields)[[3]]]], '", \n',
333 | ' author_first_name = "', input[[names(pkg_description_fields)[[4]]]], '", \n',
334 | ' author_last_name = "', input[[names(pkg_description_fields)[[5]]]],'", \n',
335 | ' author_email = "', input[[names(pkg_description_fields)[[6]]]], '", \n',
336 | ' repo_url = "', input[[names(pkg_description_fields)[[7]]]], '" \n',
337 | ' ) \n',
338 | '\n',
339 | collapse = "\n"
340 | )
341 | },
342 | if (input$set_golem_options) " golem::set_golem_options() \n",
343 | usethis_tasks,
344 | #if (input$allow_recommended_tests) " golem::use_recommended_tests() \n",
345 | if (input$use_recommended_deps) " golem::use_recommended_deps() \n",
346 | if (input$use_golem_utils) {
347 | paste0(
348 | " golem::use_utils_ui() \n",
349 | " golem::use_utils_server() \n",
350 | "\n",
351 | collapse = "\n"
352 | )
353 | },
354 | if (input$add_module_skeleton) {
355 | paste0(
356 | ' golem::add_module( name = "my_first_module" ) \n',
357 | ' golem::add_fct("my_first_module") \n',
358 | ' golem::add_utils("my_first_module") \n',
359 | '\n',
360 | collapse = "\n"
361 | )
362 | },
363 | web_dev_tasks,
364 | if (input$selected_template != "golem_default") {
365 | add_ui_template(input$selected_template)
366 | },
367 | " }",
368 | collapse = "\n"
369 | )
370 |
371 | updateF7TextArea(
372 | inputId = "custom_golem_hook",
373 | value = temp_val
374 | )
375 | })
376 |
377 | # Update aceEditor with golem commands
378 | observeEvent(
379 | c(
380 | input$package_path,
381 | input$custom_golem_hook
382 | ), {
383 | req(nchar(input$package_path) > 0)
384 |
385 | hook <- if (nchar(input$custom_golem_hook) > 0) {
386 | input$custom_golem_hook
387 | } else {
388 | "golem::project_hook"
389 | }
390 |
391 | new_val <- paste0(
392 | 'golem::create_golem( \n',
393 | ' path = "', input$package_path, '", \n',
394 | ' open = FALSE, \n',
395 | ' project_hook = ', hook,' \n',
396 | ')',
397 | collapse = "\n"
398 | )
399 |
400 | updateAceEditor(
401 | session,
402 | "code_output",
403 | value = new_val
404 | )
405 | })
406 |
407 | # Update ace editor on dark mode but don't run at start
408 | observeEvent(input$is_dark, {
409 | updateAceEditor(
410 | session,
411 | "code_output",
412 | theme = if (input$is_dark) "chaos" else "eclipse"
413 | )
414 | })
415 |
416 | # Copy to clipboard
417 | output$clip_button <- renderUI({
418 | rclipButton(
419 | "copy_code_output",
420 | div(style = "padding-right: 5px", "Copy code"),
421 | input$code_output,
422 | icon = f7Icon("camera")
423 | )
424 | })
425 |
426 |
427 | # Run the command in another process
428 | observeEvent(input$run_code_output, {
429 | jobs[[1]] <- r_bg(run_text, args = list(code = input$code_output))
430 | jobs[[1]]$wait()
431 |
432 | f7Notif(
433 | title = "Hey!",
434 | paste("Package successfully created at", jobs[[1]]$get_result()),
435 | icon = f7Icon("info_round")
436 | )
437 | })
438 |
439 | # Close the app
440 | observeEvent(input$close_app, {
441 | f7Dialog(
442 | id = "close_app_confirm",
443 | title = "Oupps",
444 | text = "Do you really want to close?",
445 | type = "confirm"
446 | )
447 | })
448 |
449 | observeEvent(input$close_app_confirm, {
450 | req(input$close_app_confirm)
451 | stopApp()
452 | })
453 |
454 | #observeEvent(input$project_type, once = TRUE, {
455 | # updateF7Accordion("config_step", selected = 2)
456 | #})
457 | }
458 |
--------------------------------------------------------------------------------
/inst/app/www/shinyMobile.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------