2022-08-31 06:33:37 +05:00
|
|
|
/*
|
|
|
|
|
This file is part of the Notesnook project (https://notesnook.com/)
|
|
|
|
|
|
|
|
|
|
Copyright (C) 2022 Streetwriters (Private) Limited
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2022-08-30 16:13:11 +05:00
|
|
|
|
2023-01-04 15:23:15 +05:00
|
|
|
import { isReminderActive } from "../collections/reminders";
|
2021-07-12 13:48:19 +05:00
|
|
|
import "../types";
|
2022-06-16 16:01:08 +05:00
|
|
|
import { getWeekGroupFromTimestamp, MONTHS_FULL } from "./date";
|
2021-07-12 13:48:19 +05:00
|
|
|
|
2022-06-16 16:01:08 +05:00
|
|
|
const MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
|
|
|
|
|
const MILLISECONDS_IN_WEEK = MILLISECONDS_IN_DAY * 7;
|
|
|
|
|
|
|
|
|
|
const comparators = {
|
2022-11-23 12:33:35 +05:00
|
|
|
dateModified: {
|
|
|
|
|
asc: (a, b) => a.dateModified - b.dateModified,
|
|
|
|
|
desc: (a, b) => b.dateModified - a.dateModified
|
|
|
|
|
},
|
2022-06-16 16:01:08 +05:00
|
|
|
dateEdited: {
|
|
|
|
|
asc: (a, b) => a.dateEdited - b.dateEdited,
|
2022-08-31 06:33:37 +05:00
|
|
|
desc: (a, b) => b.dateEdited - a.dateEdited
|
2022-06-16 16:01:08 +05:00
|
|
|
},
|
|
|
|
|
dateCreated: {
|
|
|
|
|
asc: (a, b) => a.dateCreated - b.dateCreated,
|
2022-08-31 06:33:37 +05:00
|
|
|
desc: (a, b) => b.dateCreated - a.dateCreated
|
2021-07-13 20:00:31 +05:00
|
|
|
},
|
2022-06-16 16:01:08 +05:00
|
|
|
dateDeleted: {
|
|
|
|
|
asc: (a, b) => a.dateDeleted - b.dateDeleted,
|
2022-08-31 06:33:37 +05:00
|
|
|
desc: (a, b) => b.dateDeleted - a.dateDeleted
|
2022-06-16 16:01:08 +05:00
|
|
|
},
|
|
|
|
|
title: {
|
2022-11-17 19:38:05 +05:00
|
|
|
asc: (a, b) =>
|
|
|
|
|
getTitle(a).localeCompare(getTitle(b), undefined, { numeric: true }),
|
|
|
|
|
desc: (a, b) =>
|
|
|
|
|
getTitle(b).localeCompare(getTitle(a), undefined, { numeric: true })
|
2022-08-31 06:33:37 +05:00
|
|
|
}
|
2022-06-16 16:01:08 +05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function getTitle(item) {
|
2022-12-05 10:54:55 +05:00
|
|
|
return item.alias || item.title || "";
|
2022-06-16 16:01:08 +05:00
|
|
|
}
|
2021-07-12 13:48:19 +05:00
|
|
|
|
|
|
|
|
const KEY_SELECTORS = {
|
2021-11-18 11:01:12 +05:00
|
|
|
abc: (item) => getFirstCharacter(item.alias || item.title),
|
2022-06-16 16:01:08 +05:00
|
|
|
month: (item, groupBy, dateNow) => {
|
|
|
|
|
dateNow.setTime(item[groupBy]);
|
|
|
|
|
return MONTHS_FULL[dateNow.getMonth()];
|
|
|
|
|
},
|
2021-07-12 13:48:19 +05:00
|
|
|
week: (item, groupBy) => getWeekGroupFromTimestamp(item[groupBy]),
|
2022-06-16 16:01:08 +05:00
|
|
|
year: (item, groupBy, dateNow) => {
|
|
|
|
|
dateNow.setTime(item[groupBy]);
|
|
|
|
|
return dateNow.getFullYear();
|
|
|
|
|
},
|
|
|
|
|
default: (item, groupBy, dateNow) => {
|
|
|
|
|
const date = item[groupBy];
|
|
|
|
|
return date > dateNow.getTime() - MILLISECONDS_IN_WEEK
|
2021-07-12 13:48:19 +05:00
|
|
|
? "Recent"
|
2022-06-16 16:01:08 +05:00
|
|
|
: date > dateNow.getTime() - MILLISECONDS_IN_WEEK * 2
|
2021-07-12 13:48:19 +05:00
|
|
|
? "Last week"
|
2021-07-13 20:00:10 +05:00
|
|
|
: "Older";
|
2022-08-31 06:33:37 +05:00
|
|
|
}
|
2021-07-12 13:48:19 +05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {any[]} array
|
|
|
|
|
* @param {GroupOptions} options
|
|
|
|
|
* @returns Grouped array
|
|
|
|
|
*/
|
2021-07-12 14:09:48 +05:00
|
|
|
export function groupArray(
|
|
|
|
|
array,
|
|
|
|
|
options = {
|
2021-07-16 18:46:16 +05:00
|
|
|
groupBy: "default",
|
2021-07-12 14:09:48 +05:00
|
|
|
sortBy: "dateEdited",
|
2022-08-31 06:33:37 +05:00
|
|
|
sortDirection: "desc"
|
2021-07-12 14:09:48 +05:00
|
|
|
}
|
|
|
|
|
) {
|
2022-06-16 16:01:08 +05:00
|
|
|
const cachedDate = new Date();
|
|
|
|
|
|
|
|
|
|
if (options.sortBy && options.sortDirection) {
|
|
|
|
|
const selector = comparators[options.sortBy][options.sortDirection];
|
|
|
|
|
array.sort(selector);
|
|
|
|
|
}
|
2021-07-12 13:48:19 +05:00
|
|
|
|
2022-03-31 14:32:24 +05:00
|
|
|
if (options.groupBy === "none") {
|
2022-07-19 11:22:03 +05:00
|
|
|
const conflicted = [];
|
|
|
|
|
const pinned = [];
|
|
|
|
|
const others = [];
|
|
|
|
|
for (const item of array) {
|
|
|
|
|
if (item.pinned) {
|
|
|
|
|
pinned.push(item);
|
|
|
|
|
continue;
|
|
|
|
|
} else if (item.conflicted) {
|
|
|
|
|
conflicted.push(item);
|
|
|
|
|
continue;
|
|
|
|
|
} else others.push(item);
|
|
|
|
|
}
|
|
|
|
|
const groups = [];
|
|
|
|
|
if (conflicted.length > 0)
|
|
|
|
|
groups.push({ title: "Conflicted", type: "header" }, ...conflicted);
|
|
|
|
|
if (pinned.length > 0)
|
|
|
|
|
groups.push({ title: "Pinned", type: "header" }, ...pinned);
|
|
|
|
|
if (others.length > 0)
|
|
|
|
|
groups.push({ title: "All", type: "header" }, ...others);
|
|
|
|
|
return groups;
|
2022-03-31 14:32:24 +05:00
|
|
|
}
|
|
|
|
|
|
2022-06-16 16:01:08 +05:00
|
|
|
const groups = new Map([
|
|
|
|
|
["Conflicted", []],
|
2022-08-31 06:33:37 +05:00
|
|
|
["Pinned", []]
|
2022-06-16 16:01:08 +05:00
|
|
|
]);
|
|
|
|
|
|
2022-03-31 14:32:24 +05:00
|
|
|
const keySelector = KEY_SELECTORS[options.groupBy || "default"];
|
2021-07-12 13:48:19 +05:00
|
|
|
array.forEach((item) => {
|
2022-06-16 16:01:08 +05:00
|
|
|
if (item.pinned) {
|
|
|
|
|
return addToGroup(groups, "Pinned", item);
|
|
|
|
|
} else if (item.conflicted) return addToGroup(groups, "Conflicted", item);
|
|
|
|
|
|
|
|
|
|
const groupTitle = keySelector(item, options.sortBy, cachedDate);
|
|
|
|
|
addToGroup(groups, groupTitle, item);
|
2021-07-12 13:48:19 +05:00
|
|
|
});
|
|
|
|
|
|
2023-01-04 15:23:15 +05:00
|
|
|
return flattenGroups(groups);
|
|
|
|
|
}
|
2022-06-16 16:01:08 +05:00
|
|
|
|
2023-01-04 15:23:15 +05:00
|
|
|
/**
|
|
|
|
|
* @param {any[]} array
|
|
|
|
|
* @param {GroupOptions} options
|
2023-01-04 19:13:09 +05:00
|
|
|
* @returns {(Reminder | {type: "header", title: string})[]} Grouped array
|
2023-01-04 15:23:15 +05:00
|
|
|
*/
|
|
|
|
|
export function groupReminders(array) {
|
|
|
|
|
const groups = new Map([
|
|
|
|
|
["Active", []],
|
|
|
|
|
["Inactive", []]
|
|
|
|
|
]);
|
2022-06-16 16:01:08 +05:00
|
|
|
|
2023-01-04 15:23:15 +05:00
|
|
|
array.forEach((item) => {
|
|
|
|
|
const groupTitle = isReminderActive(item) ? "Active" : "Inactive";
|
|
|
|
|
addToGroup(groups, groupTitle, item);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return flattenGroups(groups);
|
2021-07-12 13:48:19 +05:00
|
|
|
}
|
2021-11-03 13:33:47 +05:00
|
|
|
|
2022-06-16 16:01:08 +05:00
|
|
|
function addToGroup(groups, groupTitle, item) {
|
|
|
|
|
const group = groups.get(groupTitle) || [];
|
|
|
|
|
group.push(item);
|
|
|
|
|
groups.set(groupTitle, group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const REGEX = /\S/;
|
2021-11-18 11:01:12 +05:00
|
|
|
function getFirstCharacter(str) {
|
|
|
|
|
if (!str) return "-";
|
2022-06-16 16:01:08 +05:00
|
|
|
return REGEX.exec(str)[0].toUpperCase();
|
2021-11-03 13:33:47 +05:00
|
|
|
}
|
2023-01-04 15:23:15 +05:00
|
|
|
|
|
|
|
|
function flattenGroups(groups) {
|
|
|
|
|
let items = [];
|
|
|
|
|
for (let [groupTitle, groupItems] of groups.entries()) {
|
|
|
|
|
if (!groupItems.length) continue;
|
|
|
|
|
|
|
|
|
|
let group = { title: groupTitle, type: "header" };
|
|
|
|
|
items.push(group);
|
|
|
|
|
groupItems.forEach((item) => items.push(item));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return items;
|
|
|
|
|
}
|