diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index fff3f88..cbc43ba 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -315,7 +315,7 @@
"message": "Grade Analytics"
},
"grade_analytics_desc": {
- "message": "Adds an Analytics toggle to the left side of course grade pages with a score-distribution chart and your overall grade over time."
+ "message": "Adds tools to help you analyze your grades."
},
"grade_analytics_zones": {
"message": "Colored grade zones"
diff --git a/html/popup.html b/html/popup.html
index d4dfc9a..211891f 100644
--- a/html/popup.html
+++ b/html/popup.html
@@ -228,7 +228,7 @@
Grade Analytics
- Adds an Analytics toggle to the left side of course grade pages with a score-distribution chart and your overall grade over time.
+ Adds tools to help you analyze your grades.
@@ -604,14 +604,6 @@
On/off toggles
-
-
- Layout
-
-
-
- Sidebar
-
Todo list
diff --git a/js/content.js b/js/content.js
index d9917ae..f1fbe84 100644
--- a/js/content.js
+++ b/js/content.js
@@ -1757,6 +1757,17 @@ const BETTER_TODO_TIMEFRAME_DAYS = {
let betterTodoProgressFilter = null;
let domContainers = {};
+// Better Todo timeframe filter, shared by the task list and the progress
+// display so their counts always agree: keeps items due on/before now+range
+// (overdue items are before now, so they are kept too). "all" keeps
+// everything.
+function applyTodoTimeframe(items) {
+ betterTodoTimeframe = (options.todo_timeframe && Object.prototype.hasOwnProperty.call(BETTER_TODO_TIMEFRAME_DAYS, options.todo_timeframe)) ? options.todo_timeframe : "all";
+ if (betterTodoTimeframe === "all") return items;
+ const cutoff = Date.now() + (BETTER_TODO_TIMEFRAME_DAYS[betterTodoTimeframe] * 24 * 60 * 60 * 1000);
+ return items.filter(item => new Date(item.plannable_date).getTime() <= cutoff);
+}
+
// true when `courseId` is the dimmed-out class because another class is selected.
function progressFilterDim(courseId) {
return betterTodoProgressFilter != null && String(courseId) !== String(betterTodoProgressFilter);
@@ -2263,7 +2274,9 @@ function renderProgressRings(container, scopedData) {
const mode = getProgressRingMode();
if (mode === "none") { container.innerHTML = ""; return; }
- const allAssignments = scopedData.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note"));
+ // Apply the same timeframe filter the list uses so the counts in the
+ // display match what's shown below it.
+ const allAssignments = applyTodoTimeframe(scopedData.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note")));
const groups = {};
allAssignments.forEach(item => {
@@ -2931,13 +2944,9 @@ async function createTodoSections(location) {
completed = displayData.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note") && (item.submissions?.submitted || item.planner_override?.marked_complete));
// The timeframe is a persisted Better Todo List sub-option set in the
// popup. Read the current value each render so popup changes apply on
- // the next render. Keeps items due on/before now+range (overdue items
- // are before now, so they are kept too). Only the Tasks tab is affected.
- betterTodoTimeframe = (options.todo_timeframe && Object.prototype.hasOwnProperty.call(BETTER_TODO_TIMEFRAME_DAYS, options.todo_timeframe)) ? options.todo_timeframe : "all";
- if (betterTodoTimeframe !== "all") {
- const cutoff = Date.now() + (BETTER_TODO_TIMEFRAME_DAYS[betterTodoTimeframe] * 24 * 60 * 60 * 1000);
- assignmentsDue = assignmentsDue.filter(item => new Date(item.plannable_date).getTime() <= cutoff);
- }
+ // the next render. Only the Tasks tab is affected (announcements and
+ // the completed tab always show everything).
+ assignmentsDue = applyTodoTimeframe(assignmentsDue);
// console.log("assignments", assignmentsDue);
// console.log("announcements", announcements);
// console.log("completed", completed);
@@ -6776,8 +6785,8 @@ function renderGradeAnalytics() {
stats.innerHTML =
stat("Overall grade", gaData.current == null ? "-" : gaData.current.toFixed(1) + "%") +
stat("Grade trend (last 5)", trendVal, trendColor) +
- stat("Graded assignments", gaData.graded) +
- stat("Ungraded / no score", gaData.ungraded);
+ stat("Graded", gaData.graded) +
+ stat("Ungraded", gaData.ungraded);
const charts = panel.querySelector("#canvasrefined-ga-charts");
charts.style.display = "flex";
diff --git a/js/popup.js b/js/popup.js
index 5b31fd6..374ddcc 100644
--- a/js/popup.js
+++ b/js/popup.js
@@ -60,8 +60,9 @@ const exportTodo = ["better_todo", "todo_hide_feedback", "todo_full_height", "to
const exportGpa = ["gpa_calc", "gpa_calc_prepend", "gpa_calc_cumulative", "gpa_calc_weighted"];
const exportBackground = ["customBackgroundLink", "customBackgroundScale", "customBackgroundDaily", "customBackgroundNasaDaily", "fitImageToScreen", "card_transparency", "bg_opacity", "sidebar_opacity", "bg_blur", "sidebar_blur", "card_opacity", "card_blur"];
// Master "On/off toggles" = every visual toggle (no GPA, no dark-mode schedule,
-// no personal productivity features).
-const exportToggles = ["dark_mode", "quiz_safe_mode"].concat(exportCardColorToggles, exportLayout, exportSidebar, exportTodo);
+// no personal productivity features). Includes the former separate Layout and
+// Sidebar groups, plus Grade Analytics and its colored-zones sub-toggle.
+const exportToggles = ["dark_mode", "quiz_safe_mode", "grade_analytics", "grade_analytics_zones"].concat(exportCardColorToggles, exportLayout, exportSidebar, exportTodo);
const fontsDropdownStateKey = "fonts_dropdown_open";
const apiurl = "none";
@@ -1315,12 +1316,6 @@ function setup() {
case "export-background":
final = { ...final, ...(await getExport(storage, exportBackground)) };
break;
- case "export-layout":
- final = { ...final, ...(await getExport(storage, exportLayout)) };
- break;
- case "export-sidebar":
- final = { ...final, ...(await getExport(storage, exportSidebar)) };
- break;
case "export-todo":
final = { ...final, ...(await getExport(storage, exportTodo)) };
break;