Files
notesnook/packages/core/collections/notes.js

273 lines
6.6 KiB
JavaScript
Raw Normal View History

import CachedCollection from "../database/cached-collection";
2020-02-03 12:03:07 +05:00
import fuzzysearch from "fuzzysearch";
2020-03-21 11:15:24 +05:00
import { groupBy, isHex } from "../utils";
import sort from "fast-sort";
2020-02-03 12:03:07 +05:00
import {
getWeekGroupFromTimestamp,
months,
getLastWeekTimestamp,
get7DayTimestamp
2020-02-03 12:03:07 +05:00
} from "../utils/date";
2020-02-05 00:17:12 +05:00
import Notebooks from "./notebooks";
2020-02-05 20:57:43 +05:00
import Note from "../models/note";
2020-02-06 16:46:23 +05:00
import Trash from "./trash";
2020-03-19 11:30:05 +05:00
import getId from "../utils/id";
import Tags from "./tags";
import Content from "./content";
2020-02-03 12:03:07 +05:00
var tfun = require("transfun/transfun.js").tfun;
if (!tfun) {
tfun = global.tfun;
}
export default class Notes {
constructor(context) {
this._collection = new CachedCollection(context, "notes");
2020-02-03 12:03:07 +05:00
}
2020-02-05 00:17:12 +05:00
/**
*
* @param {Notebooks} notebooks
2020-02-06 16:46:23 +05:00
* @param {Trash} trash
2020-03-19 11:30:05 +05:00
* @param {Tags} tags
* @param {Tags} colors
* @param {Content} delta
* @param {Content} text
2020-02-05 00:17:12 +05:00
*/
2020-03-19 11:30:05 +05:00
async init(notebooks, trash, tags, colors, delta, text) {
await this._collection.init();
this._notebooks = notebooks;
this._trash = trash;
this._tagsCollection = tags;
this._colorsCollection = colors;
2020-03-19 11:30:05 +05:00
this._deltaCollection = delta;
this._textCollection = text;
2020-02-03 12:03:07 +05:00
}
async add(noteArg) {
if (!noteArg) return;
2020-03-21 11:15:24 +05:00
if (noteArg.remote) {
return await this._collection.addItem(noteArg);
}
2020-02-03 12:03:07 +05:00
2020-03-18 14:06:20 +05:00
let id = noteArg.id || getId();
let oldNote = this._collection.getItem(id);
2020-03-19 11:30:05 +05:00
let deltaId = 0;
let textId = 0;
if (oldNote && oldNote.content) {
deltaId = oldNote.content.delta;
textId = oldNote.content.text;
}
2020-02-03 12:03:07 +05:00
let note = {
...oldNote,
...noteArg
};
if (isNoteEmpty(note)) {
if (oldNote) await this.delete(id);
return;
}
2020-03-21 11:15:24 +05:00
const { text, delta } = note.content;
if (!textId && isHex(text)) textId = text;
if (!deltaId && isHex(delta)) deltaId = delta;
if (delta && delta.ops) {
2020-03-19 11:30:05 +05:00
deltaId = await this._deltaCollection.add({
2020-03-19 12:38:33 +05:00
noteId: id,
2020-03-19 11:30:05 +05:00
id: deltaId,
2020-03-21 11:15:24 +05:00
data: delta
2020-03-19 11:30:05 +05:00
});
}
2020-03-21 11:15:24 +05:00
if (text !== textId) {
2020-03-19 11:30:05 +05:00
textId = await this._textCollection.add({
2020-03-19 12:38:33 +05:00
noteId: id,
2020-03-19 11:30:05 +05:00
id: textId,
2020-03-21 11:15:24 +05:00
data: text
2020-03-19 11:30:05 +05:00
});
note.title = getNoteTitle(note);
note.headline = getNoteHeadline(note);
2020-02-20 11:28:16 +05:00
}
2020-02-03 12:03:07 +05:00
note = {
id,
type: "note",
2020-03-19 11:30:05 +05:00
title: note.title,
content: { text: textId, delta: deltaId },
2020-02-03 12:03:07 +05:00
pinned: !!note.pinned,
locked: !!note.locked,
notebook: note.notebook || {},
colors: note.colors || [],
tags: note.tags || [],
favorite: !!note.favorite,
2020-03-19 11:30:05 +05:00
headline: note.headline,
dateCreated: note.dateCreated
2020-02-03 12:03:07 +05:00
};
2020-02-06 22:35:53 +05:00
if (!oldNote) {
for (let color of note.colors) {
await this._colorsCollection.add(color, id);
2020-02-06 22:35:53 +05:00
}
2020-02-03 12:03:07 +05:00
for (let tag of note.tags) {
await this._tagsCollection.add(tag, id);
2020-02-03 12:03:07 +05:00
}
}
await this._collection.addItem(note);
return note.id;
}
2020-02-06 22:46:57 +05:00
/**
*
* @param {string} id The id of note
* @returns {Note} The note of the given id
*/
2020-02-05 20:57:43 +05:00
note(id) {
if (!id) return;
let note = id.type ? id : this._collection.getItem(id);
if (!note) return;
2020-02-05 20:57:43 +05:00
return new Note(this, note);
2020-02-03 12:03:07 +05:00
}
2020-03-23 15:06:12 +05:00
get raw() {
return this._collection.getRaw();
}
2020-02-03 12:03:07 +05:00
get all() {
return this._collection.getAllItems();
2020-02-03 12:03:07 +05:00
}
get pinned() {
return tfun.filter(".pinned === true")(this.all);
}
get favorites() {
return tfun.filter(".favorite === true")(this.all);
}
tagged(tag) {
return this._tagsCollection
2020-03-23 15:06:12 +05:00
.notes(tag)
.map(id => this._collection.getItem(id));
2020-02-03 12:03:07 +05:00
}
colored(color) {
return this._colorsCollection
2020-03-23 15:06:12 +05:00
.notes(color)
.map(id => this._collection.getItem(id));
2020-02-03 12:03:07 +05:00
}
group(by, special = false) {
let notes = !special
? tfun.filter(".pinned === false")(this.all)
: this.all;
2020-02-27 16:43:47 +05:00
notes = sort(notes).desc(t => t.dateCreated);
2020-02-03 12:03:07 +05:00
switch (by) {
case "abc":
2020-02-27 16:43:47 +05:00
return groupBy(notes, note => note.title[0].toUpperCase(), special);
2020-02-03 12:03:07 +05:00
case "month":
return groupBy(
notes,
note => months[new Date(note.dateCreated).getMonth()],
special
);
case "week":
return groupBy(
notes,
note => getWeekGroupFromTimestamp(note.dateCreated),
special
);
case "year":
return groupBy(
notes,
note => new Date(note.dateCreated).getFullYear().toString(),
special
);
default:
let timestamps = {
recent: getLastWeekTimestamp(7),
lastWeek: getLastWeekTimestamp(7) - get7DayTimestamp() //seven day timestamp value
2020-02-03 12:03:07 +05:00
};
return groupBy(
notes,
note =>
note.dateCreated >= timestamps.recent
? "Recent"
: note.dateCreated >= timestamps.lastWeek
? "Last week"
: "Older",
special
);
}
}
async delete(...ids) {
for (let id of ids) {
2020-02-05 20:57:43 +05:00
let item = this.note(id);
if (!item) continue;
if (item.notebook && item.notebook.id && item.notebook.topic) {
await this._collection.transaction(() =>
this._notebooks
2020-02-05 20:57:43 +05:00
.notebook(item.notebook.id)
.topics.topic(item.notebook.topic)
.delete(id)
);
2020-02-03 12:03:07 +05:00
}
for (let tag of item.tags) {
await this._tagsCollection.remove(tag, id);
2020-02-03 12:03:07 +05:00
}
for (let color of item.colors) {
await this._colorsCollection.remove(color, id);
}
2020-03-23 13:22:28 +05:00
await this._collection.removeItem(id);
await this._trash.add(item.data);
2020-02-03 12:03:07 +05:00
}
}
2020-02-05 00:17:12 +05:00
async move(to, ...noteIds) {
if (!to) throw new Error("The destination notebook cannot be undefined.");
if (!to.id || !to.topic)
throw new Error(
"The destination notebook must contain notebookId and topic."
);
let topic = this._notebooks.notebook(to.id).topics.topic(to.topic);
2020-02-05 00:17:12 +05:00
if (!topic) throw new Error("No such topic exists.");
2020-03-02 10:29:29 +05:00
await topic.add(...noteIds);
2020-02-05 00:17:12 +05:00
}
2020-02-03 12:03:07 +05:00
}
function isNoteEmpty(note) {
2020-03-09 09:45:54 +05:00
if (!note.content) return true;
const {
title,
content: { delta, text },
locked
} = note;
const isTitleEmpty = !title || !title.trim().length;
2020-03-21 11:55:00 +05:00
const isTextEmpty = !isHex(text) && (!text || !text.trim().length);
const isDeltaEmpty = !isHex(delta) && (!delta || !delta.ops);
2020-03-09 09:45:54 +05:00
return !locked && isTitleEmpty && isTextEmpty && isDeltaEmpty;
2020-02-03 12:03:07 +05:00
}
function getNoteHeadline(note) {
if (note.locked) return "";
return (
note.content.text.substring(0, 150) +
(note.content.text.length > 150 ? "..." : "")
);
}
function getNoteTitle(note) {
if (note.title && note.title.length > 0) return note.title.trim();
return note.content.text
.split(" ")
.slice(0, 3)
.join(" ")
.trim();
}