diff --git a/.Rbuildignore b/.Rbuildignore index c55dadd..1389371 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -7,6 +7,7 @@ README.html ^\.github$ ^\.lintr$ ^\.pre-commit-config\.yaml$ +^\.venv docs/ pkgdown test.R diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 9f70244..4cc0126 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.3 +current_version = 0.1.4 commit = True tag = True diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 5516aaa..ca46204 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -49,11 +49,6 @@ jobs: - name: Install package run: R CMD INSTALL . - - name: Check test coverage - run: | - covr::codecov() - shell: Rscript {0} - - name: Build {pkgdown} documentation run: | git config --local user.email "actions@github.com" diff --git a/.gitignore b/.gitignore index 5945c27..37ed5a1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ README.html clockify*.tar.gz clockify*.tgz docs/ +.venv/ diff --git a/DESCRIPTION b/DESCRIPTION index 1805490..a713181 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,17 +1,13 @@ Package: clockify Type: Package Title: A Wrapper for the 'Clockify' API -Version: 0.1.3 +Version: 0.1.4 Authors@R: c(person(given = c("Andrew", "B."), family = "Collier", role = c("aut", "cre"), - email = "andrew@fathomdata.dev"), - person(given = "Megan", - family = "Beckett", - role = "ctb", - email = "megan@fathomdata.dev")) -Description: A wrapper for the Clockify API , making it possible to query, insert and update time keeping data. + email = "andrew.b.collier@gmail.com")) +Description: A wrapper for the Clockify API , making it possible to query, insert and update time keeping data. License: GPL-3 Encoding: UTF-8 LazyData: true @@ -24,8 +20,10 @@ Imports: janitor, logger, lubridate, + methods, purrr, rlist, + stringi, tibble, tidyr Suggests: diff --git a/NAMESPACE b/NAMESPACE index e7d4622..aaa69f7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -72,6 +72,8 @@ import(janitor) import(logger) import(lubridate) import(purrr) +import(stringi) import(tibble) import(tidyr) +importFrom(methods,is) importFrom(stats,setNames) diff --git a/R/client.R b/R/client.R index b790f31..0d75621 100644 --- a/R/client.R +++ b/R/client.R @@ -1,3 +1,11 @@ +#' Parameters for client functions +#' +#' @name client-parameters +#' +#' @param client_id Client ID +#' @param concise Generate concise output +NULL + parse_client <- function(client, concise = TRUE) { client <- client %$% tibble( @@ -19,7 +27,7 @@ parse_client <- function(client, concise = TRUE) { #' Get clients #' -#' @inheritParams users +#' @inheritParams client-parameters #' #' @return A data frame with one record per client. #' @export @@ -39,7 +47,7 @@ clients <- function(concise = TRUE) { #' Get client #' -#' @param client_id Client ID +#' @inheritParams client-parameters #' #' @return A data frame with one record per client #' @export @@ -51,9 +59,9 @@ clients <- function(concise = TRUE) { client <- function(client_id, concise = TRUE) { path <- sprintf("/workspaces/%s/clients/%s", workspace(), client_id) - clockify:::GET(path) %>% + GET(path) %>% content() %>% - clockify:::parse_client(concise = concise) + parse_client(concise = concise) } #' Add a new client to workspace @@ -61,6 +69,7 @@ client <- function(client_id, concise = TRUE) { #' @inheritParams users #' #' @param name Client name +#' @inheritParams client-parameters #' #' @return A data frame with one row per record. #' @export @@ -81,7 +90,7 @@ client_create <- function(name, concise = TRUE) { #' Update a client #' -#' @param client_id Client ID +#' @inheritParams client-parameters #' @param name Client name #' @param note Note about client #' @param archived Whether or not client is archived diff --git a/R/clockify.R b/R/clockify.R index 3cccf21..f1267fc 100644 --- a/R/clockify.R +++ b/R/clockify.R @@ -7,7 +7,9 @@ #' @import anytime #' @import lubridate #' @import tibble +#' @import stringi #' @importFrom stats setNames +#' @importFrom methods is NULL BASE_PATH <- "https://api.clockify.me/api/v1" @@ -15,6 +17,7 @@ REPORTS_BASE_PATH <- "https://reports.api.clockify.me/v1" globalVariables( c( + "%$%", ".", "address", "amount", @@ -32,13 +35,17 @@ globalVariables( "error", "fields", "filters", + "fixed_date", "groupOne", "hourly_rate", + "is_public", + "link", "memberships", "name", "project_color", "project_id", "public", + "report_author", "start", "status", "template", @@ -50,9 +57,12 @@ globalVariables( "time_end", "time_entry_id", "time_start", + "type", "user_id", "user_ids", "user_name", + "visible_to_users", + "visible_to_user_groups", "workspace_id", "workspaceId" ) diff --git a/R/http.R b/R/http.R index 5edbb61..9357275 100644 --- a/R/http.R +++ b/R/http.R @@ -18,7 +18,7 @@ check_response <- function(response) { postfields <- response$request$options$postfields - if (!is.null(postfields) && class(postfields) == "raw") { + if (!is.null(postfields) && is(postfields, "raw")) { log_debug("body: {rawToChar(postfields)}") } log_error("message: {content(response)$message}") diff --git a/R/reports-shared.R b/R/reports-shared.R index 5cbc8ba..6f25587 100644 --- a/R/reports-shared.R +++ b/R/reports-shared.R @@ -1,20 +1,43 @@ EMPTY_SHARED_REPORTS <- tibble( shared_report_id = character(), + workspace_id = character(), + user_id = character(), report_author = character(), name = character(), link = character(), visible_to_users = logical(), + visible_to_user_groups = logical(), fixed_date = logical(), type = character(), - visible_to_user_groups = logical(), + filter = logical(), is_public = logical() ) parse_shared_report_list <- function(reports) { - tibble(reports) %>% + reports <- tibble(reports) %>% unnest_wider(reports) %>% - clean_names() %>% - select(shared_report_id = id, everything()) + clean_names() + + if (!("report_author" %in% names(reports))) reports$report_author <- NA + if (!("link" %in% names(reports))) reports$link <- NA + if (!("workspace_id" %in% names(reports))) reports$workspace_id <- NA + if (!("user_id" %in% names(reports))) reports$user_id <- NA + if (!("filter" %in% names(reports))) reports$filter <- NA + + reports %>% select( + shared_report_id = id, + workspace_id, + user_id, + report_author, + name, + link, + visible_to_users, + visible_to_user_groups, + fixed_date, + type, + filter, + is_public + ) } parse_shared_report <- function(report) { diff --git a/R/user.R b/R/user.R index c755449..87629a4 100644 --- a/R/user.R +++ b/R/user.R @@ -53,6 +53,10 @@ simplify_membership <- function(membership) { } else { m$hourlyRate <- list(as_tibble(m$hourlyRate)) } + if (is.null(m$costRate)) { + } else { + m$costRate <- list(as_tibble(m$costRate)) + } m }) %>% clean_names() diff --git a/R/workspace.R b/R/workspace.R index 52f2a80..6b8e192 100644 --- a/R/workspace.R +++ b/R/workspace.R @@ -3,6 +3,7 @@ unpack_workspace <- function(workspace) { workspace$featureSubscriptionType <- NULL workspace$workspaceSettings <- NULL workspace$hourlyRate <- NULL + workspace$costRate <- NULL workspace$memberships <- list(simplify_membership(workspace$memberships)) diff --git a/README.Rmd b/README.Rmd index c62a293..0bd2222 100644 --- a/README.Rmd +++ b/README.Rmd @@ -17,10 +17,10 @@ library(dplyr) [![CRAN status](https://www.r-pkg.org/badges/version/clockify)](https://cran.r-project.org/package=clockify) -[![Codecov test coverage](https://img.shields.io/codecov/c/github/datawookie/clockify.svg)](https://codecov.io/github/datawookie/clockify) +[![Codecov test coverage](https://img.shields.io/codecov/c/github/datawookie/clockify.svg)](https://app.codecov.io/github/datawookie/clockify) [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html) -An R wrapper around the [Clockify API](https://clockify.me/developers-api). +An R wrapper around the [Clockify API](https://docs.clockify.me/). The documentation for `{clockify}` is hosted at https://datawookie.github.io/clockify/. diff --git a/README.md b/README.md index faa15fd..30c893f 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,11 @@ [![CRAN status](https://www.r-pkg.org/badges/version/clockify)](https://cran.r-project.org/package=clockify) [![Codecov test -coverage](https://img.shields.io/codecov/c/github/datawookie/clockify.svg)](https://codecov.io/github/datawookie/clockify) +coverage](https://img.shields.io/codecov/c/github/datawookie/clockify.svg)](https://app.codecov.io/github/datawookie/clockify) [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html) -An R wrapper around the [Clockify -API](https://clockify.me/developers-api). +An R wrapper around the [Clockify API](https://docs.clockify.me/). The documentation for `{clockify}` is hosted at . @@ -65,7 +64,7 @@ workspaces() # A tibble: 3 × 3 workspace_id name memberships - 1 5ef46294df73063139f60bfc Fathom Data + 1 5ef46294df73063139f60bfc Fathom Data 2 61343c45ab05e02be2c8c1fd Personal 3 630c61ba9c3a3c3112812332 {clockify} sandbox @@ -86,9 +85,9 @@ user() ``` # A tibble: 1 × 3 - user_id user_name status - - 1 5f227e0cd7176a0e6e754409 Andrew ACTIVE + user_id user_name status + + 1 5f227e0cd7176a0e6e754409 Andrew Collier ACTIVE Get a list of users. @@ -97,13 +96,13 @@ users() ``` # A tibble: 5 × 3 - user_id user_name status - - 1 5f227e0cd7176a0e6e754409 Andrew ACTIVE - 2 630f17f04a05b20faf7e0afc Bob Smith ACTIVE - 3 630f16ab90cfd878937a7997 NOT_REGISTERED - 4 630f1cb9cb18da61cfd58659 Carol Brown PENDING_EMAIL_VERIFICATION - 5 630f15d3b59c366b0e3ae2e6 Alice Jones ACTIVE + user_id user_name status + + 1 5f227e0cd7176a0e6e754409 Andrew Collier ACTIVE + 2 630f17f04a05b20faf7e0afc Bob Smith ACTIVE + 3 630f16ab90cfd878937a7997 NOT_REGISTERED + 4 630f1cb9cb18da61cfd58659 Carol Brown PENDING_EMAIL_VERIFICATION + 5 630f15d3b59c366b0e3ae2e6 Alice Jones ACTIVE ## Clients @@ -127,12 +126,11 @@ projects() ``` # A tibble: 3 × 5 - project_id project_name client_id billa…¹ archi…² - - 1 632a94f8d801fa1178d366b8 test TRUE FALSE - 2 630ce53290cfd8789366fd49 {clockify} 63a55695db26c25e9d4e2d02 TRUE FALSE - 3 630ce53cb59c366b0e27743f {emayili} 63a55695db26c25e9d4e2d02 TRUE FALSE - # … with abbreviated variable names ¹​billable, ²​archived + project_id project_name client_id billable archived + + 1 632a94f8d801fa1178d366b8 test TRUE FALSE + 2 630ce53290cfd8789366fd49 {clockify} 63a55695db26c25e9d4e2… TRUE FALSE + 3 630ce53cb59c366b0e27743f {emayili} 63a55695db26c25e9d4e2… TRUE FALSE ## Time Entries @@ -167,7 +165,7 @@ Check on the ID for this new time entry. prepare_cran_entry$time_entry_id ``` - [1] "63b1d732f19c8f67dc9d0973" + [1] "64f21f2ad397e5503bef3bb4" Confirm that it has been inserted. @@ -179,7 +177,7 @@ time_entries(concise = FALSE) %>% # A tibble: 1 × 4 time_entry_id description time_start time_end - 1 63b1d732f19c8f67dc9d0973 Prepare for … 2021-08-30 08:00:00 2021-08-30 10:30:00 + 1 64f21f2ad397e5503bef3bb4 Prepare for … 2021-08-30 08:00:00 2021-08-30 10:30:00 ### Delete Time Entry @@ -197,8 +195,8 @@ time_entries(concise = FALSE) %>% ``` # A tibble: 0 × 4 - # … with 4 variables: time_entry_id , description , - # time_start , time_end + # ℹ 4 variables: time_entry_id , description , time_start , + # time_end ## Endpoints diff --git a/inst/WORDLIST b/inst/WORDLIST index 5bcf262..c9582ac 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -17,6 +17,7 @@ downlit dplyr fathomdata github +gmail https httr io diff --git a/man/client-parameters.Rd b/man/client-parameters.Rd new file mode 100644 index 0000000..3924705 --- /dev/null +++ b/man/client-parameters.Rd @@ -0,0 +1,13 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/client.R +\name{client-parameters} +\alias{client-parameters} +\title{Parameters for client functions} +\arguments{ +\item{client_id}{Client ID} + +\item{concise}{Generate concise output} +} +\description{ +Parameters for client functions +} diff --git a/man/client.Rd b/man/client.Rd index 7d256d6..7aed897 100644 --- a/man/client.Rd +++ b/man/client.Rd @@ -8,6 +8,8 @@ client(client_id, concise = TRUE) } \arguments{ \item{client_id}{Client ID} + +\item{concise}{Generate concise output} } \value{ A data frame with one record per client diff --git a/tests/testthat/setup-files.R b/tests/testthat/setup-files.R index 175ff63..9793ed0 100644 --- a/tests/testthat/setup-files.R +++ b/tests/testthat/setup-files.R @@ -1,5 +1,7 @@ +library(stringi) + CLOCKIFY_API_KEY <- Sys.getenv("CLOCKIFY_API_KEY") -# This is the workspace that was specifically created for testing {clockify}. +# This is the "{clockify} sandbox" workspace that was specifically created for testing {clockify}. CLOCKIFY_WORKSPACE <- "630c61ba9c3a3c3112812332" USER_ID_AUTHENTICATED <- "5f227e0cd7176a0e6e754409" # Andrew @@ -21,7 +23,7 @@ CLIENT_NAME_PSF <- "Python Software Foundation" NO_API_KEY_IN_ENVIRONMENT <- CLOCKIFY_API_KEY == "" random_string <- function(length = 24) { - stringi::stri_rand_strings(1, length) + stri_rand_strings(1, length) } random_integer <- function(min = 0, max = 100) { diff --git a/tests/testthat/test-report-shared.R b/tests/testthat/test-report-shared.R index cbe3e49..7826707 100644 --- a/tests/testthat/test-report-shared.R +++ b/tests/testthat/test-report-shared.R @@ -1,6 +1,7 @@ SHARED_REPORT_LIST_COLS <- c( - "shared_report_id", "report_author", "name", "link", "visible_to_users", "fixed_date", - "type", "visible_to_user_groups", "is_public" + "shared_report_id", "workspace_id", "user_id", "report_author", "name", + "link", "visible_to_users", "visible_to_user_groups", "fixed_date", "type", + "filter", "is_public" ) entries <- time_entries(concise = FALSE) @@ -36,8 +37,9 @@ test_that("create shared report", { expect_identical( names(report), c( - "shared_report_id", "workspace_id", "user_id", "name", "visible_to_user_groups", "visible_to_users", - "fixed_date", "type", "filter", "is_public" + "shared_report_id", "workspace_id", "user_id", "report_author", "name", + "link", "visible_to_users", "visible_to_user_groups", "fixed_date", + "type", "filter", "is_public" ) ) diff --git a/tests/testthat/test-report.R b/tests/testthat/test-report.R index e0dcfc5..4be35bb 100644 --- a/tests/testthat/test-report.R +++ b/tests/testthat/test-report.R @@ -9,6 +9,7 @@ REPORT_DETAILED_COLS <- c( "billable", "project_id", "task_id", + "type", "tag_ids", "approval_request_id", "is_locked",