feat(autocomplete): support specifying path when creating a new note (#2342)

This commit is contained in:
Elian Doran 2025-06-18 23:14:46 +03:00 committed by GitHub
commit 8b841c5aa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 8 deletions

View File

@ -289,13 +289,11 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
} }
if (suggestion.action === "create-note") { if (suggestion.action === "create-note") {
const { success, noteType, templateNoteId } = await noteCreateService.chooseNoteType(); const { success, noteType, templateNoteId, notePath } = await noteCreateService.chooseNoteType();
if (!success) { if (!success) {
return; return;
} }
const { note } = await noteCreateService.createNote( notePath || suggestion.parentNoteId, {
const { note } = await noteCreateService.createNote(suggestion.parentNoteId, {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false, activate: false,
type: noteType, type: noteType,

View File

@ -116,7 +116,7 @@ async function chooseNoteType() {
} }
async function createNoteWithTypePrompt(parentNotePath: string, options: CreateNoteOpts = {}) { async function createNoteWithTypePrompt(parentNotePath: string, options: CreateNoteOpts = {}) {
const { success, noteType, templateNoteId } = await chooseNoteType(); const { success, noteType, templateNoteId, notePath } = await chooseNoteType();
if (!success) { if (!success) {
return; return;
@ -125,7 +125,7 @@ async function createNoteWithTypePrompt(parentNotePath: string, options: CreateN
options.type = noteType; options.type = noteType;
options.templateNoteId = templateNoteId; options.templateNoteId = templateNoteId;
return await createNote(parentNotePath, options); return await createNote(notePath || parentNotePath, options);
} }
/* If the first element is heading, parse it out and use it as a new heading. */ /* If the first element is heading, parse it out and use it as a new heading. */

View File

@ -233,6 +233,8 @@
"move_success_message": "Selected notes have been moved into " "move_success_message": "Selected notes have been moved into "
}, },
"note_type_chooser": { "note_type_chooser": {
"change_path_prompt": "Change where to create the new note:",
"search_placeholder": "search path by name (default if empty)",
"modal_title": "Choose note type", "modal_title": "Choose note type",
"close": "Close", "close": "Close",
"modal_body": "Choose note type / template of the new note:", "modal_body": "Choose note type / template of the new note:",

View File

@ -2,6 +2,7 @@ import type { CommandNames } from "../../components/app_context.js";
import type { MenuCommandItem } from "../../menus/context_menu.js"; import type { MenuCommandItem } from "../../menus/context_menu.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import noteTypesService from "../../services/note_types.js"; import noteTypesService from "../../services/note_types.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Dropdown, Modal } from "bootstrap"; import { Dropdown, Modal } from "bootstrap";
@ -13,6 +14,11 @@ const TPL = /*html*/`
z-index: 1100 !important; z-index: 1100 !important;
} }
.note-type-chooser-dialog .input-group {
margin-top: 15px;
margin-bottom: 15px;
}
.note-type-chooser-dialog .note-type-dropdown { .note-type-chooser-dialog .note-type-dropdown {
position: relative; position: relative;
font-size: large; font-size: large;
@ -30,6 +36,12 @@ const TPL = /*html*/`
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("note_type_chooser.close")}"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("note_type_chooser.close")}"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
${t("note_type_chooser.change_path_prompt")}
<div class="input-group">
<input class="choose-note-path form-control" placeholder="${t("note_type_chooser.search_placeholder")}">
</div>
${t("note_type_chooser.modal_body")} ${t("note_type_chooser.modal_body")}
<div class="dropdown" style="display: flex;"> <div class="dropdown" style="display: flex;">
@ -48,6 +60,7 @@ export interface ChooseNoteTypeResponse {
success: boolean; success: boolean;
noteType?: string; noteType?: string;
templateNoteId?: string; templateNoteId?: string;
notePath?: string;
} }
type Callback = (data: ChooseNoteTypeResponse) => void; type Callback = (data: ChooseNoteTypeResponse) => void;
@ -57,6 +70,7 @@ export default class NoteTypeChooserDialog extends BasicWidget {
private dropdown!: Dropdown; private dropdown!: Dropdown;
private modal!: Modal; private modal!: Modal;
private $noteTypeDropdown!: JQuery<HTMLElement>; private $noteTypeDropdown!: JQuery<HTMLElement>;
private $autoComplete!: JQuery<HTMLElement>;
private $originalFocused: JQuery<HTMLElement> | null; private $originalFocused: JQuery<HTMLElement> | null;
private $originalDialog: JQuery<HTMLElement> | null; private $originalDialog: JQuery<HTMLElement> | null;
@ -72,6 +86,7 @@ export default class NoteTypeChooserDialog extends BasicWidget {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = Modal.getOrCreateInstance(this.$widget[0]); this.modal = Modal.getOrCreateInstance(this.$widget[0]);
this.$autoComplete = this.$widget.find(".choose-note-path");
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger")[0]); this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger")[0]);
@ -116,9 +131,20 @@ export default class NoteTypeChooserDialog extends BasicWidget {
}); });
} }
async refresh() {
noteAutocompleteService
.initNoteAutocomplete(this.$autoComplete, {
allowCreatingNotes: false,
hideGoToSelectedNoteButton: true,
allowJumpToSearchNotes: false,
})
}
async chooseNoteTypeEvent({ callback }: { callback: Callback }) { async chooseNoteTypeEvent({ callback }: { callback: Callback }) {
this.$originalFocused = $(":focus"); this.$originalFocused = $(":focus");
await this.refresh();
const noteTypes = await noteTypesService.getNoteTypeItems(); const noteTypes = await noteTypesService.getNoteTypeItems();
this.$noteTypeDropdown.empty(); this.$noteTypeDropdown.empty();
@ -153,12 +179,14 @@ export default class NoteTypeChooserDialog extends BasicWidget {
const $item = $(e.target).closest(".dropdown-item"); const $item = $(e.target).closest(".dropdown-item");
const noteType = $item.attr("data-note-type"); const noteType = $item.attr("data-note-type");
const templateNoteId = $item.attr("data-template-note-id"); const templateNoteId = $item.attr("data-template-note-id");
const notePath = this.$autoComplete.getSelectedNotePath() || undefined;
if (this.resolve) { if (this.resolve) {
this.resolve({ this.resolve({
success: true, success: true,
noteType, noteType,
templateNoteId templateNoteId,
notePath
}); });
} }
this.resolve = null; this.resolve = null;