Activity Feed
- Posted Re: Edits made to a copy of a New Quiz in one course are mirrored in other courses on New Quizzes Discussion. 06-22-2021 08:20 AM
- Got a Kudo for Re: Changing Course Participation setting programatically. 04-25-2021 07:08 AM
- Posted Re: Changing Course Participation setting programatically on Canvas Admin Discussion. 04-23-2021 07:36 AM
- Posted Dashboard should display current courses first if nothing favorited on Idea Conversations. 03-04-2021 08:39 AM
- Tagged Dashboard should display current courses first if nothing favorited on Idea Conversations. 03-04-2021 08:39 AM
- Tagged Dashboard should display current courses first if nothing favorited on Idea Conversations. 03-04-2021 08:39 AM
- Got a Kudo for Re: Can return enrollments- how to handle pagination? . 08-06-2020 02:01 AM
- Got a Kudo for Re: Is there a way to get the list of courses sorted in descending order by course id from canvas?. 08-06-2020 02:01 AM
- Kudoed [Dashboard] Allow past enrollments to be added to course menu for taylorbs. 07-31-2020 09:31 AM
- Kudoed [New Quizzes] New Quizzes: Download Quiz Statistics for jlbryan. 12-06-2019 12:42 PM
- Kudoed Re: Canvas Release Notes (2019-12-21) for adamtuck. 12-02-2019 06:32 AM
- Kudoed Re: Canvas Release Notes (2019-12-21) for chriscas. 12-02-2019 06:31 AM
- Kudoed Re: Canvas Release Notes (2019-12-21) for amdaigle1. 12-02-2019 06:31 AM
- Kudoed Re: Canvas Release Notes (2019-12-21) for tylerweldon. 12-02-2019 06:31 AM
- Posted API error messages on Canvas Developers Group. 11-12-2019 10:53 AM
- Tagged API error messages on Canvas Developers Group. 11-12-2019 10:53 AM
- Tagged API error messages on Canvas Developers Group. 11-12-2019 10:53 AM
- Kudoed Why can't custom roles work the same regardless of enrollment method? for pchaney. 11-08-2019 08:10 AM
- Kudoed [Theme Editor] Dark Theme/Dark Mode for Canvas for matthew_keatin1. 09-12-2019 01:13 PM
- Kudoed [People] Hide Inactive Enrollments on People Page for fosterl. 08-30-2019 08:49 AM
My Posts
Post Details | Date Published | Views | Kudos |
---|---|---|---|
Dashboard should display current courses first if nothing favorited If a user has not favorited any courses for their dashboard, the current process is to select courses, up to the 20 course maximum, first come, first serve. Meaning if the user has over 20 enro... |
03-04-2021 |
552 |
0 |
I just added an idea that the error messages returned by API calls should be more explanatory, or at least more precisely related to the actual error. I just went through several days fighting ... |
11-12-2019 |
560 |
0 |
06-22-2021
08:20 AM
We just did a quick test and the issue appears to be that questions for New Quizzes are always stored in Question Banks, and you can only edit the question in the bank, i.e. each quiz isn't getting an independent copy of the question. And, since question banks appear to be per-user not per-course or per-quiz, when you edit the question from another copy of the quiz in another course, you're still editing *the* copy of the question, so that change will show across all courses.
Thank you for pointing this out, as this could represent a significant problem for us. I wish Classic Quizzes wasn't scheduled to eventually go away. ☹️
... View more
04-23-2021
07:36 AM
1 Kudo
In the API it's under Update a Course. If you set the value course[restrict_enrollments_to_course_dates] to True, that sets the participation setting to Course, and if it's False, that sets it to Term. That's new with the change to how those work, and not yet really explained in the API documentation, but I did test it and it functioned that way after the change.
... View more
03-04-2021
08:39 AM
If a user has not favorited any courses for their dashboard, the current process is to select courses, up to the 20 course maximum, first come, first serve. Meaning if the user has over 20 enrollments, whether in published courses, or even unpublished if the user is a teacher in those, then those 20 courses are selected relatively randomly, and current courses may get displaced from the dashboard entirely and be visible only in Courses, All Courses.
Instead, current courses should be given priority. In other words, the 20 courses should be selected chronologically, from newest to oldest, so that if there isn't room to show some of the user's courses, it should be the oldest that drop off, not potentially any current ones.
... View more
11-12-2019
10:53 AM
I just added an idea that the error messages returned by API calls should be more explanatory, or at least more precisely related to the actual error. I just went through several days fighting with an enrollment call because it returned a 404 (Page Not Found) with a message text of "resource not found". In fact, the userid I was passing in was wrong, but the message had me running in circles about why the *call* was wrong. The idea is still in review as of this post, but once it's possible to upvote it, I would love to have people do so if you agree that better error messages would save time for developers and make the API more approachable by new Canvas users. https://community.canvaslms.com/ideas/15403-api-show-meaningful-error-messages
... View more
06-10-2019
12:31 PM
So I am totally not sure how Banner does this, but being an Ellucian product (at least in the last few years), I'm wondering if it uses the Integrated Learning Platform (ILP)? If so, then in theory it should work something similar to the way Colleague (Ellucian's other SIS) does it, where there's an option to say "divide by department" or not. We're in a similar situation in that we're a system of college, using a single SIS that treats us as one single institution, yet where we want things branded and organized by college. We smart code things in our SIS, so for example termcodes end up like C19FA (Castleton University 2019 Fall) vs. T19FA (Vermont Technical College 2019 Fall), as do departments, locations, and so on. Department wasn't going to do what we needed because each school has its own departments, so we would have ended up with dozens and dozens of subaccounts (think: CENG, NENG, TENG, VENG, and then multiply out, all department codes times four). But, on investigation, the screens in Colleague that configure the connection to the ILP let you specify where to get the department name and department code. So we cooked up functions in Colleague which, when called, will return the 3-character school code, and the full name of the school, and then set the department code and department name fields to use those. And it worked, allowing our four separate schools' courses to get populated into the appropriate school-based subaccounts. Again, I don't know if Banner integrates with the ILP, and if it does, if it has that same flexibility in its configuration pages. But, since they're both Ellucian products, I thought it was worth mentioning.
... View more
03-15-2019
08:42 AM
We've been using Turnitin with Moodle for years. Now that we're migrating to Canvas, we've been testing Unicheck and Plagscan to see if we want to stay with TII or move on. We didn't like the limited content repositories that Unicheck scanned compared with the broad base of content in Turnitin. Still testing Plagscan. In addition to the repositories scanned, there are differences in the implementations. For example, Unicheck integrates only via the Plagiarism Detection Framework, meaning you use Canvas assignments and grading tools, and Unicheck provides only the plagiarism scanning, scoring, and reporting. Plagscan integrates and uses Canvas assignments and grading tools as well, although I believe it is done as an LTI tool, not a Plagiarism Framework tool. Turnitin offers both options, but each method has some limitations. Our faculty absolutely love the QuickMarks tool in TII, but that's only available if you use TII as an external tool, which then means you're not using SpeedGrader and Canvas' own very good tool set. But that said, we're still not sure what we're ultimately going with.
... View more
01-29-2019
11:53 AM
1 Kudo
I would also love to hear from anyone who's using it. We're just starting the implementation project with Ellucian, and I'd love to hear suggestions and anything anyone has found out that you wish you knew up front.
... View more
12-13-2018
10:58 AM
1 Kudo
I'm also not a Node developer, but perhaps the logic in this Python code will help. The same sort of abilities exist in JavaScript/Node.js I'm sure, I just don't know the syntax for them. This is a while loop that runs through and makes the calls one by one to the API URL in url, passing in the token via the headers defined in headers. Then it grabs the returned "Link" header, splits it up, looks through all the links passed to see if there's a "next", and if so, sets the next url to be that. Then your code would do stuff, and at the end of the loop you see if you set nexturl, and if you did, set url to that and loop back up. Otherwise set the exit flag and drop out of the loop. # Now the meat of the process. We're going to loop here to get each of the 10-record pages # the Canvas API will give us in response to our request. keepgoing = True while keepgoing: # Make the call to the API URL and pass in our custom header. r = requests.get(url, headers=headers) # Make sure the call worked, and if not, we want to throw an error. if r.status_code != 200: print("ERROR: Status code returned={} for {} -- Exiting.\n".format(r.status_code, courseurl)) sys.exit() # Since there are a lot of these, we'll need to paginate. That means getting the link # header to the next page out of the LINK header. If there isn't one, then this is the # last page. linkheader = r.headers['Link'] # The header has an array of links, separated by commas... linklist = linkheader.split(",") # Loop through. We're looking for the "next" link, if there is one... nexturl = None for linkitem in linklist: # Each link item is really two things, the actual URL, and a rel= that tells us what the link is to... onelink = linkitem.split(";") # If we have a next... # Otherwise, if no next, empty nexturl so we'll know. if "next" in onelink[1]: # Get it, strip the first character (a "<") and the last letter (a ">"). nexturl = onelink[0] nexturl = nexturl[1:] nexturl = nexturl[:-1] # End of for loop **** do stuff with the data on the current page here **** # Now, if the nexturl is blank, set the keepgoing flag to false so we'll drop out of the loop. # Otherwise, set url to nexturl and we'll get the next page worth. if nexturl: url = nexturl else: keepgoing = False # End of while loop
... View more
12-13-2018
08:00 AM
2 Kudos
Well, it's not the prettiest way to do it, but while I see in the API where we can sort the returned course list with a couple of parameters passed on the request, it looks like you can only sort on a few fields, none of which are the date or the ID. If someone has more info and shows you can say sort descending in a way that uses the ID, I'd be interested to hear it as well. In the mean time, here's a Python script that just pulls them all into a hashed array, and sorts the array based on the key, which is the course ID. #!/usr/bin/python3 ################################################################################### # listcourses.py # A sample Python script that lists the courses in our Canvas install. # ajh 2018-08-15 # For this to work you'll need the requests module installed, which isn't part # of Python Core. Also, this is written and tested in Python3, I haven't tried # to see if it works in Python2 and honestly don't much care to. ################################################################################### # Pull in the module with tools like exit(). (Why is this not in by default?) import sys # Pull in the modules that allow the RESTful API access (https), and JSON parsing. import requests import json # Create and initialize a dictionary (hashed array) to hold the courses for sorting global courselist courselist = {} # The token here is the key to accessing things in our Canvas install. It's a per-user token # so you'll want to have an admin generate it to get the required access. To generate one # you go to Account, Settings, and under Approved Integrations, get a new access token. # !!Note!! When you generate the token, copy and paste it somewhere!! You will never see that # token again, and if you lose it, you'll have to delete it and generate a new one because you # cannot get the actual token value shown to you ever again. token = '(fill in you token here)' # We'll need to pass the token to Canvas using a custom header on the https request, with # a name of Authorization and a value of the word Bearer, a space, and the token you generated. headers = {'Authorization': 'Bearer ' + token} # This is the URL for the API call we want. You can get the whole list of these, with descriptions # of the JSON object returned and any parameters you can pass in (also via JSON usually), by logging # into Canvas and then going to https://(your.canvas.url)/doc/api/live (there is no link to this # inside Canvas so you'll have to go directly to that URL). # Note that we can't just call api/v1/courses, as that only gives the courses for the user whose # token we're using. We have to specify accounts plus the main account id (always 1) plus "courses" # to get all the courses. If you only want the courses in one of the sub accounts, specify that # account's id instead of the main account id. courseurl = ' https://(your.canvas.url)/api/v1/accounts/1/courses ' # Now the meat of the process. We're going to loop here to get each of the 10-record pages # the Canvas API will give us in response to our request. keepgoing = True while keepgoing: # Make the call to the API URL and pass in our custom header. r = requests.get(courseurl, headers=headers) # Make sure the call worked, and if not, we want to throw an error. if r.status_code != 200: print("ERROR: Status code returned={} for {} -- Exiting.\n".format(r.status_code, courseurl)) sys.exit() # Since there are a lot of these, we'll need to paginate. That means getting the link # header to the next page out of the LINK header. If there isn't one, then this is the # last page. linkheader = r.headers['Link'] # The header has an array of links, separated by commas... linklist = linkheader.split(",") # Loop through. We're looking for the "next" link, if there is one... nexturl = None for linkitem in linklist: # Each link item is really two things, the actual URL, and a rel= that tells us what the link is to... onelink = linkitem.split(";") # If we have a next... # Otherwise, if no next, empty nexturl so we'll know. if "next" in onelink[1]: # Get it, strip the first character (a "<") and the last letter (a ">"). nexturl = onelink[0] nexturl = nexturl[1:] nexturl = nexturl[:-1] # End of for loop # Now we pull the text of the response we got back, run that through the JSON decoder, and # stuff the whole data structure into a variable. data = json.loads(r.text) # The response will have an array of records each of which is a hash array with a bunch of items. # For this example, we'll cycle through the array, and for each one, get the idnumber and the course name # and stick them in a dictionary (a Python hashed array) for course in data: courselist[course['id']] = course['name'] # Now, if the nexturl is blank, set the keepgoing flag to false so we'll drop out of the loop. # Otherwise, set url to nexturl and we'll get the next page worth. if nexturl: url = nexturl else: keepgoing = False # End of while loop # Ok, we've got them all now. Sort them in descending order by the key and print them out. for crsid in sorted(courselist, reverse=True): print("{} - {}".format(crsid, courselist[crsid])) # End of sample script.
... View more