mirror of
https://github.com/zadam/trilium.git
synced 2026-05-06 10:17:21 +02:00
chore(revisions): address requested changes
This commit is contained in:
@@ -2539,5 +2539,9 @@
|
||||
"move_note": "Move note",
|
||||
"clone_note": "Clone note"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"save": "Save",
|
||||
"cancel": "Cancel"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import FormToggle from "../react/FormToggle";
|
||||
import { useTriliumEvent } from "../react/hooks";
|
||||
import Modal from "../react/Modal";
|
||||
import NoItems from "../react/NoItems";
|
||||
import { RawHtmlBlock } from "../react/RawHtml";
|
||||
import { RawHtmlBlock, SanitizedHtml } from "../react/RawHtml";
|
||||
import PdfViewer from "../type_widgets/file/PdfViewer";
|
||||
|
||||
export default function RevisionsDialog() {
|
||||
@@ -58,6 +58,7 @@ export default function RevisionsDialog() {
|
||||
}
|
||||
}, [ note, refreshCounter ]);
|
||||
|
||||
const revisionsLoaded = revisions !== undefined;
|
||||
const hasRevisions = !!revisions?.length;
|
||||
|
||||
if (revisions?.length && !currentRevision) {
|
||||
@@ -72,7 +73,7 @@ export default function RevisionsDialog() {
|
||||
setRevisions(undefined);
|
||||
};
|
||||
|
||||
if (!hasRevisions) {
|
||||
if (revisionsLoaded && !hasRevisions) {
|
||||
return (
|
||||
<Modal
|
||||
className="revisions-dialog"
|
||||
@@ -489,8 +490,8 @@ function RevisionDescription({ revisionItem, editing, draft, onEdit, onDraftChan
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus
|
||||
/>
|
||||
<ActionButton icon="bx bx-check" text={t("revisions.edit_description")} onClick={onSave} />
|
||||
<ActionButton icon="bx bx-x" text={t("revisions.edit_description")} onClick={onCancel} />
|
||||
<ActionButton icon="bx bx-check" text={t("common.save")} onClick={onSave} />
|
||||
<ActionButton icon="bx bx-x" text={t("common.cancel")} onClick={onCancel} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -584,41 +585,31 @@ function RevisionContentDiff({ noteContent, itemContent, itemType }: {
|
||||
itemContent: string | Buffer<ArrayBufferLike> | undefined,
|
||||
itemType: string
|
||||
}) {
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
if (!noteContent || typeof itemContent !== "string") {
|
||||
return <div className="revision-diff-content">{t("revisions.diff_not_available")}</div>;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!noteContent || typeof itemContent !== "string") {
|
||||
if (contentRef.current) {
|
||||
contentRef.current.textContent = t("revisions.diff_not_available");
|
||||
let diffHtml: string;
|
||||
if (itemType === "text") {
|
||||
// Use proper HTML-aware diff for rich text content
|
||||
diffHtml = HtmlDiff.execute(noteContent, itemContent);
|
||||
} else {
|
||||
// Use word diff for code/mermaid (plain text)
|
||||
const diff = diffWords(noteContent, itemContent);
|
||||
diffHtml = diff.map(part => {
|
||||
if (part.added) {
|
||||
return `<span class="revision-diff-added">${utils.escapeHtml(part.value)}</span>`;
|
||||
} else if (part.removed) {
|
||||
return `<span class="revision-diff-removed">${utils.escapeHtml(part.value)}</span>`;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return utils.escapeHtml(part.value);
|
||||
}).join("");
|
||||
}
|
||||
|
||||
if (itemType === "text") {
|
||||
// Use proper HTML-aware diff for rich text content
|
||||
const diffHtml = HtmlDiff.execute(noteContent, itemContent);
|
||||
if (contentRef.current) {
|
||||
contentRef.current.innerHTML = diffHtml;
|
||||
}
|
||||
} else {
|
||||
// Use word diff for code/mermaid (plain text)
|
||||
const diff = diffWords(noteContent, itemContent);
|
||||
const diffHtml = diff.map(part => {
|
||||
if (part.added) {
|
||||
return `<span class="revision-diff-added">${utils.escapeHtml(part.value)}</span>`;
|
||||
} else if (part.removed) {
|
||||
return `<span class="revision-diff-removed">${utils.escapeHtml(part.value)}</span>`;
|
||||
}
|
||||
return utils.escapeHtml(part.value);
|
||||
}).join("");
|
||||
|
||||
if (contentRef.current) {
|
||||
contentRef.current.innerHTML = diffHtml;
|
||||
}
|
||||
}
|
||||
}, [noteContent, itemContent, itemType]);
|
||||
|
||||
return <div ref={contentRef} className={clsx("revision-diff-content", itemType === "text" ? "ck-content" : "revision-diff-code")} />;
|
||||
return <SanitizedHtml
|
||||
className={clsx("revision-diff-content", itemType === "text" ? "ck-content" : "revision-diff-code")}
|
||||
html={diffHtml}
|
||||
/>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ export default function Modal({ children, className, size, title, customTitleBar
|
||||
<div className={clsx("modal-content", sidebar && "modal-content-with-sidebar")}>
|
||||
{sidebar && <div className="modal-sidebar">
|
||||
{title && <div className="modal-sidebar-header">
|
||||
<h5>{typeof title === "string" ? title : title}</h5>
|
||||
<h5>{title}</h5>
|
||||
</div>}
|
||||
{sidebar}
|
||||
</div>}
|
||||
|
||||
@@ -192,7 +192,7 @@ function register(router: Router) {
|
||||
eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/revision", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
const description = req.body?.description || "";
|
||||
const description = typeof req.body?.description === "string" ? req.body.description : "";
|
||||
note.saveRevision({ description, source: "etapi" });
|
||||
|
||||
return res.sendStatus(204);
|
||||
|
||||
@@ -351,7 +351,7 @@ function forceSaveRevision(req: Request<{ noteId: string }>) {
|
||||
throw new ValidationError(`Note revision of a protected note cannot be created outside of a protected session.`);
|
||||
}
|
||||
|
||||
const description = req.body?.description || "";
|
||||
const description = typeof req.body?.description === "string" ? req.body.description : "";
|
||||
const revision = note.saveRevision({ description, source: "manual" });
|
||||
|
||||
return {
|
||||
|
||||
@@ -101,11 +101,10 @@ export const noteTools = defineTools({
|
||||
description: "Replace the entire content of a note. Use this to completely rewrite a note's content. For text notes, provide Markdown content.",
|
||||
inputSchema: z.object({
|
||||
noteId: z.string().describe("The ID of the note to update"),
|
||||
content: z.string().describe("The new content for the note (Markdown for text notes, plain text for code notes)"),
|
||||
changeDescription: z.string().describe("A concise description of what was changed and why (e.g. 'Fix typos in introduction', 'Add section on error handling'). Keep it short, under 100 characters.")
|
||||
content: z.string().describe("The new content for the note (Markdown for text notes, plain text for code notes)")
|
||||
}),
|
||||
mutates: true,
|
||||
execute: ({ noteId, content, changeDescription }) => {
|
||||
execute: ({ noteId, content }) => {
|
||||
const note = becca.getNote(noteId);
|
||||
if (!note) {
|
||||
return { error: "Note not found" };
|
||||
@@ -117,7 +116,7 @@ export const noteTools = defineTools({
|
||||
return { error: `Cannot update content for note type: ${note.type}` };
|
||||
}
|
||||
|
||||
note.saveRevision({ description: changeDescription, source: "llm" });
|
||||
note.saveRevision({ source: "llm" });
|
||||
setNoteContentFromLlm(note, content);
|
||||
return {
|
||||
success: true,
|
||||
@@ -131,11 +130,10 @@ export const noteTools = defineTools({
|
||||
description: "Append content to the end of an existing note. For text notes, provide Markdown content.",
|
||||
inputSchema: z.object({
|
||||
noteId: z.string().describe("The ID of the note to append to"),
|
||||
content: z.string().describe("The content to append (Markdown for text notes, plain text for code notes)"),
|
||||
changeDescription: z.string().describe("A concise description of what was appended (e.g. 'Add meeting notes for May 15', 'Append troubleshooting section'). Keep it short, under 100 characters.")
|
||||
content: z.string().describe("The content to append (Markdown for text notes, plain text for code notes)")
|
||||
}),
|
||||
mutates: true,
|
||||
execute: ({ noteId, content, changeDescription }) => {
|
||||
execute: ({ noteId, content }) => {
|
||||
const note = becca.getNote(noteId);
|
||||
if (!note) {
|
||||
return { error: "Note not found" };
|
||||
@@ -160,7 +158,7 @@ export const noteTools = defineTools({
|
||||
newContent = existingContent + (existingContent.endsWith("\n") ? "" : "\n") + content;
|
||||
}
|
||||
|
||||
note.saveRevision({ description: changeDescription, source: "llm" });
|
||||
note.saveRevision({ source: "llm" });
|
||||
note.setContent(newContent);
|
||||
return {
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user