diff --git a/apps/client/src/services/note_types.ts b/apps/client/src/services/note_types.ts index b9a9fa3ef..dd4137ee9 100644 --- a/apps/client/src/services/note_types.ts +++ b/apps/client/src/services/note_types.ts @@ -1,43 +1,65 @@ -import server from "./server.js"; -import froca from "./froca.js"; import { t } from "./i18n.js"; -import type { MenuItem, MenuItemBadge } from "../menus/context_menu.js"; +import froca from "./froca.js"; +import server from "./server.js"; +import type { MenuCommandItem, MenuItem, MenuItemBadge } from "../menus/context_menu.js"; +import type { NoteType } from "../entities/fnote.js"; import type { TreeCommandNames } from "../menus/tree_context_menu.js"; +export interface NoteTypeMapping { + type: NoteType; + mime?: string; + title: string; + icon?: string; + /** Indicates that this note type is part of a beta feature. */ + isBeta?: boolean; + /** Indicates that this note type cannot be created by the user. */ + reserved?: boolean; + /** Indicates that once a note of this type is created, its type can no longer be changed. */ + static?: boolean; +} + +export const NOTE_TYPES: NoteTypeMapping[] = [ + // The suggested note type ordering method: insert the item into the corresponding group, + // then ensure the items within the group are ordered alphabetically. + + // The default note type (always the first item) + { type: "text", mime: "text/html", title: t("note_types.text"), icon: "bx-note" }, + + // Text notes group + { type: "book", mime: "", title: t("note_types.book"), icon: "bx-book" }, + + // Graphic notes + { type: "canvas", mime: "application/json", title: t("note_types.canvas"), icon: "bx-pen" }, + { type: "mermaid", mime: "text/mermaid", title: t("note_types.mermaid-diagram"), icon: "bx-selection" }, + + // Map notes + { type: "geoMap", mime: "application/json", title: t("note_types.geo-map"), icon: "bx-map-alt", isBeta: true }, + { type: "mindMap", mime: "application/json", title: t("note_types.mind-map"), icon: "bx-sitemap" }, + { type: "noteMap", mime: "", title: t("note_types.note-map"), icon: "bxs-network-chart", static: true }, + { type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), icon: "bxs-network-chart" }, + + // Misc note types + { type: "render", mime: "", title: t("note_types.render-note"), icon: "bx-extension" }, + { type: "search", title: t("note_types.saved-search"), icon: "bx-file-find", static: true }, + { type: "webView", mime: "", title: t("note_types.web-view"), icon: "bx-globe-alt" }, + + // Code notes + { type: "code", mime: "text/plain", title: t("note_types.code"), icon: "bx-code" }, + + // Reserved types (cannot be created by the user) + { type: "contentWidget", mime: "", title: t("note_types.widget"), reserved: true }, + { type: "doc", mime: "", title: t("note_types.doc"), reserved: true }, + { type: "file", title: t("note_types.file"), reserved: true }, + { type: "image", title: t("note_types.image"), reserved: true }, + { type: "launcher", mime: "", title: t("note_types.launcher"), reserved: true }, + { type: "aiChat", mime: "application/json", title: t("note_types.ai-chat"), reserved: true } +]; + const SEPARATOR = { title: "----" }; -const BETA_BADGE: MenuItemBadge = {title: t("note_types.beta-feature")}; async function getNoteTypeItems(command?: TreeCommandNames) { const items: MenuItem[] = [ - // The suggested note type ordering method: insert the item into the corresponding group, - // then ensure the items within the group are ordered alphabetically. - // Please keep the order synced with the listing found also in aps/client/src/widgets/note_types.ts. - - // The default note type (always the first item) - { title: t("note_types.text"), command, type: "text", uiIcon: "bx bx-note" }, - - // Text notes group - { title: t("note_types.book"), command, type: "book", uiIcon: "bx bx-book" }, - - // Graphic notes - { title: t("note_types.canvas"), command, type: "canvas", uiIcon: "bx bx-pen" }, - { title: t("note_types.mermaid-diagram"), command, type: "mermaid", uiIcon: "bx bx-selection" }, - - // Map notes - { title: t("note_types.geo-map"), command, type: "geoMap", uiIcon: "bx bx-map-alt" }, - { title: t("note_types.mind-map"), command, type: "mindMap", uiIcon: "bx bx-sitemap", badges: [BETA_BADGE]}, - { title: t("note_types.note-map"), command, type: "noteMap", uiIcon: "bx bxs-network-chart" }, - { title: t("note_types.relation-map"), command, type: "relationMap", uiIcon: "bx bxs-network-chart" }, - - // Misc note types - { title: t("note_types.render-note"), command, type: "render", uiIcon: "bx bx-extension" }, - { title: t("note_types.saved-search"), command, type: "search", uiIcon: "bx bx-file-find" }, - { title: t("note_types.web-view"), command, type: "webView", uiIcon: "bx bx-globe-alt" }, - - // Code notes - { title: t("note_types.code"), command, type: "code", uiIcon: "bx bx-code" }, - - // Templates + ...getBlankNoteTypes(command), ...await getBuiltInTemplates(command), ...await getUserTemplates(command) ]; @@ -45,6 +67,24 @@ async function getNoteTypeItems(command?: TreeCommandNames) { return items; } +function getBlankNoteTypes(command): MenuItem[] { + return NOTE_TYPES.filter((nt) => !nt.reserved).map((nt) => { + const menuItem: MenuCommandItem = { + title: nt.title, + command, + type: nt.type, + uiIcon: "bx " + nt.icon, + badges: [] + } + + if (nt.isBeta) { + menuItem.badges?.push({title: t("note_types.beta-feature")}); + } + + return menuItem; + }); +} + async function getUserTemplates(command?: TreeCommandNames) { const templateNoteIds = await server.get("search-templates"); const templateNotes = await froca.getNotes(templateNoteIds); diff --git a/apps/client/src/widgets/note_type.ts b/apps/client/src/widgets/note_type.ts index 198798606..04602813d 100644 --- a/apps/client/src/widgets/note_type.ts +++ b/apps/client/src/widgets/note_type.ts @@ -1,60 +1,15 @@ -import server from "../services/server.js"; +import { Dropdown } from "bootstrap"; +import { NOTE_TYPES } from "../services/note_types.js"; +import { t } from "../services/i18n.js"; +import dialogService from "../services/dialog.js"; import mimeTypesService from "../services/mime_types.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; -import dialogService from "../services/dialog.js"; -import { t } from "../services/i18n.js"; -import type FNote from "../entities/fnote.js"; -import type { NoteType } from "../entities/fnote.js"; +import server from "../services/server.js"; import type { EventData } from "../components/app_context.js"; -import { Dropdown } from "bootstrap"; +import type { NoteType } from "../entities/fnote.js"; +import type FNote from "../entities/fnote.js"; -interface NoteTypeMapping { - type: NoteType; - mime?: string; - title: string; - isBeta?: boolean; - selectable: boolean; -} - -const NOTE_TYPES: NoteTypeMapping[] = [ - // The suggested note type ordering method: insert the item into the corresponding group, - // then ensure the items within the group are ordered alphabetically. - // Please keep the order synced with the listing found also in apps/client/src/services/note_types.ts. - - // The default note type (always the first item) - { type: "text", mime: "text/html", title: t("note_types.text"), selectable: true }, - - // Text notes group - { type: "book", mime: "", title: t("note_types.book"), selectable: true }, - - // Graphic notes - { type: "canvas", mime: "application/json", title: t("note_types.canvas"), selectable: true }, - { type: "mermaid", mime: "text/mermaid", title: t("note_types.mermaid-diagram"), selectable: true }, - - // Map notes - { type: "geoMap", mime: "application/json", title: t("note_types.geo-map"), isBeta: true, selectable: true }, - { type: "mindMap", mime: "application/json", title: t("note_types.mind-map"), selectable: true }, - { type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), selectable: true }, - - // Misc note types - { type: "render", mime: "", title: t("note_types.render-note"), selectable: true }, - { type: "webView", mime: "", title: t("note_types.web-view"), selectable: true }, - - // Code notes - { type: "code", mime: "text/plain", title: t("note_types.code"), selectable: true }, - - // Reserved types (cannot be created by the user) - { type: "contentWidget", mime: "", title: t("note_types.widget"), selectable: false }, - { type: "doc", mime: "", title: t("note_types.doc"), selectable: false }, - { type: "file", title: t("note_types.file"), selectable: false }, - { type: "image", title: t("note_types.image"), selectable: false }, - { type: "launcher", mime: "", title: t("note_types.launcher"), selectable: false }, - { type: "noteMap", mime: "", title: t("note_types.note-map"), selectable: false }, - { type: "search", title: t("note_types.saved-search"), selectable: false }, - { type: "aiChat", mime: "application/json", title: t("note_types.ai-chat"), selectable: false } -]; - -const NOT_SELECTABLE_NOTE_TYPES = NOTE_TYPES.filter((nt) => !nt.selectable).map((nt) => nt.type); +const NOT_SELECTABLE_NOTE_TYPES = NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type); const TPL = /*html*/`