Skip to content

Commit 3575e5e

Browse files
authored
Merge pull request #55 from cschuijt/add-project-date-sort
Add sorting by project completion date
2 parents 0d64db0 + 873c15e commit 3575e5e

File tree

3 files changed

+80
-25
lines changed

3 files changed

+80
-25
lines changed

background/options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const defaults = {
2727
"old-blackhole": "false",
2828
"outstandings": "true",
2929
"show-custom-profiles": "true",
30+
"sort-projects-date": "false",
3031
"sync": "true",
3132
"theme": "system"
3233
};
@@ -48,6 +49,7 @@ const v1Translations = {
4849
"old-blackhole": ["settings", "old_blackhole"],
4950
"outstandings": ["settings", "outstandings"],
5051
"show-custom-profiles": ["settings", "show_custom_profiles"],
52+
"sort-projects-date": ["settings", "sort_projects_date"],
5153
"theme": ["settings", "theme", "internal_name"],
5254
"username": ["user", "login"]
5355
}

features/themes/apply.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,10 @@ li.scaleteam-list-item .rating:not([data-positive=""]) {
706706
color: var(--secondary-text-color) !important;
707707
}
708708

709+
.project-item.parent-item {
710+
border-bottom-color: var(--general-border-color) !important;
711+
}
712+
709713
.profile-menu {
710714
border-color: var(--general-border-color) !important;
711715
}

fixes/general.js

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -210,36 +210,85 @@ function setInternshipAdministrationImprovements(match) {
210210
* @param {RegExpExecArray} match
211211
*/
212212
function setPageUserImprovements(match) {
213-
// Sort marks listed by project name
213+
// Sort marks listed by project name or by completion date
214214
const projectItemsContainer = document.querySelector("#marks .overflowable-item");
215215
if (projectItemsContainer) {
216-
const projectItems = projectItemsContainer.querySelectorAll(".main-project-item, .collapsable");
217-
const projectItemsArray = Array.from(projectItems);
218-
projectItemsArray.sort((a, b) => {
219-
return a.querySelector(".marked-title > a").textContent.localeCompare(b.querySelector(".marked-title > a").textContent);
220-
});
221-
projectItemsArray.forEach(item => {
222-
projectItemsContainer.appendChild(item);
223-
});
216+
const mainProjectItems = Array.from(projectItemsContainer.querySelectorAll(".main-project-item:not(.parent-item)"));
217+
const mainProjectItemCollapsables = Array.from(projectItemsContainer.querySelectorAll(".collapsable"));
218+
improvedStorage.get("sort-projects-date").then(function(data) {
219+
// Completion date sorter function (descending)
220+
const completionDateSorterDesc = (a, b) => {
221+
return (Date.parse(b.querySelector(".project-item-lighteable").dataset.longDate) - Date.parse(a.querySelector(".project-item-lighteable").dataset.longDate));
222+
};
224223

225-
// Place any ongoing project at the top (e.g. Internships)
226-
// Ongoing projects are marked by an icon with the class "icon-clock"
227-
const ongoingProjects = projectItemsContainer.querySelectorAll(".main-project-item .icon-clock");
228-
if (ongoingProjects.length > 0) {
229-
const ongoingProject = ongoingProjects[0].closest(".main-project-item");
230-
projectItemsContainer.insertBefore(ongoingProject, projectItemsContainer.firstChild);
231-
232-
// Add any collapsables for this ongoing project to the top as well
233-
// otherwise they will be placed at the previous location of the ongoing project (when it was sorted alphabetically)
234-
const ongoingProjectCollapsables = projectItemsContainer.querySelectorAll(ongoingProject.getAttribute("data-target"));
235-
if (ongoingProjectCollapsables.length > 0) {
236-
ongoingProjectCollapsables.forEach(collapsable => {
237-
projectItemsContainer.insertBefore(collapsable, ongoingProject.nextElementSibling);
238-
});
224+
// Completion date sorter function (ascending)
225+
const completionDateSorterAsc = (a, b) => {
226+
return (Date.parse(a.querySelector(".project-item-lighteable").dataset.longDate) - Date.parse(b.querySelector(".project-item-lighteable").dataset.longDate));
227+
};
228+
229+
// Alphabetical sorter function (ascending)
230+
const alphabeticalSorterAsc = (a, b) => {
231+
return a.querySelector(".marked-title").textContent.localeCompare(b.querySelector(".marked-title").textContent);
232+
};
233+
234+
// Alphabetical sorter function (descending)
235+
const alphabeticalSorterDesc = (a, b) => {
236+
return b.querySelector(".marked-title").textContent.localeCompare(a.querySelector(".marked-title").textContent);
237+
};
238+
239+
// Sort by completion date if the option sort-projects-date is active
240+
if (optionIsActive(data, "sort-projects-date")) {
241+
mainProjectItems.sort(completionDateSorterDesc);
239242
}
240-
}
243+
// Default to alphabetic sorting otherwise
244+
else {
245+
mainProjectItems.sort(alphabeticalSorterAsc);
246+
}
247+
248+
// Place main project items in the correct order
249+
mainProjectItems.forEach(item => {
250+
projectItemsContainer.appendChild(item);
251+
});
252+
253+
// Sort collapsable project items by completion date (ascending, so that later on they will get appended to their corresponding main project item in the correct order)
254+
mainProjectItemCollapsables.sort(completionDateSorterAsc);
241255

242-
iConsole.log("Sorted marks listed by project name");
256+
// Place any collapsable project items under their corresponding main project item
257+
mainProjectItemCollapsables.forEach(collapsable => {
258+
// Find the main project item for this collapsable project item
259+
// (where data-project equals the id attribute of the collapsable and data-cursus equals the data-cursus attribute of the collapsable's project-item element)
260+
const collapsableProjectItem = collapsable.querySelector(".project-item");
261+
const mainProjectItem = projectItemsContainer.querySelector(`.project-item[data-project="${collapsableProjectItem.id}"][data-cursus="${collapsableProjectItem.dataset.cursus}"]`);
262+
if (mainProjectItem) {
263+
mainProjectItem.parentNode.insertBefore(collapsable, mainProjectItem.nextElementSibling);
264+
}
265+
});
266+
267+
// Place any "parent-item" project items at the top, like on regular Intra
268+
const parentProjectItems = Array.from(projectItemsContainer.querySelectorAll(".main-project-item.parent-item"));
269+
270+
// Reverse the order of the parent project items because the first one will be placed at the top, while in fact the last one found should be placed at the top
271+
parentProjectItems.reverse();
272+
273+
// Place parent project items in the correct spot in the project items container
274+
parentProjectItems.forEach(parentProjectItem => {
275+
projectItemsContainer.insertBefore(parentProjectItem, projectItemsContainer.firstChild);
276+
277+
// Add any collapsables for this ongoing project to the top as well
278+
// otherwise they will be placed at the previous location of the ongoing project (when it was sorted alphabetically)
279+
const parentProjectItemCollapsables = Array.from(projectItemsContainer.querySelectorAll(parentProjectItem.dataset.target));
280+
281+
// Sort collapsables by alphabetical order (descending, so that they will get appended to their corresponding main project item in the correct order)
282+
parentProjectItemCollapsables.sort(alphabeticalSorterDesc);
283+
284+
// Place collapsables in the correct spot in the project items container
285+
parentProjectItemCollapsables.forEach(collapsable => {
286+
projectItemsContainer.insertBefore(collapsable, projectItemsContainer.firstChild.nextSibling);
287+
});
288+
});
289+
290+
iConsole.log("Sorted marks listed by project name");
291+
});
243292
}
244293
else {
245294
iConsole.warn("Could not find project items container (where marks are located). Unable to sort it.");

0 commit comments

Comments
 (0)