mirror of
https://github.com/zadam/trilium.git
synced 2025-10-28 10:08:52 +01:00
refactor(react/dialogs): integrate proper closing of modal
This commit is contained in:
parent
b7482f2a6a
commit
da1f18c60f
@ -1,4 +1,3 @@
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Modal from "../react/Modal";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
@ -80,11 +79,11 @@ function AddLinkDialogComponent() {
|
||||
function onSubmit() {
|
||||
if (suggestion?.notePath) {
|
||||
// Handle note link
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
textTypeWidget?.addLink(suggestion.notePath, linkType === "reference-link" ? null : linkTitle);
|
||||
} else if (suggestion?.externalLink) {
|
||||
// Handle external link
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
textTypeWidget?.addLink(suggestion.externalLink, linkTitle, true);
|
||||
} else {
|
||||
logError("No link to add.");
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import appContext from "../../components/app_context.js";
|
||||
import { closeActiveDialog } from "../../services/dialog.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import server from "../../services/server.js";
|
||||
import toast from "../../services/toast.js";
|
||||
@ -50,7 +49,7 @@ function BranchPrefixDialogComponent() {
|
||||
}
|
||||
|
||||
savePrefix(branch.branchId, prefix);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Modal from "../react/Modal";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
@ -64,7 +63,7 @@ function BulkActionComponent() {
|
||||
});
|
||||
|
||||
toast.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}}
|
||||
onHidden={() => setShown(false)}
|
||||
>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useRef, useState } from "preact/compat";
|
||||
import appContext from "../../components/app_context";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Modal from "../react/Modal";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
@ -52,7 +51,7 @@ function CloneToDialogComponent() {
|
||||
return;
|
||||
}
|
||||
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
cloneNotesTo(notePath, clonedNoteIds, prefix);
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import Modal from "../react/Modal";
|
||||
import Button from "../react/Button";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import { useState } from "react";
|
||||
import FormCheckbox from "../react/FormCheckbox";
|
||||
@ -48,10 +47,10 @@ function ConfirmDialogComponent() {
|
||||
setShown(false);
|
||||
}}
|
||||
footer={<>
|
||||
<Button text={t("confirm.cancel")} onClick={() => closeActiveDialog()} />
|
||||
<Button text={t("confirm.cancel")} onClick={() => setShown(false)} />
|
||||
<Button text={t("confirm.ok")} onClick={() => {
|
||||
setConfirmed(true);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}} />
|
||||
</>}
|
||||
show={shown}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import FormCheckbox from "../react/FormCheckbox.js";
|
||||
import Modal from "../react/Modal.js";
|
||||
@ -74,12 +73,12 @@ function DeleteNotesDialogComponent() {
|
||||
}}
|
||||
footer={<>
|
||||
<Button text={t("delete_notes.cancel")}
|
||||
onClick={() => closeActiveDialog()} />
|
||||
onClick={() => setShown(false)} />
|
||||
<Button text={t("delete_notes.ok")} primary
|
||||
buttonRef={okButtonRef}
|
||||
onClick={() => {
|
||||
opts.callback?.({ proceed: true, deleteAllClones, eraseNotes });
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}} />
|
||||
</>}
|
||||
show={shown}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import tree from "../../services/tree";
|
||||
import Button from "../react/Button";
|
||||
@ -57,7 +56,7 @@ function ExportDialogComponent() {
|
||||
const format = (exportType === "subtree" ? subtreeFormat : singleFormat);
|
||||
const version = (format === "opml" ? opmlVersion : "1.0");
|
||||
exportBranch(opts.branchId, exportType, format, version);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}}
|
||||
onHidden={() => setShown(false)}
|
||||
footer={<Button className="export-button" text={t("export.export")} primary />}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import tree from "../../services/tree";
|
||||
import Button from "../react/Button";
|
||||
@ -49,7 +48,7 @@ function ImportDialogComponent() {
|
||||
replaceUnderscoresWithSpaces: boolToString(replaceUnderscoresWithSpaces)
|
||||
};
|
||||
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
await importService.uploadFiles("notes", parentNoteId, Array.from(files), options);
|
||||
}}
|
||||
onHidden={() => setShown(false)}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useRef, useState } from "preact/compat";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import FormGroup from "../react/FormGroup";
|
||||
import FormRadioGroup from "../react/FormRadioGroup";
|
||||
@ -38,7 +37,7 @@ function IncludeNoteDialogComponent() {
|
||||
return;
|
||||
}
|
||||
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
includeNote(suggestion.notePath, textTypeWidget);
|
||||
}}
|
||||
footer={<Button text={t("include_note.button_include")} keyboardShortcut="Enter" />}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useRef } from "react";
|
||||
import { closeActiveDialog } from "../../services/dialog.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import Button from "../react/Button.js";
|
||||
@ -35,7 +34,7 @@ function IncorrectCpuArchDialogComponent() {
|
||||
}
|
||||
}}/>
|
||||
<Button text={t("cpu_arch_warning.continue_anyway")}
|
||||
onClick={() => closeActiveDialog()} />
|
||||
onClick={() => setShown(false)} />
|
||||
</>}
|
||||
onHidden={() => setShown(false)}
|
||||
show={shown}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { EventData } from "../../components/app_context";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import Modal from "../react/Modal";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
@ -30,7 +29,7 @@ function ShowInfoDialogComponent() {
|
||||
footer={<Button
|
||||
buttonRef={okButtonRef}
|
||||
text={t("info.okButton")}
|
||||
onClick={() => closeActiveDialog()}
|
||||
onClick={() => setShown(false)}
|
||||
/>}
|
||||
show={shown}
|
||||
>
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import Modal from "../react/Modal";
|
||||
import Button from "../react/Button";
|
||||
@ -54,10 +53,10 @@ function JumpToNoteDialogComponent() {
|
||||
}, [ text ]);
|
||||
|
||||
async function onItemSelected(suggestion: Suggestion) {
|
||||
setShown(false);
|
||||
if (suggestion.notePath) {
|
||||
appContext.tabManager.getActiveContext()?.setNote(suggestion.notePath);
|
||||
} else if (suggestion.commandId) {
|
||||
closeActiveDialog();
|
||||
await commandRegistry.executeCommand(suggestion.commandId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { useCallback, useRef, useState } from "preact/compat";
|
||||
import appContext from "../../components/app_context";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import server from "../../services/server";
|
||||
import toast from "../../services/toast";
|
||||
@ -40,7 +39,7 @@ function MarkdownImportDialogComponent() {
|
||||
async function sendForm() {
|
||||
await convertMarkdownToHtml(text);
|
||||
setText("");
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import Modal from "../react/Modal";
|
||||
import { t } from "../../services/i18n";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import NoteList from "../react/NoteList";
|
||||
import FormGroup from "../react/FormGroup";
|
||||
import NoteAutocomplete from "../react/NoteAutocomplete";
|
||||
@ -32,7 +31,7 @@ function MoveToDialogComponent() {
|
||||
return;
|
||||
}
|
||||
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
const { noteId, parentNoteId } = tree.getNoteIdAndParentIdFromUrl(notePath);
|
||||
if (!parentNoteId) {
|
||||
return;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import Modal from "../react/Modal";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import FormGroup from "../react/FormGroup";
|
||||
import NoteAutocomplete from "../react/NoteAutocomplete";
|
||||
@ -67,7 +66,7 @@ function NoteTypeChooserDialogComponent() {
|
||||
templateNoteId,
|
||||
notePath: parentNote?.notePath
|
||||
});
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import Modal from "../react/Modal";
|
||||
import { t } from "../../services/i18n";
|
||||
@ -16,7 +15,7 @@ function PasswordNotSetDialogComponent() {
|
||||
size="md" className="password-not-set-dialog"
|
||||
title={t("password_not_set.title")}
|
||||
footer={<Button icon="bx bx-lock" text={t("password_not_set.go_to_password_options")} onClick={() => {
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
appContext.triggerCommand("showOptions", { section: "_optionsPassword" });
|
||||
}} />}
|
||||
onHidden={() => setShown(false)}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
import FormTextBox from "../react/FormTextBox";
|
||||
@ -14,6 +13,7 @@ function ProtectedSessionPasswordDialogComponent() {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useTriliumEvent("showProtectedSessionPasswordDialog", () => setShown(true));
|
||||
useTriliumEvent("closeProtectedSessionPasswordDialog", () => setShown(false));
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@ -45,8 +45,4 @@ export default class ProtectedSessionPasswordDialog extends ReactBasicWidget {
|
||||
return <ProtectedSessionPasswordDialogComponent />;
|
||||
}
|
||||
|
||||
closeProtectedSessionPasswordDialogEvent() {
|
||||
closeActiveDialog();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { Dispatch, StateUpdater, useEffect, useState } from "preact/hooks";
|
||||
import appContext from "../../components/app_context";
|
||||
import dialog, { closeActiveDialog } from "../../services/dialog";
|
||||
import dialog from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import server from "../../services/server";
|
||||
import toast from "../../services/toast";
|
||||
@ -71,14 +71,14 @@ function RecentChangesDialogComponent() {
|
||||
>
|
||||
<div className="recent-changes-content">
|
||||
{groupedByDate?.size
|
||||
? <RecentChangesTimeline groupedByDate={groupedByDate} />
|
||||
? <RecentChangesTimeline groupedByDate={groupedByDate} setShown={setShown} />
|
||||
: <>{t("recent_changes.no_changes_message")}</>}
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
function RecentChangesTimeline({ groupedByDate }: { groupedByDate: Map<String, RecentChangesRow[]> }) {
|
||||
function RecentChangesTimeline({ groupedByDate, setShown }: { groupedByDate: Map<String, RecentChangesRow[]>, setShown: Dispatch<StateUpdater<boolean>> }) {
|
||||
return (
|
||||
<>
|
||||
{ Array.from(groupedByDate.entries()).map(([dateDay, dayChanges]) => {
|
||||
@ -100,7 +100,7 @@ function RecentChangesTimeline({ groupedByDate }: { groupedByDate: Map<String, R
|
||||
<span title={change.date}>{formattedTime}</span>
|
||||
{ !isDeleted
|
||||
? <NoteLink notePath={notePath} title={change.current_title} />
|
||||
: <DeletedNoteLink change={change} /> }
|
||||
: <DeletedNoteLink change={change} setShown={setShown} /> }
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
@ -129,7 +129,7 @@ function NoteLink({ notePath, title }: { notePath: string, title: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function DeletedNoteLink({ change }: { change: RecentChangesRow }) {
|
||||
function DeletedNoteLink({ change, setShown }: { change: RecentChangesRow, setShown: Dispatch<StateUpdater<boolean>> }) {
|
||||
return (
|
||||
<>
|
||||
<span className="note-title">{change.current_title}</span>
|
||||
@ -141,7 +141,7 @@ function DeletedNoteLink({ change }: { change: RecentChangesRow }) {
|
||||
|
||||
if (await dialog.confirm(text)) {
|
||||
await server.put(`notes/${change.noteId}/undelete`);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { RevisionPojo, RevisionItem } from "@triliumnext/commons";
|
||||
import appContext from "../../components/app_context";
|
||||
import FNote from "../../entities/fnote";
|
||||
import dialog, { closeActiveDialog } from "../../services/dialog";
|
||||
import dialog from "../../services/dialog";
|
||||
import froca from "../../services/froca";
|
||||
import { t } from "../../services/i18n";
|
||||
import server from "../../services/server";
|
||||
@ -11,7 +11,7 @@ import Modal from "../react/Modal";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import FormList, { FormListItem } from "../react/FormList";
|
||||
import utils from "../../services/utils";
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
|
||||
import protected_session_holder from "../../services/protected_session_holder";
|
||||
import { renderMathInElement } from "../../services/math";
|
||||
import { CSSProperties } from "preact/compat";
|
||||
@ -61,7 +61,7 @@ function RevisionsDialogComponent() {
|
||||
if (note && await dialog.confirm(text)) {
|
||||
await server.remove(`notes/${note.noteId}/revisions`);
|
||||
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
toast.showMessage(t("revisions.revisions_deleted"));
|
||||
}
|
||||
}}/>)
|
||||
@ -91,7 +91,7 @@ function RevisionsDialogComponent() {
|
||||
flexDirection: "column",
|
||||
minWidth: 0
|
||||
}}>
|
||||
<RevisionPreview revisionItem={currentRevision} />
|
||||
<RevisionPreview revisionItem={currentRevision} setShown={setShown} />
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
@ -111,7 +111,7 @@ function RevisionsList({ revisions, onSelect }: { revisions: RevisionItem[], onS
|
||||
</FormList>);
|
||||
}
|
||||
|
||||
function RevisionPreview({ revisionItem }: { revisionItem?: RevisionItem}) {
|
||||
function RevisionPreview({ revisionItem, setShown }: { revisionItem?: RevisionItem, setShown: Dispatch<StateUpdater<boolean>>}) {
|
||||
const [ fullRevision, setFullRevision ] = useState<RevisionPojo>();
|
||||
const [ needsRefresh, setNeedsRefresh ] = useState<boolean>();
|
||||
|
||||
@ -137,7 +137,7 @@ function RevisionPreview({ revisionItem }: { revisionItem?: RevisionItem}) {
|
||||
onClick={async () => {
|
||||
if (await dialog.confirm(t("revisions.confirm_restore"))) {
|
||||
await server.post(`revisions/${revisionItem.revisionId}/restore`);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
toast.showMessage(t("revisions.revision_restored"));
|
||||
}
|
||||
}}/>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
import FormCheckbox from "../react/FormCheckbox";
|
||||
@ -34,8 +33,7 @@ function SortChildNotesDialogComponent() {
|
||||
sortLocale
|
||||
});
|
||||
|
||||
// Close the dialog after submission
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useEffect, useState } from "preact/compat";
|
||||
import { closeActiveDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
import FormCheckbox from "../react/FormCheckbox";
|
||||
@ -47,7 +46,7 @@ function UploadAttachmentsDialogComponent() {
|
||||
const filesCopy = Array.from(files);
|
||||
await importService.uploadFiles("attachments", parentNoteId, filesCopy, { shrinkImages });
|
||||
setIsUploading(false);
|
||||
closeActiveDialog();
|
||||
setShown(false);
|
||||
}}
|
||||
onHidden={() => setShown(false)}
|
||||
show={shown}
|
||||
|
||||
@ -4,6 +4,7 @@ import { ComponentChildren } from "preact";
|
||||
import type { CSSProperties, RefObject } from "preact/compat";
|
||||
import { openDialog } from "../../services/dialog";
|
||||
import { ParentComponent } from "./ReactBasicWidget";
|
||||
import { Modal as BootstrapModal } from "bootstrap";
|
||||
|
||||
interface ModalProps {
|
||||
className: string;
|
||||
@ -52,6 +53,7 @@ interface ModalProps {
|
||||
|
||||
export default function Modal({ children, className, size, title, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: _modalRef, formRef: _formRef, bodyStyle, show }: ModalProps) {
|
||||
const modalRef = _modalRef ?? useRef<HTMLDivElement>(null);
|
||||
const modalInstanceRef = useRef<BootstrapModal>();
|
||||
const formRef = _formRef ?? useRef<HTMLFormElement>(null);
|
||||
const parentWidget = useContext(ParentComponent);
|
||||
|
||||
@ -79,8 +81,15 @@ export default function Modal({ children, className, size, title, header, footer
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (show && parentWidget) {
|
||||
openDialog(parentWidget.$widget);
|
||||
if (!parentWidget) {
|
||||
return;
|
||||
}
|
||||
if (show) {
|
||||
openDialog(parentWidget.$widget).then(($widget) => {
|
||||
modalInstanceRef.current = BootstrapModal.getOrCreateInstance($widget[0]);
|
||||
})
|
||||
} else {
|
||||
modalInstanceRef.current?.hide();
|
||||
}
|
||||
}, [ show ]);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user