Skip to content

Commit

Permalink
Add entitylist_download
Browse files Browse the repository at this point in the history
* Downloads entity lists as `entities.csv`
* Does not yet support `$filter` and `ETag`
  • Loading branch information
florianm committed Mar 15, 2024
1 parent dc2c8d8 commit 3dc1ab7
Show file tree
Hide file tree
Showing 10 changed files with 368 additions and 15 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export(enexpr)
export(enquo)
export(ensym)
export(entitylist_detail)
export(entitylist_download)
export(entitylist_list)
export(entitylist_update)
export(expr)
Expand Down
2 changes: 2 additions & 0 deletions R/entitylist_detail.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#' Show Entity List details.
#'
#' `r lifecycle::badge("maturing")`
#'
#' An Entity List is a named collection of Entities that have the same
#' properties.
#' Entity List can be linked to Forms as Attachments.
Expand Down
137 changes: 137 additions & 0 deletions R/entitylist_download.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#' Download an Entity List as CSV.
#'
#' `r lifecycle::badge("maturing")`
#'
#' The downloaded file is named "entities.csv". The download location defaults
#' to the current workdir, but can be modified to a folder name.
#'
#' An Entity List is a named collection of Entities that have the same
#' properties.
#' Entity List can be linked to Forms as Attachments.
#' This will make it available to clients as an automatically-updating CSV.
#'
#' Entity Lists can be used as Attachments in other Forms, but they can also be
#' downloaded directly as a CSV file.
#' The CSV format closely matches the OData Dataset (Entity List) Service
#' format, with columns for system properties such as `__id` (the Entity UUID),
#' `__createdAt`, `__creatorName`, etc., the Entity Label label, and the
#' Dataset (Entity List )/Entity Properties themselves.
#' If any Property for an given Entity is blank (e.g. it was not captured by
#' that Form or was left blank), that field of the CSV is blank.
#'
#' The `$filter` querystring parameter can be used to filter on system-level
#' properties, similar to how filtering in the OData Dataset (Entity List)
#' Service works.
#'
#' This endpoint supports `ETag` header, which can be used to avoid downloading
#' the same content more than once. When an API consumer calls this endpoint,
#' the endpoint returns a value in the `ETag` header.
#' If you pass that value in the `If-None-Match` header of a subsequent request,
#' then if the Entity List has not been changed since the previous request,
#' you will receive 304 Not Modified response; otherwise you'll get the new
#' data.
#'
#' `r lifecycle::badge("maturing")`
#'
#' @template param-pid
#' @template param-did
#' @template param-url
#' @template param-auth
#' @param local_dir The local folder to save the downloaded files to,
#' default: \code{here::here}.
#' @param overwrite Whether to overwrite previously downloaded zip files,
#' default: FALSE
#' @template param-retries
#' @template param-odkcv
#' @template param-orders
#' @template param-tz
#' @template param-verbose
#' @return The path to the downloaded CSV.
# nolint start
#' @seealso \url{ https://docs.getodk.org/central-api-dataset-management/#datasets}
# nolint end
#' @family entity-management
#' @export
#' @examples
#' \dontrun{
#' # See vignette("setup") for setup and authentication options
#' # ruODK::ru_setup(svc = "....svc", un = "[email protected]", pw = "...")
#'
#' ds <- entitylist_list(pid = get_default_pid())
#' ds1 <- entitylist_download(pid = get_default_pid(), did = ds$name[1])
#' }
entitylist_download <- function(pid = get_default_pid(),
did = NULL,
url = get_default_url(),
un = get_default_un(),
pw = get_default_pw(),
local_dir = here::here(),
overwrite = TRUE,
retries = get_retries(),
odkc_version = get_default_odkc_version(),
orders = c(
"YmdHMS",
"YmdHMSz",
"Ymd HMS",
"Ymd HMSz",
"Ymd",
"ymd"
),
tz = get_default_tz(),
verbose = get_ru_verbose()) {
yell_if_missing(url, un, pw, pid = pid)

if (is.null(did)) {
ru_msg_abort(
"entitylist_download requires the Entity List name as 'did=\"name\"'."
)
}

if (odkc_version |> semver_lt("2022.3")) {
ru_msg_warn("entitylist_download is supported from v2022.3")

Check warning on line 91 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L90-L91

Added lines #L90 - L91 were not covered by tests
}

pth <- fs::path(local_dir, "entities.csv")

Check warning on line 94 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L94

Added line #L94 was not covered by tests

if (fs::file_exists(pth)) {
if (overwrite == TRUE) {
"Overwriting previous entity list: \"{pth}\"" %>%
glue::glue() %>%
ru_msg_success(verbose = verbose)

Check warning on line 100 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L96-L100

Added lines #L96 - L100 were not covered by tests
} else {
"Keeping previous entity list: \"{pth}\"" %>%
glue::glue() %>%
ru_msg_success(verbose = verbose)

Check warning on line 104 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L102-L104

Added lines #L102 - L104 were not covered by tests

return(pth)

Check warning on line 106 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L106

Added line #L106 was not covered by tests
}
} else {
"Downloading entity list \"{did}\" to {pth}" %>%
glue::glue() %>%
ru_msg_success(verbose = verbose)

Check warning on line 111 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L109-L111

Added lines #L109 - L111 were not covered by tests
}


httr::RETRY(
"GET",
httr::modify_url(url,
path = glue::glue(
"v1/projects/{pid}/datasets/",
"{URLencode(did, reserved = TRUE)}/entities.csv"

Check warning on line 120 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L115-L120

Added lines #L115 - L120 were not covered by tests
)
),
httr::add_headers(
"Accept" = "text/csv"

Check warning on line 124 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L123-L124

Added lines #L123 - L124 were not covered by tests
),
httr::authenticate(un, pw),
httr::write_disk(pth, overwrite = overwrite),
times = retries

Check warning on line 128 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L126-L128

Added lines #L126 - L128 were not covered by tests
) |>
yell_if_error(url, un, pw) |>
httr::content(encoding = "utf-8")

Check warning on line 131 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L130-L131

Added lines #L130 - L131 were not covered by tests

pth

Check warning on line 133 in R/entitylist_download.R

View check run for this annotation

Codecov / codecov/patch

R/entitylist_download.R#L133

Added line #L133 was not covered by tests
}


# usethis::use_test("entitylist_download") # nolint
2 changes: 2 additions & 0 deletions R/entitylist_list.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#' List all Entity Lists of one Project.
#'
#' `r lifecycle::badge("maturing")`
#'
#' While the API endpoint will return all Entity Lists for one Project,
#' \code{\link{entitylist_list}} will fail with incorrect or missing
#' authentication.
Expand Down
2 changes: 2 additions & 0 deletions R/entitylist_update.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#' Update Entity List details.
#'
#' `r lifecycle::badge("maturing")`
#'
#' You can only update `approvalRequired` using this endpoint.
#' The approvalRequired flag controls the Entity creation flow;
#' if it is true then the Submission must be approved before an Entity can be
Expand Down
19 changes: 14 additions & 5 deletions man/entitylist_detail.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 145 additions & 0 deletions man/entitylist_download.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions man/entitylist_list.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3dc1ab7

Please sign in to comment.