chore(react/collections/table): fix some issues with col editing

This commit is contained in:
Elian Doran 2025-09-09 18:48:09 +03:00
parent 1e654fbcd6
commit 4e37a5f08e
No known key found for this signature in database
5 changed files with 80 additions and 77 deletions

View File

@ -2,31 +2,27 @@ import { useLegacyImperativeHandlers } from "../../react/hooks";
import { Attribute } from "../../../services/attribute_parser";
import { RefObject } from "preact";
import { Tabulator } from "tabulator-tables";
import { useEffect, useState } from "preact/hooks";
import { useRef, useState } from "preact/hooks";
import { CommandListenerData, EventData } from "../../../components/app_context";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import attributes from "../../../services/attributes";
import { renameColumn } from "../../view_widgets/table_view/bulk_actions";
import FNote from "../../../entities/fnote";
import { getAttributeFromField } from "./utils";
export default function useColTableEditing(api: RefObject<Tabulator>, attributeDetailWidget: AttributeDetailWidget, parentNote: FNote) {
const [ existingAttributeToEdit, setExistingAttributeToEdit ] = useState<Attribute>();
const [ newAttribute, setNewAttribute ] = useState<Attribute>();
const [ newAttributePosition, setNewAttributePosition ] = useState<number>();
useEffect(() => {
}, []);
const newAttribute = useRef<Attribute>();
const newAttributePosition = useRef<number>();
useLegacyImperativeHandlers({
addNewTableColumnCommand({ referenceColumn, columnToEdit, direction, type }: EventData<"addNewTableColumn">) {
console.log("Ding");
let attr: Attribute | undefined;
setExistingAttributeToEdit(undefined);
if (columnToEdit) {
attr = this.getAttributeFromField(columnToEdit.getField());
attr = getAttributeFromField(parentNote, columnToEdit.getField());
if (attr) {
setExistingAttributeToEdit({ ...attr });
}
@ -47,9 +43,9 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
newPosition++;
}
setNewAttributePosition(newPosition);
newAttributePosition.current = newPosition;
} else {
setNewAttributePosition(undefined);
newAttributePosition.current = undefined;
}
attributeDetailWidget.showAttributeDetail({
@ -63,26 +59,26 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
});
},
async updateAttributeListCommand({ attributes }: CommandListenerData<"updateAttributeList">) {
setNewAttribute(attributes[0]);
newAttribute.current = attributes[0];
},
async saveAttributesCommand() {
if (!newAttribute || !api.current) {
if (!newAttribute.current || !api.current) {
return;
}
const { name, value, isInheritable } = newAttribute;
const { name, value, isInheritable } = newAttribute.current;
api.current.blockRedraw();
const isRename = (this.existingAttributeToEdit && this.existingAttributeToEdit.name !== name);
const isRename = (existingAttributeToEdit && existingAttributeToEdit.name !== name);
try {
if (isRename) {
const oldName = this.existingAttributeToEdit!.name.split(":")[1];
const oldName = existingAttributeToEdit!.name.split(":")[1];
const [ type, newName ] = name.split(":");
await renameColumn(parentNote.noteId, type as "label" | "relation", oldName, newName);
}
if (existingAttributeToEdit && (isRename || existingAttributeToEdit.isInheritable !== isInheritable)) {
attributes.removeOwnedLabelByName(parentNote, this.existingAttributeToEdit.name);
attributes.removeOwnedLabelByName(parentNote, existingAttributeToEdit.name);
}
attributes.setLabel(parentNote.noteId, name, value, isInheritable);
} finally {
@ -91,5 +87,5 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
}
});
return {};
return { newAttributePosition };
}

View File

@ -15,7 +15,7 @@ import useRowTableEditing, { canReorderRows } from "./row_editing";
import useColTableEditing from "./col_editing";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import attributes from "../../../services/attributes";
import { refreshTextDimensions } from "@excalidraw/excalidraw/element/newElement";
import { RefObject } from "preact";
interface TableConfig {
tableData?: {
@ -24,48 +24,15 @@ interface TableConfig {
}
export default function TableView({ note, noteIds, notePath, viewConfig, saveConfig }: ViewModeProps<TableConfig>) {
const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
const [ columnDefs, setColumnDefs ] = useState<ColumnDefinition[]>();
const [ rowData, setRowData ] = useState<TableData[]>();
const [ movableRows, setMovableRows ] = useState<boolean>();
const [ hasChildren, setHasChildren ] = useState<boolean>();
const tabulatorRef = useRef<VanillaTabulator>(null);
const parentComponent = useContext(ParentComponent);
function refresh() {
const info = getAttributeDefinitionInformation(note);
buildRowDefinitions(note, info, maxDepth).then(({ definitions: rowData, hasSubtree: hasChildren, rowNumber }) => {
const movableRows = canReorderRows(note) && !hasChildren;
const columnDefs = buildColumnDefinitions({
info,
movableRows,
existingColumnData: viewConfig?.tableData?.columns,
rowNumberHint: rowNumber
});
setColumnDefs(columnDefs);
setRowData(rowData);
setMovableRows(movableRows);
setHasChildren(hasChildren);
});
}
useEffect(refresh, [ note, noteIds ]);
// React to column changes.
useTriliumEvent("entitiesReloaded", ({ loadResults}) => {
if (loadResults.getAttributeRows().find(attr =>
attr.type === "label" &&
(attr.name?.startsWith("label:") || attr.name?.startsWith("relation:")) &&
attributes.isAffecting(attr, note))) {
refresh();
}
});
const [ attributeDetailWidgetEl, attributeDetailWidget ] = useLegacyWidget(() => new AttributeDetailWidget().contentSized());
const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef);
const persistenceProps = usePersistence(viewConfig, saveConfig);
const rowEditingEvents = useRowTableEditing(tabulatorRef, attributeDetailWidget, notePath);
const colEditingEvents = useColTableEditing(tabulatorRef, attributeDetailWidget, note);
const { newAttributePosition } = useColTableEditing(tabulatorRef, attributeDetailWidget, note);
const { columnDefs, rowData, movableRows, hasChildren } = useData(note, noteIds, viewConfig, newAttributePosition);
const dataTreeProps = useMemo<Options>(() => {
if (!hasChildren) return {};
return {
@ -92,8 +59,7 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
footerElement={<TableFooter note={note} />}
events={{
...contextMenuEvents,
...rowEditingEvents,
...colEditingEvents
...rowEditingEvents
}}
persistence {...persistenceProps}
layout="fitDataFill"
@ -141,3 +107,44 @@ function usePersistence(initialConfig: TableConfig | null | undefined, saveConfi
}, []);
return { persistenceReaderFunc, persistenceWriterFunc };
}
function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undefined, newAttributePosition: RefObject<number | undefined>) {
const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
const [ columnDefs, setColumnDefs ] = useState<ColumnDefinition[]>();
const [ rowData, setRowData ] = useState<TableData[]>();
const [ movableRows, setMovableRows ] = useState<boolean>();
const [ hasChildren, setHasChildren ] = useState<boolean>();
function refresh() {
const info = getAttributeDefinitionInformation(note);
buildRowDefinitions(note, info, maxDepth).then(({ definitions: rowData, hasSubtree: hasChildren, rowNumber }) => {
const movableRows = canReorderRows(note) && !hasChildren;
const columnDefs = buildColumnDefinitions({
info,
movableRows,
existingColumnData: viewConfig?.tableData?.columns,
rowNumberHint: rowNumber,
position: newAttributePosition.current ?? undefined
});
setColumnDefs(columnDefs);
setRowData(rowData);
setMovableRows(movableRows);
setHasChildren(hasChildren);
});
}
useEffect(refresh, [ note, noteIds ]);
// React to column changes.
useTriliumEvent("entitiesReloaded", ({ loadResults}) => {
if (loadResults.getAttributeRows().find(attr =>
attr.type === "label" &&
(attr.name?.startsWith("label:") || attr.name?.startsWith("relation:")) &&
attributes.isAffecting(attr, note))) {
refresh();
}
});
return { columnDefs, rowData, movableRows, hasChildren };
}

View File

@ -0,0 +1,21 @@
import FNote from "../../../entities/fnote";
import { Attribute } from "../../../services/attribute_parser";
export function getFAttributeFromField(parentNote: FNote, field: string) {
const [ type, name ] = field.split(".", 2);
const attrName = `${type.replace("s", "")}:${name}`;
return parentNote.getLabel(attrName);
}
export function getAttributeFromField(parentNote: FNote, field: string): Attribute | undefined {
const fAttribute = getFAttributeFromField(parentNote, field);
if (fAttribute) {
return {
name: fAttribute.name,
value: fAttribute.value,
type: fAttribute.type,
isInheritable: fAttribute.isInheritable
};
}
return undefined;
}

View File

@ -52,23 +52,6 @@ export default class TableColumnEditing extends Component {
this.existingAttributeToEdit = undefined;
}
getFAttributeFromField(field: string) {
const [ type, name ] = field.split(".", 2);
const attrName = `${type.replace("s", "")}:${name}`;
return this.parentNote.getLabel(attrName);
}
getAttributeFromField(field: string): Attribute | undefined {
const fAttribute = this.getFAttributeFromField(field);
if (fAttribute) {
return {
name: fAttribute.name,
value: fAttribute.value,
type: fAttribute.type,
isInheritable: fAttribute.isInheritable
};
}
return undefined;
}
}

View File

@ -123,11 +123,7 @@ export default class TableView extends ViewMode<StateInfo> {
this.colEditing?.resetNewAttributePosition();
}
addNewRowCommand(e) { this.rowEditing?.addNewRowCommand(e); }
addNewTableColumnCommand(e) { this.colEditing?.addNewTableColumnCommand(e); }
deleteTableColumnCommand(e) { this.colEditing?.deleteTableColumnCommand(e); }
updateAttributeListCommand(e) { this.colEditing?.updateAttributeListCommand(e); }
saveAttributesCommand() { this.colEditing?.saveAttributesCommand(); }
async #manageRowsUpdate() {
if (!this.api) {