Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export(get_assignment_data)
export(get_assignment_details)
export(get_assignment_groups)
export(get_assignment_submissions)
export(get_assignment_submissions_new)
export(get_course_gradebook)
export(get_quiz_submissions)
export(get_submissions)
export(get_assignments)
export(get_calendar_events)
export(get_course_announcements)
Expand Down
46 changes: 25 additions & 21 deletions R/get_assignment_submissions.R
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
#' Lists assignment submissions for a course.
#'
#' This function retrieves a list of assignment submissions for a specific course in the Canvas LMS API.
#' If an assignment_id is provided, it will use the specific assignment endpoint. Otherwise, it will
#' attempt to get all submissions using the students/submissions endpoint, which may not be available
#' in all Canvas systems.
#'
#' @param canvas An object containing the Canvas API key and base URL, obtained through the `canvas_authenticate` function.
#' @param course_id The ID of the course for which to list assignment submissions.
#' @param assignment_id (Optional) The ID of a specific assignment for which to list submissions.
#' @param assignment_id (Optional) The ID of a specific assignment for which to list submissions. If provided, uses the more reliable assignment-specific endpoint.
#' @param per_page (Optional) The number of submissions to retrieve per page of results (default is 100).
#'
#' @return A data frame of assignment submissions for the specified course and assignment.
#' @export
get_assignment_submissions <- function(canvas, course_id, assignment_id = NULL, per_page = 100) {
# Construct the API endpoint URL
url <- paste0(canvas$base_url, "/api/v1/courses/", course_id, "/students/submissions?per_page=", per_page)

# Append the assignment_id if provided
# If assignment_id is provided, use the specific assignment endpoint
if (!is.null(assignment_id)) {
url <- paste0(url, "&assignment_id=", assignment_id)
}

# Make the API request
response <- httr::GET(url, httr::add_headers(Authorization = paste("Bearer", canvas$api_key)))
# Use the new get_submissions function for specific assignment
return(get_submissions(canvas, course_id, "assignments", assignment_id, per_page))
} else {
# For getting all submissions, try the students/submissions endpoint first
# and fall back to iterating through assignments if it fails
url <- paste0(canvas$base_url, "/api/v1/courses/", course_id, "/students/submissions?per_page=", per_page)

# Make the API request
response <- httr::GET(url, httr::add_headers(Authorization = paste("Bearer", canvas$api_key)))

# Use pagination helper to get all pages
responses <- paginate(response, canvas$api_key)
# Use pagination helper to get all pages
responses <- paginate(response, canvas$api_key)

# Parse and combine all results
submissions_list <- lapply(responses, function(resp) {
httr::content(resp, "text", encoding = "UTF-8") %>%
jsonlite::fromJSON(flatten = TRUE) %>%
as.data.frame()
})
submissions <- dplyr::bind_rows(submissions_list)
# Parse and combine all results
submissions_list <- lapply(responses, function(resp) {
httr::content(resp, "text", encoding = "UTF-8") %>%
jsonlite::fromJSON(flatten = TRUE) %>%
as.data.frame()
})
submissions <- dplyr::bind_rows(submissions_list)

# Return the data frame of submissions
return(submissions)
# Return the data frame of submissions
return(submissions)
}
98 changes: 98 additions & 0 deletions R/get_course_gradebook.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#' Get course gradebook with all assignment and quiz submissions
#'
#' This function retrieves all assignment and quiz submissions for a course and combines them
#' into a single data frame. This is inspired by Jon Vik's work and provides a comprehensive
#' view of all student submissions in a course.
#'
#' @param canvas An object containing the Canvas API key and base URL, obtained through the `canvas_authenticate` function.
#' @param course_id The ID of the course for which to retrieve all submissions.
#' @param per_page (Optional) The number of submissions to retrieve per page of results (default is 100).
#' @param include_quizzes (Optional) Whether to include quiz submissions (default is TRUE).
#' @param include_assignments (Optional) Whether to include assignment submissions (default is TRUE).
#'
#' @return A data frame containing all submissions (assignments and quizzes) for the specified course.
#' @export
#'
get_course_gradebook <- function(canvas, course_id, per_page = 100, include_quizzes = TRUE, include_assignments = TRUE) {
gradebook_data <- list()

# Get assignments and their submissions
if (include_assignments) {
tryCatch({
assignments <- get_assignments(canvas, course_id)

if (nrow(assignments) > 0) {
assignment_submissions <- list()

for (i in 1:nrow(assignments)) {
assignment_id <- assignments$id[i]
assignment_name <- assignments$name[i]

tryCatch({
submissions <- get_submissions(canvas, course_id, "assignments", assignment_id, per_page)

if (length(submissions) > 0 && nrow(submissions) > 0) {
submissions$assignment_name <- assignment_name
submissions$assignment_id <- assignment_id
submissions$submission_type <- "assignment"
assignment_submissions[[as.character(assignment_id)]] <- submissions
}
}, error = function(e) {
message("Warning: Failed to get submissions for assignment ", assignment_id, ": ", e$message)
})
}

if (length(assignment_submissions) > 0) {
gradebook_data$assignments <- do.call(rbind, assignment_submissions)
}
}
}, error = function(e) {
message("Warning: Failed to get assignments: ", e$message)
})
}

# Get quizzes and their submissions
if (include_quizzes) {
tryCatch({
quizzes <- get_course_quizzes(canvas, course_id, per_page)

if (nrow(quizzes) > 0) {
quiz_submissions <- list()

for (i in 1:nrow(quizzes)) {
quiz_id <- quizzes$id[i]
quiz_name <- quizzes$title[i]

tryCatch({
submissions <- get_submissions(canvas, course_id, "quizzes", quiz_id, per_page)

if (length(submissions) > 0 && nrow(submissions) > 0) {
submissions$quiz_name <- quiz_name
submissions$quiz_id <- quiz_id
submissions$submission_type <- "quiz"
quiz_submissions[[as.character(quiz_id)]] <- submissions
}
}, error = function(e) {
message("Warning: Failed to get submissions for quiz ", quiz_id, ": ", e$message)
})
}

if (length(quiz_submissions) > 0) {
gradebook_data$quizzes <- do.call(rbind, quiz_submissions)
}
}
}, error = function(e) {
message("Warning: Failed to get quizzes: ", e$message)
})
}

# Combine all submissions
if (length(gradebook_data) > 0) {
combined_data <- do.call(rbind, gradebook_data)
combined_data$course_id <- course_id
return(combined_data)
} else {
message("No submissions found for course ", course_id)
return(data.frame())
}
}
33 changes: 33 additions & 0 deletions R/get_quiz_submissions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#' Get assignment submissions
#'
#' This function retrieves submissions for a specific assignment from the Canvas LMS API.
#' This is a convenience wrapper around get_submissions() for assignments.
#'
#' @param canvas An object containing the Canvas API key and base URL, obtained through the `canvas_authenticate` function.
#' @param course_id The ID of the course for which to retrieve assignment submissions.
#' @param assignment_id The ID of the assignment for which to retrieve submissions.
#' @param per_page (Optional) The number of submissions to retrieve per page of results (default is 100).
#'
#' @return A data frame of submissions for the specified assignment.
#' @export
#'
get_assignment_submissions_new <- function(canvas, course_id, assignment_id, per_page = 100) {
return(get_submissions(canvas, course_id, "assignments", assignment_id, per_page))
}

#' Get quiz submissions
#'
#' This function retrieves submissions for a specific quiz from the Canvas LMS API.
#' This is a convenience wrapper around get_submissions() for quizzes.
#'
#' @param canvas An object containing the Canvas API key and base URL, obtained through the `canvas_authenticate` function.
#' @param course_id The ID of the course for which to retrieve quiz submissions.
#' @param quiz_id The ID of the quiz for which to retrieve submissions.
#' @param per_page (Optional) The number of submissions to retrieve per page of results (default is 100).
#'
#' @return A data frame of submissions for the specified quiz.
#' @export
#'
get_quiz_submissions <- function(canvas, course_id, quiz_id, per_page = 100) {
return(get_submissions(canvas, course_id, "quizzes", quiz_id, per_page))
}
49 changes: 49 additions & 0 deletions R/get_submissions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#' Get submissions for assignments or quizzes
#'
#' This function retrieves submissions for assignments or quizzes from a specific course in the Canvas LMS API.
#' It can handle both assignment submissions and quiz submissions using the correct API endpoints.
#'
#' @param canvas An object containing the Canvas API key and base URL, obtained through the `canvas_authenticate` function.
#' @param course_id The ID of the course for which to retrieve submissions.
#' @param type The type of submission to retrieve. Must be either "assignments" or "quizzes".
#' @param id The ID of the assignment or quiz for which to retrieve submissions.
#' @param per_page (Optional) The number of submissions to retrieve per page of results (default is 100).
#'
#' @return A data frame of submissions for the specified assignment or quiz.
#' @export
#'
get_submissions <- function(canvas, course_id, type, id, per_page = 100) {
# Validate the type parameter
if (!type %in% c("quizzes", "assignments")) {
stop("type must be 'quizzes' or 'assignments'")
}

# Construct the API endpoint URL
url <- paste0(canvas$base_url, "/api/v1/courses/", course_id, "/",
type, "/", id, "/submissions?per_page=", per_page)

# Make the API request
response <- httr::GET(url, httr::add_headers(Authorization = paste("Bearer", canvas$api_key)))

# Check the response status code
if (httr::status_code(response) != 200) {
stop("Failed to retrieve submissions. Please check your authentication and API endpoint.")
}

# Parse the response as JSON
content_text <- httr::content(response, "text", encoding = "UTF-8")

if (type == "quizzes") {
# For quizzes, the response structure is different - need to access the first element
submissions <- jsonlite::fromJSON(content_text, flatten = TRUE)
if (is.list(submissions) && length(submissions) > 0) {
submissions <- submissions[[1]]
}
} else {
# For assignments, parse normally
submissions <- jsonlite::fromJSON(content_text, flatten = TRUE)
}

# Return the submissions data
return(submissions)
}
Loading