From 73ca285b7a6973eadc263e329ff499810d9186f9 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 23 Aug 2025 19:26:23 +0300 Subject: [PATCH] chore(react/ribbon): support reference links in attributes --- .../attribute_widgets/attribute_editor.ts | 8 ------ .../ribbon/components/AttributeEditor.tsx | 28 +++++++++++++++++-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/apps/client/src/widgets/attribute_widgets/attribute_editor.ts b/apps/client/src/widgets/attribute_widgets/attribute_editor.ts index 4d0bc64e5..9dc426c6e 100644 --- a/apps/client/src/widgets/attribute_widgets/attribute_editor.ts +++ b/apps/client/src/widgets/attribute_widgets/attribute_editor.ts @@ -162,14 +162,6 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem this.lastUpdatedNoteId = this.noteId; } - async loadReferenceLinkTitle($el: JQuery, href: string) { - const { noteId } = linkService.parseNavigationStateFromUrl(href); - const note = noteId ? await froca.getNote(noteId, true) : null; - const title = note ? note.title : "[missing]"; - - $el.text(title); - } - async createNoteForReferenceLink(title: string) { let result; if (this.notePath) { diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx index 6a8981431..9ea7ebaca 100644 --- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx +++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "preact/hooks" +import { useContext, useEffect, useRef, useState } from "preact/hooks" import { AttributeEditor as CKEditorAttributeEditor, MentionFeed, ModelElement, ModelNode, ModelPosition } from "@triliumnext/ckeditor5"; import { t } from "../../../services/i18n"; import server from "../../../services/server"; @@ -12,6 +12,10 @@ import AttributeDetailWidget from "../../attribute_widgets/attribute_detail"; import attribute_parser, { Attribute } from "../../../services/attribute_parser"; import ActionButton from "../../react/ActionButton"; import { escapeQuotes } from "../../../services/utils"; +import { ParentComponent } from "../../react/react_utils"; +import Component from "../../../components/component"; +import link from "../../../services/link"; +import froca from "../../../services/froca"; const HELP_TEXT = `

${t("attribute_editor.help_text_body1")}

@@ -66,14 +70,18 @@ const mentionSetup: MentionFeed[] = [ export default function AttributeEditor({ note, componentId }: { note: FNote, componentId: string }) { + const parentComponent = useContext(ParentComponent); + injectLoadReferenceLinkTitle(parentComponent); const [ state, setState ] = useState<"normal" | "showHelpTooltip" | "showAttributeDetail">(); const [ error, setError ] = useState(); const [ needsSaving, setNeedsSaving ] = useState(false); const [ initialValue, setInitialValue ] = useState(""); + const lastSavedContent = useRef(); const currentValueRef = useRef(initialValue); const wrapperRef = useRef(null); + const { showTooltip, hideTooltip } = useTooltip(wrapperRef, { trigger: "focus", html: true, @@ -96,7 +104,7 @@ export default function AttributeEditor({ note, componentId }: { note: FNote, co // attrs are not resorted if position changes after the initial load ownedAttributes.sort((a, b) => a.position - b.position); - let htmlAttrs = getPreprocessedData("

" + (await attribute_renderer.renderAttributes(ownedAttributes, true)).html() + "

"); + let htmlAttrs = ("

" + (await attribute_renderer.renderAttributes(ownedAttributes, true)).html() + "

"); if (saved) { lastSavedContent.current = htmlAttrs; @@ -164,7 +172,10 @@ export default function AttributeEditor({ note, componentId }: { note: FNote, co }} onChange={(currentValue) => { currentValueRef.current = currentValue ?? ""; - setNeedsSaving((lastSavedContent.current ?? "").trimEnd() !== getPreprocessedData(currentValue ?? "").trimEnd()); + + const oldValue = getPreprocessedData(lastSavedContent.current ?? "").trimEnd(); + const newValue = getPreprocessedData(currentValue ?? "").trimEnd(); + setNeedsSaving(oldValue !== newValue); setError(undefined); }} onClick={(e, pos) => { @@ -253,4 +264,15 @@ function getClickIndex(pos: ModelPosition) { } return clickIndex; +} + +function injectLoadReferenceLinkTitle(component: Component | null) { + if (!component) return; + (component as any).loadReferenceLinkTitle = async ($el: JQuery, href: string) => { + const { noteId } = link.parseNavigationStateFromUrl(href); + const note = noteId ? await froca.getNote(noteId, true) : null; + const title = note ? note.title : "[missing]"; + + $el.text(title); + } } \ No newline at end of file