feat: implement deletion of note, topic and notebook

This commit is contained in:
thecodrr
2020-02-05 01:12:36 +05:00
parent d1f7b87f19
commit 28583d7de0
6 changed files with 97 additions and 55 deletions

View File

@@ -1,4 +1,9 @@
import { StorageInterface, notebookTest, TEST_NOTEBOOK } from "./utils"; import {
StorageInterface,
notebookTest,
TEST_NOTEBOOK,
TEST_NOTE
} from "./utils";
beforeEach(async () => { beforeEach(async () => {
StorageInterface.clear(); StorageInterface.clear();
@@ -54,3 +59,17 @@ test("unfavorite a notebook", () =>
let notebook = db.notebooks.get(id); let notebook = db.notebooks.get(id);
expect(notebook.favorite).toBe(false); expect(notebook.favorite).toBe(false);
})); }));
test("delete a notebook", () =>
notebookTest().then(async ({ db, id }) => {
let noteId = await db.notes.add(TEST_NOTE);
await db.notebooks
.topics(id)
.topic("General")
.add(noteId);
let note = await db.notes.get(noteId);
expect(note.notebook.id).toBe(id);
await db.notebooks.delete(id);
note = await db.notes.get(noteId);
expect(note.notebook.id).toBeUndefined();
}));

View File

@@ -4,7 +4,8 @@ import {
noteTest, noteTest,
groupedTest, groupedTest,
LONG_TEXT, LONG_TEXT,
TEST_NOTE TEST_NOTE,
TEST_NOTEBOOK
} from "./utils"; } from "./utils";
beforeEach(async () => { beforeEach(async () => {
@@ -23,7 +24,6 @@ test("add invalid note", () =>
test("add note", () => test("add note", () =>
noteTest().then(async ({ db, id }) => { noteTest().then(async ({ db, id }) => {
expect(id).toBeDefined();
let note = db.notes.get(id); let note = db.notes.get(id);
expect(note).toBeDefined(); expect(note).toBeDefined();
expect(note.content.text).toStrictEqual(TEST_NOTE.content.text); expect(note.content.text).toStrictEqual(TEST_NOTE.content.text);
@@ -31,17 +31,22 @@ test("add note", () =>
test("get delta of note", () => test("get delta of note", () =>
noteTest().then(async ({ db, id }) => { noteTest().then(async ({ db, id }) => {
expect(id).toBeDefined();
let delta = await db.notes.delta(id); let delta = await db.notes.delta(id);
expect(delta).toStrictEqual(TEST_NOTE.content.delta); expect(delta).toStrictEqual(TEST_NOTE.content.delta);
})); }));
test("delete note", () => test("delete note", () =>
noteTest().then(async ({ db, id }) => { noteTest().then(async ({ db, id }) => {
expect(id).toBeDefined(); let notebookId = await db.notebooks.add(TEST_NOTEBOOK);
let topic = await db.notebooks
.topics(notebookId)
.topic("General")
.add(id);
expect(topic.all.findIndex(v => v.id === id)).toBeGreaterThan(-1);
await db.notes.delete(id); await db.notes.delete(id);
let note = db.notes.get(id); let note = db.notes.get(id);
expect(note).toBeUndefined(); expect(note).toBeUndefined();
expect(topic.all.findIndex(v => v.id === id)).toBe(-1);
})); }));
test("get all notes", () => test("get all notes", () =>

View File

@@ -86,7 +86,16 @@ export default class Notebooks {
return this.collection.getItem(id); return this.collection.getItem(id);
} }
delete(...ids) {} async delete(...ids) {
for (let id of ids) {
let notebook = this.get(id);
if (!notebook) continue;
await this.collection.transaction(() =>
this.topics(id).delete(...notebook.topics)
);
await this.collection.removeItem(id);
}
}
filter(query) { filter(query) {
if (!query) return []; if (!query) return [];

View File

@@ -161,24 +161,17 @@ export default class Notes {
} }
async delete(...ids) { async delete(...ids) {
if (!ids || ids.length <= 0) {
return false;
}
for (let id of ids) { for (let id of ids) {
let item = this.get(id); let item = this.get(id);
if (!id) continue; if (!id) continue;
/* TODO if ( if (item.notebook && item.notebook.id && item.notebook.topic) {
item.notebook.hasOwnProperty("topic") && await this.collection.transaction(() =>
!(await this.deleteNoteFromTopic( this.notebooks
item.notebook.id, .topics(item.notebook.id)
item.notebook.topic, .topic(item.notebook.topic)
item.dateCreated .delete(id)
)) );
) {
continue;
} }
*/
for (let tag of item.tags) { for (let tag of item.tags) {
await this.tagsCollection.remove(tag); await this.tagsCollection.remove(tag);
} }
@@ -219,11 +212,7 @@ export default class Notes {
let topic = this.notebooks.topics(to.id).topic(to.topic); let topic = this.notebooks.topics(to.id).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 () => {
for (let id of noteIds) { await topic.add(...noteIds);
let note = this.get(id);
if (!note) continue;
await topic.add(id);
}
}); });
} }

View File

@@ -42,6 +42,9 @@ export default class Topics {
t => t.title === topic.title || topic t => t.title === topic.title || topic
); );
if (index <= -1) continue; if (index <= -1) continue;
topic = notebook.topics[index];
let t = this.topic(topic);
await t.transaction(() => t.delete(...topic.notes), false);
notebook.topics.splice(index, 1); notebook.topics.splice(index, 1);
} }
await this.notebooks.add({ await this.notebooks.add({
@@ -63,18 +66,21 @@ class Topic {
this.transactionOpen = false; this.transactionOpen = false;
} }
transaction(ops) { transaction(ops, saveAfter = true) {
this.transactionOpen = true; this.transactionOpen = true;
return ops().then(() => { ops().then(() => {
this.transactionOpen = false; this.transactionOpen = false;
}); });
if (!saveAfter) return this;
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(noteId) { async add(...noteIds) {
for (let noteId of noteIds) {
let note = this.topics.notes.get(noteId); let note = this.topics.notes.get(noteId);
if (this.has(noteId) || !note) return this; if (this.has(noteId) || !note) return this;
@@ -91,16 +97,16 @@ class Topic {
.topic(note.notebook.topic) .topic(note.notebook.topic)
.delete(note.id); .delete(note.id);
} }
await this.topics.notes.add({ await this.topics.notes.add({
id: noteId, id: noteId,
notebook: { id: this.topics.notebookId, topic: this.topic.title } notebook: { id: this.topics.notebookId, topic: this.topic.title }
}); });
}
return await this.save(); return await this.save();
} }
async delete(noteId) { async delete(...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 = this.topic.notes.findIndex(n => n === noteId);
this.topic.notes.splice(index, 1); this.topic.notes.splice(index, 1);
@@ -108,6 +114,7 @@ class Topic {
id: noteId, id: noteId,
notebook: {} notebook: {}
}); });
}
return await this.save(); return await this.save();
} }

View File

@@ -4,6 +4,7 @@ export default class CachedCollection {
constructor(context, type) { constructor(context, type) {
this.map = new Map(); this.map = new Map();
this.indexer = new Indexer(context, type); this.indexer = new Indexer(context, type);
this.transactionOpen = false;
} }
async init() { async init() {
@@ -13,7 +14,17 @@ export default class CachedCollection {
} }
} }
/**
*
* @param {Promise} ops
*/
transaction(ops) {
this.transactionOpen = true;
return ops().then(() => Promise.resolve((this.transactionOpen = false)));
}
async addItem(item) { async addItem(item) {
if (this.transactionOpen) return;
if (!item.id) throw new Error("The item must contain the id field."); if (!item.id) throw new Error("The item must contain the id field.");
let exists = this.map.has(item.id); let exists = this.map.has(item.id);
@@ -24,6 +35,7 @@ export default class CachedCollection {
} }
async updateItem(item) { async updateItem(item) {
if (this.transactionOpen) return;
if (!item.id) throw new Error("The item must contain the id field."); if (!item.id) throw new Error("The item must contain the id field.");
this.map.set(item.id, item); this.map.set(item.id, item);
@@ -31,6 +43,7 @@ export default class CachedCollection {
} }
async removeItem(id) { async removeItem(id) {
if (this.transactionOpen) return;
if (this.map.delete(id)) { if (this.map.delete(id)) {
this.indexer.remove(id); this.indexer.remove(id);
await this.indexer.deindex(id); await this.indexer.deindex(id);