Initiate New Template Project

api_key.txt ignored
This commit is contained in:
Carlos R. Mercado 2022-08-15 10:57:07 -04:00
commit 1b83d59d02
15 changed files with 1913 additions and 0 deletions

1
.Rprofile Normal file
View File

@ -0,0 +1 @@
source("renv/activate.R")

51
.gitignore vendored Normal file
View File

@ -0,0 +1,51 @@
# History files
.Rhistory
.Rapp.history
# Session Data files
.RData
.RDataTmp
# User-specific files
.Ruserdata
# Example code in package build process
*-Ex.R
# Output files from R CMD build
/*.tar.gz
# Output files from R CMD check
/*.Rcheck/
# RStudio files
.Rproj.user/
# produced vignettes
vignettes/*.html
vignettes/*.pdf
# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
.httr-oauth
# knitr and R markdown default cache directories
*_cache/
/cache/
# Temporary files created by R markdown
*.utf8.md
*.knit.md
# R Environment Variables
.Renviron
# pkgdown site
docs/
# translation temp files
po/*~
# RStudio Connect folder
rsconnect/
api_key.txt

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Carlos R. Mercado
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

24
README.md Normal file
View File

@ -0,0 +1,24 @@
# Flipside Crypto R Shiny Template
This is a minimalized R Shiny template app to keep Flipside Shiny apps on-brand. It includes the following:
- shiny_template R Project
- app directory with the template app
- renv lock file (includes shroomDK)
- relevant gitignores (e.g., ignoring api_key.txt for shroomDK)
## App
The app folder serves as your template R Shiny app. It can be run as is to show filler text and a filler chart. The folder contains:
- www/
- fliplogo.jpg - the Flipside icon
- rudderstack.js - requires shinyjs; used to track clicks to the flipside website
- styles.css - template css including a few shiny specific outputs (e.g., .container-fluid) review and take care editing
- global.R - default global file for miscellaneous functions and objects.
- ui.R - default user interface file, includes both critical tags (e.g., header bar) and optional template code (e.g., chart div)
- server.R - minimized server file w/ empty server function
## renv
use `renv::restore()` (ensure you have renv downloaded) to restore the app libraries prior to testing on your machine. Note: shroomDK is in active development. This template may fall behind in shroomDK versions. Review the [documentation](https://github.com/FlipsideCrypto/sdk/tree/main/r/shroomDK) for more info.

13
app/global.R Normal file
View File

@ -0,0 +1,13 @@
library(shinyjs)
library(shroomDK)
library(data.table)
library(plotly)
library(dplyr)
library(reactable)
example_data <- data.frame(
x = 1:100,
y = abs(rnorm(100)),
z = abs(ceiling(rnorm(100))),
a = as.factor(sample(LETTERS[1:5], 100, replace = TRUE))
)

96
app/server.R Normal file
View File

@ -0,0 +1,96 @@
library(shiny)
source("global.R")
server <- function(input, output, session) {
# example_data in global
# Example SCATTERPLOT
output$exscatter <- renderPlotly({
plot_ly(data = example_data,
x = ~x,
y = ~y,
color = ~a,
size = ~z,
text = ~paste("Y: ", y,
'<br>Size:', z,
'<br>Color:', a)
) %>%
layout(title = "",
yaxis = list(title = "Y Label",
showgrid = FALSE,
color = "#FFF"),
xaxis = list(title = "X Label",
showgrid = TRUE,
color = "#FFF",
gridcolor = "#202933"),
plot_bgcolor = "transparent",
paper_bgcolor = "transparent",
legend = list(font = list(color = '#FFFFFF'))) %>%
# variety of useful config options to be aware of
# https://plotly.com/r/configuration-options/
config(scrollZoom = FALSE,
# displayModeBar = TRUE, # default is hover
toImageButtonOptions = list(format= 'svg', # one of png, svg, jpeg, webp
filename= 'template_image',
height= 500,
width= 700,
scale= 1),
displaylogo = FALSE
)
})
# Example BARPLOT
# more details - https://plotly.com/r/bar-charts/
output$exbar <- renderPlotly({
ed <- example_data %>%
group_by(a, z, .add = TRUE) %>%
summarize(n = n())
plot_ly(data = ed,
x = ~as.character(a),
y = ~n,
color = ~as.factor(z),
text = ~paste("Letter: ", a,
'<br>Category:', z,
'<br>Number:', n)
) %>%
layout(title = "",
yaxis = list(title = "Y Label",
showgrid = FALSE,
color = "#FFF"),
xaxis = list(title = "X Label",
showticklabels = TRUE,
color = "#FFF",
gridcolor = "#202933"),
plot_bgcolor = "transparent",
paper_bgcolor = "transparent",
legend = list(font = list(color = '#FFFFFF'))) %>%
# variety of useful config options to be aware of
# https://plotly.com/r/configuration-options/
config(scrollZoom = FALSE,
# displayModeBar = TRUE, # default is hover
toImageButtonOptions = list(format= 'svg', # one of png, svg, jpeg, webp
filename= 'template_image',
height= 500,
width= 700,
scale= 1),
displaylogo = FALSE
)
})
# Simple reactable - see: styles.css for formatting
output$myreactable <- renderReactable({
reactable(example_data,
borderless = TRUE,
outlined = FALSE
)
})
}

165
app/ui.R Normal file
View File

@ -0,0 +1,165 @@
library(shiny)
source("global.R")
# Define UI ------
shinyUI(fluidPage(
title = 'TITLE',
useShinyjs(),
tags$head(
tags$link(rel = 'stylesheet', type = 'text/css', href = 'styles.css'),
tags$link(rel = 'icon', href = 'fliptrans.png'),
tags$link(rel = 'stylesheet', href = 'https://fonts.googleapis.com/css?family=Roboto+Mono'),
tags$link(rel = 'stylesheet', href = 'https://fonts.googleapis.com/css?family=Inter')
),
tags$head(tags$script(src = 'rudderstack.js')),
tags$style(type='text/css',
'.shiny-output-error { visibility: hidden; }',
'.shiny-output-error:before { visibility: hidden; }'
),
withTags({
header(class='top-banner',
section(
a(class='fs-logo', href='https://www.flipsidecrypto.com',
'Powered by Flipside Crypto', onclick = 'rudderstack.track("ntr-click-flipside-icon")'),
section(class='socials',
a(class='twitter', href='https://twitter.com/flipsidecrypto',
'Twitter', onclick = 'rudderstack.track("ntr-click-twitter-icon")'),
a(class='linkedin', href='https://www.linkedin.com/company/flipside-crypto',
'LinkedIn', onclick = 'rudderstack.track("ntr-click-linkedin-icon")'),
a(class='discord', href='https://flipsidecrypto.com/discord',
'Discord', onclick = 'rudderstack.track("ntr-click-discord-icon")'),
a(href='https://app.flipsidecrypto.com/auth/signup/', # redirects to xyz signup
'Sign Up', onclick = 'rudderstack.track("ntr-click-signup-icon")')
)
)
)
}),
# APP LABEL HERE -----------------------------------
withTags({
section(class='hero',
p("HERO IMAGE HERE"),
h1(
class='header',
'TAGLINE TITLE',
),
p('TAGLINE'),
)
}),
# APP START HERE -----------------------------------
## EXAMPLE INPUTS DIV ----
div( # re-using chart classes to make smoother outlining
class = 'chart-container',
div(
class = 'chart-block',
fluidRow(
column(3,
selectInput(inputId = 'selectinput',
label = "Select Input",
choices = c("a","b","c"),
selected = NULL, multiple = TRUE)
),
column(3,
radioButtons(inputId = 'selectinput',
label = "Select Input",
choices = c("a","b","c"),
selected = NULL)
),
column(3,
textAreaInput(inputId = "textarea",label = "Text Area", value = "area input")
),
column(3,
textInput(inputId = "text",label = "Text", value = "text input")
)
),
fluidRow(
column(3,
dateInput(inputId = 'selectdate',
label = "Select Date",
value = Sys.Date(),
min = Sys.Date()- 100,
max = Sys.Date() + 100)
),
column(3,
dateRangeInput(inputId = "daterange",
label = "Date Range",
start = Sys.Date()-1,
end = Sys.Date()+1,
min = Sys.Date()- 100,
max = Sys.Date() + 100)
),
column(3,
numericInput(inputId = "numericinput",
label = "Number",
value = 1,
min = -10,
max = 10,
step = 1)
),
column(3,
checkboxGroupInput(inputId = 'checkboxgroup',
label = "Checkbox Group",
choices = c(1,2,3),
selected = 1,
choiceNames = c("One","Two","Three"))
)
)
)),
## EXAMPLE PLOTLY Scatterplot CHART ----
div(
class = 'chart-container',
div(
class = 'chart-block',
div(class = 'chart-title', span('SCATTERPLOT EXAMPLE')),
div(
class = 'chart',
plotlyOutput('exscatter')
)
)
),
# EXAMPLE PLOTLY Barplot CHART ----
div(
class = 'chart-container',
div(
class = 'chart-block',
div(class = 'chart-title', span('BARPLOT EXAMPLE')),
div(
class = 'chart',
plotlyOutput('exbar')
)
)
),
# EXAMPLE FORM DIV
# EXAMPLE REACTABLE TABLE DIV ----
# re-using chart classes to make smoother
div(
class = 'chart-container',
div(
class = 'chart-block',
div(class = 'chart-title', span('Reactable Table EXAMPLE')),
reactableOutput("myreactable")
)
)
# EXAMPLE WALLET CONNECT DIV ----
) # end FluidPage
) # end shinyUI

BIN
app/www/fliplogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

3
app/www/rudderstack.js Normal file
View File

@ -0,0 +1,3 @@
!function(){var e=window.rudderanalytics=window.rudderanalytics||[];e.methods=["load","page","track","identify","alias","group","ready","reset","getAnonymousId","setAnonymousId"],e.factory=function(t){return function(){var r=Array.prototype.slice.call(arguments);return r.unshift(t),e.push(r),e}};for(var t=0;t<e.methods.length;t++){var r=e.methods[t];e[r]=e.factory(r)}e.loadJS=function(e,t){var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.rudderlabs.com/v1.1/rudder-analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a)},e.loadJS(),
e.load('29a6Pl6fLlx4iYiOdfxRt0IBad9','https://flipsidecrworumuyiulf.dataplane.rudderstack.com'),
e.page()}();

237
app/www/styles.css Normal file
View File

@ -0,0 +1,237 @@
/*******************/
/*PUT CUSTOM CLASSES HERE*/
/*******************/
/*******************/
/* GENERAL Page */
/*******************/
body {
background-color: #10151A;
background-attachment:fixed;
background-size: auto 100%;
background-position: center;
padding-left: 10%;
padding-right: 10%;
font-family: 'Inter';
color: #FFFFFF;
padding-bottom: 6rem;
}
a {
background: transparent;
color: #FFFFFF;
}
hr {
margin: 2%;
background: #10151A;
opacity: 0.5;
border: 1px solid #637381;
}
.container-fluid {
background-color: #10151A;
max-width: 1000px;
margin: 0 auto;
height: 100%;
padding-top: 48px;
z-index: 1;
}
/******************/
/* Header Bar */
/******************/
.top-banner {
background: #161E26;
height: 48px;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.top-banner > section {
align-items: center;
display: flex;
height: 100%;
justify-content: space-between;
margin: 0 auto;
padding: 0 15px;
max-width: 1000px;
}
.top-banner a {
background-color: transparent;
}
.top-banner a:hover, .top-banner a:active {
color: #FFF;
text-decoration: none;
}
.fs-logo {
background: url("data:image/svg+xml,%3Csvg%20width=%2216%22%20height=%2216%22%20viewBox=%220%200%2016%2016%22%20fill=%22none%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M7.52088%2016C6.92112%2016%206.32136%2015.8477%205.78403%2015.543C4.56881%2014.8541%202.95205%2013.9375%201.73686%2013.2485C0.662092%2012.6393%200%2011.5131%200%2010.2945L0%205.70554C0%204.48686%200.662092%203.36075%201.73686%202.75144C2.95205%202.06249%204.56881%201.14593%205.78403%200.456977C6.85876%20-0.152326%208.18288%20-0.152326%209.25772%200.456977C10.4729%201.14593%2012.0896%202.06249%2013.3048%202.75144C13.8258%203.04684%2014.2499%203.46376%2014.5486%203.95377L9.23759%207.01154C8.19179%207.61937%207.52579%208.76857%207.52088%209.95417L7.52088%2016ZM15.0416%209.50549L15.0416%2010.2945C15.0416%2011.5131%2014.3796%2012.6393%2013.3048%2013.2485C12.0896%2013.9375%2010.4729%2014.8541%209.25772%2015.543C9.14451%2015.6072%209.02845%2015.6646%208.91038%2015.7153L8.91038%2014.29C8.91339%2013.5805%209.30794%2012.8961%209.9254%2012.5304C11.4418%2011.6491%2012.9692%2010.7862%2014.4855%209.90463C14.6838%209.78731%2014.8695%209.65331%2015.0416%209.50549ZM15.013%205.26806C15.0319%205.412%2015.0416%205.558%2015.0416%205.70554L15.0416%206.53731C15.0379%207.43057%2014.5405%208.27874%2013.7728%208.73349C12.2564%209.6148%2010.729%2010.4778%209.21271%2011.3591C9.10783%2011.4212%209.00693%2011.4887%208.91038%2011.5609L8.91038%209.95691C8.91333%209.23703%209.31737%208.5508%209.94293%208.1872L15.013%205.26806Z%22%20fill=%22white%22/%3E%3C/svg%3E") no-repeat left center;
padding-left: 24px;
}
.socials {
align-items: center;
display: flex;
}
.socials a {
display: inline-block;
margin: 0 0.5em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
width: 24px;
}
.socials a:last-child {
margin-right: 0;
overflow: visible;
text-indent: 0;
width: auto;
}
.socials a:last-child::before {
content: "|";
margin: 0 0.5em;
}
.twitter {
color: red;
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.94 18.7051C11.4989 18.7212 13.9577 17.7118 15.7672 15.9023C17.5767 14.0928 18.5861 11.634 18.57 9.0751V8.6326C19.2267 8.15147 19.7951 7.56023 20.25 6.8851C19.6316 7.15555 18.9773 7.33491 18.3075 7.4176C19.0177 6.99444 19.5506 6.32835 19.8075 5.5426C19.1456 5.93968 18.4199 6.21883 17.6625 6.3676C16.6139 5.25027 14.9461 4.97529 13.5943 5.69684C12.2425 6.41839 11.5428 7.95705 11.8875 9.4501C9.16635 9.31653 6.63036 8.03218 4.9125 5.9176C4.02372 7.46019 4.4828 9.42766 5.9625 10.4176C5.43646 10.3973 4.92259 10.2534 4.4625 9.9976V10.0351C4.45287 11.6359 5.56204 13.0263 7.125 13.3726C6.63573 13.5042 6.12322 13.5247 5.625 13.4326C6.07495 14.7902 7.33014 15.7181 8.76 15.7501C7.56691 16.7105 6.08407 17.2391 4.5525 17.2501C4.28396 17.2423 4.01606 17.2198 3.75 17.1826C5.30022 18.1703 7.1019 18.691 8.94 18.6826' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
}
.linkedin {
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19.6575 3.00002H4.3425C3.61669 2.99566 3.02038 3.57199 3 4.29752V19.65C3.01639 20.3773 3.61508 20.9559 4.3425 20.9475H19.6575C20.3849 20.9559 20.9836 20.3773 21 19.65V4.29752C20.9796 3.57199 20.3833 2.99566 19.6575 3.00002ZM8.3325 18.3075H5.6925V9.75002H8.3325V18.3075ZM7.0425 8.55752C6.19951 8.55777 5.51036 7.88527 5.49 7.04252C5.47516 6.6264 5.63396 6.22284 5.92839 5.92841C6.22282 5.63398 6.62638 5.47519 7.0425 5.49002C7.8561 5.54668 8.48716 6.2232 8.48716 7.03877C8.48716 7.85435 7.8561 8.53087 7.0425 8.58752V8.55752ZM18.36 18.255H15.75V14.07C15.75 13.0725 15.75 11.775 14.355 11.775C12.96 11.775 12.75 12.87 12.75 13.9725V18.21H10.08V9.75002H12.57V10.875H12.6225C13.1428 9.97149 14.1234 9.43343 15.165 9.48002C17.8575 9.48002 18.36 11.28 18.36 13.5675V18.255Z' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
}
.discord {
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.2354 11.1801C10.0175 11.1617 9.79902 11.2095 9.60868 11.3172C9.41833 11.425 9.26496 11.5877 9.16863 11.7841C9.07229 11.9804 9.0375 12.2013 9.06879 12.4178C9.10008 12.6343 9.19601 12.8363 9.34401 12.9973C9.492 13.1584 9.68518 13.271 9.89825 13.3205C10.1113 13.3699 10.3344 13.3539 10.5382 13.2744C10.742 13.195 10.917 13.0559 11.0405 12.8753C11.1639 12.6948 11.2299 12.4811 11.2299 12.2624C11.2358 12.126 11.2147 11.9898 11.1678 11.8616C11.121 11.7334 11.0493 11.6157 10.957 11.5151C10.8646 11.4146 10.7533 11.3333 10.6295 11.2758C10.5057 11.2184 10.3718 11.1858 10.2354 11.1801ZM13.7942 11.1801C13.5762 11.1617 13.3578 11.2095 13.1674 11.3172C12.9771 11.425 12.8237 11.5877 12.7274 11.7841C12.631 11.9804 12.5962 12.2013 12.6275 12.4178C12.6588 12.6343 12.7548 12.8363 12.9028 12.9973C13.0508 13.1584 13.2439 13.271 13.457 13.3205C13.6701 13.3699 13.8931 13.3539 14.0969 13.2744C14.3007 13.195 14.4758 13.0559 14.5992 12.8753C14.7226 12.6948 14.7887 12.4811 14.7887 12.2624C14.7945 12.126 14.7734 11.9898 14.7266 11.8616C14.6797 11.7334 14.6081 11.6157 14.5157 11.5151C14.4234 11.4146 14.3121 11.3333 14.1883 11.2758C14.0645 11.2184 13.9306 11.1858 13.7942 11.1801Z' fill='%23F4F6F8'/%3E%3Cpath d='M18.5325 3H5.46751C5.20438 3.00063 4.94396 3.05308 4.70111 3.15436C4.45826 3.25564 4.23774 3.40376 4.05213 3.59027C3.86653 3.77678 3.71948 3.99802 3.61939 4.24136C3.51929 4.4847 3.46811 4.74538 3.46876 5.0085V18.1905C3.46811 18.4536 3.51929 18.7143 3.61939 18.9576C3.71948 19.201 3.86653 19.4222 4.05213 19.6087C4.23774 19.7952 4.45826 19.9434 4.70111 20.0446C4.94396 20.1459 5.20438 20.1984 5.46751 20.199H16.524L16.0073 18.3953L17.2553 19.5555L18.435 20.6475L20.5313 22.5V5.0085C20.5319 4.74538 20.4807 4.4847 20.3806 4.24136C20.2805 3.99802 20.1335 3.77678 19.9479 3.59027C19.7623 3.40376 19.5418 3.25564 19.2989 3.15436C19.0561 3.05308 18.7956 3.00063 18.5325 3ZM14.769 15.7335C14.769 15.7335 14.418 15.3142 14.1255 14.9437C14.8322 14.7774 15.4573 14.3664 15.8903 13.7835C15.5394 14.017 15.1633 14.21 14.769 14.3588C14.3154 14.5524 13.8411 14.693 13.3553 14.778C12.5202 14.9317 11.6638 14.9284 10.83 14.7682C10.3405 14.6725 9.86073 14.5321 9.39676 14.349C9.15219 14.255 8.91437 14.1442 8.68501 14.0175C8.65576 13.998 8.62651 13.9882 8.59726 13.9688C8.58259 13.9614 8.56937 13.9515 8.55826 13.9395C8.38276 13.842 8.28526 13.7738 8.28526 13.7738C8.70251 14.3444 9.30604 14.7514 9.99151 14.9242C9.69901 15.2948 9.33826 15.7335 9.33826 15.7335C8.75909 15.7491 8.18497 15.6221 7.66642 15.3636C7.14787 15.1052 6.70078 14.7233 6.36451 14.2515C6.39616 12.2749 6.87623 10.3313 7.76851 8.56725C8.55372 7.95055 9.51103 7.59283 10.5083 7.5435L10.6058 7.6605C9.66755 7.89268 8.79203 8.32877 8.04151 8.93775C8.04151 8.93775 8.25601 8.82075 8.61676 8.655C9.3176 8.33509 10.0645 8.12779 10.83 8.04075C10.8846 8.02945 10.94 8.02293 10.9958 8.02125C11.6491 7.93613 12.3103 7.92958 12.9653 8.00175C13.9952 8.11938 14.9922 8.43735 15.9 8.93775C15.1875 8.3578 14.36 7.93574 13.4723 7.6995L13.6088 7.5435C14.606 7.59283 15.5633 7.95055 16.3485 8.56725C17.2408 10.3313 17.7209 12.2749 17.7525 14.2515C17.4135 14.7229 16.9645 15.1043 16.4446 15.3625C15.9246 15.6208 15.3494 15.7482 14.769 15.7335Z' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
}
.hero {
margin: 1.5em 0;
text-align: center;
}
.hero > p {
color: #E5E5E5;
font-size: 20px;
margin-top: 1em;
}
.header {
margin: 0;
color: #03FFFF;
font-family: 'Inter', sans-serif;
text-align: center;
}
/*****************/
/* GENERAL Forms */
/*****************/
/* helps with dropdown menu conflicts w/ body */
.dropdown-menu {
background-color: #333;
}
.form-group {
padding: 10px 10px 0;
margin: none !important;
}
.form-control {
background: #10151A;
border: 1px solid #03FFFF;
border-radius: 4px;
font-family: Roboto Mono !important;
color: #FFFFFF;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}
/******************/
/* GENERAL Charts */
/******************/
.chart-block {
background: #171E25;
border: 2px solid rgba(45, 109, 135, 0.5);
border-radius: 16px;
}
.chart-block > .row > .col-sm-6 {
padding: 0;
}
.col-sm-6 > .chart {
padding: 0;
}
.chart-title {
font-family: Inter;
font-style: normal;
font-weight: 600;
font-size: 20px;
line-height: 150%;
color: white;
padding: 32px 32px 20px;
}
.chart {
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
padding: 0 32px;
background: linear-gradient(
360deg
, rgba(16, 21, 26, 1) 0%
, rgba(16, 21, 26, 1) 11%
, rgba(0, 204, 255, 0.3) 11%
, rgba(0, 204, 255, 0) 100%
);
}
.chart-container {
padding: 10px 0;;
}
/******************/
/* REACTABLE Tables */
/******************/
.rt-page-button-current {
color: #FFF;
}
.rt-thead {
background-color: #10151A;
color: #FFFFFF;
}
.ReactTable {
background-color: #171e25;
color: #C4CDD5;
border: none;
}
.rt-th {
border: 0px solid #000000 !important;
padding-top: 15px;
padding-bottom: 15px;
font-weight: 400;
font-family: Inter;
}
.rt-tr {
padding-top: 5px;
padding-bottom: 5px;
}
.rt-pagination {
margin: 0;
background: #171e25;
opacity: 0.5;
border-bottom: 1px solid #C4CDD5;
border-top: 1px solid #C4CDD5;
}

13
real-time-data-lag.Rproj Normal file
View File

@ -0,0 +1,13 @@
Version: 1.0
RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: pdfLaTeX

331
renv.lock Normal file
View File

@ -0,0 +1,331 @@
{
"R": {
"Version": "4.2.1",
"Repositories": [
{
"Name": "CRAN",
"URL": "https://cran.rstudio.com"
}
]
},
"Packages": {
"R6": {
"Package": "R6",
"Version": "2.5.1",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "470851b6d5d0ac559e9d01bb352b4021",
"Requirements": []
},
"Rcpp": {
"Package": "Rcpp",
"Version": "1.0.9",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "e9c08b94391e9f3f97355841229124f2",
"Requirements": []
},
"base64enc": {
"Package": "base64enc",
"Version": "0.1-3",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "543776ae6848fde2f48ff3816d0628bc",
"Requirements": []
},
"bslib": {
"Package": "bslib",
"Version": "0.4.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "be5ee090716ce1671be6cd5d7c34d091",
"Requirements": [
"cachem",
"htmltools",
"jquerylib",
"jsonlite",
"memoise",
"rlang",
"sass"
]
},
"cachem": {
"Package": "cachem",
"Version": "1.0.6",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "648c5b3d71e6a37e3043617489a0a0e9",
"Requirements": [
"fastmap",
"rlang"
]
},
"commonmark": {
"Package": "commonmark",
"Version": "1.8.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "2ba81b120c1655ab696c935ef33ea716",
"Requirements": []
},
"crayon": {
"Package": "crayon",
"Version": "1.5.1",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "8dc45fd8a1ee067a92b85ef274e66d6a",
"Requirements": []
},
"digest": {
"Package": "digest",
"Version": "0.6.29",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "cf6b206a045a684728c3267ef7596190",
"Requirements": []
},
"ellipsis": {
"Package": "ellipsis",
"Version": "0.3.2",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "bb0eec2fe32e88d9e2836c2f73ea2077",
"Requirements": [
"rlang"
]
},
"fastmap": {
"Package": "fastmap",
"Version": "1.1.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "77bd60a6157420d4ffa93b27cf6a58b8",
"Requirements": []
},
"fontawesome": {
"Package": "fontawesome",
"Version": "0.3.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "a36c4a3eade472039a3ec8cb824e6dc4",
"Requirements": [
"htmltools",
"rlang"
]
},
"fs": {
"Package": "fs",
"Version": "1.5.2",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "7c89603d81793f0d5486d91ab1fc6f1d",
"Requirements": []
},
"glue": {
"Package": "glue",
"Version": "1.6.2",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "4f2596dfb05dac67b9dc558e5c6fba2e",
"Requirements": []
},
"htmltools": {
"Package": "htmltools",
"Version": "0.5.3",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "6496090a9e00f8354b811d1a2d47b566",
"Requirements": [
"base64enc",
"digest",
"fastmap",
"rlang"
]
},
"httpuv": {
"Package": "httpuv",
"Version": "1.6.5",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "97fe71f0a4a1c9890e6c2128afa04bc0",
"Requirements": [
"R6",
"Rcpp",
"later",
"promises"
]
},
"jquerylib": {
"Package": "jquerylib",
"Version": "0.1.4",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "5aab57a3bd297eee1c1d862735972182",
"Requirements": [
"htmltools"
]
},
"jsonlite": {
"Package": "jsonlite",
"Version": "1.8.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "d07e729b27b372429d42d24d503613a0",
"Requirements": []
},
"later": {
"Package": "later",
"Version": "1.3.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "7e7b457d7766bc47f2a5f21cc2984f8e",
"Requirements": [
"Rcpp",
"rlang"
]
},
"lifecycle": {
"Package": "lifecycle",
"Version": "1.0.1",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "a6b6d352e3ed897373ab19d8395c98d0",
"Requirements": [
"glue",
"rlang"
]
},
"magrittr": {
"Package": "magrittr",
"Version": "2.0.3",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "7ce2733a9826b3aeb1775d56fd305472",
"Requirements": []
},
"memoise": {
"Package": "memoise",
"Version": "2.0.1",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c",
"Requirements": [
"cachem",
"rlang"
]
},
"mime": {
"Package": "mime",
"Version": "0.12",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "18e9c28c1d3ca1560ce30658b22ce104",
"Requirements": []
},
"promises": {
"Package": "promises",
"Version": "1.2.0.1",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "4ab2c43adb4d4699cf3690acd378d75d",
"Requirements": [
"R6",
"Rcpp",
"later",
"magrittr",
"rlang"
]
},
"rappdirs": {
"Package": "rappdirs",
"Version": "0.3.3",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "5e3c5dc0b071b21fa128676560dbe94d",
"Requirements": []
},
"renv": {
"Package": "renv",
"Version": "0.15.5",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "6a38294e7d12f5d8e656b08c5bd8ae34",
"Requirements": []
},
"rlang": {
"Package": "rlang",
"Version": "1.0.4",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "6539dd8c651e67e3b55b5ffea106362b",
"Requirements": []
},
"sass": {
"Package": "sass",
"Version": "0.4.2",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "1b191143d7d3444d504277843f3a95fe",
"Requirements": [
"R6",
"fs",
"htmltools",
"rappdirs",
"rlang"
]
},
"shiny": {
"Package": "shiny",
"Version": "1.7.2",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "4f7970a3edb0a153ac6b376785a1944a",
"Requirements": [
"R6",
"bslib",
"cachem",
"commonmark",
"crayon",
"ellipsis",
"fastmap",
"fontawesome",
"glue",
"htmltools",
"httpuv",
"jsonlite",
"later",
"lifecycle",
"mime",
"promises",
"rlang",
"sourcetools",
"withr",
"xtable"
]
},
"sourcetools": {
"Package": "sourcetools",
"Version": "0.1.7",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "947e4e02a79effa5d512473e10f41797",
"Requirements": []
},
"withr": {
"Package": "withr",
"Version": "2.5.0",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "c0e49a9760983e81e55cdd9be92e7182",
"Requirements": []
},
"xtable": {
"Package": "xtable",
"Version": "1.8-4",
"Source": "Repository",
"Repository": "CRAN",
"Hash": "b8acdf8af494d9ec19ccb2481a9b11c2",
"Requirements": []
}
}
}

6
renv/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
library/
local/
cellar/
lock/
python/
staging/

942
renv/activate.R Normal file
View File

@ -0,0 +1,942 @@
local({
# the requested version of renv
version <- "0.15.5"
# the project directory
project <- getwd()
# figure out whether the autoloader is enabled
enabled <- local({
# first, check config option
override <- getOption("renv.config.autoloader.enabled")
if (!is.null(override))
return(override)
# next, check environment variables
# TODO: prefer using the configuration one in the future
envvars <- c(
"RENV_CONFIG_AUTOLOADER_ENABLED",
"RENV_AUTOLOADER_ENABLED",
"RENV_ACTIVATE_PROJECT"
)
for (envvar in envvars) {
envval <- Sys.getenv(envvar, unset = NA)
if (!is.na(envval))
return(tolower(envval) %in% c("true", "t", "1"))
}
# enable by default
TRUE
})
if (!enabled)
return(FALSE)
# avoid recursion
if (identical(getOption("renv.autoloader.running"), TRUE)) {
warning("ignoring recursive attempt to run renv autoloader")
return(invisible(TRUE))
}
# signal that we're loading renv during R startup
options(renv.autoloader.running = TRUE)
on.exit(options(renv.autoloader.running = NULL), add = TRUE)
# signal that we've consented to use renv
options(renv.consent = TRUE)
# load the 'utils' package eagerly -- this ensures that renv shims, which
# mask 'utils' packages, will come first on the search path
library(utils, lib.loc = .Library)
# unload renv if it's already been loaded
if ("renv" %in% loadedNamespaces())
unloadNamespace("renv")
# load bootstrap tools
`%||%` <- function(x, y) {
if (is.environment(x) || length(x)) x else y
}
bootstrap <- function(version, library) {
# attempt to download renv
tarball <- tryCatch(renv_bootstrap_download(version), error = identity)
if (inherits(tarball, "error"))
stop("failed to download renv ", version)
# now attempt to install
status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity)
if (inherits(status, "error"))
stop("failed to install renv ", version)
}
renv_bootstrap_tests_running <- function() {
getOption("renv.tests.running", default = FALSE)
}
renv_bootstrap_repos <- function() {
# check for repos override
repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA)
if (!is.na(repos))
return(repos)
# check for lockfile repositories
repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity)
if (!inherits(repos, "error") && length(repos))
return(repos)
# if we're testing, re-use the test repositories
if (renv_bootstrap_tests_running())
return(getOption("renv.tests.repos"))
# retrieve current repos
repos <- getOption("repos")
# ensure @CRAN@ entries are resolved
repos[repos == "@CRAN@"] <- getOption(
"renv.repos.cran",
"https://cloud.r-project.org"
)
# add in renv.bootstrap.repos if set
default <- c(FALLBACK = "https://cloud.r-project.org")
extra <- getOption("renv.bootstrap.repos", default = default)
repos <- c(repos, extra)
# remove duplicates that might've snuck in
dupes <- duplicated(repos) | duplicated(names(repos))
repos[!dupes]
}
renv_bootstrap_repos_lockfile <- function() {
lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock")
if (!file.exists(lockpath))
return(NULL)
lockfile <- tryCatch(renv_json_read(lockpath), error = identity)
if (inherits(lockfile, "error")) {
warning(lockfile)
return(NULL)
}
repos <- lockfile$R$Repositories
if (length(repos) == 0)
return(NULL)
keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1))
vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1))
names(vals) <- keys
return(vals)
}
renv_bootstrap_download <- function(version) {
# if the renv version number has 4 components, assume it must
# be retrieved via github
nv <- numeric_version(version)
components <- unclass(nv)[[1]]
# if this appears to be a development version of 'renv', we'll
# try to restore from github
dev <- length(components) == 4L
# begin collecting different methods for finding renv
methods <- c(
renv_bootstrap_download_tarball,
if (dev)
renv_bootstrap_download_github
else c(
renv_bootstrap_download_cran_latest,
renv_bootstrap_download_cran_archive
)
)
for (method in methods) {
path <- tryCatch(method(version), error = identity)
if (is.character(path) && file.exists(path))
return(path)
}
stop("failed to download renv ", version)
}
renv_bootstrap_download_impl <- function(url, destfile) {
mode <- "wb"
# https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715
fixup <-
Sys.info()[["sysname"]] == "Windows" &&
substring(url, 1L, 5L) == "file:"
if (fixup)
mode <- "w+b"
utils::download.file(
url = url,
destfile = destfile,
mode = mode,
quiet = TRUE
)
}
renv_bootstrap_download_cran_latest <- function(version) {
spec <- renv_bootstrap_download_cran_latest_find(version)
message("* Downloading renv ", version, " ... ", appendLF = FALSE)
type <- spec$type
repos <- spec$repos
info <- tryCatch(
utils::download.packages(
pkgs = "renv",
destdir = tempdir(),
repos = repos,
type = type,
quiet = TRUE
),
condition = identity
)
if (inherits(info, "condition")) {
message("FAILED")
return(FALSE)
}
# report success and return
message("OK (downloaded ", type, ")")
info[1, 2]
}
renv_bootstrap_download_cran_latest_find <- function(version) {
# check whether binaries are supported on this system
binary <-
getOption("renv.bootstrap.binary", default = TRUE) &&
!identical(.Platform$pkgType, "source") &&
!identical(getOption("pkgType"), "source") &&
Sys.info()[["sysname"]] %in% c("Darwin", "Windows")
types <- c(if (binary) "binary", "source")
# iterate over types + repositories
for (type in types) {
for (repos in renv_bootstrap_repos()) {
# retrieve package database
db <- tryCatch(
as.data.frame(
utils::available.packages(type = type, repos = repos),
stringsAsFactors = FALSE
),
error = identity
)
if (inherits(db, "error"))
next
# check for compatible entry
entry <- db[db$Package %in% "renv" & db$Version %in% version, ]
if (nrow(entry) == 0)
next
# found it; return spec to caller
spec <- list(entry = entry, type = type, repos = repos)
return(spec)
}
}
# if we got here, we failed to find renv
fmt <- "renv %s is not available from your declared package repositories"
stop(sprintf(fmt, version))
}
renv_bootstrap_download_cran_archive <- function(version) {
name <- sprintf("renv_%s.tar.gz", version)
repos <- renv_bootstrap_repos()
urls <- file.path(repos, "src/contrib/Archive/renv", name)
destfile <- file.path(tempdir(), name)
message("* Downloading renv ", version, " ... ", appendLF = FALSE)
for (url in urls) {
status <- tryCatch(
renv_bootstrap_download_impl(url, destfile),
condition = identity
)
if (identical(status, 0L)) {
message("OK")
return(destfile)
}
}
message("FAILED")
return(FALSE)
}
renv_bootstrap_download_tarball <- function(version) {
# if the user has provided the path to a tarball via
# an environment variable, then use it
tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA)
if (is.na(tarball))
return()
# allow directories
info <- file.info(tarball, extra_cols = FALSE)
if (identical(info$isdir, TRUE)) {
name <- sprintf("renv_%s.tar.gz", version)
tarball <- file.path(tarball, name)
}
# bail if it doesn't exist
if (!file.exists(tarball)) {
# let the user know we weren't able to honour their request
fmt <- "* RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist."
msg <- sprintf(fmt, tarball)
warning(msg)
# bail
return()
}
fmt <- "* Bootstrapping with tarball at path '%s'."
msg <- sprintf(fmt, tarball)
message(msg)
tarball
}
renv_bootstrap_download_github <- function(version) {
enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE")
if (!identical(enabled, "TRUE"))
return(FALSE)
# prepare download options
pat <- Sys.getenv("GITHUB_PAT")
if (nzchar(Sys.which("curl")) && nzchar(pat)) {
fmt <- "--location --fail --header \"Authorization: token %s\""
extra <- sprintf(fmt, pat)
saved <- options("download.file.method", "download.file.extra")
options(download.file.method = "curl", download.file.extra = extra)
on.exit(do.call(base::options, saved), add = TRUE)
} else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
fmt <- "--header=\"Authorization: token %s\""
extra <- sprintf(fmt, pat)
saved <- options("download.file.method", "download.file.extra")
options(download.file.method = "wget", download.file.extra = extra)
on.exit(do.call(base::options, saved), add = TRUE)
}
message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE)
url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version)
name <- sprintf("renv_%s.tar.gz", version)
destfile <- file.path(tempdir(), name)
status <- tryCatch(
renv_bootstrap_download_impl(url, destfile),
condition = identity
)
if (!identical(status, 0L)) {
message("FAILED")
return(FALSE)
}
message("OK")
return(destfile)
}
renv_bootstrap_install <- function(version, tarball, library) {
# attempt to install it into project library
message("* Installing renv ", version, " ... ", appendLF = FALSE)
dir.create(library, showWarnings = FALSE, recursive = TRUE)
# invoke using system2 so we can capture and report output
bin <- R.home("bin")
exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
r <- file.path(bin, exe)
args <- c(
"--vanilla", "CMD", "INSTALL", "--no-multiarch",
"-l", shQuote(path.expand(library)),
shQuote(path.expand(tarball))
)
output <- system2(r, args, stdout = TRUE, stderr = TRUE)
message("Done!")
# check for successful install
status <- attr(output, "status")
if (is.numeric(status) && !identical(status, 0L)) {
header <- "Error installing renv:"
lines <- paste(rep.int("=", nchar(header)), collapse = "")
text <- c(header, lines, output)
writeLines(text, con = stderr())
}
status
}
renv_bootstrap_platform_prefix <- function() {
# construct version prefix
version <- paste(R.version$major, R.version$minor, sep = ".")
prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
# include SVN revision for development versions of R
# (to avoid sharing platform-specific artefacts with released versions of R)
devel <-
identical(R.version[["status"]], "Under development (unstable)") ||
identical(R.version[["nickname"]], "Unsuffered Consequences")
if (devel)
prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
# build list of path components
components <- c(prefix, R.version$platform)
# include prefix if provided by user
prefix <- renv_bootstrap_platform_prefix_impl()
if (!is.na(prefix) && nzchar(prefix))
components <- c(prefix, components)
# build prefix
paste(components, collapse = "/")
}
renv_bootstrap_platform_prefix_impl <- function() {
# if an explicit prefix has been supplied, use it
prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA)
if (!is.na(prefix))
return(prefix)
# if the user has requested an automatic prefix, generate it
auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA)
if (auto %in% c("TRUE", "True", "true", "1"))
return(renv_bootstrap_platform_prefix_auto())
# empty string on failure
""
}
renv_bootstrap_platform_prefix_auto <- function() {
prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity)
if (inherits(prefix, "error") || prefix %in% "unknown") {
msg <- paste(
"failed to infer current operating system",
"please file a bug report at https://github.com/rstudio/renv/issues",
sep = "; "
)
warning(msg)
}
prefix
}
renv_bootstrap_platform_os <- function() {
sysinfo <- Sys.info()
sysname <- sysinfo[["sysname"]]
# handle Windows + macOS up front
if (sysname == "Windows")
return("windows")
else if (sysname == "Darwin")
return("macos")
# check for os-release files
for (file in c("/etc/os-release", "/usr/lib/os-release"))
if (file.exists(file))
return(renv_bootstrap_platform_os_via_os_release(file, sysinfo))
# check for redhat-release files
if (file.exists("/etc/redhat-release"))
return(renv_bootstrap_platform_os_via_redhat_release())
"unknown"
}
renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) {
# read /etc/os-release
release <- utils::read.table(
file = file,
sep = "=",
quote = c("\"", "'"),
col.names = c("Key", "Value"),
comment.char = "#",
stringsAsFactors = FALSE
)
vars <- as.list(release$Value)
names(vars) <- release$Key
# get os name
os <- tolower(sysinfo[["sysname"]])
# read id
id <- "unknown"
for (field in c("ID", "ID_LIKE")) {
if (field %in% names(vars) && nzchar(vars[[field]])) {
id <- vars[[field]]
break
}
}
# read version
version <- "unknown"
for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) {
if (field %in% names(vars) && nzchar(vars[[field]])) {
version <- vars[[field]]
break
}
}
# join together
paste(c(os, id, version), collapse = "-")
}
renv_bootstrap_platform_os_via_redhat_release <- function() {
# read /etc/redhat-release
contents <- readLines("/etc/redhat-release", warn = FALSE)
# infer id
id <- if (grepl("centos", contents, ignore.case = TRUE))
"centos"
else if (grepl("redhat", contents, ignore.case = TRUE))
"redhat"
else
"unknown"
# try to find a version component (very hacky)
version <- "unknown"
parts <- strsplit(contents, "[[:space:]]")[[1L]]
for (part in parts) {
nv <- tryCatch(numeric_version(part), error = identity)
if (inherits(nv, "error"))
next
version <- nv[1, 1]
break
}
paste(c("linux", id, version), collapse = "-")
}
renv_bootstrap_library_root_name <- function(project) {
# use project name as-is if requested
asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE")
if (asis)
return(basename(project))
# otherwise, disambiguate based on project's path
id <- substring(renv_bootstrap_hash_text(project), 1L, 8L)
paste(basename(project), id, sep = "-")
}
renv_bootstrap_library_root <- function(project) {
prefix <- renv_bootstrap_profile_prefix()
path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA)
if (!is.na(path))
return(paste(c(path, prefix), collapse = "/"))
path <- renv_bootstrap_library_root_impl(project)
if (!is.null(path)) {
name <- renv_bootstrap_library_root_name(project)
return(paste(c(path, prefix, name), collapse = "/"))
}
renv_bootstrap_paths_renv("library", project = project)
}
renv_bootstrap_library_root_impl <- function(project) {
root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA)
if (!is.na(root))
return(root)
type <- renv_bootstrap_project_type(project)
if (identical(type, "package")) {
userdir <- renv_bootstrap_user_dir()
return(file.path(userdir, "library"))
}
}
renv_bootstrap_validate_version <- function(version) {
loadedversion <- utils::packageDescription("renv", fields = "Version")
if (version == loadedversion)
return(TRUE)
# assume four-component versions are from GitHub; three-component
# versions are from CRAN
components <- strsplit(loadedversion, "[.-]")[[1]]
remote <- if (length(components) == 4L)
paste("rstudio/renv", loadedversion, sep = "@")
else
paste("renv", loadedversion, sep = "@")
fmt <- paste(
"renv %1$s was loaded from project library, but this project is configured to use renv %2$s.",
"Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.",
"Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
sep = "\n"
)
msg <- sprintf(fmt, loadedversion, version, remote)
warning(msg, call. = FALSE)
FALSE
}
renv_bootstrap_hash_text <- function(text) {
hashfile <- tempfile("renv-hash-")
on.exit(unlink(hashfile), add = TRUE)
writeLines(text, con = hashfile)
tools::md5sum(hashfile)
}
renv_bootstrap_load <- function(project, libpath, version) {
# try to load renv from the project library
if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE))
return(FALSE)
# warn if the version of renv loaded does not match
renv_bootstrap_validate_version(version)
# load the project
renv::load(project)
TRUE
}
renv_bootstrap_profile_load <- function(project) {
# if RENV_PROFILE is already set, just use that
profile <- Sys.getenv("RENV_PROFILE", unset = NA)
if (!is.na(profile) && nzchar(profile))
return(profile)
# check for a profile file (nothing to do if it doesn't exist)
path <- renv_bootstrap_paths_renv("profile", profile = FALSE)
if (!file.exists(path))
return(NULL)
# read the profile, and set it if it exists
contents <- readLines(path, warn = FALSE)
if (length(contents) == 0L)
return(NULL)
# set RENV_PROFILE
profile <- contents[[1L]]
if (!profile %in% c("", "default"))
Sys.setenv(RENV_PROFILE = profile)
profile
}
renv_bootstrap_profile_prefix <- function() {
profile <- renv_bootstrap_profile_get()
if (!is.null(profile))
return(file.path("profiles", profile, "renv"))
}
renv_bootstrap_profile_get <- function() {
profile <- Sys.getenv("RENV_PROFILE", unset = "")
renv_bootstrap_profile_normalize(profile)
}
renv_bootstrap_profile_set <- function(profile) {
profile <- renv_bootstrap_profile_normalize(profile)
if (is.null(profile))
Sys.unsetenv("RENV_PROFILE")
else
Sys.setenv(RENV_PROFILE = profile)
}
renv_bootstrap_profile_normalize <- function(profile) {
if (is.null(profile) || profile %in% c("", "default"))
return(NULL)
profile
}
renv_bootstrap_path_absolute <- function(path) {
substr(path, 1L, 1L) %in% c("~", "/", "\\") || (
substr(path, 1L, 1L) %in% c(letters, LETTERS) &&
substr(path, 2L, 3L) %in% c(":/", ":\\")
)
}
renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) {
renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv")
root <- if (renv_bootstrap_path_absolute(renv)) NULL else project
prefix <- if (profile) renv_bootstrap_profile_prefix()
components <- c(root, renv, prefix, ...)
paste(components, collapse = "/")
}
renv_bootstrap_project_type <- function(path) {
descpath <- file.path(path, "DESCRIPTION")
if (!file.exists(descpath))
return("unknown")
desc <- tryCatch(
read.dcf(descpath, all = TRUE),
error = identity
)
if (inherits(desc, "error"))
return("unknown")
type <- desc$Type
if (!is.null(type))
return(tolower(type))
package <- desc$Package
if (!is.null(package))
return("package")
"unknown"
}
renv_bootstrap_user_dir <- function() {
dir <- renv_bootstrap_user_dir_impl()
path.expand(chartr("\\", "/", dir))
}
renv_bootstrap_user_dir_impl <- function() {
# use local override if set
override <- getOption("renv.userdir.override")
if (!is.null(override))
return(override)
# use R_user_dir if available
tools <- asNamespace("tools")
if (is.function(tools$R_user_dir))
return(tools$R_user_dir("renv", "cache"))
# try using our own backfill for older versions of R
envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME")
for (envvar in envvars) {
root <- Sys.getenv(envvar, unset = NA)
if (!is.na(root))
return(file.path(root, "R/renv"))
}
# use platform-specific default fallbacks
if (Sys.info()[["sysname"]] == "Windows")
file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv")
else if (Sys.info()[["sysname"]] == "Darwin")
"~/Library/Caches/org.R-project.R/R/renv"
else
"~/.cache/R/renv"
}
renv_json_read <- function(file = NULL, text = NULL) {
text <- paste(text %||% read(file), collapse = "\n")
# find strings in the JSON
pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
locs <- gregexpr(pattern, text, perl = TRUE)[[1]]
# if any are found, replace them with placeholders
replaced <- text
strings <- character()
replacements <- character()
if (!identical(c(locs), -1L)) {
# get the string values
starts <- locs
ends <- locs + attr(locs, "match.length") - 1L
strings <- substring(text, starts, ends)
# only keep those requiring escaping
strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE)
# compute replacements
replacements <- sprintf('"\032%i\032"', seq_along(strings))
# replace the strings
mapply(function(string, replacement) {
replaced <<- sub(string, replacement, replaced, fixed = TRUE)
}, strings, replacements)
}
# transform the JSON into something the R parser understands
transformed <- replaced
transformed <- gsub("[[{]", "list(", transformed)
transformed <- gsub("[]}]", ")", transformed)
transformed <- gsub(":", "=", transformed, fixed = TRUE)
text <- paste(transformed, collapse = "\n")
# parse it
json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]]
# construct map between source strings, replaced strings
map <- as.character(parse(text = strings))
names(map) <- as.character(parse(text = replacements))
# convert to list
map <- as.list(map)
# remap strings in object
remapped <- renv_json_remap(json, map)
# evaluate
eval(remapped, envir = baseenv())
}
renv_json_remap <- function(json, map) {
# fix names
if (!is.null(names(json))) {
lhs <- match(names(json), names(map), nomatch = 0L)
rhs <- match(names(map), names(json), nomatch = 0L)
names(json)[rhs] <- map[lhs]
}
# fix values
if (is.character(json))
return(map[[json]] %||% json)
# handle true, false, null
if (is.name(json)) {
text <- as.character(json)
if (text == "true")
return(TRUE)
else if (text == "false")
return(FALSE)
else if (text == "null")
return(NULL)
}
# recurse
if (is.recursive(json)) {
for (i in seq_along(json)) {
json[i] <- list(renv_json_remap(json[[i]], map))
}
}
json
}
# load the renv profile, if any
renv_bootstrap_profile_load(project)
# construct path to library root
root <- renv_bootstrap_library_root(project)
# construct library prefix for platform
prefix <- renv_bootstrap_platform_prefix()
# construct full libpath
libpath <- file.path(root, prefix)
# attempt to load
if (renv_bootstrap_load(project, libpath, version))
return(TRUE)
# load failed; inform user we're about to bootstrap
prefix <- paste("# Bootstrapping renv", version)
postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "")
header <- paste(prefix, postfix)
message(header)
# perform bootstrap
bootstrap(version, libpath)
# exit early if we're just testing bootstrap
if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA)))
return(TRUE)
# try again to load
if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
message("* Successfully installed and loaded renv ", version, ".")
return(renv::load())
}
# failed to download or load renv; warn the user
msg <- c(
"Failed to find an renv installation: the project will not be loaded.",
"Use `renv::activate()` to re-initialize the project."
)
warning(paste(msg, collapse = "\n"), call. = FALSE)
})

10
renv/settings.dcf Normal file
View File

@ -0,0 +1,10 @@
bioconductor.version:
external.libraries:
ignored.packages:
package.dependency.fields: Imports, Depends, LinkingTo
r.version:
snapshot.type: implicit
use.cache: TRUE
vcs.ignore.cellar: TRUE
vcs.ignore.library: TRUE
vcs.ignore.local: TRUE