diff --git a/DESCRIPTION b/DESCRIPTION index 6bf9117..7447952 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,7 +9,7 @@ Description: R API client for the 'Redmine' project management system. URL: https://github.com/openanalytics/redmineR, http://www.redmine.org/projects/redmine/wiki/Rest_api License: GPL-3 + file LICENSE RoxygenNote: 6.1.1 -Imports: httr, jsonlite, mime +Imports: httr, jsonlite, mime, tidyr Suggests: knitr VignetteBuilder: knitr Encoding: UTF-8 diff --git a/R/utils.R b/R/utils.R index 682f03e..ec89901 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,100 +1,108 @@ -## +## removeNULL <- function(x) { x[!sapply(x, is.null)] } redmine_get_all_pages <- function(endpoint, query = NULL, maxLimit = 100) { - + nameEndpoint <- gsub(".*/([^/.]*).*$", "\\1", endpoint) limit <- maxLimit offset <- 0 pageQuery <- paste0("limit=", limit, "&offset=", offset, "&", query) - + res <- redmine_get(endpoint = endpoint, query = pageQuery) resList <- res$content[[nameEndpoint]] - + N <- res$content$total_count - + if (!is.null(N) && N > limit) { - + offsets <- seq(from = limit, to = N, by = limit) - + for (iPage in seq_along(offsets)) { pageQuery <- paste0("limit=", limit, "&offset=", offsets[iPage], "&", query) res <- redmine_get(endpoint = endpoint, query = pageQuery) resList <- c(resList, res$content[[nameEndpoint]]) } } - + # implement 'fill' manually - allNames <- Reduce(union, lapply(resList, function(x) names(x))) - + allNames <- Reduce(union, lapply(resList, function(x) names(x))) + vectors <- lapply(resList, function(x) { res <- x namesToAdd <- setdiff(allNames, names(res)) res[namesToAdd] <- NA res[allNames] }) - + res_df <- as.data.frame(do.call(rbind, vectors), stringsAsFactors = FALSE) - + # unlist columns that are actually atomic - atomicCols <- names(res_df)[vapply(res_df, function(col) !is.list(col) || !is.list(unlist(col, recursive = F)), logical(1))] - res_df[atomicCols] <- lapply(res_df[atomicCols], unlist) + # atomicCols <- names(res_df)[vapply(res_df, function(col) !is.list(col) || !is.list(unlist(col, recursive = F)), logical(1))] + # res_df[atomicCols] <- lapply(res_df[atomicCols], unlist) + + getNonAtomicCols <- function(df) names(df)[!vapply(df, function(col) !is.list(col) || !is.list(unlist(col, recursive = F)), logical(1))] + + res_df <- res_df %>% + tidyr::unnest_wider(col = all_of(getNonAtomicCols(.)), names_sep = "_") %>% + tidyr::unnest_wider(col = all_of(getNonAtomicCols(.)), names_sep = "_") + + res_df <- as.data.frame(res_df) attr(res_df, "endpoint") <- endpoint attr(res_df, "query") <- query class(res_df) <- append("redminer_df", class(res_df)) - + res_df - + } #' @export print.redminer_df <- function(x, cut = 20, ...) { - if (!is.null(x$description) && is.character(x$description)) + if ('description' %in% names(x) && !is.null(x$description) && is.character(x$description)) x$description <- ifelse(nchar(x$description) > cut, paste0(substr(x$description, 1, cut), " ..."), x$description) - - # TODO: show list columns nicer + + # TODO: show list columns nicer listCols <- names(x)[vapply(x, is.list, logical(1))] # print.data.frame(x[, grep("\\.id$", names(x), value = TRUE, invert = TRUE)]) cat("redmineR listing", - if (!is.null(attr(x, "endpoint"))) paste0(" for '", attr(x, "endpoint"), "'"), + if (!is.null(attr(x, "endpoint"))) paste0(" for '", attr(x, "endpoint"), "'"), if (!is.null(attr(x, "query"))) paste0(" [query = ", attr(x, "query"), "]"), ":\n", sep = "") - + print.data.frame(x) } #' Search id by name -#' -#' Search happens inside the 'subject' field for issues and 'name' for other +#' +#' Search happens inside the 'subject' field for issues and 'name' for other #' endpoints. #' @param name string to search for #' @param endpoint endpoint where to search ("projects", "issues", ...) -#' @param query extra query arguments -#' @return id(s) found invisibly, in addition summary of search results is -#' printed -#' +#' @param query extra query arguments +#' @return id(s) found invisibly, in addition summary of search results is +#' printed +#' #' @author Maxim Nazarov #' @export redmine_search_id <- function(name = NULL, endpoint = "projects", query = NULL) { - - enumerations <- c("issue_priorities", "time_entry_activities", + + enumerations <- c("issue_priorities", "time_entry_activities", "document_categories") if (endpoint %in% enumerations) endpoint <- paste0("enumerations/", endpoint) - + res <- redmine_get_all_pages(endpoint = endpoint, query = query) - + colSearch <- if (endpoint == "issues") "subject" else "name" - ans <- if (!is.null(name)) + ans <- if (!is.null(name)) res[grepl(name, res[[colSearch]], ignore.case = TRUE), ] else res - + if (nrow(ans) == 0) stop("No id found") print(ans)