-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2331cee
Showing
41 changed files
with
1,290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Package: feltr | ||
Title: Access the Felt API | ||
Version: 0.0.2 | ||
Authors@R: | ||
person(given = "Christopher T.", | ||
family = "Kenny", | ||
role = c("aut", "cre"), | ||
email = "christopherkenny@fas.harvard.edu", | ||
comment = c(ORCID = "0000-0002-9386-6860")) | ||
Description: Upload, download, and edit internet maps with the Felt API | ||
(<https://feltmaps.notion.site/Felt-Public-API-reference-c01e0e6b0d954a678c608131b894e8e1>). | ||
Allows users to create new maps, edit existing maps, and extract data. | ||
Provides tools for working with layers, which represent geographic data, and elements, | ||
which are interactive annotations. Spatial data accessed from the API is | ||
transformed to work with 'sf'. | ||
License: MIT + file LICENSE | ||
Encoding: UTF-8 | ||
RoxygenNote: 7.2.3 | ||
Imports: cli, curl, fs, geojsonsf, httr2, jsonlite, purrr, rlang, sf, | ||
stringr, tibble | ||
URL: http://christophertkenny.com/feltr/ | ||
Suggests: httptest2, testthat (>= 3.0.0) | ||
Config/testthat/edition: 3 | ||
NeedsCompilation: no | ||
Packaged: 2023-07-05 18:23:29 UTC; chris | ||
Author: Christopher T. Kenny [aut, cre] | ||
(<https://orcid.org/0000-0002-9386-6860>) | ||
Maintainer: Christopher T. Kenny <christopherkenny@fas.harvard.edu> | ||
Repository: CRAN | ||
Date/Publication: 2023-07-06 14:00:05 UTC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
YEAR: 2023 | ||
COPYRIGHT HOLDER: feltr authors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
a85119eb8b0120e9b55e418813d7da1e *DESCRIPTION | ||
616833dab9c77074aa2657b112f9b006 *LICENSE | ||
49c6d2e68f787871b5180e2581a2a751 *NAMESPACE | ||
fc8c3f4aba17dc5e5349f19f403e602b *NEWS.md | ||
f889f13f4f86101b68895561b001531b *R/add.R | ||
8fcd2188d566f0fb75a6b2a1b6c0bb44 *R/api_url.R | ||
664bc1bbc9a7502133332dac60e4601c *R/create.R | ||
f0e5a27a0faeae409b2a93dcdea14074 *R/delete.R | ||
f278c9a0af3fe63ee62f618ab0fe247e *R/felt_key.R | ||
ce4445d76f667ef40162fc32d37386c8 *R/finish_upload.R | ||
d14cf3cd69beb12710970a876e364e31 *R/helpers.R | ||
237763b046a5380d44a6dc0bfad7a468 *R/map.R | ||
358003bfcd9a3512bb17f92d559bb7dd *R/map_elements.R | ||
ecbdaa8a4d3478635cc95a1b4e2bf789 *R/proc.R | ||
02478d6ea773f7ded0c72e56316e92cf *R/user.R | ||
c8bee16add2c0cd8fb803b73fb55ea2b *README.md | ||
dcafe3a9c7fc22b1830fe8c5bebde3a5 *inst/httptest2/redact.R | ||
47024474bcdf50c357e673031273e3f4 *inst/towns.geojson | ||
a0b9edb7109d774d7368f226d23c6d7c *man/felt_add_map_layers.Rd | ||
65e462d0d60782227fb1d5dbcc4b281b *man/felt_add_map_layers_url.Rd | ||
8a10e9cbd4dec730f65436b1f5b167da *man/felt_create_map.Rd | ||
1be2c7cfda80ada35bfcbf369d93c619 *man/felt_delete_map.Rd | ||
14471f60025ab3f70783abf1e3d688c7 *man/felt_delete_map_layer.Rd | ||
7b6eeb77674fb869dfe52b1e77fe38e3 *man/felt_finish_upload.Rd | ||
76f65dbdd6623811448fbae598d220b8 *man/felt_get_map.Rd | ||
c5efa2eac855c704a6a15e8eb93834bf *man/felt_get_map_elements.Rd | ||
ac6a20b3d829e4dd4ef3040af028a3be *man/felt_get_user.Rd | ||
d0014c782bb08375032c800c376d3d00 *man/figures/logo.png | ||
22e89a3aad1cc54a3f97c521987c2633 *man/key.Rd | ||
06ac6d486f81c291323f4aa8f77916a5 *man/set_felt_key.Rd | ||
e09dfa175bba9ede03319f774ddcae22 *tests/testthat.R | ||
ff3b353b55b6eaa57bec2ed603745880 *tests/testthat/add.R | ||
b013980eae16bb9f943c1ff2f6475354 *tests/testthat/setup.R | ||
121fdc6280a720c2a55c6e84a61d5e97 *tests/testthat/t/create/felt.com/api/v1/maps-b1286e-POST.json | ||
058ce516e115d1b8efb611a80215afdd *tests/testthat/t/get_elements/felt.com/api/v1/maps/TBI8sDkmQjuK2GX9CSiHiUA/elements.R | ||
661ee4e4456fd7998790598934f03259 *tests/testthat/t/user/felt.com/api/v1/user.json | ||
f060f0dae7f8431313ebd4231f9c034d *tests/testthat/test-create.R | ||
f8f9cbf6b4b8f908ef0caa13a05b1b7c *tests/testthat/test-map.R | ||
b3f9a1162626b1a99d09ca500f51c96b *tests/testthat/test-map_elements.R | ||
d3cd84c5695fa3671622c9d9efe6f8f3 *tests/testthat/test-user.R |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Generated by roxygen2: do not edit by hand | ||
|
||
export(felt_add_map_layers) | ||
export(felt_add_map_layers_url) | ||
export(felt_create_map) | ||
export(felt_delete_map) | ||
export(felt_delete_map_layer) | ||
export(felt_finish_upload) | ||
export(felt_get_map) | ||
export(felt_get_map_elements) | ||
export(felt_get_map_geojson) | ||
export(felt_get_map_layers) | ||
export(felt_get_map_sf) | ||
export(felt_get_user) | ||
export(get_felt_key) | ||
export(has_felt_key) | ||
export(set_felt_key) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# feltr 0.0.2 | ||
|
||
* Adds path arguments to `felt_set_key()` and `felt_get_map_sf()` to ensure compliance with CRAN policies in writing files. | ||
|
||
# feltr 0.0.1 | ||
|
||
* Added a `NEWS.md` file to track changes to the package. | ||
* Initial package with support for API features as of July 2023. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#' Add Layers to Existing Map | ||
#' | ||
#' @param map_id map identifier from url, from `https://felt.com/map/Readable-Name-map_id` | ||
#' @param file_names Files to include | ||
#' @param name Name of the layer | ||
#' @param fill_color Color to fill shape with, typically a hexcode. Defaults to `NULL`.v | ||
#' @param stroke_color Color to outline shape with, typically a hexcode. Defaults to `NULL`. | ||
#' | ||
#' @return a string with the id for the created layer | ||
#' @export | ||
#' | ||
#' @examplesIf has_felt_key() | ||
#' felt_add_map_layers(map_id = 'Rockland-2024-Districts-TBI8sDkmQjuK2GX9CSiHiUA', | ||
#' file_names = fs::path_package('feltr', 'towns.geojson'), | ||
#' name = 'Towns') | ||
felt_add_map_layers <- function(map_id, name = NULL, file_names = NULL, | ||
fill_color = NULL, stroke_color = NULL) { | ||
# don't support webhooks for now | ||
webhook_url = NULL | ||
|
||
body <- list( | ||
file_names = list(fs::path_file(file_names)), | ||
name = name, | ||
fill_color = fill_color, | ||
stroke_color = stroke_color, | ||
webhook_url = webhook_url | ||
) |> | ||
purrr::discard(is.null) | ||
|
||
req <- httr2::request(base_url = api_url()) |> | ||
httr2::req_url_path_append('maps', map_id, 'layers') |> | ||
httr2::req_auth_bearer_token(token = get_felt_key()) |> | ||
httr2::req_body_json(body, auto_unbox = TRUE) | ||
|
||
upload_info <- req |> | ||
httr2::req_perform() |> | ||
httr2::resp_body_json() | ||
|
||
|
||
args <- upload_info |> | ||
purrr::pluck('data', 'attributes', 'presigned_attributes') | ||
upload <- upload_info |> | ||
purrr::pluck('data', 'attributes', 'url') |> | ||
httr2::request() |> | ||
req_injected(!!!args, file = curl::form_file(file_names)) | ||
|
||
out <- upload |> | ||
httr2::req_perform() | ||
|
||
finish_upload <- felt_finish_upload(map_id) | ||
|
||
upload_info$data$attributes$layer_id | ||
} | ||
|
||
#' Add Layers to Existing Map from URL | ||
#' | ||
#' See [Felt "Upload Anything" documentation](https://feltmaps.notion.site/b26d739e80184127872faa923b55d232?pvs=25#3e37f06bc38c4971b435fbff2f4da6cb) | ||
#' for detailed examples of potential URLs. | ||
#' | ||
#' @param map_id map identifier from url, from `https://felt.com/map/Readable-Name-map_id` | ||
#' @param url Link to layer to include | ||
#' @param name Name of the layer | ||
#' | ||
#' @return a [tibble::tibble] for the created layer | ||
#' @export | ||
#' | ||
#' @examplesIf has_felt_key() | ||
#' # split the URL for length reasons | ||
#' url <- paste0( | ||
#' 'https://www.rocklandgis.com/portal/sharing/rest/', | ||
#' 'content/items/73fc78cb0fb04580b4788937fe5ee697/data' | ||
#' ) | ||
#' felt_add_map_layers_url( | ||
#' map_id = 'Rockland-2024-Districts-TBI8sDkmQjuK2GX9CSiHiUA', | ||
#' url = url, | ||
#' name = 'Parks') | ||
felt_add_map_layers_url <- function(map_id, url, name = NULL) { | ||
|
||
body <- list( | ||
layer_url = url, | ||
name = name | ||
) |> | ||
purrr::discard(is.null) | ||
|
||
req <- httr2::request(base_url = api_url()) |> | ||
httr2::req_url_path_append('maps', map_id, 'layers', 'url_import') |> | ||
httr2::req_auth_bearer_token(token = get_felt_key()) |> | ||
httr2::req_body_json(body, auto_unbox = TRUE) | ||
|
||
out <- req |> | ||
httr2::req_perform() |> | ||
httr2::resp_body_json() | ||
|
||
tibble::tibble( | ||
name = out$data$attributes$name, | ||
status = out$data$attributes$status, | ||
progress = out$data$attributes$progress, | ||
id = out$data$id, | ||
type = out$data$type, | ||
relationships = out$data$relationships$datasets$data | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
api_url <- function() { | ||
'https://felt.com/api/v1' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#' Create a new map | ||
#' | ||
#' @param title Title to use for the map. Defaults to `NULL`. | ||
#' @param basemap Basemap for the new map. Defaults to `NULL`. Can be a URL or color hex code | ||
#' @param layer_urls vector of URLs to generate layers in map. Defaults to `NULL`. | ||
#' @param lat latitude to center the map. Defaults to `NULL`. | ||
#' @param lon longitude to center the map. Defaults to `NULL` | ||
#' @param zoom zoom level to initialize the map with. | ||
#' | ||
#' @return a [tibble::tibble] for the new map | ||
#' @export | ||
#' | ||
#' @examplesIf has_felt_key() | ||
#' felt_create_map(title = 'feltr example') | ||
felt_create_map <- function(title = NULL, basemap = NULL, layer_urls = NULL, | ||
lat = NULL, lon = NULL, zoom = NULL) { | ||
if (!is.null(layer_urls)) layer_urls <- as.list(layer_urls) | ||
|
||
body <- list( | ||
title = title, | ||
basemap = basemap, | ||
layer_urls = layer_urls, | ||
lat = lat, | ||
lon = lon, | ||
zoom = zoom | ||
) |> | ||
purrr::discard(is.null) | ||
|
||
req <- httr2::request(base_url = api_url()) |> | ||
httr2::req_url_path_append('maps') |> | ||
httr2::req_auth_bearer_token(token = get_felt_key()) |> | ||
httr2::req_body_json(body, auto_unbox = TRUE) | ||
|
||
req |> | ||
httr2::req_perform() |> | ||
httr2::resp_body_json() |> | ||
proc_map() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#' Delete Layer from an Existing Map | ||
#' | ||
#' @param map_id map identifier from url, from `https://felt.com/map/Readable-Name-map_id` | ||
#' @param layer_id layer identifier, as returned by `felt_get_map_layers()` or `felt_add_map_layers()` | ||
#' | ||
#' @return response code | ||
#' @export | ||
#' | ||
#' @examplesIf has_felt_key() | ||
#' layer <- felt_add_map_layers('TBI8sDkmQjuK2GX9CSiHiUA', | ||
#' 'test', fs::path_package('feltr', 'towns.geojson')) | ||
#' felt_delete_map_layer(map_id = 'Rockland-2024-Districts-TBI8sDkmQjuK2GX9CSiHiUA', | ||
#' layer) | ||
felt_delete_map_layer <- function(map_id, layer_id) { | ||
req <- httr2::request(base_url = api_url()) |> | ||
httr2::req_url_path_append('maps', map_id, 'layers', layer_id) |> | ||
httr2::req_auth_bearer_token(token = get_felt_key()) |> | ||
httr2::req_method(method = 'DELETE') | ||
|
||
req |> | ||
httr2::req_perform() |> | ||
httr2::resp_status() | ||
} | ||
|
||
#' Delete an existing map | ||
#' | ||
#' @param map_id map identifier from url, from `https://felt.com/map/Readable-Name-map_id` | ||
#' | ||
#' @return response code | ||
#' @export | ||
#' | ||
#' @examplesIf has_felt_key() | ||
#' map <- felt_create_map(title = 'feltr example') | ||
#' felt_delete_map(map_id = map$id) | ||
felt_delete_map <- function(map_id) { | ||
req <- httr2::request(base_url = api_url()) |> | ||
httr2::req_url_path_append('maps', map_id) |> | ||
httr2::req_auth_bearer_token(token = get_felt_key()) |> | ||
httr2::req_method(method = 'DELETE') | ||
|
||
req |> | ||
httr2::req_perform() |> | ||
httr2::resp_status() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#' Check or Get Felt API Key | ||
#' | ||
#' @return logical if `has`, key if `get` | ||
#' @export | ||
#' | ||
#' @name key | ||
#' | ||
#' @examples | ||
#' has_felt_key() | ||
has_felt_key <- function() { | ||
Sys.getenv('FELT_KEY') != '' | ||
} | ||
|
||
#' @rdname key | ||
#' @export | ||
get_felt_key <- function() { | ||
key <- Sys.getenv('FELT_KEY') | ||
|
||
# if (key == '') { | ||
# cli::cli_abort('Must set a key as {.val FELT_KEY}.') | ||
# } | ||
key | ||
} | ||
|
||
#' Add Entry to Renviron | ||
#' | ||
#' Adds Felt API key to .Renviron. | ||
#' | ||
#' @param key Character. API key to add to add. | ||
#' @param overwrite Defaults to FALSE. Boolean. Should existing `FELT_KEY` in Renviron be overwritten? | ||
#' @param install Defaults to FALSE. Boolean. Should this be added to an environment file, `r_env`? | ||
#' @param r_env Path to install to if `install` is `TRUE`. | ||
#' | ||
#' @return key, invisibly | ||
#' @export | ||
#' | ||
#' @examples | ||
#' example_env <- tempfile(fileext = '.Renviron') | ||
#' set_felt_key('1234', r_env = example_env) | ||
#' # r_env should likely be: file.path(Sys.getenv('HOME'), '.Renviron') | ||
set_felt_key <- function(key, overwrite = FALSE, install = FALSE, | ||
r_env = NULL) { | ||
if (missing(key)) { | ||
cli::cli_abort('Input {.arg key} cannot be missing.') | ||
} | ||
name <- 'FELT_KEY' | ||
|
||
key <- list(key) | ||
names(key) <- name | ||
|
||
if (install) { | ||
|
||
if (is.null(r_env)) { | ||
r_env <- file.path(Sys.getenv('HOME'), '.Renviron') | ||
if (interactive()) { | ||
utils::askYesNo(paste0('Install to', r_env, '?')) | ||
} else { | ||
cli::cli_abort(c('No path set and not run interactively.', | ||
i = 'Rerun with {.arg r_env} set, possibly to {.file {r_env}}')) | ||
} | ||
} | ||
|
||
if (!file.exists(r_env)) { | ||
file.create(r_env) | ||
} | ||
|
||
lines <- readLines(r_env) | ||
newline <- paste0(name, "='", key, "'") | ||
|
||
exists <- stringr::str_detect(lines, paste0(name, '=')) | ||
|
||
if (any(exists)) { | ||
if (sum(exists) > 1) { | ||
cli::cli_abort('Multiple entries in .Renviron found.\nEdit manually with {.fn usethis::edit_r_environ}.') | ||
} | ||
|
||
if (overwrite) { | ||
lines[exists] <- newline | ||
writeLines(lines, r_env) | ||
do.call(Sys.setenv, key) | ||
} else { | ||
cli::cli_inform('{.arg FELT_KEY} already exists in .Renviron. \nEdit manually with {.fn usethis::edit_r_environ} or set {.code overwrite = TRUE}.') | ||
} | ||
} else { | ||
lines[length(lines) + 1] <- newline | ||
writeLines(lines, r_env) | ||
do.call(Sys.setenv, key) | ||
} | ||
}# else { | ||
# do.call(Sys.setenv, key) | ||
#} | ||
|
||
invisible(key) | ||
} |
Oops, something went wrong.