From 56a63bc6b69d6a28553df7164c50780a19f9ce64 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 17:24:45 +0000 Subject: [PATCH 1/3] Initial plan From 6f2aa426fc5dd8d140dd36f546beca0e5215f270 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 17:32:46 +0000 Subject: [PATCH 2/3] Implement list_course_rubrics function with full documentation and testing Co-authored-by: tin900 <113692500+tin900@users.noreply.github.com> --- NAMESPACE | 1 + R/list_course_rubrics.R | 125 +++++++++++++++++++++++++++++++++++++ TODO.md | 2 +- _pkgdown.yml | 10 +-- man/list_course_rubrics.Rd | 66 ++++++++++++++++++++ 5 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 R/list_course_rubrics.R create mode 100644 man/list_course_rubrics.Rd diff --git a/NAMESPACE b/NAMESPACE index 503bd9f..c17603b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -57,6 +57,7 @@ export(get_user_course_assignment_data) export(get_user_course_messaging_data) export(get_user_course_participation_data) export(list_all_enrollment_terms) +export(list_course_rubrics) export(post_new_discussion) export(update_page) export(update_quiz) diff --git a/R/list_course_rubrics.R b/R/list_course_rubrics.R new file mode 100644 index 0000000..484f65f --- /dev/null +++ b/R/list_course_rubrics.R @@ -0,0 +1,125 @@ +#' List Course Rubrics +#' +#' Retrieves all rubrics attached to a course from the Canvas LMS API. +#' +#' @param canvas A list containing Canvas API configuration: +#' \itemize{ +#' \item base_url: The base URL of your Canvas instance +#' \item api_key: Your Canvas API key +#' } +#' @param course_id The ID of the course for which to retrieve rubrics +#' @param include A character vector or string specifying additional information to include. +#' Valid options are: +#' \itemize{ +#' \item "associations": Include rubric associations +#' \item "rubric_assessments": Include rubric assessments +#' } +#' @param per_page The number of rubrics to retrieve per page (default is 100) +#' +#' @return A data frame containing course rubric objects with all available metadata +#' +#' @details This function calls the Canvas API endpoint: +#' \code{GET /api/v1/courses/:course_id/rubrics} +#' +#' The function supports pagination and will return all rubrics for the course. +#' The \code{include} parameter allows you to retrieve additional associated data +#' such as rubric associations and assessments. +#' +#' @examples +#' \dontrun{ +#' # Set up canvas connection +#' canvas <- canvas_authenticate( +#' base_url = "https://your-institution.instructure.com", +#' api_key = "your-api-key" +#' ) +#' +#' # Get all rubrics for a course +#' rubrics <- list_course_rubrics(canvas, course_id = 12345) +#' +#' # Get rubrics with associations included +#' rubrics_with_associations <- list_course_rubrics( +#' canvas, +#' course_id = 12345, +#' include = "associations" +#' ) +#' +#' # Get rubrics with multiple include options +#' rubrics_full <- list_course_rubrics( +#' canvas, +#' course_id = 12345, +#' include = c("associations", "rubric_assessments") +#' ) +#' } +#' +#' @export +#' +list_course_rubrics <- function(canvas, course_id, include = NULL, per_page = 100) { + # Validate inputs + if (missing(canvas) || !is.list(canvas)) { + stop("canvas must be a list containing 'base_url' and 'api_key'") + } + + if (missing(course_id) || !is.numeric(course_id) && !is.character(course_id)) { + stop("course_id must be provided as a numeric or character value") + } + + # Construct the API endpoint URL + url <- paste0(canvas$base_url, "/api/v1/courses/", course_id, "/rubrics") + + # Build query parameters + query_params <- list(per_page = per_page) + + # Handle include parameter + if (!is.null(include)) { + if (is.character(include) && length(include) > 0) { + # Convert vector to comma-separated string if needed + include_str <- if (length(include) > 1) { + paste(include, collapse = ",") + } else { + include + } + query_params$include <- include_str + } else { + warning("include parameter should be a character vector; ignoring invalid value") + } + } + + # Make the API request + response <- httr::GET( + url, + query = query_params, + httr::add_headers(Authorization = paste("Bearer", canvas$api_key)) + ) + + # Check the response status code + if (httr::status_code(response) != 200) { + error_message <- paste("Failed to retrieve course rubrics. Status code:", httr::status_code(response)) + + # Try to extract error details from response + if (httr::status_code(response) == 401) { + error_message <- paste(error_message, "Please check your authentication credentials.") + } else if (httr::status_code(response) == 404) { + error_message <- paste(error_message, "Course not found. Please check the course_id.") + } + + stop(error_message) + } + + # Parse the response as JSON + rubrics <- httr::content(response, "text", encoding = "UTF-8") %>% + jsonlite::fromJSON(flatten = TRUE) + + # Handle case where no rubrics are returned + if (length(rubrics) == 0 || (is.data.frame(rubrics) && nrow(rubrics) == 0)) { + message("No rubrics found for course ", course_id) + return(data.frame()) + } + + # Convert to data frame if it's a list + if (is.list(rubrics) && !is.data.frame(rubrics)) { + rubrics <- dplyr::bind_rows(rubrics) + } + + # Return the data frame of rubrics + return(rubrics) +} \ No newline at end of file diff --git a/TODO.md b/TODO.md index 2d33507..d09958d 100644 --- a/TODO.md +++ b/TODO.md @@ -2329,7 +2329,7 @@ - [ ] List rubrics RubricsApiController#index ; GET /api/v1/accounts/:account_id/rubrics -- [ ] List rubrics RubricsApiController#index ; +- [x] List rubrics RubricsApiController#index ; GET /api/v1/courses/:course_id/rubrics - [ ] Get a single rubric RubricsApiController#show ; diff --git a/_pkgdown.yml b/_pkgdown.yml index 51aa6eb..ef05412 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1067,16 +1067,16 @@ reference: # - deactivate_role # - activate_role # - update_role -# title: Rubrics -# desc: > -# Manage rubrics. -# contents: +- title: Rubrics + desc: > + Manage rubrics. + contents: + - list_course_rubrics # - create_rubric # - update_rubric # - delete_rubric # - list_rubrics # - get_single_rubric -# # title: RubricAssessments # desc: > # Manage rubric assessments. diff --git a/man/list_course_rubrics.Rd b/man/list_course_rubrics.Rd new file mode 100644 index 0000000..474e3a7 --- /dev/null +++ b/man/list_course_rubrics.Rd @@ -0,0 +1,66 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/list_course_rubrics.R +\name{list_course_rubrics} +\alias{list_course_rubrics} +\title{List Course Rubrics} +\usage{ +list_course_rubrics(canvas, course_id, include = NULL, per_page = 100) +} +\arguments{ +\item{canvas}{A list containing Canvas API configuration: + \itemize{ + \item base_url: The base URL of your Canvas instance + \item api_key: Your Canvas API key + }} + +\item{course_id}{The ID of the course for which to retrieve rubrics} + +\item{include}{A character vector or string specifying additional information to include. + Valid options are: + \itemize{ + \item "associations": Include rubric associations + \item "rubric_assessments": Include rubric assessments + }} + +\item{per_page}{The number of rubrics to retrieve per page (default is 100)} +} +\value{ +A data frame containing course rubric objects with all available metadata +} +\description{ +Retrieves all rubrics attached to a course from the Canvas LMS API. +} +\details{ +This function calls the Canvas API endpoint: +\code{GET /api/v1/courses/:course_id/rubrics} + +The function supports pagination and will return all rubrics for the course. +The \code{include} parameter allows you to retrieve additional associated data +such as rubric associations and assessments. +} +\examples{ +\dontrun{ +# Set up canvas connection +canvas <- canvas_authenticate( + base_url = "https://your-institution.instructure.com", + api_key = "your-api-key" +) + +# Get all rubrics for a course +rubrics <- list_course_rubrics(canvas, course_id = 12345) + +# Get rubrics with associations included +rubrics_with_associations <- list_course_rubrics( + canvas, + course_id = 12345, + include = "associations" +) + +# Get rubrics with multiple include options +rubrics_full <- list_course_rubrics( + canvas, + course_id = 12345, + include = c("associations", "rubric_assessments") +) +} +} \ No newline at end of file From 3e0630a01027c4324b4f5e21cd5e7ab5bce3266c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 23 Jul 2025 13:57:13 +0000 Subject: [PATCH 3/3] Refactor list_course_rubrics to use new paginate function Co-authored-by: tin900 <113692500+tin900@users.noreply.github.com> --- R/list_course_rubrics.R | 42 +++++++++++++++++++++++++------------- man/list_course_rubrics.Rd | 4 +--- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/R/list_course_rubrics.R b/R/list_course_rubrics.R index 484f65f..d1fa3bf 100644 --- a/R/list_course_rubrics.R +++ b/R/list_course_rubrics.R @@ -14,7 +14,6 @@ #' \item "associations": Include rubric associations #' \item "rubric_assessments": Include rubric assessments #' } -#' @param per_page The number of rubrics to retrieve per page (default is 100) #' #' @return A data frame containing course rubric objects with all available metadata #' @@ -53,7 +52,7 @@ #' #' @export #' -list_course_rubrics <- function(canvas, course_id, include = NULL, per_page = 100) { +list_course_rubrics <- function(canvas, course_id, include = NULL) { # Validate inputs if (missing(canvas) || !is.list(canvas)) { stop("canvas must be a list containing 'base_url' and 'api_key'") @@ -67,7 +66,7 @@ list_course_rubrics <- function(canvas, course_id, include = NULL, per_page = 10 url <- paste0(canvas$base_url, "/api/v1/courses/", course_id, "/rubrics") # Build query parameters - query_params <- list(per_page = per_page) + query_params <- list() # Handle include parameter if (!is.null(include)) { @@ -84,7 +83,7 @@ list_course_rubrics <- function(canvas, course_id, include = NULL, per_page = 10 } } - # Make the API request + # Make the initial API request response <- httr::GET( url, query = query_params, @@ -105,21 +104,36 @@ list_course_rubrics <- function(canvas, course_id, include = NULL, per_page = 10 stop(error_message) } - # Parse the response as JSON - rubrics <- httr::content(response, "text", encoding = "UTF-8") %>% - jsonlite::fromJSON(flatten = TRUE) + # Use pagination helper to get all pages + responses <- paginate(response, canvas$api_key) + + # Parse and combine all results + rubrics_list <- lapply(responses, function(resp) { + content <- httr::content(resp, "text", encoding = "UTF-8") %>% + jsonlite::fromJSON(flatten = TRUE) + + # Handle case where content is empty or not a data frame + if (length(content) == 0) { + return(data.frame()) + } + + # Convert to data frame if it's a list + if (is.list(content) && !is.data.frame(content)) { + content <- dplyr::bind_rows(content) + } + + return(content) + }) + + # Combine all results + all_rubrics <- dplyr::bind_rows(rubrics_list) # Handle case where no rubrics are returned - if (length(rubrics) == 0 || (is.data.frame(rubrics) && nrow(rubrics) == 0)) { + if (nrow(all_rubrics) == 0) { message("No rubrics found for course ", course_id) return(data.frame()) } - # Convert to data frame if it's a list - if (is.list(rubrics) && !is.data.frame(rubrics)) { - rubrics <- dplyr::bind_rows(rubrics) - } - # Return the data frame of rubrics - return(rubrics) + return(all_rubrics) } \ No newline at end of file diff --git a/man/list_course_rubrics.Rd b/man/list_course_rubrics.Rd index 474e3a7..b56c6f4 100644 --- a/man/list_course_rubrics.Rd +++ b/man/list_course_rubrics.Rd @@ -4,7 +4,7 @@ \alias{list_course_rubrics} \title{List Course Rubrics} \usage{ -list_course_rubrics(canvas, course_id, include = NULL, per_page = 100) +list_course_rubrics(canvas, course_id, include = NULL) } \arguments{ \item{canvas}{A list containing Canvas API configuration: @@ -21,8 +21,6 @@ list_course_rubrics(canvas, course_id, include = NULL, per_page = 100) \item "associations": Include rubric associations \item "rubric_assessments": Include rubric assessments }} - -\item{per_page}{The number of rubrics to retrieve per page (default is 100)} } \value{ A data frame containing course rubric objects with all available metadata