diff --git a/packages/core/api/settings.js b/packages/core/api/settings.js index aafaefc73..b673b0e24 100644 --- a/packages/core/api/settings.js +++ b/packages/core/api/settings.js @@ -1,5 +1,6 @@ import { EV, EVENTS } from "../common"; import id from "../utils/id"; +import "../types"; import setManipulator from "../utils/set"; class Settings { @@ -12,31 +13,6 @@ class Settings { this._initSettings(); } - _initSettings() { - this._settings = { - type: "settings", - id: id(), - pins: [], - dateEdited: 0, - dateCreated: 0, - }; - } - - get raw() { - return this._settings; - } - - async merge(item) { - // TODO if (this.settings.dateEdited > (await this._db.lastSynced())) { - // this._settings.pins = setManipulator.union( - // this._settings.pins, - // item.pins - // ); - // } - this._settings = item; - await this._db.context.write("settings", item); - } - async init() { var settings = await this._db.context.read("settings"); if (settings) this._settings = settings; @@ -46,13 +22,53 @@ class Settings { }); } + get raw() { + return this._settings; + } + + async merge(item) { + if (this.settings.dateEdited > (await this._db.lastSynced())) { + this._settings.pins = setManipulator.union( + this._settings.pins, + item.pins + ); + this._settings.groupOptions = { + ...item.groupOptions, + ...this._settings.groupOptions, + }; + } else { + this._settings = item; + } + await this._db.context.write("settings", item); + } + + /** + * + * @param {string} key + * @param {GroupOptions} groupOptions + */ + async setGroupOptions(key, groupOptions) { + this._settings.groupOptions[key] = groupOptions; + await this._saveSettings(); + } + + /** + * + * @param {string} key + * @returns {GroupOptions} + */ + getGroupOptions(key) { + return this._settings.groupOptions[key]; + } + async pin(type, data) { if (type !== "notebook" && type !== "topic" && type !== "tag") throw new Error("This item cannot be pinned."); if (this.isPinned(data.id)) return; this._settings.pins.push({ type, data }); this._settings.dateEdited = Date.now(); - await this._db.context.write("settings", this._settings); + + await this._saveSettings(); } async unpin(id) { @@ -60,7 +76,8 @@ class Settings { if (index <= -1) return; this._settings.pins.splice(index, 1); this._settings.dateEdited = Date.now(); - await this._db.context.write("settings", this._settings); + + await this._saveSettings(); } isPinned(id) { @@ -89,5 +106,20 @@ class Settings { return prev; }, []); } + + _initSettings() { + this._settings = { + type: "settings", + id: id(), + pins: [], + groupOptions: {}, + dateEdited: 0, + dateCreated: 0, + }; + } + + async _saveSettings() { + await this._db.context.write("settings", this._settings); + } } export default Settings; diff --git a/packages/core/collections/notes.js b/packages/core/collections/notes.js index 89d030fd1..90dd96e48 100644 --- a/packages/core/collections/notes.js +++ b/packages/core/collections/notes.js @@ -1,11 +1,4 @@ -import { groupBy, isHex } from "../utils"; import Collection from "./collection"; -import { - getWeekGroupFromTimestamp, - months, - getLastWeekTimestamp, - get7DayTimestamp, -} from "../utils/date"; import Note from "../models/note"; import getId from "../utils/id"; import { EV, EVENTS } from "../common"; @@ -202,62 +195,6 @@ export default class Notes extends Collection { return sort(array).desc((note) => note.dateCreated); } - /** - * - * @param {"abc"|"month"|"year"|"week"|undefined} by - * @param {"asc"|"desc"} sort - */ - group(by, sort = "desc") { - let notes = this.all; - - switch (by) { - case "abc": - return groupBy( - notes, - (note) => note.title[0].toUpperCase(), - (t) => t.title[0], - sort - ); - case "month": - return groupBy( - notes, - (note) => months[new Date(note.dateCreated).getMonth()], - (t) => t.dateCreated, - sort - ); - case "week": - return groupBy( - notes, - (note) => getWeekGroupFromTimestamp(note.dateCreated), - (t) => t.dateCreated, - sort - ); - case "year": - return groupBy( - notes, - (note) => new Date(note.dateCreated).getFullYear().toString(), - (t) => t.dateCreated, - sort - ); - default: - let timestamps = { - recent: getLastWeekTimestamp(7), - lastWeek: getLastWeekTimestamp(7) - get7DayTimestamp(), //seven day timestamp value - }; - return groupBy( - notes, - (note) => - note.dateCreated >= timestamps.recent - ? "Recent" - : note.dateCreated >= timestamps.lastWeek - ? "Last week" - : "Older", - (t) => t.dateCreated, - sort - ); - } - } - delete(...ids) { return this._delete(true, ...ids); } diff --git a/packages/core/types.js b/packages/core/types.js new file mode 100644 index 000000000..7ebc92c37 --- /dev/null +++ b/packages/core/types.js @@ -0,0 +1,8 @@ +/** + * @typedef {{ + * groupId: "abc" | "year" | "month" | "week" | undefined, + * groupBy: "dateCreated" | "dateDeleted" | "dateEdited", + * sortBy: "dateCreated" | "dateDeleted" | "dateEdited" | "title", + * sortDirection: "desc" | "asc" + * }} GroupOptions + */ diff --git a/packages/core/utils/grouping.js b/packages/core/utils/grouping.js new file mode 100644 index 000000000..c74b0615b --- /dev/null +++ b/packages/core/utils/grouping.js @@ -0,0 +1,68 @@ +import "../types"; +import fastsort from "fast-sort"; +import { + getWeekGroupFromTimestamp, + months, + getLastWeekTimestamp, + get7DayTimestamp, +} from "./date"; + +/** + * + * @param {GroupOptions} options + * @returns sort selectors + */ +const getSortSelectors = (options) => [ + { desc: (t) => t.conflicted }, + { desc: (t) => t.pinned }, + { [options.sortDirection]: (item) => item[options.sortBy] }, +]; + +const TIMESTAMPS = { + recent: () => getLastWeekTimestamp(7), + lastWeek: () => getLastWeekTimestamp(7) - get7DayTimestamp(), //seven day timestamp value +}; + +const KEY_SELECTORS = { + abc: (item) => item.title[0].toUpperCase(), + month: (item, groupBy) => months[new Date(item[groupBy]).getMonth()], + week: (item, groupBy) => getWeekGroupFromTimestamp(item[groupBy]), + year: (item, groupBy) => new Date(item[groupBy]).getFullYear().toString(), + default: (item, groupBy) => + item[groupBy] >= TIMESTAMPS.recent() + ? "Recent" + : item[groupBy] >= TIMESTAMPS.lastWeek() + ? "Last week" + : "Older", +}; + +/** + * @param {any[]} array + * @param {GroupOptions} options + * @returns Grouped array + */ +export function groupArray(array, options) { + const keySelector = KEY_SELECTORS[options.groupId]; + if (sortSelector) fastsort(array).by(getSortSelectors(options)); + + let groups = new Map(); + array.forEach((item) => { + let groupTitle = item.pinned + ? "Pinned" + : item.conflicted + ? "Conflicted" + : keySelector(item, options.groupBy); + + let group = groups.get(groupTitle) || []; + group.push(item); + groups.set(groupTitle, group); + }); + + let items = []; + groups.forEach((groupItems, groupTitle) => { + let group = { title: groupTitle, type: "header" }; + items.push(group); + groupItems.forEach((item) => items.push(item)); + }); + return items; +} diff --git a/packages/core/utils/index.js b/packages/core/utils/index.js deleted file mode 100644 index aa994d2de..000000000 --- a/packages/core/utils/index.js +++ /dev/null @@ -1,38 +0,0 @@ -import fastsort from "fast-sort"; - -export function groupBy(arr, key, sortSelector, sortDirection) { - if (sortSelector) - fastsort(arr).by([ - { desc: (t) => t.conflicted }, - { desc: (t) => t.pinned }, - { [sortDirection]: sortSelector }, - ]); - - let groups = new Map(); - arr.forEach((item) => { - let groupTitle = item.pinned - ? "Pinned" - : item.conflicted - ? "Conflicted" - : key(item); - - let arr = groups.get(groupTitle) || []; - arr.push(item); - groups.set(groupTitle, arr); - }); - - let items = []; - groups.forEach((groupItems, groupTitle) => { - let group = { title: groupTitle, type: "header" }; - items.push(group); - groupItems.forEach((item) => items.push(item)); - }); - return items; -} - -var hexPattern = /([A-F]|[a-f]|\d)*/; -export function isHex(input) { - if (typeof input !== "string") return false; - if (!input.match || input.length < 16) return false; - return input.match(hexPattern)[0] === input; -}