From 6160945b9e602d512bd65200ae056eff55c141c4 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 23 Nov 2025 13:35:16 +0200 Subject: [PATCH] chore(react/promoted_attributes): bring back reacting to changes --- .../client/src/widgets/PromotedAttributes.tsx | 57 ++++++++++++------- .../client/src/widgets/promoted_attributes.ts | 12 ---- 2 files changed, 38 insertions(+), 31 deletions(-) delete mode 100644 apps/client/src/widgets/promoted_attributes.ts diff --git a/apps/client/src/widgets/PromotedAttributes.tsx b/apps/client/src/widgets/PromotedAttributes.tsx index 42296e7ba..629585869 100644 --- a/apps/client/src/widgets/PromotedAttributes.tsx +++ b/apps/client/src/widgets/PromotedAttributes.tsx @@ -1,6 +1,6 @@ -import { MutableRef, useEffect, useRef, useState } from "preact/hooks"; +import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks"; import "./PromotedAttributes.css"; -import { useNoteContext, useNoteLabel, useUniqueName } from "./react/hooks"; +import { useNoteContext, useNoteLabel, useTriliumEvent, useUniqueName } from "./react/hooks"; import { Attribute } from "../services/attribute_parser"; import FAttribute from "../entities/fattribute"; import clsx from "clsx"; @@ -9,10 +9,10 @@ import { DefinitionObject, LabelType } from "../services/promoted_attribute_defi import server from "../services/server"; import FNote from "../entities/fnote"; import { ComponentChild, HTMLInputTypeAttribute, InputHTMLAttributes, MouseEventHandler, TargetedEvent, TargetedInputEvent } from "preact"; -import tree from "../services/tree"; import NoteAutocomplete from "./react/NoteAutocomplete"; import ws from "../services/ws"; import { UpdateAttributeResponse } from "@triliumnext/commons"; +import attributes from "../services/attributes"; interface Cell { definitionAttr: FAttribute; @@ -33,11 +33,34 @@ interface CellProps { export default function PromotedAttributes() { const { note, componentId } = useNoteContext(); - const [ cells, setCells ] = useState(); - const [ viewType ] = useNoteLabel(note, "viewType"); + const [ cells, setCells ] = usePromotedAttributeData(note, componentId); const [ cellToFocus, setCellToFocus ] = useState(); - useEffect(() => { + return ( +
+
+ {note && cells?.map(cell => )} +
+
+ ); +} + +/** + * Handles the individual cells (instances for promoted attributes including empty attributes). Promoted attributes with "multiple" multiplicity will have + * each value represented as a separate cell. + * + * The cells are returned as a state since they can also be altered internally if needed, for example to add a new empty cell. + */ +function usePromotedAttributeData(note: FNote | null | undefined, componentId: string): [ Cell[] | undefined, Dispatch> ] { + const [ viewType ] = useNoteLabel(note, "viewType"); + const [ cells, setCells ] = useState(); + + function refresh() { if (!note || viewType === "table") { setCells([]); return; @@ -81,20 +104,16 @@ export default function PromotedAttributes() { } } setCells(cells); - }, [ note, viewType ]); + } - return ( -
-
- {note && cells?.map(cell => )} -
-
- ); + useEffect(refresh, [ note, viewType ]); + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) { + refresh(); + } + }); + + return [ cells, setCells ]; } function PromotedAttributeCell(props: CellProps) { diff --git a/apps/client/src/widgets/promoted_attributes.ts b/apps/client/src/widgets/promoted_attributes.ts deleted file mode 100644 index 5aafa4ed3..000000000 --- a/apps/client/src/widgets/promoted_attributes.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default class PromotedAttributesWidget extends NoteContextAwareWidget { - - focus() { - this.$widget.find(".promoted-attribute-input:first").focus(); - } - - entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { - if (loadResults.getAttributeRows(this.componentId).find((attr) => attributeService.isAffecting(attr, this.note))) { - this.refresh(); - } - } -}