From 5a20b24528496d666f687091971dab03fba94fdf Mon Sep 17 00:00:00 2001 From: Guy Sandler Date: Sun, 19 Apr 2026 21:43:30 -0700 Subject: [PATCH] better todolist 2 filters, due date categories --- js/content.js | 271 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 190 insertions(+), 81 deletions(-) diff --git a/js/content.js b/js/content.js index e8e3c64..f4b1633 100644 --- a/js/content.js +++ b/js/content.js @@ -451,7 +451,7 @@ function checkDashboardReady() { } else if (mutation.target == document.querySelector('#right-side')) { if (!mutation.target.querySelector(".bettercanvas-todosidebar")) { setupBetterTodo(); - loadBetterTodo(); + // loadBetterTodo(); } } } @@ -827,106 +827,215 @@ function createTodoCreateBtn(location) { // } function convertToDueDate(dueAt) { - // "2026-04-13T15:30:00Z" to Apr 4 at 3:30 PM - final = "due " + final = "due "; let date = new Date(dueAt); final += date.toLocaleString("en-US", { month: "short", day: "numeric" }); final += " at " + date.toLocaleString("en-US", { hour: "numeric", minute: "numeric", hour12: true }); return final; } // better todo html -betterTodoFilter = "tasks" +betterTodoFilter = "tasks"; +let domContainers = {}; async function createTodoSections(location) { - // make outer - let filterControl = makeElement("div", location, { "id": "better-todo-filter" }); - filterControl.innerHTML = - `
- - - -
`; - let header = makeElement("div", location, { id: "better-todo-header" }); - header.style = - "display: flex; align-items:center; justify-content:space-between;"; - header.innerHTML = "

Tasks

Wed Apr 8

"; - let mainSection = makeElement("div", location, { - id: "better-todo-main", - }); - mainSection.style = "display:flex;flex-direction:column;gap:10px;margin-top:10px;"; + if (!location.querySelector("#better-todo-header")) { + let header = makeElement("div", location, { id: "better-todo-header" }); + header.style = "display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--bcbackground-1);padding-bottom:-2px;"; + let today = new Date(); + today.setHours(0,0,0,0); + const todayString = today.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }); + header.innerHTML = ` +

Tasks

+

${todayString}

+ `; + + let filterControl = makeElement("div", location, { "id": "better-todo-filter" }); + filterControl.innerHTML = `
+ + + +
`; + + document.getElementById("announcement").addEventListener("click", () => { + betterTodoFilter = "announcements"; + moreAnnouncementCount = 0; + clearTodoList(); + createTodoSections(location); + }); + document.getElementById("assignments").addEventListener("click", () => { + betterTodoFilter = "tasks"; + moreAssignmentCount = 0; + clearTodoList(); + createTodoSections(location); + }); + document.getElementById("completed").addEventListener("click", () => { + betterTodoFilter = "completed"; + moreCompletedCount = 0; + clearTodoList(); + createTodoSections(location); + }); + + let mainSection = makeElement("div", location, { + id: "better-todo-main", + }); + mainSection.style = "display:flex;flex-direction:column;gap:10px;"; + } + let mainSection = location.querySelector("#better-todo-main"); assignments.then(data => { - // types: announcement console.log(data); data.forEach(item => { announcements = data.filter(item => item.plannable_type == "announcement"); - // announcements.sort((a, b) => new Date(a.plannable_date) - new Date(b.plannable_date)); - assignmentsDue = data.filter((item) => item.plannable_type == "assignment" && !item.submissions.submitted); - // assignmentsDue.sort((a, b) => new Date(a.plannable_date) - new Date(b.plannable_date)); - completed = data.filter(item => item.plannable_type == "assignment" && item.submissions.submitted); - // completed.sort((a, b) => new Date(a.plannable_date) - new Date(b.plannable_date)); + assignmentsDue = data.filter((item) => (item.plannable_type == "assignment" || item.plannable_type == "planner_note") && !item.submissions?.submitted && !item.planner_override?.marked_complete && !item.submissions.graded); + completed = data.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note") && (item.submissions.submitted || item.planner_override?.marked_complete || item.submissions.graded)); }); + console.log(assignmentsDue); + domContainers = {}; + const groupKeys = ["-1", "0", "1", "2", "3", "4", "5", "6", "7", "14", "21", "30", "Later"]; + for (const key of groupKeys) { + let wrapper = makeElement("div", mainSection, { + style: "display:none;margin-top:10px;", + className: "better-todo-dueheader" + }) + let label = "Due Later"; + if (key == "-1") label = "Overdue"; + else if (key == "0") label = "Due Today"; + else if (key == "1") label = "Tommorow"; + else if (key >= 2 && key < 7) label = "Due in " + key + " days"; + else if (key >= 14 && key < 30) label = "Due in " + key + " months"; + else if (key == 30) label = "Due in 1 month"; + makeElement("div", wrapper, { + textContent: label, + style: "display:flex;flex-direction:column;gap:10px;" + }) + + let listContainer = makeElement("div", wrapper, { className: "todo-group-list" }); + listContainer.style = "display:flex;flex-direction:column;gap:10px;margin-top:10px;"; + + domContainers[key] = { wrapper, listContainer }; + } if (betterTodoFilter == "tasks") { - assignmentsDue.forEach((item) => { - const courseColor = - options.custom_cards_3?.[String(item.course_id)]?.color ?? - options.custom_cards_3?.[item.course_id]?.color ?? - options.custom_cards_3?.[item.plannable.course_id]?.color ?? - "#cccccc"; + populateAssignments(); + } + }); +} - let assignment = makeElement("div", mainSection, { - class: "better-todo-assignment", - }); - // assignment.innerHTML = ` - //
${courseColor}
- // ${item.plannable.title}\ - // ${new Date(item.plannable_date).toLocaleString()} - // `; - assignment.innerHTML = ` -
-
-
- - - - - -
-
-
-
- ${item.context_name} - ${item.plannable.title} - ${convertToDueDate(item.plannable.due_at)} -
+function clearTodoList() { + document.getElementById("better-todo-main").querySelectorAll(".todo-group-list").forEach(list => { + list.innerHTML = ""; + }); + document.querySelectorAll(".better-todo-dueheader").forEach(header => { + header.remove(); + }); +} -
+function populateAssignments() { + const today = new Date(); + today.setHours(0,0,0,0); -
- `; + assignmentsDue.forEach((item) => { + let dueGroup = -1; + let dueDate = new Date(item.plannable_date); + dueDate.setHours(0,0,0,0); + const diffDays = Math.round((dueDate - today) / (1000 * 60 * 60 * 24)); + if (diffDays < 0) {dueGroup = 0;} + else if (diffDays <= 1) { dueGroup = diffDays.toString(); } + else if (diffDays <= 7) { dueGroup = diffDays.toString(); } + else if (diffDays <= 14) {dueGroup = 14;} + else if (diffDays <= 21) {dueGroup = 21;} + else if (diffDays <= 30) {dueGroup = 30;} + else {dueGroup = "Later"}; + + let assignment + const targetContainer = domContainers[dueGroup]; + if (targetContainer) { + targetContainer.wrapper.style.display = "block"; + assignment = makeElement("div", targetContainer.listContainer, { + class: "better-todo-assignment", }); } - }) - // let todoHeader = createTodoHeader(location); + const courseColor = + options.custom_cards_3?.[String(item.course_id)]?.color ?? + options.custom_cards_3?.[item.course_id]?.color ?? + options.custom_cards_3?.[item.plannable.course_id]?.color ?? + "#cccccc"; - // let todoAssignments = makeElement("ul", location, { "id": "bettercanvas-todo-list" }); - // /* - // let todoAssignments = document.createElement("ul"); - // todoAssignments.id = "bettercanvas-todo-list"; - // location.appendChild(todoAssignments); - // */ - // let announcementHeader = makeElement("h2", location, { "className": "todo-list-header", "textContent": "Announcements" }); - // let todoAnnouncements = makeElement("ul", location, { "id": "bettercanvas-announcement-list" }); - // /* - // let todoAnnouncements = document.createElement("ul"); - // todoAnnouncements.id = "bettercanvas-announcement-list"; - // location.appendChild(todoAnnouncements); - // */ - // let loader = '
'; - // for (let i = 0; i < options.num_todo_items; i++) { - // todoAssignments.innerHTML += loader; - // todoAnnouncements.innerHTML += loader; - // } + assignment.innerHTML = ` +
+
+
+ + + + + +
+
+
+
+ ${item.context_name} + ${item.plannable.title} + ${convertToDueDate(item.plannable_date)} +
+
+
+ `; + }); +} + +function populateAnnouncements() { + const today = new Date(); + today.setHours(0,0,0,0); + + announcementsDue.forEach((item) => { + let dueGroup = -1; + let dueDate = new Date(item.plannable_date); + dueDate.setHours(0,0,0,0); + const diffDays = Math.round((dueDate - today) / (1000 * 60 * 60 * 24)); + if (diffDays < 0) {dueGroup = 0;} + else if (diffDays <= 1) { dueGroup = diffDays.toString(); } + else if (diffDays <= 7) { dueGroup = diffDays.toString(); } + else if (diffDays <= 14) {dueGroup = 14;} + else if (diffDays <= 21) {dueGroup = 21;} + else if (diffDays <= 30) {dueGroup = 30;} + else {dueGroup = "Later"}; + + let announcement; + const targetContainer = domContainers[dueGroup]; + if (targetContainer) { + targetContainer.wrapper.style.display = "block"; + announcement = makeElement("div", targetContainer.listContainer, { + class: "better-todo-announcement", + }); + } + + const courseColor = + options.custom_cards_3?.[String(item.course_id)]?.color ?? + options.custom_cards_3?.[item.course_id]?.color ?? + options.custom_cards_3?.[item.plannable.course_id]?.color ?? + "#cccccc"; + + announcement.innerHTML = ` +
+
+
+ + + + + +
+
+
+
+ ${item.context_name} + ${item.plannable.title} + ${convertToDueDate(item.plannable_date)} +
+
+
+ `; + }); } function createTodoViewMore(location, type) { @@ -955,7 +1064,7 @@ function setupBetterTodo() { const feedback = list.querySelector(".events_list.recent_feedback"); list.textContent = ""; - list = makeElement("div", list, { "className": "bettercanvas-todosidebar" }); + list = makeElement("div", list, { "className": "bettercanvas-todosidebar","id": "bettercanvas-todo-list"}); createTodoSections(list); if (feedback) list.append(feedback);