From 60cb8d950ef0cbc81ce6212754e3eeb67a9446e4 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Tue, 6 Jan 2026 13:30:21 +0200 Subject: [PATCH] chore(core): integrate promoted_attribute_definition_parser --- .../promoted_attribute_definition_parser.ts | 12 +-------- .../attribute_widgets/UserAttributesList.tsx | 26 ++++++++++--------- .../src/widgets/collections/table/columns.tsx | 17 ++++++------ apps/server/src/services/handlers.ts | 2 +- ...promoted_attribute_definition_interface.ts | 8 ------ packages/commons/src/lib/server_api.ts | 12 +++++++++ .../promoted_attribute_definition_parser.ts | 6 ++--- 7 files changed, 40 insertions(+), 43 deletions(-) delete mode 100644 apps/server/src/services/promoted_attribute_definition_interface.ts rename {apps/server => packages/trilium-core}/src/services/promoted_attribute_definition_parser.ts (84%) diff --git a/apps/client/src/services/promoted_attribute_definition_parser.ts b/apps/client/src/services/promoted_attribute_definition_parser.ts index 0d93aae3c..292e64438 100644 --- a/apps/client/src/services/promoted_attribute_definition_parser.ts +++ b/apps/client/src/services/promoted_attribute_definition_parser.ts @@ -1,14 +1,4 @@ -export type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color"; -type Multiplicity = "single" | "multi"; - -export interface DefinitionObject { - isPromoted?: boolean; - labelType?: LabelType; - multiplicity?: Multiplicity; - numberPrecision?: number; - promotedAlias?: string; - inverseRelation?: string; -} +import { DefinitionObject, LabelType, Multiplicity } from "@triliumnext/commons"; function parse(value: string) { const tokens = value.split(",").map((t) => t.trim()); diff --git a/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx b/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx index f01e70b49..93ed5356c 100644 --- a/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx +++ b/apps/client/src/widgets/attribute_widgets/UserAttributesList.tsx @@ -1,14 +1,16 @@ -import { useState } from "preact/hooks"; -import FNote from "../../entities/fnote"; import "./UserAttributesList.css"; -import { useTriliumEvent } from "../react/hooks"; -import attributes from "../../services/attributes"; -import { DefinitionObject } from "../../services/promoted_attribute_definition_parser"; -import { formatDateTime } from "../../utils/formatters"; + +import type { DefinitionObject } from "@triliumnext/commons"; import { ComponentChildren, CSSProperties } from "preact"; +import { useState } from "preact/hooks"; + +import FNote from "../../entities/fnote"; +import attributes from "../../services/attributes"; +import { getReadableTextColor } from "../../services/css_class_manager"; +import { formatDateTime } from "../../utils/formatters"; +import { useTriliumEvent } from "../react/hooks"; import Icon from "../react/Icon"; import NoteLink from "../react/NoteLink"; -import { getReadableTextColor } from "../../services/css_class_manager"; interface UserAttributesListProps { note: FNote; @@ -29,7 +31,7 @@ export default function UserAttributesDisplay({ note, ignoredAttributes }: UserA
{userAttributes?.map(attr => buildUserAttribute(attr))}
- ) + ); } @@ -46,13 +48,13 @@ function useNoteAttributesWithDefinitions(note: FNote, attributesToIgnore: stri } function UserAttribute({ attr, children, style }: { attr: AttributeWithDefinitions, children: ComponentChildren, style?: CSSProperties }) { - const className = `${attr.type === "label" ? "label" + " " + attr.def.labelType : "relation"}`; + const className = `${attr.type === "label" ? `label` + ` ${ attr.def.labelType}` : "relation"}`; return ( {children} - ) + ); } function buildUserAttribute(attr: AttributeWithDefinitions): ComponentChildren { @@ -61,7 +63,7 @@ function buildUserAttribute(attr: AttributeWithDefinitions): ComponentChildren { let style: CSSProperties | undefined; if (attr.type === "label") { - let value = attr.value; + const value = attr.value; switch (attr.def.labelType) { case "number": let formattedValue = value; @@ -102,7 +104,7 @@ function buildUserAttribute(attr: AttributeWithDefinitions): ComponentChildren { content = <>{defaultLabel}; } - return {content} + return {content}; } function getAttributesWithDefinitions(note: FNote, attributesToIgnore: string[] = []): AttributeWithDefinitions[] { diff --git a/apps/client/src/widgets/collections/table/columns.tsx b/apps/client/src/widgets/collections/table/columns.tsx index 74db6ddb7..3c2e48763 100644 --- a/apps/client/src/widgets/collections/table/columns.tsx +++ b/apps/client/src/widgets/collections/table/columns.tsx @@ -1,11 +1,12 @@ -import type { CellComponent, ColumnDefinition, EmptyCallback, FormatterParams, ValueBooleanCallback, ValueVoidCallback } from "tabulator-tables"; -import { LabelType } from "../../../services/promoted_attribute_definition_parser.js"; +import { LabelType } from "@triliumnext/commons"; import { JSX } from "preact"; -import { renderReactWidget } from "../../react/react_utils.jsx"; -import Icon from "../../react/Icon.jsx"; import { useEffect, useRef, useState } from "preact/hooks"; +import type { CellComponent, ColumnDefinition, EmptyCallback, FormatterParams, ValueBooleanCallback, ValueVoidCallback } from "tabulator-tables"; + import froca from "../../../services/froca.js"; +import Icon from "../../react/Icon.jsx"; import NoteAutocomplete from "../../react/NoteAutocomplete.jsx"; +import { renderReactWidget } from "../../react/react_utils.jsx"; type ColumnType = LabelType | "relation"; @@ -78,7 +79,7 @@ export function buildColumnDefinitions({ info, movableRows, existingColumnData, rowHandle: movableRows, width: calculateIndexColumnWidth(rowNumberHint, movableRows), formatter: wrapFormatter(({ cell, formatterParams }) =>
- {(formatterParams as RowNumberFormatterParams).movableRows && <>{" "}} + {(formatterParams as RowNumberFormatterParams).movableRows && <>{" "}} {cell.getRow().getPosition(true)}
), formatterParams: { movableRows } satisfies RowNumberFormatterParams @@ -200,14 +201,14 @@ function wrapEditor(Component: (opts: EditorOpts) => JSX.Element): (( editorParams: {}, ) => HTMLElement | false) { return (cell, _, success, cancel, editorParams) => { - const elWithParams = + const elWithParams = ; return renderReactWidget(null, elWithParams)[0]; }; } function NoteFormatter({ cell }: FormatterOpts) { const noteId = cell.getValue(); - const [ note, setNote ] = useState(noteId ? froca.getNoteFromCache(noteId) : null) + const [ note, setNote ] = useState(noteId ? froca.getNoteFromCache(noteId) : null); useEffect(() => { if (!noteId || note?.noteId === noteId) return; @@ -231,5 +232,5 @@ function RelationEditor({ cell, success }: EditorOpts) { hideAllButtons: true }} noteIdChanged={success} - /> + />; } diff --git a/apps/server/src/services/handlers.ts b/apps/server/src/services/handlers.ts index b76417554..8a7d6d12f 100644 --- a/apps/server/src/services/handlers.ts +++ b/apps/server/src/services/handlers.ts @@ -1,3 +1,4 @@ +import { DefinitionObject } from "@triliumnext/commons"; import { type AbstractBeccaEntity, events as eventService } from "@triliumnext/core"; import becca from "../becca/becca.js"; @@ -6,7 +7,6 @@ import type BNote from "../becca/entities/bnote.js"; import hiddenSubtreeService from "./hidden_subtree.js"; import noteService from "./notes.js"; import oneTimeTimer from "./one_time_timer.js"; -import type { DefinitionObject } from "./promoted_attribute_definition_interface.js"; import scriptService from "./script.js"; import treeService from "./tree.js"; diff --git a/apps/server/src/services/promoted_attribute_definition_interface.ts b/apps/server/src/services/promoted_attribute_definition_interface.ts deleted file mode 100644 index 2f68aa7ac..000000000 --- a/apps/server/src/services/promoted_attribute_definition_interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface DefinitionObject { - isPromoted?: boolean; - labelType?: string; - multiplicity?: string; - numberPrecision?: number; - promotedAlias?: string; - inverseRelation?: string; -} diff --git a/packages/commons/src/lib/server_api.ts b/packages/commons/src/lib/server_api.ts index 17d8f1471..a26a8f286 100644 --- a/packages/commons/src/lib/server_api.ts +++ b/packages/commons/src/lib/server_api.ts @@ -298,3 +298,15 @@ export interface IconRegistry { }[] }[]; } + +export type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color"; +export type Multiplicity = "single" | "multi"; + +export interface DefinitionObject { + isPromoted?: boolean; + labelType?: LabelType; + multiplicity?: Multiplicity; + numberPrecision?: number; + promotedAlias?: string; + inverseRelation?: string; +} diff --git a/apps/server/src/services/promoted_attribute_definition_parser.ts b/packages/trilium-core/src/services/promoted_attribute_definition_parser.ts similarity index 84% rename from apps/server/src/services/promoted_attribute_definition_parser.ts rename to packages/trilium-core/src/services/promoted_attribute_definition_parser.ts index 630c57a72..bc9c66bbc 100644 --- a/apps/server/src/services/promoted_attribute_definition_parser.ts +++ b/packages/trilium-core/src/services/promoted_attribute_definition_parser.ts @@ -1,4 +1,4 @@ -import type { DefinitionObject } from "./promoted_attribute_definition_interface.js"; +import { DefinitionObject, LabelType, Multiplicity } from "@triliumnext/commons"; function parse(value: string): DefinitionObject { const tokens = value.split(",").map((t) => t.trim()); @@ -8,9 +8,9 @@ function parse(value: string): DefinitionObject { if (token === "promoted") { defObj.isPromoted = true; } else if (["text", "number", "boolean", "date", "datetime", "time", "url"].includes(token)) { - defObj.labelType = token; + defObj.labelType = token as LabelType; } else if (["single", "multi"].includes(token)) { - defObj.multiplicity = token; + defObj.multiplicity = token as Multiplicity; } else if (token.startsWith("precision")) { const chunks = token.split("=");