diff --git a/NAMESPACE b/NAMESPACE index 94ebb948..934dfbae 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,6 +8,7 @@ export(attachment_list) export(audit_get) export(dataset_detail) export(dataset_list) +export(dataset_update) export(drop_null_coords) export(encryption_key_list) export(enexpr) diff --git a/R/dataset_detail.R b/R/dataset_detail.R index ad242cc8..421f64b4 100644 --- a/R/dataset_detail.R +++ b/R/dataset_detail.R @@ -1,8 +1,4 @@ -#' List all datasets of one project. -#' -#' While the API endpoint will return all datasets for one project, -#' \code{\link{dataset_list}} will fail with incorrect or missing -#' authentication. +#' Show dataset details. #' #' A Dataset is a named collection of Entities that have the same properties. #' A Dataset can be linked to Forms as Attachments. This will make it available diff --git a/R/dataset_update.R b/R/dataset_update.R new file mode 100644 index 00000000..87cab7ef --- /dev/null +++ b/R/dataset_update.R @@ -0,0 +1,108 @@ +#' Update dataset details. +#' +#' 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 +#' created from it and if it is false then an Entity is created as soon as the +#' Submission is received by the ODK Central. +#' By default `approvalRequired` is false for the Datasets created after +#' v2023.3. Datasets created prior to that will have approvalRequired set to +#' true. +#' +#' A Dataset is a named collection of Entities that have the same properties. +#' A Dataset can be linked to Forms as Attachments. This will make it available +#' to clients as an automatically-updating CSV. +#' +#' This function is supported from ODK Central v2022.3 and will warn if the +#' given odkc_version is lower. +#' +#' `r lifecycle::badge("maturing")` +#' +#' @template param-pid +#' @param did (chr) The dataset name. +#' @param approval_required (lgl) The value to set approvalRequired to. +#' If TRUE, a submission must be approved before an entity is created, +#' if FALSE, an entity is created as soon as the submission is received by +#' ODK Central. +#' Default: FALSE. +#' @template param-url +#' @template param-auth +#' @template param-retries +#' @template param-odkcv +#' @template param-orders +#' @template param-tz +#' @return A list of lists following the exact format and naming of the API +#' response for `dataset_detail`. +#' Since this nested list is so deeply nested and irregularly shaped +#' it is not trivial to rectangle the result into a tibble. +# nolint start +#' @seealso \url{ https://docs.getodk.org/central-api-dataset-management/#datasets} +# nolint end +#' @family dataset-management +#' @export +#' @examples +#' \dontrun{ +#' # See vignette("setup") for setup and authentication options +#' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...") +#' +#' pid = get_default_pid() +#' +#' ds <- dataset_list(pid = pid) +#' +#' did = ds$name[1] +#' +#' ds1 <- dataset_detail(pid = pid, did = did) +#' ds1$approvalRequired # FALSE +#' +#' ds2 <- dataset_update(pid = pid, did = did, approval_required=TRUE) +#' ds2$approvalRequired # TRUE +#' +#' ds3 <- dataset_update(pid = pid, did = did, approval_required=FALSE) +#' ds3$approvalRequired # FALSE +#' } +dataset_update <- function(pid = get_default_pid(), + did = NULL, + approval_required = FALSE, + url = get_default_url(), + un = get_default_un(), + pw = get_default_pw(), + retries = get_retries(), + odkc_version = get_default_odkc_version(), + orders = c( + "YmdHMS", + "YmdHMSz", + "Ymd HMS", + "Ymd HMSz", + "Ymd", + "ymd" + ), + tz = get_default_tz()) { + yell_if_missing(url, un, pw, pid = pid) + + if (is.null(did)) + ru_msg_abort("dataset_update requires the dataset names as 'did=\"name\"'.") + + if (odkc_version |> semver_lt("2022.3")) { + ru_msg_warn("dataset_update is supported from v2022.3") + } + + ds <- httr::RETRY( + "PATCH", + httr::modify_url(url, + path = glue::glue( + "v1/projects/{pid}/datasets/", + "{URLencode(did, reserved = TRUE)}" + )), + httr::add_headers( + "Accept" = "application/json" + ), + encode = "json", + body = list(approvalRequired = approval_required), + httr::authenticate(un, pw), + times = retries + ) |> + yell_if_error(url, un, pw) |> + httr::content(encoding="utf-8") +} + +# usethis::use_test("dataset_update") # nolint diff --git a/man/dataset_detail.Rd b/man/dataset_detail.Rd index 26c202ad..bc0256fd 100644 --- a/man/dataset_detail.Rd +++ b/man/dataset_detail.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/dataset_detail.R \name{dataset_detail} \alias{dataset_detail} -\title{List all datasets of one project.} +\title{Show dataset details.} \usage{ dataset_detail( pid = get_default_pid(), @@ -80,15 +80,11 @@ response. Since this nested list is so deeply nested and irregularly shaped it is not trivial to rectangle the result into a tibble. } \description{ -While the API endpoint will return all datasets for one project, -\code{\link{dataset_list}} will fail with incorrect or missing -authentication. -} -\details{ A Dataset is a named collection of Entities that have the same properties. A Dataset can be linked to Forms as Attachments. This will make it available to clients as an automatically-updating CSV. - +} +\details{ This function is supported from ODK Central v2022.3 and will warn if the given odkc_version is lower. @@ -112,6 +108,7 @@ ds1$properties |> purrr::list_transpose() |> tibble::as_tibble() \url{ https://docs.getodk.org/central-api-dataset-management/#datasets} Other dataset-management: -\code{\link{dataset_list}()} +\code{\link{dataset_list}()}, +\code{\link{dataset_update}()} } \concept{dataset-management} diff --git a/man/dataset_list.Rd b/man/dataset_list.Rd index b88ad8e0..b093dd5c 100644 --- a/man/dataset_list.Rd +++ b/man/dataset_list.Rd @@ -105,6 +105,7 @@ ds |> knitr::kable() \url{ https://docs.getodk.org/central-api-dataset-management/#datasets} Other dataset-management: -\code{\link{dataset_detail}()} +\code{\link{dataset_detail}()}, +\code{\link{dataset_update}()} } \concept{dataset-management} diff --git a/man/dataset_update.Rd b/man/dataset_update.Rd new file mode 100644 index 00000000..fc69e887 --- /dev/null +++ b/man/dataset_update.Rd @@ -0,0 +1,138 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dataset_update.R +\name{dataset_update} +\alias{dataset_update} +\title{Update dataset details.} +\usage{ +dataset_update( + pid = get_default_pid(), + did = NULL, + approval_required = FALSE, + url = get_default_url(), + un = get_default_un(), + pw = get_default_pw(), + retries = get_retries(), + odkc_version = get_default_odkc_version(), + orders = c("YmdHMS", "YmdHMSz", "Ymd HMS", "Ymd HMSz", "Ymd", "ymd"), + tz = get_default_tz() +) +} +\arguments{ +\item{pid}{The numeric ID of the project, e.g.: 2. + +Default: \code{\link{get_default_pid}}. + +Set default \code{pid} through \code{ru_setup(pid="...")}. + +See \code{vignette("Setup", package = "ruODK")}.} + +\item{did}{(chr) The dataset name.} + +\item{approval_required}{(lgl) The value to set approvalRequired to. +If TRUE, a submission must be approved before an entity is created, +if FALSE, an entity is created as soon as the submission is received by +ODK Central. +Default: FALSE.} + +\item{url}{The ODK Central base URL without trailing slash. + +Default: \code{\link{get_default_url}}. + +Set default \code{url} through \code{ru_setup(url="...")}. + +See \code{vignette("Setup", package = "ruODK")}.} + +\item{un}{The ODK Central username (an email address). +Default: \code{\link{get_default_un}}. +Set default \code{un} through \code{ru_setup(un="...")}. +See \code{vignette("Setup", package = "ruODK")}.} + +\item{pw}{The ODK Central password. +Default: \code{\link{get_default_pw}}. +Set default \code{pw} through \code{ru_setup(pw="...")}. +See \code{vignette("Setup", package = "ruODK")}.} + +\item{retries}{The number of attempts to retrieve a web resource. + +This parameter is given to \code{\link[httr]{RETRY}(times = retries)}. + +Default: 3.} + +\item{odkc_version}{The ODK Central version as a semantic version string +(year.minor.patch), e.g. "2023.5.1". The version is shown on ODK Central's +version page \verb{/version.txt}. Discard the "v". +\code{ruODK} uses this parameter to adjust for breaking changes in ODK Central. + +Default: \code{\link{get_default_odkc_version}} or "2023.5.1" if unset. + +Set default \code{get_default_odkc_version} through +\code{ru_setup(odkc_version="2023.5.1")}. + +See \code{vignette("Setup", package = "ruODK")}.} + +\item{orders}{(vector of character) Orders of datetime elements for +lubridate. + +Default: +\code{c("YmdHMS", "YmdHMSz", "Ymd HMS", "Ymd HMSz", "Ymd", "ymd")}.} + +\item{tz}{A timezone to convert dates and times to. + +Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s +timezone can be set globally or per function.} +} +\value{ +A list of lists following the exact format and naming of the API +response for \code{dataset_detail}. +Since this nested list is so deeply nested and irregularly shaped +it is not trivial to rectangle the result into a tibble. +} +\description{ +You can only update \code{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 +created from it and if it is false then an Entity is created as soon as the +Submission is received by the ODK Central. +By default \code{approvalRequired} is false for the Datasets created after +v2023.3. Datasets created prior to that will have approvalRequired set to +true. +} +\details{ +A Dataset is a named collection of Entities that have the same properties. +A Dataset can be linked to Forms as Attachments. This will make it available +to clients as an automatically-updating CSV. + +This function is supported from ODK Central v2022.3 and will warn if the +given odkc_version is lower. + +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#maturing}{\figure{lifecycle-maturing.svg}{options: alt='[Maturing]'}}}{\strong{[Maturing]}} +} +\examples{ +\dontrun{ +# See vignette("setup") for setup and authentication options +# ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...") + +pid = get_default_pid() + +ds <- dataset_list(pid = pid) + +did = ds$name[1] + +ds1 <- dataset_detail(pid = pid, did = did) +ds1$approvalRequired # FALSE + +ds2 <- dataset_update(pid = pid, did = did, approval_required=TRUE) +ds2$approvalRequired # TRUE + +ds3 <- dataset_update(pid = pid, did = did, approval_required=FALSE) +ds3$approvalRequired # FALSE +} +} +\seealso{ +\url{ https://docs.getodk.org/central-api-dataset-management/#datasets} + +Other dataset-management: +\code{\link{dataset_detail}()}, +\code{\link{dataset_list}()} +} +\concept{dataset-management} diff --git a/tests/testthat/test-dataset_update.R b/tests/testthat/test-dataset_update.R new file mode 100644 index 00000000..345460e2 --- /dev/null +++ b/tests/testthat/test-dataset_update.R @@ -0,0 +1,62 @@ +test_that("dataset_update works", { + + + ds <- dataset_list(pid = get_default_pid(), + url = get_test_url(), + un = get_test_un(), + pw = get_test_pw(), + odkc_version = get_test_odkc_version()) + + ds1 <- dataset_detail(pid = get_default_pid(), + did = ds$name[1], + url = get_test_url(), + un = get_test_un(), + pw = get_test_pw(), + odkc_version = get_test_odkc_version()) + + pid <- get_default_pid() + did <- ds$name[1] + + # Update dataset with opposite approvalRequired + ds2 <- dataset_update(pid = pid, did = did, approval_required=!ds1$approvalRequired) + testthat::expect_false(ds1$approvalRequired == ds2$approvalRequired) + + # Update dataset with opposite approvalRequired again + ds3 <- dataset_update(pid = pid, did = did, approval_required=!ds2$approvalRequired) + testthat::expect_false(ds2$approvalRequired == ds3$approvalRequired) + testthat::expect_true(ds1$approvalRequired == ds3$approvalRequired) +}) + + +test_that("dataset_update warns if odkc_version too low", { + skip_if(Sys.getenv("ODKC_TEST_URL") == "", + message = "Test server not configured" + ) + + ds <- dataset_list(pid = get_default_pid(), + url = get_test_url(), + un = get_test_un(), + pw = get_test_pw(), + odkc_version = "2022.3") + + ds1 <- dataset_update( + pid = get_test_pid(), + did = ds$name[1], + url = get_test_url(), + un = get_test_un(), + pw = get_test_pw(), + odkc_version = "2022.3" + ) + + testthat::expect_warning( + ds1 <- dataset_update( + pid = get_test_pid(), + did = ds$name[1], + url = get_test_url(), + un = get_test_un(), + pw = get_test_pw(), + odkc_version = "1.5.3" + ) + ) + +}) \ No newline at end of file