diff --git a/packages/core/__tests__/tags.test.js b/packages/core/__tests__/tags.test.js index 9d9988875..815ed721c 100644 --- a/packages/core/__tests__/tags.test.js +++ b/packages/core/__tests__/tags.test.js @@ -78,4 +78,14 @@ describe.each([ tag = db[collection].tag(tag.id); expect(tag.alias).toBe(value + "-new"); })); + + test(`remove a ${action}`, () => + noteTest().then(async ({ db, id }) => { + let note = db.notes.note(id); + await note[action](value); + + let tag = db[collection].tag(value); + await db[collection].remove(tag.id); + expect(db[collection].tag(value)).toBeUndefined(); + })); }); diff --git a/packages/core/collections/notes.js b/packages/core/collections/notes.js index 20daff80a..89d030fd1 100644 --- a/packages/core/collections/notes.js +++ b/packages/core/collections/notes.js @@ -34,7 +34,7 @@ export default class Notes extends Collection { } if (!!oldNote.tags) { for (let tag of oldNote.tags) { - await this._db.tags.remove(tag, id); + await this._db.tags.untag(tag, id); } } } @@ -285,7 +285,7 @@ export default class Notes extends Collection { } } for (let tag of item.tags) { - await this._db.tags.remove(tag, id); + await this._db.tags.untag(tag, id); } if (item.data.color) { await this._db.colors.remove(item.data.color, id); diff --git a/packages/core/collections/tags.js b/packages/core/collections/tags.js index 87f967b8a..884ae0a0e 100644 --- a/packages/core/collections/tags.js +++ b/packages/core/collections/tags.js @@ -1,7 +1,8 @@ import Collection from "./collection"; import { qclone } from "qclone"; import { makeId } from "../utils/id"; -import { deleteItem } from "../utils/array"; +import { deleteItem, deleteItems } from "../utils/array"; +import setManipulator from "../utils/set"; export default class Tags extends Collection { tag(id) { @@ -9,31 +10,29 @@ export default class Tags extends Collection { return tagItem; } - async add(tagId, noteId) { - if (tagId.id || tagId.title) { - tagId = tagId.id; - } - - if (!tagId || !noteId) { - console.error("tagId and noteId cannot be falsy."); + async add(tagId, ...noteIds) { + if (!tagId) { + console.error("tagId cannot be undefined."); return; } - let tag = this.all.find((t) => t.id === tagId || t.title === tagId) || { + if (typeof tagId === "object") { + tagId = tagId.id; + } + + let tag = this.tag(tagId) || { title: tagId, }; let id = tag.id || makeId(tag.title); let notes = tag.noteIds || []; - if (notes.find((id) => id === noteId)) return id; - tag = { type: "tag", alias: tag.title, id, title: tag.title, - noteIds: [...notes, noteId], + noteIds: setManipulator.union(notes, noteIds), }; await this._collection.addItem(tag); @@ -41,9 +40,9 @@ export default class Tags extends Collection { } async rename(tagId, newName) { - let tag = this.all.find((t) => t.id === tagId); + let tag = this.tag(tagId); if (!tag) { - console.error(`No such tag found. Tag id:`, tagId); + console.error(`No tag found. Tag id:`, tagId); return; } tag.alias = newName; @@ -58,26 +57,29 @@ export default class Tags extends Collection { return this._collection.getItems(); } - async remove(tagTitle, noteId) { - if (!tagTitle || !noteId) { - console.error( - "tag title and noteId cannot be undefined.", - tagTitle, - noteId - ); - return; - } - - let tag = this.all.find((t) => t.title === tagTitle || t.id === tagTitle); + async remove(tagId) { + let tag = this.tag(tagId); if (!tag) { - console.error(`No such tag found. Tag title:`, tagTitle); + console.error(`No tag found. Tag id:`, tagId); + return; + } + for (let noteId of tag.noteIds) { + const note = this._db.notes.note(noteId); + if (!note) continue; + await note.untag(tagId); + } + await this._db.settings.unpin(tagId); + await this._collection.deleteItem(tagId); + } + + async untag(tagId, ...noteIds) { + let tag = this.tag(tagId); + if (!tag) { + console.error(`No such tag found. Tag title:`, tagId); return; } - tag = qclone(tag); - - if (!deleteItem(tag.noteIds, noteId)) - console.error(`No such note exists in tag.`, tag.id, noteId); + deleteItems(tag.noteIds, ...noteIds); if (tag.noteIds.length > 0) await this._collection.addItem(tag); else { diff --git a/packages/core/common.js b/packages/core/common.js index 6ffe88418..aa0ddc057 100644 --- a/packages/core/common.js +++ b/packages/core/common.js @@ -3,6 +3,8 @@ import EventManager from "./utils/event-manager"; export const EV = new EventManager(); export async function sendCheckUserStatusEvent(type) { + if (process.env.NODE_ENV === "testing") return true; + const results = await EV.publishWithResult(EVENTS.userCheckStatus, type); if (typeof results === "boolean") return results; return results.some((r) => r.type === type && r.result === true); diff --git a/packages/core/jest.setup.js b/packages/core/jest.setup.js index 03b1e48eb..8c8c057d1 100644 --- a/packages/core/jest.setup.js +++ b/packages/core/jest.setup.js @@ -1,6 +1,8 @@ var nodeCrypto = require("crypto"); var jsdom = require("jsdom"); +process.env.NODE_ENV = "testing"; + const dom = new jsdom.JSDOM("", {}); global.window = dom.window; global.document = dom.window.document; diff --git a/packages/core/models/note.js b/packages/core/models/note.js index 0eb3cc50f..f7ba24c1c 100644 --- a/packages/core/models/note.js +++ b/packages/core/models/note.js @@ -101,7 +101,7 @@ export default class Note { async uncolor() { if (!this._note.color) return; - await this._db.colors.remove(this._note.color, this._note.id); + await this._db.colors.untag(this._note.color, this._note.id); await this._db.notes._collection.addItem({ ...this._note, color: undefined, @@ -136,7 +136,8 @@ export default class Note { async function addTag(tag) { if (this._note.tags.indexOf(tag) > -1) - throw new Error("Cannot add a duplicate tag."); + return console.error("Cannot add a duplicate tag."); + let tagItem = await this._db.tags.add(tag, this._note.id); let arr = [...this._note.tags, tagItem.title]; const note = { ...this._note, tags: arr }; @@ -145,10 +146,11 @@ async function addTag(tag) { async function removeTag(tag) { if (this._note.tags.indexOf(tag) <= -1) - throw new Error("This note is not tagged by the specified tag."); + return console.error("This note is not tagged by the specified tag."); + let arr = [...this._note.tags]; arr.splice(arr.indexOf(tag), 1); const note = { ...this._note, tags: arr }; - await this._db.tags.remove(tag, note.id); + await this._db.tags.untag(tag, note.id); await this._db.notes._collection.addItem(note); } diff --git a/packages/core/utils/array.js b/packages/core/utils/array.js index 0ab1a473c..79d8165b5 100644 --- a/packages/core/utils/array.js +++ b/packages/core/utils/array.js @@ -6,6 +6,12 @@ export function deleteItem(array, item) { return deleteAtIndex(array, array.indexOf(item)); } +export function deleteItems(array, ...items) { + for (let item of items) { + deleteItem(array, item); + } +} + export function findById(array, id) { return array.find((item) => item.id === id); }