# Generate UI lib
-nx g @nx/angular:lib ui
-
-# Add a component
-nx g @nx/angular:component ui/src/lib/button
-
-
-
-
- View interactive project graph
-
-
nx graph
-
-
-
-
- Run affected commands
-
-
# see what's been affected by changes
-nx affected:graph
-
-# run tests for current changes
-nx affected:test
-
-# run e2e tests for current changes
-nx affected:e2e
-
-
-
-
- Carefully crafted with
-
-
-
-
- `;
- }
-}
-customElements.define('triliumnext-root', AppElement);
diff --git a/apps/client/src-example/assets/.gitkeep b/apps/client/src-example/assets/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/apps/client/src-example/favicon.ico b/apps/client/src-example/favicon.ico
deleted file mode 100644
index 317ebcb23..000000000
Binary files a/apps/client/src-example/favicon.ico and /dev/null differ
diff --git a/apps/client/src-example/index.html b/apps/client/src-example/index.html
deleted file mode 100644
index e206d4837..000000000
--- a/apps/client/src-example/index.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- Client
-
-
-
-
-
-
-
-
-
diff --git a/apps/client/src-example/main.ts b/apps/client/src-example/main.ts
deleted file mode 100644
index fdb879ded..000000000
--- a/apps/client/src-example/main.ts
+++ /dev/null
@@ -1 +0,0 @@
-import './app/app.element';
diff --git a/apps/client/src-example/styles.css b/apps/client/src-example/styles.css
deleted file mode 100644
index 90d4ee007..000000000
--- a/apps/client/src-example/styles.css
+++ /dev/null
@@ -1 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts
index 0cf5058ed..443014572 100644
--- a/apps/client/src/components/app_context.ts
+++ b/apps/client/src/components/app_context.ts
@@ -1,5 +1,4 @@
import froca from "../services/froca.js";
-import bundleService from "../services/bundle.js";
import RootCommandExecutor from "./root_command_executor.js";
import Entrypoints, { type SqlExecuteResults } from "./entrypoints.js";
import options from "../services/options.js";
@@ -470,6 +469,7 @@ export class AppContext extends Component {
this.tabManager.loadTabs();
+ const bundleService = (await import("../services/bundle.js")).default;
setTimeout(() => bundleService.executeStartupBundles(), 2000);
}
diff --git a/apps/client/src/components/note_context.ts b/apps/client/src/components/note_context.ts
index 11d32cf0d..3a8a54310 100644
--- a/apps/client/src/components/note_context.ts
+++ b/apps/client/src/components/note_context.ts
@@ -12,6 +12,7 @@ import type FNote from "../entities/fnote.js";
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
import type { CKTextEditor } from "@triliumnext/ckeditor5";
import type CodeMirror from "@triliumnext/codemirror";
+import { closeActiveDialog } from "../services/dialog.js";
export interface SetNoteOpts {
triggerSwitchEvent?: unknown;
@@ -83,7 +84,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
await this.triggerEvent("beforeNoteSwitch", { noteContext: this });
- utils.closeActiveDialog();
+ closeActiveDialog();
this.notePath = resolvedNotePath;
this.viewScope = opts.viewScope;
diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts
index 9e215821d..fd35c09b8 100644
--- a/apps/client/src/entities/fnote.ts
+++ b/apps/client/src/entities/fnote.ts
@@ -1,7 +1,6 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import ws from "../services/ws.js";
-import froca from "../services/froca.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
@@ -410,8 +409,8 @@ class FNote {
const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({
notePath: path,
isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId),
- isArchived: path.some((noteId) => froca.notes[noteId].isArchived),
- isSearch: path.some((noteId) => froca.notes[noteId].type === "search"),
+ isArchived: path.some((noteId) => this.froca.notes[noteId].isArchived),
+ isSearch: path.some((noteId) => this.froca.notes[noteId].type === "search"),
isHidden: path.includes("_hidden")
}));
@@ -982,7 +981,7 @@ class FNote {
continue;
}
- const parentNote = froca.notes[parentNoteId];
+ const parentNote = this.froca.notes[parentNoteId];
if (!parentNote || parentNote.type === "search") {
continue;
diff --git a/apps/client/src/services/bundle.ts b/apps/client/src/services/bundle.ts
index e6eea7ef1..e7b88a343 100644
--- a/apps/client/src/services/bundle.ts
+++ b/apps/client/src/services/bundle.ts
@@ -1,6 +1,6 @@
import ScriptContext from "./script_context.js";
import server from "./server.js";
-import toastService from "./toast.js";
+import toastService, { showError } from "./toast.js";
import froca from "./froca.js";
import utils from "./utils.js";
import { t } from "./i18n.js";
@@ -37,7 +37,9 @@ async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $cont
} catch (e: any) {
const note = await froca.getNote(bundle.noteId);
- toastService.showAndLogError(`Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`);
+ const message = `Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`;
+ showError(message);
+ logError(message);
}
}
diff --git a/apps/client/src/services/clipboard.ts b/apps/client/src/services/clipboard.ts
index 952ac2e22..9ca5f9d09 100644
--- a/apps/client/src/services/clipboard.ts
+++ b/apps/client/src/services/clipboard.ts
@@ -4,7 +4,7 @@ import froca from "./froca.js";
import linkService from "./link.js";
import utils from "./utils.js";
import { t } from "./i18n.js";
-import toast from "./toast.js";
+import { throwError } from "./ws.js";
let clipboardBranchIds: string[] = [];
let clipboardMode: string | null = null;
@@ -37,7 +37,7 @@ async function pasteAfter(afterBranchId: string) {
// copy will keep clipboardBranchIds and clipboardMode, so it's possible to paste into multiple places
} else {
- toastService.throwError(`Unrecognized clipboard mode=${clipboardMode}`);
+ throwError(`Unrecognized clipboard mode=${clipboardMode}`);
}
}
@@ -69,7 +69,7 @@ async function pasteInto(parentBranchId: string) {
// copy will keep clipboardBranchIds and clipboardMode, so it's possible to paste into multiple places
} else {
- toastService.throwError(`Unrecognized clipboard mode=${clipboardMode}`);
+ throwError(`Unrecognized clipboard mode=${clipboardMode}`);
}
}
diff --git a/apps/client/src/services/dialog.ts b/apps/client/src/services/dialog.ts
index e2d93250f..240172f49 100644
--- a/apps/client/src/services/dialog.ts
+++ b/apps/client/src/services/dialog.ts
@@ -1,6 +1,41 @@
+import { Modal } from "bootstrap";
import appContext from "../components/app_context.js";
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js";
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
+import { focusSavedElement, saveFocusedElement } from "./focus.js";
+
+export async function openDialog($dialog: JQuery, closeActDialog = true) {
+ if (closeActDialog) {
+ closeActiveDialog();
+ glob.activeDialog = $dialog;
+ }
+
+ saveFocusedElement();
+ Modal.getOrCreateInstance($dialog[0]).show();
+
+ $dialog.on("hidden.bs.modal", () => {
+ const $autocompleteEl = $(".aa-input");
+ if ("autocomplete" in $autocompleteEl) {
+ $autocompleteEl.autocomplete("close");
+ }
+
+ if (!glob.activeDialog || glob.activeDialog === $dialog) {
+ focusSavedElement();
+ }
+ });
+
+ const keyboardActionsService = (await import("./keyboard_actions.js")).default;
+ keyboardActionsService.updateDisplayedShortcuts($dialog);
+
+ return $dialog;
+}
+
+export function closeActiveDialog() {
+ if (glob.activeDialog) {
+ Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
+ glob.activeDialog = null;
+ }
+}
async function info(message: string) {
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));
diff --git a/apps/client/src/services/focus.ts b/apps/client/src/services/focus.ts
new file mode 100644
index 000000000..066c74558
--- /dev/null
+++ b/apps/client/src/services/focus.ts
@@ -0,0 +1,29 @@
+let $lastFocusedElement: JQuery | null;
+
+// perhaps there should be saved focused element per tab?
+export function saveFocusedElement() {
+ $lastFocusedElement = $(":focus");
+}
+
+export function focusSavedElement() {
+ if (!$lastFocusedElement) {
+ return;
+ }
+
+ if ($lastFocusedElement.hasClass("ck")) {
+ // must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
+ // the bug manifests itself in resetting the cursor position to the first character - jumping above
+
+ const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
+
+ if (editor) {
+ editor.editing.view.focus();
+ } else {
+ console.log("Could not find CKEditor instance to focus last element");
+ }
+ } else {
+ $lastFocusedElement.focus();
+ }
+
+ $lastFocusedElement = null;
+}
diff --git a/apps/client/src/services/i18n.spec.ts b/apps/client/src/services/i18n.spec.ts
index 9143097be..e64605949 100644
--- a/apps/client/src/services/i18n.spec.ts
+++ b/apps/client/src/services/i18n.spec.ts
@@ -1,6 +1,7 @@
import { LOCALES } from "@triliumnext/commons";
import { readFileSync } from "fs";
import { join } from "path";
+import { describe, expect, it } from "vitest";
describe("i18n", () => {
it("translations are valid JSON", () => {
diff --git a/apps/client/src/services/image.ts b/apps/client/src/services/image.ts
index 3cf1424d5..f13a9a3c7 100644
--- a/apps/client/src/services/image.ts
+++ b/apps/client/src/services/image.ts
@@ -1,5 +1,5 @@
import { t } from "./i18n.js";
-import toastService from "./toast.js";
+import toastService, { showError } from "./toast.js";
function copyImageReferenceToClipboard($imageWrapper: JQuery) {
try {
@@ -11,7 +11,9 @@ function copyImageReferenceToClipboard($imageWrapper: JQuery) {
if (success) {
toastService.showMessage(t("image.copied-to-clipboard"));
} else {
- toastService.showAndLogError(t("image.cannot-copy"));
+ const message = t("image.cannot-copy");
+ showError(message);
+ logError(message);
}
} finally {
window.getSelection()?.removeAllRanges();
diff --git a/apps/client/src/services/note_autocomplete.ts b/apps/client/src/services/note_autocomplete.ts
index 4ffff8594..d6eb4df0e 100644
--- a/apps/client/src/services/note_autocomplete.ts
+++ b/apps/client/src/services/note_autocomplete.ts
@@ -289,13 +289,11 @@ function initNoteAutocomplete($el: JQuery, options?: Options) {
}
if (suggestion.action === "create-note") {
- const { success, noteType, templateNoteId } = await noteCreateService.chooseNoteType();
-
+ const { success, noteType, templateNoteId, notePath } = await noteCreateService.chooseNoteType();
if (!success) {
return;
}
-
- const { note } = await noteCreateService.createNote(suggestion.parentNoteId, {
+ const { note } = await noteCreateService.createNote( notePath || suggestion.parentNoteId, {
title: suggestion.noteTitle,
activate: false,
type: noteType,
diff --git a/apps/client/src/services/note_create.ts b/apps/client/src/services/note_create.ts
index 5fa262553..6ce92bc0d 100644
--- a/apps/client/src/services/note_create.ts
+++ b/apps/client/src/services/note_create.ts
@@ -116,7 +116,7 @@ async function chooseNoteType() {
}
async function createNoteWithTypePrompt(parentNotePath: string, options: CreateNoteOpts = {}) {
- const { success, noteType, templateNoteId } = await chooseNoteType();
+ const { success, noteType, templateNoteId, notePath } = await chooseNoteType();
if (!success) {
return;
@@ -125,7 +125,7 @@ async function createNoteWithTypePrompt(parentNotePath: string, options: CreateN
options.type = noteType;
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. */
diff --git a/apps/client/src/services/script_context.ts b/apps/client/src/services/script_context.ts
index 27a8a7d44..7c15db1ae 100644
--- a/apps/client/src/services/script_context.ts
+++ b/apps/client/src/services/script_context.ts
@@ -1,4 +1,4 @@
-import FrontendScriptApi, { type Entity } from "./frontend_script_api.js";
+import type { Entity } from "./frontend_script_api.js";
import utils from "./utils.js";
import froca from "./froca.js";
@@ -14,6 +14,8 @@ async function ScriptContext(startNoteId: string, allNoteIds: string[], originEn
throw new Error(`Could not find start note ${startNoteId}.`);
}
+ const FrontendScriptApi = (await import("./frontend_script_api.js")).default;
+
return {
modules: modules,
notes: utils.toObject(allNotes, (note) => [note.noteId, note]),
diff --git a/apps/client/src/services/server.ts b/apps/client/src/services/server.ts
index f577fbfb4..861a20e60 100644
--- a/apps/client/src/services/server.ts
+++ b/apps/client/src/services/server.ts
@@ -1,5 +1,6 @@
import utils, { isShare } from "./utils.js";
import ValidationError from "./validation_error.js";
+import { throwError } from "./ws.js";
type Headers = Record;
@@ -276,7 +277,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
} else {
const title = `${statusCode} ${method} ${url}`;
toastService.showErrorTitleAndMessage(title, messageStr);
- toastService.throwError(`${title} - ${message}`);
+ throwError(`${title} - ${message}`);
}
}
diff --git a/apps/client/src/services/toast.ts b/apps/client/src/services/toast.ts
index 18cc876a9..66b3f7f50 100644
--- a/apps/client/src/services/toast.ts
+++ b/apps/client/src/services/toast.ts
@@ -78,13 +78,7 @@ function showMessage(message: string, delay = 2000) {
});
}
-function showAndLogError(message: string, delay = 10000) {
- showError(message, delay);
-
- ws.logError(message);
-}
-
-function showError(message: string, delay = 10000) {
+export function showError(message: string, delay = 10000) {
console.log(utils.now(), "error: ", message);
toast({
@@ -108,18 +102,10 @@ function showErrorTitleAndMessage(title: string, message: string, delay = 10000)
});
}
-function throwError(message: string) {
- ws.logError(message);
-
- throw new Error(message);
-}
-
export default {
showMessage,
showError,
showErrorTitleAndMessage,
- showAndLogError,
- throwError,
showPersistent,
closePersistent
};
diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts
index 412650605..c7d37e4d9 100644
--- a/apps/client/src/services/utils.ts
+++ b/apps/client/src/services/utils.ts
@@ -1,5 +1,4 @@
import dayjs from "dayjs";
-import { Modal } from "bootstrap";
import type { ViewScope } from "./link.js";
const SVG_MIME = "image/svg+xml";
@@ -275,69 +274,6 @@ function getMimeTypeClass(mime: string) {
return `mime-${mime.toLowerCase().replace(/[\W_]+/g, "-")}`;
}
-function closeActiveDialog() {
- if (glob.activeDialog) {
- Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
- glob.activeDialog = null;
- }
-}
-
-let $lastFocusedElement: JQuery | null;
-
-// perhaps there should be saved focused element per tab?
-function saveFocusedElement() {
- $lastFocusedElement = $(":focus");
-}
-
-function focusSavedElement() {
- if (!$lastFocusedElement) {
- return;
- }
-
- if ($lastFocusedElement.hasClass("ck")) {
- // must handle CKEditor separately because of this bug: https://github.com/ckeditor/ckeditor5/issues/607
- // the bug manifests itself in resetting the cursor position to the first character - jumping above
-
- const editor = $lastFocusedElement.closest(".ck-editor__editable").prop("ckeditorInstance");
-
- if (editor) {
- editor.editing.view.focus();
- } else {
- console.log("Could not find CKEditor instance to focus last element");
- }
- } else {
- $lastFocusedElement.focus();
- }
-
- $lastFocusedElement = null;
-}
-
-async function openDialog($dialog: JQuery, closeActDialog = true) {
- if (closeActDialog) {
- closeActiveDialog();
- glob.activeDialog = $dialog;
- }
-
- saveFocusedElement();
- Modal.getOrCreateInstance($dialog[0]).show();
-
- $dialog.on("hidden.bs.modal", () => {
- const $autocompleteEl = $(".aa-input");
- if ("autocomplete" in $autocompleteEl) {
- $autocompleteEl.autocomplete("close");
- }
-
- if (!glob.activeDialog || glob.activeDialog === $dialog) {
- focusSavedElement();
- }
- });
-
- const keyboardActionsService = (await import("./keyboard_actions.js")).default;
- keyboardActionsService.updateDisplayedShortcuts($dialog);
-
- return $dialog;
-}
-
function isHtmlEmpty(html: string) {
if (!html) {
return true;
@@ -823,10 +759,6 @@ export default {
setCookie,
getNoteTypeClass,
getMimeTypeClass,
- closeActiveDialog,
- openDialog,
- saveFocusedElement,
- focusSavedElement,
isHtmlEmpty,
clearBrowserCache,
copySelectionToClipboard,
diff --git a/apps/client/src/services/ws.ts b/apps/client/src/services/ws.ts
index ccfd19592..dcd63e577 100644
--- a/apps/client/src/services/ws.ts
+++ b/apps/client/src/services/ws.ts
@@ -17,7 +17,7 @@ let lastProcessedEntityChangeId = window.glob.maxEntityChangeIdAtLoad;
let lastPingTs: number;
let frontendUpdateDataQueue: EntityChange[] = [];
-function logError(message: string) {
+export function logError(message: string) {
console.error(utils.now(), message); // needs to be separate from .trace()
if (ws && ws.readyState === 1) {
@@ -301,6 +301,12 @@ setTimeout(() => {
setInterval(sendPing, 1000);
}, 0);
+export function throwError(message: string) {
+ logError(message);
+
+ throw new Error(message);
+}
+
export default {
logError,
subscribeToMessages,
diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css
index 9b83c37fe..0bf0588b0 100644
--- a/apps/client/src/stylesheets/style.css
+++ b/apps/client/src/stylesheets/style.css
@@ -440,10 +440,11 @@ body #context-menu-container .dropdown-item > span {
border-radius: 6px;
overflow: hidden;
margin: 4px;
+ font-size: var(--monospace-font-size);
}
-body .cm-editor {
- font-size: var(--monospace-font-size);
+.cm-scroller {
+ font-family: var(--monospace-font-family) !important;
}
body .cm-editor .cm-gutters {
diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json
index ab7933617..251819807 100644
--- a/apps/client/src/translations/en/translation.json
+++ b/apps/client/src/translations/en/translation.json
@@ -233,6 +233,8 @@
"move_success_message": "Selected notes have been moved into "
},
"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",
"close": "Close",
"modal_body": "Choose note type / template of the new note:",
diff --git a/apps/client/src/widgets/attribute_widgets/attribute_detail.ts b/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
index 08bb764fc..9017673f3 100644
--- a/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
+++ b/apps/client/src/widgets/attribute_widgets/attribute_detail.ts
@@ -11,6 +11,7 @@ import utils from "../../services/utils.js";
import shortcutService from "../../services/shortcuts.js";
import appContext from "../../components/app_context.js";
import type { Attribute } from "../../services/attribute_parser.js";
+import { focusSavedElement, saveFocusedElement } from "../../services/focus.js";
const TPL = /*html*/`
@@ -483,7 +484,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
return;
}
- utils.saveFocusedElement();
+ saveFocusedElement();
this.attrType = this.getAttrType(attribute);
@@ -605,7 +606,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.hide();
- utils.focusSavedElement();
+ focusSavedElement();
}
async cancelAndClose() {
@@ -613,7 +614,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.hide();
- utils.focusSavedElement();
+ focusSavedElement();
}
userEditedAttribute() {
diff --git a/apps/client/src/widgets/dialogs/about.ts b/apps/client/src/widgets/dialogs/about.ts
index 2c364d756..06cf118ec 100644
--- a/apps/client/src/widgets/dialogs/about.ts
+++ b/apps/client/src/widgets/dialogs/about.ts
@@ -4,6 +4,7 @@ import BasicWidget from "../basic_widget.js";
import openService from "../../services/open.js";
import server from "../../services/server.js";
import utils from "../../services/utils.js";
+import { openDialog } from "../../services/dialog.js";
interface AppInfo {
appVersion: string;
@@ -111,6 +112,6 @@ export default class AboutDialog extends BasicWidget {
async openAboutDialogEvent() {
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/add_link.ts b/apps/client/src/widgets/dialogs/add_link.ts
index fe2295442..d7758c92d 100644
--- a/apps/client/src/widgets/dialogs/add_link.ts
+++ b/apps/client/src/widgets/dialogs/add_link.ts
@@ -1,11 +1,11 @@
import { t } from "../../services/i18n.js";
import treeService from "../../services/tree.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import type { Suggestion } from "../../services/note_autocomplete.js";
import type { default as TextTypeWidget } from "../type_widgets/editable_text.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -111,7 +111,7 @@ export default class AddLinkDialog extends BasicWidget {
this.updateTitleSettingsVisibility();
- await utils.openDialog(this.$widget);
+ await openDialog(this.$widget);
this.$autoComplete.val("");
this.$linkTitle.val("");
diff --git a/apps/client/src/widgets/dialogs/branch_prefix.ts b/apps/client/src/widgets/dialogs/branch_prefix.ts
index 345d30557..496700a0c 100644
--- a/apps/client/src/widgets/dialogs/branch_prefix.ts
+++ b/apps/client/src/widgets/dialogs/branch_prefix.ts
@@ -2,11 +2,11 @@ import treeService from "../../services/tree.js";
import server from "../../services/server.js";
import froca from "../../services/froca.js";
import toastService from "../../services/toast.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import appContext from "../../components/app_context.js";
import { t } from "../../services/i18n.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -93,7 +93,7 @@ export default class BranchPrefixDialog extends BasicWidget {
}
await this.refresh(notePath);
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
async savePrefix() {
diff --git a/apps/client/src/widgets/dialogs/bulk_actions.ts b/apps/client/src/widgets/dialogs/bulk_actions.ts
index a8680500d..544a5d03e 100644
--- a/apps/client/src/widgets/dialogs/bulk_actions.ts
+++ b/apps/client/src/widgets/dialogs/bulk_actions.ts
@@ -1,11 +1,11 @@
import BasicWidget from "../basic_widget.js";
import froca from "../../services/froca.js";
import bulkActionService from "../../services/bulk_action.js";
-import utils from "../../services/utils.js";
import server from "../../services/server.js";
import toastService from "../../services/toast.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { closeActiveDialog, openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -104,7 +104,7 @@ export default class BulkActionsDialog extends BasicWidget {
});
toastService.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
- utils.closeActiveDialog();
+ closeActiveDialog();
});
}
@@ -170,6 +170,6 @@ export default class BulkActionsDialog extends BasicWidget {
this.$includeDescendants.prop("checked", false);
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/clone_to.ts b/apps/client/src/widgets/dialogs/clone_to.ts
index 08ee3108b..7c3a53071 100644
--- a/apps/client/src/widgets/dialogs/clone_to.ts
+++ b/apps/client/src/widgets/dialogs/clone_to.ts
@@ -1,5 +1,4 @@
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import treeService from "../../services/tree.js";
import toastService from "../../services/toast.js";
import froca from "../../services/froca.js";
@@ -8,6 +7,7 @@ import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -94,7 +94,7 @@ export default class CloneToDialog extends BasicWidget {
}
}
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$noteAutoComplete.val("").trigger("focus");
this.$noteList.empty();
diff --git a/apps/client/src/widgets/dialogs/delete_notes.ts b/apps/client/src/widgets/dialogs/delete_notes.ts
index 52a0d9941..b9f7f89cd 100644
--- a/apps/client/src/widgets/dialogs/delete_notes.ts
+++ b/apps/client/src/widgets/dialogs/delete_notes.ts
@@ -1,10 +1,10 @@
import server from "../../services/server.js";
import froca from "../../services/froca.js";
import linkService from "../../services/link.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { FAttributeRow } from "../../entities/fattribute.js";
+import { closeActiveDialog, openDialog } from "../../services/dialog.js";
// TODO: Use common with server.
interface Response {
@@ -119,13 +119,13 @@ export default class DeleteNotesDialog extends BasicWidget {
this.$widget.on("shown.bs.modal", () => this.$okButton.trigger("focus"));
this.$cancelButton.on("click", () => {
- utils.closeActiveDialog();
+ closeActiveDialog();
this.resolve({ proceed: false });
});
this.$okButton.on("click", () => {
- utils.closeActiveDialog();
+ closeActiveDialog();
this.resolve({
proceed: true,
@@ -179,7 +179,7 @@ export default class DeleteNotesDialog extends BasicWidget {
await this.renderDeletePreview();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$deleteAllClones.prop("checked", !!forceDeleteAllClones).prop("disabled", !!forceDeleteAllClones);
diff --git a/apps/client/src/widgets/dialogs/export.ts b/apps/client/src/widgets/dialogs/export.ts
index d8fcd670d..d9b13f4ed 100644
--- a/apps/client/src/widgets/dialogs/export.ts
+++ b/apps/client/src/widgets/dialogs/export.ts
@@ -8,6 +8,7 @@ import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -214,7 +215,7 @@ export default class ExportDialog extends BasicWidget {
this.$widget.find(".opml-v2").prop("checked", true); // setting default
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
diff --git a/apps/client/src/widgets/dialogs/help.ts b/apps/client/src/widgets/dialogs/help.ts
index 747d01b02..ad8961d0c 100644
--- a/apps/client/src/widgets/dialogs/help.ts
+++ b/apps/client/src/widgets/dialogs/help.ts
@@ -1,6 +1,6 @@
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -155,6 +155,6 @@ export default class HelpDialog extends BasicWidget {
}
showCheatsheetEvent() {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/import.ts b/apps/client/src/widgets/dialogs/import.ts
index f1ac2663d..c8cd66a27 100644
--- a/apps/client/src/widgets/dialogs/import.ts
+++ b/apps/client/src/widgets/dialogs/import.ts
@@ -1,4 +1,4 @@
-import utils, { escapeQuotes } from "../../services/utils.js";
+import { escapeQuotes } from "../../services/utils.js";
import treeService from "../../services/tree.js";
import importService, { type UploadFilesOptions } from "../../services/import.js";
import options from "../../services/options.js";
@@ -6,6 +6,7 @@ import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import { Modal, Tooltip } from "bootstrap";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -155,7 +156,7 @@ export default class ImportDialog extends BasicWidget {
this.$noteTitle.text(await treeService.getNoteTitle(this.parentNoteId));
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
async importIntoNote(parentNoteId: string) {
diff --git a/apps/client/src/widgets/dialogs/include_note.ts b/apps/client/src/widgets/dialogs/include_note.ts
index 06375aa48..61b22a35b 100644
--- a/apps/client/src/widgets/dialogs/include_note.ts
+++ b/apps/client/src/widgets/dialogs/include_note.ts
@@ -1,12 +1,12 @@
import { t } from "../../services/i18n.js";
import treeService from "../../services/tree.js";
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import froca from "../../services/froca.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
import type { EventData } from "../../components/app_context.js";
import type EditableTextTypeWidget from "../type_widgets/editable_text.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -83,7 +83,7 @@ export default class IncludeNoteDialog extends BasicWidget {
async showIncludeNoteDialogEvent({ textTypeWidget }: EventData<"showIncludeDialog">) {
this.textTypeWidget = textTypeWidget;
await this.refresh();
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$autoComplete.trigger("focus").trigger("select"); // to be able to quickly remove entered text
}
diff --git a/apps/client/src/widgets/dialogs/info.ts b/apps/client/src/widgets/dialogs/info.ts
index 508599912..34015dc7d 100644
--- a/apps/client/src/widgets/dialogs/info.ts
+++ b/apps/client/src/widgets/dialogs/info.ts
@@ -1,9 +1,9 @@
import type { EventData } from "../../components/app_context.js";
import { t } from "../../services/i18n.js";
-import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
import type { ConfirmDialogCallback } from "./confirm.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -72,7 +72,7 @@ export default class InfoDialog extends BasicWidget {
}
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.resolve = callback;
}
diff --git a/apps/client/src/widgets/dialogs/jump_to_note.ts b/apps/client/src/widgets/dialogs/jump_to_note.ts
index 54428b3b6..98ee6e0e4 100644
--- a/apps/client/src/widgets/dialogs/jump_to_note.ts
+++ b/apps/client/src/widgets/dialogs/jump_to_note.ts
@@ -5,6 +5,7 @@ import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -54,7 +55,7 @@ export default class JumpToNoteDialog extends BasicWidget {
}
async jumpToNoteEvent() {
- const dialogPromise = utils.openDialog(this.$widget);
+ const dialogPromise = openDialog(this.$widget);
if (utils.isMobile()) {
dialogPromise.then(($dialog) => {
const el = $dialog.find(">.modal-dialog")[0];
diff --git a/apps/client/src/widgets/dialogs/markdown_import.ts b/apps/client/src/widgets/dialogs/markdown_import.ts
index 2f7c2bdf4..40af0c84a 100644
--- a/apps/client/src/widgets/dialogs/markdown_import.ts
+++ b/apps/client/src/widgets/dialogs/markdown_import.ts
@@ -6,6 +6,7 @@ import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js";
import server from "../../services/server.js";
import { Modal } from "bootstrap";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -89,7 +90,7 @@ export default class MarkdownImportDialog extends BasicWidget {
this.convertMarkdownToHtml(text);
} else {
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
}
}
diff --git a/apps/client/src/widgets/dialogs/move_to.ts b/apps/client/src/widgets/dialogs/move_to.ts
index 91ffcfd71..49e016f15 100644
--- a/apps/client/src/widgets/dialogs/move_to.ts
+++ b/apps/client/src/widgets/dialogs/move_to.ts
@@ -1,5 +1,4 @@
import noteAutocompleteService from "../../services/note_autocomplete.js";
-import utils from "../../services/utils.js";
import toastService from "../../services/toast.js";
import froca from "../../services/froca.js";
import branchService from "../../services/branches.js";
@@ -7,6 +6,7 @@ import treeService from "../../services/tree.js";
import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
+import { openDialog } from "../../services/dialog.js";
const TPL = /*html*/`
@@ -83,7 +83,7 @@ export default class MoveToDialog extends BasicWidget {
async moveBranchIdsToEvent({ branchIds }: EventData<"moveBranchIdsTo">) {
this.movedBranchIds = branchIds;
- utils.openDialog(this.$widget);
+ openDialog(this.$widget);
this.$noteAutoComplete.val("").trigger("focus");
diff --git a/apps/client/src/widgets/dialogs/note_type_chooser.ts b/apps/client/src/widgets/dialogs/note_type_chooser.ts
index ff4442826..02b960308 100644
--- a/apps/client/src/widgets/dialogs/note_type_chooser.ts
+++ b/apps/client/src/widgets/dialogs/note_type_chooser.ts
@@ -2,6 +2,7 @@ import type { CommandNames } from "../../components/app_context.js";
import type { MenuCommandItem } from "../../menus/context_menu.js";
import { t } from "../../services/i18n.js";
import noteTypesService from "../../services/note_types.js";
+import noteAutocompleteService from "../../services/note_autocomplete.js";
import BasicWidget from "../basic_widget.js";
import { Dropdown, Modal } from "bootstrap";
@@ -13,6 +14,11 @@ const TPL = /*html*/`
z-index: 1100 !important;
}
+ .note-type-chooser-dialog .input-group {
+ margin-top: 15px;
+ margin-bottom: 15px;
+ }
+
.note-type-chooser-dialog .note-type-dropdown {
position: relative;
font-size: large;
@@ -30,6 +36,12 @@ const TPL = /*html*/`