feat(react/ribbon): port template switch

This commit is contained in:
Elian Doran 2025-08-22 12:14:53 +03:00
parent f04f9dc262
commit c91748da15
No known key found for this signature in database
5 changed files with 23 additions and 64 deletions

View File

@ -316,6 +316,7 @@ export function useNoteProperty<T extends keyof FNote>(note: FNote | null | unde
export function useNoteLabel(note: FNote | undefined | null, labelName: string): [string | null | undefined, (newValue: string) => void] { export function useNoteLabel(note: FNote | undefined | null, labelName: string): [string | null | undefined, (newValue: string) => void] {
const [ labelValue, setLabelValue ] = useState<string | null | undefined>(note?.getLabelValue(labelName)); const [ labelValue, setLabelValue ] = useState<string | null | undefined>(note?.getLabelValue(labelName));
useEffect(() => setLabelValue(note?.getLabelValue(labelName) ?? null), [ note ]);
useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
for (const attr of loadResults.getAttributeRows()) { for (const attr of loadResults.getAttributeRows()) {
if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) { if (attr.type === "label" && attr.name === labelName && attributes.isAffecting(attr, note)) {
@ -336,8 +337,10 @@ export function useNoteLabel(note: FNote | undefined | null, labelName: string):
] as const; ] as const;
} }
export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: string): [ boolean | null | undefined, (newValue: boolean) => void] { export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: string): [ boolean, (newValue: boolean) => void] {
const [ labelValue, setLabelValue ] = useState<boolean | null | undefined>(note?.hasLabel(labelName)); const [ labelValue, setLabelValue ] = useState<boolean>(!!note?.hasLabel(labelName));
useEffect(() => setLabelValue(!!note?.hasLabel(labelName)), [ note ]);
useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => { useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
for (const attr of loadResults.getAttributeRows()) { for (const attr of loadResults.getAttributeRows()) {

View File

@ -15,6 +15,7 @@ import FormDropdownList from "../react/FormDropdownList";
import toast from "../../services/toast"; import toast from "../../services/toast";
import branches from "../../services/branches"; import branches from "../../services/branches";
import sync from "../../services/sync"; import sync from "../../services/sync";
import TemplateSwitchWidget from "../template_switch";
export default function BasicPropertiesTab() { export default function BasicPropertiesTab() {
const { note } = useNoteContext(); const { note } = useNoteContext();
@ -26,6 +27,7 @@ export default function BasicPropertiesTab() {
<EditabilitySelect note={note} /> <EditabilitySelect note={note} />
<BookmarkSwitch note={note} /> <BookmarkSwitch note={note} />
<SharedSwitch note={note} /> <SharedSwitch note={note} />
<TemplateSwitch note={note} />
</div> </div>
); );
} }
@ -202,6 +204,22 @@ function BookmarkSwitch({ note }: { note?: FNote | null }) {
) )
} }
function TemplateSwitch({ note }: { note?: FNote | null }) {
const [ isTemplate, setIsTemplate ] = useNoteLabelBoolean(note, "template");
return (
<div className="template-switch-container">
<FormToggle
switchOnName={t("template_switch.template")} switchOnTooltip={t("template_switch.toggle-on-hint")}
switchOffName={t("template_switch.template")} switchOffTooltip={t("template_switch.toggle-off-hint")}
helpPage="KC1HB96bqqHX"
disabled={note?.noteId.startsWith("_options")}
currentValue={isTemplate} onChange={setIsTemplate}
/>
</div>
)
}
function SharedSwitch({ note }: { note?: FNote | null }) { function SharedSwitch({ note }: { note?: FNote | null }) {
const [ isShared, setIsShared ] = useState(false); const [ isShared, setIsShared ] = useState(false);
const refreshState = useCallback(() => { const refreshState = useCallback(() => {

View File

@ -10,8 +10,6 @@ import type FNote from "../../entities/fnote.js";
import NoteLanguageWidget from "../note_language.js"; import NoteLanguageWidget from "../note_language.js";
const TPL = /*html*/` const TPL = /*html*/`
<div class="template-switch-container"></div>
<div class="note-language-container"> <div class="note-language-container">
<span>${t("basic_properties.language")}:</span> &nbsp; <span>${t("basic_properties.language")}:</span> &nbsp;
</div> </div>

View File

@ -1,14 +1,6 @@
import { t } from "../services/i18n.js"; import { t } from "../services/i18n.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js";
const TPL = /*html*/`
<div class="switch-widget">
<style>
</style>
</div>`;
export default class SwitchWidget extends NoteContextAwareWidget { export default class SwitchWidget extends NoteContextAwareWidget {
doRender() { doRender() {

View File

@ -1,52 +0,0 @@
import SwitchWidget from "./switch.js";
import attributeService from "../services/attributes.js";
import { t } from "../services/i18n.js";
import type { EventData } from "../components/app_context.js";
import type FNote from "../entities/fnote.js";
/**
* Switch for the basic properties widget which allows the user to select whether the note is a template or not, which toggles the `#template` attribute.
*/
export default class TemplateSwitchWidget extends SwitchWidget {
isEnabled() {
return super.isEnabled() && !this.noteId?.startsWith("_options");
}
doRender() {
super.doRender();
this.switchOnName = t("template_switch.template");
this.switchOnTooltip = t("template_switch.toggle-on-hint");
this.switchOffName = t("template_switch.template");
this.switchOffTooltip = t("template_switch.toggle-off-hint");
this.$helpButton.attr("data-help-page", "template.html").show();
}
async switchOn() {
if (this.noteId) {
await attributeService.setLabel(this.noteId, "template");
}
}
async switchOff() {
if (this.note && this.noteId) {
for (const templateAttr of this.note.getOwnedLabels("template")) {
await attributeService.removeAttributeById(this.noteId, templateAttr.attributeId);
}
}
}
async refreshWithNote(note: FNote) {
const isTemplate = note.hasLabel("template");
this.isToggled = isTemplate;
}
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (loadResults.getAttributeRows().find((attr) => attr.type === "label" && attr.name === "template" && attr.noteId === this.noteId)) {
this.refresh();
}
}
}