refactor(note_create): simplify type implementation and documentation

This commit is contained in:
Jakob Schlanstedt 2025-10-28 18:03:32 +01:00
parent bcb29d22f5
commit a5ef5eee2f
12 changed files with 135 additions and 160 deletions

View File

@ -11,7 +11,7 @@ import froca from "../services/froca.js";
import linkService from "../services/link.js"; import linkService from "../services/link.js";
import { t } from "../services/i18n.js"; import { t } from "../services/i18n.js";
import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons"; import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons";
import noteCreateService, { CreateNoteIntoInboxURLOpts, CreateNoteTarget } from "../services/note_create.js"; import noteCreateService, { CreateNoteIntoInboxOpts, CreateNoteTarget } from "../services/note_create.js";
export default class Entrypoints extends Component { export default class Entrypoints extends Component {
constructor() { constructor() {
@ -26,7 +26,7 @@ export default class Entrypoints extends Component {
async createNoteIntoInboxCommand() { async createNoteIntoInboxCommand() {
await noteCreateService.createNote( await noteCreateService.createNote(
{ target: CreateNoteTarget.IntoInbox } as CreateNoteIntoInboxURLOpts { target: CreateNoteTarget.IntoInbox } as CreateNoteIntoInboxOpts
); );
} }

View File

@ -1,5 +1,5 @@
import appContext, { type EventData } from "./app_context.js"; import appContext, { type EventData } from "./app_context.js";
import noteCreateService, { CreateNoteTarget, CreateNoteIntoURLOpts, CreateNoteAfterURLOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteTarget, CreateNoteIntoUrlOpts, CreateNoteAfterUrlOpts } from "../services/note_create.js";
import treeService from "../services/tree.js"; import treeService from "../services/tree.js";
import hoistedNoteService from "../services/hoisted_note.js"; import hoistedNoteService from "../services/hoisted_note.js";
import Component from "./component.js"; import Component from "./component.js";
@ -55,7 +55,7 @@ export default class MainTreeExecutors extends Component {
isProtected: activeNoteContext.note.isProtected, isProtected: activeNoteContext.note.isProtected,
saveSelection: false, saveSelection: false,
promptForType: false, promptForType: false,
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
} }
@ -84,7 +84,7 @@ export default class MainTreeExecutors extends Component {
targetBranchId: node.data.branchId, targetBranchId: node.data.branchId,
isProtected: isProtected, isProtected: isProtected,
saveSelection: false saveSelection: false
} as CreateNoteAfterURLOpts } as CreateNoteAfterUrlOpts
); );
} }
} }

View File

@ -8,7 +8,7 @@ import options from "../services/options.js";
import froca from "../services/froca.js"; import froca from "../services/froca.js";
import utils from "../services/utils.js"; import utils from "../services/utils.js";
import toastService from "../services/toast.js"; import toastService from "../services/toast.js";
import noteCreateService, { CreateNoteIntoURLOpts, CreateNoteTarget } from "../services/note_create.js"; import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteTarget } from "../services/note_create.js";
export default class RootCommandExecutor extends Component { export default class RootCommandExecutor extends Component {
editReadOnlyNoteCommand() { editReadOnlyNoteCommand() {
@ -249,7 +249,7 @@ export default class RootCommandExecutor extends Component {
messages: [], messages: [],
title: "New AI Chat" title: "New AI Chat"
}), }),
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
if (!result.note) { if (!result.note) {

View File

@ -2,7 +2,7 @@ import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
import treeService from "../services/tree.js"; import treeService from "../services/tree.js";
import froca from "../services/froca.js"; import froca from "../services/froca.js";
import clipboard from "../services/clipboard.js"; import clipboard from "../services/clipboard.js";
import noteCreateService, { CreateNoteAfterURLOpts, CreateNoteIntoURLOpts, CreateNoteTarget } from "../services/note_create.js"; import noteCreateService, { CreateNoteAfterUrlOpts, CreateNoteIntoUrlOpts, CreateNoteTarget } from "../services/note_create.js";
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js"; import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js"; import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js";
import noteTypesService from "../services/note_types.js"; import noteTypesService from "../services/note_types.js";
@ -293,7 +293,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: isProtected, isProtected: isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteAfterURLOpts } as CreateNoteAfterUrlOpts
); );
} else if (command === "insertChildNote") { } else if (command === "insertChildNote") {
const parentNotePath = treeService.getNotePath(this.node); const parentNotePath = treeService.getNotePath(this.node);
@ -306,7 +306,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: this.node.data.isProtected, isProtected: this.node.data.isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
} else if (command === "openNoteInSplit") { } else if (command === "openNoteInSplit") {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts(); const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();

View File

@ -1,6 +1,6 @@
import server from "./server.js"; import server from "./server.js";
import appContext from "../components/app_context.js"; import appContext from "../components/app_context.js";
import noteCreateService, { CreateNoteIntoURLOpts, CreateNoteTarget, CreateNoteIntoInboxURLOpts } from "./note_create.js"; import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteTarget, CreateNoteIntoInboxOpts } from "./note_create.js";
import froca from "./froca.js"; import froca from "./froca.js";
import { t } from "./i18n.js"; import { t } from "./i18n.js";
import commandRegistry from "./command_registry.js"; import commandRegistry from "./command_registry.js";
@ -487,7 +487,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: true, activate: true,
promptForType: true, promptForType: true,
} as CreateNoteIntoInboxURLOpts } as CreateNoteIntoInboxOpts
); );
if (!note) return; if (!note) return;
@ -507,7 +507,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoInboxURLOpts, } as CreateNoteIntoInboxOpts,
); );
if (!note) return; if (!note) return;
@ -528,7 +528,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: true, activate: true,
promptForType: true, promptForType: true,
} as CreateNoteIntoURLOpts, } as CreateNoteIntoUrlOpts,
); );
if (!note) return; if (!note) return;
@ -549,7 +549,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
if (!note) return; if (!note) return;

View File

@ -13,44 +13,56 @@ import type { CKTextEditor } from "@triliumnext/ckeditor5";
import dateNoteService from "../services/date_notes.js"; import dateNoteService from "../services/date_notes.js";
/** /**
* The `note_create` function can be called with multiple valid combinations * Defines the type hierarchy and rules for valid argument combinations
* of arguments. This type hierarchy defines and enforces which combinations * accepted by `note_create`.
* are valid at compile time.
* *
* The function overloads later in `note_create` correspond to these types, * ## Overview
* ensuring that each variant of note creation accepts only the correct * Each variant (e.g. `CreateNoteIntoUrlOpts`, `CreateNoteBeforeUrlOpts`, etc.)
* set of arguments. * extends `CreateNoteOpts` and enforces specific constraints to ensure only
* valid note creation options are allowed at compile time.
* *
* Theoretically: If type checking produces no errors, then the provided * ## Type Safety
* arguments represent a valid state assuming the types below are defined * The `PromptingRule` ensures that `promptForType` and `type` stay mutually
* correctly. Through the CurryHoward correspondence, this type system * exclusive (if prompting, `type` is undefined).
* effectively acts as a proof system: a successful type check serves as a
* compile-time proof that the arguments of `create_note` can only produce
* a valid state.
* *
* To align with its theoretical foundation in type theory (via the * The type system prevents invalid argument mixes by design successful type
* CurryHoward correspondence), `type` is used instead of `interface` * checks guarantee a valid state, following CurryHoward correspondence
* principles (types as proofs).
* *
* * Hierarchy of general to specific categories(hypernyms -> hyponyms): * ## Maintenance
* If adding or modifying `Opts`, ensure:
* - All valid combinations are represented (avoid *false negatives*).
* - No invalid ones slip through (avoid *false positives*).
* *
* * CreateNoteEntity * Hierarchy (general specific):
* | * - CreateNoteOpts
* \-- CreateNoteOpts * - CreateNoteAtUrlOpts
* | * - CreateNoteIntoUrlOpts
* +-- CreateNoteAtUrlOpts * - CreateNoteBeforeUrlOpts
* | +-- CreateNoteIntoURLOpts * - CreateNoteAfterUrlOpts
* | \-- CreateNoteSiblingURLOpts * - CreateNoteIntoInboxOpts
* | +-- CreateNoteBeforeURLOpts
* | \-- CreateNoteAfterURLOpts
* |
* \-- CreateNoteIntoInboxURLOpts
*/ */
/** /** enforces a truth rule:
* this is the shared basis for all types. Every other type is child (hyponym) * - If `promptForType` is true `type` must be undefined.
* of it (Its the domain hypernym). * - If `promptForType` is false `type` must be defined.
*/ */
type CreateNoteEntity = { type PromptingRule = {
promptForType: true;
type?: never;
} | {
promptForType?: false;
type: string;
};
/**
* Base type for all note creation options (domain hypernym).
* All specific note option types extend from this.
*
* Combine with `&` to ensure valid logical combinations.
*/
export type CreateNoteOpts = {
target: CreateNoteTarget; target: CreateNoteTarget;
isProtected?: boolean; isProtected?: boolean;
saveSelection?: boolean; saveSelection?: boolean;
@ -62,43 +74,30 @@ type CreateNoteEntity = {
activate?: boolean; activate?: boolean;
focus?: "title" | "content"; focus?: "title" | "content";
textEditor?: CKTextEditor; textEditor?: CKTextEditor;
} } & PromptingRule;
export type CreateNoteOpts =
| (CreateNoteEntity & {
promptForType: true;
type?: never;
})
| (CreateNoteEntity & {
promptForType?: false;
type?: string;
});
/* /*
* For creating a note in a specific path. At is the broader category (hypernym) * Defines options for creating a note at a specific path.
* of "into" and "as siblings". It is not exported because it only exists, to * Serves as a base (not exported) for "into", "before", and "after" variants,
* have its legal values propagated to its children (types inheriting from it). * sharing common URL-related fields.
*/ */
type CreateNoteAtUrlOpts = CreateNoteOpts & { type CreateNoteAtUrlOpts = CreateNoteOpts & {
// `Url` means either parentNotePath or parentNoteId. // `Url` may refer to either parentNotePath or parentNoteId.
// The vocabulary is inspired by its loose semantics of getNoteIdFromUrl. // The vocabulary is inspired by existing function getNoteIdFromUrl.
parentNoteUrl: string; parentNoteUrl: string;
/*
* targetBranchId disambiguates the position for cloned notes. This is a // Disambiguates the position for cloned notes.
* concern whenever we are given a note URL.
*/
targetBranchId: string; targetBranchId: string;
} }
export type CreateNoteIntoURLOpts = CreateNoteAtUrlOpts; export type CreateNoteIntoUrlOpts = CreateNoteAtUrlOpts;
export type CreateNoteBeforeUrlOpts = CreateNoteAtUrlOpts;
export type CreateNoteAfterUrlOpts = CreateNoteAtUrlOpts;
type CreateNoteSiblingURLOpts = CreateNoteAtUrlOpts; type NeverDefineParentNoteUrlRule = {
export type CreateNoteBeforeURLOpts = CreateNoteSiblingURLOpts;
export type CreateNoteAfterURLOpts = CreateNoteSiblingURLOpts;
export type CreateNoteIntoInboxURLOpts = CreateNoteOpts & {
parentNoteUrl?: never; parentNoteUrl?: never;
} };
export type CreateNoteIntoInboxOpts = CreateNoteOpts & NeverDefineParentNoteUrlRule;
export enum CreateNoteTarget { export enum CreateNoteTarget {
IntoNoteURL, IntoNoteURL,
@ -118,23 +117,6 @@ interface DuplicateResponse {
note: FNote; note: FNote;
} }
/* We are overloading createNote for each type */
async function createNote(
options: CreateNoteIntoURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }>;
async function createNote(
options: CreateNoteAfterURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }>;
async function createNote(
options: CreateNoteBeforeURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }>;
async function createNote(
options: CreateNoteIntoInboxURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }>;
async function createNote( async function createNote(
options: CreateNoteOpts options: CreateNoteOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }> { ): Promise<{ note: FNote | null; branch: FBranch | undefined }> {
@ -143,41 +125,28 @@ async function createNote(
// handle prompts centrally to write once fix for all // handle prompts centrally to write once fix for all
if (options.promptForType) { if (options.promptForType) {
const { success, noteType, templateNoteId, notePath } = await chooseNoteType(); let maybeResolvedOptions = await promptForType(options);
if (!maybeResolvedOptions) {
if (!success) return { return {
note: null, branch: undefined note: null, branch: undefined
}; };
resolvedOptions = {
...resolvedOptions,
promptForType: false,
type: noteType,
templateNoteId,
} as CreateNoteOpts;
if (notePath) {
resolvedOptions = resolvedOptions as CreateNoteIntoURLOpts;
resolvedOptions = {
...resolvedOptions,
target: CreateNoteTarget.IntoNoteURL,
parentNoteUrl: notePath,
} as CreateNoteIntoURLOpts;
} }
resolvedOptions = maybeResolvedOptions;
} }
switch (resolvedOptions.target) { switch (resolvedOptions.target) {
case CreateNoteTarget.IntoNoteURL: case CreateNoteTarget.IntoNoteURL:
return await createNoteIntoNote(resolvedOptions as CreateNoteIntoURLOpts); return await createNoteAtNote("into", {...options} as CreateNoteAtUrlOpts);
case CreateNoteTarget.BeforeNoteURL: case CreateNoteTarget.BeforeNoteURL:
return await createNoteBeforeNote(resolvedOptions as CreateNoteBeforeURLOpts); return await createNoteAtNote("before", resolvedOptions as CreateNoteBeforeUrlOpts);
case CreateNoteTarget.AfterNoteURL: case CreateNoteTarget.AfterNoteURL:
return await createNoteAfterNote(resolvedOptions as CreateNoteAfterURLOpts); return await createNoteAtNote("after", resolvedOptions as CreateNoteAfterUrlOpts);
case CreateNoteTarget.IntoInbox: case CreateNoteTarget.IntoInbox:
return await createNoteIntoInbox(resolvedOptions as CreateNoteIntoInboxURLOpts); return await createNoteIntoInbox(resolvedOptions as CreateNoteIntoInboxOpts);
default: { default: {
console.warn("[createNote] Unknown target:", options.target, resolvedOptions); console.warn("[createNote] Unknown target:", options.target, resolvedOptions);
@ -187,14 +156,40 @@ async function createNote(
} }
} }
async function promptForType(
options: CreateNoteOpts
) : Promise<CreateNoteOpts | null> {
const { success, noteType, templateNoteId, notePath } = await chooseNoteType();
if (!success) {
return null;
}
let resolvedOptions = {
...options,
promptForType: false,
type: noteType,
templateNoteId,
} as CreateNoteOpts;
if (notePath) {
resolvedOptions = resolvedOptions as CreateNoteIntoUrlOpts;
resolvedOptions = {
...resolvedOptions,
target: CreateNoteTarget.IntoNoteURL,
parentNoteUrl: notePath,
} as CreateNoteIntoUrlOpts;
}
return resolvedOptions;
}
/** /**
* Core function that creates a new note under the specified parent note path. * Creates a new note under a specified parent note path.
* *
* @param target - Duplicates apps/server/src/routes/api/notes.ts createNote * @param target - Mirrors the `createNote` API in apps/server/src/routes/api/notes.ts.
* @param {CreateNoteEntity} [options] - Options controlling note creation (title, content, type, template, focus, etc.). * @param options - Note creation options
* with parentNotePath - The parent note path where the new note will be created. * @returns A promise resolving with the created note and its branch.
* @returns {Promise<{ note: FNote | null; branch: FBranch | undefined }>}
* Resolves with the created note and branch entities.
*/ */
async function createNoteAtNote( async function createNoteAtNote(
target: "into" | "after" | "before", target: "into" | "after" | "before",
@ -271,35 +266,15 @@ async function createNoteAtNote(
} }
// Small wrapper functions for @see createNoteAtNote, using it a certain way to
// remove code duplication
async function createNoteIntoNote(
options: CreateNoteIntoURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }> {
return createNoteAtNote("into", {...options} as CreateNoteAtUrlOpts);
}
async function createNoteBeforeNote(
options: CreateNoteBeforeURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }> {
return createNoteAtNote("before", {...options} as CreateNoteAtUrlOpts);
}
async function createNoteAfterNote(
options: CreateNoteAfterURLOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }> {
return createNoteAtNote("after", {...options} as CreateNoteAtUrlOpts);
}
/** /**
* Creates a new note inside the user's Inbox. * Creates a new note inside the user's Inbox.
* *
* @param {CreateNoteEntity} [options] - Optional settings such as title, type, template, or content. * @param {CreateNoteIntoInboxOpts} [options] - Optional settings such as title, type, template, or content.
* @returns {Promise<{ note: FNote | null; branch: FBranch | undefined }>} * @returns {Promise<{ note: FNote | null; branch: FBranch | undefined }>}
* Resolves with the created note and its branch, or `{ note: null, branch: undefined }` if the inbox is missing. * Resolves with the created note and its branch, or `{ note: null, branch: undefined }` if the inbox is missing.
*/ */
async function createNoteIntoInbox( async function createNoteIntoInbox(
options: CreateNoteIntoInboxURLOpts options: CreateNoteIntoInboxOpts
): Promise<{ note: FNote | null; branch: FBranch | undefined }> { ): Promise<{ note: FNote | null; branch: FBranch | undefined }> {
const inboxNote = await dateNoteService.getInboxNote(); const inboxNote = await dateNoteService.getInboxNote();
if (!inboxNote) { if (!inboxNote) {
@ -313,11 +288,11 @@ async function createNoteIntoInbox(
inboxNote.isProtected && protectedSessionHolder.isProtectedSessionAvailable(); inboxNote.isProtected && protectedSessionHolder.isProtectedSessionAvailable();
} }
const result = await createNoteIntoNote( const result = await createNoteAtNote("into",
{ {
...options, ...options,
parentNoteUrl: inboxNote.noteId, parentNoteUrl: inboxNote.noteId,
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
return result; return result;

View File

@ -7,7 +7,7 @@ import branches from "../../../services/branches";
import { executeBulkActions } from "../../../services/bulk_action"; import { executeBulkActions } from "../../../services/bulk_action";
import froca from "../../../services/froca"; import froca from "../../../services/froca";
import { t } from "../../../services/i18n"; import { t } from "../../../services/i18n";
import note_create, { CreateNoteIntoURLOpts, CreateNoteTarget } from "../../../services/note_create.js"; import note_create, { CreateNoteIntoUrlOpts, CreateNoteTarget } from "../../../services/note_create.js";
import server from "../../../services/server"; import server from "../../../services/server";
import { ColumnMap } from "./data"; import { ColumnMap } from "./data";
@ -44,7 +44,7 @@ export default class BoardApi {
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
activate: false, activate: false,
title, title,
} as CreateNoteIntoURLOpts); } as CreateNoteIntoUrlOpts);
if (newNote && newBranch) { if (newNote && newBranch) {
await this.changeColumn(newNote.noteId, column); await this.changeColumn(newNote.noteId, column);
@ -150,7 +150,7 @@ export default class BoardApi {
activate: false, activate: false,
targetBranchId: relativeToBranchId, targetBranchId: relativeToBranchId,
title: t("board_view.new-item"), title: t("board_view.new-item"),
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
if (!note || !branch) { if (!note || !branch) {

View File

@ -9,7 +9,7 @@ import branches from "../../../services/branches.js";
import Component from "../../../components/component.js"; import Component from "../../../components/component.js";
import NoteColorPicker from "../../../menus/custom-items/NoteColorPicker.jsx"; import NoteColorPicker from "../../../menus/custom-items/NoteColorPicker.jsx";
import { RefObject } from "preact"; import { RefObject } from "preact";
import { CreateNoteAfterURLOpts, CreateNoteBeforeURLOpts, CreateNoteTarget } from "../../../services/note_create.js"; import { CreateNoteAfterUrlOpts, CreateNoteBeforeUrlOpts, CreateNoteTarget } from "../../../services/note_create.js";
export function useContextMenu(parentNote: FNote, parentComponent: Component | null | undefined, tabulator: RefObject<Tabulator>): Partial<EventCallBackMethods> { export function useContextMenu(parentNote: FNote, parentComponent: Component | null | undefined, tabulator: RefObject<Tabulator>): Partial<EventCallBackMethods> {
const events: Partial<EventCallBackMethods> = {}; const events: Partial<EventCallBackMethods> = {};
@ -186,7 +186,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: CreateNoteTarget.BeforeNoteURL, target: CreateNoteTarget.BeforeNoteURL,
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteBeforeURLOpts } as CreateNoteBeforeUrlOpts
}) })
}, },
{ {
@ -200,7 +200,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: CreateNoteTarget.AfterNoteURL, target: CreateNoteTarget.AfterNoteURL,
targetBranchId: branchId, targetBranchId: branchId,
} as CreateNoteAfterURLOpts } as CreateNoteAfterUrlOpts
}); });
} }
}, },
@ -213,7 +213,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: CreateNoteTarget.AfterNoteURL, target: CreateNoteTarget.AfterNoteURL,
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteAfterURLOpts } as CreateNoteAfterUrlOpts
}) })
}, },
{ kind: "separator" }, { kind: "separator" },

View File

@ -1,6 +1,6 @@
import { EventCallBackMethods, RowComponent, Tabulator } from "tabulator-tables"; import { EventCallBackMethods, RowComponent, Tabulator } from "tabulator-tables";
import { CommandListenerData } from "../../../components/app_context"; import { CommandListenerData } from "../../../components/app_context";
import note_create, { CreateNoteOpts, CreateNoteIntoURLOpts as CreateNoteIntoURLOpts, CreateNoteTarget } from "../../../services/note_create"; import note_create, { CreateNoteOpts, CreateNoteIntoUrlOpts as CreateNoteIntoUrlOpts, CreateNoteTarget } from "../../../services/note_create";
import { useLegacyImperativeHandlers } from "../../react/hooks"; import { useLegacyImperativeHandlers } from "../../react/hooks";
import { RefObject } from "preact"; import { RefObject } from "preact";
import { setAttribute, setLabel } from "../../../services/attributes"; import { setAttribute, setLabel } from "../../../services/attributes";
@ -23,7 +23,7 @@ export default function useRowTableEditing(api: RefObject<Tabulator>, attributeD
{ {
parentNoteUrl: notePath, parentNoteUrl: notePath,
...opts ...opts
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
).then(({ branch }) => { ).then(({ branch }) => {
if (branch) { if (branch) {
setTimeout(() => { setTimeout(() => {

View File

@ -3,7 +3,7 @@ import appContext from "../../components/app_context";
import contextMenu from "../../menus/context_menu"; import contextMenu from "../../menus/context_menu";
import branches from "../../services/branches"; import branches from "../../services/branches";
import { t } from "../../services/i18n"; import { t } from "../../services/i18n";
import note_create, { CreateNoteIntoURLOpts, CreateNoteTarget } from "../../services/note_create"; import note_create, { CreateNoteIntoUrlOpts, CreateNoteTarget } from "../../services/note_create";
import tree from "../../services/tree"; import tree from "../../services/tree";
import ActionButton from "../react/ActionButton"; import ActionButton from "../react/ActionButton";
import { ParentComponent } from "../react/react_utils"; import { ParentComponent } from "../react/react_utils";
@ -33,7 +33,7 @@ export default function MobileDetailMenu() {
{ {
target: CreateNoteTarget.IntoNoteURL, target: CreateNoteTarget.IntoNoteURL,
parentNoteUrl: appContext.tabManager.getActiveContextNotePath() ?? undefined parentNoteUrl: appContext.tabManager.getActiveContextNotePath() ?? undefined
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
); );
} else if (command === "delete") { } else if (command === "delete") {
const notePath = appContext.tabManager.getActiveContextNotePath(); const notePath = appContext.tabManager.getActiveContextNotePath();

View File

@ -7,7 +7,7 @@ import branchService from "../services/branches.js";
import ws from "../services/ws.js"; import ws from "../services/ws.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js";
import server from "../services/server.js"; import server from "../services/server.js";
import noteCreateService, { CreateNoteIntoURLOpts, CreateNoteTarget } from "../services/note_create.js"; import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteTarget } from "../services/note_create.js";
import toastService from "../services/toast.js"; import toastService from "../services/toast.js";
import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js"; import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js"; import keyboardActionsService from "../services/keyboard_actions.js";
@ -229,7 +229,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: CreateNoteTarget.IntoNoteURL, target: CreateNoteTarget.IntoNoteURL,
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteIntoURLOpts, } as CreateNoteIntoUrlOpts,
); );
} else if (target.classList.contains("enter-workspace-button")) { } else if (target.classList.contains("enter-workspace-button")) {
const node = $.ui.fancytree.getNode(e as unknown as Event); const node = $.ui.fancytree.getNode(e as unknown as Event);
@ -1847,7 +1847,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: CreateNoteTarget.IntoNoteURL, target: CreateNoteTarget.IntoNoteURL,
parentNoteUrl: notePath, parentNoteUrl: notePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteIntoURLOpts } as CreateNoteIntoUrlOpts
) )
} }
}), }),

View File

@ -19,7 +19,7 @@ import contextMenu from "../../../menus/context_menu";
import type { CommandData, FilteredCommandNames } from "../../../components/app_context"; import type { CommandData, FilteredCommandNames } from "../../../components/app_context";
import { AttributeType } from "@triliumnext/commons"; import { AttributeType } from "@triliumnext/commons";
import attributes from "../../../services/attributes"; import attributes from "../../../services/attributes";
import note_create, { CreateNoteAfterURLOpts, CreateNoteIntoURLOpts, CreateNoteTarget, CreateNoteIntoInboxURLOpts } from "../../../services/note_create"; import note_create, { CreateNoteAfterUrlOpts, CreateNoteIntoUrlOpts, CreateNoteTarget, CreateNoteIntoInboxOpts } from "../../../services/note_create";
import { CreateNoteAction } from "@triliumnext/commons"; import { CreateNoteAction } from "@triliumnext/commons";
type AttributeCommandNames = FilteredCommandNames<CommandData>; type AttributeCommandNames = FilteredCommandNames<CommandData>;
@ -266,7 +266,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
target: CreateNoteTarget.IntoInbox, target: CreateNoteTarget.IntoInbox,
title, title,
activate: false activate: false
} as CreateNoteIntoInboxURLOpts } as CreateNoteIntoInboxOpts
); );
return note?.getBestNotePathString() ?? ""; return note?.getBestNotePathString() ?? "";
} }
@ -280,7 +280,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
title, title,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoURLOpts, } as CreateNoteIntoUrlOpts,
) )
return resp?.note?.getBestNotePathString() ?? ""; return resp?.note?.getBestNotePathString() ?? "";
} }