mirror of
https://github.com/zadam/trilium.git
synced 2025-12-12 18:34:24 +01:00
feat(note_actions): integrate note type
This commit is contained in:
parent
77f5770bff
commit
6f85b7cc09
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
|
import { Dispatch, StateUpdater, useCallback, useEffect, useMemo, useState } 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 { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
|
import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
|
||||||
@ -28,7 +28,7 @@ const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
|||||||
export default function BasicPropertiesTab({ note }: TabContext) {
|
export default function BasicPropertiesTab({ note }: TabContext) {
|
||||||
return (
|
return (
|
||||||
<div className="basic-properties-widget">
|
<div className="basic-properties-widget">
|
||||||
<NoteTypeWidget note={note} />
|
{!isNewLayout && <NoteTypeWidget note={note} />}
|
||||||
{!isNewLayout && <ProtectedNoteSwitch note={note} />}
|
{!isNewLayout && <ProtectedNoteSwitch note={note} />}
|
||||||
{!isNewLayout && <EditabilitySelect note={note} />}
|
{!isNewLayout && <EditabilitySelect note={note} />}
|
||||||
{!isNewLayout && <BookmarkSwitch note={note} />}
|
{!isNewLayout && <BookmarkSwitch note={note} />}
|
||||||
@ -40,18 +40,42 @@ export default function BasicPropertiesTab({ note }: TabContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
||||||
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
|
|
||||||
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
|
||||||
const mimeTypes = useMemo(() => {
|
|
||||||
mime_types.loadMimeTypes();
|
|
||||||
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled)
|
|
||||||
}, [ codeNotesMimeTypes ]);
|
|
||||||
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []);
|
||||||
|
|
||||||
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
||||||
const currentNoteMime = useNoteProperty(note, "mime");
|
const currentNoteMime = useNoteProperty(note, "mime");
|
||||||
const [ modalShown, setModalShown ] = useState(false);
|
const [ modalShown, setModalShown ] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="note-type-container">
|
||||||
|
<span>{t("basic_properties.note_type")}:</span>
|
||||||
|
<Dropdown
|
||||||
|
dropdownContainerClassName="note-type-dropdown"
|
||||||
|
text={<span className="note-type-desc">{findTypeTitle(currentNoteType, currentNoteMime)}</span>}
|
||||||
|
disabled={notSelectableNoteTypes.includes(currentNoteType ?? "text")}
|
||||||
|
>
|
||||||
|
<NoteTypeDropdownContent currentNoteType={currentNoteType} currentNoteMime={currentNoteMime} note={note} setModalShown={setModalShown} />
|
||||||
|
</Dropdown>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
className="code-mime-types-modal"
|
||||||
|
title={t("code_mime_types.title")}
|
||||||
|
show={modalShown} onHidden={() => setModalShown(false)}
|
||||||
|
size="xl" scrollable
|
||||||
|
>
|
||||||
|
<CodeMimeTypesList />
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NoteTypeDropdownContent({ currentNoteType, currentNoteMime, note, setModalShown }: { currentNoteType?: NoteType, currentNoteMime?: string | null, note?: FNote | null, setModalShown: Dispatch<StateUpdater<boolean>> }) {
|
||||||
|
const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes");
|
||||||
|
const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []);
|
||||||
|
const mimeTypes = useMemo(() => {
|
||||||
|
mime_types.loadMimeTypes();
|
||||||
|
return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled);
|
||||||
|
}, [ codeNotesMimeTypes ]);
|
||||||
const changeNoteType = useCallback(async (type: NoteType, mime?: string) => {
|
const changeNoteType = useCallback(async (type: NoteType, mime?: string) => {
|
||||||
if (!note || (type === currentNoteType && mime === currentNoteMime)) {
|
if (!note || (type === currentNoteType && mime === currentNoteMime)) {
|
||||||
return;
|
return;
|
||||||
@ -71,70 +95,54 @@ function NoteTypeWidget({ note }: { note?: FNote | null }) {
|
|||||||
}, [ note, currentNoteType, currentNoteMime ]);
|
}, [ note, currentNoteType, currentNoteMime ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="note-type-container">
|
<>
|
||||||
<span>{t("basic_properties.note_type")}:</span>
|
{noteTypes.map(({ isNew, isBeta, type, mime, title }) => {
|
||||||
<Dropdown
|
const badges: FormListBadge[] = [];
|
||||||
dropdownContainerClassName="note-type-dropdown"
|
if (isNew) {
|
||||||
text={<span className="note-type-desc">{findTypeTitle(currentNoteType, currentNoteMime)}</span>}
|
badges.push({
|
||||||
disabled={notSelectableNoteTypes.includes(currentNoteType ?? "text")}
|
className: "new-note-type-badge",
|
||||||
>
|
text: t("note_types.new-feature")
|
||||||
{noteTypes.map(({ isNew, isBeta, type, mime, title }) => {
|
});
|
||||||
const badges: FormListBadge[] = [];
|
}
|
||||||
if (isNew) {
|
if (isBeta) {
|
||||||
badges.push({
|
badges.push({
|
||||||
className: "new-note-type-badge",
|
text: t("note_types.beta-feature")
|
||||||
text: t("note_types.new-feature")
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
if (isBeta) {
|
|
||||||
badges.push({
|
|
||||||
text: t("note_types.beta-feature")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const checked = (type === currentNoteType);
|
const checked = (type === currentNoteType);
|
||||||
if (type !== "code") {
|
if (type !== "code") {
|
||||||
return (
|
return (
|
||||||
|
<FormListItem
|
||||||
|
checked={checked}
|
||||||
|
badges={badges}
|
||||||
|
onClick={() => changeNoteType(type, mime)}
|
||||||
|
>{title}</FormListItem>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormDropdownDivider />
|
||||||
<FormListItem
|
<FormListItem
|
||||||
checked={checked}
|
checked={checked}
|
||||||
badges={badges}
|
disabled
|
||||||
onClick={() => changeNoteType(type, mime)}
|
>
|
||||||
>{title}</FormListItem>
|
<strong>{title}</strong>
|
||||||
);
|
</FormListItem>
|
||||||
} else {
|
</>
|
||||||
return (
|
);
|
||||||
<>
|
}
|
||||||
<FormDropdownDivider />
|
})}
|
||||||
<FormListItem
|
|
||||||
checked={checked}
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
<strong>{title}</strong>
|
|
||||||
</FormListItem>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
|
|
||||||
{mimeTypes.map(({ title, mime }) => (
|
{mimeTypes.map(({ title, mime }) => (
|
||||||
<FormListItem onClick={() => changeNoteType("code", mime)}>
|
<FormListItem onClick={() => changeNoteType("code", mime)}>
|
||||||
{title}
|
{title}
|
||||||
</FormListItem>
|
</FormListItem>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<FormDropdownDivider />
|
<FormDropdownDivider />
|
||||||
<FormListItem icon="bx bx-cog" onClick={() => setModalShown(true)}>{t("basic_properties.configure_code_notes")}</FormListItem>
|
<FormListItem icon="bx bx-cog" onClick={() => setModalShown(true)}>{t("basic_properties.configure_code_notes")}</FormListItem>
|
||||||
</Dropdown>
|
</>
|
||||||
|
|
||||||
<Modal
|
|
||||||
className="code-mime-types-modal"
|
|
||||||
title={t("code_mime_types.title")}
|
|
||||||
show={modalShown} onHidden={() => setModalShown(false)}
|
|
||||||
size="xl" scrollable
|
|
||||||
>
|
|
||||||
<CodeMimeTypesList />
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ConvertToAttachmentResponse } from "@triliumnext/commons";
|
import { ConvertToAttachmentResponse } from "@triliumnext/commons";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext, useState } from "preact/hooks";
|
||||||
|
|
||||||
import appContext, { CommandNames } from "../../components/app_context";
|
import appContext, { CommandNames } from "../../components/app_context";
|
||||||
import NoteContext from "../../components/note_context";
|
import NoteContext from "../../components/note_context";
|
||||||
@ -17,7 +17,7 @@ import { FormDropdownDivider, FormDropdownSubmenu, FormListItem, FormListTogglea
|
|||||||
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumOption } from "../react/hooks";
|
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumOption } from "../react/hooks";
|
||||||
import { ParentComponent } from "../react/react_utils";
|
import { ParentComponent } from "../react/react_utils";
|
||||||
import { isExperimentalFeatureEnabled } from "../../services/experimental_features";
|
import { isExperimentalFeatureEnabled } from "../../services/experimental_features";
|
||||||
import { useNoteBookmarkState, useShareState } from "./BasicPropertiesTab";
|
import { NoteTypeDropdownContent, useNoteBookmarkState, useShareState } from "./BasicPropertiesTab";
|
||||||
import protected_session from "../../services/protected_session";
|
import protected_session from "../../services/protected_session";
|
||||||
|
|
||||||
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
|
||||||
@ -148,6 +148,8 @@ function NoteBasicProperties({ note }: { note: FNote }) {
|
|||||||
title={t("protect_note.toggle-on")}
|
title={t("protect_note.toggle-on")}
|
||||||
currentValue={!!isProtected} onChange={shouldProtect => protected_session.protectNote(note.noteId, shouldProtect, false)}
|
currentValue={!!isProtected} onChange={shouldProtect => protected_session.protectNote(note.noteId, shouldProtect, false)}
|
||||||
/>
|
/>
|
||||||
|
<FormDropdownDivider />
|
||||||
|
<NoteTypeDropdown note={note} />
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +171,18 @@ function EditabilityDropdown({ note }: { note: FNote }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NoteTypeDropdown({ note }: { note: FNote }) {
|
||||||
|
const currentNoteType = useNoteProperty(note, "type") ?? undefined;
|
||||||
|
const currentNoteMime = useNoteProperty(note, "mime");
|
||||||
|
const [ modalShown, setModalShown ] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormDropdownSubmenu title={t("basic_properties.note_type")} icon="bx bx-file" dropStart>
|
||||||
|
<NoteTypeDropdownContent currentNoteType={currentNoteType} currentNoteMime={currentNoteMime} note={note} setModalShown={setModalShown} />
|
||||||
|
</FormDropdownSubmenu>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function DevelopmentActions({ note, noteContext }: { note: FNote, noteContext?: NoteContext }) {
|
function DevelopmentActions({ note, noteContext }: { note: FNote, noteContext?: NoteContext }) {
|
||||||
return (
|
return (
|
||||||
<FormDropdownSubmenu title="Development Actions" icon="bx bx-wrench" dropStart>
|
<FormDropdownSubmenu title="Development Actions" icon="bx bx-wrench" dropStart>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user