mirror of
https://github.com/zadam/trilium.git
synced 2025-11-26 02:24:23 +01:00
chore(react/promoted_attributes): integrate value change listener
This commit is contained in:
parent
49189bc63e
commit
7f0fe1681b
@ -8,7 +8,8 @@ import { t } from "../services/i18n";
|
|||||||
import { DefinitionObject, LabelType } from "../services/promoted_attribute_definition_parser";
|
import { DefinitionObject, LabelType } from "../services/promoted_attribute_definition_parser";
|
||||||
import server from "../services/server";
|
import server from "../services/server";
|
||||||
import FNote from "../entities/fnote";
|
import FNote from "../entities/fnote";
|
||||||
import { HTMLInputTypeAttribute } from "preact";
|
import { HTMLInputTypeAttribute, TargetedEvent } from "preact";
|
||||||
|
import tree from "../services/tree";
|
||||||
|
|
||||||
interface Cell {
|
interface Cell {
|
||||||
definitionAttr: FAttribute;
|
definitionAttr: FAttribute;
|
||||||
@ -27,6 +28,12 @@ interface CellProps {
|
|||||||
setCellToFocus(cell: Cell): void;
|
setCellToFocus(cell: Cell): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Deduplicate
|
||||||
|
interface AttributeResult {
|
||||||
|
attributeId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function PromotedAttributes() {
|
export default function PromotedAttributes() {
|
||||||
const { note, componentId } = useNoteContext();
|
const { note, componentId } = useNoteContext();
|
||||||
const [ cells, setCells ] = useState<Cell[]>();
|
const [ cells, setCells ] = useState<Cell[]>();
|
||||||
@ -130,15 +137,13 @@ const LABEL_MAPPINGS: Record<LabelType, HTMLInputTypeAttribute> = {
|
|||||||
|
|
||||||
function LabelInput({ inputId, ...props }: CellProps & { inputId: string }) {
|
function LabelInput({ inputId, ...props }: CellProps & { inputId: string }) {
|
||||||
const { valueAttr, definition, definitionAttr } = props.cell;
|
const { valueAttr, definition, definitionAttr } = props.cell;
|
||||||
|
const onChangeListener = buildPromotedAttributeChangedListener({...props});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (definition.labelType === "text") {
|
if (definition.labelType === "text") {
|
||||||
const el = document.getElementById(inputId);
|
const el = document.getElementById(inputId);
|
||||||
if (el) {
|
if (el) {
|
||||||
setupTextLabelAutocomplete(el as HTMLInputElement, valueAttr, () => {
|
setupTextLabelAutocomplete(el as HTMLInputElement, valueAttr, onChangeListener);
|
||||||
// TODO: Implement me.
|
|
||||||
console.log("Got change");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@ -154,6 +159,7 @@ function LabelInput({ inputId, ...props }: CellProps & { inputId: string }) {
|
|||||||
data-attribute-id={valueAttr.attributeId}
|
data-attribute-id={valueAttr.attributeId}
|
||||||
data-attribute-type={valueAttr.type}
|
data-attribute-type={valueAttr.type}
|
||||||
data-attribute-name={valueAttr.name}
|
data-attribute-name={valueAttr.name}
|
||||||
|
onChange={onChangeListener}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -242,7 +248,7 @@ function PromotedActionButton({ icon, title, onClick }: {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute, onChangeListener: () => void) {
|
function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute, onChangeListener: TargetedEvent<HTMLInputElement, Event>) {
|
||||||
// no need to await for this, can be done asynchronously
|
// no need to await for this, can be done asynchronously
|
||||||
const $input = $(el);
|
const $input = $(el);
|
||||||
server.get<string[]>(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then((_attributeValues) => {
|
server.get<string[]>(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then((_attributeValues) => {
|
||||||
@ -278,3 +284,33 @@ function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute,
|
|||||||
$input.on("autocomplete:selected", onChangeListener);
|
$input.on("autocomplete:selected", onChangeListener);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildPromotedAttributeChangedListener({ note, cell, componentId }: CellProps) {
|
||||||
|
return async (e: TargetedEvent<HTMLInputElement, Event>) => {
|
||||||
|
const inputEl = e.target as HTMLInputElement;
|
||||||
|
let value: string;
|
||||||
|
|
||||||
|
if (inputEl.type === "checkbox") {
|
||||||
|
value = inputEl.checked ? "true" : "false";
|
||||||
|
} else if (inputEl.dataset.attributeType === "relation") {
|
||||||
|
const selectedPath = $(inputEl).getSelectedNotePath();
|
||||||
|
value = selectedPath ? tree.getNoteIdFromUrl(selectedPath) ?? "" : "";
|
||||||
|
console.log("Got relation ", value);
|
||||||
|
} else {
|
||||||
|
value = inputEl.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await server.put<AttributeResult>(
|
||||||
|
`notes/${note.noteId}/attribute`,
|
||||||
|
{
|
||||||
|
attributeId: cell.valueAttr.attributeId,
|
||||||
|
type: cell.valueAttr.type,
|
||||||
|
name: cell.valueName,
|
||||||
|
value: value
|
||||||
|
},
|
||||||
|
componentId
|
||||||
|
);
|
||||||
|
|
||||||
|
cell.valueAttr.attributeId = result.attributeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -12,10 +12,6 @@ import type { Attribute } from "../services/attribute_parser.js";
|
|||||||
import type FAttribute from "../entities/fattribute.js";
|
import type FAttribute from "../entities/fattribute.js";
|
||||||
import type { EventData } from "../components/app_context.js";
|
import type { EventData } from "../components/app_context.js";
|
||||||
|
|
||||||
// TODO: Deduplicate
|
|
||||||
interface AttributeResult {
|
|
||||||
attributeId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
||||||
|
|
||||||
@ -44,9 +40,6 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
if (valueAttr.value === "true") {
|
if (valueAttr.value === "true") {
|
||||||
$input.prop("checked", "checked");
|
$input.prop("checked", "checked");
|
||||||
}
|
}
|
||||||
} else if (definition.labelType === "date") {
|
|
||||||
} else if (definition.labelType === "datetime") {
|
|
||||||
} else if (definition.labelType === "time") {
|
|
||||||
} else if (definition.labelType === "url") {
|
} else if (definition.labelType === "url") {
|
||||||
$input.prop("placeholder", t("promoted_attributes.url_placeholder"));
|
$input.prop("placeholder", t("promoted_attributes.url_placeholder"));
|
||||||
|
|
||||||
@ -114,35 +107,6 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
return $wrapper;
|
return $wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
async promotedAttributeChanged(event: JQuery.TriggeredEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) {
|
|
||||||
const $attr = $(event.target);
|
|
||||||
|
|
||||||
let value;
|
|
||||||
|
|
||||||
if ($attr.prop("type") === "checkbox") {
|
|
||||||
value = $attr.is(":checked") ? "true" : "false";
|
|
||||||
} else if ($attr.attr("data-attribute-type") === "relation") {
|
|
||||||
const selectedPath = $attr.getSelectedNotePath();
|
|
||||||
|
|
||||||
value = selectedPath ? treeService.getNoteIdFromUrl(selectedPath) : "";
|
|
||||||
} else {
|
|
||||||
value = $attr.val();
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await server.put<AttributeResult>(
|
|
||||||
`notes/${this.noteId}/attribute`,
|
|
||||||
{
|
|
||||||
attributeId: $attr.attr("data-attribute-id"),
|
|
||||||
type: $attr.attr("data-attribute-type"),
|
|
||||||
name: $attr.attr("data-attribute-name"),
|
|
||||||
value: value
|
|
||||||
},
|
|
||||||
this.componentId
|
|
||||||
);
|
|
||||||
|
|
||||||
$attr.attr("data-attribute-id", result.attributeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this.$widget.find(".promoted-attribute-input:first").focus();
|
this.$widget.find(".promoted-attribute-input:first").focus();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user