mirror of
https://github.com/zadam/trilium.git
synced 2025-12-17 04:44:23 +01:00
chore(layout): support for similar notes in the status bar
This commit is contained in:
parent
42bde3873b
commit
f1bb786a49
@ -826,7 +826,8 @@
|
|||||||
"note_size_info": "Note size provides rough estimate of storage requirements for this note. It takes into account note's content and content of its note revisions.",
|
"note_size_info": "Note size provides rough estimate of storage requirements for this note. It takes into account note's content and content of its note revisions.",
|
||||||
"calculate": "calculate",
|
"calculate": "calculate",
|
||||||
"subtree_size": "(subtree size: {{size}} in {{count}} notes)",
|
"subtree_size": "(subtree size: {{size}} in {{count}} notes)",
|
||||||
"title": "Note Info"
|
"title": "Note Info",
|
||||||
|
"show_similar_notes": "Show similar notes"
|
||||||
},
|
},
|
||||||
"note_map": {
|
"note_map": {
|
||||||
"open_full": "Expand to full",
|
"open_full": "Expand to full",
|
||||||
|
|||||||
@ -57,9 +57,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-note-info {
|
.dropdown-note-info {
|
||||||
|
padding: 1em !important;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding: 0.5em;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: table;
|
display: table;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import "./StatusBar.css";
|
import "./StatusBar.css";
|
||||||
|
|
||||||
import { Locale } from "@triliumnext/commons";
|
import { Locale } from "@triliumnext/commons";
|
||||||
|
import { Dropdown as BootstrapDropdown } from "bootstrap";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { type ComponentChildren } from "preact";
|
import { type ComponentChildren } from "preact";
|
||||||
import { createPortal } from "preact/compat";
|
import { createPortal } from "preact/compat";
|
||||||
@ -16,16 +17,19 @@ import server from "../../services/server";
|
|||||||
import { openInAppHelpFromUrl } from "../../services/utils";
|
import { openInAppHelpFromUrl } from "../../services/utils";
|
||||||
import { formatDateTime } from "../../utils/formatters";
|
import { formatDateTime } from "../../utils/formatters";
|
||||||
import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions";
|
import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions";
|
||||||
|
import Collapsible from "../react/Collapsible";
|
||||||
import Dropdown, { DropdownProps } from "../react/Dropdown";
|
import Dropdown, { DropdownProps } from "../react/Dropdown";
|
||||||
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
||||||
import { useActiveNoteContext, useLegacyImperativeHandlers, useNoteLabel, useNoteProperty, useStaticTooltip, useTriliumEvent, useTriliumEvents } from "../react/hooks";
|
import { useActiveNoteContext, useLegacyImperativeHandlers, useNoteLabel, useNoteProperty, useStaticTooltip, useTriliumEvent, useTriliumEvents } from "../react/hooks";
|
||||||
import Icon from "../react/Icon";
|
import Icon from "../react/Icon";
|
||||||
|
import LinkButton from "../react/LinkButton";
|
||||||
import { ParentComponent } from "../react/react_utils";
|
import { ParentComponent } from "../react/react_utils";
|
||||||
import { ContentLanguagesModal, NoteTypeCodeNoteList, NoteTypeOptionsModal, useLanguageSwitcher, useMimeTypes } from "../ribbon/BasicPropertiesTab";
|
import { ContentLanguagesModal, NoteTypeCodeNoteList, NoteTypeOptionsModal, useLanguageSwitcher, useMimeTypes } from "../ribbon/BasicPropertiesTab";
|
||||||
import AttributeEditor, { AttributeEditorImperativeHandlers } from "../ribbon/components/AttributeEditor";
|
import AttributeEditor, { AttributeEditorImperativeHandlers } from "../ribbon/components/AttributeEditor";
|
||||||
import InheritedAttributesTab from "../ribbon/InheritedAttributesTab";
|
import InheritedAttributesTab from "../ribbon/InheritedAttributesTab";
|
||||||
import { NoteSizeWidget, useNoteMetadata } from "../ribbon/NoteInfoTab";
|
import { NoteSizeWidget, useNoteMetadata } from "../ribbon/NoteInfoTab";
|
||||||
import { NotePathsWidget, useSortedNotePaths } from "../ribbon/NotePathsTab";
|
import { NotePathsWidget, useSortedNotePaths } from "../ribbon/NotePathsTab";
|
||||||
|
import SimilarNotesTab from "../ribbon/SimilarNotesTab";
|
||||||
import { useAttachments } from "../type_widgets/Attachment";
|
import { useAttachments } from "../type_widgets/Attachment";
|
||||||
import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector";
|
import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector";
|
||||||
import Breadcrumb from "./Breadcrumb";
|
import Breadcrumb from "./Breadcrumb";
|
||||||
@ -41,6 +45,7 @@ interface StatusBarContext {
|
|||||||
export default function StatusBar() {
|
export default function StatusBar() {
|
||||||
const { note, notePath, noteContext, viewScope, hoistedNoteId } = useActiveNoteContext();
|
const { note, notePath, noteContext, viewScope, hoistedNoteId } = useActiveNoteContext();
|
||||||
const [ attributesShown, setAttributesShown ] = useState(false);
|
const [ attributesShown, setAttributesShown ] = useState(false);
|
||||||
|
const [ similarNotesShown, setSimilarNotesShown ] = useState(false);
|
||||||
const context: StatusBarContext | undefined | null = note && noteContext && { note, notePath, noteContext, viewScope, hoistedNoteId };
|
const context: StatusBarContext | undefined | null = note && noteContext && { note, notePath, noteContext, viewScope, hoistedNoteId };
|
||||||
const attributesContext: AttributesProps | undefined | null = context && { ...context, attributesShown, setAttributesShown };
|
const attributesContext: AttributesProps | undefined | null = context && { ...context, attributesShown, setAttributesShown };
|
||||||
const isHiddenNote = note?.isInHiddenSubtree();
|
const isHiddenNote = note?.isInHiddenSubtree();
|
||||||
@ -48,6 +53,7 @@ export default function StatusBar() {
|
|||||||
return (
|
return (
|
||||||
<div className="status-bar">
|
<div className="status-bar">
|
||||||
{attributesContext && <AttributesPane {...attributesContext} />}
|
{attributesContext && <AttributesPane {...attributesContext} />}
|
||||||
|
{context && <SimilarNotesPane {...context} shown={similarNotesShown} setShown={setSimilarNotesShown}/>}
|
||||||
|
|
||||||
<div className="status-bar-main-row">
|
<div className="status-bar-main-row">
|
||||||
{context && attributesContext && <>
|
{context && attributesContext && <>
|
||||||
@ -60,7 +66,7 @@ export default function StatusBar() {
|
|||||||
<AttributesButton {...attributesContext} />
|
<AttributesButton {...attributesContext} />
|
||||||
<AttachmentCount {...context} />
|
<AttachmentCount {...context} />
|
||||||
<BacklinksBadge {...context} />
|
<BacklinksBadge {...context} />
|
||||||
<NoteInfoBadge {...context} />
|
<NoteInfoBadge {...context} showSimilarNotes={() => setSimilarNotesShown(true)} />
|
||||||
</div>
|
</div>
|
||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
@ -197,7 +203,10 @@ export function getLocaleName(locale: Locale | null | undefined) {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Note info
|
//#region Note info
|
||||||
export function NoteInfoBadge({ note }: { note: FNote | null | undefined }) {
|
export function NoteInfoBadge({ note, showSimilarNotes }: StatusBarContext & {
|
||||||
|
showSimilarNotes: () => void
|
||||||
|
}) {
|
||||||
|
const dropdownRef = useRef<BootstrapDropdown>(null);
|
||||||
const { metadata, ...sizeProps } = useNoteMetadata(note);
|
const { metadata, ...sizeProps } = useNoteMetadata(note);
|
||||||
const [ originalFileName ] = useNoteLabel(note, "originalFileName");
|
const [ originalFileName ] = useNoteLabel(note, "originalFileName");
|
||||||
|
|
||||||
@ -205,6 +214,7 @@ export function NoteInfoBadge({ note }: { note: FNote | null | undefined }) {
|
|||||||
<StatusBarDropdown
|
<StatusBarDropdown
|
||||||
icon="bx bx-info-circle"
|
icon="bx bx-info-circle"
|
||||||
title={t("status_bar.note_info_title")}
|
title={t("status_bar.note_info_title")}
|
||||||
|
dropdownRef={dropdownRef}
|
||||||
dropdownContainerClassName="dropdown-note-info"
|
dropdownContainerClassName="dropdown-note-info"
|
||||||
dropdownOptions={{ autoClose: "outside" }}
|
dropdownOptions={{ autoClose: "outside" }}
|
||||||
>
|
>
|
||||||
@ -216,6 +226,14 @@ export function NoteInfoBadge({ note }: { note: FNote | null | undefined }) {
|
|||||||
<NoteInfoValue text={t("note_info_widget.note_id")} value={<code>{note.noteId}</code>} />
|
<NoteInfoValue text={t("note_info_widget.note_id")} value={<code>{note.noteId}</code>} />
|
||||||
<NoteInfoValue text={t("note_info_widget.note_size")} title={t("note_info_widget.note_size_info")} value={<NoteSizeWidget {...sizeProps} />} />
|
<NoteInfoValue text={t("note_info_widget.note_size")} title={t("note_info_widget.note_size_info")} value={<NoteSizeWidget {...sizeProps} />} />
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<LinkButton
|
||||||
|
text={t("note_info_widget.show_similar_notes")}
|
||||||
|
onClick={() => {
|
||||||
|
dropdownRef.current?.hide();
|
||||||
|
showSimilarNotes();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</StatusBarDropdown>
|
</StatusBarDropdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -228,6 +246,17 @@ function NoteInfoValue({ text, title, value }: { text: string; title?: string, v
|
|||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SimilarNotesPane({ note, shown }: StatusBarContext & {
|
||||||
|
shown: boolean;
|
||||||
|
setShown: (value: boolean) => void;
|
||||||
|
}) {
|
||||||
|
return (shown &&
|
||||||
|
<div className="similar-notes-pane">
|
||||||
|
<SimilarNotesTab note={note} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Backlinks
|
//#region Backlinks
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { useEffect, useState } from "preact/hooks";
|
|
||||||
import { TabContext } from "./ribbon-interface";
|
|
||||||
import { SimilarNoteResponse } from "@triliumnext/commons";
|
import { SimilarNoteResponse } from "@triliumnext/commons";
|
||||||
import server from "../../services/server";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { t } from "../../services/i18n";
|
|
||||||
import froca from "../../services/froca";
|
|
||||||
import NoteLink from "../react/NoteLink";
|
|
||||||
|
|
||||||
export default function SimilarNotesTab({ note }: TabContext) {
|
import froca from "../../services/froca";
|
||||||
|
import { t } from "../../services/i18n";
|
||||||
|
import server from "../../services/server";
|
||||||
|
import NoteLink from "../react/NoteLink";
|
||||||
|
import { TabContext } from "./ribbon-interface";
|
||||||
|
|
||||||
|
export default function SimilarNotesTab({ note }: Pick<TabContext, "note">) {
|
||||||
const [ similarNotes, setSimilarNotes ] = useState<SimilarNoteResponse>();
|
const [ similarNotes, setSimilarNotes ] = useState<SimilarNoteResponse>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -17,7 +18,7 @@ export default function SimilarNotesTab({ note }: TabContext) {
|
|||||||
await froca.getNotes(noteIds, true); // preload all at once
|
await froca.getNotes(noteIds, true); // preload all at once
|
||||||
}
|
}
|
||||||
setSimilarNotes(similarNotes);
|
setSimilarNotes(similarNotes);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [ note?.noteId ]);
|
}, [ note?.noteId ]);
|
||||||
@ -42,5 +43,5 @@ export default function SimilarNotesTab({ note }: TabContext) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user