Compare commits

...

9 Commits

24 changed files with 334 additions and 286 deletions

View File

@ -19,3 +19,4 @@ drafting
app app
^\.lintr$ ^\.lintr$
^CODE_OF_CONDUCT\.md$ ^CODE_OF_CONDUCT\.md$
^~/REDCapCAST/inst/shiny-examples/casting/rsconnect$

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ drafting
\.DS_Store \.DS_Store
.DS_Store .DS_Store
cran-comments.md cran-comments.md
~/REDCapCAST/inst/shiny-examples/casting/rsconnect

View File

@ -1,6 +1,6 @@
Package: REDCapCAST Package: REDCapCAST
Title: REDCap Castellated Data Handling Title: REDCap Castellated Data Handling And Metadata Casting
Version: 24.10.3 Version: 24.11.1
Authors@R: c( Authors@R: c(
person("Andreas Gammelgaard", "Damsbo", email = "agdamsbo@clin.au.dk", person("Andreas Gammelgaard", "Damsbo", email = "agdamsbo@clin.au.dk",
role = c("aut", "cre"),comment = c(ORCID = "0000-0002-7559-1154")), role = c("aut", "cre"),comment = c(ORCID = "0000-0002-7559-1154")),
@ -11,6 +11,7 @@ Description: Originally forked from the R part of 'REDCapRITS' by Paul Egeler.
'REDCap' database casting and handling of castellated data when using 'REDCap' database casting and handling of castellated data when using
repeated instruments and longitudinal projects. Keeps a focused data export repeated instruments and longitudinal projects. Keeps a focused data export
approach, by allowing to only export required data from the database. approach, by allowing to only export required data from the database.
Also for casting new REDCap databases based on datasets from other sources.
'REDCap' (Research Electronic Data Capture) is a secure, web-based software 'REDCap' (Research Electronic Data Capture) is a secure, web-based software
platform designed to support data capture for research studies, providing platform designed to support data capture for research studies, providing
1) an intuitive interface for validated data capture; 2) audit trails for 1) an intuitive interface for validated data capture; 2) audit trails for
@ -36,7 +37,7 @@ Suggests:
spelling, spelling,
glue, glue,
rhub, rhub,
shinythemes bslib
License: GPL (>= 3) License: GPL (>= 3)
Encoding: UTF-8 Encoding: UTF-8
LazyData: true LazyData: true

View File

@ -30,11 +30,9 @@ export(read_redcap_instrument)
export(read_redcap_tables) export(read_redcap_tables)
export(redcap_wider) export(redcap_wider)
export(sanitize_split) export(sanitize_split)
export(server_factory)
export(shiny_cast) export(shiny_cast)
export(split_non_repeating_forms) export(split_non_repeating_forms)
export(strsplitx) export(strsplitx)
export(ui_factory)
importFrom(REDCapR,redcap_event_instruments) importFrom(REDCapR,redcap_event_instruments)
importFrom(REDCapR,redcap_metadata_read) importFrom(REDCapR,redcap_metadata_read)
importFrom(REDCapR,redcap_read) importFrom(REDCapR,redcap_read)

12
NEWS.md
View File

@ -1,16 +1,24 @@
# REDCapCAST 24.10.4 # REDCapCAST 24.11.1
Revised tests. Revised tests.
Documentation has been slightly updated to highlight the shiny app for casting REDCap metadata. I am working on hosting my own Shiny Server.
### Functions: ### Functions:
* Bug: 'form.name' specified to 'ds2dd_detailed()' was ignored. Corrected to only be ignored if 'form.sep' is specified. Added handling of re-occurring `form.sep` pattern. * Bug: 'form.name' specified to 'ds2dd_detailed()' was ignored. Corrected to only be ignored if 'form.sep' is specified. Added handling of re-occurring `form.sep` pattern.
* New: `export_redcap_instrument()` is a new version of `create_instrument_meta()`, that will only export a single instrument. Multiple instrument export can be done with `lapply()` or `purrr::map()`. This allows for inclusion of this functionality in the Shiny implementation and is easier to handle. `create_instrument_meta()` is deprecated. * New: `export_redcap_instrument()` is a new version of `create_instrument_meta()`, that will only export a single instrument. Multiple instrument export can be done with `lapply()` or `purrr::map()`. This allows for inclusion of this functionality in the Shiny implementation and is easier to handle. `create_instrument_meta()` is deprecated.
* Improved: `shiny_cast()` app has been updated to actually work if you install the package and not clones the whole repository.
### Shiny: ### Shiny:
* New: Export a REDCap instrument ready to add to your database based on an uploaded spreadsheet. This is thanks to the `export_redcap_instrument()` function. THis functionality is intended for projects in production and adding instruments should be handled manually and not by API upload. * New: Major overhaul of the app interface with the introduction of `bslib` for building the page. Also Detailed documentation added for the app workflow.
* New: Export a REDCap instrument ready to add to your database based on an uploaded spreadsheet. This is thanks to the `export_redcap_instrument()` function. This functionality is intended for projects in production and adding instruments should be handled manually and not by API upload.
* Bug: Export datadictionary with "" instead of "NA" for NAs. Upload to REDCap failed. Not anymore.
The shiny implementation is included with this package. Implementing in shinylive may be looked into again later. The shiny implementation is included with this package. Implementing in shinylive may be looked into again later.

View File

@ -1,40 +1,27 @@
utils::globalVariables(c("server"))
#' Shiny server factory
#'
#' @return shiny server
#' @export
server_factory <- function() {
source(here::here("app/server.R"))
server
}
#' UI factory for shiny app
#'
#' @return shiny ui
#' @export
ui_factory <- function() {
# require(ggplot2)
source(here::here("app/ui.R"))
}
#' Launch the included Shiny-app for database casting and upload #' Launch the included Shiny-app for database casting and upload
#' #'
#' @description
#' Wraps shiny::runApp()
#'
#' @param ... Arguments passed to shiny::runApp()
#'
#' @return shiny app #' @return shiny app
#' @export #' @export
#' #'
#' @examples #' @examples
#' # shiny_cast() #' # shiny_cast()
#' #'
shiny_cast <- function() { shiny_cast <- function(...) {
# shiny::runApp(appDir = here::here("app/"), launch.browser = TRUE) appDir <- system.file("shiny-examples", "casting", package = "REDCapCAST")
if (appDir == "") {
stop("Could not find example directory. Try re-installing `REDCapCAST`.", call. = FALSE)
}
shiny::shinyApp( shiny::runApp(appDir = appDir, ...)
ui_factory(),
server_factory()
)
} }
#' Helper to import files correctly #' Helper to import files correctly
#' #'
#' @param filenames file names #' @param filenames file names

View File

@ -23,6 +23,8 @@ I started working on this project as the castellated longitudinal data set was a
For any more advanced uses, consider using the [`redcapAPI`](https://github.com/vubiostat/redcapAPI) or [`REDCapR`](https://ouhscbbmc.github.io/REDCapR/) packages. For any more advanced uses, consider using the [`redcapAPI`](https://github.com/vubiostat/redcapAPI) or [`REDCapR`](https://ouhscbbmc.github.io/REDCapR/) packages.
What is unique in this package, is the work towards making it a lot easier to move data from different sources to REDCap databases: casting REDCap metadata based on a spreadsheet. This is all wrapped in `shiny_cast()`and [hosted for all to use here](https://agdamsbo.shinyapps.io/redcapcast/).
## Main functionality ## Main functionality
Here is just a short description of the main functions: Here is just a short description of the main functions:
@ -39,7 +41,7 @@ Here is just a short description of the main functions:
* `doc2dd()`: Converts a document table to data dictionary. This allows to specify instrument or whole data dictionary in text document, which for most is easier to work with and easily modifiable. Very much like a easy version of just working directly in the data dictionary file itself. * `doc2dd()`: Converts a document table to data dictionary. This allows to specify instrument or whole data dictionary in text document, which for most is easier to work with and easily modifiable. Very much like a easy version of just working directly in the data dictionary file itself.
* `shiny_cast()`: [Shiny](https://shiny.posit.co/) application to ease the process of converting a spreadsheet/data set to a REDCap database. The app runs locally and data is transferred securely. You can just create and upload the data dictionary, but you can also transfer the given data in the same process. The app is [hosted on shinyapps.io](https://agdamsbo.shinyapps.io/redcapcast/) ~~while I work on a [shinylive](https://posit-dev.github.io/r-shinylive/) implementation~~. * `shiny_cast()`: [Shiny](https://shiny.posit.co/) application to ease the process of converting a spreadsheet/data set to a REDCap database. The app runs locally and data is transferred securely. You can just create and upload the data dictionary, but you can also transfer the given data in the same process. The app is [hosted on shinyapps.io](https://agdamsbo.shinyapps.io/redcapcast/).
## Future ## Future
@ -60,6 +62,12 @@ require("remotes")
remotes::install_github("agdamsbo/REDCapCAST") remotes::install_github("agdamsbo/REDCapCAST")
``` ```
Launch the REDCapCAST app interface directly on your own machine:
```
REDCapCAST::shiny_cast()
```
## Code of Conduct ## Code of Conduct
Please note that the REDCapCAST project is released with a [Contributor Code of Conduct](https://agdamsbo.github.io/REDCapCAST/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. Please note that the REDCapCAST project is released with a [Contributor Code of Conduct](https://agdamsbo.github.io/REDCapCAST/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.

View File

@ -1,10 +0,0 @@
name: redcapcast
title:
username: agdamsbo
account: agdamsbo
server: shinyapps.io
hostUrl: https://api.shinyapps.io/v1
appId: 11351429
bundleId: 9264087
url: https://agdamsbo.shinyapps.io/redcapcast/
version: 1

144
app/ui.R
View File

@ -1,144 +0,0 @@
ui <- shiny::shinyUI(
shiny::fluidPage(
theme = shinythemes::shinytheme("flatly"),
## -----------------------------------------------------------------------------
## Application title
## -----------------------------------------------------------------------------
# customHeaderPanel(title = "REDCapCAST: data base creation and data upload from data set file",
# windowTitle = "REDCap database creator"
# ),
shiny::titlePanel(
title = shiny::div(
shiny::a(shiny::img(src = "logo.png"), href = "https://agdamsbo.github.io/REDCapCAST"),
"Easy REDCap database creation"
),
windowTitle = "REDCap database creator"
),
shiny::h4(
"THese are the functionalities to create and migrate data from a spreadsheet to a REDCap database:",
shiny::br(),
"1) create a REDCap data dictionary or instrument based on a spreadsheet (.csv/.xls(x)/.dta/.ods) and",
shiny::br(),
"2) upload said database file on a given REDCap server and upload the dataset via API access or download for all manual upload."
),
## -----------------------------------------------------------------------------
## Side panel
## -----------------------------------------------------------------------------
shiny::sidebarPanel(
shiny::h4("1) REDCap datadictionary and compatible dataset"),
shiny::fileInput("ds", "Choose data file",
multiple = FALSE,
accept = c(
".csv",
".xls",
".xlsx",
".dta",
".ods"
)
),
shiny::h6("Below you can download the dataset formatted for upload and the
corresponding data dictionary for a new data base, if you want to upload manually."),
# Button
shiny::downloadButton("downloadData", "Download data"),
# Button
shiny::downloadButton("downloadMeta", "Download data dictionary"),
# Button
shiny::downloadButton("downloadInstrument", "Download as instrument"),
# Horizontal line ----
shiny::tags$hr(),
shiny::h4("2) REDCap upload"),
shiny::h6("This tool is usable for now. Detailed instructions are coming."),
shiny::textInput(
inputId = "uri",
label = "URI",
value = "https://redcap.your.institution/api/"
),
shiny::textInput(
inputId = "api",
label = "API key",
value = ""
),
shiny::h6("An API key is an access key to the REDCap database. Please", shiny::a("see here for directions", href = "https://www.iths.org/news/redcap-tip/redcap-api-101/"), " to obtain an API key for your project."),
shiny::actionButton(
inputId = "upload.meta",
label = "Upload datadictionary", icon = shiny::icon("book-bookmark")
),
shiny::h6("Please note, that before uploading any real data, put your project
into production mode."),
shiny::actionButton(
inputId = "upload.data",
label = "Upload data", icon = shiny::icon("upload")
),
# Horizontal line ----
shiny::tags$hr()
),
shiny::mainPanel(
shiny::tabsetPanel(
## -----------------------------------------------------------------------------
## Summary tab
## -----------------------------------------------------------------------------
shiny::tabPanel(
"Summary",
shiny::h3("Data overview (first 20)"),
shiny::htmlOutput("data.tbl", container = shiny::span),
shiny::h3("Dictionary overview"),
shiny::htmlOutput("meta.tbl", container = shiny::span)
),
## -----------------------------------------------------------------------------
## Upload tab
## -----------------------------------------------------------------------------
shiny::tabPanel(
"Upload",
shiny::h3("Meta upload overview"),
shiny::htmlOutput("upload.meta.print", container = shiny::span),
shiny::h3("Data upload overview"),
shiny::htmlOutput("upload.data.print", container = shiny::span)
)
)
),
# close sidebarLayout
shiny::br(),
shiny::br(),
shiny::br(),
shiny::br(),
shiny::hr(),
shiny::tags$footer(shiny::strong("Disclaimer: "),
"This tool is aimed at demonstrating use of REDCapCAST. The app can be run locally or on a hosted server (will save no data anywhere). No responsibility for data loss or any other problems will be taken. Please contact me for support.",
shiny::br(),
shiny::a("License: GPL-3+", href = "https://agdamsbo.github.io/REDCapCAST/LICENSE.html"),
"|",
shiny::a("agdamsbo/REDCapCAST", href = "https://agdamsbo.github.io/REDCapCAST"),
"|",
shiny::a("Source", href = "https://github.com/agdamsbo/REDCapCAST"),
"|",
shiny::a("Contact", href = "https://andreas.gdamsbo.dk"),
align = "center",
style = "
position:fixed;
bottom:40px;
width:100%;
height:20px;
color: black;
padding: 0px;
background-color: White;
z-index: 100;
"
)
)
)

View File

@ -1,4 +1,4 @@
── R CMD check results ─────────────────────────────────────────────────────────────────────────────── REDCapCAST 24.10.1 ──── ── R CMD check results ─────────────────────────────────────────────────────────────────────────────── REDCapCAST 24.11.1 ────
Duration: 23.8s Duration: 23.8s
0 errors ✔ | 0 warnings ✔ | 0 notes ✔ 0 errors ✔ | 0 warnings ✔ | 0 notes ✔

View File

@ -9,3 +9,11 @@ mtcars_redcap |>
write.csv(here::here("data/mtcars_redcap.csv"), row.names = FALSE) write.csv(here::here("data/mtcars_redcap.csv"), row.names = FALSE)
usethis::use_data(mtcars_redcap, overwrite = TRUE) usethis::use_data(mtcars_redcap, overwrite = TRUE)
gtsummary::trial|>
dplyr::mutate(
record_id = dplyr::row_number()
) |>
dplyr::select(record_id, dplyr::everything())|>
write.csv(here::here("drafting/trials_redcap.csv"), row.names = FALSE)

View File

@ -11,3 +11,5 @@ redcapcast_data <- REDCapR::redcap_read(
# widen.data = FALSE) # widen.data = FALSE)
usethis::use_data(redcapcast_data, overwrite = TRUE) usethis::use_data(redcapcast_data, overwrite = TRUE)
write.csv(redcapcast_data,here::here("data/redcapcast_data.csv"),row.names = FALSE)

26
data/redcapcast_data.csv Normal file
View File

@ -0,0 +1,26 @@
"record_id","redcap_event_name","redcap_repeat_instrument","redcap_repeat_instance","cpr","inclusion","inclusion_time","dob","age","age_integer","sex","cohabitation","hypertension","diabetes","region","baseline_data_start_complete","mrs_assessed","mrs_date","mrs_score","mrs_complete","con_mrs","con_calc","consensus_complete","event_datetime","event_age","event_type","new_event_complete"
1,"inclusion",NA,NA,"1203401OB4",2023-03-13,12:38:49,1940-03-12,83.0023888238636,83,"female","Yes","No","Yes","East","Incomplete","Yes",2023-03-13,1,"Incomplete",NA,NA,NA,NA,NA,NA,NA
2,"inclusion",NA,NA,"0102342303",2023-03-01,10:38:57,1934-02-01,89.0778044723711,89,"male","Yes","No","No","South","Incomplete","Yes",2023-03-07,1,"Incomplete",NA,NA,NA,NA,NA,NA,NA
2,"follow1",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Yes",2023-03-09,3,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
2,"follow1","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:49:42,NA,"TIA","Incomplete"
3,"inclusion",NA,NA,"2301569823",2022-03-08,12:01:07,1956-01-23,66.1231921257795,66,"male","No","Yes","Yes","North","Incomplete",NA,NA,NA,"Incomplete",NA,NA,NA,NA,NA,NA,NA
3,"follow1",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Yes",2022-08-16,2,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
3,"follow2",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Yes",2023-03-13,1,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
3,"follow1","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:49:58,NA,"AIS","Incomplete"
3,"follow1","New Event (?)",2,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:01,NA,"ICH","Incomplete"
3,"follow2","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:05,NA,"ICH","Incomplete"
3,"follow2","New Event (?)",2,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:07,NA,"TIA","Incomplete"
3,"follow2","New Event (?)",3,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:09,NA,"AIS","Incomplete"
4,"inclusion",NA,NA,"0204051342",2023-03-14,20:39:19,1905-04-02,117.949033861065,117,"female",NA,NA,NA,NA,"Incomplete",NA,NA,NA,"Incomplete",NA,NA,NA,NA,NA,NA,NA
4,"follow1",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
4,"follow2",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
4,"follow1","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2001-04-11 08:39:05,96,"TIA","Complete"
4,"follow1","New Event (?)",2,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2010-04-11 08:39:25,105,"TIA","Complete"
4,"follow2","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:19,118,"AIS","Complete"
4,"follow2","New Event (?)",2,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:22,118,"ICH","Incomplete"
4,"follow2","New Event (?)",3,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-01-18 12:50:24,118,"Unknown","Complete"
5,"inclusion",NA,NA,"0201976043",2023-03-23,08:50:31,1897-01-02,126.21751302217,126,"male","No","Yes","Yes","East","Complete",NA,NA,NA,"Incomplete",NA,NA,NA,NA,NA,NA,NA
5,"follow1",NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,"Incomplete",NA,NA,"Incomplete",NA,NA,NA,NA
5,"follow1","New Event (?)",1,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-04-11 09:00:33,127,"AIS","Complete"
5,"follow1","New Event (?)",2,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,2024-04-11 09:00:41,127,"ICH","Complete"
6,"inclusion",NA,NA,"1202320122",2024-01-25,08:49:28,1932-02-12,91.952606829709,91,"female","No","Yes","No","East","Complete",NA,NA,NA,"Incomplete",NA,NA,NA,NA,NA,NA,NA
1 record_id redcap_event_name redcap_repeat_instrument redcap_repeat_instance cpr inclusion inclusion_time dob age age_integer sex cohabitation hypertension diabetes region baseline_data_start_complete mrs_assessed mrs_date mrs_score mrs_complete con_mrs con_calc consensus_complete event_datetime event_age event_type new_event_complete
2 1 inclusion NA NA 1203401OB4 2023-03-13 12:38:49 1940-03-12 83.0023888238636 83 female Yes No Yes East Incomplete Yes 2023-03-13 1 Incomplete NA NA NA NA NA NA NA
3 2 inclusion NA NA 0102342303 2023-03-01 10:38:57 1934-02-01 89.0778044723711 89 male Yes No No South Incomplete Yes 2023-03-07 1 Incomplete NA NA NA NA NA NA NA
4 2 follow1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA Yes 2023-03-09 3 Incomplete NA NA Incomplete NA NA NA NA
5 2 follow1 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:49:42 NA TIA Incomplete
6 3 inclusion NA NA 2301569823 2022-03-08 12:01:07 1956-01-23 66.1231921257795 66 male No Yes Yes North Incomplete NA NA NA Incomplete NA NA NA NA NA NA NA
7 3 follow1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA Yes 2022-08-16 2 Incomplete NA NA Incomplete NA NA NA NA
8 3 follow2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA Yes 2023-03-13 1 Incomplete NA NA Incomplete NA NA NA NA
9 3 follow1 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:49:58 NA AIS Incomplete
10 3 follow1 New Event (?) 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:01 NA ICH Incomplete
11 3 follow2 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:05 NA ICH Incomplete
12 3 follow2 New Event (?) 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:07 NA TIA Incomplete
13 3 follow2 New Event (?) 3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:09 NA AIS Incomplete
14 4 inclusion NA NA 0204051342 2023-03-14 20:39:19 1905-04-02 117.949033861065 117 female NA NA NA NA Incomplete NA NA NA Incomplete NA NA NA NA NA NA NA
15 4 follow1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA Incomplete NA NA Incomplete NA NA NA NA
16 4 follow2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA Incomplete NA NA Incomplete NA NA NA NA
17 4 follow1 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2001-04-11 08:39:05 96 TIA Complete
18 4 follow1 New Event (?) 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2010-04-11 08:39:25 105 TIA Complete
19 4 follow2 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:19 118 AIS Complete
20 4 follow2 New Event (?) 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:22 118 ICH Incomplete
21 4 follow2 New Event (?) 3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-01-18 12:50:24 118 Unknown Complete
22 5 inclusion NA NA 0201976043 2023-03-23 08:50:31 1897-01-02 126.21751302217 126 male No Yes Yes East Complete NA NA NA Incomplete NA NA NA NA NA NA NA
23 5 follow1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA Incomplete NA NA Incomplete NA NA NA NA
24 5 follow1 New Event (?) 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-04-11 09:00:33 127 AIS Complete
25 5 follow1 New Event (?) 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 2024-04-11 09:00:41 127 ICH Complete
26 6 inclusion NA NA 1202320122 2024-01-25 08:49:28 1932-02-12 91.952606829709 91 female No Yes No East Complete NA NA NA Incomplete NA NA NA NA NA NA NA

View File

@ -2,6 +2,7 @@ Andreas
Assesment Assesment
CMD CMD
Codecov Codecov
DEPRICATED
DOI DOI
DataDictionary DataDictionary
GStat GStat
@ -18,7 +19,6 @@ README
REDCap REDCap
REDCapR REDCapR
REDCapRITS REDCapRITS
UI
WD WD
al al
api api
@ -27,6 +27,7 @@ charater
cond cond
da da
dafault dafault
datadictionary
datetime datetime
demonstrational demonstrational
dir dir
@ -41,7 +42,6 @@ github
gues gues
hms hms
https https
immprovements
io io
jbi jbi
keyring keyring
@ -62,6 +62,7 @@ pre
readr readr
realising realising
renv renv
runApp
sel sel
sep sep
seperator seperator
@ -76,7 +77,6 @@ thorugh
tibble tibble
tidyverse tidyverse
trinker trinker
ui
uri uri
wil wil
ymd ymd

View File

@ -1,9 +1,12 @@
server <- function(input, output, session) { server <- function(input, output, session) {
require(REDCapCAST) require(REDCapCAST)
# bslib::bs_themer()
dat <- shiny::reactive({ dat <- shiny::reactive({
shiny::req(input$ds) shiny::req(input$ds)
output_staging$file <- "loaded"
read_input(input$ds$datapath) read_input(input$ds$datapath)
}) })
@ -29,15 +32,15 @@ server <- function(input, output, session) {
output$downloadData <- shiny::downloadHandler( output$downloadData <- shiny::downloadHandler(
filename = "data_ready.csv", filename = "data_ready.csv",
content = function(file) { content = function(file) {
write.csv(purrr::pluck(dd(), "data"), file, row.names = FALSE) write.csv(purrr::pluck(dd(), "data"), file, row.names = FALSE,na = "")
} }
) )
# Downloadable csv of data dictionary ---- # Downloadable csv of data dictionary ----
output$downloadMeta <- shiny::downloadHandler( output$downloadMeta <- shiny::downloadHandler(
filename = "dictionary_ready.csv", filename = "datadictionary_ready.csv",
content = function(file) { content = function(file) {
write.csv(purrr::pluck(dd(), "meta"), file, row.names = FALSE) write.csv(purrr::pluck(dd(), "meta"), file, row.names = FALSE,na = "")
} }
) )
@ -45,12 +48,22 @@ server <- function(input, output, session) {
output$downloadInstrument <- shiny::downloadHandler( output$downloadInstrument <- shiny::downloadHandler(
filename = paste0("REDCapCAST_instrument",Sys.Date(),".zip"), filename = paste0("REDCapCAST_instrument",Sys.Date(),".zip"),
content = function(file) { content = function(file) {
create_instrument_meta_single(purrr::pluck(dd(), "meta"), file) export_redcap_instrument(purrr::pluck(dd(), "meta"), file)
} }
) )
output_staging <- shiny::reactiveValues() output_staging <- shiny::reactiveValues()
output_staging$meta <- output_staging$data <- NA output_staging$meta <- output_staging$data <- output_staging$file <- NA
output$uploaded <- shiny::reactive({
if (is.na(output_staging$file)) {
"no"
} else {
"yes"
}
})
shiny::outputOptions(output, "uploaded", suspendWhenHidden = FALSE)
shiny::observeEvent(input$upload.meta,{ upload_meta() }) shiny::observeEvent(input$upload.meta,{ upload_meta() })

View File

@ -0,0 +1,104 @@
ui <-
bslib::page(
theme = bslib::bs_theme(preset = "united"),
title = "REDCap database creator",
bslib::page_navbar(
title = "Easy REDCap database creation",
sidebar = bslib::sidebar(width = 300,
shiny::h5("1) Database meta data"),
shiny::fileInput(
inputId = "ds",
label = "Upload spreadsheet",
multiple = FALSE,
accept = c(
".csv",
".xls",
".xlsx",
".dta",
".ods"
)
),
conditionalPanel(
condition = "output.uploaded=='yes'",
shiny::helpText("Below you can download the dataset formatted for upload and the
corresponding data dictionary for a new data base, if you want to upload manually."),
# Button
shiny::downloadButton("downloadData", "Download adjusted data"),
# Button
shiny::downloadButton("downloadMeta", "Download data dictionary"),
# Button
shiny::downloadButton("downloadInstrument", "Download as instrument"),
# Horizontal line ----
shiny::tags$hr(),
shiny::radioButtons(
inputId = "upload_redcap",
label = "Upload directly to REDCap server?",
selected = "no",
inline = TRUE,
choices = list(
"No" = "no",
"Yes" = "yes"
)
),
shiny::conditionalPanel(
condition = "input.upload_redcap=='yes'",
shiny::h4("2) Data base upload"),
shiny::helpText("This tool is usable for now. Detailed instructions are coming."),
shiny::textInput(
inputId = "uri",
label = "URI",
value = "https://redcap.your.institution/api/"
),
shiny::textInput(
inputId = "api",
label = "API key",
value = ""
),
shiny::helpText("An API key is an access key to the REDCap database. Please", shiny::a("see here for directions", href = "https://www.iths.org/news/redcap-tip/redcap-api-101/"), " to obtain an API key for your project."),
shiny::actionButton(
inputId = "upload.meta",
label = "Upload datadictionary", icon = shiny::icon("book-bookmark")
),
shiny::helpText("Please note, that before uploading any real data, put your project
into production mode."),
shiny::actionButton(
inputId = "upload.data",
label = "Upload data", icon = shiny::icon("upload")
)
)
),
shiny::br(),
shiny::br(),
shiny::br(),
shiny::p(
"License: ",shiny::a("GPL-3+", href = "https://agdamsbo.github.io/REDCapCAST/LICENSE.html")),
shiny::p(
shiny::a("Package documentation", href = "https://agdamsbo.github.io/REDCapCAST"))
),
bslib::nav_panel(
title = "Intro",
shiny::markdown(readLines("www/SHINYCAST.md")),
shiny::br()
),
bslib::nav_spacer(),
bslib::nav_panel(
title = "Data preview",
shiny::htmlOutput(outputId = "data.tbl", container = shiny::span)
),
bslib::nav_panel(
title = "Dictionary overview",
shiny::htmlOutput(outputId = "meta.tbl", container = shiny::span)
),
bslib::nav_panel(
title = "Upload",
shiny::h3("Meta upload overview"),
shiny::htmlOutput(outputId = "upload.meta.print", container = shiny::span),
shiny::h3("Data upload overview"),
shiny::htmlOutput(outputId = "upload.data.print", container = shiny::span)
)
)
)

View File

@ -0,0 +1,66 @@
# ![](logo.png) REDCapCAST app
Welcome to the REDCapCAST app to create/cast REDCap database metadata. This is app allows you to create a new REDCap data base or instrument based on a simple spreadsheet.
## Disclaimer
This tool is aimed at demonstrating use of REDCapCAST. The app can be run locally or on a hosted server (will save no data anywhere). No responsibility for data loss or any other problems will be taken.
Also, this tool will not produce a ready-for-prime-time database, but it will be a comprehensive framework with suggestions for data-classes. You will need to go through your database afterwards and take your time to ensure everything is as you'd expect and work as intended.
## Overview
The functions of this app can be described in two parts:
1. create REDCap metadata files like data dictionary or instrument based on a spreadsheet (.csv/.xls(x)/.dta/.ods) for download and manual upload to your REDCap server or
2. upload the created database file and data to a given REDCap server via API access.
## Getting started
On the left, you initially just find one single option to upload a spreadsheet. Having done this, you can then preview the uploaded data and generated data dictionary by selecting the relevant tab on the top right.
### REDCap database files creation
The spreadsheet column names will be adjusted to comply with REDCap naming criteria, and a renamed (adjusted) spreadsheet can be downloaded.
Based on the uploaded spreadsheet, the app will make a qualified guess on data classes and if the data is labelled (like .rda or .dta) all this information will be included in the data dictionary file. The default data format is "text".
If you want to add data to an existing database, an instrument can be created. This metadata file is identical to a data dictionary, but does not include a "record_id" field and is packaged as a .zip file, which is uploaded in the "Designer" interface in REDCap.
### Transferring directly to a REDCap database
Based on the API-functions in REDCap, you can upload your data dictionary and renamed data directly from this interface (no data is stored on the server, but consider launching this shiny app on your own machine after having installed the [REDCapCAST package](https://agdamsbo.github.io/REDCapCAST/#installation) in R). Launch a local instance of this app with:
```
REDCapCAST::shiny_cast()
```
Please mind you, that uploading a new data dictionary can delete data in your database and is non-reversible. Make sure to save a backup beforehand. Also, uploading a data dictionary to a server in production is not possible. This step is only advisable for newly created databases. See the "Disclaimer" above.
## Background
The main structure of variables of a REDCap database is defined by a so-called data dictionary. This is a simple spreadsheet file defining one or more instruments, data classes, branching logic and more. It does not contain any information on randomization, longitudinal data or repeatable instruments. These functions must be set up in the REDCap interface after having defined the data dictionary.
## Motivation
This tool has been created out of frustration with the lack of easy-to-use tools available and with a hope to help colleagues and others to easily create and extend REDCap databases.
## Use and feedback
Please, if you use this tool, don't hesitate to contact me with feedback if something doesn't work as expected. But, please also mind the disclaimer above. Contact information can be found on the [package documentation page](https://agdamsbo.github.io/REDCapCAST/).
## Citing
This app and package can be cited using the following bibtex citation or by referencing the following doi-identifier: [10.5281/zenodo.8013984](https://doi.org/10.5281/zenodo.8013984)
```
@agdamsboREDCapCAST{,
title = {REDCapCAST: REDCap Castellated Data Handling And Metadata Casting},
author = {Andreas Gammelgaard Damsbo and Paul Egeler},
year = {2024},
note = {R package version 24.11.1, https://agdamsbo.github.io/REDCapCAST/},
url = {https://github.com/agdamsbo/REDCapCAST},
doi = {10.5281/zenodo.8013984},
}
```

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -4,11 +4,11 @@
\name{REDCapCAST-package} \name{REDCapCAST-package}
\alias{REDCapCAST} \alias{REDCapCAST}
\alias{REDCapCAST-package} \alias{REDCapCAST-package}
\title{REDCapCAST: REDCap Castellated Data Handling} \title{REDCapCAST: REDCap Castellated Data Handling And Metadata Casting}
\description{ \description{
\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
Originally forked from the R part of 'REDCapRITS' by Paul Egeler. See \url{https://github.com/pegeler/REDCapRITS}. 'REDCap' database casting and handling of castellated data when using repeated instruments and longitudinal projects. Keeps a focused data export approach, by allowing to only export required data from the database. 'REDCap' (Research Electronic Data Capture) is a secure, web-based software platform designed to support data capture for research studies, providing 1) an intuitive interface for validated data capture; 2) audit trails for tracking data manipulation and export procedures; 3) automated export procedures for seamless data downloads to common statistical packages; and 4) procedures for data integration and interoperability with external sources (Harris et al (2009) \doi{10.1016/j.jbi.2008.08.010}; Harris et al (2019) \doi{10.1016/j.jbi.2019.103208}). Originally forked from the R part of 'REDCapRITS' by Paul Egeler. See \url{https://github.com/pegeler/REDCapRITS}. 'REDCap' database casting and handling of castellated data when using repeated instruments and longitudinal projects. Keeps a focused data export approach, by allowing to only export required data from the database. Also for casting new REDCap databases based on datasets from other sources. 'REDCap' (Research Electronic Data Capture) is a secure, web-based software platform designed to support data capture for research studies, providing 1) an intuitive interface for validated data capture; 2) audit trails for tracking data manipulation and export procedures; 3) automated export procedures for seamless data downloads to common statistical packages; and 4) procedures for data integration and interoperability with external sources (Harris et al (2009) \doi{10.1016/j.jbi.2008.08.010}; Harris et al (2019) \doi{10.1016/j.jbi.2019.103208}).
} }
\seealso{ \seealso{
Useful links: Useful links:

View File

@ -1,14 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/shiny_cast.R
\name{server_factory}
\alias{server_factory}
\title{Shiny server factory}
\usage{
server_factory()
}
\value{
shiny server
}
\description{
Shiny server factory
}

View File

@ -4,13 +4,16 @@
\alias{shiny_cast} \alias{shiny_cast}
\title{Launch the included Shiny-app for database casting and upload} \title{Launch the included Shiny-app for database casting and upload}
\usage{ \usage{
shiny_cast() shiny_cast(...)
}
\arguments{
\item{...}{Arguments passed to shiny::runApp()}
} }
\value{ \value{
shiny app shiny app
} }
\description{ \description{
Launch the included Shiny-app for database casting and upload Wraps shiny::runApp()
} }
\examples{ \examples{
# shiny_cast() # shiny_cast()

View File

@ -1,14 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/shiny_cast.R
\name{ui_factory}
\alias{ui_factory}
\title{UI factory for shiny app}
\usage{
ui_factory()
}
\value{
shiny ui
}
\description{
UI factory for shiny app
}

110
renv.lock
View File

@ -21,7 +21,7 @@
}, },
"REDCapR": { "REDCapR": {
"Package": "REDCapR", "Package": "REDCapR",
"Version": "1.1.0", "Version": "1.3.0",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -37,28 +37,28 @@
"tibble", "tibble",
"tidyr" "tidyr"
], ],
"Hash": "e76c401b631961c865b89bb5a4ea3b97" "Hash": "de630e9e6168aae0a178eaa3198dbe54"
}, },
"Rcpp": { "Rcpp": {
"Package": "Rcpp", "Package": "Rcpp",
"Version": "1.0.12", "Version": "1.0.13-1",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"methods", "methods",
"utils" "utils"
], ],
"Hash": "5ea2700d21e038ace58269ecdbeb9ec0" "Hash": "6b868847b365672d6c1677b1608da9ed"
}, },
"askpass": { "askpass": {
"Package": "askpass", "Package": "askpass",
"Version": "1.2.0", "Version": "1.2.1",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"sys" "sys"
], ],
"Hash": "cad6cf7f1d5f6e906700b9d3e718c796" "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a"
}, },
"assertthat": { "assertthat": {
"Package": "assertthat", "Package": "assertthat",
@ -72,13 +72,13 @@
}, },
"backports": { "backports": {
"Package": "backports", "Package": "backports",
"Version": "1.4.1", "Version": "1.5.0",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R" "R"
], ],
"Hash": "c39fbec8a30d23e721980b8afb31984c" "Hash": "e1e1b9d75c37401117b636b7ae50827a"
}, },
"base64enc": { "base64enc": {
"Package": "base64enc", "Package": "base64enc",
@ -92,17 +92,17 @@
}, },
"bit": { "bit": {
"Package": "bit", "Package": "bit",
"Version": "4.0.5", "Version": "4.5.0",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R" "R"
], ],
"Hash": "d242abec29412ce988848d0294b208fd" "Hash": "5dc7b2677d65d0e874fc4aaf0e879987"
}, },
"bit64": { "bit64": {
"Package": "bit64", "Package": "bit64",
"Version": "4.0.5", "Version": "4.5.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -112,11 +112,11 @@
"stats", "stats",
"utils" "utils"
], ],
"Hash": "9fe98599ca456d6552421db0d6772d8f" "Hash": "e84984bf5f12a18628d9a02322128dfd"
}, },
"bslib": { "bslib": {
"Package": "bslib", "Package": "bslib",
"Version": "0.7.0", "Version": "0.8.0",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -134,7 +134,7 @@
"rlang", "rlang",
"sass" "sass"
], ],
"Hash": "8644cc53f43828f19133548195d7e59e" "Hash": "b299c6741ca9746fb227debcb0f9fb6c"
}, },
"cachem": { "cachem": {
"Package": "cachem", "Package": "cachem",
@ -161,7 +161,7 @@
}, },
"checkmate": { "checkmate": {
"Package": "checkmate", "Package": "checkmate",
"Version": "2.3.1", "Version": "2.3.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -169,18 +169,18 @@
"backports", "backports",
"utils" "utils"
], ],
"Hash": "c01cab1cb0f9125211a6fc99d540e315" "Hash": "0e14e01ce07e7c88fd25de6d4260d26b"
}, },
"cli": { "cli": {
"Package": "cli", "Package": "cli",
"Version": "3.6.2", "Version": "3.6.3",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"utils" "utils"
], ],
"Hash": "1216ac65ac55ec0058a6f75d7ca0fd52" "Hash": "b21916dd77a27642b447374a5d30ecf3"
}, },
"clipr": { "clipr": {
"Package": "clipr", "Package": "clipr",
@ -194,10 +194,10 @@
}, },
"commonmark": { "commonmark": {
"Package": "commonmark", "Package": "commonmark",
"Version": "1.9.1", "Version": "1.9.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Hash": "5d8225445acb167abf7797de48b2ee3c" "Hash": "14eb0596f987c71535d07c3aff814742"
}, },
"cpp11": { "cpp11": {
"Package": "cpp11", "Package": "cpp11",
@ -211,7 +211,7 @@
}, },
"crayon": { "crayon": {
"Package": "crayon", "Package": "crayon",
"Version": "1.5.2", "Version": "1.5.3",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -219,28 +219,28 @@
"methods", "methods",
"utils" "utils"
], ],
"Hash": "e8a1e41acf02548751f45c718d55aa6a" "Hash": "859d96e65ef198fd43e82b9628d593ef"
}, },
"curl": { "curl": {
"Package": "curl", "Package": "curl",
"Version": "5.2.1", "Version": "6.0.1",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R" "R"
], ],
"Hash": "411ca2c03b1ce5f548345d2fc2685f7a" "Hash": "e8ba62486230951fcd2b881c5be23f96"
}, },
"digest": { "digest": {
"Package": "digest", "Package": "digest",
"Version": "0.6.35", "Version": "0.6.37",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"utils" "utils"
], ],
"Hash": "698ece7ba5a4fa4559e3d537e7ec3d31" "Hash": "33698c4b3127fc9f506654607fb73676"
}, },
"dplyr": { "dplyr": {
"Package": "dplyr", "Package": "dplyr",
@ -324,14 +324,14 @@
}, },
"fs": { "fs": {
"Package": "fs", "Package": "fs",
"Version": "1.6.4", "Version": "1.6.5",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"methods" "methods"
], ],
"Hash": "15aeb8c27f5ea5161f9f6a641fafd93a" "Hash": "7f48af39fa27711ea5fbd183b399920d"
}, },
"generics": { "generics": {
"Package": "generics", "Package": "generics",
@ -346,14 +346,14 @@
}, },
"glue": { "glue": {
"Package": "glue", "Package": "glue",
"Version": "1.7.0", "Version": "1.8.0",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"methods" "methods"
], ],
"Hash": "e0b3a53876554bd45879e596cdb10a52" "Hash": "5899f1eaa825580172bb56c08266f37c"
}, },
"haven": { "haven": {
"Package": "haven", "Package": "haven",
@ -448,13 +448,13 @@
}, },
"jsonlite": { "jsonlite": {
"Package": "jsonlite", "Package": "jsonlite",
"Version": "1.8.8", "Version": "1.8.9",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"methods" "methods"
], ],
"Hash": "e1b9c55281c5adc4dd113652d9e26768" "Hash": "4e993b65c2c3ffbffce7bb3e2c6f832b"
}, },
"keyring": { "keyring": {
"Package": "keyring", "Package": "keyring",
@ -533,7 +533,7 @@
}, },
"minty": { "minty": {
"Package": "minty", "Package": "minty",
"Version": "0.0.1", "Version": "0.0.4",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -541,21 +541,21 @@
"cpp11", "cpp11",
"tzdb" "tzdb"
], ],
"Hash": "d19909f1b3fac42e7f3ac635321dbb15" "Hash": "ab9d0930bfa21e98aec9d07f0c43cc89"
}, },
"openssl": { "openssl": {
"Package": "openssl", "Package": "openssl",
"Version": "2.2.0", "Version": "2.2.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"askpass" "askpass"
], ],
"Hash": "2bcca3848e4734eb3b16103bc9aa4b8e" "Hash": "d413e0fef796c9401a4419485f709ca1"
}, },
"openxlsx2": { "openxlsx2": {
"Package": "openxlsx2", "Package": "openxlsx2",
"Version": "1.9", "Version": "1.10",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -568,7 +568,7 @@
"utils", "utils",
"zip" "zip"
], ],
"Hash": "f3e00e7d16abb500e63faee67b7dc1a7" "Hash": "ee4b99fc9ca05bbfd29d567785c093d2"
}, },
"pillar": { "pillar": {
"Package": "pillar", "Package": "pillar",
@ -664,12 +664,13 @@
}, },
"readODS": { "readODS": {
"Package": "readODS", "Package": "readODS",
"Version": "2.3.0", "Version": "2.3.1",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"cellranger", "cellranger",
"cpp11",
"minty", "minty",
"stringi", "stringi",
"tibble", "tibble",
@ -677,7 +678,7 @@
"vctrs", "vctrs",
"zip" "zip"
], ],
"Hash": "54bd5930f49d8f914f80eb0eedcd45e2" "Hash": "d81971565325ed8cbe59993ed5c0e611"
}, },
"readr": { "readr": {
"Package": "readr", "Package": "readr",
@ -711,19 +712,24 @@
}, },
"renv": { "renv": {
"Package": "renv", "Package": "renv",
"Version": "1.0.9", "Version": "1.0.11",
"Source": "Repository" "Source": "Repository",
"Repository": "CRAN",
"Requirements": [
"utils"
],
"Hash": "47623f66b4e80b3b0587bc5d7b309888"
}, },
"rlang": { "rlang": {
"Package": "rlang", "Package": "rlang",
"Version": "1.1.3", "Version": "1.1.4",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
"R", "R",
"utils" "utils"
], ],
"Hash": "42548638fae05fd9a9b5f3f437fbbbe2" "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1"
}, },
"sass": { "sass": {
"Package": "sass", "Package": "sass",
@ -774,10 +780,10 @@
}, },
"sodium": { "sodium": {
"Package": "sodium", "Package": "sodium",
"Version": "1.3.1", "Version": "1.3.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Hash": "dd86d6fd2a01d4eb3777dfdee7076d56" "Hash": "869b09ca565ecaa9efc62534ebfa3efd"
}, },
"sourcetools": { "sourcetools": {
"Package": "sourcetools", "Package": "sourcetools",
@ -821,10 +827,10 @@
}, },
"sys": { "sys": {
"Package": "sys", "Package": "sys",
"Version": "3.4.2", "Version": "3.4.3",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Hash": "3a1be13d68d47a8cd0bfd74739ca1555" "Hash": "de342ebfebdbf40477d0758d05426646"
}, },
"tibble": { "tibble": {
"Package": "tibble", "Package": "tibble",
@ -947,7 +953,7 @@
}, },
"withr": { "withr": {
"Package": "withr", "Package": "withr",
"Version": "3.0.0", "Version": "3.0.2",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Requirements": [ "Requirements": [
@ -955,7 +961,7 @@
"grDevices", "grDevices",
"graphics" "graphics"
], ],
"Hash": "d31b6c62c10dcf11ec530ca6b0dd5d35" "Hash": "cc2d62c76458d425210d1eb1478b30b4"
}, },
"xtable": { "xtable": {
"Package": "xtable", "Package": "xtable",
@ -971,10 +977,10 @@
}, },
"yaml": { "yaml": {
"Package": "yaml", "Package": "yaml",
"Version": "2.3.8", "Version": "2.3.10",
"Source": "Repository", "Source": "Repository",
"Repository": "CRAN", "Repository": "CRAN",
"Hash": "29240487a071f535f5e5d5a323b7afbd" "Hash": "51dab85c6c98e50a18d7551e9d49f76c"
}, },
"zip": { "zip": {
"Package": "zip", "Package": "zip",

View File

@ -2,7 +2,7 @@
local({ local({
# the requested version of renv # the requested version of renv
version <- "1.0.9" version <- "1.0.11"
attr(version, "sha") <- NULL attr(version, "sha") <- NULL
# the project directory # the project directory
@ -368,8 +368,7 @@ local({
quiet = TRUE quiet = TRUE
) )
if ("headers" %in% names(formals(utils::download.file))) if ("headers" %in% names(formals(utils::download.file))) {
{
headers <- renv_bootstrap_download_custom_headers(url) headers <- renv_bootstrap_download_custom_headers(url)
if (length(headers) && is.character(headers)) if (length(headers) && is.character(headers))
args$headers <- headers args$headers <- headers
@ -457,9 +456,8 @@ local({
# add custom headers if available -- note that # add custom headers if available -- note that
# utils::available.packages() will pass this to download.file() # utils::available.packages() will pass this to download.file()
if ("headers" %in% names(formals(utils::download.file))) if ("headers" %in% names(formals(utils::download.file))) {
{ headers <- renv_bootstrap_download_custom_headers(repos)
headers <- renv_bootstrap_download_custom_headers(url)
if (length(headers) && is.character(headers)) if (length(headers) && is.character(headers))
args$headers <- headers args$headers <- headers
} }