chore(react/promoted_attributes): add logic to add new labels

This commit is contained in:
Elian Doran 2025-11-23 10:46:56 +02:00
parent 5b9401fafe
commit 33b19e40e0
No known key found for this signature in database
2 changed files with 61 additions and 34 deletions

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from "preact/hooks"; import { MutableRef, useEffect, useRef, useState } from "preact/hooks";
import "./PromotedAttributes.css"; import "./PromotedAttributes.css";
import { useNoteContext, useNoteLabel } from "./react/hooks"; import { useNoteContext, useNoteLabel, useUniqueName } from "./react/hooks";
import { Attribute } from "../services/attribute_parser"; import { Attribute } from "../services/attribute_parser";
import FAttribute from "../entities/fattribute"; import FAttribute from "../entities/fattribute";
import clsx from "clsx"; import clsx from "clsx";
@ -14,10 +14,19 @@ interface Cell {
valueName: string; valueName: string;
} }
interface CellProps {
cell: Cell,
cells: Cell[],
shouldFocus: boolean;
setCells(cells: Cell[]): void;
setCellToFocus(cell: Cell): void;
}
export default function PromotedAttributes() { export default function PromotedAttributes() {
const { note } = useNoteContext(); const { note } = useNoteContext();
const [ cells, setCells ] = useState<Cell[]>(); const [ cells, setCells ] = useState<Cell[]>();
const [ viewType ] = useNoteLabel(note, "viewType"); const [ viewType ] = useNoteLabel(note, "viewType");
const [ cellToFocus, setCellToFocus ] = useState<Cell>();
useEffect(() => { useEffect(() => {
if (!note || viewType === "table") { if (!note || viewType === "table") {
@ -62,15 +71,23 @@ export default function PromotedAttributes() {
return ( return (
<div className="promoted-attributes-widget"> <div className="promoted-attributes-widget">
<div className="promoted-attributes-container"> <div className="promoted-attributes-container">
{cells?.map(cell => <PromotedAttributeCell cell={cell} />)} {cells?.map(cell => <PromotedAttributeCell cell={cell} cells={cells} setCells={setCells} shouldFocus={cell === cellToFocus} setCellToFocus={setCellToFocus} />)}
</div> </div>
</div> </div>
); );
} }
function PromotedAttributeCell({ cell }: { cell: Cell }) { function PromotedAttributeCell(props: CellProps) {
const { valueName, valueAttr, definition, definitionAttr } = cell; const { valueName, valueAttr, definition, definitionAttr } = props.cell;
const inputId = `value-${valueAttr.attributeId}`; const inputId = useUniqueName(`value-${valueAttr.name}`);
useEffect(() => {
if (!props.shouldFocus) return;
const inputEl = document.getElementById(inputId);
if (inputEl) {
inputEl.focus();
}
}, [ props.shouldFocus ]);
return ( return (
<div className="promoted-attribute-cell"> <div className="promoted-attribute-cell">
@ -81,13 +98,13 @@ function PromotedAttributeCell({ cell }: { cell: Cell }) {
id={inputId} id={inputId}
/> />
</div> </div>
<ActionCell cell={cell} /> <ActionCell />
<MultiplicityCell cell={cell} /> <MultiplicityCell {...props} />
</div> </div>
) )
} }
function ActionCell({ cell }: { cell: Cell }) { function ActionCell() {
return ( return (
<div> <div>
@ -95,23 +112,53 @@ function ActionCell({ cell }: { cell: Cell }) {
) )
} }
function MultiplicityCell({ cell }: { cell: Cell }) { function MultiplicityCell({ cell, cells, setCells, setCellToFocus }: CellProps) {
return (cell.definition.multiplicity === "multi" && return (cell.definition.multiplicity === "multi" &&
<td className="multiplicity"> <td className="multiplicity">
<PromotedActionButton icon="bx bx-plus" title={t("promoted_attributes.add_new_attribute")} />{' '} <PromotedActionButton
<PromotedActionButton icon="bx bx-trash" title={t("promoted_attributes.remove_this_attribute")} /> icon="bx bx-plus"
title={t("promoted_attributes.add_new_attribute")}
onClick={() => {
const index = cells.indexOf(cell);
const newCell: Cell = {
...cell,
valueAttr: {
attributeId: "",
type: cell.valueAttr.type,
name: cell.valueName,
value: ""
}
};
setCells([
...cells.slice(0, index + 1),
newCell,
...cells.slice(index + 1)
]);
setCellToFocus(newCell);
}}
/>{' '}
<PromotedActionButton
icon="bx bx-trash"
title={t("promoted_attributes.remove_this_attribute")}
onClick={() => {
}}
/>
</td> </td>
) )
} }
function PromotedActionButton({ icon, title }: { function PromotedActionButton({ icon, title, onClick }: {
icon: string, icon: string,
title: string }) title: string,
onClick: () => void
})
{ {
return ( return (
<span <span
className={clsx("tn-tool-button pointer", icon)} className={clsx("tn-tool-button pointer", icon)}
title={title} title={title}
onClick={onClick}
/> />
) )
} }

View File

@ -164,26 +164,6 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
} }
if (definition.multiplicity === "multi") { if (definition.multiplicity === "multi") {
const $addButton = $("<span>")
.on("click", async () => {
const $new = await this.createPromotedAttributeCell(
definitionAttr,
{
attributeId: "",
type: valueAttr.type,
name: valueName,
value: ""
},
valueName
);
if ($new) {
$wrapper.after($new);
$new.find("input").trigger("focus");
}
});
const $removeButton = $("<span>") const $removeButton = $("<span>")
.on("click", async () => { .on("click", async () => {
const attributeId = $input.attr("data-attribute-id"); const attributeId = $input.attr("data-attribute-id");