Bodong Chen

Crisscross Landscapes

CanvasNet: Formative feedback for 'social learning' on Canvas

2015-11-19


I have been teaching an undergraduate course using Canvas this semester. I don’t remember how it happened because I’m essentially a disbeliever in Learning Management Systems (LMS). I believe one’s learning should not be managed. “LMS is the minivan of Education,” says Phil Hill. Even better, “the LMS is more like a bus than a minivan - someone else is driving, it only travels on a pre-arranged route, the bus is often late but you still have to be on time because it won’t wait if you miss it” – says Stephen Downes. However, to show my mistrust in the ‘minivan’ or ‘bus’, I didn’t choose to avoid it but to jump on board and play with it.

'The LMS is the minivan of education—everyone has one and no one is proud of it' - @PhilOnEdTech #opened15 pic.twitter.com/gdel0oj8Pn

— Tom Evans (@taevans) November 18, 2015

As a social construtivist researcher, social interaction is a must in my teaching. Because the course I am teaching is writing-intensive, posting some text each week in the forum is an important part of course participation. As a novice (online) instructor, I’ve been trying to find means to nurture social interaction in the forum. (Btw, regardless of ‘bells and whistles’ of features for management, the discussion forum on Canvas is unsurprisingly dully designed.) As an R tinkerer, I thought it might be neat to write some tools to provide formative feedback to my students on their social and conceptual engagement.

CanvasNet

With these goals in mind, I put together a rough plan and designed an analytics-driven “intervention” for my class. The analytics is simple – social network analytics and a wordcloud based on weekly discussions. Pedagogical design included written interpretations and encouragements that went into weekly announcements on Canvas.

In researching means to develop the feedback tools, I stumbled upon Martin Hawksey’s blog post on getting Canvas discussion forum into Google Spreadsheet and then exporting data for social network analysis using NodeXL. Following Martin’s recipe, it took 20 minutes to get things setup before Google Spreadsheet started to take care of data gathering and storage for me.

With Google taking care of data, I wrote a Shiny app in R which reads data from Google, processes social interactions and posts (using the igraph and tm packages respectively), and returns two simple interactive visualizations to students.

example figures here

example figures here

Data collection is ongoing. Student beliefs in ‘social learning’ have been collected through a questionnaire. Online focus groups were conducted to explore students’ experience of social interactions in this course. We will interview some students to understand the usefulness of this tool.

My intuition is the current version of this tool will NOT work for a variety of reasons. The lack of dialogues around this tool is one possible factor. The habit of learning as individuals is another contributor. Lessons learned will be used to inform the next design cycle.

Calling the Canvas API from R

Supposing we need to remove the dependency on Google Spreadsheets, calling the Canvas API directly from R is also quite straightforward. Below is a (sort of) minimal example to play with:

library(RCurl)
library(jsonlite)
library(dplyr)

#################################
## Functions
#################################

CreateCurlHandle <- function() {
  ### Create a curl handle that will be shared among API calls

  library(RCurl)
  curl = getCurlHandle()
  curlSetOpt(cookiejar = "",
             followlocation = TRUE,
             curl = curl) # do not need to read the cookies
  return(curl)
}

CleanJSONText = function(text) {
  ## Clean json text that might cause lexical error when parsing

  text = gsub("\n", " ", text)
  text = gsub("\t", " ", text)
  text = gsub("\\\\<", "<", text)
  text = gsub("<img.*?>", "", text) # get rid of images
  text = gsub("\r", " ", text)
  return(text)
}

#################################

## Baseurl and access token
baseUrl = "https://YOUR_HOST.instructure.com/api/v1/courses"
token = "YOUR_CANVAS_TOKEN"

curl = CreateCurlHandle()

## Authenticate
auth = tbl_df(fromJSON(
  getForm(baseUrl, access_token = token, curl=curl),
  flatten = TRUE
))
glimpse(auth)

## Pick a course
courseUrl = paste0(baseUrl, "/", YOUR_COURSE_NUMBER)

## Retrieve all topics
topicsUrl = paste0(courseUrl, "/discussion_topics")
json = getForm(topicsUrl,
               .opts = list(httpheader = c(Authorization=paste("Bearer", token))),
               # access_token = token,
               curl=curl)
topics = tbl_df(fromJSON(CleanJSONText(json), flatten = TRUE))
data.frame(topics %>% select(id, title, url))

## Pick one topic, and get the full topic
topicUrl = paste0(topicsUrl, "/", topics$id[4], "/view")
json = getForm(topicUrl,
               access_token = token,
               curl=curl)
topic = fromJSON(CleanJSONText(json), flatten = TRUE)
participants = topic$participants
posts = topic$view
replies = do.call("rbind", posts$replies)
# from replies social network could then be analyzed ...

Wrap up

This post mainly reports on a technological effort to develop a simple feedback tool for online discussion on Canvas. The current design is to harness Canvas data using Google Spreadsheet and then visualize data using an R Shiny app. Reading data directly from Canvas could be an option in future design and development. The efficacy of the simple prototype remain unclear and likely to be challenged. Tons of issues need to be further explored.