refactor: make all private methods/properties start with an underscore

This commit is contained in:
thecodrr
2020-02-22 21:53:56 +05:00
parent 4a96a0aae2
commit 8bf34553cc
11 changed files with 197 additions and 178 deletions

View File

@@ -213,6 +213,7 @@ test("pin note", () =>
noteTest().then(async ({ db, id }) => { noteTest().then(async ({ db, id }) => {
let note = db.notes.note(id); let note = db.notes.note(id);
await note.pin(); await note.pin();
note = db.notes.note(id);
expect(note.data.pinned).toBe(true); expect(note.data.pinned).toBe(true);
})); }));
@@ -220,6 +221,7 @@ test("favorite note", () =>
noteTest().then(async ({ db, id }) => { noteTest().then(async ({ db, id }) => {
let note = db.notes.note(id); let note = db.notes.note(id);
await note.favorite(); await note.favorite();
note = db.notes.note(id);
expect(note.data.favorite).toBe(true); expect(note.data.favorite).toBe(true);
})); }));
@@ -232,6 +234,7 @@ test("lock and unlock note", () =>
}).then(async ({ db, id }) => { }).then(async ({ db, id }) => {
let note = db.notes.note(id); let note = db.notes.note(id);
await note.lock("password123"); await note.lock("password123");
note = db.notes.note(id);
expect(note.data.locked).toBe(true); expect(note.data.locked).toBe(true);
expect(note.data.content.iv).toBeDefined(); expect(note.data.content.iv).toBeDefined();
expect((await note.delta()).iv).toBeDefined(); expect((await note.delta()).iv).toBeDefined();
@@ -253,8 +256,9 @@ test("add note to topic", () =>
await topics.add("Home"); await topics.add("Home");
let topic = topics.topic("Home"); let topic = topics.topic("Home");
await topic.add(id); await topic.add(id);
topic = topics.topic("Home");
expect(topic.all.length).toBe(1); expect(topic.all.length).toBe(1);
expect(topic.topic.totalNotes).toBe(1); expect(topic.totalNotes).toBe(1);
expect(db.notebooks.notebook(notebookId).data.totalNotes).toBe(1); expect(db.notebooks.notebook(notebookId).data.totalNotes).toBe(1);
let note = db.notes.note(id); let note = db.notes.note(id);
expect(note.notebook.id).toBe(notebookId); expect(note.notebook.id).toBe(notebookId);

View File

@@ -47,7 +47,9 @@ test("get topic", () =>
let topic = topics.topic("Home"); let topic = topics.topic("Home");
let noteId = await db.notes.add({ content: { text: "Hello", delta: [] } }); let noteId = await db.notes.add({ content: { text: "Hello", delta: [] } });
await topic.add(noteId); await topic.add(noteId);
topic = topics.topic("Home");
expect(topic.all[0].content.text).toBe("Hello"); expect(topic.all[0].content.text).toBe("Hello");
expect(topic.totalNotes).toBe(1);
})); }));
test("delete a topic", () => test("delete a topic", () =>

View File

@@ -17,10 +17,10 @@ test("delete a note", () =>
.add(id); .add(id);
await db.notes.delete(id); await db.notes.delete(id);
expect(db.trash.all.length).toBe(1); expect(db.trash.all.length).toBe(1);
expect(await db.trash.deltaStorage.read(id + "_delta")).toBeDefined(); expect(await db.trash._deltaStorage.read(id + "_delta")).toBeDefined();
await db.trash.delete(db.trash.all[0].id); await db.trash.delete(db.trash.all[0].id);
expect(db.trash.all.length).toBe(0); expect(db.trash.all.length).toBe(0);
expect(await db.trash.deltaStorage.read(id + "_delta")).toBeUndefined(); expect(await db.trash._deltaStorage.read(id + "_delta")).toBeUndefined();
})); }));
test("restore a deleted note", () => test("restore a deleted note", () =>

View File

@@ -9,9 +9,7 @@ if (!tfun) {
} }
export default class Notebooks { export default class Notebooks {
constructor(context) { constructor(context) {
this.context = context; this._collection = new CachedCollection(context, "notebooks");
this.collection = new CachedCollection(context, "notebooks");
this.notes = undefined;
} }
/** /**
@@ -20,16 +18,16 @@ export default class Notebooks {
* @param {Trash} trash * @param {Trash} trash
*/ */
init(notes, trash) { init(notes, trash) {
this.notes = notes; this._trash = trash;
this.trash = trash; this._notes = notes;
return this.collection.init(); return this._collection.init();
} }
async add(notebookArg) { async add(notebookArg) {
if (!notebookArg) throw new Error("Notebook cannot be undefined or null."); if (!notebookArg) throw new Error("Notebook cannot be undefined or null.");
//TODO reliably and efficiently check for duplicates. //TODO reliably and efficiently check for duplicates.
const id = notebookArg.id || Date.now().toString() + "_notebook"; const id = notebookArg.id || Date.now().toString() + "_notebook";
let oldNotebook = this.collection.getItem(id); let oldNotebook = this._collection.getItem(id);
if (!oldNotebook && !notebookArg.title) if (!oldNotebook && !notebookArg.title)
throw new Error("Notebook must contain at least a title."); throw new Error("Notebook must contain at least a title.");
@@ -54,7 +52,7 @@ export default class Notebooks {
notebook.topics.splice(0, 0, "General"); notebook.topics.splice(0, 0, "General");
} }
await this.collection.addItem(notebook); await this._collection.addItem(notebook);
//if (!oldNotebook) { //if (!oldNotebook) {
await this.notebook(notebook.id).topics.add(...notebook.topics); await this.notebook(notebook.id).topics.add(...notebook.topics);
@@ -63,7 +61,7 @@ export default class Notebooks {
} }
get all() { get all() {
return this.collection.getAllItems(); return this._collection.getAllItems();
} }
/** /**
@@ -72,7 +70,7 @@ export default class Notebooks {
* @returns {Notebook} The notebook of the given id * @returns {Notebook} The notebook of the given id
*/ */
notebook(id) { notebook(id) {
let notebook = this.collection.getItem(id); let notebook = this._collection.getItem(id);
if (!notebook) return; if (!notebook) return;
return new Notebook(this, notebook); return new Notebook(this, notebook);
} }
@@ -81,11 +79,11 @@ export default class Notebooks {
for (let id of ids) { for (let id of ids) {
let notebook = this.notebook(id); let notebook = this.notebook(id);
if (!notebook) continue; if (!notebook) continue;
await this.collection.transaction(() => await this._collection.transaction(() =>
notebook.topics.delete(...notebook.topics.all) notebook.topics.delete(...notebook.data.topics)
); );
await this.collection.removeItem(id); await this._collection.removeItem(id);
await this.trash.add(notebook.data); await this._trash.add(notebook.data);
} }
} }

View File

@@ -19,8 +19,8 @@ if (!tfun) {
export default class Notes { export default class Notes {
constructor(context) { constructor(context) {
this.collection = new CachedCollection(context, "notes"); this._collection = new CachedCollection(context, "notes");
this.deltaStorage = new Storage(context); this._deltaStorage = new Storage(context);
} }
/** /**
@@ -29,20 +29,18 @@ export default class Notes {
* @param {Trash} trash * @param {Trash} trash
*/ */
async init(notebooks, trash, tags, colors) { async init(notebooks, trash, tags, colors) {
await this.collection.init(); await this._collection.init();
this.notebooks = notebooks; this._notebooks = notebooks;
this.trash = trash; this._trash = trash;
// await this.tagsCollection.init(); this._tagsCollection = tags;
// await this.colorsCollection.init(); this._colorsCollection = colors;
this.tagsCollection = tags;
this.colorsCollection = colors;
} }
async add(noteArg) { async add(noteArg) {
if (!noteArg) return; if (!noteArg) return;
let id = noteArg.id || Date.now().toString() + "_note"; let id = noteArg.id || Date.now().toString() + "_note";
let oldNote = this.collection.getItem(id); let oldNote = this._collection.getItem(id);
let note = { let note = {
...oldNote, ...oldNote,
...noteArg ...noteArg
@@ -54,7 +52,7 @@ export default class Notes {
} }
if (!(note.content.delta instanceof String)) { if (!(note.content.delta instanceof String)) {
await this.deltaStorage.write(id + "_delta", note.content.delta); await this._deltaStorage.write(id + "_delta", note.content.delta);
} }
note = { note = {
@@ -74,15 +72,15 @@ export default class Notes {
if (!oldNote) { if (!oldNote) {
for (let color of note.colors) { for (let color of note.colors) {
await this.colorsCollection.add(color); await this._colorsCollection.add(color);
} }
for (let tag of note.tags) { for (let tag of note.tags) {
await this.tagsCollection.add(tag); await this._tagsCollection.add(tag);
} }
} }
await this.collection.addItem(note); await this._collection.addItem(note);
return note.id; return note.id;
} }
@@ -92,13 +90,13 @@ export default class Notes {
* @returns {Note} The note of the given id * @returns {Note} The note of the given id
*/ */
note(id) { note(id) {
let note = this.collection.getItem(id); let note = this._collection.getItem(id);
if (!note) return undefined; if (!note) return undefined;
return new Note(this, note); return new Note(this, note);
} }
get all() { get all() {
return this.collection.getAllItems(); return this._collection.getAllItems();
} }
get pinned() { get pinned() {
@@ -121,9 +119,7 @@ export default class Notes {
if (!query) return []; if (!query) return [];
let queryFn = v => fuzzysearch(query, v.title + " " + v.content.text); let queryFn = v => fuzzysearch(query, v.title + " " + v.content.text);
if (query instanceof Function) queryFn = query; if (query instanceof Function) queryFn = query;
let c = tfun.filter(queryFn)(this.all); return tfun.filter(queryFn)(this.all);
return c;
} }
group(by, special = false) { group(by, special = false) {
@@ -179,18 +175,18 @@ export default class Notes {
let item = this.note(id); let item = this.note(id);
if (!item) continue; if (!item) continue;
if (item.notebook && item.notebook.id && item.notebook.topic) { if (item.notebook && item.notebook.id && item.notebook.topic) {
await this.collection.transaction(() => await this._collection.transaction(() =>
this.notebooks this._notebooks
.notebook(item.notebook.id) .notebook(item.notebook.id)
.topics.topic(item.notebook.topic) .topics.topic(item.notebook.topic)
.delete(id) .delete(id)
); );
} }
for (let tag of item.tags) { for (let tag of item.tags) {
await this.tagsCollection.remove(tag); await this._tagsCollection.remove(tag);
} }
await this.collection.removeItem(id); await this._collection.removeItem(id);
await this.trash.add(item.data); await this._trash.add(item.data);
} }
} }
@@ -200,7 +196,7 @@ export default class Notes {
throw new Error( throw new Error(
"The destination notebook must contain notebookId and topic." "The destination notebook must contain notebookId and topic."
); );
let topic = this.notebooks.notebook(to.id).topics.topic(to.topic); let topic = this._notebooks.notebook(to.id).topics.topic(to.topic);
if (!topic) throw new Error("No such topic exists."); if (!topic) throw new Error("No such topic exists.");
await topic.transaction(async () => { await topic.transaction(async () => {
await topic.add(...noteIds); await topic.add(...noteIds);

View File

@@ -2,37 +2,37 @@ import CachedCollection from "../database/cached-collection";
export default class Tags { export default class Tags {
constructor(context, name) { constructor(context, name) {
this.collection = new CachedCollection(context, name); this._collection = new CachedCollection(context, name);
} }
init() { init() {
return this.collection.init(); return this._collection.init();
} }
async add(id) { async add(id) {
if (!id || id.trim().length <= 0) return; if (!id || id.trim().length <= 0) return;
let tag = (await this.collection.getItem(id)) || { let tag = (await this._collection.getItem(id)) || {
id, id,
title: id, title: id,
count: 0 count: 0
}; };
tag.count++; tag.count++;
await this.collection.addItem(tag); await this._collection.addItem(tag);
} }
get all() { get all() {
return this.collection.getAllItems(); return this._collection.getAllItems();
} }
async remove(id) { async remove(id) {
if (!id || id.trim().length <= 0) return; if (!id || id.trim().length <= 0) return;
let tag = this.collection.getItem(id); let tag = this._collection.getItem(id);
if (!tag) return; if (!tag) return;
tag.count--; tag.count--;
if (tag.count === 0) { if (tag.count === 0) {
await this.collection.removeItem(id); await this._collection.removeItem(id);
} else { } else {
await this.collection.addItem(tag); await this._collection.addItem(tag);
} }
} }
} }

View File

@@ -7,43 +7,50 @@ export default class Topics {
/** /**
* *
* @param {Notebooks} notebooks * @param {Notebooks} notebooks
* @param {Notes} notes
* @param {string} notebookId * @param {string} notebookId
*/ */
constructor(notebooks, notes, notebookId) { constructor(notebooks, notebookId) {
this.notebooks = notebooks; this._notebooks = notebooks;
this.notebookId = notebookId; this._notebookId = notebookId;
this.notes = notes;
} }
exists(topic) { has(topic) {
return this.all.findIndex(v => v.title === (topic.title || topic)) > -1; return this.all.findIndex(v => v.title === (topic.title || topic)) > -1;
} }
async add(...topics) { _dedupe(source) {
let notebook = this.notebooks.notebook(this.notebookId); let length = source.length,
let uniqueTopics = [...notebook.data.topics, ...topics]; seen = new Map();
uniqueTopics = uniqueTopics.filter( for (let index = 0; index < length; index++) {
(v, i) => let value = source[index];
v && let title = value.title || value;
(v.title || v).trim().length > 0 && if (title.trim().length <= 0) continue;
uniqueTopics.findIndex(t => (v.title || v) === (t.title || t)) === i seen.set(title, value);
);
notebook.data.topics = [];
notebook.data.totalNotes = 0;
for (let topic of uniqueTopics) {
let t = makeTopic(topic, this.notebookId);
notebook.data.topics.push(t);
notebook.data.totalNotes += t.totalNotes;
} }
await this.notebooks.collection.addItem(notebook.data); return seen;
}
async add(...topics) {
let notebook = { ...this._notebooks.notebook(this._notebookId).data };
let allTopics = [...notebook.topics, ...topics];
const unique = this._dedupe(allTopics);
notebook.topics = [];
notebook.totalNotes = 0;
unique.forEach(t => {
let topic = makeTopic(t, this._notebookId);
notebook.topics.push(topic);
notebook.totalNotes += topic.totalNotes;
});
return this._notebooks._collection.addItem(notebook);
} }
/** /**
* @returns {Array} an array containing all the topics * @returns {Array} an array containing all the topics
*/ */
get all() { get all() {
return this.notebooks.notebook(this.notebookId).data.topics; return this._notebooks.notebook(this._notebookId).data.topics;
} }
/** /**
@@ -71,7 +78,7 @@ export default class Topics {
allTopics.splice(i, 1); allTopics.splice(i, 1);
} }
} }
await this.notebooks.add({ id: this.notebookId, topics: allTopics }); await this._notebooks.add({ id: this._notebookId, topics: allTopics });
} }
} }

View File

@@ -4,8 +4,8 @@ import Notebooks from "./notebooks";
import Storage from "../database/storage"; import Storage from "../database/storage";
export default class Trash { export default class Trash {
constructor(context) { constructor(context) {
this.collection = new CachedCollection(context, "trash"); this._collection = new CachedCollection(context, "trash");
this.deltaStorage = new Storage(context); this._deltaStorage = new Storage(context);
} }
/** /**
@@ -14,59 +14,59 @@ export default class Trash {
* @param {Notebooks} notebooks * @param {Notebooks} notebooks
*/ */
async init(notes, notebooks) { async init(notes, notebooks) {
this.notes = notes; this._notes = notes;
this.notebooks = notebooks; this._notebooks = notebooks;
await this.collection.init(); await this._collection.init();
} }
get all() { get all() {
return this.collection.getAllItems(); return this._collection.getAllItems();
} }
async add(item) { async add(item) {
if (this.collection.exists(item.id + "_deleted")) if (this._collection.exists(item.id + "_deleted"))
throw new Error("This item has already been deleted."); throw new Error("This item has already been deleted.");
item.dateDeleted = Date.now(); item.dateDeleted = Date.now();
item.id = item.id + "_deleted"; item.id = item.id + "_deleted";
await this.collection.addItem(item); await this._collection.addItem(item);
} }
async delete(...ids) { async delete(...ids) {
for (let id of ids) { for (let id of ids) {
if (!this.collection.exists(id)) return; if (!this._collection.exists(id)) return;
if (id.indexOf("note") > -1) if (id.indexOf("note") > -1)
await this.deltaStorage.remove(id.replace("_deleted", "") + "_delta"); await this._deltaStorage.remove(id.replace("_deleted", "") + "_delta");
await this.collection.removeItem(id); await this._collection.removeItem(id);
} }
} }
async restore(...ids) { async restore(...ids) {
for (let id of ids) { for (let id of ids) {
let item = this.collection.getItem(id); let item = this._collection.getItem(id);
if (!item) continue; if (!item) continue;
delete item.dateDeleted; delete item.dateDeleted;
item.id = item.id.replace("_deleted", ""); item.id = item.id.replace("_deleted", "");
if (item.type === "note") { if (item.type === "note") {
let { notebook } = item; let { notebook } = item;
item.notebook = {}; item.notebook = {};
await this.notes.add(item); await this._notes.add(item);
if (notebook && notebook.id && notebook.topic) { if (notebook && notebook.id && notebook.topic) {
const { id, topic } = notebook; const { id, topic } = notebook;
// if the notebook has been deleted // if the notebook has been deleted
if (!this.notebooks.collection.exists(id)) { if (!this._notebooks._collection.exists(id)) {
notebook = {}; notebook = {};
} else { } else {
// if the topic has been deleted // if the topic has been deleted
if (!this.notebooks.notebook(id).topics.exists(topic)) { if (!this._notebooks.notebook(id).topics.has(topic)) {
notebook = {}; notebook = {};
} }
} }
// restore the note to the topic it was in before deletion // restore the note to the topic it was in before deletion
if (notebook.id && notebook.topic) { if (notebook.id && notebook.topic) {
await this.notebooks await this._notebooks
.notebook(id) .notebook(id)
.topics.topic(topic) .topics.topic(topic)
.add(item.id); .add(item.id);
@@ -75,8 +75,8 @@ export default class Trash {
} else { } else {
const { topics } = item; const { topics } = item;
item.topics = []; item.topics = [];
await this.notebooks.add(item); await this._notebooks.add(item);
let notebook = this.notebooks.notebook(item.id); let notebook = this._notebooks.notebook(item.id);
for (let topic of topics) { for (let topic of topics) {
await notebook.topics.add(topic.title || topic); await notebook.topics.add(topic.title || topic);
let t = notebook.topics.topic(topic.title || topic); let t = notebook.topics.topic(topic.title || topic);
@@ -84,12 +84,12 @@ export default class Trash {
if (topic.notes) await t.add(...topic.notes); if (topic.notes) await t.add(...topic.notes);
} }
} }
await this.collection.removeItem(id); await this._collection.removeItem(id);
} }
} }
async clear() { async clear() {
let indices = await this.collection.indexer.getIndices(); let indices = await this._collection.indexer.getIndices();
return this.delete(...indices); return this.delete(...indices);
} }
} }

View File

@@ -7,127 +7,129 @@ export default class Note {
* @param {Object} note * @param {Object} note
*/ */
constructor(notes, note) { constructor(notes, note) {
this.note = note; this._note = note;
this.notes = notes; this._notes = notes;
} }
get data() { get data() {
return this.note; return this._note;
} }
get headline() { get headline() {
return this.note.headline; return this._note.headline;
} }
get title() { get title() {
return this.note.title; return this._note.title;
} }
get tags() { get tags() {
return this.note.tags; return this._note.tags;
} }
get colors() { get colors() {
return this.note.colors; return this._note.colors;
} }
get id() { get id() {
return this.note.id; return this._note.id;
} }
get notebook() { get notebook() {
return this.note.notebook; return this._note.notebook;
} }
get text() { get text() {
return this.note.content.text; return this._note.content.text;
} }
delta() { delta() {
return this.notes.deltaStorage.read(this.note.id + "_delta"); return this._notes._deltaStorage.read(this._note.id + "_delta");
} }
color(color) { color(color) {
return addTag.call(this, color, "colorsCollection", "colors"); return addTag.call(this, color, "_colorsCollection", "colors");
} }
uncolor(color) { uncolor(color) {
return removeTag.call(this, color, "colorsCollection", "colors"); return removeTag.call(this, color, "_colorsCollection", "colors");
} }
tag(tag) { tag(tag) {
return addTag.call(this, tag, "tagsCollection", "tags"); return addTag.call(this, tag, "_tagsCollection", "tags");
} }
untag(tag) { untag(tag) {
return removeTag.call(this, tag, "tagsCollection", "tags"); return removeTag.call(this, tag, "_tagsCollection", "tags");
} }
async save() { _toggle(prop) {
await this.notes.add(this.note); return this._notes.add({ id: this._note.id, [prop]: !this._note[prop] });
return this;
}
toggle(prop) {
this.note[prop] = !this.note[prop];
return this.save();
} }
favorite() { favorite() {
return this.toggle("favorite"); return this._toggle("favorite");
} }
pin() { pin() {
return this.toggle("pinned"); return this._toggle("pinned");
} }
async lock(password) { async lock(password) {
let delta = await this.delta(); let delta = await this.delta();
if (delta) { if (delta) {
delta = await this.notes.collection.indexer.encrypt( delta = await this._notes._collection.indexer.encrypt(
password, password,
JSON.stringify(delta) JSON.stringify(delta)
); );
await this.notes.deltaStorage.write(this.note.content.delta, delta); await this._notes._deltaStorage.write(this._note.content.delta, delta);
} }
this.note.content = await this.notes.collection.indexer.encrypt( const note = { ...this._note };
note.content = await this._notes._collection.indexer.encrypt(
password, password,
JSON.stringify(this.note.content) JSON.stringify(this._note.content)
); );
this.note.locked = true; note.locked = true;
return await this.notes.collection.addItem(this.note); return await this._notes._collection.addItem(note);
} }
async unlock(password, perm = false) { async unlock(password, perm = false) {
let decrypted = JSON.parse( let decrypted = JSON.parse(
await this.notes.collection.indexer.decrypt(password, this.note.content) await this._notes._collection.indexer.decrypt(
password,
this._note.content
)
); );
let delta = JSON.parse( let delta = JSON.parse(
await this.notes.collection.indexer.decrypt(password, await this.delta()) await this._notes._collection.indexer.decrypt(
password,
await this.delta()
)
); );
if (perm) { if (perm) {
this.note.locked = false; const note = { ...this._note, locked: false, content: decrypted };
this.note.content = decrypted; note.locked = false;
await this.notes.collection.addItem(this.note); note.content = decrypted;
await this.notes.deltaStorage.write(this.note.content.delta, delta); await this._notes._collection.addItem(note);
await this._notes._deltaStorage.write(note.content.delta, delta);
} }
return { return {
...this.note, ...this._note,
content: { ...decrypted, delta } content: { ...decrypted, delta }
}; };
} }
} }
async function addTag(tag, collection, array) { async function addTag(tag, collection, array) {
if (this.note[array].indexOf(tag) > -1) if (this._note[array].indexOf(tag) > -1)
throw new Error("Cannot add a duplicate tag."); throw new Error("Cannot add a duplicate tag.");
this.note[array].push(tag); this._note[array].push(tag);
await this.notes[collection].add(tag); await this._notes[collection].add(tag);
await this.notes.collection.addItem(this.note); await this._notes._collection.addItem(this._note);
} }
async function removeTag(tag, collection, array) { async function removeTag(tag, collection, array) {
if (this.note[array].indexOf(tag) <= -1) if (this._note[array].indexOf(tag) <= -1)
throw new Error("This note is not tagged by the specified tag."); throw new Error("This note is not tagged by the specified tag.");
this.note[array].splice(this.note[array].indexOf(tag), 1); this._note[array].splice(this._note[array].indexOf(tag), 1);
await this.notes[collection].remove(tag); await this._notes[collection].remove(tag);
await this.notes.collection.addItem(this.note); await this._notes._collection.addItem(this._note);
} }

View File

@@ -8,34 +8,34 @@ export default class Notebook {
* @param {Object} notebook * @param {Object} notebook
*/ */
constructor(notebooks, notebook) { constructor(notebooks, notebook) {
this.notebook = notebook; this._notebook = notebook;
this.notebooks = notebooks; this._notebooks = notebooks;
} }
get title() { get title() {
return this.notebook.title; return this._notebook.title;
} }
get data() { get data() {
return this.notebook; return this._notebook;
} }
get topics() { get topics() {
return new Topics(this.notebooks, this.notebooks.notes, this.notebook.id); return new Topics(this._notebooks, this._notebook.id);
} }
toggle(prop) { _toggle(prop) {
return this.notebooks.add({ return this._notebooks.add({
id: this.notebook.id, id: this._notebook.id,
[prop]: !this.notebook[prop] [prop]: !this._notebook[prop]
}); });
} }
pin() { pin() {
return this.toggle("pinned"); return this._toggle("pinned");
} }
favorite() { favorite() {
return this.toggle("favorite"); return this._toggle("favorite");
} }
} }

View File

@@ -7,72 +7,82 @@ export default class Topic {
* @param {Object} topic * @param {Object} topic
*/ */
constructor(topics, topic) { constructor(topics, topic) {
this.topic = topic; this._topic = topic;
this.topics = topics; this._topics = topics;
this.transactionOpen = false; this._transactionOpen = false;
}
get totalNotes() {
return this._topic.totalNotes;
} }
transaction(ops, saveAfter = true) { transaction(ops, saveAfter = true) {
this.transactionOpen = true; this._transactionOpen = true;
ops().then(() => { ops().then(() => {
this.transactionOpen = false; this._transactionOpen = false;
}); });
if (!saveAfter) return this; if (!saveAfter) return this;
return this.save(); return this._save();
} }
has(noteId) { has(noteId) {
return this.topic.notes.findIndex(n => n === noteId) > -1; return this._topic.notes.findIndex(n => n === noteId) > -1;
} }
async add(...noteIds) { async add(...noteIds) {
const topic = { ...this._topic };
for (let noteId of noteIds) { for (let noteId of noteIds) {
let note = this.topics.notes.note(noteId); let note = this._topics._notebooks._notes.note(noteId);
if (this.has(noteId) || !note) return this; if (this.has(noteId) || !note) continue;
topic.notes.push(noteId);
this.topic.notes.push(noteId);
if (note.notebook && note.notebook.id && note.notebook.topic) { if (note.notebook && note.notebook.id && note.notebook.topic) {
if ( if (
note.notebook.id === this.topics.notebookId && note.notebook.id === this._topics.notebookId &&
note.notebook.topic === this.topic.title note.notebook.topic === topic.title
) )
return this; return this;
await this.topics.notebooks await this._topics._notebooks
.topics(note.notebook.id) .topics(note.notebook.id)
.topic(note.notebook.topic) .topic(note.notebook.topic)
.delete(note.id); .delete(note.id);
} }
await this.topics.notes.add({ await this._topics._notebooks._notes.add({
id: noteId, id: noteId,
notebook: { id: this.topics.notebookId, topic: this.topic.title } notebook: { id: this._topics._notebookId, topic: topic.title }
}); });
topic.totalNotes++;
} }
this.topic.totalNotes++; return await this._save(topic);
return await this.save();
} }
async delete(...noteIds) { async delete(...noteIds) {
const topic = { ...this._topic };
for (let noteId of noteIds) { for (let noteId of noteIds) {
if (!this.has(noteId)) return this; if (!this.has(noteId)) return this;
let index = this.topic.notes.findIndex(n => n === noteId); let index = topic.notes.findIndex(n => n === noteId);
this.topic.notes.splice(index, 1); topic.notes.splice(index, 1);
await this.topics.notes.add({ await this._topics._notebooks._notes.add({
id: noteId, id: noteId,
notebook: {} notebook: {}
}); });
topic.totalNotes--;
} }
this.topic.totalNotes--; return await this._save(topic);
return await this.save();
} }
async save() { async _save(topic) {
if (this.transactionOpen) return this; if (this._transactionOpen) return this;
await this.topics.add(this.topic); await this._topics.add(topic);
return this; return this;
} }
get all() { get all() {
return this.topic.notes.map(note => this.topics.notes.note(note).note); return this._topic.notes
.map(note => {
let fullNote = this._topics._notebooks._notes.note(note);
if (fullNote) return fullNote.data;
})
.filter(v => v);
} }
} }