chore(react/ribbon): display current note type

This commit is contained in:
Elian Doran 2025-08-21 20:38:19 +03:00
parent cabeb13adb
commit c0beab8a5d
No known key found for this signature in database
4 changed files with 70 additions and 55 deletions

View File

@ -14,8 +14,7 @@ const NOT_SELECTABLE_NOTE_TYPES = NOTE_TYPES.filter((nt) => nt.reserved || nt.st
const TPL = /*html*/` const TPL = /*html*/`
<div class="dropdown note-type-widget"> <div class="dropdown note-type-widget">
<button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle select-button note-type-button"> <button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle select-button note-type-button">
<span class="note-type-desc"></span> <span class=""></span>
<span class="caret"></span>
</button> </button>
</div> </div>
`; `;
@ -36,7 +35,6 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
this.$noteTypeButton = this.$widget.find(".note-type-button"); this.$noteTypeButton = this.$widget.find(".note-type-button");
this.$noteTypeDesc = this.$widget.find(".note-type-desc");
this.$widget.on("click", ".dropdown-item", () => this.dropdown.toggle()); this.$widget.on("click", ".dropdown-item", () => this.dropdown.toggle());
} }
@ -105,18 +103,7 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
} }
} }
async findTypeTitle(type: NoteType, mime: string) {
if (type === "code") {
const mimeTypes = mimeTypesService.getMimeTypes();
const found = mimeTypes.find((mt) => mt.mime === mime);
return found ? found.title : mime;
} else {
const noteType = NOTE_TYPES.find((nt) => nt.type === type);
return noteType ? noteType.title : type;
}
}
async save(type: NoteType, mime?: string) { async save(type: NoteType, mime?: string) {
if (type === this.note?.type && mime === this.note?.mime) { if (type === this.note?.type && mime === this.note?.mime) {

View File

@ -14,9 +14,10 @@ interface DropdownProps {
dropdownContainerClassName?: string; dropdownContainerClassName?: string;
hideToggleArrow?: boolean; hideToggleArrow?: boolean;
disabled?: boolean; disabled?: boolean;
text?: ComponentChildren;
} }
export default function Dropdown({ className, buttonClassName, isStatic, children, title, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, disabled }: DropdownProps) { export default function Dropdown({ className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, disabled }: DropdownProps) {
const dropdownRef = useRef<HTMLDivElement | null>(null); const dropdownRef = useRef<HTMLDivElement | null>(null);
const triggerRef = useRef<HTMLButtonElement | null>(null); const triggerRef = useRef<HTMLButtonElement | null>(null);
@ -56,7 +57,7 @@ export default function Dropdown({ className, buttonClassName, isStatic, childre
return ( return (
<div ref={dropdownRef} class={`dropdown ${className ?? ""}`} style={{ display: "flex" }}> <div ref={dropdownRef} class={`dropdown ${className ?? ""}`} style={{ display: "flex" }}>
<button <button
className={`btn ${buttonClassName ?? ""} ${!hideToggleArrow ? "dropdown-toggle" : ""}`} className={`btn select-button ${buttonClassName ?? ""} ${!hideToggleArrow ? "dropdown-toggle" : ""}`}
ref={triggerRef} ref={triggerRef}
type="button" type="button"
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
@ -66,7 +67,10 @@ export default function Dropdown({ className, buttonClassName, isStatic, childre
title={title} title={title}
id={ariaId} id={ariaId}
disabled={disabled} disabled={disabled}
/> >
{text}
<span className="caret"></span>
</button>
<div <div
class={`dropdown-menu ${isStatic ? "static" : ""} ${dropdownContainerClassName ?? ""} tn-dropdown-list`} class={`dropdown-menu ${isStatic ? "static" : ""} ${dropdownContainerClassName ?? ""} tn-dropdown-list`}

View File

@ -1,10 +1,11 @@
import { useCallback, useMemo } from "preact/hooks"; import { useMemo } from "preact/hooks";
import Dropdown from "../react/Dropdown"; import Dropdown from "../react/Dropdown";
import { NOTE_TYPES } from "../../services/note_types"; import { NOTE_TYPES } from "../../services/note_types";
import { FormDivider, FormListBadge, FormListItem } from "../react/FormList"; import { FormDivider, FormListBadge, FormListItem } from "../react/FormList";
import { t } from "../../services/i18n"; import { t } from "../../services/i18n";
import { useTriliumOption } from "../react/hooks"; import { useNoteContext, useNoteProperty, useTriliumOption } from "../react/hooks";
import mime_types from "../../services/mime_types"; import mime_types from "../../services/mime_types";
import { NoteType } from "@triliumnext/commons";
export default function BasicPropertiesTab() { export default function BasicPropertiesTab() {
return ( return (
@ -18,44 +19,67 @@ function NoteTypeWidget() {
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []); const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes"); const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
const mimeTypes = useMemo(() => mime_types.getMimeTypes().filter(mimeType => mimeType.enabled), [ codeNotesMimeTypes ]); const mimeTypes = useMemo(() => mime_types.getMimeTypes().filter(mimeType => mimeType.enabled), [ codeNotesMimeTypes ]);
const { note } = useNoteContext();
const type = useNoteProperty(note, "type") ?? undefined;
const mime = useNoteProperty(note, "mime");
return ( return (
<Dropdown dropdownContainerClassName="note-type-dropdown"> <>
{noteTypes.map(noteType => { <span>{t("basic_properties.note_type")}:</span> &nbsp;
const badges: FormListBadge[] = []; <Dropdown
if (noteType.isNew) { dropdownContainerClassName="note-type-dropdown"
badges.push({ text={<span className="note-type-desc">{findTypeTitle(type, mime)}</span>}
className: "new-note-type-badge", >
text: t("note_types.new-feature") {noteTypes.map(noteType => {
}); const badges: FormListBadge[] = [];
} if (noteType.isNew) {
if (noteType.isBeta) { badges.push({
badges.push({ className: "new-note-type-badge",
text: t("note_types.beta-feature") text: t("note_types.new-feature")
}); });
} }
if (noteType.isBeta) {
badges.push({
text: t("note_types.beta-feature")
});
}
if (noteType.type !== "code") { if (noteType.type !== "code") {
return ( return (
<FormListItem <FormListItem
badges={badges} badges={badges}
>{noteType.title}</FormListItem> >{noteType.title}</FormListItem>
); );
} else { } else {
return ( return (
<> <>
<FormDivider /> <FormDivider />
<FormListItem disabled> <FormListItem disabled>
<strong>{noteType.title}</strong> <strong>{noteType.title}</strong>
</FormListItem> </FormListItem>
</> </>
) )
} }
})} })}
{mimeTypes.map(mimeType => ( {mimeTypes.map(mimeType => (
<FormListItem>{mimeType.title}</FormListItem> <FormListItem>{mimeType.title}</FormListItem>
))} ))}
</Dropdown> </Dropdown>
</>
) )
}
function findTypeTitle(type?: NoteType, mime?: string) {
if (type === "code") {
const mimeTypes = mime_types.getMimeTypes();
const found = mimeTypes.find((mt) => mt.mime === mime);
return found ? found.title : mime;
} else {
const noteType = NOTE_TYPES.find((nt) => nt.type === type);
return noteType ? noteType.title : type;
}
} }

View File

@ -11,7 +11,7 @@ import NoteLanguageWidget from "../note_language.js";
const TPL = /*html*/` const TPL = /*html*/`
<div class="note-type-container"> <div class="note-type-container">
<span>${t("basic_properties.note_type")}:</span> &nbsp;
</div> </div>
<div class="protected-note-switch-container"></div> <div class="protected-note-switch-container"></div>