├── .github
├── .gitignore
├── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
└── workflows
│ └── R-CMD-check.yaml
├── inst
├── binder
│ ├── .gitignore
│ ├── apt.txt
│ └── install.R
├── joss
│ ├── .gitignore
│ └── paper.bib
├── extdoc
│ └── ruODK.pdf
├── extdata
│ ├── I8n_no_lang.xls
│ ├── I8n_label_lang.xls
│ ├── I8n_label_choices.xls
│ ├── I8n_lang_choicefilter.xlsx
│ └── I8n_no_lang_choicefilter.xlsx
├── rmarkdown
│ └── templates
│ │ └── odata
│ │ └── template.yaml
├── CITATION
└── schemaorg.json
├── tests
├── testthat
│ ├── .gitignore
│ ├── test-submission_get_audit.R
│ ├── test-utils-lifecycle.R
│ ├── test-prepend_uuid.R
│ ├── test-strip_uuid.R
│ ├── test-odata_metadata_get.R
│ ├── test-odata_service_get.R
│ ├── test-ru_msg.R
│ ├── test-encryption_key_list.R
│ ├── test-project_create.R
│ ├── test-handle_ru_datetimes.R
│ ├── test-form_detail.R
│ ├── test-attachment_list.R
│ ├── test-submission_detail.R
│ ├── test-entity_list.R
│ ├── test-form_xml.R
│ ├── test-audit_get.R
│ ├── test-entitylist_list.R
│ ├── test-form_list.R
│ ├── test-odata_submission_parse.R
│ ├── test-entitylist_update.R
│ ├── test-attachment_link.R
│ ├── test-handle_ru_attachments.R
│ ├── test-submission_list.R
│ ├── test-entitylist_detail.R
│ ├── test-drop_null_coords.R
│ ├── test-form_schema_parse.R
│ ├── test-user_list.R
│ └── test-entity_detail.R
└── testthat.R
├── .gitattributes
├── data
├── fs_v7.rda
├── fq_data.rda
├── fq_meta.rda
├── fq_raw.rda
├── fq_svc.rda
├── geo_fs.rda
├── geo_gj.rda
├── geo_wkt.rda
├── fs_v7_raw.rda
├── geo_gj88.rda
├── geo_gj_raw.rda
├── geo_wkt88.rda
├── fq_data_taxa.rda
├── fq_form_list.rda
├── fq_form_xml.rda
├── fq_raw_taxa.rda
├── fq_zip_data.rda
├── fq_zip_taxa.rda
├── geo_wkt_raw.rda
├── fq_attachments.rda
├── fq_data_strata.rda
├── fq_form_detail.rda
├── fq_form_schema.rda
├── fq_project_list.rda
├── fq_raw_strata.rda
├── fq_submissions.rda
├── fq_zip_strata.rda
├── fq_project_detail.rda
└── fq_submission_list.rda
├── man
├── figures
│ ├── bcs.png
│ ├── logo.jpg
│ ├── dbca_bcs.png
│ ├── ruODK2.png
│ ├── lifecycle-defunct.svg
│ ├── lifecycle-retired.svg
│ ├── lifecycle-archived.svg
│ ├── lifecycle-maturing.svg
│ ├── lifecycle-questioning.svg
│ ├── lifecycle-soft-deprecated.svg
│ ├── lifecycle-deprecated.svg
│ ├── lifecycle-superseded.svg
│ ├── lifecycle-experimental.svg
│ └── lifecycle-stable.svg
├── pipe.Rd
├── lifecycle_shim.Rd
├── listcol_names.Rd
├── ru_msg_abort.Rd
├── ru_msg_info.Rd
├── ru_msg_noop.Rd
├── ru_msg_success.Rd
├── ru_msg_warn.Rd
├── odata_svc_parse.Rd
├── yell_if_error.Rd
├── semver_lt.Rd
├── semver_gt.Rd
├── fq_form_list.Rd
├── ruODK-package.Rd
├── fq_project_list.Rd
├── fs_v7_raw.Rd
├── fs_v7.Rd
├── tidyeval.Rd
├── fq_form_xml.Rd
├── fq_form_detail.Rd
├── fq_project_detail.Rd
├── fq_submission_list.Rd
├── fq_attachments.Rd
├── fq_zip_data.Rd
├── fq_zip_taxa.Rd
├── fq_zip_strata.Rd
├── geo_gj_raw.Rd
├── geo_wkt_raw.Rd
├── geo_fs.Rd
├── fq_submissions.Rd
├── geo_wkt.Rd
├── geo_gj.Rd
├── prepend_uuid.Rd
├── strip_uuid.Rd
├── fq_meta.Rd
├── fq_svc.Rd
├── predict_ruodk_name.Rd
├── geo_wkt88.Rd
├── geo_gj88.Rd
├── project_create.Rd
├── fq_raw_strata.Rd
├── parse_odkc_version.Rd
├── fq_form_schema.Rd
├── fq_raw.Rd
├── yell_if_missing.Rd
├── fq_raw_taxa.Rd
├── fq_data_strata.Rd
├── fq_data.Rd
├── isodt_to_local.Rd
├── odata_service_get.Rd
├── fq_data_taxa.Rd
└── odata_metadata_get.Rd
├── .Rinstignore
├── vignettes
├── media
│ ├── 1701678074209.jpg
│ ├── 1701678107041.jpg
│ ├── 1701678512568.jpg
│ ├── 1701678535420.jpg
│ └── 1701678592627.jpg
└── .gitignore
├── man-roxygen
├── param-iid.R
├── param-wkt.R
├── tpl-auth-missing.R
├── tpl-rusetup.R
├── tpl-names-cleaned-top-level.R
├── tpl-compat-2022-3.R
├── param-did.R
├── param-eid.R
├── param-retries.R
├── param-orders.R
├── param-tz.R
├── param-verbose.R
├── param-pp.R
├── tpl-def-entitylist.R
├── param-pid.R
├── param-url.R
├── param-fid.R
├── tpl-entitylist-dataset.R
├── param-fs.R
├── tpl-structure-nested.R
├── param-auth.R
└── param-odkcv.R
├── .gitignore
├── .lintr
├── data-raw
├── record_asciicast.R
├── make_logo.R
└── make_asciicast.R
├── R
├── utils-pipe.R
├── utils-lifecycle.R
├── ruODK-package.R
├── utils-tidy-eval.R
├── isodt_to_local.R
├── odata_metadata_get.R
├── odata_service_get.R
├── form_xml.R
├── project_create.R
├── handle_ru_datetimes.R
├── drop_null_coords.R
├── entitylist_list.R
├── project_detail.R
├── project_list.R
├── attachment_link.R
├── handle_ru_geopoints.R
└── submission_detail.R
├── codecov.yml
├── ruODK.Rproj
├── .Rbuildignore
├── .devcontainer
├── Dockerfile
└── devcontainer.json
├── Dockerfile
├── appveyor.yml
├── CODE_OF_CONDUCT.md
├── cran-comments.md
└── .pre-commit-config.yaml
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/inst/binder/.gitignore:
--------------------------------------------------------------------------------
1 | README.html
2 |
--------------------------------------------------------------------------------
/inst/joss/.gitignore:
--------------------------------------------------------------------------------
1 | paper.html
2 | paper.pdf
3 |
--------------------------------------------------------------------------------
/tests/testthat/.gitignore:
--------------------------------------------------------------------------------
1 | media
2 | _snaps
3 | R
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | tests/fixtures/**/* -diff
3 |
--------------------------------------------------------------------------------
/data/fs_v7.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fs_v7.rda
--------------------------------------------------------------------------------
/data/fq_data.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_data.rda
--------------------------------------------------------------------------------
/data/fq_meta.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_meta.rda
--------------------------------------------------------------------------------
/data/fq_raw.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_raw.rda
--------------------------------------------------------------------------------
/data/fq_svc.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_svc.rda
--------------------------------------------------------------------------------
/data/geo_fs.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_fs.rda
--------------------------------------------------------------------------------
/data/geo_gj.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_gj.rda
--------------------------------------------------------------------------------
/data/geo_wkt.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_wkt.rda
--------------------------------------------------------------------------------
/data/fs_v7_raw.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fs_v7_raw.rda
--------------------------------------------------------------------------------
/data/geo_gj88.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_gj88.rda
--------------------------------------------------------------------------------
/data/geo_gj_raw.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_gj_raw.rda
--------------------------------------------------------------------------------
/data/geo_wkt88.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_wkt88.rda
--------------------------------------------------------------------------------
/man/figures/bcs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/man/figures/bcs.png
--------------------------------------------------------------------------------
/.Rinstignore:
--------------------------------------------------------------------------------
1 | tests/files/.*[.]csv$
2 | tests/files/.*[.]zip$
3 | tests/files/.*[.]jpg$
4 |
--------------------------------------------------------------------------------
/data/fq_data_taxa.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_data_taxa.rda
--------------------------------------------------------------------------------
/data/fq_form_list.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_form_list.rda
--------------------------------------------------------------------------------
/data/fq_form_xml.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_form_xml.rda
--------------------------------------------------------------------------------
/data/fq_raw_taxa.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_raw_taxa.rda
--------------------------------------------------------------------------------
/data/fq_zip_data.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_zip_data.rda
--------------------------------------------------------------------------------
/data/fq_zip_taxa.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_zip_taxa.rda
--------------------------------------------------------------------------------
/data/geo_wkt_raw.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/geo_wkt_raw.rda
--------------------------------------------------------------------------------
/inst/extdoc/ruODK.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdoc/ruODK.pdf
--------------------------------------------------------------------------------
/man/figures/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/man/figures/logo.jpg
--------------------------------------------------------------------------------
/data/fq_attachments.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_attachments.rda
--------------------------------------------------------------------------------
/data/fq_data_strata.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_data_strata.rda
--------------------------------------------------------------------------------
/data/fq_form_detail.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_form_detail.rda
--------------------------------------------------------------------------------
/data/fq_form_schema.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_form_schema.rda
--------------------------------------------------------------------------------
/data/fq_project_list.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_project_list.rda
--------------------------------------------------------------------------------
/data/fq_raw_strata.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_raw_strata.rda
--------------------------------------------------------------------------------
/data/fq_submissions.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_submissions.rda
--------------------------------------------------------------------------------
/data/fq_zip_strata.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_zip_strata.rda
--------------------------------------------------------------------------------
/man/figures/dbca_bcs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/man/figures/dbca_bcs.png
--------------------------------------------------------------------------------
/man/figures/ruODK2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/man/figures/ruODK2.png
--------------------------------------------------------------------------------
/data/fq_project_detail.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_project_detail.rda
--------------------------------------------------------------------------------
/data/fq_submission_list.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/data/fq_submission_list.rda
--------------------------------------------------------------------------------
/inst/extdata/I8n_no_lang.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdata/I8n_no_lang.xls
--------------------------------------------------------------------------------
/inst/extdata/I8n_label_lang.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdata/I8n_label_lang.xls
--------------------------------------------------------------------------------
/inst/extdata/I8n_label_choices.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdata/I8n_label_choices.xls
--------------------------------------------------------------------------------
/vignettes/media/1701678074209.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/vignettes/media/1701678074209.jpg
--------------------------------------------------------------------------------
/vignettes/media/1701678107041.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/vignettes/media/1701678107041.jpg
--------------------------------------------------------------------------------
/vignettes/media/1701678512568.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/vignettes/media/1701678512568.jpg
--------------------------------------------------------------------------------
/vignettes/media/1701678535420.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/vignettes/media/1701678535420.jpg
--------------------------------------------------------------------------------
/vignettes/media/1701678592627.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/vignettes/media/1701678592627.jpg
--------------------------------------------------------------------------------
/man-roxygen/param-iid.R:
--------------------------------------------------------------------------------
1 | #' @param iid The `instance_id`, a UUID, as returned by
2 | #' \code{\link{submission_list}}.
3 |
--------------------------------------------------------------------------------
/inst/extdata/I8n_lang_choicefilter.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdata/I8n_lang_choicefilter.xlsx
--------------------------------------------------------------------------------
/tests/testthat/test-submission_get_audit.R:
--------------------------------------------------------------------------------
1 | test_that("submission_get_audit works", {
2 | expect_equal(2 * 2, 4)
3 | })
4 |
--------------------------------------------------------------------------------
/man-roxygen/param-wkt.R:
--------------------------------------------------------------------------------
1 | #' @param wkt Whether geofields are GeoJSON (if FALSE) or WKT
2 | #' strings (if TRUE), default: FALSE.
3 |
--------------------------------------------------------------------------------
/inst/extdata/I8n_no_lang_choicefilter.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ropensci/ruODK/HEAD/inst/extdata/I8n_no_lang_choicefilter.xlsx
--------------------------------------------------------------------------------
/man-roxygen/tpl-auth-missing.R:
--------------------------------------------------------------------------------
1 | #' ## Authentication
2 | #' This function will fail with incorrect or missing authentication.
3 | #'
4 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-rusetup.R:
--------------------------------------------------------------------------------
1 | #' # See vignette("setup") for setup and authentication options
2 | #' # ruODK::ru_setup(svc = "... .svc", un = "...", pw = "...")
3 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-names-cleaned-top-level.R:
--------------------------------------------------------------------------------
1 | #' ## Names
2 | #' Names are cleaned at the top level only. List columns contain original
3 | #' `camelCase` names.
4 | #'
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 | inst/doc/*
6 | *.RData
7 | manual.tex
8 | manual-concordance.tex
9 | docs/
10 | inst/doc
11 |
--------------------------------------------------------------------------------
/inst/rmarkdown/templates/odata/template.yaml:
--------------------------------------------------------------------------------
1 | name: ODK Central via OData
2 | description: >
3 | Access data captured with OpenDataKit through the ODK Central OData API
4 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-compat-2022-3.R:
--------------------------------------------------------------------------------
1 | #' ## Compatibility
2 | #' This function is supported from ODK Central v2022.3 and will warn if the
3 | #' given `odkc_version` is lower.
4 | #'
5 |
--------------------------------------------------------------------------------
/man-roxygen/param-did.R:
--------------------------------------------------------------------------------
1 | #' @param did (chr) The name of the Entity List, internally called Dataset.
2 | #' The function will error if this parameter is not given.
3 | #' Default: "".
4 |
--------------------------------------------------------------------------------
/tests/testthat/test-utils-lifecycle.R:
--------------------------------------------------------------------------------
1 | test_that("lifecycle_shim does nothing as expected", {
2 | testthat::capture_warning(ruODK:::lifecycle_shim())
3 | testthat::expect_true(TRUE)
4 | })
5 |
--------------------------------------------------------------------------------
/.lintr:
--------------------------------------------------------------------------------
1 | linters: linters_with_defaults(
2 | line_length_linter(120),
3 | object_name_linter = NULL,
4 | line_length_linter = NULL,
5 | commented_code_linter = NULL
6 | )
7 | exclusions: list()
8 |
--------------------------------------------------------------------------------
/man-roxygen/param-eid.R:
--------------------------------------------------------------------------------
1 | #' @param eid (chr) The UUID of an Entity, which can be retrieved by
2 | #' `entity_list()`.
3 | #' The function will error if this parameter is not given.
4 | #' Default: "".
5 |
--------------------------------------------------------------------------------
/man-roxygen/param-retries.R:
--------------------------------------------------------------------------------
1 | #' @param retries The number of attempts to retrieve a web resource.
2 | #'
3 | #' This parameter is given to \code{\link[httr]{RETRY}(times = retries)}.
4 | #'
5 | #' Default: 3.
6 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(ruODK)
3 |
4 | if (Sys.getenv("ODKC_TEST_URL") == "") {
5 | ru_msg_info("Test server not configured, skipping tests.")
6 | } else {
7 | test_check("ruODK")
8 | }
9 |
--------------------------------------------------------------------------------
/man-roxygen/param-orders.R:
--------------------------------------------------------------------------------
1 | #' @param orders (vector of character) Orders of datetime elements for
2 | #' lubridate.
3 | #'
4 | #' Default:
5 | #' \code{c("YmdHMS", "YmdHMSz", "Ymd HMS", "Ymd HMSz", "Ymd", "ymd")}.
6 |
--------------------------------------------------------------------------------
/man-roxygen/param-tz.R:
--------------------------------------------------------------------------------
1 | #' @param tz A timezone to convert dates and times to.
2 | #'
3 | #' Read `vignette("setup", package = "ruODK")` to learn how `ruODK`'s
4 | #' timezone can be set globally or per function.
5 |
--------------------------------------------------------------------------------
/man-roxygen/param-verbose.R:
--------------------------------------------------------------------------------
1 | #' @param verbose Whether to display debug messages or not.
2 | #'
3 | #' Read `vignette("setup", package = "ruODK")` to learn how `ruODK`'s
4 | #' verbosity can be set globally or per function.
5 |
--------------------------------------------------------------------------------
/man-roxygen/param-pp.R:
--------------------------------------------------------------------------------
1 | #' @param pp The passphrase for an encrypted form.
2 | #'
3 | #' Default: NULL.
4 | #'
5 | #' Passphrases can be stored e.g. as environment variables.
6 | #'
7 | #' See \code{vignette("Setup", package = "ruODK")}.
8 |
--------------------------------------------------------------------------------
/data-raw/record_asciicast.R:
--------------------------------------------------------------------------------
1 | cast <- asciicast::record(here::here("data-raw/make_asciicast.R"))
2 | asciicast::write_json(cast, here::here("data-raw/odata.json"))
3 | asciicast::write_svg(cast, here::here("man", "figures", "odata.svg"))
4 | asciicast::play(cast)
5 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-def-entitylist.R:
--------------------------------------------------------------------------------
1 | #' An Entity List is a named collection of Entities that have the same properties.
2 | #' An Entity List can be linked to Forms as Attachments.
3 | #' This will make it available to clients as an automatically-updating CSV.
4 | #'
5 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | manual.log
3 | manual-concordance.tex
4 | manual.synctex.gz
5 | manual.tex
6 | *.R
7 | manual.Rnw
8 | comparison_files
9 | *.aux
10 | *.pdf
11 | odata-api_files
12 | restful-api_files
13 | setup_files
14 | spatial_files
15 |
--------------------------------------------------------------------------------
/R/utils-pipe.R:
--------------------------------------------------------------------------------
1 | #' Pipe operator
2 | #'
3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details.
4 | #'
5 | #' @name %>%
6 | #' @rdname pipe
7 | #' @keywords internal
8 | #' @export
9 | #' @importFrom magrittr %>%
10 | #' @usage lhs \%>\% rhs
11 | NULL
12 |
--------------------------------------------------------------------------------
/man-roxygen/param-pid.R:
--------------------------------------------------------------------------------
1 | #' @param pid The numeric ID of the project, e.g.: 2.
2 | #'
3 | #' Default: \code{\link{get_default_pid}}.
4 | #'
5 | #' Set default \code{pid} through \code{ru_setup(pid="...")}.
6 | #'
7 | #' See \code{vignette("Setup", package = "ruODK")}.
8 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: ruODK is missing something
4 | title: ''
5 | labels: feature
6 | assignees: florianm
7 |
8 | ---
9 |
10 | ## Feature
11 |
12 |
--------------------------------------------------------------------------------
/man-roxygen/param-url.R:
--------------------------------------------------------------------------------
1 | #' @param url The ODK Central base URL without trailing slash.
2 | #'
3 | #' Default: \code{\link{get_default_url}}.
4 | #'
5 | #' Set default \code{url} through \code{ru_setup(url="...")}.
6 | #'
7 | #' See \code{vignette("Setup", package = "ruODK")}.
8 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: false
2 |
3 | coverage:
4 | status:
5 | project:
6 | default:
7 | target: auto
8 | threshold: 1%
9 | patch:
10 | default:
11 | target: auto
12 | threshold: 1%
13 | ignore:
14 | - "R/utils-lifecycle.R"
15 |
--------------------------------------------------------------------------------
/man-roxygen/param-fid.R:
--------------------------------------------------------------------------------
1 | #' @param fid The alphanumeric form ID, e.g. "build_Spotlighting-0-8_1559885147".
2 | #'
3 | #' Default: \code{\link{get_default_fid}}.
4 | #'
5 | #' Set default \code{fid} through \code{ru_setup(fid="...")}.
6 | #'
7 | #' See \code{vignette("Setup", package = "ruODK")}.
8 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-entitylist-dataset.R:
--------------------------------------------------------------------------------
1 | #' ## Entity Lists are Datasets
2 | #' ODK Central calls Entity Lists internally Datasets. `ruODK` chooses the term
3 | #' Entity Lists as it is used in the ODK Central user interface and conveys
4 | #' its relation to Entities better than the term Dataset.
5 | #'
6 |
--------------------------------------------------------------------------------
/man/pipe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils-pipe.R
3 | \name{\%>\%}
4 | \alias{\%>\%}
5 | \title{Pipe operator}
6 | \usage{
7 | lhs \%>\% rhs
8 | }
9 | \description{
10 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details.
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/man-roxygen/param-fs.R:
--------------------------------------------------------------------------------
1 | #' @param form_schema An optional form_schema,
2 | #' like the output of \code{\link{form_schema}}. If a form schema is supplied,
3 | #' location fields will not be unnested. While WKT location fields contain
4 | #' plain text and will never be unnested, GeoJSON location fields would cause
5 | #' errors during unnesting.
6 |
--------------------------------------------------------------------------------
/R/utils-lifecycle.R:
--------------------------------------------------------------------------------
1 | #' Shim to allow Import of lifecycle, required for building docs.
2 | #'
3 | #' HT Jim Hester, Lionel Henry, Jenny Bryan for advice
4 | #' @importFrom lifecycle deprecate_soft
5 | #' @keywords internal
6 | lifecycle_shim <- function() {
7 | lifecycle::deprecate_soft(when = "1.0", what = "lifecycle_shim()")
8 | }
9 |
10 | # usethis::use_test("utils-lifecycle") # nolint
11 |
--------------------------------------------------------------------------------
/man/lifecycle_shim.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils-lifecycle.R
3 | \name{lifecycle_shim}
4 | \alias{lifecycle_shim}
5 | \title{Shim to allow Import of lifecycle, required for building docs.}
6 | \usage{
7 | lifecycle_shim()
8 | }
9 | \description{
10 | HT Jim Hester, Lionel Henry, Jenny Bryan for advice
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/inst/binder/apt.txt:
--------------------------------------------------------------------------------
1 | libxml2-dev
2 | libjq-dev
3 | libudunits2-dev
4 | libgdal-dev
5 | libgeos-dev
6 | libproj-dev
7 | libicu-dev
8 | libv8-dev
9 | libjq-dev
10 | libprotobuf-dev
11 | protobuf-compiler
12 | libgit2-dev
13 | rsync
14 | mdbtools
15 | cargo
16 | libavfilter-dev
17 | libfontconfig1-dev
18 | libopenblas-dev
19 | libct4
20 | libsybdb5
21 | freetds-bin
22 | freetds-common
23 | freetds-dev
24 | libsybdb5
25 | tdsodbc
26 | unixodbc
27 |
--------------------------------------------------------------------------------
/tests/testthat/test-prepend_uuid.R:
--------------------------------------------------------------------------------
1 | test_that("prepend_uuid works", {
2 | stuff <- "sdfsdf"
3 | uuid_stuff <- glue::glue("uuid:{stuff}") %>% as.character(.)
4 | expect_equal(uuid_stuff, prepend_uuid(stuff))
5 | })
6 |
7 |
8 | test_that("prepend_uuid undoes strip_uuid", {
9 | stuff <- "sdfsdf"
10 | uuid_stuff <- prepend_uuid(stuff)
11 | uuid_stuff_stripped <- strip_uuid(uuid_stuff)
12 | expect_equal(stuff, uuid_stuff_stripped)
13 | })
14 |
--------------------------------------------------------------------------------
/man-roxygen/tpl-structure-nested.R:
--------------------------------------------------------------------------------
1 | #' ## Structure
2 | #' The response from ODK Central from this endpoint is irregular and dynamic.
3 | #' Depending on the life history of records in ODK Central, some parts may be
4 | #' populated with deeply nested structures, empty, or missing.
5 | #' `ruODK` preserves the original structure as not to introduce additional
6 | #' complexity. If a use case exists to decompose the original structure further
7 | #' please create a GitHub issue.
8 | #'
9 |
--------------------------------------------------------------------------------
/tests/testthat/test-strip_uuid.R:
--------------------------------------------------------------------------------
1 | test_that("strip_uuid works", {
2 | expect_equal(
3 | "c0f9ce58-4388-4e7b-98d7-feac459d2e12",
4 | strip_uuid("uuid:c0f9ce58-4388-4e7b-98d7-feac459d2e12")
5 | )
6 | })
7 |
8 | test_that("strip_uuid does its job even with weird clients", {
9 | expect_equal(
10 | "4e7b-98d7-feac459d2e12",
11 | strip_uuid("uuid:uuid:uuid:4e7b-uuid:98d7-feac459d2e12uuid:uuid:")
12 | )
13 | })
14 |
15 | # usethis::use_r("attachment_get") # nolint
16 |
--------------------------------------------------------------------------------
/ruODK.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: No
4 | SaveWorkspace: No
5 | AlwaysSaveHistory: No
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | StripTrailingWhitespace: Yes
16 |
17 | BuildType: Package
18 | PackageUseDevtools: Yes
19 | PackageInstallArgs: --no-multiarch --with-keep.source
20 | PackageCheckArgs: --as-cran
21 | PackageRoxygenize: rd,collate,namespace,vignette
22 |
--------------------------------------------------------------------------------
/man-roxygen/param-auth.R:
--------------------------------------------------------------------------------
1 | #' @param un The ODK Central username (an email address).
2 | #' Default: \code{\link{get_default_un}}.
3 | #' Set default \code{un} through \code{ru_setup(un="...")}.
4 | #' See \code{vignette("Setup", package = "ruODK")}.
5 | #' @param pw The ODK Central password.
6 | #' Default: \code{\link{get_default_pw}}.
7 | #' Set default \code{pw} through \code{ru_setup(pw="...")}.
8 | #' See \code{vignette("Setup", package = "ruODK")}.
9 |
--------------------------------------------------------------------------------
/tests/testthat/test-odata_metadata_get.R:
--------------------------------------------------------------------------------
1 | context("test-odata_metadata_get.R")
2 |
3 | test_that("odata_metadata_get works", {
4 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
5 | message = "Test server not configured"
6 | )
7 |
8 | md <- odata_metadata_get(
9 | get_test_pid(),
10 | get_test_fid(),
11 | url = get_test_url(),
12 | un = get_test_un(),
13 | pw = get_test_pw()
14 | )
15 | testthat::expect_equal(class(md), "list")
16 | })
17 |
18 | # usethis::use_r("odata_metadata_get") # nolint
19 |
--------------------------------------------------------------------------------
/inst/CITATION:
--------------------------------------------------------------------------------
1 | citHeader("To cite ruODK in publications use (with the correct version number:")
2 |
3 | bibentry(
4 | bibtype = "Misc",
5 | title = "ruODK: Client for the ODK Central API",
6 | author = "Florian W. Mayer",
7 | note = "R package version X.X.X",
8 | year = 2020,
9 | url = "https://github.com/ropensci/ruODK",
10 | textVersion = paste(
11 | "Mayer, Florian Wendelin. (2020, Nov 19). ",
12 | "ruODK: An R Client for the ODK Central API (Version X.X.X). ",
13 | "Zenodo. https://doi.org/10.5281/zenodo.5559164"
14 | )
15 | )
16 |
--------------------------------------------------------------------------------
/man-roxygen/param-odkcv.R:
--------------------------------------------------------------------------------
1 | #' @param odkc_version The ODK Central version as a semantic version string
2 | #' (year.minor.patch), e.g. "2023.5.1". The version is shown on ODK Central's
3 | #' version page `/version.txt`. Discard the "v".
4 | #' `ruODK` uses this parameter to adjust for breaking changes in ODK Central.
5 | #'
6 | #' Default: \code{\link{get_default_odkc_version}} or "2023.5.1" if unset.
7 | #'
8 | #' Set default \code{get_default_odkc_version} through
9 | #' \code{ru_setup(odkc_version="2023.5.1")}.
10 | #'
11 | #' See \code{vignette("Setup", package = "ruODK")}.
12 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | ^LICENSE\.md$
4 | ^README\.Rmd$
5 | ^docs$
6 | ^CODE_OF_CONDUCT\.md$
7 | ^data-raw$
8 | ^\.travis\.yml$
9 | ^codecov\.yml$
10 | ^\_pkgdown\.yml$
11 | ^CONTRIBUTING\.md$
12 | ^ISSUE_TEMPLATE\.md$
13 | ^SUPPORT\.md$
14 | ^man-roxygen$
15 | ^appveyor\.yml$
16 | codemeta.json
17 | ^inst/joss/paper\.html$
18 | ^inst/joss/paper\.pdf$
19 | ^install\.R$
20 | ^cran-comments\.md$
21 | ^\.ccache$
22 | ^clang-.*
23 | ^gfortran.*
24 | ^tic\.R$
25 | ^Dockerfile$
26 | ^codemeta\.json$
27 | ^\.devcontainer
28 | ^\.github
29 | ^\.vscode
30 | ^.lintr
31 | ^\.pre-commit-config\.yaml$
32 |
--------------------------------------------------------------------------------
/man/listcol_names.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/odata_submission_rectangle.R
3 | \name{listcol_names}
4 | \alias{listcol_names}
5 | \title{A functional to extract names of list columns from a tibble.}
6 | \usage{
7 | listcol_names(tbl)
8 | }
9 | \arguments{
10 | \item{tbl}{A tibble, possibly with list columns}
11 | }
12 | \value{
13 | A vector of list column names
14 | }
15 | \description{
16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/tests/testthat/test-odata_service_get.R:
--------------------------------------------------------------------------------
1 | context("test-odata_service_get.R")
2 |
3 | test_that("odata_service_get works", {
4 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
5 | message = "Test server not configured"
6 | )
7 |
8 | svc <- odata_service_get(
9 | get_test_pid(),
10 | get_test_fid(),
11 | url = get_test_url(),
12 | un = get_test_un(),
13 | pw = get_test_pw()
14 | )
15 |
16 | testthat::expect_equal(class(svc), c("tbl_df", "tbl", "data.frame"))
17 | cn <- c("name", "kind", "url")
18 | testthat::expect_equal(names(svc), cn)
19 | })
20 |
21 | # usethis::use_r("odata_service_get") # nolint
22 |
--------------------------------------------------------------------------------
/tests/testthat/test-ru_msg.R:
--------------------------------------------------------------------------------
1 | test_that("ru_msg_* output silent if not verbose", {
2 | # Messages can be hidden
3 | expect_message(ru_msg_success("Test", verbose = TRUE), "Test")
4 | expect_silent(ru_msg_success("Test", verbose = FALSE))
5 | expect_message(ru_msg_noop("Test", verbose = TRUE), "Test")
6 | expect_silent(ru_msg_noop("Test", verbose = FALSE))
7 | expect_message(ru_msg_info("Test", verbose = TRUE), "Test")
8 | expect_silent(ru_msg_info("Test", verbose = FALSE))
9 |
10 | # Warnings can be hidden
11 | expect_warning(ru_msg_warn("Test", verbose = TRUE), "Test")
12 | expect_silent(ru_msg_warn("Test", verbose = FALSE))
13 |
14 | # Errors can't be hidden
15 | expect_error(ru_msg_abort("Test"))
16 | })
17 |
--------------------------------------------------------------------------------
/R/ruODK-package.R:
--------------------------------------------------------------------------------
1 | #' @description \code{\link{ruODK}} is an R Client for the ODK Central API.
2 | #'
3 | #' Please see the `ruODK` website for full documentation:
4 | #'
5 | #'
6 | #' `ruODK` is "pipe-friendly" and re-exports `\%>\%` and `\%||\%`, but does not
7 | #' require their use.
8 | #'
9 | #' @keywords internal
10 | "_PACKAGE"
11 |
12 | utils::globalVariables(c(
13 | ".",
14 | "archived",
15 | "children",
16 | "id",
17 | "name",
18 | "path",
19 | "type",
20 | "variable",
21 | "xx",
22 | "xml_form_id"
23 | ))
24 |
25 | ## usethis namespace: start
26 | #' @import rlang
27 | #' @importFrom glue glue
28 | #' @importFrom lifecycle deprecated
29 | ## usethis namespace: end
30 | NULL
31 |
--------------------------------------------------------------------------------
/R/utils-tidy-eval.R:
--------------------------------------------------------------------------------
1 | #' Tidy eval helpers
2 | #'
3 | #' These functions provide tidy eval-compatible ways to capture
4 | #' symbols (`sym()`, `syms()`, `ensym()`), expressions (`expr()`,
5 | #' `exprs()`, `enexpr()`), and quosures (`quo()`, `quos()`, `enquo()`).
6 | #'
7 | #' @name tidyeval
8 | #' @keywords internal
9 | #' @family utilities
10 | #' @aliases quo quos enquo sym syms ensym expr exprs enexpr quo_name
11 | #' @importFrom rlang quo quos enquo sym syms ensym expr exprs enexpr quo_name
12 | #' @importFrom dplyr all_of any_of one_of contains ends_with starts_with
13 | #' @importFrom dplyr everything
14 | #' @importFrom rlang UQ UQS .data := %||%
15 | #' @export quo quos enquo sym syms ensym expr exprs enexpr quo_name
16 | NULL
17 |
--------------------------------------------------------------------------------
/tests/testthat/test-encryption_key_list.R:
--------------------------------------------------------------------------------
1 | test_that("encryption_key_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | x <- encryption_key_list(
7 | pid = Sys.getenv("ODKC_TEST_PID_ENC"),
8 | fid = Sys.getenv("ODKC_TEST_FID_ENC"),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 |
14 | cn <- c(
15 | "id",
16 | "public",
17 | "managed",
18 | "hint",
19 | "created_at"
20 | )
21 |
22 | purrr::map(
23 | cn,
24 | ~ testthat::expect_true(
25 | . %in% names(x),
26 | label = glue::glue("Column {.} present in encryption_key_list")
27 | )
28 | )
29 | })
30 |
31 |
32 | # usethis::use_r("encryption_key_list") # nolint
33 |
--------------------------------------------------------------------------------
/man/ru_msg_abort.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_msg.R
3 | \name{ru_msg_abort}
4 | \alias{ru_msg_abort}
5 | \title{rlang::abort() with a red error message with a cross symbol.}
6 | \usage{
7 | ru_msg_abort(message)
8 | }
9 | \arguments{
10 | \item{message}{(chr) A message to print}
11 | }
12 | \description{
13 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
14 | }
15 | \examples{
16 | \dontrun{
17 | ru_msg_abort("This is an error, abort.")
18 | }
19 | }
20 | \seealso{
21 | Other messaging:
22 | \code{\link{ru_msg_info}()},
23 | \code{\link{ru_msg_noop}()},
24 | \code{\link{ru_msg_success}()},
25 | \code{\link{ru_msg_warn}()}
26 | }
27 | \concept{messaging}
28 |
--------------------------------------------------------------------------------
/inst/binder/install.R:
--------------------------------------------------------------------------------
1 | options(repos = c(ropensci = "https://ropensci.r-universe.dev",
2 | MRAN = "https://mran.microsoft.com/snapshot/2020-07-16",
3 | CRAN = "https://cloud.r-project.org"))
4 |
5 | # install.packages("remotes")
6 | # install.packages("rmarkdown")
7 | install.packages("mapview")
8 | install.packages("gt")
9 | install.packages("reactable")
10 |
11 | install.packages("leaflet")
12 | install.packages("leaflet.extras")
13 | install.packages("leaflet.providers")
14 | install.packages("leaftime")
15 | install.packages("caTools")
16 | install.packages("bitops")
17 | install.packages("ckanr")
18 | install.packages("googledrive")
19 |
20 | install.packages("ruODK")
21 | # remotes::install_github(
22 | # 'ropensci/ruODK@main',
23 | # force = TRUE,
24 | # ask=FALSE,
25 | # upgrade='never',
26 | # dependencies = c('Depends', 'Imports', 'Suggests')
27 | # )
28 |
--------------------------------------------------------------------------------
/tests/testthat/test-project_create.R:
--------------------------------------------------------------------------------
1 | test_that("project_create works", {
2 | # nolint start
3 | # p <- project_create(
4 | # "Test Project",
5 | # url = Sys.getenv("ODKC_TEST_URL"),
6 | # un = Sys.getenv("ODKC_TEST_UN"),
7 | # pw = Sys.getenv("ODKC_TEST_PW")
8 | # )
9 | # testthat::expect_equal(nrow(p), 1)
10 | #
11 | # # project_create returns a tibble
12 | # testthat::expect_equal(class(p), c("tbl_df", "tbl", "data.frame"))
13 | #
14 | # # Project metadata (some) are the tibble's columns
15 | # cn <- c(
16 | # "id", "name", "archived"
17 | # )
18 | # testthat::expect_equal(names(p), cn)
19 | # nolint end
20 |
21 | testthat::expect_warning(
22 | project_create(
23 | "Test Project",
24 | url = get_test_url(),
25 | un = get_test_un(),
26 | pw = get_test_pw()
27 | ), "Not implemented."
28 | )
29 | })
30 |
31 | # usethis::use_r("project_create") # nolint
32 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-retired.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-soft-deprecated.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/man/ru_msg_info.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_msg.R
3 | \name{ru_msg_info}
4 | \alias{ru_msg_info}
5 | \title{Print a blue info message with an info symbol.}
6 | \usage{
7 | ru_msg_info(message, verbose = get_ru_verbose())
8 | }
9 | \arguments{
10 | \item{message}{(chr) A message to print}
11 |
12 | \item{verbose}{Whether to display debug messages or not.
13 |
14 | Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s
15 | verbosity can be set globally or per function.}
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \examples{
21 | ru_msg_info("This is an info message.")
22 | }
23 | \seealso{
24 | Other messaging:
25 | \code{\link{ru_msg_abort}()},
26 | \code{\link{ru_msg_noop}()},
27 | \code{\link{ru_msg_success}()},
28 | \code{\link{ru_msg_warn}()}
29 | }
30 | \concept{messaging}
31 |
--------------------------------------------------------------------------------
/man/ru_msg_noop.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_msg.R
3 | \name{ru_msg_noop}
4 | \alias{ru_msg_noop}
5 | \title{Print a green noop message with a filled circle symbol.}
6 | \usage{
7 | ru_msg_noop(message, verbose = get_ru_verbose())
8 | }
9 | \arguments{
10 | \item{message}{(chr) A message to print}
11 |
12 | \item{verbose}{Whether to display debug messages or not.
13 |
14 | Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s
15 | verbosity can be set globally or per function.}
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \examples{
21 | ru_msg_noop("This is a noop message.")
22 | }
23 | \seealso{
24 | Other messaging:
25 | \code{\link{ru_msg_abort}()},
26 | \code{\link{ru_msg_info}()},
27 | \code{\link{ru_msg_success}()},
28 | \code{\link{ru_msg_warn}()}
29 | }
30 | \concept{messaging}
31 |
--------------------------------------------------------------------------------
/man/ru_msg_success.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_msg.R
3 | \name{ru_msg_success}
4 | \alias{ru_msg_success}
5 | \title{Print a green success message with a tick symbol.}
6 | \usage{
7 | ru_msg_success(message, verbose = get_ru_verbose())
8 | }
9 | \arguments{
10 | \item{message}{(chr) A message to print}
11 |
12 | \item{verbose}{Whether to display debug messages or not.
13 |
14 | Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s
15 | verbosity can be set globally or per function.}
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \examples{
21 | ru_msg_success("This is a success message.")
22 | }
23 | \seealso{
24 | Other messaging:
25 | \code{\link{ru_msg_abort}()},
26 | \code{\link{ru_msg_info}()},
27 | \code{\link{ru_msg_noop}()},
28 | \code{\link{ru_msg_warn}()}
29 | }
30 | \concept{messaging}
31 |
--------------------------------------------------------------------------------
/man/ru_msg_warn.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_msg.R
3 | \name{ru_msg_warn}
4 | \alias{ru_msg_warn}
5 | \title{rlang::warn() with a yellow warning message with a warning symbol.}
6 | \usage{
7 | ru_msg_warn(message, verbose = get_ru_verbose())
8 | }
9 | \arguments{
10 | \item{message}{(chr) A message to print}
11 |
12 | \item{verbose}{Whether to display debug messages or not.
13 |
14 | Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s
15 | verbosity can be set globally or per function.}
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \examples{
21 | \dontrun{
22 | ru_msg_warn("This is a warning.")
23 | }
24 | }
25 | \seealso{
26 | Other messaging:
27 | \code{\link{ru_msg_abort}()},
28 | \code{\link{ru_msg_info}()},
29 | \code{\link{ru_msg_noop}()},
30 | \code{\link{ru_msg_success}()}
31 | }
32 | \concept{messaging}
33 |
--------------------------------------------------------------------------------
/tests/testthat/test-handle_ru_datetimes.R:
--------------------------------------------------------------------------------
1 | test_that("handle_ru_datetimes produces datetimes", {
2 | data("fq_raw")
3 | data("fq_form_schema")
4 |
5 | fq_with_dates <- fq_raw %>%
6 | ruODK::odata_submission_rectangle() %>%
7 | ruODK::handle_ru_datetimes(form_schema = fq_form_schema)
8 |
9 | # nolint start
10 | # fq_with_dates %>% purrr::map(class)
11 | # nolint end
12 |
13 | date_time_fields <- fq_form_schema %>%
14 | dplyr::filter(type == "dateTime") %>%
15 | magrittr::extract2("ruodk_name")
16 |
17 | if (length(date_time_fields) == 0) {
18 | rlang::warn(
19 | glue::glue(
20 | "test-handle_ru_datetimes needs test data",
21 | "with at least one dateTime field. Form schema:\n\n",
22 | "{knitr::kable(fq_form_schema)}"
23 | )
24 | )
25 | }
26 |
27 | # Is this a date?
28 | # https://i.imgur.com/NKRMXW4.jpg
29 | testthat::expect_equal(
30 | fq_with_dates %>% magrittr::extract2(date_time_fields[[1]]) %>% class(),
31 | c("POSIXct", "POSIXt")
32 | )
33 | })
34 |
35 | # usethis::use_r("handle_ru_datetimess") # nolint
36 |
--------------------------------------------------------------------------------
/tests/testthat/test-form_detail.R:
--------------------------------------------------------------------------------
1 | test_that("form_detail works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | # The test project has a list of forms
7 | fl <- form_list(
8 | get_test_pid(),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 |
14 | # The first form in the test project
15 | f <- form_detail(
16 | get_test_pid(),
17 | fl$fid[[1]],
18 | url = get_test_url(),
19 | un = get_test_un(),
20 | pw = get_test_pw()
21 | )
22 |
23 | # form_detail returns exactly one row
24 | testthat::expect_true(nrow(f) == 1)
25 |
26 | # Columns: name, xmlFormId, and more
27 | testthat::expect_true("name" %in% names(f))
28 | testthat::expect_true("fid" %in% names(f))
29 | cn <- c(
30 | "name", "fid", "version", "state", "submissions", "created_at",
31 | "created_by_id", "created_by", "updated_at", "published_at",
32 | "last_submission", "hash"
33 | )
34 | testthat::expect_equal(names(f), cn)
35 | })
36 |
37 | # usethis::use_r("form_detail") # nolint
38 |
--------------------------------------------------------------------------------
/tests/testthat/test-attachment_list.R:
--------------------------------------------------------------------------------
1 | test_that("attachment_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | sl <- submission_list(
7 | pid = get_test_pid(),
8 | fid = get_test_fid(),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 |
14 | al <- get_one_submission_att_list(
15 | sl$instance_id[[1]],
16 | pid = get_test_pid(),
17 | fid = get_test_fid(),
18 | url = get_test_url(),
19 | un = get_test_un(),
20 | pw = get_test_pw()
21 | )
22 |
23 | all <- attachment_list(
24 | sl$instance_id,
25 | pid = get_test_pid(),
26 | fid = get_test_fid(),
27 | url = get_test_url(),
28 | un = get_test_un(),
29 | pw = get_test_pw()
30 | )
31 |
32 | # attachment_list returns a tibble
33 | testthat::expect_equal(class(al), c("tbl_df", "tbl", "data.frame"))
34 |
35 | # Attachment attributes are the tibble's columns
36 | cn <- c("name", "exists")
37 | testthat::expect_equal(names(al), cn)
38 | })
39 |
40 | # usethis::use_r("attachment_list") # nolint
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-submission_detail.R:
--------------------------------------------------------------------------------
1 | test_that("submission_detail works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | sl <- submission_list(
7 | pid = get_test_pid(),
8 | fid = get_test_fid(),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 |
14 | sub <- submission_detail(
15 | sl$instance_id[[1]],
16 | pid = get_test_pid(),
17 | fid = get_test_fid(),
18 | url = get_test_url(),
19 | un = get_test_un(),
20 | pw = get_test_pw()
21 | )
22 |
23 | # submission_detail returns a tibble
24 | testthat::expect_equal(class(sub), c("tbl_df", "tbl", "data.frame"))
25 |
26 |
27 | # The details for one submission return exactly one row
28 | testthat::expect_equal(nrow(sub), 1)
29 |
30 | # The columns are metadata, plus the submission data in column 'xml`
31 | # names(sub) # nolint
32 | cn <- c(
33 | "instance_id", "submitter_id", "submitter", "created_at", "updated_at"
34 | )
35 | testthat::expect_equal(names(sub), cn)
36 | })
37 |
38 | # usethis::use_r("submission_detail") # nolint
39 |
--------------------------------------------------------------------------------
/man/odata_svc_parse.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{odata_svc_parse}
4 | \alias{odata_svc_parse}
5 | \title{Retrieve URL, project ID, and form ID from an ODK Central OData service URL.}
6 | \usage{
7 | odata_svc_parse(svc)
8 | }
9 | \arguments{
10 | \item{svc}{(character) The OData service URL of a form as provided by the
11 | ODK Central form submissions tab.
12 | Example: "https://URL/v1/projects/PID/forms/FID.svc"}
13 | }
14 | \value{
15 | A named list with three components (all of type character):
16 | \itemize{
17 | \item \code{url} The ODK Central base URL.
18 | \item \code{pid} The project ID.
19 | \item\code{fid} The form ID.
20 | }
21 | }
22 | \description{
23 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
24 | }
25 | \seealso{
26 | Other ru_settings:
27 | \code{\link{parse_odkc_version}()},
28 | \code{\link{ru_settings}()},
29 | \code{\link{ru_setup}()},
30 | \code{\link{semver_gt}()},
31 | \code{\link{semver_lt}()},
32 | \code{\link{yell_if_error}()},
33 | \code{\link{yell_if_missing}()}
34 | }
35 | \concept{ru_settings}
36 |
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ghcr.io/rocker-org/devcontainer/r-ver:4.2
2 |
3 | # non interactive frontend for locales
4 | ENV DEBIAN_FRONTEND=noninteractive
5 |
6 | # installing texlive and utils
7 | RUN apt-get update && \
8 | apt-get -y install --no-install-recommends \
9 | libudunits2-dev libxtst6 libxt6 libmagick++-dev \
10 | libxml2-dev libjq-dev libudunits2-dev libgdal-dev libgeos-dev libproj-dev \
11 | libicu-dev libv8-dev libjq-dev libprotobuf-dev protobuf-compiler libgit2-dev \
12 | rsync mdbtools cargo libavfilter-dev libfontconfig1-dev libopenblas-dev \
13 | freetds-common libct4 libsybdb5 freetds-bin freetds-dev libsybdb5 tdsodbc \
14 | unixodbc make git procps locales curl && \
15 | rm -rf /var/lib/apt/lists/*
16 |
17 | # generating locales
18 | RUN sed -i -e 's/# en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen && \
19 | dpkg-reconfigure --frontend=noninteractive locales && \
20 | update-locale LANG=en_GB.UTF-8
21 | ENV LANGUAGE=en_GB.UTF-8 LANG=en_GB.UTF-8 LC_ALL=en_GB.UTF-8
22 |
23 | # installing cpanm & missing latexindent dependencies
24 | RUN curl -L http://cpanmin.us | perl - --self-upgrade && \
25 | cpanm Log::Dispatch::File YAML::Tiny File::HomeDir
26 |
--------------------------------------------------------------------------------
/tests/testthat/test-entity_list.R:
--------------------------------------------------------------------------------
1 | test_that("entity_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | ru_setup(
7 | pid = get_test_pid(),
8 | url = get_test_url(),
9 | un = get_test_un(),
10 | pw = get_test_pw(),
11 | odkc_version = get_test_odkc_version()
12 | )
13 |
14 | el <- entitylist_list()
15 | did <- el$name[1]
16 | en <- entity_list(did = el$name[1])
17 | eid <- en$uuid[1]
18 |
19 | testthat::expect_s3_class(en, "tbl_df")
20 |
21 | cn <- c(
22 | "uuid",
23 | "creator_id",
24 | "created_at",
25 | "updated_at",
26 | "deleted_at",
27 | "current_version_current",
28 | "current_version_label",
29 | "current_version_creator_id",
30 | "current_version_user_agent",
31 | "current_version_version",
32 | "current_version_base_version",
33 | "current_version_conflicting_properties",
34 | "current_version_created_at",
35 | "current_version_branch_id",
36 | "current_version_trunk_version",
37 | "current_version_branch_base_version"
38 | )
39 |
40 | testthat::expect_equal(names(en), cn)
41 | })
42 |
43 | # usethis::use_r("entity_list") # nolint
44 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM rocker/binder:4.1.3 as base
2 | LABEL maintainer=Florian.Mayer@dbca.wa.gov.au
3 | LABEL description="rocker/binder:4.1.3 with ruODK"
4 | # Build this image with
5 | # docker build . -t dbcawa/ruodk:latest --build-arg GITHUB_PAT="..."
6 | # Run this image as Jupyter Notebook with
7 | # docker run -p 8888:8888 dbcawa/ruodk:latest
8 | # Open URL, then select New > Rstudio
9 |
10 | # Build args ------------------------------------------------------------------#
11 | ARG NB_USER
12 | ARG NB_UID
13 | ARG GITHUB_PAT
14 | ENV GITHUB_PAT=$GITHUB_PAT
15 |
16 | # Home directory --------------------------------------------------------------#
17 | USER root
18 | COPY inst/binder ${HOME}
19 | RUN chown -R ${NB_USER} ${HOME}
20 |
21 | # System dependencies ---------------------------------------------------------#
22 | RUN apt-get update --fix-missing && apt remove -y libvorbis0a && \
23 | xargs -a apt.txt apt-get -y install --no-install-recommends && \
24 | apt-get purge && apt-get clean && rm -rf /var/lib/apt/lists/*
25 |
26 | # R packages ------------------------------------------------------------------#
27 | FROM base as r_libs
28 | USER ${NB_USER}
29 | RUN if [ -f install.R ]; then R --quiet -f install.R; fi
30 |
--------------------------------------------------------------------------------
/R/isodt_to_local.R:
--------------------------------------------------------------------------------
1 | #' Parse an ISO8601 datetime string to a timezone aware datetime.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' This function is used internally by `ruODK` to parse ISO timestamps
6 | #' to timezone-aware local times.
7 | #'
8 | #' Warnings are suppressed through `lubridate::parse_date_time(quiet=TRUE)`.
9 | #'
10 | #' @param datetime_string (character) An ISO8601 datetime string as produced by
11 | #' XForms exported from ODK Central.
12 | #' @param orders (vector of character) Orders of datetime elements for
13 | #' `lubridate`.
14 | #' Default: \code{c("YmdHMS", "YmdHMSz", "Ymd HMS", "Ymd HMSz")}.
15 | #' @template param-tz
16 | #' @param quiet (lgl) Used in `lubridate::parse_date_time(quiet=quiet)` to
17 | #' suppress warnings from attempting to parse all empty values or columns.
18 | #' Run with `quiet=FALSE` to show any `lubridate` warnings.
19 | #' @return A `lubridate` PosixCT datetime in the given timezone.
20 | #' @family utilities
21 | #' @keywords internal
22 | isodt_to_local <- function(datetime_string,
23 | orders = c("YmdHMS", "YmdHMSz"),
24 | tz = get_default_tz(),
25 | quiet = TRUE) {
26 | datetime_string %>%
27 | lubridate::parse_date_time(orders = orders, quiet = quiet) %>%
28 | lubridate::with_tz(., tzone = tz)
29 | }
30 |
--------------------------------------------------------------------------------
/tests/testthat/test-form_xml.R:
--------------------------------------------------------------------------------
1 | test_that("form_xml returns a nested list with parse defaults", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | fxml <- form_xml(
7 | pid = get_test_pid(),
8 | fid = get_test_fid(),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 | testthat::expect_equal(class(fxml), "list")
14 | })
15 |
16 | test_that("form_xml returns a nested list with parse=TRUE", {
17 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
18 | message = "Test server not configured"
19 | )
20 |
21 | fxml <- form_xml(
22 | parse = TRUE,
23 | pid = get_test_pid(),
24 | fid = get_test_fid(),
25 | url = get_test_url(),
26 | un = get_test_un(),
27 | pw = get_test_pw()
28 | )
29 | testthat::expect_equal(class(fxml), "list")
30 | })
31 |
32 | test_that("form_xml returns an xml_document with parse=FALSE", {
33 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
34 | message = "Test server not configured"
35 | )
36 |
37 | fxml <- form_xml(
38 | parse = FALSE,
39 | pid = get_test_pid(),
40 | fid = get_test_fid(),
41 | url = get_test_url(),
42 | un = get_test_un(),
43 | pw = get_test_pw()
44 | )
45 | testthat::expect_equal(class(fxml), c("xml_document", "xml_node"))
46 | })
47 |
48 | # usethis::use_r("form_xml") # nolint
49 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/tests/testthat/test-audit_get.R:
--------------------------------------------------------------------------------
1 | test_that("audit_get works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | logs <- audit_get(
7 | url = get_test_url(),
8 | un = get_test_un(),
9 | pw = get_test_pw()
10 | )
11 |
12 | # With search parameters
13 | logs_pars <- audit_get(
14 | action = "project.update",
15 | start = "2019-08-01Z",
16 | end = "2019-08-31Z",
17 | limit = 100,
18 | offset = 0,
19 | url = get_test_url(),
20 | un = get_test_un(),
21 | pw = get_test_pw()
22 | )
23 |
24 | logs_part <- audit_get(
25 | action = "project.update",
26 | limit = 100,
27 | offset = 0,
28 | url = get_test_url(),
29 | un = get_test_un(),
30 | pw = get_test_pw()
31 | )
32 |
33 | # submission_list returns a tibble
34 | testthat::expect_equal(class(logs), c("tbl_df", "tbl", "data.frame"))
35 | testthat::expect_equal(class(logs_pars), c("tbl_df", "tbl", "data.frame"))
36 | testthat::expect_equal(class(logs_part), c("tbl_df", "tbl", "data.frame"))
37 |
38 | # Submission attributes are the tibble's columns
39 | cn <- c("actor_id", "action", "actee_id", "details", "logged_at")
40 | testthat::expect_equal(names(logs), cn)
41 | testthat::expect_equal(names(logs_pars), cn)
42 | testthat::expect_equal(names(logs_part), cn)
43 | })
44 |
45 | # usethis::use_r("audit_get") # nolint
46 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | # DO NOT CHANGE the "init" and "install" sections below
2 |
3 | # Download script file from GitHub
4 | init:
5 | ps: |
6 | $ErrorActionPreference = "Stop"
7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
8 | Import-Module '..\appveyor-tool.ps1'
9 |
10 | install:
11 | ps: Bootstrap
12 |
13 | cache:
14 | - C:\RLibrary
15 |
16 | environment:
17 | NOT_CRAN: true
18 | # env vars that may need to be set, at least temporarily, from time to time
19 | # see https://github.com/krlmlr/r-appveyor#readme for details
20 | USE_RTOOLS: true
21 | # https://github.com/krlmlr/r-appveyor/issues/135
22 | # Fix error "cannot remove prior installation of package 'curl'"
23 | R_REMOTES_STANDALONE: true
24 |
25 | # Adapt as necessary starting from here
26 |
27 | build_script:
28 | - travis-tool.sh install_deps
29 |
30 | test_script:
31 | - travis-tool.sh run_tests
32 |
33 | on_failure:
34 | - 7z a failure.zip *.Rcheck\*
35 | - appveyor PushArtifact failure.zip
36 |
37 | artifacts:
38 | - path: '*.Rcheck\**\*.log'
39 | name: Logs
40 |
41 | - path: '*.Rcheck\**\*.out'
42 | name: Logs
43 |
44 | - path: '*.Rcheck\**\*.fail'
45 | name: Logs
46 |
47 | - path: '*.Rcheck\**\*.Rout'
48 | name: Logs
49 |
50 | - path: '\*_*.tar.gz'
51 | name: Bits
52 |
53 | - path: '\*_*.zip'
54 | name: Bits
55 |
--------------------------------------------------------------------------------
/data-raw/make_logo.R:
--------------------------------------------------------------------------------
1 | # -----------------------------------------------------------------------------#
2 | # Hex sticker
3 | #
4 | # remotes::install_github("GuangchuangYu/hexSticker")
5 | library(hexSticker)
6 | library(showtext)
7 | sysfonts::font_add_google("Knewave", "knewave")
8 | # sysfonts::font_add_google("Prosto One", "prosto")
9 | # sysfonts::font_add_google("Concert One", "concert")
10 | turtle <- here::here("man", "figures", "turtle.png")
11 | logo <- here::here("man", "figures", "logo.jpg")
12 | ruodklogo <- here::here("man", "figures", "ruODK.png")
13 | ruodklogo2 <- here::here("man", "figures", "ruODK2.png")
14 | darkred <- "#a50b0b"
15 | # logo s_, text p_, bg h_
16 | hexSticker::sticker(
17 | turtle,
18 | # asp = 0.684, dpi = 300,
19 | s_x = 1.0, s_y = 1.00, s_width = 1.1, # s_height = 0.1,
20 | package = "ruODK", p_x = 1, p_y = 0.43, p_size = 24,
21 | p_family = "knewave", p_color = darkred,
22 | h_fill = "#aaaaaa", h_color = darkred,
23 | # url = "docs.ropensci.org/ruODK", u_size = 4, u_color = "#ffffff",
24 | white_around_sticker = TRUE,
25 | filename = ruodklogo
26 | )
27 |
28 | hexSticker::sticker(
29 | logo,
30 | s_x = 1.0, s_y = 1.05, s_width = 1.05,
31 | package = "", p_x = 1, p_y = 0.43, p_size = 24,
32 | h_fill = "#000000", h_color = "#000000",
33 | url = "docs.ropensci.org/ruODK",
34 | u_size = 6, u_color = "#ffffff", u_x = 1.05, u_y = 0.1,
35 | white_around_sticker = TRUE,
36 | filename = ruodklogo2
37 | )
38 |
--------------------------------------------------------------------------------
/man/yell_if_error.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{yell_if_error}
4 | \alias{yell_if_error}
5 | \title{Warn about failed web requests and give helpful troubleshooting tips.}
6 | \usage{
7 | yell_if_error(response, url, un, pw, pid = NULL, fid = NULL)
8 | }
9 | \arguments{
10 | \item{response}{A httr response object}
11 |
12 | \item{url}{A URL (character)}
13 |
14 | \item{un}{A username (character)}
15 |
16 | \item{pw}{A password (character)}
17 |
18 | \item{pid}{A project ID (numeric, optional)}
19 |
20 | \item{fid}{A form ID (character, optional)}
21 | }
22 | \value{
23 | The response object
24 | }
25 | \description{
26 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
27 | }
28 | \details{
29 | A wrapper around \code{httr::stop_for_status} with a more helpful error
30 | message.
31 | Examples: see tests for \code{\link{project_list}}.
32 | This function is used internally but may be useful for debugging and
33 | \code{\link{ruODK}} development.
34 | }
35 | \seealso{
36 | Other ru_settings:
37 | \code{\link{odata_svc_parse}()},
38 | \code{\link{parse_odkc_version}()},
39 | \code{\link{ru_settings}()},
40 | \code{\link{ru_setup}()},
41 | \code{\link{semver_gt}()},
42 | \code{\link{semver_lt}()},
43 | \code{\link{yell_if_missing}()}
44 | }
45 | \concept{ru_settings}
46 | \keyword{internal}
47 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 |
30 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect all people who
4 | contribute through reporting issues, posting feature requests, updating documentation,
5 | submitting pull requests or patches, and other activities.
6 |
7 | We are committed to making participation in this project a harassment-free experience for
8 | everyone, regardless of level of experience, gender, gender identity and expression,
9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
10 |
11 | Examples of unacceptable behaviour by participants include the use of sexual language or
12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment,
13 | insults, or other unprofessional conduct.
14 |
15 | Project maintainers have the right and responsibility to remove, edit, or reject comments,
16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this
17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed
18 | from the project team.
19 |
20 | Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by
21 | opening an issue or contacting one or more of the project maintainers.
22 |
23 | This Code of Conduct is adapted from the Contributor Covenant
24 | (), version 1.0.0, available at
25 |
26 |
--------------------------------------------------------------------------------
/man/semver_lt.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{semver_lt}
4 | \alias{semver_lt}
5 | \title{Show whether a given semver is lesser than a baseline version.}
6 | \usage{
7 | semver_lt(sv = get_default_odkc_version(), to = "1.5.0")
8 | }
9 | \arguments{
10 | \item{sv}{The semver to compare as character
11 | ("2023.5.1", "1.5.0", "1.5"), or numeric (1.5).
12 | The value is always parsed with \code{semver::parse_semver()}.
13 | Default: get_default_odkc_version().}
14 |
15 | \item{to}{The semver to compare to as string. Although semver can parse
16 | complete version strings, \code{to} is still parsed by \code{parse_odkc_version()}
17 | to ensure it is complete with major, minor, and patch version components.}
18 | }
19 | \value{
20 | A boolean indicating whether the given semver \code{sv} is greater than
21 | the baseline semver \code{to}.
22 | }
23 | \description{
24 | Show whether a given semver is lesser than a baseline version.
25 | }
26 | \examples{
27 | get_default_odkc_version() |> semver_lt("0.8.0")
28 | "2024.1.1" |> semver_lt("2024.1.0")
29 | "2024.1.1" |> semver_lt("2024.1.1")
30 | "2024.1.1" |> semver_lt("2024.1.2")
31 | }
32 | \seealso{
33 | Other ru_settings:
34 | \code{\link{odata_svc_parse}()},
35 | \code{\link{parse_odkc_version}()},
36 | \code{\link{ru_settings}()},
37 | \code{\link{ru_setup}()},
38 | \code{\link{semver_gt}()},
39 | \code{\link{yell_if_error}()},
40 | \code{\link{yell_if_missing}()}
41 | }
42 | \concept{ru_settings}
43 |
--------------------------------------------------------------------------------
/tests/testthat/test-entitylist_list.R:
--------------------------------------------------------------------------------
1 | test_that("entitylist_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | ru_setup(
7 | pid = get_test_pid(),
8 | url = get_test_url(),
9 | un = get_test_un(),
10 | pw = get_test_pw(),
11 | odkc_version = get_test_odkc_version()
12 | )
13 |
14 | ds <- entitylist_list()
15 | testthat::expect_true(nrow(ds) > 0)
16 | testthat::expect_true("name" %in% names(ds))
17 |
18 | # function returns a tibble
19 | testthat::expect_s3_class(ds, "tbl_df")
20 |
21 | # Expected column names
22 | cn <- c(
23 | "name",
24 | "created_at",
25 | "project_id",
26 | "approval_required",
27 | "owner_only",
28 | "entities",
29 | "last_entity",
30 | "conflicts"
31 | )
32 | testthat::expect_equal(names(ds), cn)
33 | })
34 |
35 |
36 | test_that("entitylist_list warns if odkc_version too low", {
37 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
38 | message = "Test server not configured"
39 | )
40 |
41 | ru_setup(
42 | pid = get_test_pid(),
43 | url = get_test_url(),
44 | un = get_test_un(),
45 | pw = get_test_pw(),
46 | odkc_version = get_test_odkc_version()
47 | )
48 |
49 | ds <- entitylist_list()
50 | did <- ds$name[1]
51 |
52 | ds1 <- entitylist_list()
53 |
54 | testthat::expect_warning(
55 | ds1 <- entitylist_list(odkc_version = "1.5.3")
56 | )
57 | })
58 |
59 | # usethis::use_r("entitylist_list") # nolint
60 |
--------------------------------------------------------------------------------
/man/semver_gt.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{semver_gt}
4 | \alias{semver_gt}
5 | \title{Show whether a given semver is greater than a baseline version.}
6 | \usage{
7 | semver_gt(sv = get_default_odkc_version(), to = "1.5.0")
8 | }
9 | \arguments{
10 | \item{sv}{The semver to compare as character
11 | ("2023.5.1", "1.5.0", "1.5"), or numeric (1.5).
12 | The value is always parsed with \code{semver::parse_semver()}.
13 | Default: get_default_odkc_version().}
14 |
15 | \item{to}{The semver to compare to as string. Although semver can parse
16 | complete version strings, \code{to} is still parsed by \code{parse_odkc_version()}
17 | to ensure it is complete with major, minor, and patch version components.}
18 | }
19 | \value{
20 | A boolean indicating whether the given semver \code{sv} is greater than
21 | the baseline semver \code{to}.
22 | }
23 | \description{
24 | Show whether a given semver is greater than a baseline version.
25 | }
26 | \examples{
27 | get_default_odkc_version() |> semver_gt("0.8.0")
28 | "2024.1.1" |> semver_gt("2024.1.0")
29 | "2024.1.1" |> semver_gt("2024.1.1")
30 | "2024.1.1" |> semver_gt("2024.1.2")
31 | }
32 | \seealso{
33 | Other ru_settings:
34 | \code{\link{odata_svc_parse}()},
35 | \code{\link{parse_odkc_version}()},
36 | \code{\link{ru_settings}()},
37 | \code{\link{ru_setup}()},
38 | \code{\link{semver_lt}()},
39 | \code{\link{yell_if_error}()},
40 | \code{\link{yell_if_missing}()}
41 | }
42 | \concept{ru_settings}
43 |
--------------------------------------------------------------------------------
/data-raw/make_asciicast.R:
--------------------------------------------------------------------------------
1 | #' Title: ruODK walkthough
2 | #' Author_img_url: ../man/figures/ruODK2.png
3 | #' Cols: 120
4 | #' Typing_speed: 0.05
5 | #' Empty_wait: 1
6 | #' End_wait: 20
7 |
8 | # <<
9 | # Use your form's OData Service URL (Form > Submissions > Analyse data)
10 | # Read vignette("setup") on setting username and password via .Renviron
11 | # <<
12 | suppressMessages(library(tidyverse))
13 | library(ruODK)
14 | ruODK::ru_setup(
15 | svc = Sys.getenv("ODKC_TEST_SVC"),
16 | un = ruODK::get_test_un(),
17 | pw = ruODK::get_test_pw()
18 | )
19 |
20 | # <<
21 | # List available submission data tables
22 | # <<
23 | fq_svc <- ruODK::odata_service_get()
24 | fq_svc
25 |
26 | # <<
27 | # Download main submissions and attachments
28 | # <<
29 | fq_data <- ruODK::odata_submission_get(
30 | table = fq_svc$name[1], wkt = TRUE, verbose = TRUE
31 | )
32 |
33 | # <<
34 | # Download first nested subtable, join to main submissions
35 | # <<
36 | fq_data_strata <- ruODK::odata_submission_get(
37 | table = fq_svc$name[2], wkt = TRUE, verbose = TRUE
38 | ) %>%
39 | dplyr::left_join(fq_data, by = c("submissions_id" = "id"))
40 |
41 | # <<
42 | # Download second nested subtable, join to main submissions
43 | # <<
44 | fq_data_taxa <- ruODK::odata_submission_get(
45 | table = fq_svc$name[3], wkt = TRUE, verbose = TRUE
46 | ) %>%
47 | dplyr::left_join(fq_data, by = c("submissions_id" = "id"))
48 |
49 | # <<
50 | # View data
51 | # <<
52 | names(fq_data)
53 | head(fq_data)
54 | head(fq_data_strata)
55 | head(fq_data_taxa)
56 |
--------------------------------------------------------------------------------
/man/fq_form_list.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_form_list}
6 | \alias{fq_form_list}
7 | \title{A tibble of forms.}
8 | \format{
9 | A tibble of forms
10 | }
11 | \source{
12 | The output of \code{\link{form_list}}.
13 | run on the project.
14 | }
15 | \usage{
16 | fq_form_list
17 | }
18 | \description{
19 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
20 | }
21 | \seealso{
22 | Other included:
23 | \code{\link{fq_attachments}},
24 | \code{\link{fq_data}},
25 | \code{\link{fq_data_strata}},
26 | \code{\link{fq_data_taxa}},
27 | \code{\link{fq_form_detail}},
28 | \code{\link{fq_form_schema}},
29 | \code{\link{fq_form_xml}},
30 | \code{\link{fq_meta}},
31 | \code{\link{fq_project_detail}},
32 | \code{\link{fq_project_list}},
33 | \code{\link{fq_raw}},
34 | \code{\link{fq_raw_strata}},
35 | \code{\link{fq_raw_taxa}},
36 | \code{\link{fq_submission_list}},
37 | \code{\link{fq_submissions}},
38 | \code{\link{fq_svc}},
39 | \code{\link{fq_zip_data}},
40 | \code{\link{fq_zip_strata}},
41 | \code{\link{fq_zip_taxa}},
42 | \code{\link{fs_v7}},
43 | \code{\link{fs_v7_raw}},
44 | \code{\link{geo_fs}},
45 | \code{\link{geo_gj}},
46 | \code{\link{geo_gj88}},
47 | \code{\link{geo_gj_raw}},
48 | \code{\link{geo_wkt}},
49 | \code{\link{geo_wkt88}},
50 | \code{\link{geo_wkt_raw}}
51 | }
52 | \concept{included}
53 | \keyword{datasets}
54 |
--------------------------------------------------------------------------------
/tests/testthat/test-form_list.R:
--------------------------------------------------------------------------------
1 | test_that("form_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | fl <- form_list(
7 | get_test_pid(),
8 | url = get_test_url(),
9 | un = get_test_un(),
10 | pw = get_test_pw()
11 | )
12 | testthat::expect_equal(class(fl), c("tbl_df", "tbl", "data.frame"))
13 | cn <- c(
14 | "project_id", "xml_form_id", "state", "enketo_id", "enketo_once_id",
15 | "created_at", "updated_at", "webforms_enabled", "key_id", "version", "hash",
16 | "sha", "sha256", "draft_token", "published_at", "name",
17 | "submissions", "entity_related", "review_states_received",
18 | "review_states_has_issues", "review_states_edited", "last_submission",
19 | "excel_content_type", "public_links", "created_by_id", "created_by_type",
20 | "created_by_display_name", "created_by_created_at",
21 | "created_by_updated_at", "created_by_deleted_at", "fid"
22 | )
23 | testthat::expect_equal(names(fl), cn)
24 |
25 | # Testing #86 form_list should work with draft forms present.
26 | # The above call to form_list worked so we test here that
27 | # the test forms contain a draft form.
28 | # Update: https://github.com/ropensci/ruODK/issues/119
29 | # Draft forms, and any forms from older Central versions
30 | # have published_at = NA.
31 | fl %>%
32 | dplyr::filter(is.na(published_at)) %>%
33 | nrow() %>%
34 | testthat::expect_gt(0)
35 | })
36 |
37 | # usethis::use_r("form_list") # nolint
38 |
--------------------------------------------------------------------------------
/tests/testthat/test-odata_submission_parse.R:
--------------------------------------------------------------------------------
1 | context("test-odata_submission_rectangle.R")
2 |
3 | test_that("odata_submission_rectangle works with gaps in first submission", {
4 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
5 | message = "Test server not configured"
6 | )
7 |
8 | t <- tempdir()
9 |
10 | fresh_raw <- odata_submission_get(
11 | pid = get_test_pid(),
12 | fid = get_test_fid_gap(),
13 | url = get_test_url(),
14 | un = get_test_un(),
15 | pw = get_test_pw(),
16 | odkc_version = get_test_odkc_version(),
17 | download = FALSE,
18 | parse = FALSE,
19 | verbose = TRUE
20 | )
21 |
22 | fresh_raw_parsed <- odata_submission_get(
23 | pid = get_test_pid(),
24 | fid = get_test_fid_gap(),
25 | url = get_test_url(),
26 | un = get_test_un(),
27 | pw = get_test_pw(),
28 | odkc_version = get_test_odkc_version(),
29 | download = FALSE,
30 | parse = TRUE,
31 | verbose = TRUE,
32 | local_dir = t
33 | )
34 |
35 | fresh_parsed <- fresh_raw %>% odata_submission_rectangle(verbose = TRUE)
36 | testthat::expect_gte(nrow(fresh_parsed), length(fresh_raw$value))
37 | testthat::expect_gte(nrow(fresh_parsed), nrow(fresh_raw_parsed))
38 |
39 | # TODO update to new test data
40 | # testthat::expect_equal(
41 | # class(fresh_raw_parsed$encounter_start_datetime[1]),
42 | # c("POSIXct", "POSIXt")
43 | # )
44 | })
45 |
46 | # nolint start
47 | # usethis::use_r("odata_submission_get")
48 | # usethis::use_r("odata_submission_rectangle")
49 | # nolint end
50 |
--------------------------------------------------------------------------------
/man/ruODK-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ruODK-package.R
3 | \docType{package}
4 | \name{ruODK-package}
5 | \alias{ruODK}
6 | \alias{ruODK-package}
7 | \title{ruODK: An R Client for the ODK Central API}
8 | \description{
9 | \code{\link{ruODK}} is an R Client for the ODK Central API.
10 |
11 | Please see the \code{ruODK} website for full documentation:
12 | \url{https://docs.ropensci.org/ruODK/}
13 |
14 | \code{ruODK} is "pipe-friendly" and re-exports \verb{\\\%>\\\%} and \verb{\\\%||\\\%}, but does not
15 | require their use.
16 | }
17 | \seealso{
18 | Useful links:
19 | \itemize{
20 | \item \url{https://docs.ropensci.org/ruODK}
21 | \item \url{https://github.com/ropensci/ruODK}
22 | \item Report bugs at \url{https://github.com/ropensci/ruODK/issues}
23 | }
24 |
25 | }
26 | \author{
27 | \strong{Maintainer}: Florian W. Mayer \email{Florian.Mayer@dpc.wa.gov.au} (\href{https://orcid.org/0000-0003-4269-4242}{ORCID})
28 |
29 | Other contributors:
30 | \itemize{
31 | \item Maëlle Salmon \email{maelle.salmon@yahoo.se} (\href{https://orcid.org/0000-0002-2815-0399}{ORCID}) [reviewer]
32 | \item Karissa Whiting (\href{https://orcid.org/0000-0002-4683-1868}{ORCID}) [reviewer]
33 | \item Jason Taylor [reviewer]
34 | \item Marcelo Tyszler (\href{https://orcid.org/0000-0002-4573-0002}{ORCID}) [contributor]
35 | \item Hélène Langet (\href{https://orcid.org/0000-0002-6758-2397}{ORCID}) [contributor]
36 | \item DBCA [copyright holder, funder]
37 | \item NWSFTCP [funder]
38 | }
39 |
40 | }
41 | \keyword{internal}
42 |
--------------------------------------------------------------------------------
/man/fq_project_list.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_project_list}
6 | \alias{fq_project_list}
7 | \title{A tibble of project metadata.}
8 | \format{
9 | A tibble of project metadata.
10 | }
11 | \source{
12 | The output of \code{\link{project_list}}
13 | run on all projects on the configured ODK Central server.
14 | }
15 | \usage{
16 | fq_project_list
17 | }
18 | \description{
19 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
20 | }
21 | \seealso{
22 | Other included:
23 | \code{\link{fq_attachments}},
24 | \code{\link{fq_data}},
25 | \code{\link{fq_data_strata}},
26 | \code{\link{fq_data_taxa}},
27 | \code{\link{fq_form_detail}},
28 | \code{\link{fq_form_list}},
29 | \code{\link{fq_form_schema}},
30 | \code{\link{fq_form_xml}},
31 | \code{\link{fq_meta}},
32 | \code{\link{fq_project_detail}},
33 | \code{\link{fq_raw}},
34 | \code{\link{fq_raw_strata}},
35 | \code{\link{fq_raw_taxa}},
36 | \code{\link{fq_submission_list}},
37 | \code{\link{fq_submissions}},
38 | \code{\link{fq_svc}},
39 | \code{\link{fq_zip_data}},
40 | \code{\link{fq_zip_strata}},
41 | \code{\link{fq_zip_taxa}},
42 | \code{\link{fs_v7}},
43 | \code{\link{fs_v7_raw}},
44 | \code{\link{geo_fs}},
45 | \code{\link{geo_gj}},
46 | \code{\link{geo_gj88}},
47 | \code{\link{geo_gj_raw}},
48 | \code{\link{geo_wkt}},
49 | \code{\link{geo_wkt88}},
50 | \code{\link{geo_wkt_raw}}
51 | }
52 | \concept{included}
53 | \keyword{datasets}
54 |
--------------------------------------------------------------------------------
/man/fs_v7_raw.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fs_v7_raw}
6 | \alias{fs_v7_raw}
7 | \title{The unparsed XML form_schema of a form from ODK Central v0.6 as nested list.}
8 | \format{
9 | An object of class \code{list} of length 6.
10 | }
11 | \source{
12 | \code{\link{form_schema}(odkc_version = 0.7, parse = FALSE)}
13 | }
14 | \usage{
15 | fs_v7_raw
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \seealso{
21 | Other included:
22 | \code{\link{fq_attachments}},
23 | \code{\link{fq_data}},
24 | \code{\link{fq_data_strata}},
25 | \code{\link{fq_data_taxa}},
26 | \code{\link{fq_form_detail}},
27 | \code{\link{fq_form_list}},
28 | \code{\link{fq_form_schema}},
29 | \code{\link{fq_form_xml}},
30 | \code{\link{fq_meta}},
31 | \code{\link{fq_project_detail}},
32 | \code{\link{fq_project_list}},
33 | \code{\link{fq_raw}},
34 | \code{\link{fq_raw_strata}},
35 | \code{\link{fq_raw_taxa}},
36 | \code{\link{fq_submission_list}},
37 | \code{\link{fq_submissions}},
38 | \code{\link{fq_svc}},
39 | \code{\link{fq_zip_data}},
40 | \code{\link{fq_zip_strata}},
41 | \code{\link{fq_zip_taxa}},
42 | \code{\link{fs_v7}},
43 | \code{\link{geo_fs}},
44 | \code{\link{geo_gj}},
45 | \code{\link{geo_gj88}},
46 | \code{\link{geo_gj_raw}},
47 | \code{\link{geo_wkt}},
48 | \code{\link{geo_wkt88}},
49 | \code{\link{geo_wkt_raw}}
50 | }
51 | \concept{included}
52 | \keyword{datasets}
53 |
--------------------------------------------------------------------------------
/man/fs_v7.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fs_v7}
6 | \alias{fs_v7}
7 | \title{The parsed XML form_schema of a form from ODK Central v0.6.}
8 | \format{
9 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 12 rows and 3 columns.
10 | }
11 | \source{
12 | \code{\link{form_schema_parse}(fs_v7_raw)}
13 | }
14 | \usage{
15 | fs_v7
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \seealso{
21 | Other included:
22 | \code{\link{fq_attachments}},
23 | \code{\link{fq_data}},
24 | \code{\link{fq_data_strata}},
25 | \code{\link{fq_data_taxa}},
26 | \code{\link{fq_form_detail}},
27 | \code{\link{fq_form_list}},
28 | \code{\link{fq_form_schema}},
29 | \code{\link{fq_form_xml}},
30 | \code{\link{fq_meta}},
31 | \code{\link{fq_project_detail}},
32 | \code{\link{fq_project_list}},
33 | \code{\link{fq_raw}},
34 | \code{\link{fq_raw_strata}},
35 | \code{\link{fq_raw_taxa}},
36 | \code{\link{fq_submission_list}},
37 | \code{\link{fq_submissions}},
38 | \code{\link{fq_svc}},
39 | \code{\link{fq_zip_data}},
40 | \code{\link{fq_zip_strata}},
41 | \code{\link{fq_zip_taxa}},
42 | \code{\link{fs_v7_raw}},
43 | \code{\link{geo_fs}},
44 | \code{\link{geo_gj}},
45 | \code{\link{geo_gj88}},
46 | \code{\link{geo_gj_raw}},
47 | \code{\link{geo_wkt}},
48 | \code{\link{geo_wkt88}},
49 | \code{\link{geo_wkt_raw}}
50 | }
51 | \concept{included}
52 | \keyword{datasets}
53 |
--------------------------------------------------------------------------------
/man/tidyeval.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils-tidy-eval.R
3 | \name{tidyeval}
4 | \alias{tidyeval}
5 | \alias{quo}
6 | \alias{quos}
7 | \alias{enquo}
8 | \alias{sym}
9 | \alias{syms}
10 | \alias{ensym}
11 | \alias{expr}
12 | \alias{exprs}
13 | \alias{enexpr}
14 | \alias{quo_name}
15 | \title{Tidy eval helpers}
16 | \description{
17 | These functions provide tidy eval-compatible ways to capture
18 | symbols (\code{sym()}, \code{syms()}, \code{ensym()}), expressions (\code{expr()},
19 | \code{exprs()}, \code{enexpr()}), and quosures (\code{quo()}, \code{quos()}, \code{enquo()}).
20 | }
21 | \seealso{
22 | Other utilities:
23 | \code{\link{attachment_get}()},
24 | \code{\link{attachment_link}()},
25 | \code{\link{attachment_url}()},
26 | \code{\link{drop_null_coords}()},
27 | \code{\link{form_schema_parse}()},
28 | \code{\link{get_one_attachment}()},
29 | \code{\link{get_one_submission}()},
30 | \code{\link{get_one_submission_att_list}()},
31 | \code{\link{get_one_submission_audit}()},
32 | \code{\link{handle_ru_attachments}()},
33 | \code{\link{handle_ru_datetimes}()},
34 | \code{\link{handle_ru_geopoints}()},
35 | \code{\link{handle_ru_geoshapes}()},
36 | \code{\link{handle_ru_geotraces}()},
37 | \code{\link{isodt_to_local}()},
38 | \code{\link{odata_submission_rectangle}()},
39 | \code{\link{predict_ruodk_name}()},
40 | \code{\link{prepend_uuid}()},
41 | \code{\link{split_geopoint}()},
42 | \code{\link{split_geoshape}()},
43 | \code{\link{split_geotrace}()},
44 | \code{\link{strip_uuid}()},
45 | \code{\link{unnest_all}()}
46 | }
47 | \concept{utilities}
48 | \keyword{internal}
49 |
--------------------------------------------------------------------------------
/man/fq_form_xml.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_form_xml}
6 | \alias{fq_form_xml}
7 | \title{A nested list of a form definition.}
8 | \format{
9 | A nested list of a form definition.
10 | }
11 | \source{
12 | The output of \code{\link{form_xml}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_form_xml
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_meta}},
32 | \code{\link{fq_project_detail}},
33 | \code{\link{fq_project_list}},
34 | \code{\link{fq_raw}},
35 | \code{\link{fq_raw_strata}},
36 | \code{\link{fq_raw_taxa}},
37 | \code{\link{fq_submission_list}},
38 | \code{\link{fq_submissions}},
39 | \code{\link{fq_svc}},
40 | \code{\link{fq_zip_data}},
41 | \code{\link{fq_zip_strata}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_form_detail.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_form_detail}
6 | \alias{fq_form_detail}
7 | \title{A tibble of form metadata.}
8 | \format{
9 | A tibble of form metadata.
10 | }
11 | \source{
12 | The output of \code{\link{form_detail}}
13 | run on submissions of the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_form_detail
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_list}},
29 | \code{\link{fq_form_schema}},
30 | \code{\link{fq_form_xml}},
31 | \code{\link{fq_meta}},
32 | \code{\link{fq_project_detail}},
33 | \code{\link{fq_project_list}},
34 | \code{\link{fq_raw}},
35 | \code{\link{fq_raw_strata}},
36 | \code{\link{fq_raw_taxa}},
37 | \code{\link{fq_submission_list}},
38 | \code{\link{fq_submissions}},
39 | \code{\link{fq_svc}},
40 | \code{\link{fq_zip_data}},
41 | \code{\link{fq_zip_strata}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_project_detail.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_project_detail}
5 | \alias{fq_project_detail}
6 | \title{A tibble of project metadata.}
7 | \format{
8 | A tibble of project metadata.
9 | }
10 | \source{
11 | The output of \code{\link{project_detail}}
12 | run on the project containing the test form
13 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
14 | }
15 | \usage{
16 | fq_project_detail
17 | }
18 | \description{
19 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
20 | }
21 | \seealso{
22 | Other included:
23 | \code{\link{fq_attachments}},
24 | \code{\link{fq_data}},
25 | \code{\link{fq_data_strata}},
26 | \code{\link{fq_data_taxa}},
27 | \code{\link{fq_form_detail}},
28 | \code{\link{fq_form_list}},
29 | \code{\link{fq_form_schema}},
30 | \code{\link{fq_form_xml}},
31 | \code{\link{fq_meta}},
32 | \code{\link{fq_project_list}},
33 | \code{\link{fq_raw}},
34 | \code{\link{fq_raw_strata}},
35 | \code{\link{fq_raw_taxa}},
36 | \code{\link{fq_submission_list}},
37 | \code{\link{fq_submissions}},
38 | \code{\link{fq_svc}},
39 | \code{\link{fq_zip_data}},
40 | \code{\link{fq_zip_strata}},
41 | \code{\link{fq_zip_taxa}},
42 | \code{\link{fs_v7}},
43 | \code{\link{fs_v7_raw}},
44 | \code{\link{geo_fs}},
45 | \code{\link{geo_gj}},
46 | \code{\link{geo_gj88}},
47 | \code{\link{geo_gj_raw}},
48 | \code{\link{geo_wkt}},
49 | \code{\link{geo_wkt88}},
50 | \code{\link{geo_wkt_raw}}
51 | }
52 | \concept{included}
53 | \keyword{datasets}
54 |
--------------------------------------------------------------------------------
/man/fq_submission_list.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_submission_list}
6 | \alias{fq_submission_list}
7 | \title{A tibble of submission metadata.}
8 | \format{
9 | A tibble of submission metadata.
10 | }
11 | \source{
12 | The output of \code{\link{submission_list}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_submission_list
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submissions}},
39 | \code{\link{fq_svc}},
40 | \code{\link{fq_zip_data}},
41 | \code{\link{fq_zip_strata}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_attachments.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_attachments}
6 | \alias{fq_attachments}
7 | \title{A tibble of submission attachments.}
8 | \format{
9 | A tibble of submission attachments.
10 | }
11 | \source{
12 | The output of \code{\link{attachment_list}}
13 | run on submissions of the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_attachments
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_data}},
25 | \code{\link{fq_data_strata}},
26 | \code{\link{fq_data_taxa}},
27 | \code{\link{fq_form_detail}},
28 | \code{\link{fq_form_list}},
29 | \code{\link{fq_form_schema}},
30 | \code{\link{fq_form_xml}},
31 | \code{\link{fq_meta}},
32 | \code{\link{fq_project_detail}},
33 | \code{\link{fq_project_list}},
34 | \code{\link{fq_raw}},
35 | \code{\link{fq_raw_strata}},
36 | \code{\link{fq_raw_taxa}},
37 | \code{\link{fq_submission_list}},
38 | \code{\link{fq_submissions}},
39 | \code{\link{fq_svc}},
40 | \code{\link{fq_zip_data}},
41 | \code{\link{fq_zip_strata}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_zip_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_zip_data}
6 | \alias{fq_zip_data}
7 | \title{A tibble of the main data table of records from a test form.}
8 | \format{
9 | A tibble of main records from a test form.
10 | }
11 | \source{
12 | \code{\link{submission_export}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_zip_data
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_strata}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_zip_taxa.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_zip_taxa}
6 | \alias{fq_zip_taxa}
7 | \title{A tibble of a repeated sub-group of records from a test form.}
8 | \format{
9 | A tibble of repeated sub-group of records from a test form.
10 | }
11 | \source{
12 | \code{\link{submission_export}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_zip_taxa
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_zip_strata.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_zip_strata}
6 | \alias{fq_zip_strata}
7 | \title{A tibble of a repeated sub-group of records from a test form.}
8 | \format{
9 | A tibble of repeated sub-group of records from a test form.
10 | }
11 | \source{
12 | \code{\link{submission_export}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | fq_zip_strata
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_taxa}},
43 | \code{\link{fs_v7}},
44 | \code{\link{fs_v7_raw}},
45 | \code{\link{geo_fs}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/geo_gj_raw.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_gj_raw}
6 | \alias{geo_gj_raw}
7 | \title{The unparsed submissions of a form containing geofields in GeoJSON.}
8 | \format{
9 | An object of class \code{list} of length 2.
10 | }
11 | \source{
12 | \code{\link{odata_submission_get}(wkt=FALSE, parse=FALSE)}
13 | run on the test form
14 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | geo_gj_raw
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_fs}},
47 | \code{\link{geo_gj}},
48 | \code{\link{geo_gj88}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/geo_wkt_raw.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_wkt_raw}
6 | \alias{geo_wkt_raw}
7 | \title{The unparsed submissions of a form containing geofields in WKT.}
8 | \format{
9 | An object of class \code{list} of length 2.
10 | }
11 | \source{
12 | \code{\link{odata_submission_get}(wkt=TRUE, parse=FALSE)}
13 | run on the test form
14 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | geo_wkt_raw
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_fs}},
47 | \code{\link{geo_gj}},
48 | \code{\link{geo_gj88}},
49 | \code{\link{geo_gj_raw}},
50 | \code{\link{geo_wkt}},
51 | \code{\link{geo_wkt88}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/geo_fs.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_fs}
6 | \alias{geo_fs}
7 | \title{The form_schema of a form containing geofields in GeoJSON.}
8 | \format{
9 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 19 rows and 6 columns.
10 | }
11 | \source{
12 | \code{\link{form_schema}}
13 | run on the test form
14 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | geo_fs
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_gj}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/man/fq_submissions.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{fq_submissions}
6 | \alias{fq_submissions}
7 | \title{A nested list of submission data.}
8 | \format{
9 | A nested list of submission data.
10 | }
11 | \source{
12 | The output of \code{\link{submission_get}}
13 | run on the test form
14 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
15 | using submission instance IDs from \code{\link{submission_list}}.
16 | }
17 | \usage{
18 | fq_submissions
19 | }
20 | \description{
21 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
22 | }
23 | \seealso{
24 | Other included:
25 | \code{\link{fq_attachments}},
26 | \code{\link{fq_data}},
27 | \code{\link{fq_data_strata}},
28 | \code{\link{fq_data_taxa}},
29 | \code{\link{fq_form_detail}},
30 | \code{\link{fq_form_list}},
31 | \code{\link{fq_form_schema}},
32 | \code{\link{fq_form_xml}},
33 | \code{\link{fq_meta}},
34 | \code{\link{fq_project_detail}},
35 | \code{\link{fq_project_list}},
36 | \code{\link{fq_raw}},
37 | \code{\link{fq_raw_strata}},
38 | \code{\link{fq_raw_taxa}},
39 | \code{\link{fq_submission_list}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_fs}},
47 | \code{\link{geo_gj}},
48 | \code{\link{geo_gj88}},
49 | \code{\link{geo_gj_raw}},
50 | \code{\link{geo_wkt}},
51 | \code{\link{geo_wkt88}},
52 | \code{\link{geo_wkt_raw}}
53 | }
54 | \concept{included}
55 | \keyword{datasets}
56 |
--------------------------------------------------------------------------------
/tests/testthat/test-entitylist_update.R:
--------------------------------------------------------------------------------
1 | test_that("entitylist_update works", {
2 | ru_setup(
3 | pid = get_test_pid(),
4 | url = get_test_url(),
5 | un = get_test_un(),
6 | pw = get_test_pw(),
7 | odkc_version = get_test_odkc_version()
8 | )
9 |
10 | ds <- entitylist_list()
11 |
12 | ds1 <- entitylist_detail(did = ds$name[1])
13 |
14 | did <- ds$name[1]
15 |
16 | # Update dataset with opposite approval_required
17 | ds2 <- entitylist_update(did = did, approval_required = !ds1$approval_required)
18 | testthat::expect_false(ds1$approval_required == ds2$approval_required)
19 |
20 | # Update dataset with opposite approval_required again
21 | ds3 <- entitylist_update(did = did, approval_required = !ds2$approval_required)
22 | testthat::expect_false(ds2$approval_required == ds3$approval_required)
23 | testthat::expect_true(ds1$approval_required == ds3$approval_required)
24 | })
25 |
26 | test_that("entitylist_update errors if did is missing", {
27 | testthat::expect_error(
28 | entitylist_update()
29 | )
30 | })
31 |
32 | test_that("entitylist_update warns if odkc_version too low", {
33 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
34 | message = "Test server not configured"
35 | )
36 | ru_setup(
37 | pid = get_test_pid(),
38 | url = get_test_url(),
39 | un = get_test_un(),
40 | pw = get_test_pw(),
41 | odkc_version = get_test_odkc_version()
42 | )
43 |
44 | ds <- entitylist_list()
45 | did <- ds$name[1]
46 |
47 | ds1 <- entitylist_update(did = did)
48 |
49 | testthat::expect_warning(
50 | ds1 <- entitylist_update(did = did, odkc_version = "1.5.3")
51 | )
52 | })
53 |
54 |
55 | # usethis::use_r("entitylist_update") # nolint
56 |
--------------------------------------------------------------------------------
/man/geo_wkt.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_wkt}
6 | \alias{geo_wkt}
7 | \title{The parsed submissions of a form containing geofields in WKT.}
8 | \format{
9 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 1 rows and 56 columns.
10 | }
11 | \source{
12 | \code{\link{odata_submission_get}(wkt=TRUE, parse=TRUE)}
13 | run on the test form
14 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | geo_wkt
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_fs}},
47 | \code{\link{geo_gj}},
48 | \code{\link{geo_gj88}},
49 | \code{\link{geo_gj_raw}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/tests/testthat/test-attachment_link.R:
--------------------------------------------------------------------------------
1 | test_that("submission_export works", {
2 | # This test downloads files
3 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
4 | message = "Test server not configured"
5 | )
6 |
7 |
8 | # A fresh litterbox
9 | t <- tempdir()
10 | fid <- get_test_fid_att() # Form with one submission
11 |
12 | fid_csv <- fs::path(t, glue::glue("{fid}.csv"))
13 |
14 | # Download submissions of a form with media attachments
15 | se <- submission_export(
16 | local_dir = t,
17 | overwrite = TRUE,
18 | verbose = TRUE,
19 | pid = get_test_pid(),
20 | fid = fid,
21 | url = get_test_url(),
22 | un = get_test_un(),
23 | pw = get_test_pw(),
24 | pp = get_test_pp()
25 | )
26 |
27 | fs <- form_schema(
28 | url = get_test_url(),
29 | un = get_test_un(),
30 | pw = get_test_pw(),
31 | pid = get_test_pid(),
32 | fid = fid,
33 | odkc_version = get_test_odkc_version()
34 | )
35 |
36 | # Comb through the litterbox
37 | f <- unzip(se, exdir = t)
38 |
39 | # Find the payload
40 | testthat::expect_true(fid_csv %in% fs::dir_ls(t))
41 | testthat::expect_true(fs::file_exists(fid_csv))
42 |
43 | suppressWarnings(
44 | data_quadrat_csv <- fid_csv %>%
45 | readr::read_csv(na = c("", "NA", "na")) %>%
46 | janitor::clean_names(.) %>%
47 | handle_ru_datetimes(fs) %>%
48 | # handle_ru_geopoints(fs) %>% # no geopoints
49 | attachment_link(fs)
50 | )
51 |
52 | # Test that filepath of attachment exists
53 | for (i in seq_len(nrow(data_quadrat_csv))) {
54 | testthat::expect_true(
55 | fs::path(t, data_quadrat_csv[i, ]$location_quadrat_photo) %>%
56 | fs::file_exists()
57 | )
58 | }
59 | })
60 |
--------------------------------------------------------------------------------
/R/odata_metadata_get.R:
--------------------------------------------------------------------------------
1 | #' Retrieve metadata from an OData URL ending in .svc as list of lists.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @template param-pid
6 | #' @template param-fid
7 | #' @template param-url
8 | #' @template param-auth
9 | #' @template param-retries
10 | #' @return A nested list containing Edmx (dataset schema definition) and
11 | #' .attrs (Version).
12 | # nolint start
13 | #' @seealso \url{https://docs.getodk.org/central-api-odata-endpoints/#metadata-document}
14 | # nolint end
15 | #' @family odata-api
16 | #' @export
17 | #' @examples
18 | #' \dontrun{
19 | #' # See vignette("setup") for setup and authentication options
20 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
21 | #'
22 | #' meta <- odata_metadata_get()
23 | #' listviewer::jsonedit(meta)
24 | #' }
25 | odata_metadata_get <- function(pid = get_default_pid(),
26 | fid = get_default_fid(),
27 | url = get_default_url(),
28 | un = get_default_un(),
29 | pw = get_default_pw(),
30 | retries = get_retries()) {
31 | yell_if_missing(url, un, pw)
32 | httr::RETRY(
33 | "GET",
34 | httr::modify_url(
35 | url,
36 | path = glue::glue(
37 | "v1/projects/{pid}/forms/",
38 | "{URLencode(fid, reserved = TRUE)}.svc/$metadata"
39 | )
40 | ),
41 | httr::add_headers(Accept = "application/xml"),
42 | httr::authenticate(un, pw),
43 | times = retries
44 | ) %>%
45 | yell_if_error(., url, un, pw) %>%
46 | httr::content(.) %>%
47 | xml2::as_list(.)
48 | }
49 |
50 | # usethis::use_test("odata_metadata_get") # nolint
51 |
--------------------------------------------------------------------------------
/man/geo_gj.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_gj}
6 | \alias{geo_gj}
7 | \title{The parsed submissions of a form containing geofields in GeoJSON.}
8 | \format{
9 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 1 rows and 59 columns.
10 | }
11 | \source{
12 | \code{\link{odata_submission_get}(wkt=FALSE, parse=TRUE)}
13 | run on the test form
14 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
15 | }
16 | \usage{
17 | geo_gj
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \seealso{
23 | Other included:
24 | \code{\link{fq_attachments}},
25 | \code{\link{fq_data}},
26 | \code{\link{fq_data_strata}},
27 | \code{\link{fq_data_taxa}},
28 | \code{\link{fq_form_detail}},
29 | \code{\link{fq_form_list}},
30 | \code{\link{fq_form_schema}},
31 | \code{\link{fq_form_xml}},
32 | \code{\link{fq_meta}},
33 | \code{\link{fq_project_detail}},
34 | \code{\link{fq_project_list}},
35 | \code{\link{fq_raw}},
36 | \code{\link{fq_raw_strata}},
37 | \code{\link{fq_raw_taxa}},
38 | \code{\link{fq_submission_list}},
39 | \code{\link{fq_submissions}},
40 | \code{\link{fq_svc}},
41 | \code{\link{fq_zip_data}},
42 | \code{\link{fq_zip_strata}},
43 | \code{\link{fq_zip_taxa}},
44 | \code{\link{fs_v7}},
45 | \code{\link{fs_v7_raw}},
46 | \code{\link{geo_fs}},
47 | \code{\link{geo_gj88}},
48 | \code{\link{geo_gj_raw}},
49 | \code{\link{geo_wkt}},
50 | \code{\link{geo_wkt88}},
51 | \code{\link{geo_wkt_raw}}
52 | }
53 | \concept{included}
54 | \keyword{datasets}
55 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: ruODK is doing something wrong
4 | title: ''
5 | labels: bug
6 | assignees: florianm
7 |
8 | ---
9 |
10 | ## Problem
11 |
14 | ## ruODK function(s) used
15 |
18 |
19 | ## Unexpected behaviour
20 |
25 |
26 | ## Reproducible example
27 |
42 |
43 | ```{r}
44 | # insert reprex here
45 | ```
46 |
47 |
48 | Session Info
49 |
50 |
53 | ODK Central version:
54 |
55 |
58 | ```{r}
59 | # utils::sessionInfo()
60 | ```
61 |
62 |
--------------------------------------------------------------------------------
/man/prepend_uuid.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/attachment_get.R
3 | \name{prepend_uuid}
4 | \alias{prepend_uuid}
5 | \title{Prepend a leading "uuid:" to any string, e.g. an md5 hash.}
6 | \usage{
7 | prepend_uuid(md5hash)
8 | }
9 | \arguments{
10 | \item{md5hash}{A string, e.g. an md5 hash.}
11 | }
12 | \value{
13 | The string with a prepended "uuid:"
14 | }
15 | \description{
16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
17 | }
18 | \details{
19 | This is the inverse of the helper function \code{\link{strip_uuid}}.
20 | }
21 | \examples{
22 | \dontrun{
23 | prepend_uuid("1234")
24 | prepend_uuid("d3bcefea-32a8-4dbc-80ca-4ecb0678e2b0")
25 | }
26 | }
27 | \seealso{
28 | Other utilities:
29 | \code{\link{attachment_get}()},
30 | \code{\link{attachment_link}()},
31 | \code{\link{attachment_url}()},
32 | \code{\link{drop_null_coords}()},
33 | \code{\link{form_schema_parse}()},
34 | \code{\link{get_one_attachment}()},
35 | \code{\link{get_one_submission}()},
36 | \code{\link{get_one_submission_att_list}()},
37 | \code{\link{get_one_submission_audit}()},
38 | \code{\link{handle_ru_attachments}()},
39 | \code{\link{handle_ru_datetimes}()},
40 | \code{\link{handle_ru_geopoints}()},
41 | \code{\link{handle_ru_geoshapes}()},
42 | \code{\link{handle_ru_geotraces}()},
43 | \code{\link{isodt_to_local}()},
44 | \code{\link{odata_submission_rectangle}()},
45 | \code{\link{predict_ruodk_name}()},
46 | \code{\link{split_geopoint}()},
47 | \code{\link{split_geoshape}()},
48 | \code{\link{split_geotrace}()},
49 | \code{\link{strip_uuid}()},
50 | \code{\link{tidyeval}},
51 | \code{\link{unnest_all}()}
52 | }
53 | \concept{utilities}
54 | \keyword{internal}
55 |
--------------------------------------------------------------------------------
/man/strip_uuid.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/attachment_get.R
3 | \name{strip_uuid}
4 | \alias{strip_uuid}
5 | \title{Strip the leading "uuid:" from a UUID hash.}
6 | \usage{
7 | strip_uuid(uuid)
8 | }
9 | \arguments{
10 | \item{uuid}{A string which may contain any number of "uuid:"}
11 | }
12 | \value{
13 | The string with every occurrence of "uuid:" deleted.
14 | }
15 | \description{
16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
17 | }
18 | \details{
19 | This is a helper function used by \code{\link{attachment_get}}.
20 | }
21 | \examples{
22 | \dontrun{
23 | strip_uuid("uuid:1234")
24 | strip_uuid("uuid:d3bcefea-32a8-4dbc-80ca-4ecb0678e2b0")
25 | }
26 | }
27 | \seealso{
28 | Other utilities:
29 | \code{\link{attachment_get}()},
30 | \code{\link{attachment_link}()},
31 | \code{\link{attachment_url}()},
32 | \code{\link{drop_null_coords}()},
33 | \code{\link{form_schema_parse}()},
34 | \code{\link{get_one_attachment}()},
35 | \code{\link{get_one_submission}()},
36 | \code{\link{get_one_submission_att_list}()},
37 | \code{\link{get_one_submission_audit}()},
38 | \code{\link{handle_ru_attachments}()},
39 | \code{\link{handle_ru_datetimes}()},
40 | \code{\link{handle_ru_geopoints}()},
41 | \code{\link{handle_ru_geoshapes}()},
42 | \code{\link{handle_ru_geotraces}()},
43 | \code{\link{isodt_to_local}()},
44 | \code{\link{odata_submission_rectangle}()},
45 | \code{\link{predict_ruodk_name}()},
46 | \code{\link{prepend_uuid}()},
47 | \code{\link{split_geopoint}()},
48 | \code{\link{split_geoshape}()},
49 | \code{\link{split_geotrace}()},
50 | \code{\link{tidyeval}},
51 | \code{\link{unnest_all}()}
52 | }
53 | \concept{utilities}
54 | \keyword{internal}
55 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "R (rocker/r-ver base)",
3 | "dockerFile": "Dockerfile",
4 | "features": {
5 | "ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": {
6 | "version": "prerelease"
7 | },
8 | "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
9 | "packages": "libudunits2-dev,libxtst6,libxt6,libmagick++-dev"
10 | },
11 | "ghcr.io/rocker-org/devcontainer-features/r-packages:1": {
12 | "packages": "github::rstudio/renv,tidyverse,git2r,knitr,spelling,languageserver,precommit,clisymbols,crayon,dplyr,fs,glue,httr,httr2,janitor,lifecycle,lubridate,magrittr,purrr,readr,rlang,stringr,semver,tibble,tidyr,xml2,covr,DT,ggplot2,here,knitr,lattice,leaflet,listviewer,leafpop,leafem,mapview,rmarkdown,roxygen2,sf,terra,testthat,tmap,usethis"
13 | },
14 | "ghcr.io/devcontainers-contrib/features/pre-commit:2": {}
15 | },
16 | "mounts": [
17 | "source=${localEnv:HOME}${localEnv:USERPROFILE}/.gitconfig,target=~/.gitconfig,type=bind,consistency=cached"
18 | ],
19 | "onCreateCommand": "pre-commit install && pre-commit run",
20 | "customizations": {
21 | "vscode": {
22 | "extensions": [
23 | "mechatroner.rainbow-csv",
24 | "REditorSupport.r",
25 | "RDebugger.r-debugger",
26 | "ms-azuretools.vscode-docker",
27 | "usernamehw.errorlens",
28 | "christian-kohler.path-intellisense",
29 | "ms-vscode.live-server"
30 | ]
31 | },
32 | "codespaces": {
33 | "openFiles": [
34 | "DESCRIPTION",
35 | "NEWS.md",
36 | "data-raw/make_release.R"
37 | ]
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/inst/joss/paper.bib:
--------------------------------------------------------------------------------
1 | @Misc{ruodk,
2 | title = {ruODK: Client for the ODK Central API v0.9.0},
3 | author = {Florian W. Mayer},
4 | note = {R package version 0.9.0},
5 | year = {2019},
6 | url = {https://github.com/ropensci/ruODK},
7 | }
8 |
9 | @online{github,
10 | author = {GitHub},
11 | title = {GitHub.com},
12 | year = 2008,
13 | url = {https://github.com},
14 | urldate = {2024-03-08}
15 | }
16 |
17 | @online{odk,
18 | author = {OpenDataKit},
19 | title = {getodk.org},
20 | year = 2019,
21 | url = {https://getodk.org/},
22 | urldate = {2024-03-08}
23 | }
24 |
25 | @online{odkdocs,
26 | author = {OpenDataKit Documentation},
27 | title = {docs.getodk.org},
28 | year = 2019,
29 | url = {https://docs.getodk.org/},
30 | urldate = {2024-03-08}
31 | }
32 |
33 | @online{odkapi,
34 | author = {OpenDataKit API},
35 | title = {docs.getodk.org/central-api/},
36 | year = 2019,
37 | url = {https://docs.getodk.org/central-api/},
38 | urldate = {2024-03-08}
39 | }
40 |
41 | @inproceedings{hartung,
42 | author = {Hartung, Carl and Lerer, Adam and Anokwa, Yaw and Tseng, Clint and Brunette, Waylon and Borriello, Gaetano},
43 | title = {Open Data Kit: Tools to Build Information Services for Developing Regions},
44 | booktitle = {Proceedings of the 4th ACM/IEEE International Conference on Information and Communication Technologies and Development},
45 | series = {ICTD '10},
46 | year = {2010},
47 | isbn = {978-1-4503-0787-1},
48 | location = {London, United Kingdom},
49 | pages = {18:1--18:12},
50 | articleno = {18},
51 | numpages = {12},
52 | url = {http://doi.acm.org/10.1145/2369220.2369236},
53 | doi = {10.1145/2369220.2369236},
54 | acmid = {2369236},
55 | publisher = {ACM},
56 | address = {New York, NY, USA},
57 | keywords = {ICTD, client-server distributed systems, mobile computing, mobile phones},
58 | }
59 |
--------------------------------------------------------------------------------
/man/fq_meta.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_meta}
5 | \alias{fq_meta}
6 | \title{OData metadata document for an ODK Central form.}
7 | \format{
8 | A list of lists
9 | }
10 | \source{
11 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
12 | }
13 | \usage{
14 | fq_meta
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | The OData response for the metadata of an ODK Central form.
21 |
22 | This data is kept up to date with the data used in vignettes and package
23 | tests. The data is comprised of test records with nonsensical data.
24 | The forms used to capture this data are development versions of real-world
25 | forms.
26 | }
27 | \seealso{
28 | Other included:
29 | \code{\link{fq_attachments}},
30 | \code{\link{fq_data}},
31 | \code{\link{fq_data_strata}},
32 | \code{\link{fq_data_taxa}},
33 | \code{\link{fq_form_detail}},
34 | \code{\link{fq_form_list}},
35 | \code{\link{fq_form_schema}},
36 | \code{\link{fq_form_xml}},
37 | \code{\link{fq_project_detail}},
38 | \code{\link{fq_project_list}},
39 | \code{\link{fq_raw}},
40 | \code{\link{fq_raw_strata}},
41 | \code{\link{fq_raw_taxa}},
42 | \code{\link{fq_submission_list}},
43 | \code{\link{fq_submissions}},
44 | \code{\link{fq_svc}},
45 | \code{\link{fq_zip_data}},
46 | \code{\link{fq_zip_strata}},
47 | \code{\link{fq_zip_taxa}},
48 | \code{\link{fs_v7}},
49 | \code{\link{fs_v7_raw}},
50 | \code{\link{geo_fs}},
51 | \code{\link{geo_gj}},
52 | \code{\link{geo_gj88}},
53 | \code{\link{geo_gj_raw}},
54 | \code{\link{geo_wkt}},
55 | \code{\link{geo_wkt88}},
56 | \code{\link{geo_wkt_raw}}
57 | }
58 | \concept{included}
59 | \keyword{datasets}
60 |
--------------------------------------------------------------------------------
/tests/testthat/test-handle_ru_attachments.R:
--------------------------------------------------------------------------------
1 | test_that("handle_ru_attachments downloads files", {
2 | # This test downloads files
3 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
4 | message = "Test server not configured"
5 | )
6 |
7 | data("fq_raw")
8 | data("fq_form_schema")
9 |
10 | t <- tempdir()
11 | fs::dir_ls(t) %>% fs::file_delete()
12 |
13 | fq_with_att <- fq_raw %>%
14 | ruODK::odata_submission_rectangle() %>%
15 | ruODK::handle_ru_attachments(
16 | form_schema = fq_form_schema,
17 | local_dir = t,
18 | pid = ruODK::get_test_pid(),
19 | fid = ruODK::get_test_fid(),
20 | url = ruODK::get_test_url(),
21 | un = ruODK::get_test_un(),
22 | pw = ruODK::get_test_pw(),
23 | verbose = TRUE
24 | )
25 |
26 | # There should be files in local_dir
27 | testthat::expect_true(fs::dir_ls(t) %>% length() > 0)
28 | })
29 |
30 | test_that("handle_ru_attachments downloads files from subtables", {
31 | # This test downloads files
32 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
33 | message = "Test server not configured"
34 | )
35 |
36 | data("fq_raw")
37 | data("fq_raw_taxa")
38 | data("fq_form_schema")
39 |
40 | t <- tempdir()
41 | fs::dir_ls(t) %>% fs::file_delete()
42 |
43 | fq_with_att <- fq_raw_taxa %>%
44 | ruODK::odata_submission_rectangle() %>%
45 | ruODK::handle_ru_attachments(
46 | form_schema = fq_form_schema,
47 | local_dir = t,
48 | pid = ruODK::get_test_pid(),
49 | fid = ruODK::get_test_fid(),
50 | url = ruODK::get_test_url(),
51 | un = ruODK::get_test_un(),
52 | pw = ruODK::get_test_pw(),
53 | verbose = TRUE
54 | )
55 |
56 | # There should be files in local_dir
57 | testthat::expect_true(fs::dir_ls(t) %>% length() > 0)
58 | })
59 |
60 | # usethis::use_r("handle_ru_attachments") # nolint
61 |
--------------------------------------------------------------------------------
/inst/schemaorg.json:
--------------------------------------------------------------------------------
1 | {
2 | "@context": "https://schema.org",
3 | "type": "SoftwareSourceCode",
4 | "author": {
5 | "id": "https://orcid.org/0000-0003-4269-4242",
6 | "type": "Person",
7 | "email": "Florian.Mayer@dpc.wa.gov.au",
8 | "familyName": "Mayer",
9 | "givenName": [
10 | "Florian",
11 | "W."
12 | ]
13 | },
14 | "codeRepository": "https://github.com/ropensci/ruODK",
15 | "contributor": [
16 | {
17 | "id": "https://orcid.org/0000-0002-4573-0002",
18 | "type": "Person",
19 | "familyName": "Tyszler",
20 | "givenName": "Marcelo"
21 | },
22 | {
23 | "id": "https://orcid.org/0000-0002-6758-2397",
24 | "type": "Person",
25 | "familyName": "Langet",
26 | "givenName": "Hélène"
27 | }
28 | ],
29 | "copyrightHolder": {
30 | "type": "Organization",
31 | "name": "DBCA"
32 | },
33 | "description": "Access and tidy up data from the 'ODK Central' API. 'ODK Central' is a clearinghouse for digitally captured data using ODK . It manages user accounts and permissions, stores form definitions, and allows data collection clients like 'ODK Collect' to connect to it for form download and submission upload. The 'ODK Central' API is documented at .",
34 | "funder": [
35 | {
36 | "type": "Organization",
37 | "name": "DBCA"
38 | },
39 | {
40 | "type": "Organization",
41 | "name": "NWSFTCP"
42 | }
43 | ],
44 | "license": "https://spdx.org/licenses/GPL-3.0",
45 | "name": "ruODK: An R Client for the ODK Central API",
46 | "programmingLanguage": {
47 | "type": "ComputerLanguage",
48 | "name": "R",
49 | "url": "https://r-project.org"
50 | },
51 | "runtimePlatform": "R version 4.4.1 (2024-06-14 ucrt)",
52 | "version": "1.5.0"
53 | }
54 |
--------------------------------------------------------------------------------
/R/odata_service_get.R:
--------------------------------------------------------------------------------
1 | #' Retrieve service metadata from an OData URL ending in .svc as tibble.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @template param-pid
6 | #' @template param-fid
7 | #' @template param-url
8 | #' @template param-auth
9 | #' @template param-retries
10 | #' @return A tibble with one row per submission data endpoint.
11 | #' Columns: name, kind, url.
12 | # nolint start
13 | #' @seealso \url{https://docs.getodk.org/central-api-odata-endpoints/#service-document}
14 | # nolint end
15 | #' @family odata-api
16 | #' @export
17 | #' @examples
18 | #' \dontrun{
19 | #' # See vignette("setup") for setup and authentication options
20 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
21 | #'
22 | #' svc <- odata_service_get()
23 | #' svc
24 | #' }
25 | odata_service_get <- function(pid = get_default_pid(),
26 | fid = get_default_fid(),
27 | url = get_default_url(),
28 | un = get_default_un(),
29 | pw = get_default_pw(),
30 | retries = get_retries()) {
31 | yell_if_missing(url, un, pw)
32 | httr::RETRY(
33 | "GET",
34 | httr::modify_url(
35 | url,
36 | path = glue::glue(
37 | "v1/projects/{pid}/forms/{URLencode(fid, reserved = TRUE)}.svc"
38 | )
39 | ),
40 | httr::add_headers(Accept = "application/json"),
41 | httr::authenticate(un, pw),
42 | times = retries
43 | ) %>%
44 | yell_if_error(., url, un, pw) %>%
45 | httr::content(.) %>%
46 | magrittr::extract2("value") %>%
47 | { # nolint
48 | tibble::tibble(
49 | name = purrr::map_chr(., "name"),
50 | kind = purrr::map_chr(., "kind"),
51 | url = purrr::map_chr(., "url")
52 | )
53 | }
54 | }
55 |
56 | # usethis::use_test("odata_service_get") # nolint
57 |
--------------------------------------------------------------------------------
/man/fq_svc.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_svc}
5 | \alias{fq_svc}
6 | \title{OData service document for an ODK Central form.}
7 | \format{
8 | A tibble with one row per submission data endpoint.
9 | }
10 | \source{
11 | OData service document for
12 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
13 | }
14 | \usage{
15 | fq_svc
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
19 | }
20 | \details{
21 | The OData response for the metadata of an ODK Central form.
22 |
23 | This data is kept up to date with the data used in vignettes and package
24 | tests. The data is comprised of test records with nonsensical data.
25 | The forms used to capture this data are development versions of real-world
26 | forms.
27 | }
28 | \seealso{
29 | Other included:
30 | \code{\link{fq_attachments}},
31 | \code{\link{fq_data}},
32 | \code{\link{fq_data_strata}},
33 | \code{\link{fq_data_taxa}},
34 | \code{\link{fq_form_detail}},
35 | \code{\link{fq_form_list}},
36 | \code{\link{fq_form_schema}},
37 | \code{\link{fq_form_xml}},
38 | \code{\link{fq_meta}},
39 | \code{\link{fq_project_detail}},
40 | \code{\link{fq_project_list}},
41 | \code{\link{fq_raw}},
42 | \code{\link{fq_raw_strata}},
43 | \code{\link{fq_raw_taxa}},
44 | \code{\link{fq_submission_list}},
45 | \code{\link{fq_submissions}},
46 | \code{\link{fq_zip_data}},
47 | \code{\link{fq_zip_strata}},
48 | \code{\link{fq_zip_taxa}},
49 | \code{\link{fs_v7}},
50 | \code{\link{fs_v7_raw}},
51 | \code{\link{geo_fs}},
52 | \code{\link{geo_gj}},
53 | \code{\link{geo_gj88}},
54 | \code{\link{geo_gj_raw}},
55 | \code{\link{geo_wkt}},
56 | \code{\link{geo_wkt88}},
57 | \code{\link{geo_wkt_raw}}
58 | }
59 | \concept{included}
60 | \keyword{datasets}
61 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | ## Test environments
2 | * Local machine
3 | * Running under: Ubuntu 20.04.2 LTS
4 | * Platform: x86_64-pc-linux-gnu (64-bit)
5 | * R version 4.0.4 (2021-02-15)
6 | * AppVeyor CI
7 | * Running under: Windows Server 2012 R2 x64 (build 9600)
8 | * Platform: x86_64-w64-mingw32/x64 (64-bit)
9 | * R version 4.0.3 Patched (2020-11-08 r79411)
10 | * GitHub Actions: R devel, release, oldrel for each of
11 | * Windows-latest (Windows Server 2019)
12 | * Windows Server 2016
13 | * MacOS-lastest (MacOS X Catalina 10.05)
14 | * Ubuntu 20.04
15 | * Ubuntu 18.04
16 |
17 | ## R CMD check results
18 |
19 | 0 errors | 0 warnings | 1 note
20 |
21 | * This is a new release.
22 |
23 | Resolved NOTE comments:
24 | * Possibly invalid URLs:
25 | * The package comparison section in the README contains Markdown badges with
26 | CRAN links to packages that are not yet or not any more on CRAN. These
27 | links are correct, and while they currently do not resolve, they will do so
28 | once the packages are (re-)submitted to CRAN. Currently removed.
29 | * The README contains an ODK Central form OData service URL to illustrate
30 | setting up ruODK. The URL redirects to a login screen if followed directly.
31 | This is expected behaviour. Currently not appearing as warning.
32 | * The PDF version of the manual is now included.
33 | * The example data contains UTF-8 strings. This is a realistic scenario.
34 | The note has disappeared after the R version 4 release.
35 | * Test coverage: All functionality supporting the current ODK Central release is
36 | covered by tests.
37 | The only exception is `form_schema{_parse}`, which supports a breaking
38 | change between ODK Central 0.7 and 0.8. The test server runs ODK Central 0.8,
39 | a production server (used by the package author, but not accessible to other
40 | maintainers) runs 0.7 successfully. The tests for v 0.7 use packaged data.
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-submission_list.R:
--------------------------------------------------------------------------------
1 | test_that("submission_list works", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 |
6 | sl <- submission_list(
7 | get_test_pid(),
8 | get_test_fid(),
9 | url = get_test_url(),
10 | un = get_test_un(),
11 | pw = get_test_pw()
12 | )
13 |
14 | fl <- form_list(
15 | get_test_pid(),
16 | url = get_test_url(),
17 | un = get_test_un(),
18 | pw = get_test_pw()
19 | )
20 | # submission_list returns a tibble
21 | testthat::expect_equal(class(sl), c("tbl_df", "tbl", "data.frame"))
22 |
23 | # https://github.com/ropensci/ruODK/issues/138
24 | # review_state was incorrectly picked up by mutate_at looking for "_at" dates
25 | testthat::expect_equal(class(sl$review_state), "character")
26 |
27 | # Submission attributes are the tibble's columns
28 | cn <- c(
29 | "instance_id",
30 | "submitter_id",
31 | "device_id",
32 | "created_at",
33 | "updated_at",
34 | "review_state",
35 | "user_agent",
36 | "deleted_at",
37 | "submitter_id_2",
38 | "submitter_type",
39 | "submitter_display_name",
40 | "submitter_created_at",
41 | "submitter_updated_at",
42 | "submitter_deleted_at",
43 | "current_version"
44 | )
45 | testthat::expect_equal(names(sl), cn)
46 | # testthat::expect_equal(class(sl$review_state), "logical")
47 | purrr::map(
48 | cn,
49 | ~ testthat::expect_true(
50 | . %in% names(sl),
51 | label = glue::glue("Column {.} in submission_list")
52 | )
53 | )
54 |
55 | # Number of submissions (rows) is same as advertised in form_list
56 | form_list_nsub <- fl %>%
57 | dplyr::filter(fid == get_test_fid()) %>%
58 | magrittr::extract2("submissions") %>%
59 | as.numeric()
60 | testthat::expect_equal(nrow(sl), form_list_nsub)
61 | })
62 |
63 | # usethis::use_r("submission_list") # nolint
64 |
--------------------------------------------------------------------------------
/man/predict_ruodk_name.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/form_schema_parse.R
3 | \name{predict_ruodk_name}
4 | \alias{predict_ruodk_name}
5 | \title{Predict a field name after \code{tidyr::unnest_wider(names_sep="_")} prefixes
6 | the form path.}
7 | \usage{
8 | predict_ruodk_name(name_str, path_str)
9 | }
10 | \arguments{
11 | \item{name_str}{An Xforms field name string.}
12 |
13 | \item{path_str}{A path string,
14 | e.g. "Submissions" or "Submissions.group_name".}
15 | }
16 | \value{
17 | The name as built by \code{tidyr::unnest_wider(names_sep="_")}.
18 | }
19 | \description{
20 | Predict a field name after \code{tidyr::unnest_wider(names_sep="_")} prefixes
21 | the form path.
22 | }
23 | \examples{
24 | \dontrun{
25 | predict_ruodk_name("bar", "Submissions.foo")
26 | # > "foo_bar"
27 | predict_ruodk_name("bar", "Submissions")
28 | # > "bar"
29 | predict_ruodk_name("rock", "Submissions.foo_fighters")
30 | # > "foo_fighters_rock"
31 | }
32 | }
33 | \seealso{
34 | Other utilities:
35 | \code{\link{attachment_get}()},
36 | \code{\link{attachment_link}()},
37 | \code{\link{attachment_url}()},
38 | \code{\link{drop_null_coords}()},
39 | \code{\link{form_schema_parse}()},
40 | \code{\link{get_one_attachment}()},
41 | \code{\link{get_one_submission}()},
42 | \code{\link{get_one_submission_att_list}()},
43 | \code{\link{get_one_submission_audit}()},
44 | \code{\link{handle_ru_attachments}()},
45 | \code{\link{handle_ru_datetimes}()},
46 | \code{\link{handle_ru_geopoints}()},
47 | \code{\link{handle_ru_geoshapes}()},
48 | \code{\link{handle_ru_geotraces}()},
49 | \code{\link{isodt_to_local}()},
50 | \code{\link{odata_submission_rectangle}()},
51 | \code{\link{prepend_uuid}()},
52 | \code{\link{split_geopoint}()},
53 | \code{\link{split_geoshape}()},
54 | \code{\link{split_geotrace}()},
55 | \code{\link{strip_uuid}()},
56 | \code{\link{tidyeval}},
57 | \code{\link{unnest_all}()}
58 | }
59 | \concept{utilities}
60 | \keyword{internal}
61 |
--------------------------------------------------------------------------------
/tests/testthat/test-entitylist_detail.R:
--------------------------------------------------------------------------------
1 | test_that("entitylist_detail works", {
2 | ru_setup(
3 | pid = get_test_pid(),
4 | url = get_test_url(),
5 | un = get_test_un(),
6 | pw = get_test_pw(),
7 | odkc_version = get_test_odkc_version()
8 | )
9 |
10 | ds <- entitylist_list()
11 | did <- ds$name[1]
12 |
13 | ds1 <- entitylist_detail(did = did)
14 |
15 | # entitylist_detail returns a list
16 | testthat::expect_is(ds1, "list")
17 |
18 | # linked_forms contain form xmlFormId and name
19 | lf <- ds1$linked_forms |>
20 | purrr::list_transpose() |>
21 | tibble::as_tibble()
22 | testthat::expect_equal(names(lf), c("xmlFormId", "name"))
23 |
24 | # source_forms contain form xmlFormId and name
25 | sf <- ds1$source_forms |>
26 | purrr::list_transpose() |>
27 | tibble::as_tibble()
28 | testthat::expect_equal(names(sf), c("xmlFormId", "name"))
29 |
30 | # properties lists attributes of entities
31 | pr <- ds1$properties |>
32 | purrr::list_transpose() |>
33 | tibble::as_tibble()
34 | testthat::expect_equal(
35 | names(pr),
36 | c("name", "publishedAt", "odataName", "forms")
37 | )
38 | })
39 |
40 | test_that("entitylist_detail errors if did is missing", {
41 | testthat::expect_error(
42 | entitylist_detail()
43 | )
44 | })
45 |
46 | test_that("entitylist_detail warns if odkc_version too low", {
47 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
48 | message = "Test server not configured"
49 | )
50 |
51 | ru_setup(
52 | pid = get_test_pid(),
53 | url = get_test_url(),
54 | un = get_test_un(),
55 | pw = get_test_pw(),
56 | odkc_version = get_test_odkc_version()
57 | )
58 |
59 | ds <- entitylist_list()
60 | did <- ds$name[1]
61 |
62 | ds1 <- entitylist_detail(did = did)
63 |
64 | testthat::expect_warning(
65 | ds1 <- entitylist_detail(did = did, odkc_version = "1.5.3")
66 | )
67 | })
68 |
69 |
70 | # usethis::use_r("entitylist_detail") # nolint
71 |
--------------------------------------------------------------------------------
/R/form_xml.R:
--------------------------------------------------------------------------------
1 | #' Show the XML representation of one form as list.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @param parse Whether to parse the XML into a nested list, default: TRUE
6 | #' @template param-pid
7 | #' @template param-fid
8 | #' @template param-url
9 | #' @template param-auth
10 | #' @template param-retries
11 | #' @return The form XML as a nested list.
12 | # nolint start
13 | #' @seealso \url{https://docs.getodk.org/central-api-form-management/#retrieving-form-xml}
14 | # nolint end
15 | #' @family form-management
16 | #' @export
17 | #' @examples
18 | #' \dontrun{
19 | #' # See vignette("setup") for setup and authentication options
20 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
21 | #'
22 | #' # With explicit pid and fid
23 | #' fxml_defaults <- form_xml(1, "build_xformsId")
24 | #'
25 | #' # With defaults
26 | #' fxml <- form_xml()
27 | #' listviewer::jsonedit(fxml)
28 | #'
29 | #' # form_xml returns a nested list
30 | #' class(fxml)
31 | #' # > "list"
32 | #' }
33 | form_xml <- function(parse = TRUE,
34 | pid = get_default_pid(),
35 | fid = get_default_fid(),
36 | url = get_default_url(),
37 | un = get_default_un(),
38 | pw = get_default_pw(),
39 | retries = get_retries()) {
40 | yell_if_missing(url, un, pw, pid = pid, fid = fid)
41 | out <- httr::RETRY(
42 | "GET",
43 | httr::modify_url(
44 | url,
45 | path = glue::glue(
46 | "v1/projects/{pid}/forms/{URLencode(fid, reserved = TRUE)}.xml"
47 | )
48 | ),
49 | httr::add_headers("Accept" = "application/xml"),
50 | httr::authenticate(un, pw),
51 | times = retries
52 | ) %>%
53 | yell_if_error(., url, un, pw) %>%
54 | httr::content(.)
55 |
56 | if (parse == FALSE) {
57 | return(out)
58 | }
59 | out %>% xml2::as_list(.)
60 | }
61 |
62 | # usethis::use_test("form_xml") # nolint
63 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | exclude: "/migrations/|^venv/|/email/subject/"
2 | default_stages: [pre-commit]
3 |
4 | repos:
5 | - repo: https://github.com/pre-commit/pre-commit-hooks
6 | rev: v5.0.0
7 | hooks:
8 | - id: trailing-whitespace
9 | name: Drop trailing whitespace
10 | exclude: man
11 | - id: end-of-file-fixer
12 | name: Fix end of files
13 | - id: check-yaml
14 | name: Check YAML syntax
15 | - id: check-toml
16 | name: Check TOML syntax
17 | # - id: pretty-format-json
18 | # name: Format JSON
19 | - id: check-added-large-files
20 | name: Prevent adding large files
21 | args: ['--maxkb=1024']
22 | - id: check-merge-conflict
23 | name: Check for unhandled merge conflicts
24 | - id: debug-statements
25 | name: Check for debug statements
26 | - id: detect-private-key
27 | name: Detect private keys
28 |
29 | # https://lorenzwalthert.github.io/precommit/articles/available-hooks.html
30 | - repo: https://github.com/lorenzwalthert/precommit
31 | rev: v0.4.3.9003
32 | hooks:
33 | - id: style-files
34 | name: Style code to tidyverse conventions
35 | args: [--scope=spaces]
36 | - id: readme-rmd-rendered
37 | name: Ensure README.md is up to date
38 | - id: no-debug-statement
39 | name: Ensure that no debug() statement is committed
40 | - id: no-browser-statement
41 | name: Ensure that no browser() statement is committed
42 | # - id: spell-check
43 | # name: Spellcheck
44 | # - id: deps-in-desc
45 | # name: Ensure that DESCRIPTION lists all dependencies
46 | # args: [--allow_private_imports, --root=R]
47 | - id: use-tidy-description
48 | name: Format DESCRIPTION
49 | # - id: pkgdown
50 | # name: Validate pkgdown.yml
51 | # - id: lintr
52 | # name: Lint code but emit only warnings
53 | # args: [--warn_only]
54 | # verbose: true
55 |
--------------------------------------------------------------------------------
/man/geo_wkt88.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_wkt88}
6 | \alias{geo_wkt88}
7 | \title{The parsed submissions of a form containing geofields in WKT
8 | with trailing empty coordinates present.}
9 | \format{
10 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 1 rows and 48 columns.
11 | }
12 | \source{
13 | \code{\link{odata_submission_get}(wkt=TRUE, parse=TRUE)}
14 | run on the test form
15 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
16 | }
17 | \usage{
18 | geo_wkt88
19 | }
20 | \description{
21 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
22 | }
23 | \details{
24 | This issue was fixed in #88.
25 | ODK Central versions 0.7 - 0.9 export geotraces and geoshapes with trailing
26 | empty coordinates. ruODK has a patch to drop trailing empty coordinates.
27 | This dataset is used to test the patch in ruODK.
28 | }
29 | \seealso{
30 | Other included:
31 | \code{\link{fq_attachments}},
32 | \code{\link{fq_data}},
33 | \code{\link{fq_data_strata}},
34 | \code{\link{fq_data_taxa}},
35 | \code{\link{fq_form_detail}},
36 | \code{\link{fq_form_list}},
37 | \code{\link{fq_form_schema}},
38 | \code{\link{fq_form_xml}},
39 | \code{\link{fq_meta}},
40 | \code{\link{fq_project_detail}},
41 | \code{\link{fq_project_list}},
42 | \code{\link{fq_raw}},
43 | \code{\link{fq_raw_strata}},
44 | \code{\link{fq_raw_taxa}},
45 | \code{\link{fq_submission_list}},
46 | \code{\link{fq_submissions}},
47 | \code{\link{fq_svc}},
48 | \code{\link{fq_zip_data}},
49 | \code{\link{fq_zip_strata}},
50 | \code{\link{fq_zip_taxa}},
51 | \code{\link{fs_v7}},
52 | \code{\link{fs_v7_raw}},
53 | \code{\link{geo_fs}},
54 | \code{\link{geo_gj}},
55 | \code{\link{geo_gj88}},
56 | \code{\link{geo_gj_raw}},
57 | \code{\link{geo_wkt}},
58 | \code{\link{geo_wkt_raw}}
59 | }
60 | \concept{included}
61 | \keyword{datasets}
62 |
--------------------------------------------------------------------------------
/man/geo_gj88.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \encoding{UTF-8}
5 | \name{geo_gj88}
6 | \alias{geo_gj88}
7 | \title{The parsed submissions of a form containing geofields in GeoJSON
8 | with trailing empty coordinates present.}
9 | \format{
10 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 1 rows and 51 columns.
11 | }
12 | \source{
13 | \code{\link{odata_submission_get}(wkt=FALSE, parse=TRUE)}
14 | run on the test form
15 | \code{system.file("extdata", "Locations.xml", package = "ruODK")}.
16 | }
17 | \usage{
18 | geo_gj88
19 | }
20 | \description{
21 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
22 | }
23 | \details{
24 | This issue was fixed in #88.
25 | ODK Central versions 0.7 - 0.9 export geotraces and geoshapes with trailing
26 | empty coordinates. ruODK has a patch to drop trailing empty coordinates.
27 | This dataset is used to test the patch in ruODK.
28 | }
29 | \seealso{
30 | Other included:
31 | \code{\link{fq_attachments}},
32 | \code{\link{fq_data}},
33 | \code{\link{fq_data_strata}},
34 | \code{\link{fq_data_taxa}},
35 | \code{\link{fq_form_detail}},
36 | \code{\link{fq_form_list}},
37 | \code{\link{fq_form_schema}},
38 | \code{\link{fq_form_xml}},
39 | \code{\link{fq_meta}},
40 | \code{\link{fq_project_detail}},
41 | \code{\link{fq_project_list}},
42 | \code{\link{fq_raw}},
43 | \code{\link{fq_raw_strata}},
44 | \code{\link{fq_raw_taxa}},
45 | \code{\link{fq_submission_list}},
46 | \code{\link{fq_submissions}},
47 | \code{\link{fq_svc}},
48 | \code{\link{fq_zip_data}},
49 | \code{\link{fq_zip_strata}},
50 | \code{\link{fq_zip_taxa}},
51 | \code{\link{fs_v7}},
52 | \code{\link{fs_v7_raw}},
53 | \code{\link{geo_fs}},
54 | \code{\link{geo_gj}},
55 | \code{\link{geo_gj_raw}},
56 | \code{\link{geo_wkt}},
57 | \code{\link{geo_wkt88}},
58 | \code{\link{geo_wkt_raw}}
59 | }
60 | \concept{included}
61 | \keyword{datasets}
62 |
--------------------------------------------------------------------------------
/R/project_create.R:
--------------------------------------------------------------------------------
1 | #' Create a new project.
2 | #'
3 | #' `r lifecycle::badge('experimental')`
4 | #'
5 | #' @param name The desired name of the project. Can contain whitespace.
6 | #' @template param-url
7 | #' @template param-auth
8 | #' @return A tibble with one row per project and all project metadata
9 | #' as columns as per ODK Central API docs.
10 | # nolint start
11 | #' @seealso \url{https://docs.getodk.org/central-api-project-management/#creating-a-project}
12 | # nolint end
13 | #' @family project-management
14 | #' @export
15 | #' @examples
16 | #' \dontrun{
17 | #' # See vignette("setup") for setup and authentication options
18 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
19 | #'
20 | #' p <- project_create("Test Project")
21 | #' knitr::kable(p)
22 | #'
23 | #' # project_create returns a tibble
24 | #' class(p)
25 | #' # > "tbl_df" "tbl" "data.frame"
26 | #'
27 | #' # columns are project metadata
28 | #' names(p)
29 | #' # > "id" "name" "archived"
30 | #' }
31 | project_create <- function(name,
32 | url = get_default_url(),
33 | un = get_default_un(),
34 | pw = get_default_pw()) {
35 | ru_msg_warn("Not implemented.")
36 |
37 | # nolint start
38 | # has_internet()
39 | # glue::glue("{url}/v1/projects/") %>%
40 | # httr::POST(
41 | # config = list(
42 | # httr::add_headers("Content-Type" = "application/json"),
43 | # httr::authenticate(un, pw)
44 | # ),
45 | # body = jsonlite::toJSON(list(name = "x"), auto_unbox = T),
46 | # encode = "json"
47 | # ) %>%
48 | # httr::stop_for_status(
49 | # task = glue::glue("create a project with name {name}")
50 | # ) %>%
51 | # httr::content(.) %>%
52 | # {
53 | # tibble::tibble(
54 | # id = purrr::map_int(., "id"),
55 | # name = purrr::map_chr(., "name"),
56 | # archived = ifelse(is.null(.$archived), FALSE, TRUE)
57 | # )
58 | # }
59 | # nolint end
60 | }
61 |
62 | # usethis::use_test("project_create") # nolint
63 |
--------------------------------------------------------------------------------
/R/handle_ru_datetimes.R:
--------------------------------------------------------------------------------
1 | #' Parse datetimes of submission data according to a form schema.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @details For a given tibble of submissions, parse all columns which are
6 | #' marked in the form schema as type "date" or "dateTime" using a set of
7 | #' lubridate orders and a given timezone.
8 | #' @param data Submissions rectangled into a tibble. E.g. the output of
9 | #' ```
10 | #' ruODK::odata_submission_get(parse = FALSE) %>%
11 | #' ruODK::odata_submission_rectangle()
12 | #' ```
13 | #' @param form_schema The `form_schema` for the submissions.
14 | #' E.g. the output of `ruODK::form_schema()`.
15 | #' @template param-orders
16 | #' @template param-tz
17 | #' @template param-verbose
18 | #' @return The submissions tibble with all date/dateTime columns mutated as
19 | #' lubridate datetimes.
20 | #' @export
21 | #' @family utilities
22 | #' @examples
23 | #' \dontrun{
24 | #' library(magrittr)
25 | #' data("fq_raw")
26 | #' data("fq_form_schema")
27 | #'
28 | #' fq_with_dates <- fq_raw %>%
29 | #' ruODK::odata_submission_rectangle() %>%
30 | #' ruODK::handle_ru_datetimes(form_schema = fq_form_schema)
31 | #'
32 | #' dplyr::glimpse(fq_with_dates)
33 | #' }
34 | handle_ru_datetimes <- function(data,
35 | form_schema,
36 | orders = get_default_orders(),
37 | tz = get_default_tz(),
38 | verbose = get_ru_verbose()) {
39 | # Find all date/time columns in form_schema
40 | dttm_cols <- form_schema %>%
41 | dplyr::filter(type %in% c("dateTime", "date")) %>%
42 | magrittr::extract2("ruodk_name") %>%
43 | intersect(names(data))
44 |
45 | x <- paste(dttm_cols, collapse = ", ") # nolint
46 | "Found date/times: {x}." %>%
47 | glue::glue() %>%
48 | ru_msg_info(verbose = verbose)
49 |
50 | data %>%
51 | dplyr::mutate_at(
52 | dplyr::vars(dplyr::all_of(dttm_cols)),
53 | ~ isodt_to_local(., orders = orders, tz = tz)
54 | )
55 | }
56 |
57 | # usethis::use_test("handle_ru_datetimes") # nolint
58 |
--------------------------------------------------------------------------------
/man/project_create.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/project_create.R
3 | \name{project_create}
4 | \alias{project_create}
5 | \title{Create a new project.}
6 | \usage{
7 | project_create(
8 | name,
9 | url = get_default_url(),
10 | un = get_default_un(),
11 | pw = get_default_pw()
12 | )
13 | }
14 | \arguments{
15 | \item{name}{The desired name of the project. Can contain whitespace.}
16 |
17 | \item{url}{The ODK Central base URL without trailing slash.
18 |
19 | Default: \code{\link{get_default_url}}.
20 |
21 | Set default \code{url} through \code{ru_setup(url="...")}.
22 |
23 | See \code{vignette("Setup", package = "ruODK")}.}
24 |
25 | \item{un}{The ODK Central username (an email address).
26 | Default: \code{\link{get_default_un}}.
27 | Set default \code{un} through \code{ru_setup(un="...")}.
28 | See \code{vignette("Setup", package = "ruODK")}.}
29 |
30 | \item{pw}{The ODK Central password.
31 | Default: \code{\link{get_default_pw}}.
32 | Set default \code{pw} through \code{ru_setup(pw="...")}.
33 | See \code{vignette("Setup", package = "ruODK")}.}
34 | }
35 | \value{
36 | A tibble with one row per project and all project metadata
37 | as columns as per ODK Central API docs.
38 | }
39 | \description{
40 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
41 | }
42 | \examples{
43 | \dontrun{
44 | # See vignette("setup") for setup and authentication options
45 | # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
46 |
47 | p <- project_create("Test Project")
48 | knitr::kable(p)
49 |
50 | # project_create returns a tibble
51 | class(p)
52 | # > "tbl_df" "tbl" "data.frame"
53 |
54 | # columns are project metadata
55 | names(p)
56 | # > "id" "name" "archived"
57 | }
58 | }
59 | \seealso{
60 | \url{https://docs.getodk.org/central-api-project-management/#creating-a-project}
61 |
62 | Other project-management:
63 | \code{\link{project_detail}()},
64 | \code{\link{project_list}()}
65 | }
66 | \concept{project-management}
67 |
--------------------------------------------------------------------------------
/tests/testthat/test-drop_null_coords.R:
--------------------------------------------------------------------------------
1 | test_that("drop_null_coords works on data with empty last coords ", {
2 | # This test will break once the ODK Central Sandbox has fixed
3 | # issue https://github.com/getodk/central-backend/issues/282
4 | # through https://github.com/getodk/central-backend/pull/283
5 | # and ruODK's package data have been updated.
6 | # We therefore have included a snapshot of test data exhibiting the problem.
7 | # The data uses "bad" coordinates from the ODK Sandbox and an unpatched ruODK.
8 | # The data "geo_gj" uses "bad" coordinates (soon: good coordinates) from the
9 | # ODK Sandbox and a patched ruODK.
10 | data("geo_gj88")
11 |
12 | len_coords <- length(geo_gj88$path_location_path_gps[[1]]$coordinates)
13 |
14 | length(geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]]) %>%
15 | testthat::expect_equal(2)
16 |
17 | geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]][[1]] %>%
18 | testthat::expect_null()
19 |
20 | geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]][[2]] %>%
21 | testthat::expect_null()
22 |
23 | geo_gj_repaired <- geo_gj88 %>%
24 | dplyr::mutate(
25 | path_location_path_gps = path_location_path_gps %>%
26 | purrr::map(drop_null_coords)
27 | )
28 |
29 | len_coords_repaired <- length(
30 | geo_gj_repaired$path_location_path_gps[[1]]$coordinates
31 | )
32 | testthat::expect_equal(len_coords_repaired + 1, len_coords)
33 | })
34 |
35 | test_that("drop_null_coords works on data without empty last coords ", {
36 | data("geo_gj")
37 |
38 | len_coords <- length(geo_gj$path_location_path_gps[[1]]$coordinates)
39 |
40 | geo_gj_repaired <- geo_gj %>%
41 | dplyr::mutate(
42 | path_location_path_gps = path_location_path_gps %>%
43 | purrr::map(drop_null_coords)
44 | )
45 |
46 | len_coords_repaired <- length(
47 | geo_gj_repaired$path_location_path_gps[[1]]$coordinates
48 | )
49 |
50 | # No coordinates were harmed in the making of this test
51 | testthat::expect_equal(len_coords_repaired, len_coords)
52 | })
53 |
54 |
55 | # usethis::use_r("drop_null_coords") # nolint
56 |
--------------------------------------------------------------------------------
/man/fq_raw_strata.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_raw_strata}
5 | \alias{fq_raw_strata}
6 | \title{OData submission data for a subgroup of an ODK Central form.}
7 | \format{
8 | A list of lists
9 | }
10 | \source{
11 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
12 | }
13 | \usage{
14 | fq_raw_strata
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | The OData response for the subgroup of an ODK Central form.
21 |
22 | This subgroup represents vegetation strata as per the NVIS classification.
23 | A vegetation stratum is a layer of plants with the same height, and dominated
24 | by one or few plant taxa. Plant communities can be made of up to five strata,
25 | with two to three being most common.
26 |
27 | This data is kept up to date with the data used in vignettes and package
28 | tests. The data is comprised of test records with nonsensical data.
29 | The forms used to capture this data are development versions of real-world
30 | forms.
31 | }
32 | \seealso{
33 | Other included:
34 | \code{\link{fq_attachments}},
35 | \code{\link{fq_data}},
36 | \code{\link{fq_data_strata}},
37 | \code{\link{fq_data_taxa}},
38 | \code{\link{fq_form_detail}},
39 | \code{\link{fq_form_list}},
40 | \code{\link{fq_form_schema}},
41 | \code{\link{fq_form_xml}},
42 | \code{\link{fq_meta}},
43 | \code{\link{fq_project_detail}},
44 | \code{\link{fq_project_list}},
45 | \code{\link{fq_raw}},
46 | \code{\link{fq_raw_taxa}},
47 | \code{\link{fq_submission_list}},
48 | \code{\link{fq_submissions}},
49 | \code{\link{fq_svc}},
50 | \code{\link{fq_zip_data}},
51 | \code{\link{fq_zip_strata}},
52 | \code{\link{fq_zip_taxa}},
53 | \code{\link{fs_v7}},
54 | \code{\link{fs_v7_raw}},
55 | \code{\link{geo_fs}},
56 | \code{\link{geo_gj}},
57 | \code{\link{geo_gj88}},
58 | \code{\link{geo_gj_raw}},
59 | \code{\link{geo_wkt}},
60 | \code{\link{geo_wkt88}},
61 | \code{\link{geo_wkt_raw}}
62 | }
63 | \concept{included}
64 | \keyword{datasets}
65 |
--------------------------------------------------------------------------------
/man/parse_odkc_version.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{parse_odkc_version}
4 | \alias{parse_odkc_version}
5 | \title{Parse a given ODK Central version string or number into a \code{semver}.}
6 | \usage{
7 | parse_odkc_version(v, env_var = "ODKC_VERSION")
8 | }
9 | \arguments{
10 | \item{v}{A string (e.g. "ODKC_VERSION=") or number (e.g. 0.8, 1.5) of a
11 | complete or partial semver, or a semver of class "svlist".}
12 |
13 | \item{env_var}{A string indicating which environment variable was targeted.
14 | This is used in the warning to advise which environment variable to update.
15 | If set to an empty string, the warning message is suppressed.
16 | Default: "ODKC_VERSION".}
17 | }
18 | \value{
19 | semver::svlist The version as semver of major, minor, and patch.
20 | }
21 | \description{
22 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
23 | }
24 | \details{
25 | Past versions of ruODK advised to set ODKC_VERSION to a floating point number
26 | indicating major and minor versions, e.g. \code{ODKC_VERSION=0.7} or
27 | \code{ODKC_VERSION=1.5}.
28 |
29 | ODK Central has since switched to semantic versioning, e.g.
30 | \verb{ODKC_VERSION=ODKC_VERSION=}.
31 |
32 | To preserve backwards compatibility, ruODK handles both formats gracefully,
33 | but emits a helpful warning to update the version string if the older format
34 | is detected, or the version string is missing the minor or patch version.
35 | }
36 | \examples{
37 | parse_odkc_version("1.2.3")
38 |
39 | # Warn: too short
40 | parse_odkc_version("1")
41 | parse_odkc_version("1.2")
42 |
43 | # Warn: too long
44 | parse_odkc_version("1.2.3.4")
45 |
46 | # Warn: otherwise invalid
47 | parse_odkc_version("1.2.")
48 | parse_odkc_version(".2.3")
49 |
50 | }
51 | \seealso{
52 | Other ru_settings:
53 | \code{\link{odata_svc_parse}()},
54 | \code{\link{ru_settings}()},
55 | \code{\link{ru_setup}()},
56 | \code{\link{semver_gt}()},
57 | \code{\link{semver_lt}()},
58 | \code{\link{yell_if_error}()},
59 | \code{\link{yell_if_missing}()}
60 | }
61 | \concept{ru_settings}
62 |
--------------------------------------------------------------------------------
/man/fq_form_schema.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_form_schema}
5 | \alias{fq_form_schema}
6 | \title{JSON form schema for an ODK Central form.}
7 | \format{
8 | The output of \code{ruODK::form_schema()}, a tibble with columns "type",
9 | "name" and "path" and one row per form field.
10 | }
11 | \source{
12 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
13 | and \code{ruODK::form_schema()}.
14 | }
15 | \usage{
16 | fq_form_schema
17 | }
18 | \description{
19 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
20 | }
21 | \details{
22 | The parsed form schema of an ODK Central form.
23 |
24 | This data is kept up to date with the data used in vignettes and package
25 | tests. The data is comprised of test records with nonsensical data.
26 | The forms used to capture this data are development versions of real-world
27 | forms.
28 |
29 | This data is used to build vignettes offline and without the need for
30 | credentials to an ODK Central server. The test suite ensures that the
31 | "canned" data is identical to the "live" data.
32 | }
33 | \seealso{
34 | Other included:
35 | \code{\link{fq_attachments}},
36 | \code{\link{fq_data}},
37 | \code{\link{fq_data_strata}},
38 | \code{\link{fq_data_taxa}},
39 | \code{\link{fq_form_detail}},
40 | \code{\link{fq_form_list}},
41 | \code{\link{fq_form_xml}},
42 | \code{\link{fq_meta}},
43 | \code{\link{fq_project_detail}},
44 | \code{\link{fq_project_list}},
45 | \code{\link{fq_raw}},
46 | \code{\link{fq_raw_strata}},
47 | \code{\link{fq_raw_taxa}},
48 | \code{\link{fq_submission_list}},
49 | \code{\link{fq_submissions}},
50 | \code{\link{fq_svc}},
51 | \code{\link{fq_zip_data}},
52 | \code{\link{fq_zip_strata}},
53 | \code{\link{fq_zip_taxa}},
54 | \code{\link{fs_v7}},
55 | \code{\link{fs_v7_raw}},
56 | \code{\link{geo_fs}},
57 | \code{\link{geo_gj}},
58 | \code{\link{geo_gj88}},
59 | \code{\link{geo_gj_raw}},
60 | \code{\link{geo_wkt}},
61 | \code{\link{geo_wkt88}},
62 | \code{\link{geo_wkt_raw}}
63 | }
64 | \concept{included}
65 | \keyword{datasets}
66 |
--------------------------------------------------------------------------------
/man/fq_raw.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_raw}
5 | \alias{fq_raw}
6 | \title{OData submission data for an ODK Central form.}
7 | \format{
8 | A list of lists
9 | }
10 | \source{
11 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
12 | }
13 | \usage{
14 | fq_raw
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | The OData response for the submissions of an ODK Central form.
21 | This form represents a Flora Quadrat, which is a ca 50 by 50 m quadrat of
22 | a uniform plant community.
23 |
24 | The XML and .odkbuild versions for this form are available as
25 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
26 | and \code{system.file("extdata", "FloraQuadrat04.odkbuild", package = "ruODK")},
27 | respectively.
28 |
29 | This data is kept up to date with the data used in vignettes and package
30 | tests. The data is comprised of test records with nonsensical data.
31 | The forms used to capture this data are development versions of real-world
32 | forms.
33 | }
34 | \seealso{
35 | Other included:
36 | \code{\link{fq_attachments}},
37 | \code{\link{fq_data}},
38 | \code{\link{fq_data_strata}},
39 | \code{\link{fq_data_taxa}},
40 | \code{\link{fq_form_detail}},
41 | \code{\link{fq_form_list}},
42 | \code{\link{fq_form_schema}},
43 | \code{\link{fq_form_xml}},
44 | \code{\link{fq_meta}},
45 | \code{\link{fq_project_detail}},
46 | \code{\link{fq_project_list}},
47 | \code{\link{fq_raw_strata}},
48 | \code{\link{fq_raw_taxa}},
49 | \code{\link{fq_submission_list}},
50 | \code{\link{fq_submissions}},
51 | \code{\link{fq_svc}},
52 | \code{\link{fq_zip_data}},
53 | \code{\link{fq_zip_strata}},
54 | \code{\link{fq_zip_taxa}},
55 | \code{\link{fs_v7}},
56 | \code{\link{fs_v7_raw}},
57 | \code{\link{geo_fs}},
58 | \code{\link{geo_gj}},
59 | \code{\link{geo_gj88}},
60 | \code{\link{geo_gj_raw}},
61 | \code{\link{geo_wkt}},
62 | \code{\link{geo_wkt88}},
63 | \code{\link{geo_wkt_raw}}
64 | }
65 | \concept{included}
66 | \keyword{datasets}
67 |
--------------------------------------------------------------------------------
/man/yell_if_missing.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ru_setup.R
3 | \name{yell_if_missing}
4 | \alias{yell_if_missing}
5 | \title{Abort on missing ODK Central credentials (url, username, password).}
6 | \usage{
7 | yell_if_missing(
8 | url,
9 | un,
10 | pw,
11 | pid = NULL,
12 | fid = NULL,
13 | iid = NULL,
14 | did = NULL,
15 | eid = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{url}{A URL (character)}
20 |
21 | \item{un}{A username (character)}
22 |
23 | \item{pw}{A password (character)}
24 |
25 | \item{pid}{A project ID (numeric, optional)}
26 |
27 | \item{fid}{A form ID (character, optional)}
28 |
29 | \item{iid}{A submission instance ID (character, optional)}
30 |
31 | \item{did}{An Entity List (dataset) name (character, optional)}
32 |
33 | \item{eid}{An Entity UUID (character, optional)}
34 | }
35 | \description{
36 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
37 | }
38 | \details{
39 | This is a helper function to pat down \code{\link{ruODK}} functions
40 | for missing credentials and stop with a loud but informative yell.
41 | }
42 | \examples{
43 | testthat::expect_error(yell_if_missing("", "username", "password"))
44 | testthat::expect_error(yell_if_missing("url", "", "password"))
45 | testthat::expect_error(yell_if_missing("url", "username", ""))
46 | testthat::expect_error(yell_if_missing(NULL, "", ""))
47 | testthat::expect_error(yell_if_missing("", "", ""))
48 | testthat::expect_error(yell_if_missing("", "", "", ""))
49 | testthat::expect_error(yell_if_missing("", "", "", "", ""))
50 | testthat::expect_error(yell_if_missing("", "", "", "", "", ""))
51 | testthat::expect_error(yell_if_missing("", "", "", "", "", "", ""))
52 | testthat::expect_error(yell_if_missing("", "", "", "", "", "", "", ""))
53 | }
54 | \seealso{
55 | Other ru_settings:
56 | \code{\link{odata_svc_parse}()},
57 | \code{\link{parse_odkc_version}()},
58 | \code{\link{ru_settings}()},
59 | \code{\link{ru_setup}()},
60 | \code{\link{semver_gt}()},
61 | \code{\link{semver_lt}()},
62 | \code{\link{yell_if_error}()}
63 | }
64 | \concept{ru_settings}
65 | \keyword{internal}
66 |
--------------------------------------------------------------------------------
/tests/testthat/test-form_schema_parse.R:
--------------------------------------------------------------------------------
1 | test_that("predict_ruodk_name works", {
2 | testthat::expect_equal(
3 | predict_ruodk_name("bar", "Submissions.foo"),
4 | "foo_bar"
5 | )
6 |
7 | testthat::expect_equal(
8 | predict_ruodk_name("bar", "Submissions"),
9 | "bar"
10 | )
11 |
12 | testthat::expect_equal(
13 | predict_ruodk_name("rock", "Submissions.foo_fighters"),
14 | "foo_fighters_rock"
15 | )
16 | })
17 |
18 | # nolint start
19 | # This test is retired, as the current test server runs at v1.4+
20 | # test_that("form_schema works with ODK Central v0.8", {
21 | # skip_if(Sys.getenv("ODKC_TEST_URL") == "",
22 | # message = "Test server not configured"
23 | # )
24 | # fs <- form_schema(
25 | # flatten = FALSE,
26 | # parse = FALSE,
27 | # odata = FALSE,
28 | # pid = get_test_pid(),
29 | # fid = get_test_fid(),
30 | # url = get_test_url(),
31 | # un = get_test_un(),
32 | # pw = get_test_pw(),
33 | # odkc_version = get_test_odkc_version(),
34 | # verbose = TRUE
35 | # )
36 | # testthat::expect_true(tibble::is_tibble(fs))
37 | # testthat::expect_equal(
38 | # names(fs),
39 | # c("path", "name", "type", "binary", "ruodk_name")
40 | # )
41 | # testthat::expect_true("encounter_start_datetime" %in% fs$name)
42 | # testthat::expect_true("quadrat_photo" %in% fs$name)
43 | # # # Attachments
44 | # # fsp %>% dplyr::filter(type=="binary")
45 | # #
46 | # # # dateYime
47 | # # fsp %>% dplyr::filter(type=="dateTime")
48 | # #
49 | # # # Point location
50 | # # fsp %>% dplyr::filter(type=="geopoint")
51 | # })
52 | # nolint end
53 |
54 | test_that("form_schema_parse debug messages work", {
55 | data("fs_v7_raw")
56 | data("fs_v7")
57 |
58 | testthat::capture_output(
59 | testthat::expect_message(
60 | fs_v7_parsed <- form_schema_parse(fs_v7_raw, verbose = TRUE)
61 | )
62 | )
63 |
64 | testthat::expect_equal(class(fs_v7_parsed), c("tbl_df", "tbl", "data.frame"))
65 | testthat::expect_true("observation_start_time" %in% fs_v7_parsed$name)
66 | testthat::expect_true("disturbance_cause" %in% fs_v7_parsed$name)
67 |
68 | testthat::expect_equal(fs_v7, fs_v7_parsed)
69 | })
70 |
--------------------------------------------------------------------------------
/tests/testthat/test-user_list.R:
--------------------------------------------------------------------------------
1 | test_that("user_list returns list of users", {
2 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
3 | message = "Test server not configured"
4 | )
5 | ul <- user_list(
6 | url = get_test_url(),
7 | un = get_test_un(),
8 | pw = get_test_pw()
9 | )
10 | testthat::expect_s3_class(ul, "tbl_df")
11 |
12 | cn <- c(
13 | "id",
14 | "type",
15 | "display_name",
16 | "created_at",
17 | "email",
18 | "updated_at"
19 | )
20 |
21 | purrr::map(
22 | cn,
23 | ~ testthat::expect_true(
24 | . %in% names(ul),
25 | label = glue::glue("Column {.} missing from user_list")
26 | )
27 | )
28 | })
29 |
30 | test_that("user_list returns filtered list of users", {
31 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
32 | message = "Test server not configured"
33 | )
34 |
35 | # Use the first user's name to generate search strings
36 | ul <- user_list(
37 | url = get_test_url(),
38 | un = get_test_un(),
39 | pw = get_test_pw()
40 | )
41 | ss3 <- substr(ul$display_name[[1]], 1, 3) # too short
42 | ss5 <- substr(ul$display_name[[1]], 1, 5) # long enough
43 |
44 | # Concerningly short search strings will emit a warning only if verbose
45 | testthat::expect_message(
46 | # reason: provided query string
47 | testthat::expect_warning(
48 | # reason: query string too short
49 | ul_flt3 <- user_list(
50 | url = get_test_url(),
51 | un = get_test_un(),
52 | pw = get_test_pw(),
53 | qry = ss3,
54 | verbose = TRUE
55 | )
56 | )
57 | )
58 |
59 | # No warning here
60 | ul_flt3 <- user_list(
61 | url = get_test_url(),
62 | un = get_test_un(),
63 | pw = get_test_pw(),
64 | qry = ss3,
65 | verbose = FALSE
66 | )
67 | ul_flt5 <- user_list(
68 | url = get_test_url(),
69 | un = get_test_un(),
70 | pw = get_test_pw(),
71 | qry = ss5
72 | )
73 |
74 | testthat::expect_gte(
75 | nrow(ul_flt3),
76 | 0,
77 | label = "Short search strings (3 char) should return no matches"
78 | )
79 |
80 | testthat::expect_gte(
81 | nrow(ul_flt5),
82 | 1,
83 | label = "Sufficiently long search strings (5 char) should return matches"
84 | )
85 | })
86 |
87 | # usethis::use_r("user_list") # nolint
88 |
--------------------------------------------------------------------------------
/tests/testthat/test-entity_detail.R:
--------------------------------------------------------------------------------
1 | test_that("entity_detail works", {
2 | ru_setup(
3 | pid = get_test_pid(),
4 | url = get_test_url(),
5 | un = get_test_un(),
6 | pw = get_test_pw(),
7 | odkc_version = get_test_odkc_version()
8 | )
9 |
10 | el <- entitylist_list()
11 |
12 | # Entity List name (dataset ID)
13 | did <- el$name[1]
14 |
15 | # All Entities of Entity List
16 | en <- entity_list(did = el$name[1])
17 |
18 | # Entity detail
19 | ed <- entity_detail(did = el$name[1], eid = en$uuid[1])
20 |
21 | cn <- c(
22 | "uuid",
23 | "creator_id",
24 | "conflict",
25 | "created_at",
26 | "updated_at",
27 | "deleted_at",
28 | "current_version"
29 | # not unfolded:
30 | # "current_version_created_at",
31 | # "current_version_current",
32 | # "current_version_label",
33 | # "current_version_creator_id",
34 | # "current_version_user_agent",
35 | # "current_version_version",
36 | # "current_version_base_version",
37 | # "current_version_conflicting_properties"
38 | )
39 | testthat::expect_equal(cn, names(ed))
40 |
41 | # The UUID of the first Entity
42 | eid <- en$uuid[1]
43 | testthat::expect_is(eid, "character")
44 |
45 | # The current version of the first Entity
46 | ev <- en$current_version_version[1]
47 | testthat::expect_is(ev, "integer")
48 | })
49 |
50 | test_that("entity_detail errors if did is missing", {
51 | testthat::expect_error(
52 | entity_detail()
53 | )
54 | })
55 |
56 | test_that("entity_detail warns if odkc_version too low", {
57 | skip_if(Sys.getenv("ODKC_TEST_URL") == "",
58 | message = "Test server not configured"
59 | )
60 |
61 | ru_setup(
62 | pid = get_test_pid(),
63 | url = get_test_url(),
64 | un = get_test_un(),
65 | pw = get_test_pw(),
66 | odkc_version = get_test_odkc_version()
67 | )
68 |
69 | el <- entitylist_list()
70 |
71 | # Entity List name (dataset ID)
72 | did <- el$name[1]
73 |
74 | # All Entities of Entity List
75 | en <- entity_list(did = el$name[1])
76 |
77 | # Entity detail
78 | ed <- entity_detail(did = el$name[1], eid = en$uuid[1])
79 |
80 | # Expect error with missing eid
81 | testthat::expect_error(
82 | entity_detail(did = el$name[1])
83 | )
84 | })
85 |
86 |
87 | # usethis::use_r("entity_detail") # nolint
88 |
--------------------------------------------------------------------------------
/man/fq_raw_taxa.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_raw_taxa}
5 | \alias{fq_raw_taxa}
6 | \title{OData submission data for a subgroup of an ODK Central form.}
7 | \format{
8 | A list of lists
9 | }
10 | \source{
11 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
12 | }
13 | \usage{
14 | fq_raw_taxa
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | The OData response for a subgroup of an ODK Central form.
21 |
22 | This subgroup represents an individual plant taxon which is encountered by
23 | the enumerators. Typically, one voucher specimen is taken for each distinct
24 | encountered plant taxon. A field name is allocated by the enumerators, which
25 | can be the proper canonical name (if known) or any other moniker.
26 | The voucher specimens are later determined by taxonomic experts, who then
27 | provide the real, terminal taxonomic name for a given voucher specimen.
28 |
29 | This data is kept up to date with the data used in vignettes and package
30 | tests. The data is comprised of test records with nonsensical data.
31 | The forms used to capture this data are development versions of real-world
32 | forms.
33 | }
34 | \seealso{
35 | Other included:
36 | \code{\link{fq_attachments}},
37 | \code{\link{fq_data}},
38 | \code{\link{fq_data_strata}},
39 | \code{\link{fq_data_taxa}},
40 | \code{\link{fq_form_detail}},
41 | \code{\link{fq_form_list}},
42 | \code{\link{fq_form_schema}},
43 | \code{\link{fq_form_xml}},
44 | \code{\link{fq_meta}},
45 | \code{\link{fq_project_detail}},
46 | \code{\link{fq_project_list}},
47 | \code{\link{fq_raw}},
48 | \code{\link{fq_raw_strata}},
49 | \code{\link{fq_submission_list}},
50 | \code{\link{fq_submissions}},
51 | \code{\link{fq_svc}},
52 | \code{\link{fq_zip_data}},
53 | \code{\link{fq_zip_strata}},
54 | \code{\link{fq_zip_taxa}},
55 | \code{\link{fs_v7}},
56 | \code{\link{fs_v7_raw}},
57 | \code{\link{geo_fs}},
58 | \code{\link{geo_gj}},
59 | \code{\link{geo_gj88}},
60 | \code{\link{geo_gj_raw}},
61 | \code{\link{geo_wkt}},
62 | \code{\link{geo_wkt88}},
63 | \code{\link{geo_wkt_raw}}
64 | }
65 | \concept{included}
66 | \keyword{datasets}
67 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: R-CMD-check
10 |
11 | jobs:
12 | R-CMD-check:
13 | runs-on: ubuntu-latest
14 | environment: ci
15 | env:
16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
17 | R_KEEP_PKG_SOURCE: yes
18 | ODKC_TEST_URL: ${{ secrets.ODKC_TEST_URL }}
19 | ODKC_TEST_SVC: ${{ secrets.ODKC_TEST_SVC }}
20 | ODKC_TEST_PID: ${{ secrets.ODKC_TEST_PID }}
21 | ODKC_TEST_PID_ENC: ${{ secrets.ODKC_TEST_PID_ENC }}
22 | ODKC_TEST_PP: ${{ secrets.ODKC_TEST_PP }}
23 | ODKC_TEST_FID: ${{ secrets.ODKC_TEST_FID }}
24 | ODKC_TEST_FID_ZIP: ${{ secrets.ODKC_TEST_FID_ZIP }}
25 | ODKC_TEST_FID_ATT: ${{ secrets.ODKC_TEST_FID_ATT }}
26 | ODKC_TEST_FID_GAP: ${{ secrets.ODKC_TEST_FID_GAP }}
27 | ODKC_TEST_FID_WKT: ${{ secrets.ODKC_TEST_FID_WKT }}
28 | ODKC_TEST_FID_I8N0: ${{ secrets.ODKC_TEST_FID_I8N0 }}
29 | ODKC_TEST_FID_I8N1: ${{ secrets.ODKC_TEST_FID_I8N1 }}
30 | ODKC_TEST_FID_I8N2: ${{ secrets.ODKC_TEST_FID_I8N2 }}
31 | ODKC_TEST_FID_ENC: ${{ secrets.ODKC_TEST_FID_ENC }}
32 | ODKC_TEST_VERSION: ${{ secrets.ODKC_TEST_VERSION }}
33 | RU_VERBOSE: ${{ secrets.RU_VERBOSE }}
34 | RU_TIMEZONE: ${{ secrets.RU_TIMEZONE }}
35 | RU_RETRIES: ${{ secrets.RU_RETRIES }}
36 | ODKC_TEST_UN: ${{ secrets.ODKC_TEST_UN }}
37 | ODKC_TEST_PW: ${{ secrets.ODKC_TEST_PW }}
38 | ODKC_URL: ${{ secrets.ODKC_TEST_URL }}
39 | ODKC_UN: ${{ secrets.ODKC_TEST_UN }}
40 | ODKC_PW: ${{ secrets.ODKC_TEST_PW }}
41 | ODKC_PP: ${{ secrets.ODKC_TEST_PP }}
42 | ODKC_VERSION: ${{ secrets.ODKC_TEST_VERSION }}
43 |
44 | steps:
45 | - uses: actions/checkout@v4
46 |
47 | - uses: r-lib/actions/setup-r@v2
48 | with:
49 | use-public-rspm: true
50 |
51 | - uses: r-lib/actions/setup-r-dependencies@v2
52 | with:
53 | extra-packages: any::rcmdcheck
54 | needs: check
55 |
56 | - uses: r-lib/actions/check-r-package@v2
57 | with:
58 | upload-snapshots: true
59 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
60 |
--------------------------------------------------------------------------------
/man/fq_data_strata.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_data_strata}
5 | \alias{fq_data_strata}
6 | \title{Parsed submission data for a subgroup of an ODK Central form.}
7 | \format{
8 | The output of \code{\link{odata_submission_get}} for a set of example
9 | data. A tidy tibble referencing the attachments included in the vignettes
10 | and documentation at a relative path \verb{attachments/media/.}.
11 | }
12 | \source{
13 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
14 | and \code{\link{odata_submission_get}}.
15 | }
16 | \usage{
17 | fq_data_strata
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \details{
23 | The parsed OData response for the subgroup of an ODK Central form.
24 |
25 | This subgroup represents vegetation strata as per the NVIS classification.
26 | A vegetation stratum is a layer of plants with the same height, and dominated
27 | by one or few plant taxa. Plant communities can be made of up to five strata,
28 | with two to three being most common.
29 |
30 | This data is kept up to date with the data used in vignettes and package
31 | tests. The data is comprised of test records with nonsensical data.
32 | The forms used to capture this data are development versions of real-world
33 | forms.
34 | }
35 | \seealso{
36 | Other included:
37 | \code{\link{fq_attachments}},
38 | \code{\link{fq_data}},
39 | \code{\link{fq_data_taxa}},
40 | \code{\link{fq_form_detail}},
41 | \code{\link{fq_form_list}},
42 | \code{\link{fq_form_schema}},
43 | \code{\link{fq_form_xml}},
44 | \code{\link{fq_meta}},
45 | \code{\link{fq_project_detail}},
46 | \code{\link{fq_project_list}},
47 | \code{\link{fq_raw}},
48 | \code{\link{fq_raw_strata}},
49 | \code{\link{fq_raw_taxa}},
50 | \code{\link{fq_submission_list}},
51 | \code{\link{fq_submissions}},
52 | \code{\link{fq_svc}},
53 | \code{\link{fq_zip_data}},
54 | \code{\link{fq_zip_strata}},
55 | \code{\link{fq_zip_taxa}},
56 | \code{\link{fs_v7}},
57 | \code{\link{fs_v7_raw}},
58 | \code{\link{geo_fs}},
59 | \code{\link{geo_gj}},
60 | \code{\link{geo_gj88}},
61 | \code{\link{geo_gj_raw}},
62 | \code{\link{geo_wkt}},
63 | \code{\link{geo_wkt88}},
64 | \code{\link{geo_wkt_raw}}
65 | }
66 | \concept{included}
67 | \keyword{datasets}
68 |
--------------------------------------------------------------------------------
/man/fq_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_data}
5 | \alias{fq_data}
6 | \title{Parsed submission data for an ODK Central form.}
7 | \format{
8 | The output of \code{\link{odata_submission_get}} for a set of example
9 | data. A tidy tibble referencing the attachments included in the vignettes
10 | and documentation at a relative path \verb{attachments/media/.}.
11 | }
12 | \source{
13 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
14 | and \code{\link{odata_submission_get}}.
15 | }
16 | \usage{
17 | fq_data
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \details{
23 | The parsed OData response for the submissions of an ODK Central form.
24 | This form represents a Flora Quadrat, which is a ca 50 by 50 m quadrat of
25 | a uniform plant community.
26 |
27 | The XML and .odkbuild versions for this form are available as
28 | \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
29 | and \code{system.file("extdata", "FloraQuadrat04.odkbuild", package = "ruODK")},
30 | respectively.
31 |
32 | This data is kept up to date with the data used in vignettes and package
33 | tests. The data is comprised of test records with nonsensical data.
34 | The forms used to capture this data are development versions of real-world
35 | forms.
36 | }
37 | \seealso{
38 | Other included:
39 | \code{\link{fq_attachments}},
40 | \code{\link{fq_data_strata}},
41 | \code{\link{fq_data_taxa}},
42 | \code{\link{fq_form_detail}},
43 | \code{\link{fq_form_list}},
44 | \code{\link{fq_form_schema}},
45 | \code{\link{fq_form_xml}},
46 | \code{\link{fq_meta}},
47 | \code{\link{fq_project_detail}},
48 | \code{\link{fq_project_list}},
49 | \code{\link{fq_raw}},
50 | \code{\link{fq_raw_strata}},
51 | \code{\link{fq_raw_taxa}},
52 | \code{\link{fq_submission_list}},
53 | \code{\link{fq_submissions}},
54 | \code{\link{fq_svc}},
55 | \code{\link{fq_zip_data}},
56 | \code{\link{fq_zip_strata}},
57 | \code{\link{fq_zip_taxa}},
58 | \code{\link{fs_v7}},
59 | \code{\link{fs_v7_raw}},
60 | \code{\link{geo_fs}},
61 | \code{\link{geo_gj}},
62 | \code{\link{geo_gj88}},
63 | \code{\link{geo_gj_raw}},
64 | \code{\link{geo_wkt}},
65 | \code{\link{geo_wkt88}},
66 | \code{\link{geo_wkt_raw}}
67 | }
68 | \concept{included}
69 | \keyword{datasets}
70 |
--------------------------------------------------------------------------------
/R/drop_null_coords.R:
--------------------------------------------------------------------------------
1 | #' Drop any NULL coordinates from a GeoJSON geometry.
2 | #'
3 | #' This helper patches a bug/feature in ODK Central (versions 0.7-0.9), where
4 | #' geotrace / geoshape GeoJSON contains a last coordinate pair with NULL
5 | #' lat/lon (no alt/acc), and WKT ends in `, undefined NaN`.
6 | #'
7 | #' While \code{\link{split_geotrace}} and \code{\link{split_geoshape}} modify
8 | #' the WKT inline, it is more maintainable to separate the GeoJSON cleaner
9 | #' into this function.
10 | #'
11 | #' This helper drops the last element of a GeoJSON coordinate list if it is
12 | #' `list(NULL, NULL)`.
13 | #'
14 | #' @param x A GeoJSON geometry parsed as nested list.
15 | #' E.g. `geo_gj$path_location_path_gps`.
16 | #' @return The nested list minus the last element (if NULL).
17 | #' @family utilities
18 | #' @export
19 | #' @examples
20 | #' # A snapshot of geo data with trailing empty coordinates.
21 | #' data("geo_gj88")
22 | #'
23 | #' len_coords <- length(geo_gj88$path_location_path_gps[[1]]$coordinates)
24 | #'
25 | #' length(geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]]) %>%
26 | #' testthat::expect_equal(2)
27 | #'
28 | #' geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]][[1]] %>%
29 | #' testthat::expect_null()
30 | #'
31 | #' geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]][[2]] %>%
32 | #' testthat::expect_null()
33 | #'
34 | #' # The last coordinate pair is a list(NULL, NULL).
35 | #' # Invalid coordinates like these are a choking hazard for geospatial
36 | #' # packages. We should remove them before we can convert ODK data into native
37 | #' # spatial formats, such as sf.
38 | #' str(geo_gj88$path_location_path_gps[[1]]$coordinates[[len_coords]])
39 | #'
40 | #' geo_gj_repaired <- geo_gj88 %>%
41 | #' dplyr::mutate(
42 | #' path_location_path_gps = path_location_path_gps %>%
43 | #' purrr::map(drop_null_coords)
44 | #' )
45 | #'
46 | #' len_coords_repaired <- length(
47 | #' geo_gj_repaired$path_location_path_gps[[1]]$coordinates
48 | #' )
49 | #' testthat::expect_equal(len_coords_repaired + 1, len_coords)
50 | drop_null_coords <- function(x) {
51 | # Extract and simplify last coords. list(NULL, NULL) becomes list().
52 | xx <- purrr::compact(x$coordinates[[length(x$coordinates)]])
53 | # Remove empty coords by setting the entire list(NULL, NULL) to NULL.
54 | if (is.list(xx) && length(xx) == 0) {
55 | x$coordinates[[length(x$coordinates)]] <- NULL
56 | }
57 | x
58 | }
59 |
60 | # usethis::use_test("drop_null_coords") # nolint
61 |
--------------------------------------------------------------------------------
/man/isodt_to_local.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/isodt_to_local.R
3 | \name{isodt_to_local}
4 | \alias{isodt_to_local}
5 | \title{Parse an ISO8601 datetime string to a timezone aware datetime.}
6 | \usage{
7 | isodt_to_local(
8 | datetime_string,
9 | orders = c("YmdHMS", "YmdHMSz"),
10 | tz = get_default_tz(),
11 | quiet = TRUE
12 | )
13 | }
14 | \arguments{
15 | \item{datetime_string}{(character) An ISO8601 datetime string as produced by
16 | XForms exported from ODK Central.}
17 |
18 | \item{orders}{(vector of character) Orders of datetime elements for
19 | \code{lubridate}.
20 | Default: \code{c("YmdHMS", "YmdHMSz", "Ymd HMS", "Ymd HMSz")}.}
21 |
22 | \item{tz}{A timezone to convert dates and times to.
23 |
24 | Read \code{vignette("setup", package = "ruODK")} to learn how \code{ruODK}'s
25 | timezone can be set globally or per function.}
26 |
27 | \item{quiet}{(lgl) Used in \code{lubridate::parse_date_time(quiet=quiet)} to
28 | suppress warnings from attempting to parse all empty values or columns.
29 | Run with \code{quiet=FALSE} to show any \code{lubridate} warnings.}
30 | }
31 | \value{
32 | A \code{lubridate} PosixCT datetime in the given timezone.
33 | }
34 | \description{
35 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
36 | }
37 | \details{
38 | This function is used internally by \code{ruODK} to parse ISO timestamps
39 | to timezone-aware local times.
40 |
41 | Warnings are suppressed through \code{lubridate::parse_date_time(quiet=TRUE)}.
42 | }
43 | \seealso{
44 | Other utilities:
45 | \code{\link{attachment_get}()},
46 | \code{\link{attachment_link}()},
47 | \code{\link{attachment_url}()},
48 | \code{\link{drop_null_coords}()},
49 | \code{\link{form_schema_parse}()},
50 | \code{\link{get_one_attachment}()},
51 | \code{\link{get_one_submission}()},
52 | \code{\link{get_one_submission_att_list}()},
53 | \code{\link{get_one_submission_audit}()},
54 | \code{\link{handle_ru_attachments}()},
55 | \code{\link{handle_ru_datetimes}()},
56 | \code{\link{handle_ru_geopoints}()},
57 | \code{\link{handle_ru_geoshapes}()},
58 | \code{\link{handle_ru_geotraces}()},
59 | \code{\link{odata_submission_rectangle}()},
60 | \code{\link{predict_ruodk_name}()},
61 | \code{\link{prepend_uuid}()},
62 | \code{\link{split_geopoint}()},
63 | \code{\link{split_geoshape}()},
64 | \code{\link{split_geotrace}()},
65 | \code{\link{strip_uuid}()},
66 | \code{\link{tidyeval}},
67 | \code{\link{unnest_all}()}
68 | }
69 | \concept{utilities}
70 | \keyword{internal}
71 |
--------------------------------------------------------------------------------
/man/odata_service_get.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/odata_service_get.R
3 | \name{odata_service_get}
4 | \alias{odata_service_get}
5 | \title{Retrieve service metadata from an OData URL ending in .svc as tibble.}
6 | \usage{
7 | odata_service_get(
8 | pid = get_default_pid(),
9 | fid = get_default_fid(),
10 | url = get_default_url(),
11 | un = get_default_un(),
12 | pw = get_default_pw(),
13 | retries = get_retries()
14 | )
15 | }
16 | \arguments{
17 | \item{pid}{The numeric ID of the project, e.g.: 2.
18 |
19 | Default: \code{\link{get_default_pid}}.
20 |
21 | Set default \code{pid} through \code{ru_setup(pid="...")}.
22 |
23 | See \code{vignette("Setup", package = "ruODK")}.}
24 |
25 | \item{fid}{The alphanumeric form ID, e.g. "build_Spotlighting-0-8_1559885147".
26 |
27 | Default: \code{\link{get_default_fid}}.
28 |
29 | Set default \code{fid} through \code{ru_setup(fid="...")}.
30 |
31 | See \code{vignette("Setup", package = "ruODK")}.}
32 |
33 | \item{url}{The ODK Central base URL without trailing slash.
34 |
35 | Default: \code{\link{get_default_url}}.
36 |
37 | Set default \code{url} through \code{ru_setup(url="...")}.
38 |
39 | See \code{vignette("Setup", package = "ruODK")}.}
40 |
41 | \item{un}{The ODK Central username (an email address).
42 | Default: \code{\link{get_default_un}}.
43 | Set default \code{un} through \code{ru_setup(un="...")}.
44 | See \code{vignette("Setup", package = "ruODK")}.}
45 |
46 | \item{pw}{The ODK Central password.
47 | Default: \code{\link{get_default_pw}}.
48 | Set default \code{pw} through \code{ru_setup(pw="...")}.
49 | See \code{vignette("Setup", package = "ruODK")}.}
50 |
51 | \item{retries}{The number of attempts to retrieve a web resource.
52 |
53 | This parameter is given to \code{\link[httr]{RETRY}(times = retries)}.
54 |
55 | Default: 3.}
56 | }
57 | \value{
58 | A tibble with one row per submission data endpoint.
59 | Columns: name, kind, url.
60 | }
61 | \description{
62 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
63 | }
64 | \examples{
65 | \dontrun{
66 | # See vignette("setup") for setup and authentication options
67 | # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
68 |
69 | svc <- odata_service_get()
70 | svc
71 | }
72 | }
73 | \seealso{
74 | \url{https://docs.getodk.org/central-api-odata-endpoints/#service-document}
75 |
76 | Other odata-api:
77 | \code{\link{odata_metadata_get}()},
78 | \code{\link{odata_submission_get}()}
79 | }
80 | \concept{odata-api}
81 |
--------------------------------------------------------------------------------
/man/fq_data_taxa.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data.R
3 | \docType{data}
4 | \name{fq_data_taxa}
5 | \alias{fq_data_taxa}
6 | \title{Parsed submission data for a subgroup of an ODK Central form.}
7 | \format{
8 | The output of \code{\link{odata_submission_get}} for a set of example
9 | data. A tidy tibble referencing the attachments included in the vignettes
10 | and documentation at a relative path \verb{attachments/media/.}.
11 | }
12 | \source{
13 | See \code{system.file("extdata", "FloraQuadrat04.xml", package = "ruODK")}
14 | and \code{\link{odata_submission_get}}.
15 | }
16 | \usage{
17 | fq_data_taxa
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
21 | }
22 | \details{
23 | The parsed OData response for a subgroup of an ODK Central form.
24 |
25 | This subgroup represents an individual plant taxon which is encountered by
26 | the enumerators. Typically, one voucher specimen is taken for each distinct
27 | encountered plant taxon. A field name is allocated by the enumerators, which
28 | can be the proper canonical name (if known) or any other moniker.
29 | The voucher specimens are later determined by taxonomic experts, who then
30 | provide the real, terminal taxonomic name for a given voucher specimen.
31 |
32 | This data is kept up to date with the data used in vignettes and package
33 | tests. The data is comprised of test records with nonsensical data.
34 | The forms used to capture this data are development versions of real-world
35 | forms.
36 | }
37 | \seealso{
38 | Other included:
39 | \code{\link{fq_attachments}},
40 | \code{\link{fq_data}},
41 | \code{\link{fq_data_strata}},
42 | \code{\link{fq_form_detail}},
43 | \code{\link{fq_form_list}},
44 | \code{\link{fq_form_schema}},
45 | \code{\link{fq_form_xml}},
46 | \code{\link{fq_meta}},
47 | \code{\link{fq_project_detail}},
48 | \code{\link{fq_project_list}},
49 | \code{\link{fq_raw}},
50 | \code{\link{fq_raw_strata}},
51 | \code{\link{fq_raw_taxa}},
52 | \code{\link{fq_submission_list}},
53 | \code{\link{fq_submissions}},
54 | \code{\link{fq_svc}},
55 | \code{\link{fq_zip_data}},
56 | \code{\link{fq_zip_strata}},
57 | \code{\link{fq_zip_taxa}},
58 | \code{\link{fs_v7}},
59 | \code{\link{fs_v7_raw}},
60 | \code{\link{geo_fs}},
61 | \code{\link{geo_gj}},
62 | \code{\link{geo_gj88}},
63 | \code{\link{geo_gj_raw}},
64 | \code{\link{geo_wkt}},
65 | \code{\link{geo_wkt88}},
66 | \code{\link{geo_wkt_raw}}
67 | }
68 | \concept{included}
69 | \keyword{datasets}
70 |
--------------------------------------------------------------------------------
/R/entitylist_list.R:
--------------------------------------------------------------------------------
1 | #' List all Entity Lists of one Project.
2 | #'
3 | #' `r lifecycle::badge("maturing")`
4 | #'
5 | #' The returned list is useful to retrieve the valid name of an Entity List for
6 | #' further use by functions of the Entity Management family.
7 | #'
8 | #' @template tpl-def-entitylist
9 | #' @template tpl-entitylist-dataset
10 | #' @template tpl-auth-missing
11 | #' @template tpl-compat-2022-3
12 | #' @template param-pid
13 | #' @template param-url
14 | #' @template param-auth
15 | #' @template param-retries
16 | #' @template param-odkcv
17 | #' @template param-orders
18 | #' @template param-tz
19 | #' @return A tibble with exactly one row for each Entity List of the given
20 | #' Project as per ODK Central API docs.
21 | #' Column names are renamed from ODK Central's `camelCase` to `snake_case`.
22 | # nolint start
23 | #' @seealso \url{ https://docs.getodk.org/central-api-dataset-management/#datasets}
24 | # nolint end
25 | #' @family entity-management
26 | #' @export
27 | #' @examples
28 | #' \dontrun{
29 | #' # See vignette("setup") for setup and authentication options
30 | #' # ruODK::ru_setup(svc = "... .svc", un = "me@email.com", pw = "...")
31 | #'
32 | #' ds <- entitylist_list(pid = get_default_pid())
33 | #'
34 | #' ds |> knitr::kable()
35 | #' }
36 | entitylist_list <- function(pid = get_default_pid(),
37 | url = get_default_url(),
38 | un = get_default_un(),
39 | pw = get_default_pw(),
40 | retries = get_retries(),
41 | odkc_version = get_default_odkc_version(),
42 | orders = get_default_orders(),
43 | tz = get_default_tz()) {
44 | yell_if_missing(url, un, pw, pid = pid)
45 |
46 | if (odkc_version |> semver_lt("2022.3")) {
47 | ru_msg_warn("entitylist_list is supported from v2022.3")
48 | }
49 |
50 | httr::RETRY(
51 | "GET",
52 | httr::modify_url(url, path = glue::glue("v1/projects/{pid}/datasets")),
53 | httr::add_headers(
54 | "Accept" = "application/json",
55 | "X-Extended-Metadata" = "true"
56 | ),
57 | httr::authenticate(un, pw),
58 | times = retries
59 | ) |>
60 | yell_if_error(url, un, pw) |>
61 | httr::content(encoding = "utf-8") |>
62 | purrr::list_transpose() |>
63 | tibble::as_tibble() |>
64 | janitor::clean_names() |>
65 | dplyr::mutate_at(
66 | dplyr::vars(c("created_at", "last_entity")),
67 | ~ isodt_to_local(., orders = orders, tz = tz)
68 | )
69 | }
70 |
71 | # usethis::use_test("entitylist_list") # nolint
72 |
--------------------------------------------------------------------------------
/man/odata_metadata_get.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/odata_metadata_get.R
3 | \name{odata_metadata_get}
4 | \alias{odata_metadata_get}
5 | \title{Retrieve metadata from an OData URL ending in .svc as list of lists.}
6 | \usage{
7 | odata_metadata_get(
8 | pid = get_default_pid(),
9 | fid = get_default_fid(),
10 | url = get_default_url(),
11 | un = get_default_un(),
12 | pw = get_default_pw(),
13 | retries = get_retries()
14 | )
15 | }
16 | \arguments{
17 | \item{pid}{The numeric ID of the project, e.g.: 2.
18 |
19 | Default: \code{\link{get_default_pid}}.
20 |
21 | Set default \code{pid} through \code{ru_setup(pid="...")}.
22 |
23 | See \code{vignette("Setup", package = "ruODK")}.}
24 |
25 | \item{fid}{The alphanumeric form ID, e.g. "build_Spotlighting-0-8_1559885147".
26 |
27 | Default: \code{\link{get_default_fid}}.
28 |
29 | Set default \code{fid} through \code{ru_setup(fid="...")}.
30 |
31 | See \code{vignette("Setup", package = "ruODK")}.}
32 |
33 | \item{url}{The ODK Central base URL without trailing slash.
34 |
35 | Default: \code{\link{get_default_url}}.
36 |
37 | Set default \code{url} through \code{ru_setup(url="...")}.
38 |
39 | See \code{vignette("Setup", package = "ruODK")}.}
40 |
41 | \item{un}{The ODK Central username (an email address).
42 | Default: \code{\link{get_default_un}}.
43 | Set default \code{un} through \code{ru_setup(un="...")}.
44 | See \code{vignette("Setup", package = "ruODK")}.}
45 |
46 | \item{pw}{The ODK Central password.
47 | Default: \code{\link{get_default_pw}}.
48 | Set default \code{pw} through \code{ru_setup(pw="...")}.
49 | See \code{vignette("Setup", package = "ruODK")}.}
50 |
51 | \item{retries}{The number of attempts to retrieve a web resource.
52 |
53 | This parameter is given to \code{\link[httr]{RETRY}(times = retries)}.
54 |
55 | Default: 3.}
56 | }
57 | \value{
58 | A nested list containing Edmx (dataset schema definition) and
59 | .attrs (Version).
60 | }
61 | \description{
62 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
63 | }
64 | \examples{
65 | \dontrun{
66 | # See vignette("setup") for setup and authentication options
67 | # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
68 |
69 | meta <- odata_metadata_get()
70 | listviewer::jsonedit(meta)
71 | }
72 | }
73 | \seealso{
74 | \url{https://docs.getodk.org/central-api-odata-endpoints/#metadata-document}
75 |
76 | Other odata-api:
77 | \code{\link{odata_service_get}()},
78 | \code{\link{odata_submission_get}()}
79 | }
80 | \concept{odata-api}
81 |
--------------------------------------------------------------------------------
/R/project_detail.R:
--------------------------------------------------------------------------------
1 | #' List all details of one project.
2 | #'
3 | #' While the API endpoint will return all details for one project,
4 | #' \code{\link{project_detail}} will fail with incorrect or missing
5 | #' authentication.
6 | #'
7 | #' `r lifecycle::badge("stable")`
8 | #'
9 | #' @template param-pid
10 | #' @template param-url
11 | #' @template param-auth
12 | #' @template param-retries
13 | #' @return A tibble with exactly one row for the project and all project
14 | #' metadata as columns as per ODK Central API docs.
15 | #' Column names are renamed from ODK's `camelCase` to `snake_case`.
16 | #' Values differ to values returned by ODK Central API:
17 | #'
18 | #' * archived: FALSE (if NULL) else TRUE
19 | #' * dates: NA if NULL
20 | # nolint start
21 | #' @seealso \url{https://docs.getodk.org/central-api-project-management/#getting-project-details}
22 | # nolint end
23 | #' @family project-management
24 | #' @export
25 | #' @examples
26 | #' \dontrun{
27 | #' # See vignette("setup") for setup and authentication options
28 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
29 | #'
30 | #' pd <- project_detail()
31 | #'
32 | #' pd %>%
33 | #' dplyr::select(-"verbs") %>%
34 | #' knitr::kable(.)
35 | #' }
36 | project_detail <- function(pid = get_default_pid(),
37 | url = get_default_url(),
38 | un = get_default_un(),
39 | pw = get_default_pw(),
40 | retries = get_retries()) {
41 | yell_if_missing(url, un, pw, pid = pid)
42 | httr::RETRY(
43 | "GET",
44 | httr::modify_url(url, path = glue::glue("v1/projects/{pid}")),
45 | httr::add_headers(
46 | "Accept" = "application/xml",
47 | "X-Extended-Metadata" = "true"
48 | ),
49 | httr::authenticate(un, pw),
50 | times = retries
51 | ) |>
52 | yell_if_error(url, un, pw) |>
53 | httr::content() %>%
54 | { # nolint
55 | tibble::tibble(
56 | id = .$id,
57 | name = .$name,
58 | forms = .$forms,
59 | app_users = .$appUsers,
60 | last_submission = ifelse(
61 | is.null(.$lastSubmission),
62 | NA_character_,
63 | .$lastSubmission
64 | ),
65 | created_at = .$createdAt,
66 | updated_at = ifelse(
67 | is.null(.$updatedAt),
68 | NA_character_,
69 | .$updatedAt
70 | ),
71 | archived = ifelse(
72 | is.null(.$archived),
73 | FALSE,
74 | TRUE
75 | ),
76 | verbs = list(.$verbs)
77 | )
78 | }
79 | }
80 |
81 | # usethis::use_test("project_detail") # nolint
82 |
--------------------------------------------------------------------------------
/R/project_list.R:
--------------------------------------------------------------------------------
1 | #' List all projects.
2 | #'
3 | #'
4 | #' While the API endpoint will return all projects,
5 | #' \code{\link{project_list}} will fail with incorrect or missing
6 | #' authentication.
7 | #'
8 | #' `r lifecycle::badge("stable")`
9 | #'
10 | #' @template param-url
11 | #' @template param-auth
12 | #' @template param-retries
13 | #' @template param-orders
14 | #' @template param-tz
15 | #' @return A tibble with one row per project and all project metadata
16 | #' as columns as per ODK Central API docs.
17 | # nolint start
18 | #' @seealso \url{https://docs.getodk.org/central-api-project-management/#listing-projects}
19 | # nolint end
20 | #' @family project-management
21 | #' @export
22 | #' @examples
23 | #' \dontrun{
24 | #' # See vignette("setup") for setup and authentication options
25 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
26 | #'
27 | #' pl <- project_list()
28 | #' knitr::kable(pl)
29 | #'
30 | #' # project_list returns a tibble
31 | #' class(pl)
32 | #' # > "tbl_df" "tbl" "data.frame"
33 | #'
34 | #' # columns are project metadata
35 | #' names(pl)
36 | #' # > "id" "name" "forms" "app_users" "created_at" "updated_at"
37 | #' # > "last_submission" "archived"
38 | #' }
39 | project_list <- function(url = get_default_url(),
40 | un = get_default_un(),
41 | pw = get_default_pw(),
42 | retries = get_retries(),
43 | orders = get_default_orders(),
44 | tz = get_default_tz()) {
45 | yell_if_missing(url, un, pw)
46 | httr::RETRY(
47 | "GET",
48 | httr::modify_url(url, path = glue::glue("v1/projects")),
49 | httr::add_headers(
50 | "Accept" = "application/xml",
51 | "X-Extended-Metadata" = "true"
52 | ),
53 | httr::authenticate(un, pw),
54 | times = retries
55 | ) %>%
56 | yell_if_error(., url, un, pw) %>%
57 | httr::content(.) %>%
58 | tibble::tibble(.) %>%
59 | tidyr::unnest_wider(".", names_repair = "universal") %>%
60 | # tidyr::unnest_wider(
61 | # "verbs",
62 | # names_repair = "universal", names_sep = "_"
63 | # ) %>%
64 | janitor::clean_names(.) %>%
65 | dplyr::mutate(
66 | dplyr::across(
67 | dplyr::contains("last_submission|created_at|updated_at|deleted_at"),
68 | ~ isodt_to_local(., orders = orders, tz = tz)
69 | )
70 | ) %>%
71 | {
72 | if ("archived" %in% names(.)) {
73 | dplyr::mutate(., archived = tidyr::replace_na(archived, FALSE))
74 | } else {
75 | .
76 | }
77 | }
78 | }
79 |
80 | # usethis::use_test("project_list") # nolint
81 |
--------------------------------------------------------------------------------
/R/attachment_link.R:
--------------------------------------------------------------------------------
1 | #' Prefix attachment columns from CSV export with a local attachment file path.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @param data_tbl The downloaded submissions from
6 | #' \code{\link{submission_export}} read into a `tibble` by
7 | #' \code{readr::read_csv}.
8 | #' @param form_schema The `form_schema` for the submissions.
9 | #' E.g. the output of `ruODK::form_schema()`.
10 | #' @param att_path A local path, default: "media" (as per .csv.zip export).
11 | #' Selected columns of the dataframe (containing attchment filenames) are
12 | #' prefixed with `att_path`, thus turning them into relative paths.
13 | #' @return The dataframe with attachment columns modified to contain relative
14 | #' paths to the downloaded attachment files.
15 | #' @export
16 | #' @family utilities
17 | #' @examples
18 | #' \dontrun{
19 | #' t <- tempdir()
20 | #' # See vignette("setup") for setup and authentication options
21 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
22 | #'
23 | #' # Predict filenames (with knowledge of form)
24 | #' fid <- get_default_fid()
25 | #' fid_csv <- fs::path(t, glue::glue("{fid}.csv"))
26 | #' fid_csv_tae <- fs::path(t, glue::glue("{fid}-taxon_encounter.csv"))
27 | #' fs <- form_schema()
28 | #'
29 | #' # Download the zip file
30 | #' se <- ruODK::submission_export(
31 | #' local_dir = t,
32 | #' overwrite = FALSE,
33 | #' verbose = TRUE
34 | #' )
35 | #'
36 | #' # Unpack the zip file
37 | #' f <- unzip(se, exdir = t)
38 | #' fs::dir_ls(t)
39 | #'
40 | #' # Prepend attachments with media/ to turn into relative file paths
41 | #' data_quadrat <- fid_csv %>%
42 | #' readr::read_csv(na = c("", "NA", "na")) %>%
43 | #' janitor::clean_names() %>%
44 | #' handle_ru_datetimes(fs) %>%
45 | #' attachment_link(fs)
46 | #' }
47 | attachment_link <- function(data_tbl,
48 | form_schema,
49 | att_path = "media") {
50 | # Find attachment columns
51 | # Caveat: if an attachment field has no submissions, it is dropped from data
52 | att_cols <- form_schema %>%
53 | dplyr::filter(type == "binary") %>%
54 | magrittr::extract2("ruodk_name") %>%
55 | intersect(names(data_tbl))
56 |
57 | data_tbl %>%
58 | dplyr::mutate_at(
59 | dplyr::vars(dplyr::all_of(att_cols)),
60 | ~ fs::path(att_path, .)
61 | )
62 | }
63 |
64 | # nolint start
65 | # usethis::use_test("attachment_link")
66 | # usethis::use_test("submission_export")
67 | # covr::file_coverage("R/attachment_link.R",
68 | # test_files = c("tests/testthat/test-attachment_link.R",
69 | # "tests/testthat/test-submission_export.R"))
70 | # nolint end
71 |
--------------------------------------------------------------------------------
/R/handle_ru_geopoints.R:
--------------------------------------------------------------------------------
1 | #' Split all geopoints of a submission tibble into their components.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @details For a given tibble of submissions, find all columns which are listed
6 | #' in the form schema as type \code{geopoint}, and extract their components.
7 | #' Extracted components are longitude (X), latitude (Y), altitude (Z, where
8 | #' given), and accuracy (M, where given).
9 | #'
10 | #' The original column is retained to allow parsing into other spatially
11 | #' enabled formats.
12 | #' @param data Submissions rectangled into a tibble. E.g. the output of
13 | #' ```
14 | #' ruODK::odata_submission_get(parse = FALSE) %>%
15 | #' ruODK::odata_submission_rectangle()
16 | #' ```
17 | #' @param form_schema The `form_schema` for the submissions.
18 | #' E.g. the output of `ruODK::form_schema()`.
19 | #' @template param-wkt
20 | #' @template param-verbose
21 | #' @return The submissions tibble with all geopoints retained in their original
22 | #' format, plus columns of their coordinate components as provided by
23 | #' \code{\link{split_geopoint}}.
24 | #' @export
25 | #' @family utilities
26 | #' @examples
27 | #' library(magrittr)
28 | #' data("geo_fs")
29 | #' data("geo_gj_raw")
30 | #' data("geo_wkt_raw")
31 | #'
32 | #' # GeoJSON
33 | #' geo_gj_parsed <- geo_gj_raw %>%
34 | #' ruODK::odata_submission_rectangle(form_schema = geo_fs) %>%
35 | #' ruODK::handle_ru_geopoints(form_schema = geo_fs, wkt = FALSE)
36 | #'
37 | #' dplyr::glimpse(geo_gj_parsed)
38 | #'
39 | #' # WKT
40 | #' geo_wkt_parsed <- geo_wkt_raw %>%
41 | #' ruODK::odata_submission_rectangle(form_schema = geo_fs) %>%
42 | #' ruODK::handle_ru_geopoints(form_schema = geo_fs, wkt = TRUE)
43 | #'
44 | #' dplyr::glimpse(geo_wkt_parsed)
45 | handle_ru_geopoints <- function(data,
46 | form_schema,
47 | wkt = FALSE,
48 | verbose = get_ru_verbose()) {
49 | # Find Geopoint columns
50 | geo_cols <- form_schema %>%
51 | dplyr::filter(type == "geopoint") %>%
52 | magrittr::extract2("ruodk_name") %>%
53 | intersect(names(data))
54 |
55 | x <- paste(geo_cols, collapse = ", ") # nolint
56 | "Found geopoints: {x}." %>%
57 | glue::glue() %>%
58 | ru_msg_info(verbose = verbose)
59 |
60 | for (colname in geo_cols) {
61 | if (colname %in% names(data)) {
62 | "Parsing {colname}..." %>%
63 | glue::glue() %>%
64 | ru_msg_info(verbose = verbose)
65 | data <-
66 | data %>% split_geopoint(as.character(colname), wkt = wkt)
67 | }
68 | }
69 |
70 | data
71 | }
72 |
73 | # usethis::use_test("handle_ru_geopoints") # nolint
74 |
--------------------------------------------------------------------------------
/R/submission_detail.R:
--------------------------------------------------------------------------------
1 | #' Show metadata for one submission.
2 | #'
3 | #' `r lifecycle::badge("stable")`
4 | #'
5 | #' @template param-iid
6 | #' @template param-pid
7 | #' @template param-fid
8 | #' @template param-url
9 | #' @template param-auth
10 | #' @template param-retries
11 | #' @return A nested list of submission metadata.
12 | # nolint start
13 | #' @seealso \url{https://docs.getodk.org/central-api-submission-management/#getting-submission-metadata}
14 | # nolint end
15 | #' @family submission-management
16 | #' @export
17 | #' @examples
18 | #' \dontrun{
19 | #' # See vignette("setup") for setup and authentication options
20 | #' # ruODK::ru_setup(svc = "....svc", un = "me@email.com", pw = "...")
21 | #'
22 | #' sl <- submission_list()
23 | #'
24 | #' sub <- submission_detail(sl$instance_id[[1]])
25 | #'
26 | #' # The details for one submission return exactly one row
27 | #' nrow(sub)
28 | #' # > 1
29 | #'
30 | #' # The columns are metadata about the submission and the submitter
31 | #' names(sub)
32 | #' # > "instance_id" "submitter_id" "submitter_type" "submitter_display_name"
33 | #' # > "submitter_created_at" "device_id" "created_at"
34 | #' }
35 | submission_detail <- function(iid,
36 | pid = get_default_pid(),
37 | fid = get_default_fid(),
38 | url = get_default_url(),
39 | un = get_default_un(),
40 | pw = get_default_pw(),
41 | retries = get_retries()) {
42 | yell_if_missing(url, un, pw, pid = pid, fid = fid)
43 | httr::RETRY(
44 | "GET",
45 | httr::modify_url(
46 | url,
47 | path = glue::glue(
48 | "v1/projects/{pid}/forms/",
49 | "{URLencode(fid, reserved = TRUE)}/submissions/{iid}"
50 | )
51 | ),
52 | httr::add_headers(
53 | "Accept" = "application/json; extended",
54 | "X-Extended-Metadata" = "true"
55 | ),
56 | httr::authenticate(un, pw),
57 | times = retries
58 | ) %>%
59 | yell_if_error(., url, un, pw) %>%
60 | httr::content(.) %>%
61 | { # nolint
62 | tibble::tibble(
63 | instance_id = .$instanceId,
64 | submitter_id = .$submitter$id,
65 | submitter = .$submitter$displayName,
66 | created_at = readr::parse_datetime(
67 | .$createdAt,
68 | format = "%Y-%m-%dT%H:%M:%OSZ"
69 | ),
70 | updated_at = ifelse(
71 | is.null(.$updatedAt),
72 | NA,
73 | readr::parse_datetime(
74 | .$updatedAt,
75 | format = "%Y-%m-%dT%H:%M:%OSZ"
76 | )
77 | )
78 | )
79 | }
80 | }
81 |
82 | # usethis::use_test("submission_detail") # nolint
83 |
--------------------------------------------------------------------------------