mirror of
https://github.com/GuySandler/CanvasRefined.git
synced 2026-06-21 01:49:54 +02:00
better todolist 4
animations, styles, announcement badge, and markings as un/complete
This commit is contained in:
parent
1bde70d424
commit
312257493a
@ -42,7 +42,6 @@ Better Canvas introduces improvements to the Canvas user interface:
|
||||
- Themes created by users (broken due to fork)
|
||||
- Assignments due list
|
||||
- Dashboard notes
|
||||
- Better todo list
|
||||
- Custom fonts
|
||||
- Condensed cards
|
||||
- Dashboard grades
|
||||
@ -60,11 +59,11 @@ Better Canvas introduces improvements to the Canvas user interface:
|
||||
- Searching themes (the original didn't actually impliment that)
|
||||
- Card Styles (image size, card roundness, card spacing, width, height, theme compatible)
|
||||
- Custom Background (by URL, theme compatible)
|
||||
- NEW Better todo list (todo: hover preview, cutoff, maybe fix some missing ones)
|
||||
|
||||
## Planned Features (by priority)
|
||||
- popup UI revamp
|
||||
- widgets (music, timer)
|
||||
- update better todo list (with hover assignment preview)
|
||||
- better sidebar
|
||||
- better notes
|
||||
- auto rotate theme + theme history + fix theme submissions
|
||||
|
||||
106
js/content.js
106
js/content.js
@ -834,11 +834,23 @@ function convertToDueDate(dueAt) {
|
||||
return final;
|
||||
}
|
||||
function updateIndicator(element) {
|
||||
const rect = element.getBoundingClientRect();
|
||||
const parentRect = element.parentElement.getBoundingClientRect();
|
||||
const indicator = document.getElementById("better-todo-indicator");
|
||||
indicator.style.width = `${element.offsetWidth*2}px`;
|
||||
indicator.style.left = `${element.offsetLeft - (element.offsetWidth * .5)}px`;
|
||||
|
||||
const buttons = ["announcement", "assignments", "completed"];
|
||||
buttons.forEach(button => {
|
||||
const btn = document.getElementById(`better-todo-${button}`);
|
||||
if (btn == element) {
|
||||
btn.firstElementChild.style.opacity = "1";
|
||||
// btn.style.filter = "none";
|
||||
}
|
||||
else {
|
||||
btn.firstElementChild.style.opacity = ".3";
|
||||
// btn.style.filter = "grayscale(100%)";
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
// better todo html
|
||||
betterTodoFilter = "tasks";
|
||||
@ -858,9 +870,9 @@ async function createTodoSections(location) {
|
||||
let filterControl = makeElement("div", location, { "id": "better-todo-filter" });
|
||||
filterControl.innerHTML = `
|
||||
<div style="display:flex;justify-content:center;margin-top:20px;">
|
||||
<div id="better-todo-filterbuttongroup" style="display:flex;gap:5px;justify-content:space-between;position:relative;padding-bottom:5px;width:60%;">
|
||||
<div id="better-todo-filterbuttongroup" style="display:flex;gap:50px;justify-content:space-between;position:relative;padding-bottom:5px;width:70%;height:30px;">
|
||||
<div id="better-todo-announcement" style="color:black !important;width:25px;cursor:pointer;">
|
||||
<svg fill="#ffffff" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg fill="#ffffff" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg" style="transition:all .3s ease;">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<path d="M1587.162 31.278c11.52-23.491 37.27-35.689 63.473-29.816 25.525 6.099 43.483 28.8 43.483 55.002V570.46C1822.87 596.662 1920 710.733 1920 847.053c0 136.32-97.13 250.503-225.882 276.705v513.883c0 26.202-17.958 49.016-43.483 55.002a57.279 57.279 0 0 1-12.988 1.468c-21.12 0-40.772-11.745-50.485-31.171C1379.238 1247.203 964.18 1242.347 960 1242.347H564.706v564.706h87.755c-11.859-90.127-17.506-247.003 63.473-350.683 52.405-67.087 129.657-101.082 229.948-101.082v112.941c-64.49 0-110.57 18.861-140.837 57.487-68.781 87.868-45.064 263.83-30.269 324.254 4.18 16.828.34 34.673-10.277 48.34-10.73 13.665-27.219 21.684-44.499 21.684H508.235c-31.171 0-56.47-25.186-56.47-56.47v-621.177h-56.47c-155.747 0-282.354-126.607-282.354-282.353v-56.47h-56.47C25.299 903.523 0 878.336 0 847.052c0-31.172 25.299-56.471 56.47-56.471h56.471v-56.47c0-155.634 126.607-282.354 282.353-282.354h564.593c16.941-.112 420.48-7.002 627.275-420.48Zm-5.986 218.429c-194.71 242.371-452.216 298.164-564.705 311.04v572.724c112.489 12.876 369.995 68.556 564.705 311.04ZM903.53 564.7H395.294c-93.402 0-169.412 76.01-169.412 169.411v225.883c0 93.402 76.01 169.412 169.412 169.412H903.53V564.7Zm790.589 123.444v317.93c65.618-23.379 112.94-85.497 112.94-159.021 0-73.525-47.322-135.53-112.94-158.909Z" fill-rule="evenodd"></path>
|
||||
@ -868,7 +880,7 @@ async function createTodoSections(location) {
|
||||
</svg>
|
||||
</div>
|
||||
<div id="better-todo-assignments" style="color:black !important;width:25px;cursor:pointer;">
|
||||
<svg fill="#ffffff" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff">
|
||||
<svg fill="#ffffff" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff" style="transition:all .3s ease;">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="1"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<path d="M1468.214 0v551.145L840.27 1179.089c-31.623 31.623-49.693 74.54-49.693 119.715v395.289h395.288c45.176 0 88.093-18.07 119.716-49.694l162.633-162.633v438.206H0V0h1468.214Zm129.428 581.3c22.137-22.136 57.825-22.136 79.962 0l225.879 225.879c22.023 22.023 22.023 57.712 0 79.848l-677.638 677.637c-10.616 10.503-24.96 16.49-39.98 16.49H903.516v-282.35c0-15.02 5.986-29.364 16.49-39.867Zm-920.005 548.095H338.82v112.94h338.818v-112.94Zm225.88-225.879H338.818v112.94h564.697v-112.94Zm734.106-202.5-89.561 89.56 146.03 146.031 89.562-89.56-146.031-146.031Zm-508.228-362.197H338.82v338.818h790.576V338.82Z" fill-rule="evenodd"></path>
|
||||
@ -876,7 +888,7 @@ async function createTodoSections(location) {
|
||||
</svg>
|
||||
</div>
|
||||
<div id="better-todo-completed" style="color:black !important;width:25px;cursor:pointer;">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="transition:all .3s ease;">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier"> <g id="Interface / Checkbox_Check">
|
||||
@ -925,8 +937,26 @@ async function createTodoSections(location) {
|
||||
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);
|
||||
console.log(announcements);
|
||||
console.log("assignments", assignmentsDue);
|
||||
console.log("announcements", announcements);
|
||||
console.log("completed", completed);
|
||||
|
||||
if (!document.getElementById("better-todo-announcement-badge")) {
|
||||
let isAnnoucementBadge = 0;
|
||||
announcements.forEach(item => {
|
||||
if (item.plannable.read_state == "unread") {
|
||||
isAnnoucementBadge++;
|
||||
return;
|
||||
}
|
||||
})
|
||||
if (isAnnoucementBadge > 0) {
|
||||
makeElement("div", document.getElementById("better-todo-announcement"), {
|
||||
id: "better-todo-announcement-badge",
|
||||
style: "background-color:#ff0000;width:15px;height:15px;border-radius:50%;font-size:12px;position:absolute;top:-7px;left:16px;display:flex;justify-content:center;align-items:center;", // TODO: theme compatibility
|
||||
innerHTML: `<span style="color:white;">${isAnnoucementBadge}</span>`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
domContainers = {};
|
||||
const groupKeys = ["-1", "0", "1", "2", "3", "4", "5", "6", "7", "14", "21", "30", "Later", "New", "Seen", "Ungraded", "Graded"];
|
||||
@ -984,6 +1014,7 @@ function populateAssignments(iscompleted = false) {
|
||||
|
||||
assignments.forEach((item) => {
|
||||
let dueGroup = -1;
|
||||
if (!iscompleted) {
|
||||
let dueDate = new Date(item.plannable_date);
|
||||
dueDate.setHours(0,0,0,0);
|
||||
const diffDays = Math.round((dueDate - today) / (1000 * 60 * 60 * 24));
|
||||
@ -994,6 +1025,9 @@ function populateAssignments(iscompleted = false) {
|
||||
else if (diffDays <= 21) {dueGroup = 21;}
|
||||
else if (diffDays <= 30) {dueGroup = 30;}
|
||||
else {dueGroup = "Later"};
|
||||
} else {
|
||||
dueGroup = item.submissions?.graded ? "Graded" : "Ungraded";
|
||||
}
|
||||
|
||||
let assignment
|
||||
const targetContainer = domContainers[dueGroup];
|
||||
@ -1022,15 +1056,26 @@ function populateAssignments(iscompleted = false) {
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width:calc(100% - 40px);height:80%;display:flex;flex-direction:column;gap:5px;padding-left:2px;box-sizing:border-box;overflow:hidden;">
|
||||
<div style="width:calc(100% - 40px);height:80%;display:flex;flex-direction:column;gap:5px;padding-left:2px;box-sizing:border-box;overflow:hidden;position:relative;">
|
||||
<div style="display:flex;flex-direction:column;gap:3px;">
|
||||
<span style="color:${courseColor};font-size:12px;margin-top:-2px;">${item.context_name}</span>
|
||||
<a href="${domain + item.html_url}" style="color:inherit;text-decoration:none;font-weight:bold;text-overflow:ellipsis;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:-5px;">${item.plannable.title}</a>
|
||||
<span style="color:gray;font-size:12px;margin-top:-5px;">${convertToDueDate(item.plannable_date)}</span>
|
||||
</div>
|
||||
<svg class="better-todo-assignment-checkmark" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="width:15px;height:15px;position:absolute;top:0px;right:5px;opacity:0.3;transition:all .3s ease;cursor:pointer;" onmouseover="this.style.opacity='1'" onmouseout="this.style.opacity='0.3'">
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier"> <g id="Interface / Checkbox_Check">
|
||||
<path id="Vector" d="M8 12L11 15L16 9M4 16.8002V7.2002C4 6.08009 4 5.51962 4.21799 5.0918C4.40973 4.71547 4.71547 4.40973 5.0918 4.21799C5.51962 4 6.08009 4 7.2002 4H16.8002C17.9203 4 18.4796 4 18.9074 4.21799C19.2837 4.40973 19.5905 4.71547 19.7822 5.0918C20 5.5192 20 6.07899 20 7.19691V16.8036C20 17.9215 20 18.4805 19.7822 18.9079C19.5905 19.2842 19.2837 19.5905 18.9074 19.7822C18.48 20 17.921 20 16.8031 20H7.19691C6.07899 20 5.5192 20 5.0918 19.7822C4.71547 19.5905 4.40973 19.2842 4.21799 18.9079C4 18.4801 4 17.9203 4 16.8002Z" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||
</g></g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
assignment.querySelector(".better-todo-assignment-checkmark").addEventListener("click", () => {
|
||||
console.log("marking ", item.plannable.title, " as complete");
|
||||
markAs(item)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1039,19 +1084,10 @@ function populateAnnouncements() {
|
||||
today.setHours(0,0,0,0);
|
||||
|
||||
announcements.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 dueGroup = item.plannable.read_state == "read" ? "Seen" : "New";
|
||||
|
||||
let announcement;
|
||||
// console.log(domContainers)
|
||||
const targetContainer = domContainers[dueGroup];
|
||||
if (targetContainer) {
|
||||
targetContainer.wrapper.style.display = "block";
|
||||
@ -1094,6 +1130,36 @@ function populateAnnouncements() {
|
||||
});
|
||||
}
|
||||
|
||||
function markAs(item) {
|
||||
const csrfToken = CSRFtoken();
|
||||
const completeState = item.planner_override ? !item.planner_override.marked_complete : true;
|
||||
fetch(domain + "/api/v1/planner/overrides/" + (item.planner_override ? "/" + item.planner_override.id : ""), {
|
||||
method: item.planner_override ? "PUT" : "POST",
|
||||
headers: {
|
||||
"content-type":"application/json",
|
||||
"accept":"application/json",
|
||||
"X-CSRF-Token": csrfToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: item.planner_override ? item.planner_override.id : null,
|
||||
marked_complete: completeState,
|
||||
plannable_id: item.plannable_id,
|
||||
plannable_type: item.plannable_type
|
||||
})
|
||||
})
|
||||
.then(resp => {
|
||||
if (resp.status == 200 || resp.status == 201) {
|
||||
console.log("marked as complete");
|
||||
item.planner_override = item.planner_override || {};
|
||||
item.planner_override.marked_complete = completeState;
|
||||
clearTodoList();
|
||||
createTodoSections(document.querySelector("#bettercanvas-todo-list"));
|
||||
}
|
||||
})
|
||||
.catch(err => console.error("error marking as complete", err));
|
||||
|
||||
}
|
||||
|
||||
function createTodoViewMore(location, type) {
|
||||
let viewMoreButton = makeElement("button", location, { "className": "bettercanvas-custom-btn bettercanvas-viewmore-btn", "textContent": "View More" });
|
||||
//viewMoreButton.classList.add("bettercanvas-viewmore-btn");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user