├── .github
├── .gitignore
└── workflows
│ ├── R-CMD-check.yaml
│ ├── test-coverage.yaml
│ └── pr-commands.yaml
├── .gitignore
├── LICENSE
├── data
├── repos.rda
├── cran_dl_data.rda
└── gh_stars_data.rda
├── tests
├── testthat.R
├── spelling.R
└── testthat
│ ├── test-make_table.R
│ ├── test-get_data.R
│ ├── test-golem-recommended.R
│ ├── test-make_plots.R
│ └── test-mod_plots.R
├── inst
├── app
│ └── www
│ │ ├── hex.png
│ │ ├── favicon.ico
│ │ └── styles.css
├── golem-config.yml
├── WORDLIST
└── CODE_OF_CONDUCT.md
├── .Rbuildignore
├── R
├── repos.R
├── gh_stars_data.R
├── cran_dl_data.R
├── run_app.R
├── app_server.R
├── app_config.R
├── fct_make_table.R
├── mod_plots.R
├── mod_table.R
├── app_ui.R
├── fct_get_data.R
├── utils.R
├── fct_make_plots.R
└── mod_sidebar.R
├── app.R
├── man
├── run_app.Rd
├── gh_plot.Rd
├── cran_plot.Rd
├── repos.Rd
├── theme_calendar.Rd
├── get_cran_name.Rd
├── get_gh_stars.Rd
├── gh_stars_data.Rd
├── cran_dl_data.Rd
└── get_cran_data.Rd
├── dev
├── run_dev.R
├── 03_deploy.R
├── 01_start.R
└── 02_dev.R
├── cranstars.Rproj
├── DESCRIPTION
├── LICENSE.md
├── NAMESPACE
├── data-raw
└── DATASET.R
└── README.md
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rhistory
2 | .RData
3 | .Rproj.user
4 | .Rproj
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2020
2 | COPYRIGHT HOLDER: Zauad Shahreer Abeer
3 |
--------------------------------------------------------------------------------
/data/repos.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahreyar-abeer/cranstars/HEAD/data/repos.rda
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(cranstars)
3 |
4 | test_check("cranstars")
5 |
--------------------------------------------------------------------------------
/data/cran_dl_data.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahreyar-abeer/cranstars/HEAD/data/cran_dl_data.rda
--------------------------------------------------------------------------------
/inst/app/www/hex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahreyar-abeer/cranstars/HEAD/inst/app/www/hex.png
--------------------------------------------------------------------------------
/data/gh_stars_data.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahreyar-abeer/cranstars/HEAD/data/gh_stars_data.rda
--------------------------------------------------------------------------------
/inst/app/www/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahreyar-abeer/cranstars/HEAD/inst/app/www/favicon.ico
--------------------------------------------------------------------------------
/inst/golem-config.yml:
--------------------------------------------------------------------------------
1 | default:
2 | golem_name: cranstars
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 | ^codecov\.yml$
8 | ^app\.R$
9 | ^rsconnect$
10 | ^\.github$
11 | ^LICENSE\.md$
12 |
--------------------------------------------------------------------------------
/inst/WORDLIST:
--------------------------------------------------------------------------------
1 | abeer
2 | codecov
3 | cran
4 | cranstars’
5 | dl
6 | downlaods
7 | eg
8 | gh
9 | github
10 | Github
11 | golem
12 | https
13 | io
14 | Lifecycle
15 | repo
16 | Repo
17 | repos
18 | rsconnect
19 | rstudio
20 | shahreyar
21 | shinyapps
22 | tidyverse
23 |
--------------------------------------------------------------------------------
/R/repos.R:
--------------------------------------------------------------------------------
1 |
2 | #' 20 tidyverse packages
3 | #'
4 | #' A dataset containing 20 tidyverse packages in the form of github repos.
5 | #'
6 | #' @format A data frame with 20 rows and 1 variable:
7 | #' \describe{
8 | #' \item{tidypacks}{The name of the github repo}
9 | #' }
10 | "repos"
--------------------------------------------------------------------------------
/tests/testthat/test-make_table.R:
--------------------------------------------------------------------------------
1 | test_that("make_table() works", {
2 | r = list(
3 | repo = "hadley/dplyr",
4 | date = c((Sys.Date() - 50), (Sys.Date() - 10)),
5 | cran_dl = cran_dl_data,
6 | gh_stars = gh_stars_data
7 | )
8 | expect_is(make_table(r), "data.frame")
9 | })
--------------------------------------------------------------------------------
/app.R:
--------------------------------------------------------------------------------
1 | # Launch the ShinyApp (Do not remove this comment)
2 | # To deploy, run: rsconnect::deployApp()
3 | # Or use the blue button on top of this file
4 |
5 | pkgload::load_all(export_all = FALSE,helpers = FALSE,attach_testthat = FALSE)
6 | options( "golem.app.prod" = TRUE)
7 | cranstars::run_app() # add parameters here (if any)
8 |
--------------------------------------------------------------------------------
/tests/testthat/test-get_data.R:
--------------------------------------------------------------------------------
1 |
2 | test_that("get_gh_data() works", {
3 | repo <- "rstudio/rsconnect"
4 | expect_is(get_gh_stars(repo), "data.frame")
5 | })
6 |
7 | test_that("get_cran_data() works", {
8 | package_name <- "rsconnect"
9 | expect_is(get_cran_data(package_name, from = (Sys.Date() - 10)), "data.frame")
10 | })
11 |
--------------------------------------------------------------------------------
/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 | }
9 | \arguments{
10 | \item{...}{A series of options to be used inside the app.}
11 | }
12 | \description{
13 | Run the Shiny Application
14 | }
15 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/R/gh_stars_data.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | #' Github Stars for 20 tidyverse packages
4 | #'
5 | #' A dataset containing the daily number of stars the packages got
6 | #'
7 | #' @format A data frame with 12748 rows and 3 variables:
8 | #' \describe{
9 | #' \item{date}{The date}
10 | #' \item{n_stars}{Number of stars in the date}
11 | #' \item{package}{Repo of package}
12 | #' }
13 | "gh_stars_data"
--------------------------------------------------------------------------------
/R/cran_dl_data.R:
--------------------------------------------------------------------------------
1 |
2 | #' CRAN downloads for 20 tidyverse packages
3 | #'
4 | #' A dataset containing the daily number of downloads for the supplied packages
5 | #'
6 | #' @format A data frame with 77940 rows and 3 variables:
7 | #' \describe{
8 | #' \item{date}{The date}
9 | #' \item{count}{Number of downlaods in the date}
10 | #' \item{package}{Name of package}
11 | #' }
12 | "cran_dl_data"
--------------------------------------------------------------------------------
/cranstars.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | BuildType: Package
16 | PackageUseDevtools: Yes
17 | PackageInstallArgs: --no-multiarch --with-keep.source
18 |
--------------------------------------------------------------------------------
/man/gh_plot.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/fct_make_plots.R
3 | \name{gh_plot}
4 | \alias{gh_plot}
5 | \title{Title}
6 | \usage{
7 | gh_plot(r)
8 | }
9 | \arguments{
10 | \item{r}{\code{reactiveValues} object with 4 slots, repo, date, cran_dl & gh_stars}
11 | }
12 | \value{
13 | \code{ggplot}
14 | }
15 | \description{
16 | Title
17 | }
18 |
--------------------------------------------------------------------------------
/man/cran_plot.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/fct_make_plots.R
3 | \name{cran_plot}
4 | \alias{cran_plot}
5 | \title{Title}
6 | \usage{
7 | cran_plot(r)
8 | }
9 | \arguments{
10 | \item{r}{\code{reactiveValues} object with 4 slots, repo, date, cran_dl & gh_stars}
11 | }
12 | \value{
13 | \code{ggplot}
14 | }
15 | \description{
16 | Title
17 | }
18 |
--------------------------------------------------------------------------------
/tests/testthat/test-golem-recommended.R:
--------------------------------------------------------------------------------
1 | test_that("app ui", {
2 | ui <- app_ui()
3 | golem::expect_shinytaglist(ui)
4 | })
5 |
6 | test_that("app server", {
7 | server <- app_server
8 | expect_is(server, "function")
9 | })
10 |
11 | # Configure this test to fit your need
12 | test_that(
13 | "app launches",{
14 | skip_if_not(interactive())
15 | golem::expect_running(sleep = 5)
16 | }
17 | )
--------------------------------------------------------------------------------
/R/run_app.R:
--------------------------------------------------------------------------------
1 | #' Run the Shiny Application
2 | #'
3 | #' @param ... A series of options to be used inside the app.
4 | #'
5 | #' @export
6 | #' @importFrom shiny shinyApp
7 | #' @importFrom golem with_golem_options
8 | run_app <- function(
9 | ...
10 | ) {
11 | with_golem_options(
12 | app = shinyApp(
13 | ui = app_ui,
14 | server = app_server
15 | ),
16 | golem_opts = list(...)
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/man/repos.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/repos.R
3 | \docType{data}
4 | \name{repos}
5 | \alias{repos}
6 | \title{20 tidyverse packages}
7 | \format{
8 | A data frame with 20 rows and 1 variable:
9 | \describe{
10 | \item{tidypacks}{The name of the github repo}
11 | }
12 | }
13 | \usage{
14 | repos
15 | }
16 | \description{
17 | A dataset containing 20 tidyverse packages in the form of github repos.
18 | }
19 | \keyword{datasets}
20 |
--------------------------------------------------------------------------------
/man/theme_calendar.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{theme_calendar}
4 | \alias{theme_calendar}
5 | \title{Theme for the github calendar plot}
6 | \usage{
7 | theme_calendar(base_size = 15, base_family = "sans")
8 | }
9 | \arguments{
10 | \item{base_size}{\code{numeric} Base font size}
11 |
12 | \item{base_family}{\code{string} Base font family}
13 | }
14 | \description{
15 | Theme for the github calendar plot
16 | }
17 |
--------------------------------------------------------------------------------
/tests/testthat/test-make_plots.R:
--------------------------------------------------------------------------------
1 | test_that("cran_plot() works", {
2 | r = list(
3 | repo = "hadley/dplyr",
4 | date = c((Sys.Date() - 10), (Sys.Date() - 5)),
5 | cran_dl = cran_dl_data,
6 | gh_stars = gh_stars_data
7 | )
8 | expect_is(cran_plot(r), "highchart")
9 | })
10 |
11 | test_that("gh_plot() works", {
12 | r = list(
13 | repo = "hadley/dplyr",
14 | date = c((Sys.Date() - 10), (Sys.Date() - 5)),
15 | cran_dl = cran_dl_data,
16 | gh_stars = gh_stars_data
17 | )
18 | expect_is(gh_plot(r), "ggplot")
19 | })
20 |
--------------------------------------------------------------------------------
/man/get_cran_name.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{get_cran_name}
4 | \alias{get_cran_name}
5 | \title{Get only package name from repo name}
6 | \usage{
7 | get_cran_name(repo)
8 | }
9 | \arguments{
10 | \item{repo}{\code{string} The repo name, e.g., \bold{"rstudio/rsconnect"}}
11 | }
12 | \value{
13 | \code{string} The package name, e.g., \bold{"rsconnect"}
14 | }
15 | \description{
16 | Get only package name from repo name
17 | }
18 | \examples{
19 | get_cran_name("rsconnect/rstudio")
20 | }
21 |
--------------------------------------------------------------------------------
/man/get_gh_stars.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/fct_get_data.R
3 | \name{get_gh_stars}
4 | \alias{get_gh_stars}
5 | \title{Get the github stars for the supplied repo on a daily basis}
6 | \usage{
7 | get_gh_stars(repo)
8 | }
9 | \arguments{
10 | \item{repo}{A \code{character} vector containing the repo name, eg. "rstudio/rsconnect"}
11 | }
12 | \value{
13 | A \code{data.frame}
14 | }
15 | \description{
16 | Get the github stars for the supplied repo on a daily basis
17 | }
18 | \examples{
19 | get_gh_stars("rstudio/rsconnect")
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/man/gh_stars_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/gh_stars_data.R
3 | \docType{data}
4 | \name{gh_stars_data}
5 | \alias{gh_stars_data}
6 | \title{Github Stars for 20 tidyverse packages}
7 | \format{
8 | A data frame with 12748 rows and 3 variables:
9 | \describe{
10 | \item{date}{The date}
11 | \item{n_stars}{Number of stars in the date}
12 | \item{package}{Repo of package}
13 | }
14 | }
15 | \usage{
16 | gh_stars_data
17 | }
18 | \description{
19 | A dataset containing the daily number of stars the packages got
20 | }
21 | \keyword{datasets}
22 |
--------------------------------------------------------------------------------
/man/cran_dl_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/cran_dl_data.R
3 | \docType{data}
4 | \name{cran_dl_data}
5 | \alias{cran_dl_data}
6 | \title{CRAN downloads for 20 tidyverse packages}
7 | \format{
8 | A data frame with 77940 rows and 3 variables:
9 | \describe{
10 | \item{date}{The date}
11 | \item{count}{Number of downlaods in the date}
12 | \item{package}{Name of package}
13 | }
14 | }
15 | \usage{
16 | cran_dl_data
17 | }
18 | \description{
19 | A dataset containing the daily number of downloads for the supplied packages
20 | }
21 | \keyword{datasets}
22 |
--------------------------------------------------------------------------------
/man/get_cran_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/fct_get_data.R
3 | \name{get_cran_data}
4 | \alias{get_cran_data}
5 | \title{Title}
6 | \usage{
7 | get_cran_data(package_names, from_date, to_date = Sys.Date())
8 | }
9 | \arguments{
10 | \item{package_names}{A character vector, names of packages to download data for}
11 |
12 | \item{from_date}{A string}
13 |
14 | \item{to_date}{A string, default is set to today's date}
15 | }
16 | \value{
17 | A \code{data.frame}
18 | }
19 | \description{
20 | Title
21 | }
22 | \examples{
23 | get_cran_data("rsconnect", from_date = (Sys.Date() - 10))
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/R/app_server.R:
--------------------------------------------------------------------------------
1 | #' cranStars server-side
2 | #'
3 | #' @param input,output,session Internal parameters for {shiny}.
4 | #'
5 | #' @importFrom shiny reactiveValues renderUI invalidateLater tags
6 | #' @noRd
7 | app_server <- function( input, output, session ) {
8 | # List the first level callModules here
9 | r = reactiveValues(
10 | repo = NULL,
11 | date = NULL,
12 | cran_dl = NULL,
13 | gh_stars = NULL
14 | )
15 | mod_sidebar_server("sidebar", r)
16 | mod_plot_server("cran", r, "cran")
17 | mod_plot_server("gh", r, "gh")
18 | mod_table_server("gt", r)
19 |
20 | output$quote <- renderUI({
21 | invalidateLater(1000)
22 | tags$blockquote(icon("clock"), format(Sys.time(), "%a, %b %d, %Y | %X"), style = "color: #8a8a8a")
23 | })
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | name: R-CMD-check
12 |
13 | jobs:
14 | R-CMD-check:
15 | runs-on: macOS-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - uses: r-lib/actions/setup-r@master
19 | - name: Install dependencies
20 | run: |
21 | install.packages(c("remotes", "rcmdcheck"))
22 | remotes::install_deps(dependencies = TRUE)
23 | shell: Rscript {0}
24 | - name: Check
25 | run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "error")
26 | shell: Rscript {0}
27 |
--------------------------------------------------------------------------------
/R/app_config.R:
--------------------------------------------------------------------------------
1 | #' Access files in the current app
2 | #'
3 | #' @param ... Character vector specifying directory and or file to
4 | #' point to inside the current package.
5 | #'
6 | #' @noRd
7 | app_sys <- function(...){
8 | system.file(..., package = "cranstars")
9 | }
10 |
11 |
12 | #' Read App Config
13 | #'
14 | #' @param value Value to retrieve from the config file.
15 | #' @param config R_CONFIG_ACTIVE value.
16 | #' @param use_parent Logical, scan the parent directory for config file.
17 | #'
18 | #' @noRd
19 | get_golem_config <- function(
20 | value,
21 | config = Sys.getenv("R_CONFIG_ACTIVE", "default"),
22 | use_parent = TRUE
23 | ){
24 | config::get(
25 | value = value,
26 | config = config,
27 | # Modify this if your config file is somewhere else:
28 | file = app_sys("golem-config.yml"),
29 | use_parent = use_parent
30 | )
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: cranstars
2 | Title: A Shiny app that shows CRAN downloads & Github stars statistics
3 | Version: 0.1.1
4 | Authors@R:
5 | person(given = "Zauad Shahreer",
6 | family = "Abeer",
7 | role = c("aut", "cre"),
8 | email = "shahreyar.abeer@gmail.com")
9 | Description: A shiny app that given a package name, shows cran downloads & github stars stats, made with the {golem} framework.
10 | License: MIT + file LICENSE
11 | Depends: R (>= 2.10)
12 | Imports:
13 | config,
14 | golem,
15 | shiny,
16 | dplyr,
17 | gh,
18 | lubridate,
19 | rlang,
20 | cranlogs,
21 | ggplot2,
22 | shinyjs,
23 | waiter,
24 | gt,
25 | pkgload,
26 | highcharter,
27 | attempt,
28 | DT,
29 | glue,
30 | htmltools,
31 | processx
32 | Encoding: UTF-8
33 | LazyData: true
34 | RoxygenNote: 7.1.1
35 | Suggests:
36 | testthat,
37 | covr,
38 | spelling
39 | Language: en-US
40 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2020 Zauad Shahreer Abeer
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 |
--------------------------------------------------------------------------------
/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 | ## RStudio ----
24 | ## If you want to deploy on RStudio related platforms
25 | golem::add_rstudioconnect_file()
26 | golem::add_shinyappsio_file()
27 | golem::add_shinyserver_file()
28 |
29 | ## Docker ----
30 | ## If you want to deploy via a generic Dockerfile
31 | golem::add_dockerfile()
32 |
33 | ## If you want to deploy to ShinyProxy
34 | golem::add_dockerfile_shinyproxy()
35 |
36 | ## If you want to deploy to Heroku
37 | golem::add_dockerfile_heroku()
38 |
--------------------------------------------------------------------------------
/tests/testthat/test-mod_plots.R:
--------------------------------------------------------------------------------
1 | test_that("mod_plot_ui works", {
2 | expect_is(mod_plot_ui("ID", 450, "cran"), "shiny.tag.list")
3 | })
4 |
5 | test_that("mod_plot_server works for ggplot", {
6 | shiny::testServer(
7 | mod_plot_server,
8 | args = list(
9 | r = reactiveValues(
10 | repo = "hadley/dplyr",
11 | date = c((Sys.Date() - 10), (Sys.Date() - 5)),
12 | cran_dl = cran_dl_data,
13 | gh_stars = gh_stars_data
14 | ),
15 | type = "gh"
16 | ), {
17 | expect_type(session$output$plot_gh$src, "character")
18 | expect_equal(session$output$plot_gh$class, "shiny-scalable")
19 | })
20 | })
21 |
22 |
23 | test_that("mod_plot_server works for highchart", {
24 | shiny::testServer(
25 | mod_plot_server,
26 | args = list(
27 | r = reactiveValues(
28 | repo = "hadley/dplyr",
29 | date = c((Sys.Date() - 10), (Sys.Date() - 5)),
30 | cran_dl = cran_dl_data,
31 | gh_stars = gh_stars_data
32 | ),
33 | type = "cran"
34 | ), {
35 | expect_type(session$output$plot_cran, "character")
36 | expect_s3_class(session$output$plot_cran, "json")
37 | })
38 | })
--------------------------------------------------------------------------------
/R/fct_make_table.R:
--------------------------------------------------------------------------------
1 |
2 | make_table <- function(r) {
3 |
4 | ## for R-CMD-check
5 | n_stars <- NULL
6 |
7 | repo <- get_cran_name(r$repo)
8 | date_range = r$date
9 |
10 | cran <- r$cran_dl %>%
11 | filter(
12 | .data$package == repo,
13 | date >= date_range[1] & date <= date_range[2]
14 | ) %>%
15 | mutate(
16 | yrmon = make_yrmon(date)
17 | )
18 |
19 | gh <- r$gh_stars %>%
20 | filter(
21 | .data$package == r$repo,
22 | date >= date_range[1] & date <= date_range[2]
23 | ) %>%
24 | mutate(
25 | yrmon = make_yrmon(date)
26 | ) %>%
27 | rename(count = n_stars)
28 |
29 | col_names <- c(
30 | "Most in a day",
31 | "Best month",
32 | "Average/month"
33 | )
34 |
35 | cran_summary <- c(
36 | get_most_count(cran),
37 | get_most_month(cran),
38 | get_avg(cran)
39 | )
40 |
41 | gh_summary = c(
42 | get_most_count(gh),
43 | get_most_month(gh),
44 | get_avg(gh)
45 | )
46 |
47 | cran_summary_data <- data.frame(col_names, cran_summary)
48 | gh_summary_data <- data.frame(col_names, gh_summary)
49 |
50 | cran_summary_data %>%
51 | left_join(gh_summary_data, by = "col_names")
52 |
53 | }
--------------------------------------------------------------------------------
/inst/app/www/styles.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | @import url(//fonts.googleapis.com/css?family=IBM+Plex+Sans);
4 |
5 | :root {
6 | --pine-tree: #292e1eff;
7 | --orange: #DA7C30;
8 | --dark-orchid: #9649cbff;
9 | --rstudio-blue: #4F84B6;
10 | --background: white;
11 | }
12 |
13 | body{
14 | background-color: var(--rstudio-blue);
15 | margin:2em;
16 | font-family: IBM Plex Sans;
17 | }
18 |
19 | .h-title {
20 | margin-top:0px !important;
21 | }
22 |
23 | .col-sm-3, .col-sm-9 {
24 | margin-top: 20px;
25 | }
26 |
27 | .col-sm-9> .row{
28 | background: var(--background);
29 | border:solid 1px;
30 | border-radius:25px;
31 | border-color: var(--orange);
32 | padding:2em;
33 | margin-bottom:1em
34 | }
35 | .well{
36 | background-color: var(--background);
37 | border-radius:25px;
38 | padding:2em;
39 | border-color: var(--orange)
40 | }
41 |
42 | h2, h3{
43 | color: var(--pine-tree);
44 | }
45 |
46 | img{
47 | padding-top:0em;
48 | }
49 |
50 | .waiter-overlay-content {
51 | margin-top: -50px !important;
52 | }
53 |
54 | .gt_table {
55 | margin-top: 10px;
56 | }
57 |
58 | #quote {
59 | margin-left: 120px;
60 | margin-top: 120px;
61 | }
62 |
63 | .highcharts-root {
64 | font-family: IBM Plex Sans !important;
65 | font-size: 15px;
66 | }
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(cran_plot)
4 | export(get_cran_data)
5 | export(get_cran_name)
6 | export(get_gh_stars)
7 | export(gh_plot)
8 | export(run_app)
9 | import(dplyr)
10 | import(ggplot2)
11 | import(gt)
12 | import(shiny)
13 | importFrom(cranlogs,cran_downloads)
14 | importFrom(dplyr,filter)
15 | importFrom(ggplot2,theme_bw)
16 | importFrom(gh,gh)
17 | importFrom(golem,activate_js)
18 | importFrom(golem,add_resource_path)
19 | importFrom(golem,bundle_resources)
20 | importFrom(golem,favicon)
21 | importFrom(golem,with_golem_options)
22 | importFrom(highcharter,hc_caption)
23 | importFrom(highcharter,hc_subtitle)
24 | importFrom(highcharter,hc_title)
25 | importFrom(highcharter,hcaes)
26 | importFrom(highcharter,hchart)
27 | importFrom(highcharter,highchartOutput)
28 | importFrom(highcharter,renderHighchart)
29 | importFrom(lubridate,day)
30 | importFrom(lubridate,week)
31 | importFrom(lubridate,year)
32 | importFrom(lubridate,ymd_hms)
33 | importFrom(rlang,.data)
34 | importFrom(shiny,NS)
35 | importFrom(shiny,invalidateLater)
36 | importFrom(shiny,reactiveValues)
37 | importFrom(shiny,renderUI)
38 | importFrom(shiny,shinyApp)
39 | importFrom(shiny,tagList)
40 | importFrom(shiny,tags)
41 | importFrom(shinyjs,hidden)
42 | importFrom(shinyjs,hide)
43 | importFrom(shinyjs,show)
44 | importFrom(shinyjs,useShinyjs)
45 | importFrom(waiter,Waiter)
46 | importFrom(waiter,spin_loaders)
47 | importFrom(waiter,use_waiter)
48 |
--------------------------------------------------------------------------------
/R/mod_plots.R:
--------------------------------------------------------------------------------
1 | #' main UI Function
2 | #'
3 | #' @description A shiny Module.
4 | #'
5 | #' @param id,input,output,session Internal parameters for {shiny}.
6 | #'
7 | #' @noRd
8 | #'
9 | #' @importFrom shiny NS tagList
10 | #' @importFrom highcharter highchartOutput
11 | mod_plot_ui <- function(id, height, type){
12 | ns <- NS(id)
13 | tagList(
14 | fluidRow(
15 | if ( type == "cran" ) highchartOutput(ns("plot_cran"), height = height)
16 | else plotOutput(ns("plot_gh"), height = height)
17 | )
18 | )
19 | }
20 |
21 | #' main Server Function
22 | #' @importFrom highcharter renderHighchart
23 | #' @noRd
24 | mod_plot_server <- function(id, r, type = c("cran", "gh")){
25 |
26 | type <- match.arg(type)
27 |
28 | moduleServer(
29 | id = id,
30 | function(input, output, session) {
31 | ns <- session$ns
32 |
33 | if ( type == "cran" ) {
34 | output$plot_cran <- renderHighchart({
35 | cran_plot(r)
36 | })
37 | } else {
38 | output$plot_gh <- renderCachedPlot({
39 |
40 | req(r$cran_dl)
41 | req(r$gh_stars)
42 | # if (type == "cran") {
43 | # gg <- cran_plot(r)
44 | # } else {
45 | # gg <- gh_plot(r)
46 | # }
47 |
48 | gh_plot(r)
49 |
50 | }, cacheKeyExpr = {list(r$repo, r$date, r$gh_stars, r$cran_dl)} )
51 | }
52 |
53 |
54 | }
55 | )
56 | }
57 |
58 |
59 |
--------------------------------------------------------------------------------
/inst/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect all people who
4 | contribute through reporting issues, posting feature requests, updating documentation,
5 | submitting pull requests or patches, and other activities.
6 |
7 | We are committed to making participation in this project a harassment-free experience for
8 | everyone, regardless of level of experience, gender, gender identity and expression,
9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
10 |
11 | Examples of unacceptable behavior by participants include the use of sexual language or
12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment,
13 | insults, or other unprofessional conduct.
14 |
15 | Project maintainers have the right and responsibility to remove, edit, or reject comments,
16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this
17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed
18 | from the project team.
19 |
20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
21 | opening an issue or contacting one or more of the project maintainers.
22 |
23 | This Code of Conduct is adapted from the Contributor Covenant
24 | (https://www.contributor-covenant.org), version 1.0.0, available at
25 | https://contributor-covenant.org/version/1/0/0/.
--------------------------------------------------------------------------------
/.github/workflows/test-coverage.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - master
5 | pull_request:
6 | branches:
7 | - master
8 |
9 | name: test-coverage
10 |
11 | jobs:
12 | test-coverage:
13 | runs-on: macOS-latest
14 | env:
15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - uses: r-lib/actions/setup-r@master
20 |
21 | - uses: r-lib/actions/setup-pandoc@master
22 |
23 | - name: Query dependencies
24 | run: |
25 | install.packages('remotes')
26 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
27 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
28 | shell: Rscript {0}
29 |
30 | - name: Cache R packages
31 | uses: actions/cache@v2
32 | with:
33 | path: ${{ env.R_LIBS_USER }}
34 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
35 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
36 |
37 | - name: Install dependencies
38 | run: |
39 | install.packages(c("remotes"))
40 | remotes::install_deps(dependencies = TRUE)
41 | remotes::install_cran("covr")
42 | shell: Rscript {0}
43 |
44 | - name: Test coverage
45 | run: covr::codecov()
46 | shell: Rscript {0}
47 |
--------------------------------------------------------------------------------
/data-raw/DATASET.R:
--------------------------------------------------------------------------------
1 |
2 | # github stars data -------------------------------------------------------
3 |
4 | ## list tidyverse packages
5 | tidypacks <-
6 | c("tidyverse/broom",
7 | "hadley/dplyr",
8 | "wesm/feather",
9 | "tidyverse/forcats",
10 | "hadley/ggplot2",
11 | "tidyverse/haven",
12 | "hadley/httr",
13 | "rstats-db/hms",
14 | "jeroenooms/jsonlite",
15 | "hadley/lubridate",
16 | "tidyverse/magrittr",
17 | "hadley/modelr",
18 | "hadley/purrr",
19 | "tidyverse/readr",
20 | "hadley/readxl",
21 | "tidyverse/stringr",
22 | "tidyverse/tibble",
23 | "hadley/rvest",
24 | "tidyverse/tidyr",
25 | "hadley/xml2")
26 |
27 | repos = data.frame(tidypacks)
28 | ## making the list of repos available as a data set
29 | usethis::use_data(repos, overwrite = TRUE)
30 |
31 | ## getting the github stars using the get_gh_stars() defined in this package
32 | gh_stars_data <- purrr::map(tidypacks, get_gh_stars)
33 | gh_stars_data <- dplyr::bind_rows(gh_stars_data)
34 |
35 | usethis::use_data(gh_stars_data, overwrite = TRUE)
36 |
37 |
38 | # cran downloads data -----------------------------------------------------
39 |
40 | ## getting cran names, function get_cran_name() defined in the package
41 | tidypacks_cran <- get_cran_name(tidypacks)
42 |
43 | ## getting cran data for 10+ years
44 | cran_dl_data <- get_cran_data(tidypacks_cran,
45 | from_date = "2010-01-01",
46 | to_date = "2020-09-01")
47 |
48 | usethis::use_data(cran_dl_data, overwrite = TRUE)
49 |
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | [](https://www.tidyverse.org/lifecycle/#experimental)
5 | [](https://github.com/shahreyar-abeer/cranstars/actions)
6 | [](https://codecov.io/gh/shahreyar-abeer/cranstars)
7 |
8 |
9 |
10 | # cranstars
11 |
12 | `{cranstars}` is simple shiny app that given a package name, shows CRAN downloads & github star statistics.
13 | This is developed with the {golem} framework.
14 |
15 | App available at
16 |
17 |
18 | The following is a [feedback](https://twitter.com/_ColinFay/status/1319188197759459328) given by [Colin Fay](https://twitter.com/_ColinFay) from [Thinkr](https://thinkr.fr/)
19 |
20 |
21 | 
22 |
23 |
24 | ## Installing & Running
25 |
26 | Install `{cranstars}` on your machine with:
27 |
28 | ``` r
29 | # Install
30 | devtools::install_github("shahreyar-abeer/cranstars")
31 |
32 | # Run
33 | cranstars::run_app()
34 | ```
35 |
36 |
37 | Please note that the ‘cranstars’ project is released with a [Contributor
38 | Code of Conduct](inst/CODE_OF_CONDUCT.md). By contributing to this project,
39 | you agree to abide by its terms.
40 |
41 |
--------------------------------------------------------------------------------
/R/mod_table.R:
--------------------------------------------------------------------------------
1 | #' table UI Function
2 | #'
3 | #' @description A shiny Module.
4 | #'
5 | #' @param id,input,output,session Internal parameters for {shiny}.
6 | #'
7 | #' @noRd
8 | #'
9 | #' @importFrom shiny NS tagList
10 | #' @import gt
11 | mod_table_ui <- function(id){
12 | ns <- NS(id)
13 | tagList(
14 | fluidRow(
15 | gt_output(ns("gt"))
16 | )
17 | )
18 | }
19 |
20 | #' table Server Function
21 | #'
22 | #' @noRd
23 | mod_table_server <- function(id, r){
24 |
25 | moduleServer(
26 | id = id,
27 | function(input, output, session) {
28 |
29 | ns <- session$ns
30 |
31 | output$gt <- render_gt({
32 |
33 | req(r$cran_dl)
34 | req(r$gh_stars)
35 |
36 | make_table(r) %>%
37 | gt(rowname_col = "col_names") %>%
38 | cols_label(
39 | cran_summary = md(paste(web_image("https://cran.r-project.org/Rlogo.svg",
40 | height = "18px; padding-top:0px !important"),
41 | "CRAN Downloads")),
42 | gh_summary = md(paste(web_image("https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
43 | height = "25px; padding-top:0px !important"),
44 | "Github Stars"))
45 | ) %>%
46 | opt_table_lines() %>%
47 | tab_header(
48 | title = "Summary Statistics",
49 | subtitle = paste0("{", r$repo, "}")
50 | ) %>%
51 | tab_footnote("In case of ties, only the first value is shown", locations = cells_stub(rows = c("Most in a day")))
52 | })
53 | }
54 | )
55 |
56 | }
57 |
58 |
59 |
--------------------------------------------------------------------------------
/R/app_ui.R:
--------------------------------------------------------------------------------
1 | #' cranStars User-Interface
2 | #'
3 | #' @param request Internal parameter for `{shiny}`.
4 | #' DO NOT REMOVE.
5 | #' @import shiny
6 | #' @noRd
7 | app_ui <- function(request) {
8 | tagList(
9 | golem_add_external_resources(),
10 | fluidPage(
11 | sidebarLayout(
12 | sidebarPanel(
13 | width = 3,
14 | fluidRow(
15 | h1("cranStars", class = "h-title"),
16 | mod_sidebar_ui("sidebar")
17 | )
18 | ),
19 |
20 | mainPanel(
21 | width = 9,
22 | fluidRow(
23 | column(
24 | width = 6,
25 | mod_plot_ui("gh", 450, "gh")
26 | ),
27 | column(
28 | width = 6,
29 | mod_plot_ui("cran", 450, "cran")
30 | ),
31 | column(
32 | width = 6,
33 | mod_table_ui("gt")
34 | ),
35 | column(
36 | width = 6,
37 | uiOutput("quote")
38 | )
39 | )
40 | )
41 | )
42 | )
43 | )
44 | }
45 |
46 | #' Add external Resources to the Application
47 | #'
48 | #' This function is internally used to add external
49 | #' resources inside the Shiny application.
50 | #'
51 | #' @importFrom shiny tags
52 | #' @importFrom golem add_resource_path activate_js favicon bundle_resources
53 | #' @importFrom waiter use_waiter
54 | #' @importFrom shinyjs useShinyjs
55 | #'
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 = 'cranstars'
68 | ),
69 | use_waiter(),
70 | useShinyjs()
71 | )
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/.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@master
15 | with:
16 | repo-token: ${{ secrets.GITHUB_TOKEN }}
17 | - uses: r-lib/actions/setup-r@master
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@master
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@master
40 | with:
41 | repo-token: ${{ secrets.GITHUB_TOKEN }}
42 | - uses: r-lib/actions/setup-r@master
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@master
54 | with:
55 | repo-token: ${{ secrets.GITHUB_TOKEN }}
56 |
--------------------------------------------------------------------------------
/R/fct_get_data.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | #' Get the github stars for the supplied repo on a daily basis
4 | #'
5 | #' @param repo A \code{character} vector containing the repo name, eg. "rstudio/rsconnect"
6 | #'
7 | #' @return A \code{data.frame}
8 | #'
9 | #'
10 | #' @export
11 | #'
12 | #' @importFrom lubridate ymd_hms
13 | #' @importFrom gh gh
14 | #' @importFrom rlang .data
15 | #' @import dplyr
16 | #'
17 | #'
18 | #' @examples
19 | #' get_gh_stars("rstudio/rsconnect")
20 | #'
21 | get_gh_stars <- function(repo) {
22 | # get data, loop because pagination
23 | stardates <- NULL
24 |
25 | geht <- TRUE
26 | page <- 1
27 | while(geht){
28 | stars <- try(gh::gh(paste0("/repos/", repo, "/stargazers"),
29 | .send_headers = c("Accept" = 'application/vnd.github.v3.star+json'),
30 | .token = Sys.getenv("GITHUB_PAT"),
31 | page = page),
32 | silent = TRUE)
33 |
34 | if(inherits(stars, "try-error")) return(stars)
35 |
36 | geht <- length(stars) != 0
37 | if(geht){
38 | stardates <- c(stardates, vapply(stars, "[[", "", "starred_at"))
39 | page <- page + 1
40 | }
41 | }
42 |
43 | star_table <- data.frame(time = ymd_hms(stardates)) %>%
44 | mutate(date = as.Date(.data$time)) %>%
45 | group_by(date) %>%
46 | summarise(n_stars = n()) %>%
47 | mutate(package = repo)
48 |
49 | star_table
50 | }
51 |
52 |
53 | #' Title
54 | #'
55 | #' @param package_names A character vector, names of packages to download data for
56 | #' @param from_date A string
57 | #' @param to_date A string, default is set to today's date
58 | #'
59 | #' @return A \code{data.frame}
60 | #'
61 | #' @importFrom cranlogs cran_downloads
62 | #'
63 | #' @export
64 | #'
65 | #' @examples
66 | #' get_cran_data("rsconnect", from_date = (Sys.Date() - 10))
67 | #'
68 | get_cran_data <- function(package_names, from_date, to_date = Sys.Date()) {
69 | cran_downloads(
70 | package_names,
71 | from = from_date,
72 | to = as.character(to_date)
73 | )
74 | }
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/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 | golem::fill_desc(
17 | pkg_name = "cranstars", # The Name of the package containing the App
18 | pkg_title = "PKG_TITLE", # The Title of the package containing the App
19 | pkg_description = "PKG_DESC.", # The Description of the package containing the App
20 | author_first_name = "AUTHOR_FIRST", # Your First Name
21 | author_last_name = "AUTHOR_LAST", # Your Last Name
22 | author_email = "AUTHOR@MAIL.COM", # Your Email
23 | repo_url = NULL # The URL of the GitHub Repo (optional)
24 | )
25 |
26 | ## Set {golem} options ----
27 | golem::set_golem_options()
28 |
29 | ## Create Common Files ----
30 | ## See ?usethis for more information
31 | usethis::use_mit_license( name = "Golem User" ) # You can set another license here
32 | usethis::use_readme_rmd( open = FALSE )
33 | usethis::use_code_of_conduct()
34 | usethis::use_lifecycle_badge( "Experimental" )
35 | usethis::use_news_md( open = FALSE )
36 |
37 | ## Use git ----
38 | usethis::use_git()
39 |
40 | ## Init Testing Infrastructure ----
41 | ## Create a template for tests
42 | golem::use_recommended_tests()
43 |
44 | ## Use Recommended Packages ----
45 | golem::use_recommended_deps()
46 |
47 | ## Favicon ----
48 | # If you want to change the favicon (default is golem's one)
49 | golem::remove_favicon()
50 | golem::use_favicon() # path = "path/to/ico". Can be an online file.
51 |
52 | ## Add helper functions ----
53 | golem::use_utils_ui()
54 | golem::use_utils_server()
55 |
56 | # You're now set! ----
57 |
58 | # go to dev/02_dev.R
59 | rstudioapi::navigateToFile( "dev/02_dev.R" )
60 |
61 |
--------------------------------------------------------------------------------
/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 ftc_* 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("cranstars")
48 | devtools::build_vignettes()
49 |
50 | ## Code Coverage ----
51 | ## Set the code coverage service ("codecov" or "coveralls")
52 | usethis::use_coverage()
53 |
54 | ## CI ----
55 | ## Use this part of the script if you need to set up a CI
56 | ## service for your application
57 | ##
58 | ## (You'll need GitHub there)
59 | usethis::use_github()
60 |
61 | # GitHub Actions
62 | usethis::use_github_action()
63 | # Chose one of the three
64 | # See https://usethis.r-lib.org/reference/use_github_action.html
65 | usethis::use_github_action_check_release()
66 | usethis::use_github_action_check_standard()
67 | usethis::use_github_action_check_full()
68 | # Add action for PR
69 | usethis::use_github_action_pr_commands()
70 |
71 | # Travis CI
72 | usethis::use_travis()
73 | usethis::use_travis_badge()
74 |
75 | # AppVeyor
76 | usethis::use_appveyor()
77 | usethis::use_appveyor_badge()
78 |
79 | # Circle CI
80 | usethis::use_circleci()
81 | usethis::use_circleci_badge()
82 |
83 | # Jenkins
84 | usethis::use_jenkins()
85 |
86 | # GitLab CI
87 | usethis::use_gitlab_ci()
88 |
89 | # You're now set! ----
90 | # go to dev/03_deploy.R
91 | rstudioapi::navigateToFile("dev/03_deploy.R")
92 |
93 |
--------------------------------------------------------------------------------
/R/utils.R:
--------------------------------------------------------------------------------
1 |
2 | #' Get only package name from repo name
3 | #'
4 | #' @param repo \code{string} The repo name, e.g., \bold{"rstudio/rsconnect"}
5 | #'
6 | #' @return \code{string} The package name, e.g., \bold{"rsconnect"}
7 | #' @export
8 | #'
9 | #' @examples
10 | #' get_cran_name("rsconnect/rstudio")
11 | get_cran_name <- function(repo) {
12 | broken <- strsplit(repo, "/")
13 | unlist(lapply(broken, "[[", 2))
14 | }
15 |
16 |
17 | orange <- "#DA7C30"
18 |
19 | feedback <- function(r) {
20 | repo = get_cran_name(r$repo)
21 | adjectives <- c("outstanding", "great", "first-class", "awesome", "luminous",
22 | "extraordinary", "polished", "stylish", "magnificent", "stunning",
23 | "superb", "praiseworthy", "marvelous", "sensational", "remarkable")
24 | ds <- r$cran_dl %>%
25 | filter(.data$package == repo) %>%
26 | select(count) %>%
27 | pull() %>%
28 | sum()
29 | if ( ds > 10000 ) paste0("{", repo, "} ", " is ", sample(adjectives, 1), "!")
30 | else "Is the clock ticking?"
31 | }
32 |
33 |
34 | make_yrmon <- function(date) {
35 | paste0(format(date, "%b"), ", ", format(date, "%Y"))
36 | }
37 |
38 |
39 | get_most_count <- function(data) {
40 | d <- data %>%
41 | filter(count == max(count, na.rm = TRUE)) %>%
42 | slice(1) %>%
43 | select(date, count) %>%
44 | mutate(
45 | date = format(date, "%d %b, %Y"),
46 | count = ifelse(count > 1000, paste0(round(count/1000, 1), "k"), count)
47 | )
48 | paste(d$date, " (", d$count, ")")
49 | }
50 |
51 | get_most_month <- function(data) {
52 | d <- data %>%
53 | count(.data$yrmon, wt = count) %>%
54 | filter(n == max(n, na.rm = TRUE)) %>%
55 | slice(1) %>%
56 | mutate(n = ifelse(n > 1000, paste0(round(n/1000, 1), "k"), n))
57 | paste(d$yrmon, "(", d$n, ")")
58 | }
59 |
60 | get_avg <- function(data) {
61 | avg <- NULL
62 | avg2 <- NULL
63 | data %>%
64 | group_by(.data$yrmon) %>%
65 | summarise(avg = mean(count, na.rm = TRUE)) %>%
66 | #glimpse() %>%
67 | summarise(avg2 = mean(avg)) %>%
68 | mutate(avg2 = ifelse(avg2 > 1000, paste0(round(avg2/1000, 1), "k"), round(avg2, 1))) %>%
69 | pull()
70 | }
71 |
72 |
73 |
74 | #' Theme for the github calendar plot
75 | #'
76 | #' @param base_size \code{numeric} Base font size
77 | #' @param base_family \code{string} Base font family
78 | #'
79 | #' @importFrom ggplot2 theme_bw
80 | theme_calendar <- function(base_size = 15, base_family = "sans") {
81 | ret <- theme_bw(base_family = base_family, base_size = base_size) +
82 | theme(legend.background = element_blank(),
83 | legend.key = element_blank(),
84 | panel.background = element_blank(),
85 | panel.border = element_blank(),
86 | strip.background = element_blank(),
87 | plot.background = element_blank(),
88 | axis.line = element_blank(),
89 | panel.grid = element_blank())
90 | ret
91 | }
--------------------------------------------------------------------------------
/R/fct_make_plots.R:
--------------------------------------------------------------------------------
1 |
2 |
3 | #' Title
4 | #'
5 | #' @param r \code{reactiveValues} object with 4 slots, repo, date, cran_dl & gh_stars
6 | #'
7 | #' @importFrom dplyr filter
8 | #' @importFrom highcharter hchart hcaes hc_title hc_subtitle hc_caption
9 | #'
10 | #' @return \code{ggplot}
11 | #' @export
12 | #'
13 |
14 | cran_plot <- function(r) {
15 | repo <- get_cran_name(r$repo)
16 | date_range = r$date
17 |
18 |
19 | r$cran_dl %>%
20 | filter(
21 | .data$package == repo,
22 | date >= date_range[1] & date <= date_range[2]
23 | ) %>%
24 | hchart(type = "line",
25 | hcaes(x = date, y = count, group = .data$package),
26 | color = orange) %>%
27 | hc_title(text = "CRAN Downloads", style = list(fontFamily = "IBM Plex Sans",
28 | fontSize = "18px", fontWeight = "bold",
29 | color = "#292e1eff"),
30 | align = "left", x = 30) %>%
31 | hc_subtitle(text = paste0("CRAN downloads data for {", repo, "}"),
32 | style = list(fontFamily = "IBM Plex Sans", fontSize = "15px"),
33 | align = "left", x = 30) %>%
34 | hc_caption(text = feedback(r), style = list(fontFamily = "IBM Plex Sans", fontSize = "13px"),
35 | align = "right")
36 |
37 | # title = "CRAN Downloads",
38 | # subtitle = paste0("CRAN downloads for {", repo, "}")
39 | # ) +
40 | # theme_minimal(base_size = 18, base_family = "sans")
41 | }
42 |
43 |
44 |
45 | #' Title
46 | #'
47 | #' @param r \code{reactiveValues} object with 4 slots, repo, date, cran_dl & gh_stars
48 | #'
49 | #' @return \code{ggplot}
50 | #'
51 | #' @importFrom lubridate year week day
52 | #' @import ggplot2
53 | #'
54 | #' @export
55 | #'
56 | gh_plot <- function(r) {
57 | #praise = paste0("{", repo, "} ", " is ", sample(adjectives, 1), "!")
58 |
59 | ## for R-CMD-check
60 | n_stars <- NULL
61 |
62 | repo = r$repo
63 | date_range = r$date
64 |
65 | start = date_range[1]
66 | end = date_range[2]
67 | all_dates <- data.frame(date = seq(start, end, by = "day"))
68 |
69 | stars <- r$gh_stars %>%
70 | filter(.data$package == repo)
71 |
72 | joined <- all_dates %>%
73 | left_join(stars) %>%
74 | mutate(year = year(date), week = week(date), day = weekdays(date, TRUE)) %>%
75 | filter(date >= date_range[1] & date <= date_range[2])
76 |
77 |
78 | joined %>%
79 | ggplot(aes(x = week, y = day, fill = n_stars)) +
80 |
81 | scale_fill_gradient(
82 | low = "#c1f5ca",
83 | high = "#366E39",
84 | na.value = "grey90",
85 | limits = c(0, max(joined$n_stars)
86 | )) +
87 |
88 | geom_tile(color = "white", size = 0.4) +
89 | facet_wrap("year", ncol = 1) +
90 | scale_x_continuous(
91 | expand = c(0, 0),
92 | breaks = seq(1, 52, length = 12),
93 | labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
94 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")) +
95 | scale_y_discrete(
96 | expand = c(0, 0),
97 | #breaks = seq(1, 7),
98 | labels = c("Thu", "Wed", "Tue", "Mon", "Sun", "Sat", "Fri"),
99 | ) +
100 | labs(
101 | title = "Github Stars (in a github calendar plot)",
102 | subtitle = paste0("Stars for {", repo, "}")
103 | ) +
104 | theme_calendar() +
105 | theme(axis.title = element_blank(),
106 | axis.ticks = element_blank(),
107 | legend.position = "bottom",
108 | legend.key.width = unit(1, "cm"),
109 | strip.text = element_text(hjust = 0.01, face = "bold", size = 15),
110 | title = element_text(size = 18),
111 | plot.subtitle = element_text(color = "#666666"),
112 | legend.title = element_blank())
113 | }
114 |
--------------------------------------------------------------------------------
/R/mod_sidebar.R:
--------------------------------------------------------------------------------
1 | #' sidebar UI Function
2 | #'
3 | #' @description Module for the sidebar. The main data processing is handled by it.
4 | #'
5 | #' @param id Module's ID
6 | #'
7 | #' @import shiny
8 | #' @importFrom shinyjs hidden
9 |
10 | #'
11 | #' @noRd
12 | mod_sidebar_ui <- function(id){
13 | ns <- NS(id)
14 | tagList(
15 | tags$h3("Overview"),
16 | tags$p("This app shows CRAN downloads & Github Stars statistics for a given package (repo)."),
17 | tags$p("You can check out some tidyverse packages that comes with the app.",
18 | "And if you have a package on CRAN, see how its doing."),
19 | selectizeInput(
20 | inputId = ns("repo"),
21 | label = "Repo",
22 | choices = cranstars::repos$tidypacks
23 | ),
24 | dateRangeInput(
25 | inputId = ns("date"),
26 | label = "Date Range",
27 | min = "2010-01-01",
28 | max = Sys.Date() - 3,
29 | start = "2018-01-01",
30 | end = Sys.Date() - 3,
31 | startview = "year"
32 | ),
33 | hidden(textInput(
34 | inputId = ns("my_repo"),
35 | label = "Your Repo",
36 | placeholder = "e.g., rstudio/rsconnect",
37 | value = "dreamRs/esquisse"
38 | )),
39 | hidden(actionButton(
40 | inputId = ns("go"),
41 | label = "Go"
42 | )),
43 | checkboxInput(
44 | inputId = ns("check_my_repo"),
45 | label = "Let's see some other packages, possibly mine!"
46 | ),
47 | uiOutput(ns("downloading"), style="height:100px;"),
48 | tags$p("Because the data from github is downloaded page by page,
49 | the more stars you have, the longer you'll have to wait."),
50 | tags$blockquote("Popularity is a curse sometimes",
51 | style = "color: #8a8a8a; font-size:14px;"),
52 | tags$p("I'll leave it to you to ponder on that."),
53 | tags$hr(),
54 | tags$footer(
55 | tags$img(src = "https://raw.githubusercontent.com/rstudio/hex-stickers/master/thumbs/shiny.png",
56 | height = "60px", width = "50px", style = "padding-top:0 !important; float:right"),
57 | tags$img(src = "https://raw.githubusercontent.com/ThinkR-open/golem/master/inst/rstudio/templates/project/golem.png",
58 | height = "60px", width = "50px", style = "padding-top:0 !important; float:right"),
59 | tags$a(href = "https://github.com/shahreyar-abeer/cranstars", target = "_blank",
60 | icon("link"), "Github"),
61 | HTML(" "),
62 | tags$a(href = "https://thewaywer.rbind.io/projects/cranstars-a-first-golem-app-possibly-cran/",
63 | target = "_blank", icon("link"), "Blog Post"),
64 | br(),
65 | br(),
66 | "by",
67 | tags$a(href = "https://thewaywer.rbind.io/about/", "Zauad Shahreer Abeer"),
68 | style = "text-align: center;"
69 | )
70 | )
71 | }
72 |
73 | #' sidebar Server Function
74 | #'
75 | #' @param id Module's ID
76 | #' @param input,output,session Internal parameters for {shiny}.
77 | #'
78 | #' @importFrom shinyjs show hide
79 | #' @importFrom waiter Waiter spin_loaders
80 | #' @noRd
81 | mod_sidebar_server <- function(id, r){
82 | moduleServer(
83 | id = id,
84 | function(input, output, session) {
85 | ns <- session$ns
86 |
87 |
88 | w = Waiter$new(
89 | id = ns("downloading"),
90 | color = "transparent",
91 | html = tagList(
92 | spin_loaders(id = 38, color = "#292e1eff"),
93 | tags$p("connecting & downloading", style = "color:#292e1eff")
94 | )
95 | )
96 |
97 | observeEvent(input$repo, {
98 |
99 | if( isFALSE(input$check_my_repo) ) {
100 | r$repo = input$repo
101 | r$cran_dl = cranstars::cran_dl_data
102 | r$gh_stars = cranstars::gh_stars_data
103 | }
104 |
105 | })
106 |
107 | observeEvent(input$date, {
108 | r$date = input$date
109 | })
110 |
111 | observeEvent(input$check_my_repo, {
112 | if ( isTRUE(input$check_my_repo) ) {
113 | hide("repo", anim = TRUE, animType = "fade", time = .2)
114 | show("my_repo", anim = TRUE, animType = "slide", time = 1.2)
115 | show("go", anim = TRUE, animType = "slide", time = 1.2)
116 | } else {
117 | hide("my_repo", anim = TRUE, animType = "fade", time = .2)
118 | hide("go", anim = TRUE, animType = "fade", time = .2)
119 | show("repo", anim = TRUE, animType = "slide", time = 1.2)
120 | }
121 | })
122 |
123 | observeEvent(input$go, {
124 |
125 | r$cran_dl <- NULL
126 | r$gh_stars <- NULL
127 |
128 | if ( isTRUE(input$check_my_repo) ) {
129 |
130 | package = input$my_repo
131 | date = input$date
132 |
133 | if ( isTRUE(grepl("/", package)) ) {
134 |
135 | gh_stars <- reactive({
136 | w$show()
137 | g <- get_gh_stars(package)
138 | cran_name <- get_cran_name(package)
139 | r$cran_dl <- get_cran_data(
140 | package_names = cran_name,
141 | from_date = date[1],
142 | to_date = date[2]
143 | )
144 | g
145 | })
146 |
147 | output$downloading <- renderUI({
148 | # ...
149 | })
150 |
151 | if( inherits(gh_stars(), "try-error") ) {
152 | showModal(modalDialog(
153 | title = "Error! Cannot Proceed",
154 | icon("warning"),
155 | "Please make sure the github repo exists.",
156 | style="background: #ff9966"
157 | ))
158 | } else {
159 |
160 | if( sum(r$cran_dl$count) == 0 ) {
161 | showModal(modalDialog(
162 | title = "Is it on CRAN yet?",
163 | icon("warning"),
164 | "0 downloads from CRAN. Maybe its not on CRAN yet, is it?",
165 | style = "background: #ffcc00"
166 | ))
167 | } else {
168 | showModal(modalDialog(
169 | title = "Success!",
170 | icon("check"),
171 | " Data successfully downloaded from CRAN & Github.",
172 | style = "background: #99cc33;"
173 | ))
174 | }
175 | r$repo <- package
176 | r$gh_stars <- gh_stars()
177 | }
178 | } else {
179 | showModal(modalDialog(
180 | title = "Error! Cannot Proceed.",
181 | icon("warning"),
182 | "Please provide your repo name in the form", tags$em('rstudio/rsconnect'),
183 | style="background: #ff9966"
184 | ))
185 | }
186 | }
187 | })
188 | }
189 | )
190 | }
191 |
192 |
193 |
--------------------------------------------------------------------------------