Celebrate Excellence in Education: Nominate Outstanding Educators by April 15!
Found this content helpful? Log in or sign up to leave a like!
Tacoma Community College has manually entered all of the degree, program, and course outcomes to Canvas. Currently, when the outcomes are revised, I receive a .CSV file from CurricUNET (an Internet-based software application designed to automate and enhance the development and approval of curriculum) and the outcomes must be manually reviewed and edited within Canvas. We have talked to our professional services team about importing outcomes as a .csv file in an email from my boss, "It is possible to do this, and there is a script that has been written which you can find here. However, this is not something we offer support for." The location of the "here" is on the picture I've attached below. I have also included the sample Outcomes CSV that I'd like to test the .CSV in the tacomacc.beta.instructure.com instance, but do not have enough skills in API development to get it to work. There is a script that was developed individually by this person: https://github.com/kajigga who contributes code to the open source project and I would like to know if anyone has tried to use it with outcomes on a campus-wide level. Has anyone worked with this developer's API to import outcomes to either the entire Canvas instance or to an individual course? I'd be grateful for any assistance and training.
DPadden I have not tried the script from kajigga, but I will! Later this summer I will be doing the same thing, in fact just yesterday in a meeting I was asked if we could do this for a department wanting to add their Outcomes. So thank you for the heads up, I'll give this a try.
However, while you have helped me, i fear I might be not be able to help you. We are still doing this type of service as one-offs and don't have a plan in place to make something like this available without our support. Likely, I will personally upload the Outcomes for the few departments that want it done.
If you want to run this individually, in order to get this to work you first need to set up Python on your desktop. After you download this page from github, you will then edit the first two line of outcomes_importcsv_onefile.py with your institutions canvas url and your personal access token (How do I obtain an API access token? | Canvas Admin Guide | Canvas Guides). Once that is in place and saved you will then need to run that page with Python.
I haven't look at all of the code, but I'm assuming once the script is run it will ask you for the location of the csv file.
Thank you for your input. I'll read some of what you have suggested, run some tests and try to figure out what might work. Fortunately, I have many staff who love projects, so updating to the production environment is never a problem, just a long process.
Thanks!
Debbie Padden
eLearning Support Specialist and
Adjunct Faculty
Tacoma Community College
6501 S 19th Street, Bldg 16-125
Tacoma, WA 98466
253-566-5197 (office)
dpadden@tacomacc.edu<mailto:dpadden@tacomacc.edu>
Need help? Go to this website:
https://my.tacomacc.edu/tcclearn
or email us at elearning@tacomacc.edu
Hi Debora,
The script at the link you’ve provided does not perform the type of request you’ll need to update your outcomes. What it contains is a script for creating a new outcome (POST request), whereas you’d like to update an existing outcome (PUT request). The API does provide an end point for updating an existing outcome:
Canvas API Documentation for Updating an Outcome
If you don’t have adequate programming experience to automate this yourself, there is a rudimentary method you can use that requires almost no coding and can be implemented right from your browser (assuming you’re an admin in your instance of Canvas). I would strongly recommend trying it out in a test instance before updating live records:
function updateOutcomes(outcomes) {
outcomes.forEach(function(outcome){
var url = '/api/v1/outcomes/' + outcome['outcome_id'];
var outcomeData = {
title: outcome['name'],
description: outcome['description'],
mastery_points: parseInt(outcome['mastery_points'])
};
$.ajax({
url: url,
type: 'PUT',
dataType: 'json',
data: outcomeData,
})
.done(function(response) {
console.log(response);
console.log('Successfully updated Outcome #' + outcome['outcome_id'] + ': ' + outcome['name']);
})
.fail(function(response) {
console.log(response);
console.log('Error. Failed to update Outcome #' + outcome['outcome_id'] + ': ' + outcome['name']);
})
.always(function() {
console.log('Request sent to ' + url);
});
});
};
That is a Javascript function. It takes a series of information like your JSON array and for each piece of information in that series it uses a method called ‘ajax’ from a Javascript library Canvas loads called jQuery to send a PUT (update) request to your domain at the route of a given outcome. It brings data with it: the new name, description, and mastery points. If the request is successful, you’ll see a success message and and some information that Canvas sends back to you. And if it doesn’t work you’ll see an error message. Once you’ve pasted the script into you console, press Enter.
8. now type 'updateOutcomes(outcomes);’ and press Enter.
9. The output should look something like this:
Now go check on Canvas to see if your records are updated. Sometimes updating mastery points can be a little funky, so beware. Also, changing the outcome group of a outcome requires a different request. But yea, that’s pretty much how to update your outcomes from the browser. It’s easy to just pop your terminal open and shoot off a couple of requests while you’re toodle’in around the Canvas.
I hope that was helpful in some way.
Thank you so much! With the reading I’ve been given and my desire to learn and master this in a doable format that I can encourage others to use, I’m hoping that we can all build an API that takes care of the necessary updates to Outcomes. I’ll experiment in the test environment so that I don’t mess things up. My staff love projects so the Outcomes in the production environment are still up-to-date and clean as a whistle. I appreciate your instructions!
Thanks!
Debbie Padden
eLearning Support Specialist and
Adjunct Faculty
Tacoma Community College
6501 S 19th Street, Bldg 16-125
Tacoma, WA 98466
253-566-5197 (office)
dpadden@tacomacc.edu<mailto:dpadden@tacomacc.edu>
Need help? Go to this website:
https://my.tacomacc.edu/tcclearn
or email us at elearning@tacomacc.edu
I think this is the direction I need to go as well except that I want to actually POST the outcomes there for the first time. Do I simply swap out PUT with POST or are there other changes that must be made. I tried that and received the following error message for each item being imported
POST https://greenhill.test.instructure.com/api/v1/outcomes/undefined 404 (Not Found)I.support.ajax.I.ajaxTransport.send @ common-1fc630f7be.js:3I.extend.ajax @ common-1fc630f7be.js:3(anonymous function) @ VM898:10updateOutcomes @ VM898:3(anonymous function) @ VM1011:2InjectedScript._evaluateOn @ VM693:905InjectedScript._evaluateAndWrap @ VM693:838InjectedScript.evaluate @ VM693:694
VM898:21 Object {readyState: 4, responseText: "{"errors":{"base":"Unexpected error, ID: 26670000000002831"},"status":"404 Not Found"}", status: 404, statusText: "Not Found"}
VM898:22 Error. Failed to update Outcome #undefined: undefined
VM898:25 Request sent to /api/v1/outcomes/undefined
This makes me think it is still looking for a standard to update so I am not sure what I am missing here. I am going to try the Python method but I do love the ideas of being able to do this through JSON and the developer tools. I am new to this so any help would be wonderful.
Thanks,
Chris
I'm late to the game here, but thank you Matthew for this method. It's been very useful. I've been using a modified version that will REMOVE all currently unused outcomes from a course and IMPORT a new set from a JSON object. The method is the same as the one outlined by Matthew Meyers above that uses your browser's console, but you will need a couple of additional columns in your CSV.
Your CSV headers should include:
group_name | title | description |
calculation_method | calculation_int | mastery_points |
rubric_1_points | rubric_1_text | rubric_2_points | rubric_2_text |
rubric_3_points | rubric_3_text | rubric_4_points | rubric_4_text
Note: the columns for rubric points and rubric text allow you to set up a different 4-level rubric for each outcome.
/**
* @author Steven Carpenter
* credit to marinated_pork for the base updateOutcomes() code
*/
function importOutcomes(outcomes) {
var course_id = window.location.href.split('courses/')[1].split('/')[0];
var subgroups_url;
var outcome_group_ids = {};
// Remove current outcomes
$.get('/api/v1/courses/'+course_id+'/outcome_group_links?per_page=100').then(function(data){
data.forEach(function(outcome){
if(outcome.context_type = 'Course'){
var group_id = outcome.outcome_group.id;
var outcome_id = outcome.outcome.id;
var url = '/api/v1/courses/'+course_id+'/outcome_groups/'+group_id+'/outcomes/'+outcome_id;
$.ajax({
url: url,
type: 'DELETE'
})
}
})
});
// Get outcome groups
$.get('/api/v1/courses/'+course_id+'/root_outcome_group').then(function(data){
subgroups_url = data.subgroups_url;
$.get('/api/v1/courses/'+course_id+'/outcome_groups').then(function(data){
data.forEach(function(group){
outcome_group_ids[group.title] = group.id
});
addOutcomes()
});
});
function addOutcomes(){
outcomes.forEach(function(outcome){
var group_name = outcome['group_name']
var group_id;
if( group_name in outcome_group_ids){
group_id = outcome_group_ids[group_name]
}
else{
group_id = addGroup(group_name)
outcome_group_ids[group_name] = group_id
}
var url = '/api/v1/courses/'+course_id+'/outcome_groups/'+group_id+'/outcomes';
var outcomeData = {
title: outcome['title'],
description: outcome['description'],
mastery_points: outcome['mastery_points'],
calculation_method: outcome['calculation_method'],
calculation_int: outcome['calculation_int'],
ratings: [
{
description: outcome['rubric_4_text'],
points: outcome['rubric_4_points']
},
{
description: outcome['rubric_3_text'],
points: outcome['rubric_3_points']
},
{
description: outcome['rubric_2_text'],
points: outcome['rubric_2_points']
},
{
description: outcome['rubric_1_text'],
points: outcome['rubric_1_points']
}
]
};
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
data: JSON.stringify(outcomeData),
contentType: "application/json",
})
.done(function(response) {
console.log(response);
console.log('Successfully added ' + outcome['title'] + ' to ' + group_name);
})
.fail(function(response) {
console.log(response);
console.log('Error. Failed to add ' + outcome['title'] + ' to ' + group_name);
})
.always(function() {
console.log('Request sent to ' + url);
});
});
function addGroup(group_name){
group_data = {
'title': group_name
}
$.ajax({
url: subgroups_url,
type: 'POST',
dataType: 'json',
data: group_data
}).then(function(data){
return data.id
});
}
}
};
I had trouble getting the kajiagga script to work. I ended up creating my own version of a python script that will import Outcomes from a csv file into Canvas. This script will also allow for adding Outcomes to a course as well as at a sub-account level.
Here is a link to my version of an outcome_importer.py, it can be downloaded from gitHub.
There is also an example csv file available with the required headers set. Each csv file can handle only one rating scale, so you will need to bunch your imports by that common parameter.
If you haven't done so before, here is a good resource about how to run a python script: How to Run a Python Script via a File or the Shell | Python Central
If you decide to use this script, please let me know if you have any questions or run into any trouble.
Thank you, Matt! I will try this out soon. Questions for you:
1. About the rating scale: Your reference to using only one rating scale means that the default is what is used and each outcome is not able to be rated other than the 5-3-0 scale? If so, then I think we are fine with uploading to the account level with the default.
2. You mention that it can update existing outcomes--that is keyed through the unique identifiers, right?
I appreciate your hard work!!
--Deb Padden--
eLearning Support Specialist, Tacoma Community College
Debra,
Any scale can be used, just not in the same csv file. If you had some Outcomes using a 5-3-0 scale and other Outcomes using a 5-4-3-2-1-0 scale you will need to create two different csv files and run the script once for each file.
However, I just ran into an issue with the script I have yet to fix. It does not look like it is correctly iterating over the paginations of the API calls. This means that the part of the script that is grabbing the account/sub-account ids isn't grabbing every account.
I'm working on getting this to run properly, but for the moment my own personal fix was to up the number of returned accounts per API call to the maximum of 100. Since we don't have any account with more than 100 sub-account this is working as a temporary fix. I'll update the github file and add this as a note to the documentation until I fix the real issue.
I slightly mistyped before it wasn't the account ids that were potentially getting missed but outcome group and outcome ids if there were more than 10 within each subaccount.
The script should now work as long as you have fewer than 100 outcome groups within an individual subaccount, and fewer than 100 outcomes within an outcome group.
Please let me know if you have questions.
Hi DPadden,
I am going through having a look at some of the early days in the Canvas Developers group, and checking in to see if older enquiries have been answered.
I am wondering, were you ever able to find out the cause of your issue, I am hoping I can assume that it is well and truly resolved by now, but if not, please let us know and we can certainly have another look.
I am going to mark this as assumed answered for the time being, however by all means please let us know if you still have an outstanding issue and we will take a peek!
Cheers,
Stuart
Thank you! We continue to do the manual update because of the changes. The API call is primarily for a course-by-course or sub-account upload and can cause more problems than I am willing to deal with on a total account basis (which is how our Outcomes are situated so that all divisions can easily access other divisions' outcomes).
To participate in the Instructure Community, you need to sign up or log in:
Sign In