Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
da-stoi committed Nov 11, 2023
0 parents commit 7daadf0
Show file tree
Hide file tree
Showing 20 changed files with 2,484 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/dist/
/node_modules/
.vscode
.DS_Store
/archives/
/promotional/
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Links
- [Project Page](https://daniel.stoiber.network/project/canvas-strikethrough)
- [Download Extension](https://chrome.google.com/webstore/detail/canvas-strikethrough/cnohgbfhedbjkglpkfbjhiikjemcjhng)

### What is it?
__Canvas Strikethrough__ is a *Chrome Extension* that allows users to mark any event on the Canvas calendar as complete. This is useful for students who want to keep track of what assignments they have completed when their instructor does not require them to submit their work through Canvas.

### How does it work?
After installing the extension, either visit the Canvas calendar, or go to a assignment/page of your choice. You will then see a new option to mark that assignment as complete.

### Features
- Mark assignments/pages as complete from the calendar.
- Mark assignments/pages as complete from the assignment/page itself.

### Things to note
- Marking an assignment as complete is only for your own reference. It does not affect your submission/grade, nor does it notify your instructor.
- This extension only works on the computer you install it on. If you mark an assignment as complete on your laptop, it will not be marked as complete on your phone.
- Due to complexities of getting the extension approved on the Chrome Web Store, the extension is not allowed to run on all pages. Unfortunately each university has their own domain for Canvas, so I have to manually add each domain to the list of allowed domains. If your university is not on the list, please open an issue on GitHub and I will add it as soon as possible.

#### Allowed Canvas Domains
Instructions on how to add your own university's Canvas domain will be added in the future. For now, if you would like to add your own domain, please open an issue on GitHub.
- `*.instructure.com`
- `canvas.wpi.edu`
- `canvas.olin.edu`
- `canvas.calpoly.edu`
- `canvas.pratt.edu`
- `canvas.ucla.edu`
- `carmen.osu.edu`
- `canvas.uw.edu`
- `bcourses.berkeley.edu`
- `online.smc.edu`
- `egator.greenriver.edu`
- `canvas.ucsd.edu`
- `canvas.ucdavis.edu`
- `canvas.vt.edu`
- `catcourses.ucmerced.edu`
- `canvas.umich.edu`
- `canvas.ubc.ca`
- `canvas.qut.edu.au`
- `canvas.csun.edu`
- `canvas.psu.edu`
- `canvas.colorado.edu`

---
[<img src="https://da-stoi.github.io/portfolio-assets/assets/chromeWebStore/availableDark.png" style="display: block; margin-left: auto; margin-right: auto;" height="50"/>](https://chrome.google.com/webstore/detail/canvas-strikethrough/cnohgbfhedbjkglpkfbjhiikjemcjhng)
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "canvas-class-average",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"clean": "rm -rf dist",
"build": "yarn clean && webpack --config webpack/webpack.config.js"
},
"keywords": [],
"author": "",
"license": "GNU GPLv3",
"dependencies": {},
"devDependencies": {
"@types/chrome": "0.0.177",
"copy-webpack-plugin": "^10.2.1",
"ts-loader": "^9.2.6",
"typescript": "^4.5.4",
"webpack": "^5.66.0",
"webpack-cli": "^4.9.1"
}
}
Binary file added public/icons/icon128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/icon16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/icon32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/icon48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "Canvas Strikethrough",
"description": "Mark assignments without deliverables as complete.",
"author": "Daniel Stoiber",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"storage"
],
"content_scripts": [
{
"matches": [
"https://*.instructure.com/*",
"https://canvas.wpi.edu/*",
"https://canvas.olin.edu/*",
"https://canvas.calpoly.edu/*",
"https://canvas.pratt.edu/*",
"https://canvas.ucla.edu/*",
"https://carmen.osu.edu/*",
"https://canvas.uw.edu/*",
"https://bcourses.berkeley.edu/*",
"https://online.smc.edu/*",
"https://egator.greenriver.edu/*",
"https://canvas.ucsd.edu/*",
"https://canvas.ucdavis.edu/*",
"https://canvas.vt.edu/*",
"https://catcourses.ucmerced.edu/*",
"https://canvas.umich.edu/*",
"https://canvas.ubc.ca/*",
"https://canvas.qut.edu.au/*",
"https://canvas.csun.edu/*",
"https://canvas.psu.edu/*",
"https://canvas.colorado.edu/*"
],
"js": [
"content.js"
],
"run_at": "document_end"
}
],
"icons": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
106 changes: 106 additions & 0 deletions src/content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { getCalendarEvents } from "./getCalendarEvents";
import { getCheckedCourses } from "./getCheckedCourses";
import { getCheckedTodos } from "./storage";
import { Todo, CalendarEvent } from "./types";
import { checkEvent } from "./updateCalendarEvent";
import { displayCheckButton } from "./displayCheckButton";

export async function calendar() {

// Get checked courses
const courseList: number[] = getCheckedCourses();

// Get all checked assignments
const checkedTodos: Todo[] = getCheckedTodos(courseList);
// const checkedTodoIds: number[] = checkedTodos.map((todo: Todo) => todo.id);

// Get all calendar events
const calendarEvents: CalendarEvent[] = getCalendarEvents();

console.log(courseList);
console.log(checkedTodos);
console.log(calendarEvents);

calendarEvents.forEach((event: CalendarEvent) => {
const { name, element } = event;

// If assignment is checked
if (checkedTodos.find((todo: Todo) => todo.name === name)) {
checkEvent(element);
}
});
}

const path = window.location.pathname;
if (path.includes('calendar')) {

// Keep track of last time DOM was modified
let domLastModified = new Date().getTime();
let lastPopupUrl = '';

// Select the target node to observe
const calendarElement = document.querySelector('#content');
const body = document.body;

if (calendarElement) {
// Options for the observer (specify which changes to observe)
const config = { childList: true, subtree: true };

// Callback function to execute when mutations are observed
const callback = function (mutationsList: any) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {

const now = new Date().getTime();
// Only allow calendar to update once every 100ms
if (now - domLastModified > 100) {
console.log('calendar change');
calendar();
domLastModified = now;
}
}
}
};

// Create an observer instance
const observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(calendarElement, config);
}

if (body) {
// Options for the observer (specify which changes to observe)
const config = { childList: true, subtree: true };

// Callback function to execute when mutations are observed
const callback = function (mutationsList: any) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {

const eventLinkElement = document.querySelector('#event-details-trap-focus > div.event-details-header > h2 > a');
if (!eventLinkElement) {
lastPopupUrl = '';
} else {
if (lastPopupUrl !== eventLinkElement.getAttribute('href')) {
console.log('popup change');
displayCheckButton();
}
lastPopupUrl = eventLinkElement.getAttribute('href') || '';
}
}
}
};

// Create an observer instance
const observer = new MutationObserver(callback);

// Start observing the target node for configured mutations
observer.observe(body, config);
}

} else if (path.includes('courses') && (path.includes('assignments') || path.includes('pages'))) {
setTimeout(() => {
displayCheckButton();
}, 1000);
}
Loading

0 comments on commit 7daadf0

Please sign in to comment.