diff --git a/CHANGELOG.md b/CHANGELOG.md
index 615af73..f197efc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,13 +3,17 @@
## Bug Fixes
- Fixed bug of Changelog not loading in about page
- Changing pages within the extension while using a color theme doesn't flicker white anymore
+- Fixed issue where choosing a subject color with the color picker on settings would break if many colors were clicked within the color picker (now, the color is only saved when the color picker is closed)
+- Clicking on a class from a subject that has only one day on the schedule now shows the info panel on the right, instead of showing just one full sized schedule with one single day
## Popup
+- Added button to lateral navbar to list all the subjects from the current schedule
- Color Themes:
- Sapphire
- Ambar
# [Changelog v1.2.0](https://github.com/digas99/schedule-ua/releases/tag/v1.2.0)
+Released on 10/09/2022
## Popup
- Added Dark Mode
diff --git a/README.md b/README.md
index 288c666..cf881e8 100644
--- a/README.md
+++ b/README.md
@@ -28,17 +28,15 @@ Browser Extension for easy access to your Schedule from Universidade de Aveiro.
### Bug Fixes
- Fixed bug of Changelog not loading in about page
-
-## [Changelog v1.2.0](https://github.com/digas99/schedule-ua/releases/tag/v1.2.0)
+- Changing pages within the extension while using a color theme doesn't flicker white anymore
+- Fixed issue where choosing a subject color with the color picker on settings would break if many colors were clicked within the color picker (now, the color is only saved when the color picker is closed)
+- Clicking on a class from a subject that has only one day on the schedule now shows the info panel on the right, instead of showing just one full sized schedule with one single day
### Popup
-- Added Dark Mode
-- Added Changelog to about page
+- Added button to lateral navbar to list all the subjects from the current schedule
- Color Themes:
- - Light Mode
- - Light High Contrast
- - Dark Mode
- - Dark High Contrast
+ - Sapphire
+ - Ambar
[(All changelogs)](CHANGELOG.md)
diff --git a/home.html b/home.html
index 646cbf0..005d7c0 100644
--- a/home.html
+++ b/home.html
@@ -11,9 +11,8 @@
-
-
+
diff --git a/images/icons/day.png b/images/icons/day.png
new file mode 100644
index 0000000..f3af17f
Binary files /dev/null and b/images/icons/day.png differ
diff --git a/images/icons/list.png b/images/icons/list.png
new file mode 100644
index 0000000..f6040ea
Binary files /dev/null and b/images/icons/list.png differ
diff --git a/scripts/home.js b/scripts/home.js
index e70e9fa..09e83e5 100644
--- a/scripts/home.js
+++ b/scripts/home.js
@@ -155,6 +155,10 @@ window.addEventListener("click", e => {
const selected = target.innerText;
switch(selected) {
case "Week":
+ const listSubjectsButton = document.getElementById("list-subjects");
+ if (listSubjectsButton)
+ listSubjectsButton.classList.replace("button-inactive", "clickable");
+
scheduleWrapper.firstChild?.remove();
scheduleWrapper.querySelector(".info-panel")?.remove();
@@ -219,6 +223,10 @@ window.addEventListener("click", e => {
}
if (target.closest(".class")) {
+ const listSubjectsButton = document.getElementById("list-subjects");
+ if (listSubjectsButton)
+ listSubjectsButton.classList.replace("button-inactive", "clickable");
+
const targetSubject = target.closest(".class").innerText.split(" - ")[0];
const days = Object.entries(storage["schedule"])
.filter(([day, subjects]) => subjects.some(subject => subject["subject"]["abbrev"] == targetSubject))
@@ -233,30 +241,37 @@ window.addEventListener("click", e => {
scheduleWrapper.firstChild?.remove();
scheduleWrapper.querySelector(".info-panel")?.remove();
- // adjust schedule
- const newSchedule = JSON.parse(JSON.stringify(storage["schedule"])); // deep clone schedule
- Object.keys(DAYS_INDEX).forEach(day => {
- if (!days.includes(day))
- delete newSchedule[day];
- });
+ if (days.length == 1)
+ createDaySchedule(scheduleWrapper, days[0]);
+ else {
+ // adjust schedule
+ const newSchedule = JSON.parse(JSON.stringify(storage["schedule"])); // deep clone schedule
+ Object.keys(DAYS_INDEX).forEach(day => {
+ if (!days.includes(day))
+ delete newSchedule[day];
+ });
- mySchedule = new Schedule(scheduleWrapper, {
- "hours": defaultHours,
- "days": days,
- "schedule": newSchedule,
- "colors": mySchedule.subjectColors,
- "trimmed": mySchedule.trimmed,
- "limitTrimming": mySchedule.limitTrimming,
- "soonest": mySchedule.soonest,
- "latest": mySchedule.latest
- });
-
- mySchedule.create();
- mySchedule.setupOverlappedSubjects();
+ mySchedule = new Schedule(scheduleWrapper, {
+ "hours": defaultHours,
+ "days": days,
+ "schedule": newSchedule,
+ "colors": mySchedule.subjectColors,
+ "trimmed": mySchedule.trimmed,
+ "limitTrimming": mySchedule.limitTrimming,
+ "soonest": mySchedule.soonest,
+ "latest": mySchedule.latest
+ });
- highlightNowCell();
+ mySchedule.create();
+ mySchedule.setupOverlappedSubjects();
+
+ highlightNowCell();
+ }
}
}
+
+ if (!target.closest(".floating-info-panel") && !target.closest("#list-subjects") && !target.closest("#darkmode") && document.querySelector(".floating-info-panel"))
+ document.querySelector("#list-subjects").click();
});
window.addEventListener("mouseover", e => {
@@ -369,6 +384,9 @@ window.addEventListener("mouseout", e => {
const createDaySchedule = (scheduleWrapper, scheduleDay) => {
scheduleWrapper.firstChild?.remove();
scheduleWrapper.querySelector(".info-panel")?.remove();
+ const listSubjectsButton = document.getElementById("list-subjects");
+ if (listSubjectsButton)
+ listSubjectsButton.classList.replace("clickable", "button-inactive");
mySchedule = new Schedule(scheduleWrapper, {
"hours": defaultHours,
@@ -434,68 +452,107 @@ const infoPanel = schedule => {
const title = document.createElement("h2");
wrapper.appendChild(title);
title.appendChild(document.createTextNode("Your classes"));
-
- // general data
- const genDataWrapper = document.createElement("div");
- wrapper.appendChild(genDataWrapper);
-
- const subjectsWrapper = document.createElement("div");
- wrapper.appendChild(subjectsWrapper);
- const subjects = Object.values(schedule).flat(1);
- let pract = 0, theor = 0, hoursTotal = 0;
- if (subjects) {
- subjects.forEach(subject => {
- if (subject) {
- const subjectWrapper = document.createElement("div");
- subjectsWrapper.appendChild(subjectWrapper);
- subjectWrapper.classList.add("subject-info");
- const classTitle = document.createElement("div");
- subjectWrapper.appendChild(classTitle);
- classTitle.appendChild(document.createTextNode(`${subject["subject"]["abbrev"]} - ${subject["subject"]["name"]}`));
- classTitle.style.backgroundColor = mySchedule.subjectColors[subject["subject"]["abbrev"]];
- const infoWrapper = document.createElement("div");
- subjectWrapper.appendChild(infoWrapper);
- const classNumberWrapper = document.createElement("div");
- infoWrapper.appendChild(classNumberWrapper);
- const classNumber = document.createElement("div");
- classNumberWrapper.appendChild(classNumber);
- classNumber.appendChild(document.createTextNode(subject["class"]));
- const info = document.createElement("div");
- infoWrapper.appendChild(info);
- const start = parseFloat(subject["start"].replace(",", "."));
- const duration = parseFloat(subject["duration"].replace(",", "."));
- const end = start+duration;
- subject["time"] = `${start}h - ${end}h`;
- ["time" ,"duration", "room", "capacity"].forEach(type => {
- const rowWrapper = document.createElement("div");
- info.appendChild(rowWrapper);
- rowWrapper.title = type.charAt(0).toUpperCase()+type.slice(1);
- const rowIcon = document.createElement("img");
- rowWrapper.appendChild(rowIcon);
- rowIcon.src = `images/icons/${type}.png`;
- rowIcon.classList.add("icon");
- const rowContent = document.createElement("div");
- rowWrapper.appendChild(rowContent);
- rowContent.appendChild(document.createTextNode(subject[type]));
+
+ if (schedule) {
+ const scheduleSize = Object.keys(schedule).length;
+
+ // summary
+ const genDataWrapper = document.createElement("div");
+ wrapper.appendChild(genDataWrapper);
+
+ let dayChooser;
+ if (scheduleSize > 1) {
+ // day chooser
+ dayChooser = document.createElement("div");
+ wrapper.appendChild(dayChooser);
+ dayChooser.classList.add("day-chooser");
+ }
+
+ const subjectsWrapper = document.createElement("div");
+ wrapper.appendChild(subjectsWrapper);
+ let pract = 0, theor = 0, hoursTotal = 0;
+
+ Object.entries(schedule).forEach(([day, subjects]) => {
+ if (subjects) {
+ const container = document.createElement("div");
+ subjectsWrapper.appendChild(container);
+ container.setAttribute("day", day);
+ subjects.forEach(subject => {
+ if (subject) {
+ const subjectWrapper = document.createElement("div");
+ container.appendChild(subjectWrapper);
+ subjectWrapper.classList.add("subject-info");
+ const classTitle = document.createElement("div");
+ subjectWrapper.appendChild(classTitle);
+ classTitle.appendChild(document.createTextNode(`${subject["subject"]["abbrev"]} - ${subject["subject"]["name"]}`));
+ classTitle.style.backgroundColor = mySchedule.subjectColors[subject["subject"]["abbrev"]];
+ const infoWrapper = document.createElement("div");
+ subjectWrapper.appendChild(infoWrapper);
+ const classNumberWrapper = document.createElement("div");
+ infoWrapper.appendChild(classNumberWrapper);
+ const classNumber = document.createElement("div");
+ classNumberWrapper.appendChild(classNumber);
+ classNumber.appendChild(document.createTextNode(subject["class"]));
+ const info = document.createElement("div");
+ infoWrapper.appendChild(info);
+ const start = parseFloat(subject["start"].replace(",", "."));
+ const duration = parseFloat(subject["duration"].replace(",", "."));
+ const end = start+duration;
+ subject["time"] = `${start}h - ${end}h`;
+ subject["day"] = day.slice(0, 3).toUpperCase();
+ const keys = ["day", "time" ,"duration", "room", "capacity"];
+ if (scheduleSize == 1)
+ delete keys[0];
+
+ keys.forEach(type => {
+ const rowWrapper = document.createElement("div");
+ info.appendChild(rowWrapper);
+ rowWrapper.title = type.charAt(0).toUpperCase()+type.slice(1);
+ const rowIcon = document.createElement("img");
+ rowWrapper.appendChild(rowIcon);
+ rowIcon.src = `images/icons/${type}.png`;
+ rowIcon.classList.add("icon");
+ const rowContent = document.createElement("div");
+ rowWrapper.appendChild(rowContent);
+ rowContent.appendChild(document.createTextNode(subject[type]));
+ });
+
+ if (subject["class"].charAt(0) == "P") pract++;
+ else theor++;
+
+ hoursTotal += parseFloat(subject["duration"].replace(",", "."));
+ }
});
-
- if (subject["class"].charAt(0) == "P") pract++;
- else theor++;
-
- hoursTotal += parseFloat(subject["duration"].replace(",", "."));
- }
+ }
+ });
+
+ // summary
+ const data = [scheduleSize, pract+theor, pract, theor, hoursTotal+"h"];
+ const titles = ["Days", "Classes", "Pract.", "Theor.", "Hours Total"];
+ if (scheduleSize == 1) {
+ delete data[0];
+ delete titles[0];
+ }
+ titles.forEach((title, i) => {
+ const wrapper = document.createElement("div");
+ genDataWrapper.appendChild(wrapper);
+ const titleElem = document.createElement("b");
+ wrapper.appendChild(titleElem);
+ titleElem.appendChild(document.createTextNode(title));
+ wrapper.appendChild(document.createTextNode(` ${data[i]}`));
});
- }
- const data = [pract+theor, pract, theor, hoursTotal+"h"];
- ["Classes", "Pract.", "Theor.", "Hours Total"].forEach((title, i) => {
- const wrapper = document.createElement("div");
- genDataWrapper.appendChild(wrapper);
- const titleElem = document.createElement("b");
- wrapper.appendChild(titleElem);
- titleElem.appendChild(document.createTextNode(title));
- wrapper.appendChild(document.createTextNode(` ${data[i]}`));
- });
+ // day chooser
+ if (scheduleSize > 1) {
+ Object.keys(schedule).forEach(dayString => {
+ const dayWrapper = document.createElement("div");
+ dayChooser.appendChild(dayWrapper);
+ dayWrapper.appendChild(document.createTextNode(dayString));
+ dayWrapper.classList.add("clickable");
+ dayWrapper.addEventListener("click", () => wrapper.parentElement.scrollTo(0, subjectsWrapper.querySelector(`div[day="${dayString}"]`).offsetTop));
+ });
+ }
+ }
return wrapper;
}
diff --git a/scripts/settings.js b/scripts/settings.js
index 02891cb..38f2766 100644
--- a/scripts/settings.js
+++ b/scripts/settings.js
@@ -19,9 +19,16 @@ chrome.storage.sync.get(SETTINGS_KEYS, result => {
colorPicker.type = "color";
colorPicker.value = color;
- colorPicker.addEventListener("input", () => {
- subjectColors[subject] = colorPicker.value;
- chrome.storage.sync.set({"subject_colors": subjectColors});
+ let choosingColor = false;
+ colorPicker.addEventListener("click", () => choosingColor = true);
+
+ colorPicker.addEventListener("input", () => subjectColors[subject] = colorPicker.value);
+
+ colorPicker.addEventListener("mouseout", () => {
+ if (choosingColor) {
+ chrome.storage.sync.set({"subject_colors": subjectColors});
+ choosingColor = false;
+ }
});
});
}
diff --git a/scripts/sidebar.js b/scripts/sidebar.js
index d888aa7..dc845fb 100644
--- a/scripts/sidebar.js
+++ b/scripts/sidebar.js
@@ -2,15 +2,44 @@ window.addEventListener("click", e => {
const target = e.target;
chrome.storage.sync.get("color_schema", result => {
- if (target.closest("#exit"))
- chrome.storage.sync.remove([...SCHEDULE_CONFIGS, "subject_colors"]).then(() => window.location.href = `/login.html?theme=${result["color_schema"]}`);
+ if (target.closest("#exit"))
+ chrome.storage.sync.remove([...SCHEDULE_CONFIGS, "subject_colors"]).then(() => window.location.href = `/login.html?theme=${result["color_schema"]}`);
- if (target.closest("#schedule") && !target.closest("#schedule").classList.contains("button-inactive")) window.location.href = `/home.html?theme=${result["color_schema"]}`;
+ if (target.closest("#schedule") && !target.closest("#schedule").classList.contains("button-inactive")) window.location.href = `/home.html?theme=${result["color_schema"]}`;
- if (target.closest("#settings") && !target.closest("#settings").classList.contains("button-inactive")) window.location.href = `/settings.html?theme=${result["color_schema"]}`;
+ if (target.closest("#settings") && !target.closest("#settings").classList.contains("button-inactive")) window.location.href = `/settings.html?theme=${result["color_schema"]}`;
- if (target.closest("#about") && !target.closest("#about").classList.contains("button-inactive")) window.location.href = `/about.html?theme=${result["color_schema"]}`;
+ if (target.closest("#about") && !target.closest("#about").classList.contains("button-inactive")) window.location.href = `/about.html?theme=${result["color_schema"]}`;
+ });
if (target.closest("#darkmode")) swapColorSchema(target.closest("#darkmode").title);
- });
+
+ if (target.closest("#list-subjects") && !target.closest("#list-subjects").classList.contains("button-inactive") && document.getElementById("main") && mySchedule.schedule) {
+ let floatingInfoPanel = document.querySelector(".floating-info-panel");
+ if (!floatingInfoPanel) {
+ floatingInfoPanel = document.createElement("div");
+ document.getElementById("main").appendChild(floatingInfoPanel);
+ floatingInfoPanel.classList.add("floating-info-panel");
+ const sortedSchedule = Object.entries(mySchedule.schedule)
+ .filter(([, value]) => value && value.length > 0)
+ .sort(([a,], [b,]) => mySchedule.daysIndex[a] - mySchedule.daysIndex[b])
+ .reduce((acc, [key, value]) => ({...acc, [key]: value}), {});
+
+ const panel = infoPanel(sortedSchedule);
+ floatingInfoPanel.appendChild(panel);
+
+ floatingInfoPanel.style.transition = "0.3s";
+ floatingInfoPanel.style.right = `-${floatingInfoPanel.offsetWidth}px`;
+ setTimeout(() => {
+ floatingInfoPanel.style.right = "51px";
+ setTimeout(() => floatingInfoPanel.style.removeProperty("transition"), 300);
+ }, 50);
+
+ }
+ else {
+ floatingInfoPanel.style.transition = "0.3s";
+ floatingInfoPanel.style.right = `-${floatingInfoPanel.offsetWidth}px`;
+ setTimeout(() => floatingInfoPanel.remove(), 300);
+ }
+ }
});
\ No newline at end of file
diff --git a/settings.html b/settings.html
index dbe3b1b..7387b2e 100644
--- a/settings.html
+++ b/settings.html
@@ -32,7 +32,7 @@
Schedule
Tomorrow
-