mirror of
https://github.com/zadam/trilium.git
synced 2025-10-20 15:19:01 +02:00
fix(react/dialogs): some type errors
This commit is contained in:
parent
edd18b53d0
commit
bde270b73f
@ -13,6 +13,7 @@ import note_autocomplete, { Suggestion } from "../../services/note_autocomplete"
|
||||
import type { default as TextTypeWidget } from "../type_widgets/editable_text.js";
|
||||
import { logError } from "../../services/ws";
|
||||
import FormGroup from "../react/FormGroup.js";
|
||||
import { refToJQuerySelector } from "../react/react_utils";
|
||||
|
||||
type LinkType = "reference-link" | "external-link" | "hyper-link";
|
||||
|
||||
@ -26,7 +27,7 @@ function AddLinkDialogComponent({ text: _text, textTypeWidget }: AddLinkDialogPr
|
||||
const [ linkTitle, setLinkTitle ] = useState("");
|
||||
const hasSelection = textTypeWidget?.hasSelection();
|
||||
const [ linkType, setLinkType ] = useState<LinkType>(hasSelection ? "hyper-link" : "reference-link");
|
||||
const [ suggestion, setSuggestion ] = useState<Suggestion>(null);
|
||||
const [ suggestion, setSuggestion ] = useState<Suggestion | null>(null);
|
||||
|
||||
async function setDefaultLinkTitle(noteId: string) {
|
||||
const noteTitle = await tree.getNoteTitle(noteId);
|
||||
@ -60,7 +61,7 @@ function AddLinkDialogComponent({ text: _text, textTypeWidget }: AddLinkDialogPr
|
||||
}, [suggestion]);
|
||||
|
||||
function onShown() {
|
||||
const $autocompleteEl = $(autocompleteRef.current);
|
||||
const $autocompleteEl = refToJQuerySelector(autocompleteRef);
|
||||
if (!text) {
|
||||
note_autocomplete.showRecentNotes($autocompleteEl);
|
||||
} else {
|
||||
@ -74,11 +75,11 @@ function AddLinkDialogComponent({ text: _text, textTypeWidget }: AddLinkDialogPr
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
if (suggestion.notePath) {
|
||||
if (suggestion?.notePath) {
|
||||
// Handle note link
|
||||
closeActiveDialog();
|
||||
textTypeWidget?.addLink(suggestion.notePath, linkType === "reference-link" ? null : linkTitle);
|
||||
} else if (suggestion.externalLink) {
|
||||
} else if (suggestion?.externalLink) {
|
||||
// Handle external link
|
||||
closeActiveDialog();
|
||||
textTypeWidget?.addLink(suggestion.externalLink, linkTitle, true);
|
||||
|
@ -17,15 +17,19 @@ import toast from "../../services/toast";
|
||||
import NoteList from "../react/NoteList";
|
||||
|
||||
interface CloneToDialogProps {
|
||||
clonedNoteIds: string[];
|
||||
clonedNoteIds?: string[];
|
||||
}
|
||||
|
||||
function CloneToDialogComponent({ clonedNoteIds }: CloneToDialogProps) {
|
||||
const [ prefix, setPrefix ] = useState("");
|
||||
const [ suggestion, setSuggestion ] = useState<Suggestion>(null);
|
||||
const [ suggestion, setSuggestion ] = useState<Suggestion | null>(null);
|
||||
const autoCompleteRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
function onSubmit() {
|
||||
if (!clonedNoteIds) {
|
||||
return;
|
||||
}
|
||||
|
||||
const notePath = suggestion?.notePath;
|
||||
if (!notePath) {
|
||||
logError(t("clone_to.no_path_to_clone_to"));
|
||||
@ -64,7 +68,7 @@ function CloneToDialogComponent({ clonedNoteIds }: CloneToDialogProps) {
|
||||
|
||||
export default class CloneToDialog extends ReactBasicWidget {
|
||||
|
||||
private props: CloneToDialogProps;
|
||||
private props: CloneToDialogProps = {};
|
||||
|
||||
get component() {
|
||||
return <CloneToDialogComponent {...this.props} />;
|
||||
@ -75,7 +79,7 @@ export default class CloneToDialog extends ReactBasicWidget {
|
||||
noteIds = [appContext.tabManager.getActiveContextNoteId() ?? ""];
|
||||
}
|
||||
|
||||
const clonedNoteIds = [];
|
||||
const clonedNoteIds: string[] = [];
|
||||
|
||||
for (const noteId of noteIds) {
|
||||
if (!clonedNoteIds.includes(noteId)) {
|
||||
|
@ -20,6 +20,7 @@ function ConfirmDialogComponent({ title, message, callback, lastElementToFocus,
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="confirm-dialog"
|
||||
title={title ?? t("confirm.confirmation")}
|
||||
size="md"
|
||||
zIndex={2000}
|
||||
@ -93,7 +94,7 @@ export default class ConfirmDialog extends ReactBasicWidget {
|
||||
|
||||
private showDialog(title: string | null, message: MessageType, callback: ConfirmDialogCallback, isConfirmDeleteNoteBox: boolean) {
|
||||
this.props = {
|
||||
title: title,
|
||||
title: title ?? undefined,
|
||||
message: (typeof message === "object" && "length" in message ? message[0] : message),
|
||||
lastElementToFocus: (document.activeElement as HTMLElement),
|
||||
callback,
|
||||
|
@ -94,7 +94,7 @@ function DeletedNotes({ noteIdsToBeDeleted }: { noteIdsToBeDeleted: DeleteNotesP
|
||||
|
||||
useEffect(() => {
|
||||
froca.getNotes(noteIdsToBeDeleted).then(async (notes: FNote[]) => {
|
||||
const noteLinks = [];
|
||||
const noteLinks: string[] = [];
|
||||
|
||||
for (const note of notes) {
|
||||
noteLinks.push((await link.createLink(note.noteId, { showNotePath: true })).html());
|
||||
@ -121,7 +121,9 @@ function BrokenRelations({ brokenRelations }: { brokenRelations: DeleteNotesPrev
|
||||
const [ notesWithBrokenRelations, setNotesWithBrokenRelations ] = useState<BrokenRelationData[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const noteIds = brokenRelations.map(relation => relation.noteId);
|
||||
const noteIds = brokenRelations
|
||||
.map(relation => relation.noteId)
|
||||
.filter(noteId => noteId) as string[];
|
||||
froca.getNotes(noteIds).then(async (notes) => {
|
||||
const notesWithBrokenRelations: BrokenRelationData[] = [];
|
||||
for (const attr of brokenRelations) {
|
||||
@ -142,7 +144,7 @@ function BrokenRelations({ brokenRelations }: { brokenRelations: DeleteNotesPrev
|
||||
{brokenRelations.map((_, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
<span dangerouslySetInnerHTML={{ __html: t("delete_notes.deleted_relation_text", notesWithBrokenRelations[index]) }} />
|
||||
<span dangerouslySetInnerHTML={{ __html: t("delete_notes.deleted_relation_text", notesWithBrokenRelations[index] as unknown as Record<string, string>) }} />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useRef } from "react";
|
||||
import { openDialog } from "../../services/dialog.js";
|
||||
import { closeActiveDialog, openDialog } from "../../services/dialog.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import Button from "../react/Button.js";
|
||||
@ -31,7 +31,7 @@ function IncorrectCpuArchDialogComponent() {
|
||||
}
|
||||
}}/>
|
||||
<Button text={t("cpu_arch_warning.continue_anyway")}
|
||||
onClick={() => openDialog(null)} />
|
||||
onClick={() => closeActiveDialog()} />
|
||||
</>}
|
||||
>
|
||||
<p>{utils.isMac() ? t("cpu_arch_warning.message_macos") : t("cpu_arch_warning.message_windows")}</p>
|
||||
|
@ -6,6 +6,7 @@ import Modal from "../react/Modal";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
import { useRef } from "preact/compat";
|
||||
import { RawHtmlBlock } from "../react/RawHtml";
|
||||
|
||||
interface ShowInfoDialogProps {
|
||||
message?: string | HTMLElement;
|
||||
@ -31,7 +32,7 @@ function ShowInfoDialogComponent({ message, callback, lastElementToFocus }: Show
|
||||
onClick={() => closeActiveDialog()}
|
||||
/>}
|
||||
>
|
||||
<div className="info-dialog-content" dangerouslySetInnerHTML={{ __html: message ?? "" }}></div>
|
||||
<RawHtmlBlock className="info-dialog-content" html={message} />
|
||||
</Modal>);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import note_autocomplete, { Suggestion } from "../../services/note_autocomplete";
|
||||
import appContext from "../../components/app_context";
|
||||
import commandRegistry from "../../services/command_registry";
|
||||
import { refToJQuerySelector } from "../react/react_utils";
|
||||
|
||||
const KEEP_LAST_SEARCH_FOR_X_SECONDS = 120;
|
||||
|
||||
@ -37,7 +38,7 @@ function JumpToNoteDialogComponent({ mode }: JumpToNoteDialogProps) {
|
||||
}
|
||||
|
||||
function onShown() {
|
||||
const $autoComplete = $(autocompleteRef.current);
|
||||
const $autoComplete = refToJQuerySelector(autocompleteRef);
|
||||
switch (mode) {
|
||||
case "last-search":
|
||||
// Fall-through if there is no text, in order to display the recent notes.
|
||||
@ -85,7 +86,7 @@ function JumpToNoteDialogComponent({ mode }: JumpToNoteDialogProps) {
|
||||
|
||||
export default class JumpToNoteDialog extends ReactBasicWidget {
|
||||
|
||||
private lastOpenedTs: number;
|
||||
private lastOpenedTs?: number;
|
||||
private props: JumpToNoteDialogProps = {
|
||||
mode: "last-search"
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ import { Modal as BootstrapModal } from "bootstrap";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import FormTextBox from "../react/FormTextBox";
|
||||
import FormGroup from "../react/FormGroup";
|
||||
import { refToJQuerySelector } from "../react/react_utils";
|
||||
|
||||
// JQuery here is maintained for compatibility with existing code.
|
||||
interface ShownCallbackData {
|
||||
@ -44,10 +45,10 @@ function PromptDialogComponent({ title, message, shown: shownCallback, callback
|
||||
modalRef={modalRef} formRef={formRef}
|
||||
onShown={() => {
|
||||
shownCallback?.({
|
||||
$dialog: $(modalRef.current),
|
||||
$question: $(labelRef.current),
|
||||
$answer: $(answerRef.current),
|
||||
$form: $(formRef.current) as JQuery<HTMLFormElement>
|
||||
$dialog: refToJQuerySelector(modalRef),
|
||||
$question: refToJQuerySelector(labelRef),
|
||||
$answer: refToJQuerySelector(answerRef),
|
||||
$form: refToJQuerySelector(formRef)
|
||||
});
|
||||
answerRef.current?.focus();
|
||||
}}
|
||||
@ -72,7 +73,7 @@ function PromptDialogComponent({ title, message, shown: shownCallback, callback
|
||||
|
||||
export default class PromptDialog extends ReactBasicWidget {
|
||||
|
||||
private props: PromptDialogProps;
|
||||
private props: PromptDialogProps = {};
|
||||
|
||||
get component() {
|
||||
return <PromptDialogComponent {...this.props} />;
|
||||
|
@ -180,7 +180,7 @@ function RevisionContent({ revisionItem, fullRevision }: { revisionItem?: Revisi
|
||||
|
||||
switch (revisionItem.type) {
|
||||
case "text": {
|
||||
const contentRef = useRef<HTMLDivElement>();
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (contentRef.current?.querySelector("span.math-tex")) {
|
||||
renderMathInElement(contentRef.current, { trust: true });
|
||||
|
@ -2,7 +2,7 @@ import { ComponentChildren, RefObject } from "preact";
|
||||
|
||||
interface FormGroupProps {
|
||||
labelRef?: RefObject<HTMLLabelElement>;
|
||||
label: string;
|
||||
label?: string;
|
||||
title?: string;
|
||||
className?: string;
|
||||
children: ComponentChildren;
|
||||
@ -14,7 +14,7 @@ export default function FormGroup({ label, title, className, children, descripti
|
||||
<div className={`form-group ${className}`} title={title}
|
||||
style={{ "margin-bottom": "15px" }}>
|
||||
<label style={{ width: "100%" }} ref={labelRef}>
|
||||
<div style={{ "margin-bottom": "10px" }}>{label}</div>
|
||||
{label && <div style={{ "margin-bottom": "10px" }}>{label}</div> }
|
||||
{children}
|
||||
</label>
|
||||
|
||||
|
@ -1,7 +1,28 @@
|
||||
interface RawHtmlProps {
|
||||
html: string;
|
||||
className?: string;
|
||||
html: string | HTMLElement;
|
||||
}
|
||||
|
||||
export default function RawHtml({ html }: RawHtmlProps) {
|
||||
return <span dangerouslySetInnerHTML={{ __html: html }} />;
|
||||
export default function RawHtml({ className, html }: RawHtmlProps) {
|
||||
return <span
|
||||
className={className}
|
||||
dangerouslySetInnerHTML={getHtml(html)}
|
||||
/>;
|
||||
}
|
||||
|
||||
export function RawHtmlBlock({ className, html }: RawHtmlProps) {
|
||||
return <div
|
||||
className={className}
|
||||
dangerouslySetInnerHTML={getHtml(html)}
|
||||
/>
|
||||
}
|
||||
|
||||
function getHtml(html: string | HTMLElement) {
|
||||
if (typeof html !== "string") {
|
||||
html = html.outerHTML;
|
||||
}
|
||||
|
||||
return {
|
||||
__html: html
|
||||
};
|
||||
}
|
15
apps/client/src/widgets/react/react_utils.ts
Normal file
15
apps/client/src/widgets/react/react_utils.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { RefObject } from "preact";
|
||||
|
||||
/**
|
||||
* Takes in a React ref and returns a corresponding JQuery selector.
|
||||
*
|
||||
* @param ref the React ref from which to obtain the jQuery selector.
|
||||
* @returns the corresponding jQuery selector.
|
||||
*/
|
||||
export function refToJQuerySelector<T extends HTMLElement>(ref: RefObject<T> | null): JQuery<T> {
|
||||
if (ref?.current) {
|
||||
return $(ref.current);
|
||||
} else {
|
||||
return $();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user