diff --git a/apps/web/src/components/note/index.tsx b/apps/web/src/components/note/index.tsx index ef56fe7e3..4ac92501e 100644 --- a/apps/web/src/components/note/index.tsx +++ b/apps/web/src/components/note/index.tsx @@ -587,7 +587,6 @@ function colorsToMenuItems( } function notebooksMenuItems(ids: string[]): MenuItem[] { - console.log("NOTE IDS", ids); return [ { type: "button", @@ -601,26 +600,53 @@ function notebooksMenuItems(ids: string[]): MenuItem[] { key: "notebooks-lazy-loader", async items() { const notebooks: Map = new Map(); - for (const id of ids) { - const linkedNotebooks = await db.relations - .to({ id, type: "note" }, "notebook") - .resolve(); - linkedNotebooks.forEach((nb) => notebooks.set(nb.id, nb)); + const notebookShortcuts: Map = new Map(); + + const linkedNotebooks = await db.relations + .to({ ids, type: "note" }, "notebook") + .resolve(); + linkedNotebooks.forEach((nb) => notebooks.set(nb.id, nb)); + + for (const notebook of await db.shortcuts.resolved("notebooks")) { + if (notebooks.has(notebook.id)) continue; + notebookShortcuts.set(notebook.id, notebook); + } + + const menuItems: MenuItem[] = []; + if (notebooks.size > 0) + menuItems.push( + { + type: "button", + key: "remove-from-all-notebooks", + title: "Unlink from all", + icon: RemoveShortcutLink.path, + onClick: async () => { + await db.notes.removeFromAllNotebooks(...ids); + store.refresh(); + } + }, + { key: "sep", type: "separator" } + ); + + if (notebookShortcuts.size > 0) { + menuItems.push({ key: "sep3", type: "separator" }); + notebookShortcuts.forEach((notebook) => { + menuItems.push({ + type: "button", + key: notebook.id, + title: notebook.title, + icon: Notebook.path, + isChecked: false, + onClick: async () => { + await db.notes.addToNotebook(notebook.id, ...ids); + store.refresh(); + } + }); + }); + + if (notebooks.size > 0) + menuItems.push({ key: "sep2", type: "separator" }); } - if (notebooks.size <= 0) return []; - const menuItems: MenuItem[] = [ - { - type: "button", - key: "remove-from-all-notebooks", - title: "Unlink from all", - icon: RemoveShortcutLink.path, - onClick: async () => { - await db.notes.removeFromAllNotebooks(...ids); - store.refresh(); - } - }, - { key: "sep", type: "separator" } - ]; notebooks.forEach((notebook) => { menuItems.push({ @@ -629,7 +655,6 @@ function notebooksMenuItems(ids: string[]): MenuItem[] { title: notebook.title, icon: Notebook.path, isChecked: true, - tooltip: "Click to remove from this notebook", onClick: async () => { await db.notes.removeFromNotebook(notebook.id, ...ids); store.refresh(); @@ -656,30 +681,60 @@ function tagsMenuItems(ids: string[]): MenuItem[] { key: "tags-lazy-loader", async items() { const tags: Map = new Map(); - for (const id of ids) { - const linkedTags = await db.relations - .to({ id, type: "note" }, "tag") - .resolve(); - linkedTags.forEach((tag) => tags.set(tag.id, tag)); + const tagShortcuts: Map = new Map(); + + const linkedTags = await db.relations + .to({ ids, type: "note" }, "tag") + .resolve(); + linkedTags.forEach((tag) => tags.set(tag.id, tag)); + + for (const tag of await db.shortcuts.resolved("tags")) { + if (tags.has(tag.id)) continue; + tagShortcuts.set(tag.id, tag); } - if (tags.size <= 0) return []; - const menuItems: MenuItem[] = [ - { - type: "button", - key: "remove-from-all-tags", - title: "Remove from all", - icon: RemoveShortcutLink.path, - onClick: async () => { - for (const id of ids) { - await db.relations.to({ id, type: "note" }, "tag").unlink(); + + const menuItems: MenuItem[] = []; + if (tags.size > 0) + menuItems.push( + { + type: "button", + key: "remove-from-all-tags", + title: "Remove from all", + icon: RemoveShortcutLink.path, + onClick: async () => { + for (const id of ids) { + await db.relations.to({ id, type: "note" }, "tag").unlink(); + } + tagStore.get().refresh(); + await editorStore.get().refreshTags(); + await store.get().refresh(); } - tagStore.get().refresh(); - await editorStore.get().refreshTags(); - await store.get().refresh(); - } - }, - { key: "sep", type: "separator" } - ]; + }, + { key: "sep", type: "separator" } + ); + + if (tagShortcuts.size > 0) { + menuItems.push({ key: "sep3", type: "separator" }); + tagShortcuts.forEach((tag) => { + menuItems.push({ + type: "button", + key: tag.id, + title: tag.title, + icon: TagIcon.path, + isChecked: false, + onClick: async () => { + for (const id of ids) { + await db.relations.add(tag, { id, type: "note" }); + } + await tagStore.get().refresh(); + await editorStore.get().refreshTags(); + await store.get().refresh(); + } + }); + }); + + if (tags.size > 0) menuItems.push({ key: "sep2", type: "separator" }); + } tags.forEach((tag) => { menuItems.push({ @@ -688,12 +743,11 @@ function tagsMenuItems(ids: string[]): MenuItem[] { title: tag.title, icon: TagIcon.path, isChecked: true, - tooltip: "Click to remove from this tag", onClick: async () => { for (const id of ids) { await db.relations.unlink(tag, { id, type: "note" }); } - tagStore.get().refresh(); + await tagStore.get().refresh(); await editorStore.get().refreshTags(); await store.get().refresh(); } diff --git a/packages/core/src/collections/shortcuts.ts b/packages/core/src/collections/shortcuts.ts index 1f8356aa4..cd8e13082 100644 --- a/packages/core/src/collections/shortcuts.ts +++ b/packages/core/src/collections/shortcuts.ts @@ -19,9 +19,16 @@ along with this program. If not, see . import Database from "../api"; import { SQLCachedCollection } from "../database/sql-cached-collection"; -import { Shortcut } from "../types"; +import { Notebook, Shortcut, Tag } from "../types"; import { ICollection } from "./collection"; +type ResolveTypeToItem = + T extends "tags" + ? Tag[] + : T extends "notebooks" + ? Notebook[] + : (Tag | Notebook)[]; + const ALLOWED_SHORTCUT_TYPES = ["notebook", "topic", "tag"]; export class Shortcuts implements ICollection { name = "shortcuts"; @@ -88,19 +95,29 @@ export class Shortcuts implements ICollection { return this.collection.items(); } - async resolved() { + async resolved( + type: T = "all" as T + ): Promise> { const tagIds: string[] = []; const notebookIds: string[] = []; for (const shortcut of this.all) { - if (shortcut.itemType === "notebook") notebookIds.push(shortcut.itemId); - else if (shortcut.itemType === "tag") tagIds.push(shortcut.itemId); + if ( + (type === "all" || type === "notebooks") && + shortcut.itemType === "notebook" + ) + notebookIds.push(shortcut.itemId); + else if ( + (type === "all" || type === "tags") && + shortcut.itemType === "tag" + ) + tagIds.push(shortcut.itemId); } return [ ...(notebookIds.length > 0 ? await this.db.notebooks.all.items(notebookIds) : []), ...(tagIds.length > 0 ? await this.db.tags.all.items(tagIds) : []) - ]; + ] as ResolveTypeToItem; } exists(id: string) {