· 8 years ago · Feb 20, 2018, 12:30 AM
1/* -----------------------------------------
2Canvas Extensions Toolbar
3------------------------------------------
4
5Javascript for Chome bookmark:
6javascript:(function(){ var script=document.createElement('script'); script.src='https://ilearn.swin.edu.au/bbcswebdav/orgs/TLIP_scripts/shortcut-scripts/canvasExtentionToolbar.js'; document.head.appendChild(script); }())
7
8*/
9// get Current course ID
10
11var query_string = window.location.href;
12var query_string_split = query_string.split("/");
13window.currentCourse = query_string_split.indexOf('courses') >= 0 ? query_string_split[query_string_split.indexOf('courses') + 1] : "";
14
15window.canvasExtension = {};
16window.canvasExtension.extensionMenu = {};
17
18window.canvasExtension.dialog;
19window.canvasExtension.dialogId = "#extensionsDialog";
20
21window.canvasExtension.allItems = [];
22window.canvasExtension.allItemsAjax = [];
23window.canvasExtension.gradeBookColumns = [];
24
25
26/**
27 * init, create the extension menu, each button runs a function or opens a dialog
28 *
29 */
30window.canvasExtension.initCanvasExtensionMenu = function() {
31 window.canvasExtension.buildDialog();
32 //remove any existing extensions menu
33 $('#extensionMenu').remove();
34 //extension menu html
35 var menuHTML = " \
36 <div id='extensionMenu' class='' style='z-index: 12; background: #EEE; position: fixed; top: 0; right: 0; padding: 5px; text-align: right; box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.75); font-size: 0.5em; line-height: 1em; '> \
37 <a title='Scroll to top' onClick='window.scrollTo(0,0)' class='btn btn-default' style='padding: 0.5em; border-color: black;'><i class='icon-arrow-open-up'> </i></a> \
38 <a title='Expand all' onClick='window.canvasExtension.expandAll()' class='btn btn-info' style='padding: 0.5em; border-color: black;'><i class='icon-page-down'> </i></a> \
39 <a title='Contract all' onClick='window.canvasExtension.contractAll()' class='btn btn-info' style='padding: 0.5em; border-color: black;'><i class='icon-page-up'> </i></a> \
40 <a title='Publish all' onClick='window.canvasExtension.publishAll()' class='btn btn-success' style='padding: 0.5em; border-color: black;'><i class='icon-publish'> </i></a> \
41 <a title='Unpublish all' onClick='window.canvasExtension.unpublishAll()' class='btn' style='padding: 0.5em; border-color: black;'><i class='icon-unpublish'> </i></a> \
42 <a title='Add groups' onClick='window.canvasExtension.setupAddGroups()' class='btn btn-warning' style='padding: 0.5em; background-color: red; border-color: black;'><i class='icon-group'> </i></a> \
43 <a title='Manage GradeBook columns' onClick='window.canvasExtension.setupGradeBookColumns()' class='btn btn-warning' style='padding: 0.5em; background-color: orange; border-color: black;'><i class='icon-gradebook'> </i></a> \
44 <a title='Remove assignment dates' onClick='window.canvasExtension.runDialog(\"RemoveAssignmentDates\")' class='btn btn-danger' style='padding: 0.5em; color: black; background-color: yellow; border-color: black;'><i class='icon-calendar-clock'> </i></a> \
45 <a title='Find/remove empty items' onClick='window.canvasExtension.setupEmptyItems()' class='btn btn-danger' style='padding: 0.5em; background-color: green; border-color: black;'><i class='icon-document'> </i></a> \
46 <a title='Remove empty modules and assignment groups' onClick='window.canvasExtension.runDialog(\"RemoveEmptyModules\")' class='btn btn-danger' style='padding: 0.5em; background-color: blue; border-color: black;'><i class='icon-module'> </i></a> \
47 <a title='Expand all Quizzes' onClick='window.canvasExtension.expandQuiz()' class='btn btn-info' style='padding: 0.5em; color: white; background-color: purple;'><i class='icon-quiz'></i></a> \
48 <a title='Reformat all Quizzes' onClick='window.canvasExtension.reformatQuiz()' class='btn btn-info' style='padding: 0.5em; color: white; background-color: violet;'><i class='icon-question'></i></a> \
49 <a title='Highlight Issues' onClick='window.canvasExtension.highlightIssues()' class='btn btn-info' style='padding: 0.5em; color: white; background-color: black;'><i class='icon-flag'></i></a> \
50 </div> \
51 ";
52 //add extension menu to page
53 window.extensionMenu = $('body').append(menuHTML);
54}
55
56
57
58/**
59 * setup the dialog window, add it to the page
60 *
61 */
62window.canvasExtension.buildDialog = function() {
63 //destroy any existing dialogs
64 //if element exists, remove
65 if ($(window.canvasExtension.dialog) > 0) window.canvasExtension.dialog.dialog("destroy");
66 $(window.canvasExtension.dialogId).remove();
67 //add dialog
68 $('body').append('<div id="' + window.canvasExtension.dialogId.substring(1) + '" title=""></div>');
69 window.canvasExtension.dialog = $(window.canvasExtension.dialogId);
70 var dialogHtml = "";
71 window.canvasExtension.dialog.append(dialogHtml);
72}
73
74window.canvasExtension.highlightIssues = function() {
75
76 var editor = tinyMCE.activeEditor
77 editor.execCommand("selectAll")
78 editor.execCommand("Reformat")
79 var stuff = editor.getContent();
80 str = stuff;
81 console.log(str)
82 str = str.replace(/<*.p> /g, "");
83 str = str.replace(/ /g, " ");
84 console.log(str)
85 editor.setContent(str)
86
87}
88
89
90
91// Reformat all quiz questions/answer
92window.canvasExtension.expandQuiz = function() {
93 //454260 to 454329
94 $('#question_454331 .icon-edit.standalone-icon:visible, .element_toggler[aria.expanded="false"]:visible').click();
95 $('.form_answers .icon-edit.standalone-icon:visible, .element_toggler[aria.expanded="false"]:visible').click()
96 for (i=454260; i < 454330; i++){
97 var question_object = 'question_teaser_' + i.toString();
98 console.log(question_object)
99 //
100 }
101
102}
103window.canvasExtension.reformatQuiz = function() {
104 console.log(tinyMCE.editors.length)
105 for (i=0; i < tinyMCE.editors.length; i++){
106 try {
107 var currentEditor = tinyMCE.editors[i];
108 currentEditor.execCommand('SelectAll');
109 currentEditor.execCommand('RemoveFormat');
110 // remove formatting from the text
111 var content = currentEditor.getContent();
112 str = content;
113 str = str.replace(/ +/g, " ");
114 // attempt for replacing double spaces
115 str = str.replace(/<*.p> /g, "");
116 // remove empty paragraphs
117 str = str.replace(/<*.div>/gi, "");
118 str = str.replace(/ /g, " ");
119 // remove any divs
120 console.log(str);
121 currentEditor.setContent(str);
122
123 }
124 catch(TypeError) {
125 i++;
126 }
127 }
128 console.log("we here?")
129 // i want to update question
130 $.clkck()
131
132}
133
134/**
135 * Open a dialog window, set the size and content of the dialog
136 *
137 * @param {string} modalType - The switch value for which modal to open.
138 * @param {object} dialogData - A {object} that is used to pass data and properties to the modal.
139 */
140window.canvasExtension.runDialog = function(modalType, dialogData) {
141 // default values for dialog
142 var dWidth = 1000;
143 var dHeight = $(window).height();
144 var dPosition = "";
145 var dTitle = "";
146 var dialogHtml = "";
147
148 // setup for different types of dialogs
149 switch (modalType) {
150
151 case "RemoveAssignmentDates":
152 dialogHtml += "<p class='text-center'>Remove all of the assignment dates for this course (id: " + window.currentCourse + " )?</p>"
153 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeAssignmentDates();'>Yes, delete assignment dates</a></p>";
154 dWidth = 400;
155 dHeight = 300;
156 dTitle = "Remove assignment dates";
157 break;
158
159 case "OutcomeRemoveAssignmentDates":
160 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " assignments updated.</p>";
161 dWidth = 400;
162 dHeight = 300;
163 dTitle = "Assignment dates removed";
164 break;
165
166 case "RemoveEmptyModules":
167 dialogHtml += "<p class='text-center'>Delete all <strong>empty</strong> modules for this course (id: " + window.currentCourse + " )?</p>";
168 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.confirmRemoveEmptyModules();'>Yes, find empty modules</a></p>";
169 dialogHtml += "<p class='text-center'>Delete all <strong>empty</strong> assignment groups for this course (id: " + window.currentCourse + " )?</p>";
170 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.confirmRemoveEmptyAssignmentGroups();'>Yes, find empty assignment groups</a></p>";
171 dWidth = 450;
172 dHeight = 350;
173 dTitle = "Remove empty modules and assignment groups";
174 break;
175
176 case "ConfirmRemoveEmptyModule":
177 if (dialogData["modules"].length > 0) {
178 dialogHtml += "<p class='text-center'>The following modules are empty:</p>";
179 dialogHtml += "<ul>";
180 $.each(dialogData["modules"], function(i, mItem) {
181 dialogHtml += "<li>" + mItem.id + " - " + mItem.name + "</li>";
182 });
183 dialogHtml += "</ul>";
184 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeEmptyModules();'>REMOVE THESE MODULES</a></p>";
185 } else {
186 dialogHtml += "<p>There are no empty modules to remove.</p>";
187 }
188 dWidth = 400;
189 dHeight = 500;
190 dTitle = "Remove empty modules";
191 break;
192
193
194 case "ConfirmRemoveEmptyAssignmentGroups":
195 if (dialogData["assignment_groups"].length > 0) {
196 dialogHtml += "<p class='text-center'>The following assignment groups are empty:</p>";
197 dialogHtml += "<ul>";
198 $.each(dialogData["assignment_groups"], function(i, gItem) {
199 dialogHtml += "<li>" + gItem.id + " - " + gItem.name + "</li>";
200 });
201 dialogHtml += "</ul>";
202 dialogHtml += "<p class='text-center'><a class='btn btn-danger' onClick='window.canvasExtension.removeEmptyAssignmentGroups();'>REMOVE THESE ASSIGNMENT GROUPS</a></p>";
203 } else {
204 dialogHtml += "<p>There are no empty assignment groups to remove.</p>";
205 }
206 dWidth = 400;
207 dHeight = 500;
208 dTitle = "Remove empty assignment groups";
209 break;
210
211 case "OutcomeRemoveEmptyModules":
212 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " empty modules have been removed.</p>";
213 dialogHtml += "<p class='text-center'>Please refresh the modules page to see the updates.</p>";
214 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
215 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
216 dWidth = 400;
217 dHeight = 450;
218 dTitle += "Empty modules removed";
219 break;
220
221 case "OutcomeRemoveEmptyAssignmentGroups":
222 dialogHtml += "<p class='text-center'>" + dialogData["number"] + " empty assignment groups have been removed.</p>";
223 dialogHtml += "<p class='text-center'>Please refresh the assignments page to see the updates.</p>";
224 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
225 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
226 dWidth = 400;
227 dHeight = 450;
228 dTitle += "Empty assignment groups removed";
229 break;
230
231 case "EmptyItems":
232 dialogHtml += "<p><em>Note: You will have to refresh the Modules page after any removals to see updates.</em></p>";
233 dialogHtml += "<p>The following pages are empty (may take a while to load):</p>";
234 dialogHtml += "<table id='emptyPageList' class='table'><thead><tr><th>id</th><th>type</th><th>title</th><th>link</th><th>delete?</th></tr></thead><tbody></tbody></table>";
235 dialogHtml += "<div class='loading text-center'><img src='/images/ajax-reload-animated.gif'> Loading.</div>";
236 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.location.reload();'>Refresh page</a></p>";
237 dialogHtml += "<p class='text-center'><a class='btn btn-info' href='/courses/" + window.currentCourse + "/undelete'>Undelete items</a></p>";
238 dWidth = 1000;
239 dTitle = "Remove empty pages/dicussions/assignments/quizzes";
240 break;
241
242 case "AddGroups":
243 if (dialogData["groupCategories"].length > 0) {
244 dialogHtml += "<p>Add group names on separate lines.</p>";
245 dialogHtml += "<p><strong>Group set</strong>: <select>";
246 $.each(dialogData["groupCategories"], function(i, gItem) {
247 dialogHtml += "<option value='" + gItem.id + "'>" + gItem.name + "</option>";
248 });
249 dialogHtml += "</select></p>";
250 dialogHtml += "<p class='text-center'><textarea style='width: 90%; height: 100px;'></textarea></p>";
251 dialogHtml += "<p class='text-center'><a class='btn btn-warning' onClick='window.canvasExtension.addGroups($(window.canvasExtension.dialogId+\" select option:selected\").val());'>Add groups</a></p>";
252 } else {
253 dialogHtml += "<p>There are no Group Categories. Please add a group category from the People tab.</p>";
254 }
255 dWidth = 500;
256 dHeight = 500;
257 dTitle = "Add groups";
258 break;
259
260 case "OutcomeAddGroups":
261 if (dialogData["groupNames"].length > 0) {
262 dialogHtml += "<p class='text-center'>" + dialogData["groupNames"].length + " groups added.</p>";
263 dialogHtml += "<p>" + dialogData["groupNames"].join(", ") + "</p>";
264 } else {
265 dialogHtml += "<p>No groups added.</p>"
266 }
267 dWidth = 400;
268 dHeight = 300;
269 dTitle = "Added groups";
270 break;
271
272 case "ManageGradeBookColumns":
273 dialogHtml += "<table id='emptyPageList' class='table'><thead><tr><th>title</th><th>hidden</th><th>teacher_notes</th><th>update?</th><th>delete?</th></tr></thead><tbody>";
274 if(window.canvasExtension.gradeBookColumns.length > 0){
275 $.each(window.canvasExtension.gradeBookColumns, function(i, gItem){
276 console.log(gItem);
277 dialogHtml += "<tr>";
278 dialogHtml += "<td><input class='gradebookcolumn_title' type='text' value='"+gItem.title+"'></input></td>";
279 dialogHtml += (gItem.hidden) ? "<td><input type='checkbox' class='gradebookcolumn_hidden' checked='checked'></input></td>" : "<td><input type='checkbox' class='gradebookcolumn_hidden'></input></td>";
280 dialogHtml += (gItem.teacher_notes) ? "<td><input type='checkbox' class='gradebookcolumn_teacher_notes' checked='checked'></input></td>" : "<td><input type='checkbox' class='gradebookcolumn_teacher_notes'></input></td>";
281 dialogHtml += "<td><a class='btn btn-success' onClick='window.canvasExtension.updateGradeBookColumn($(this), "+gItem.id+")'><i class='icon-refresh'> </i></a></td>";
282 dialogHtml += "<td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteGradeBookColumn($(this), "+gItem.id+");'><i class='icon-trash'> </i></a></td>";
283 dialogHtml += "</tr>";
284 });
285 }else{
286 dialogHtml += "<tr><td colspan='5'><p class='text-center'>There are no custom gradebook columns in this unit.</p></td></tr>";
287 }
288 dialogHtml += "</tbody></table>";
289 dialogHtml += "<hr/>";
290 dialogHtml += "<div id='addNewGradeBookColumn'>";
291 dialogHtml += "<p><strong>Add new gradebook column</strong></p>";
292 dialogHtml += "<p><strong>Title:</strong> <input class='gradebookcolumn_title' type='text'></input>";
293 dialogHtml += " <input type='checkbox' class='gradebookcolumn_hidden'></input> <strong>Hidden?</strong> ";
294 dialogHtml += " <input type='checkbox' class='gradebookcolumn_teacher_notes' checked='checked'><strong>Teacher notes?</strong> ";
295 dialogHtml += " <a class='btn btn-warning' onClick='window.canvasExtension.addGradeBookColumn();'>Add column</a></p>";
296 dialogHtml += "</div>"
297 dWidth = 800;
298 dTitle = "Manage gradebook columns";
299 break;
300
301
302 case "Message":
303 dialogHtml += dialogData["message"];
304 dWidth = 400;
305 dHeight = 300;
306 dTitle = dialogData["title"];
307 break;
308
309 default:
310 //nothing
311 }
312
313 //set dialog properties, and open the dialog window
314 window.canvasExtension.dialog.html("");
315 window.canvasExtension.dialog.append(dialogHtml);
316 // have to set the title in a few ways, the title doesn't change after the first time it runs
317 window.canvasExtension.dialog.attr("title", dTitle);
318 $('.ui-dialog-title', window.canvasExtension.dialog).html(dTitle);
319 window.canvasExtension.dialog.dialog({
320 "title": dTitle,
321 buttons: [{ text: "Close", click: function() { $(this).dialog("close"); } }]
322 });
323 window.canvasExtension.dialog.dialog("option", "width", dWidth);
324 window.canvasExtension.dialog.dialog("option", "height", dHeight);
325 window.canvasExtension.dialog.dialog("option", "position", dPosition);
326}
327
328
329
330// Expand all modules/assignments
331window.canvasExtension.contractAll = function() {
332 $('.ig-header-title.collapse_module_link:visible, .element_toggler[aria-expanded="true"]:visible').click();
333 $('.item-group-container .item-group-condensed, .ig-header').attr('style', 'padding: 0;').addClass('contractedExpanderGroups');
334 $('.item-group-container .ig-header button').attr('style', 'padding: 0 5px').addClass('contractedExpanderGroups');
335 //$('.ig-header-title, .expand_module_link').attr('style', 'margin: 0;');
336}
337
338// Contract all modules/assignments
339window.canvasExtension.expandAll = function() {
340 $('.ig-header-title.expand_module_link:visible, .element_toggler[aria-expanded="false"]:visible').click();
341 $('.contractedExpanderGroups').attr('style', '').removeClass('contractedExpanderGroups');
342}
343
344// publish all items on page
345window.canvasExtension.publishAll = function() {
346 //publish pages
347 $('#context_modules_sortable_container .context_module_item .ig-admin span[role="button"] > i').each(function() {
348 if ($(this).hasClass("icon-unpublish")) {
349 $(this).parent().trigger("click");
350 }
351 });
352 //publish modules
353 $('#context_modules_sortable_container div.ig-header > .ig-header-admin span[role="button"] > i').each(function() {
354 if ($(this).hasClass("icon-unpublish")) {
355 $(this).parent().trigger("click");
356 }
357 });
358}
359
360// Unpublish all items on page
361window.canvasExtension.unpublishAll = function() {
362 //unpublish pages
363 $('#context_modules_sortable_container .context_module_item .ig-admin span[role="button"] > i').each(function() {
364 if ($(this).hasClass("icon-publish")) {
365 $(this).parent().trigger("click");
366 }
367 });
368 //unpublish modules
369 $('#context_modules_sortable_container div.ig-header > .ig-header-admin span[role="button"] > i').each(function() {
370 if ($(this).hasClass("icon-publish")) {
371 $(this).parent().trigger("click");
372 }
373 });
374}
375
376// Set up page dialog
377window.canvasExtension.setupEmptyItems = function() {
378 window.canvasExtension.runDialog("EmptyItems");
379 window.canvasExtension.getEmptyItems();
380}
381
382// list all coueses in an account
383window.canvasExtension.getEmptyItems = function() {
384 //reset variables
385 window.canvasExtension.allItems = [];
386 window.canvasExtension.allItemsAjax = [];
387 // LIST ALL ITEMS
388 window.canvasExtension.listItemsFromCourse(
389 ["Page", "Assignment", "Discussion", "Quiz"], // types of search
390 { "Page": 1, "Assignment": 1, "Discussion": 1, "Quiz": 1 }, // type paging counters
391 { "Page": false, "Assignment": false, "Discussion": false, "Quiz": false }, // type done yet?
392 window.canvasExtension.allItems, // results array for all items
393 window.canvasExtension.allItemsAjax, // array for all ajax objs
394 window.canvasExtension.resultsEmptyItems // callback
395 );
396}
397
398window.canvasExtension.resultsEmptyItems = function() {
399 $(window.canvasExtension.dialogId + " .loading").remove();
400 $.each(window.canvasExtension.allItems, function(i, item) {
401 switch (item.type) {
402 case "Page":
403 if (!item.body) {
404 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.page_id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.url + "\")'><i class='icon-trash'> </i></a></td></p>");
405 }
406 break;
407 case "Assignment":
408 if (!item.description) {
409 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.name + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
410 }
411 break;
412 case "Discussion":
413 if (!item.message) {
414 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
415 }
416 break;
417 case "Quiz":
418 if (!item.description && item.question_count <= 0) {
419 $(window.canvasExtension.dialogId + " #emptyPageList tbody").append("<tr><td>" + item.id + "</td><td>" + item.type + "</td><td>" + item.title + "</td><td><a href='" + item.html_url + "' target='_blank' class='button'><i class='icon-link'> </i></a></td><td><a class='btn btn-danger' onClick='window.canvasExtension.confirmDeleteItem($(this), \"" + item.type + "\",\"" + item.id + "\")'><i class='icon-trash'> </i></a></td></p>");
420 }
421 break;
422 default:
423 }
424 });
425}
426
427/**
428 * Confirm the deletion of an item:
429 * Change the button that was pressed into a confirmation button, that when
430 * pressed, will trigger a function to remove the item.
431 *
432 * @param {$element} element - The jQuery element that triggered the call
433 * @param {string} type - The Canvas 'type' of the item, i.e. Page, Assignment, Discussion, Quiz
434 * @param {string} id - The id of the Canvas item
435 */
436window.canvasExtension.confirmDeleteItem = function(element, type, id) {
437 // set up the confirmation button
438 var confirmElement = "<a class='btn btn-danger' onClick='window.canvasExtension.removeItem(\"" + type + "\",\"" + id + "\");$(this).closest(\"tr\").remove();'>Are you sure?</a>";
439 // replace the @param element with the confirmation button
440 $(element).replaceWith(confirmElement);
441}
442
443
444/**
445 * Remove an item from the current course
446 *
447 * @param {string} type - The Canvas 'type' of the item, i.e. Page, Assignment, Discussion, Quiz
448 * @param {string} id - The id of the Canvas item
449 */
450window.canvasExtension.removeItem = function(type, id) {
451 var removeURL = "";
452 // generate the ajax URL that'll remove the item
453 switch (type) {
454 case "Page":
455 removeURL = "/api/v1/courses/" + window.currentCourse + "/pages/" + id
456 break;
457 case "Assignment":
458 removeURL = "/api/v1/courses/" + window.currentCourse + "/assignments/" + id
459 break;
460 case "Discussion":
461 removeURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics/" + id
462 break;
463 case "Quiz":
464 removeURL = "/api/v1/courses/" + window.currentCourse + "/quizzes/" + id
465 break;
466 default:
467 //ignore
468 }
469 // remove the item
470 $.ajax({
471 type: "DELETE",
472 url: removeURL,
473 dataType: "json",
474 headers: {
475 'Accept': 'application/json',
476 'Content-Type': 'application/json'
477 },
478 success: function(data, textStatus, xhr) {
479 console.log(textStatus, xhr.status, data);
480 },
481 error: function(xhr, textStatus, errorThrown) {
482 console.log("error: " + errorThrown);
483 }
484 });
485}
486
487/**
488 * Set up the Add Groups dialog:
489 * Get the current set of group categories, and pass them to the AddGroups dialog
490 * to use.
491 *
492 */
493window.canvasExtension.setupAddGroups = function() {
494 $.getJSON("/api/v1/courses/" + window.currentCourse + "/group_categories", function(groupCategoryData) {
495 var groupCategories = [];
496 $.each(groupCategoryData, function(i, groupCategory) {
497 groupCategories.push({
498 "id": groupCategory.id,
499 "name": groupCategory.name
500 });
501 });
502 window.canvasExtension.runDialog("AddGroups", { "groupCategories": groupCategories });
503 });
504}
505
506
507/**
508 * Add the groups from the text entred, to the course
509 *
510 * @param {string} groupCategory - The id of the group category to add the groups to.
511 */
512window.canvasExtension.addGroups = function(groupCategory) {
513 var groupNames = [];
514 // read the text area, split each new line into a string for a new group name
515 $.each($(window.canvasExtension.dialogId + ' textarea').attr('value').split("\n"), function() {
516 var groupId = this.trim();
517 if (groupId != "") groupNames.push(groupId);
518 });
519 // create the groups under the @groupCategory
520 $.each(groupNames, function(g, groupName) {
521 $.ajax({
522 type: "POST",
523 url: "/api/v1/group_categories/" + groupCategory + "/groups",
524 dataType: "json",
525 headers: {
526 'Accept': 'application/json',
527 'Content-Type': 'application/json'
528 },
529 data: '{"name":"' + groupName + '"}',
530 success: function(data, textStatus, xhr) {
531 console.log(textStatus, xhr.status, data);
532 },
533 error: function(xhr, textStatus, errorThrown) {
534 console.log("error: " + errorThrown);
535 }
536 });
537 });
538 // run the outcome dialog, returning the list of group names
539 window.canvasExtension.runDialog("OutcomeAddGroups", { "groupNames": groupNames });
540}
541
542
543/**
544 * Confirm the removal of all of the empty modules:
545 * Generate a list of empty modules, and send them to the confirmation dialog.
546 *
547 */
548window.canvasExtension.confirmRemoveEmptyModules = function() {
549 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
550 // search for modules in the current course, check to see if they are empty
551 $.getJSON("/api/v1/courses/" + window.currentCourse + "/modules?include=items&per_page=100", function(moduleData) {
552 var modulesForRemoval = [];
553 $.each(moduleData, function(i, mItem) {
554 if (mItem.items.length > 0) {
555 // ignore - not empty
556 } else {
557 modulesForRemoval.push(mItem);
558 }
559 });
560 // run the confirmation dialog
561 window.canvasExtension.runDialog("ConfirmRemoveEmptyModule", { "modules": modulesForRemoval });
562 });
563}
564
565/**
566 * Confirm the removal of all of the empty assignment groups:
567 * Generate a list of empty assignment groups, and send them to the confirmation dialog.
568 *
569 */
570window.canvasExtension.confirmRemoveEmptyAssignmentGroups = function() {
571 // search for assignment_groups in the current course, check to see if they are empty
572 $.getJSON("/api/v1/courses/" + window.currentCourse + "/assignment_groups?include=assignments&per_page=100", function(groupData) {
573 console.log(groupData);
574 var assignmentGroupsForRemoval = [];
575 $.each(groupData, function(i, gItem) {
576 if (gItem.assignments.length > 0) {
577 // ignore - not empty
578 } else {
579 assignmentGroupsForRemoval.push(gItem);
580 }
581 });
582 // run the confirmation dialog
583 window.canvasExtension.runDialog("ConfirmRemoveEmptyAssignmentGroups", { "assignment_groups": assignmentGroupsForRemoval });
584 });
585}
586
587/**
588 * Remove the empty modules from the course
589 *
590 */
591window.canvasExtension.removeEmptyModules = function() {
592 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
593 // search all of the modules of the current course
594 $.getJSON("/api/v1/courses/" + window.currentCourse + "/modules?include=items&per_page=100", function(moduleData) {
595 var mCount = 0;
596 $.each(moduleData, function(i, mItem) {
597 if (mItem.items.length > 0) {
598 // ignore - not empty
599 } else {
600 mCount++;
601 // delete the empty module
602 $.ajax({
603 type: "DELETE",
604 url: "/api/v1/courses/" + window.currentCourse + "/modules/" + mItem.id,
605 dataType: "json",
606 headers: {
607 'Accept': 'application/json',
608 'Content-Type': 'application/json'
609 },
610 success: function(data, textStatus, xhr) {
611 console.log(textStatus, xhr.status, data);
612 },
613 error: function(xhr, textStatus, errorThrown) {
614 console.log("error: " + errorThrown);
615 }
616 });
617 }
618 });
619 // show the outcome dialog, with a count of the number of modules removed.
620 window.canvasExtension.runDialog("OutcomeRemoveEmptyModules", { "number": mCount });
621 });
622}
623
624/**
625 * Remove the empty assignment groups from the course
626 *
627 */
628window.canvasExtension.removeEmptyAssignmentGroups = function() {
629 // note: that Canvas is restricted to only get 100 modules per page, if there are more, then you'll have to build in paging.
630 // search all of the modules of the current course
631 $.getJSON("/api/v1/courses/" + window.currentCourse + "/assignment_groups?include=assignments&per_page=100", function(assignmentGroupData) {
632 var gCount = 0;
633 $.each(assignmentGroupData, function(i, gItem) {
634 if (gItem.assignments.length > 0) {
635 // ignore - not empty
636 } else {
637 gCount++;
638 // delete the empty module
639 $.ajax({
640 type: "DELETE",
641 url: "/api/v1/courses/" + window.currentCourse + "/assignment_groups/" + gItem.id,
642 dataType: "json",
643 headers: {
644 'Accept': 'application/json',
645 'Content-Type': 'application/json'
646 },
647 success: function(data, textStatus, xhr) {
648 console.log(textStatus, xhr.status, data);
649 },
650 error: function(xhr, textStatus, errorThrown) {
651 console.log("error: " + errorThrown);
652 }
653 });
654 }
655 });
656 // show the outcome dialog, with a count of the number of modules removed.
657 window.canvasExtension.runDialog("OutcomeRemoveEmptyAssignmentGroups", { "number": gCount });
658 });
659}
660
661
662/**
663 * Remove dates from Assignment pages
664 *
665 */
666window.canvasExtension.removeAssignmentDates = function() {
667 // get all of the assignments in the courses
668 $.ajax({
669 type: "get",
670 url: "/api/v1/courses/" + window.currentCourse + "/assignments?per_page=100",
671 crossDomain: true,
672 cache: false,
673 dataType: "json",
674 contentType: "application/json; charset=UTF-8",
675 success: function(data, textStatus, xhr) {
676 for (var i = 0; i < data.length; i++) {
677 // remove the due date, and start/end dates for each assignment
678 $.ajax({
679 type: "PUT",
680 url: "/api/v1/courses/" + window.currentCourse + "/assignments/" + data[i].id,
681 dataType: "json",
682 headers: {
683 'Accept': 'application/json',
684 'Content-Type': 'application/json'
685 },
686 data: '{"assignment":{"due_at":"","lock_at":"","unlock_at":""}}',
687 success: function(data, textStatus, xhr) {
688 console.log(textStatus, xhr.status, data);
689 },
690 error: function(xhr, textStatus, errorThrown) {
691 console.log("error: " + errorThrown);
692 }
693 });
694 }
695 // show the outcome dialog, send then number of assignments that were updated
696 window.canvasExtension.runDialog("OutcomeRemoveAssignmentDates", { "number": data.length });
697 },
698 error: function(xhr, textStatus, errorThrown) {
699 console.log("error: " + errorThrown);
700 }
701 });
702}
703
704/**
705 * LIST ALL ITEMS FROM COURSE BY TYPE
706 *
707 *
708 * @param {array} itemTypes - set of item types, i.e. ["Page", "Assignment", "Discussion", "Quiz"]
709 * @param {object} itemTypesPageCount - object with page counter matching types
710 * @param {object} resultsByType - object with resutls by type
711 * @param {global array} itemResults - array for item results
712 * @param {global array} itemsResultsAjax - array for ajax calls
713 * @param {requestCallback} callback - callback function, this runs after all of the items have been retrieved
714 */
715window.canvasExtension.listItemsFromCourse = function(itemTypes, itemTypesPageCount, resultsByType, itemResults, itemsResultsAjax, callback) {
716 $.each(itemTypes, function(i, itemType) {
717 var itemType = itemType;
718 var itemTypeURL = "";
719 var itemURL = "";
720 var itemIdOn = "";
721
722 // get URLs for item calls. Canvas is limited to 100 items per 'page', so listItemsFromCourse may be called multiple times
723 switch (itemType) {
724 case "Page":
725 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/pages?sort=title&page=" + itemTypesPageCount[itemType] + "&per_page=100"
726 itemURL = "/api/v1/courses/" + window.currentCourse + "/pages/"
727 itemIdOn = 'url'
728 break;
729 case "Assignment":
730 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/assignments?page=" + itemTypesPageCount[itemType] + "&per_page=100"
731 itemURL = "/api/v1/courses/" + window.currentCourse + "/assignments/"
732 itemIdOn = 'id'
733 break;
734 case "Discussion":
735 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics?page=" + itemTypesPageCount[itemType] + "&per_page=100"
736 itemURL = "/api/v1/courses/" + window.currentCourse + "/discussion_topics/"
737 itemIdOn = 'id'
738 break;
739 case "Quiz":
740 itemTypeURL = "/api/v1/courses/" + window.currentCourse + "/quizzes?page=" + itemTypesPageCount[itemType] + "&per_page=100"
741 itemURL = "/api/v1/courses/" + window.currentCourse + "/quizzes/"
742 itemIdOn = 'id'
743 break;
744 default:
745 }
746
747 itemsResultsAjax.push(
748 $.ajax({
749 type: "GET",
750 url: itemTypeURL,
751 success: function(data, textStatus, xhr) {
752 $.each(data, function(t, tItem) {
753 itemsResultsAjax.push($.ajax({
754 type: "GET",
755 url: itemURL + tItem[itemIdOn],
756 success: function(data) {
757 data.type = itemType;
758 // add item to results
759 itemResults.push(data);
760 }
761 }));
762 });
763 // will throw out of loop if number of courses > 10000 -- if you have more than 10000 units, increase the pNum check
764 if (xhr.getResponseHeader('Link').indexOf('rel="next"') > 0 && itemTypesPageCount[itemType] < 100) {
765 itemTypesPageCount[itemType]++;
766 // get next page
767 // keep getting items, get next set for this item type
768 window.canvasExtension.listItemsFromCourse([itemType], itemTypesPageCount, resultsByType, itemResults, itemsResultsAjax, callback);
769 } else {
770 resultsByType[itemType] = true;
771 //check all items for all item types are done
772 var allTrue = true;
773 $.each(resultsByType, function(n, nDone) {
774 if (!nDone) allTrue = false;
775 });
776 // if they're all done, do results
777 if (allTrue) {
778 // when all the ajax is done, run the callback
779 $.when.apply(undefined, itemsResultsAjax).then(callback);
780 }
781 }
782 },
783 error: function(xhr, textStatus, errorThrown) {
784 console.log("error: " + errorThrown);
785 }
786 })
787 );
788 });
789}
790
791
792
793/**
794 * setupGradeBookColumns
795 */
796window.canvasExtension.setupGradeBookColumns = function(){
797 window.canvasExtension.listGradeBookColumns(function(data){
798 window.canvasExtension.gradeBookColumns = data;
799 window.canvasExtension.runDialog("ManageGradeBookColumns");
800 });
801}
802
803/**
804 * LIST - GET /api/v1/courses/:course_id/custom_gradebook_columns
805 * @param {function} callback
806 */
807window.canvasExtension.listGradeBookColumns = function(callback){
808 $.getJSON("/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns?include_hidden=true", function(data) {
809 callback(data);
810 //window.canvasExtension.newGradeBookColumn("New column", gradeBookColumns.length+1, false, true)
811 });
812}
813
814/**
815 * Confirm the deletion of an item:
816 * Change the button that was pressed into a confirmation button, that when
817 * pressed, will trigger a function to remove the item.
818 *
819 * @param {$element} element - The jQuery element that triggered the call
820 * @param {string} id - The id of the gradebook column
821 */
822window.canvasExtension.confirmDeleteGradeBookColumn = function(element, id){
823 // set up the confirmation button
824 var confirmElement = "<a class='btn btn-danger' onClick='window.canvasExtension.deleteGradeBookColumn(\"" + id + "\");$(this).closest(\"tr\").remove();'>Are you sure?</a>";
825 // replace the @param element with the confirmation button
826 $(element).replaceWith(confirmElement);
827}
828
829
830/**
831 * LIST - GET /api/v1/courses/:course_id/custom_gradebook_columns
832 * @param {function} callback
833 */
834window.canvasExtension.deleteGradeBookColumn = function(id){
835 // remove the gradebook column
836 $.ajax({
837 type: "DELETE",
838 url: "/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns/"+id,
839 dataType: "json",
840 headers: {
841 'Accept': 'application/json',
842 'Content-Type': 'application/json'
843 },
844 success: function(data, textStatus, xhr) {
845 console.log(textStatus, xhr.status, data);
846 window.canvasExtension.setupGradeBookColumns();
847 },
848 error: function(xhr, textStatus, errorThrown) {
849 console.log("error: " + errorThrown);
850 }
851 });
852}
853
854
855
856/**
857 * UPDATE - PUT /api/v1/courses/:course_id/custom_gradebook_columns/:id
858 * @param {$element} update button that called function
859 * @param {string} id of gradebook column
860 */
861window.canvasExtension.updateGradeBookColumn = function(element, id){
862 var column_title = $(element).closest('tr').find('.gradebookcolumn_title').attr('value');
863 var column_hidden = ($(element).closest('tr').find('.gradebookcolumn_hidden').attr('checked')) ? true : false;
864 var column_teacher_notes = ($(element).closest('tr').find('.gradebookcolumn_teacher_notes').attr('checked')) ? true : false;
865 console.log("column_title", column_title, "column_hidden", column_hidden, "column_teacher_notes", column_teacher_notes);
866 $.ajax({
867 type: "PUT",
868 url: "/api/v1/courses/" + window.currentCourse + "/custom_gradebook_columns/" + id,
869 dataType: "json",
870 headers: {
871 'Accept': 'application/json',
872 'Content-Type': 'application/json'
873 },
874 data: '{"column": {"title": "'+column_title+'", "hidden": "'+column_hidden+'", "teacher_notes": "'+column_teacher_notes+'"}}',
875 success: function(data, textStatus, xhr) {
876 console.log(textStatus, xhr.status, data);
877 window.canvasExtension.setupGradeBookColumns();
878 },
879 error: function(xhr, textStatus, errorThrown) {
880 console.log("error: " + errorThrown);
881 }
882 });
883}
884
885
886/**
887 * Add gradebook column
888 */
889window.canvasExtension.addGradeBookColumn = function(){
890 var column_title = $(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_title").attr('value');
891 var column_position = window.canvasExtension.gradeBookColumns.length+1;
892 var column_hidden = ($(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_hidden").attr('checked')) ? true : false;
893 var column_teacher_notes = ($(window.canvasExtension.dialogId + " #addNewGradeBookColumn .gradebookcolumn_teacher_notes").attr('checked')) ? true : false;
894 window.canvasExtension.createGradeBookColumn(column_title, column_position, column_hidden, column_teacher_notes, window.canvasExtension.setupGradeBookColumns);
895}
896
897
898/**
899 * NEW COLUMN - POST /api/v1/courses/:course_id/custom_gradebook_columns
900 * @param {Required string} column_title - no description
901 * @param {integer} column_position - The position of the column relative to other custom columns
902 * @param {boolean} column_hidden - Hidden columns are not displayed in the gradebook
903 * @param {boolean} column_teacher_notes - Set this if the column is created by a teacher. The gradebook only supports one teacher_notes column.
904 * @param {function} callback
905 */
906window.canvasExtension.createGradeBookColumn = function(column_title, column_position, column_hidden, column_teacher_notes, callback){
907 $.ajax({
908 type: "POST",
909 url: "/api/v1/courses/"+window.currentCourse+"/custom_gradebook_columns",
910 dataType: "json",
911 headers: {
912 'Accept': 'application/json',
913 'Content-Type': 'application/json'
914 },
915 data: '{"column":{"title": "'+column_title+'", "position": '+column_position+', "hidden": '+column_hidden+',"teacher_notes": '+column_teacher_notes+'}}',
916 success: function(data, textStatus, xhr) {
917 console.log(textStatus, xhr.status, data);
918 callback();
919 },
920 error: function(xhr, textStatus, errorThrown) {
921 console.log("error: " + errorThrown);
922 }
923 });
924}
925
926
927
928
929// ------------------ WIP::COURSES -----------------
930
931
932window.canvasExtension.allCourses = [];
933
934// list all coueses in an account
935window.canvasExtension.listAllCourses = function() {
936 window.canvasExtension.allCourses = [];
937 var nextPage = 1;
938 window.canvasExtension.listNextCourses(nextPage);
939}
940
941window.canvasExtension.listNextCourses = function(pNum) {
942 $.ajax({
943 type: "GET",
944 url: "/api/v1/accounts/1/courses?page=" + pNum + "&per_page=100",
945 dataType: "json",
946 headers: {
947 'Accept': 'application/json',
948 'Content-Type': 'application/json'
949 },
950 success: function(data, textStatus, xhr) {
951 //console.log(xhr.getResponseHeader('Link'));
952 $.each(data, function(i, tCourse) {
953 window.canvasExtension.allCourses.push({
954 "name": tCourse.name,
955 "id": tCourse.id
956 });
957 //$(window.canvasExtension.dialogId+" #courseList tbody").append('<tr><td>'+tCourse.id+'</td><td>'+tCourse.name+'</td></tr>');
958 });
959 //will throw out of loop if number of courses > 10000 -- if you have more than 10000 units, increase the pNum check
960 if (xhr.getResponseHeader('Link').indexOf('rel="next"') > 0 && pNum < 100) {
961 pNum++;
962 window.canvasExtension.listNextCourses(pNum);
963 } else {
964 window.canvasExtension.addCourseResults();
965 }
966 },
967 error: function(xhr, textStatus, errorThrown) {
968 console.log("error: " + errorThrown);
969 }
970 });
971}
972
973window.canvasExtension.addCourseResults = function() {
974 console.log(window.canvasExtension.allCourses);
975}
976
977
978//---- RUN THE INIT ------------------------------
979
980window.canvasExtension.initCanvasExtensionMenu();