chore(react/collections/table): integrate cleanup

This commit is contained in:
Elian Doran 2025-09-09 19:41:38 +03:00
parent 3046cfd6ee
commit 32ce6e7a08
No known key found for this signature in database
4 changed files with 19 additions and 150 deletions

View File

@ -2,7 +2,7 @@ import { useLegacyImperativeHandlers } from "../../react/hooks";
import { Attribute } from "../../../services/attribute_parser";
import { RefObject } from "preact";
import { Tabulator } from "tabulator-tables";
import { useRef, useState } from "preact/hooks";
import { useRef } from "preact/hooks";
import { CommandListenerData, EventData } from "../../../components/app_context";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import attributes from "../../../services/attributes";
@ -14,7 +14,7 @@ import { executeBulkActions } from "../../../services/bulk_action";
export default function useColTableEditing(api: RefObject<Tabulator>, attributeDetailWidget: AttributeDetailWidget, parentNote: FNote) {
const [ existingAttributeToEdit, setExistingAttributeToEdit ] = useState<Attribute>();
const existingAttributeToEdit = useRef<Attribute>();
const newAttribute = useRef<Attribute>();
const newAttributePosition = useRef<number>();
@ -22,11 +22,11 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
addNewTableColumnCommand({ referenceColumn, columnToEdit, direction, type }: EventData<"addNewTableColumn">) {
let attr: Attribute | undefined;
setExistingAttributeToEdit(undefined);
existingAttributeToEdit.current = undefined;
if (columnToEdit) {
attr = getAttributeFromField(parentNote, columnToEdit.getField());
if (attr) {
setExistingAttributeToEdit({ ...attr });
existingAttributeToEdit.current = { ...attr };
}
}
@ -71,16 +71,16 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
const { name, value, isInheritable } = newAttribute.current;
api.current.blockRedraw();
const isRename = (existingAttributeToEdit && existingAttributeToEdit.name !== name);
const isRename = (existingAttributeToEdit.current && existingAttributeToEdit.current.name !== name);
try {
if (isRename) {
const oldName = existingAttributeToEdit!.name.split(":")[1];
const oldName = existingAttributeToEdit.current!.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, existingAttributeToEdit.name);
if (existingAttributeToEdit.current && (isRename || existingAttributeToEdit.current.isInheritable !== isInheritable)) {
attributes.removeOwnedLabelByName(parentNote, existingAttributeToEdit.current.name);
}
attributes.setLabel(parentNote.noteId, name, value, isInheritable);
} finally {
@ -108,7 +108,13 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
}
});
return { newAttributePosition };
function resetNewAttributePosition() {
newAttribute.current = undefined;
newAttributePosition.current = undefined;
existingAttributeToEdit.current = undefined;
}
return { newAttributePosition, resetNewAttributePosition };
}
async function deleteColumn(parentNoteId: string, type: "label" | "relation", columnName: string) {

View File

@ -31,8 +31,8 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef);
const persistenceProps = usePersistence(viewConfig, saveConfig);
const rowEditingEvents = useRowTableEditing(tabulatorRef, attributeDetailWidget, notePath);
const { newAttributePosition } = useColTableEditing(tabulatorRef, attributeDetailWidget, note);
const { columnDefs, rowData, movableRows, hasChildren } = useData(note, noteIds, viewConfig, newAttributePosition);
const { newAttributePosition, resetNewAttributePosition } = useColTableEditing(tabulatorRef, attributeDetailWidget, note);
const { columnDefs, rowData, movableRows, hasChildren } = useData(note, noteIds, viewConfig, newAttributePosition, resetNewAttributePosition);
const dataTreeProps = useMemo<Options>(() => {
if (!hasChildren) return {};
return {
@ -108,7 +108,7 @@ function usePersistence(initialConfig: TableConfig | null | undefined, saveConfi
return { persistenceReaderFunc, persistenceWriterFunc };
}
function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undefined, newAttributePosition: RefObject<number | undefined>) {
function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undefined, newAttributePosition: RefObject<number | undefined>, resetNewAttributePosition: () => void) {
const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
const [ columnDefs, setColumnDefs ] = useState<ColumnDefinition[]>();
@ -130,6 +130,7 @@ function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undef
setColumnDefs(columnDefs);
setRowData(rowData);
setHasChildren(hasChildren);
resetNewAttributePosition();
});
}

View File

@ -1,37 +0,0 @@
import { Tabulator } from "tabulator-tables";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import Component from "../../../components/component";
import { CommandListenerData, EventData } from "../../../components/app_context";
import attributes from "../../../services/attributes";
import FNote from "../../../entities/fnote";
import { deleteColumn, renameColumn } from "./bulk_actions";
import dialog from "../../../services/dialog";
import { t } from "../../../services/i18n";
export default class TableColumnEditing extends Component {
private api: Tabulator;
private parentNote: FNote;
private newAttribute?: Attribute;
constructor($parent: JQuery<HTMLElement>, parentNote: FNote, api: Tabulator) {
super();
const parentComponent = glob.getComponentByEl($parent[0]);
this.api = api;
this.parentNote = parentNote;
}
getNewAttributePosition() {
return this.newAttributePosition;
}
resetNewAttributePosition() {
this.newAttribute = undefined;
this.newAttributePosition = undefined;
this.existingAttributeToEdit = undefined;
}
}

View File

@ -1,101 +0,0 @@
import ViewMode, { type ViewModeArgs } from "../view_mode.js";
import attributes from "../../../services/attributes.js";
import SpacedUpdate from "../../../services/spaced_update.js";
import type { EventData } from "../../../components/app_context.js";
import buildFooter from "./footer.js";
import getAttributeDefinitionInformation, { buildRowDefinitions } from "./rows.js";
import { AttributeDefinitionInformation, buildColumnDefinitions } from "./columns.js";
import { setupContextMenu } from "./context_menu.js";
import TableColumnEditing from "./col_editing.js";
import TableRowEditing from "./row_editing.js";
const TPL = /*html*/`
<style>
</style>
`;
export interface StateInfo {
}
export default class TableView extends ViewMode<StateInfo> {
private $root: JQuery<HTMLElement>;
private $container: JQuery<HTMLElement>;
private spacedUpdate: SpacedUpdate;
private api?: Tabulator;
private persistentData: StateInfo["tableData"];
private colEditing?: TableColumnEditing;
private rowEditing?: TableRowEditing;
private maxDepth: number = -1;
private rowNumberHint: number = 1;
constructor(args: ViewModeArgs) {
super(args, "table");
this.$root = $(TPL);
this.$container = this.$root.find(".table-view-container");
this.spacedUpdate = new SpacedUpdate(() => this.onSave(), 5_000);
this.persistentData = {};
args.$parent.append(this.$root);
}
async renderList() {
this.$container.empty();
this.renderTable(this.$container[0]);
return this.$root;
}
private async initialize(el: HTMLElement, info: AttributeDefinitionInformation[]) {
const viewStorage = await this.viewStorage.restore();
this.persistentData = viewStorage?.tableData || {};
this.api = new Tabulator(el, opts);
this.colEditing = new TableColumnEditing(this.args.$parent, this.args.parentNote, this.api);
this.rowEditing = new TableRowEditing(this.api, this.args.parentNotePath!);
setupContextMenu(this.api, this.parentNote);
}
#manageColumnUpdate() {
if (!this.api) {
return;
}
const info = getAttributeDefinitionInformation(this.parentNote);
const columnDefs = buildColumnDefinitions({
info,
movableRows: !!this.api.options.movableRows,
existingColumnData: this.persistentData?.columns,
rowNumberHint: this.rowNumberHint,
position: this.colEditing?.getNewAttributePosition()
});
this.api.setColumns(columnDefs);
this.colEditing?.resetNewAttributePosition();
}
deleteTableColumnCommand(e) { this.colEditing?.deleteTableColumnCommand(e); }
async #manageRowsUpdate() {
if (!this.api) {
return;
}
const info = getAttributeDefinitionInformation(this.parentNote);
const { definitions, hasSubtree, rowNumber } = await buildRowDefinitions(this.parentNote, info, this.maxDepth);
this.rowNumberHint = rowNumber;
// Force a refresh if the data tree needs enabling/disabling.
if (this.api.options.dataTree !== hasSubtree) {
return true;
}
await this.api.replaceData(definitions);
return false;
}
}