NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Task Bar // @namespace CCAU // @description Automate course copies // @match https://*.instructure.com/courses/* // @version 0.2.1 // @author Cappiebara // @grant none // @license GPL-3.0-or-later // ==/UserScript== "use strict"; (() => { // out/ccau.js function isAdmin() { const adminButton = document.querySelector("#global_nav_accounts_link"); return adminButton ? true : false; } function getCourseID() { return window.location.href.match(/courses\/(\d+)/)?.[1] ?? "NO_COURSE_ID"; } async function isLiveCourse() { const response = await fetch("https://se.instructure.com/api/v1/courses/" + getCourseID()); const data = await response.json(); if (!data.start_at) { return new Promise((resolve) => resolve(false)); } return new Date(data.start_at) < /* @__PURE__ */ new Date(); } // out/task.js function getTasks() { return TASKS.tasks; } var TASKS = { "tasks": [ { "help": "Click the --> button to start the copy", "name": "Begin Course Copy", "path": "" }, { "help": "If there is any content, don't do the copy", "name": "Check for Content", "path": "modules" }, { "help": "Delete 'Student Introductions' and 'Questions and Answers'", "name": "Delete Discussions", "path": "discussion_topics" }, { "help": "Delete all pages except University Information", "name": "Delete Pages", "path": "pages" }, { "help": "Double check the email to make sure you copy the right course", "name": "Copy Content", "path": "content_migrations" }, { "help": "Copy the current holiday from the SE University Holidays course (select content)", "name": "Copy Holiday", "path": "content_migrations" }, { "help": "Delete any duplicate menu items. The original item is the first one listed", "name": "Delete Duplicate Menu Items", "path": "settings/configurations#tab-tools" }, { "help": "Move the items in the navigation menu to this order:\n\nHome\nAnnouncements\nSyllabus\nModules\nGrades\nSubmit Grades\nPeople\nSE Email\nHenry G. Bennett Library\nTech Support\nTutor.com\nYuJa\nPanorama\nLockdown Browser\nItem Banks\nCredentials\nFollett Discover\n(whatever else happens to be there)\n", "name": "Fix Menu Order", "path": "settings#tab-navigation" }, { "help": "Click the Auto-Move button, then the arrow in the bottom left", "name": "Move Content", "path": "modules" }, { "help": "Click the Remove Empty button, then the arrow in the bottom left", "name": "Delete Empty Modules", "path": "modules" }, { "help": "Click the Add Dates button and wait for them to publish and move into place", "name": "Add Date Headers", "path": "modules" }, { "help": "Delete any GOLD Orientation and the University Information items which are NOT at the bottom of the START HERE module", "name": "Delete Old START HERE Items", "path": "modules" }, { "help": "Move the holiday module into place", "name": "Move Holiday", "path": "modules" }, { "help": "Delete any undeployed GOLD Orientation assignments and empty categories", "name": "Delete Old GOLD and Empty Groups", "path": "assignments" }, { "help": "Use https://k.ngn.tf/8775a to fix broken images; manually fix broken module links", "name": "Fix Homepage", "path": "wiki" }, { "help": "Make sure the dates are correct, especially regarding the holiday-adjacent weeks", "name": "Check Assignment Dates", "path": "assignments" }, { "help": "Check for Blackboard references, as well as getting the grade total / weights", "name": "Check Syllabus", "path": "assignments/syllabus" }, { "help": "Make sure it matches the syllabus", "name": "Check Gradebook", "path": "gradebook" }, { "help": "If any real links are broken, inform the professor", "name": "Run Link Validator", "path": "link_validator" }, { "help": "Ensure that all the steps on the Google Sheet have been followed. If something there isn't covered in the automation, lmk", "name": "Check Google Sheet", "path": "" }, { "help": "Excellent work, 47. The money has been wired to your account", "name": "Done", "path": "" } ] }; // out/ui.js function addButton(task, fn, label) { const slot = document.querySelector(".right-of-crumbs"); const button = document.createElement("a"); button.textContent = label; button.classList.add("btn"); button.setAttribute("tabindex", "0"); button.addEventListener("click", fn, false); button.setAttribute("title", task.help); slot?.insertAdjacentElement("beforebegin", button); } function goto(path_) { const id = getCourseID(); const newLoc = `https://se.instructure.com/courses/${id}/${path_}`; if (window.location.href === newLoc) { window.location.reload(); } else { window.location.href = newLoc; } } function getCurrentTask() { const id = getCourseID(); const taskNum = Number(localStorage.getItem(`ccau_${id}_task`)); return isNaN(taskNum) ? null : taskNum; } function setCurrentTask(taskNum) { const id = getCourseID(); localStorage.setItem(`ccau_${id}_task`, taskNum.toString()); } // out/index.js async function main() { if (!isAdmin()) { throw new Error("Only admins can use CCAU"); } if (await isLiveCourse()) { throw new Error("CCAU is disabled in live courses"); } const tasks = getTasks(); const taskNum = getCurrentTask() ?? 0; const task = tasks[taskNum]; const prevNum = Math.max(0, taskNum - 1); const prev = tasks[prevNum]; const nextNum = (taskNum + 1) % tasks.length; const next = tasks[nextNum]; addButton(prev, () => { setCurrentTask(prevNum); goto(prev.path); }, "<--"); addButton(task, () => { alert(task.help); }, task.name); addButton(next, () => { setCurrentTask(nextNum); goto(next.path); }, "-->"); } main(); })();