chore(react/collections/table): set up writing to attachment

This commit is contained in:
Elian Doran
2025-09-07 19:03:16 +03:00
parent c2504bb6db
commit e761cd7c27
3 changed files with 31 additions and 20 deletions

View File

@@ -1,8 +1,8 @@
import { useContext, useEffect, useRef, useState } from "preact/hooks"; import { useCallback, useContext, useEffect, useRef, useState } from "preact/hooks";
import { ViewModeProps } from "../interface"; import { ViewModeProps } from "../interface";
import { buildColumnDefinitions } from "./columns"; import { buildColumnDefinitions } from "./columns";
import getAttributeDefinitionInformation, { buildRowDefinitions, TableData } from "./rows"; import getAttributeDefinitionInformation, { buildRowDefinitions, TableData } from "./rows";
import { useNoteLabelInt } from "../../react/hooks"; import { useNoteLabelInt, useSpacedUpdate } from "../../react/hooks";
import { canReorderRows } from "../../view_widgets/table_view/dragging"; import { canReorderRows } from "../../view_widgets/table_view/dragging";
import Tabulator from "./tabulator"; import Tabulator from "./tabulator";
import { Tabulator as VanillaTabulator, SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, ColumnDefinition, DataTreeModule} from 'tabulator-tables'; import { Tabulator as VanillaTabulator, SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, ColumnDefinition, DataTreeModule} from 'tabulator-tables';
@@ -19,7 +19,7 @@ interface TableConfig {
}; };
} }
export default function TableView({ note, viewConfig }: ViewModeProps<TableConfig>) { export default function TableView({ note, viewConfig, saveConfig }: ViewModeProps<TableConfig>) {
const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1; const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
const [ columnDefs, setColumnDefs ] = useState<ColumnDefinition[]>(); const [ columnDefs, setColumnDefs ] = useState<ColumnDefinition[]>();
const [ rowData, setRowData ] = useState<TableData[]>(); const [ rowData, setRowData ] = useState<TableData[]>();
@@ -42,10 +42,12 @@ export default function TableView({ note, viewConfig }: ViewModeProps<TableConfi
}, [ note ]); }, [ note ]);
const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef); const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef);
const persistenceProps = usePersistence(viewConfig, saveConfig);
console.log("Render with viewconfig", viewConfig);
return ( return (
<div className="table-view"> <div className="table-view">
{columnDefs && ( {viewConfig && columnDefs && (
<> <>
<Tabulator <Tabulator
tabulatorRef={tabulatorRef} tabulatorRef={tabulatorRef}
@@ -55,6 +57,7 @@ export default function TableView({ note, viewConfig }: ViewModeProps<TableConfi
modules={[ SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, DataTreeModule ]} modules={[ SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, DataTreeModule ]}
footerElement={<TableFooter note={note} />} footerElement={<TableFooter note={note} />}
{...contextMenuEvents} {...contextMenuEvents}
persistence {...persistenceProps}
/> />
<TableFooter note={note} /> <TableFooter note={note} />
</> </>
@@ -74,3 +77,22 @@ function TableFooter({ note }: { note: FNote }) {
</div> </div>
) )
} }
function usePersistence(initialConfig: TableConfig | null | undefined, saveConfig: (newConfig: TableConfig) => void) {
const config = useRef<TableConfig | null | undefined>(initialConfig);
const spacedUpdate = useSpacedUpdate(() => {
if (config.current) {
saveConfig(config.current);
}
}, 5_000);
const persistenceWriterFunc = useCallback((_id, type: string, data: object) => {
if (!config.current) config.current = {};
if (!config.current.tableData) config.current.tableData = {};
(config.current.tableData as Record<string, {}>)[type] = data;
spacedUpdate.scheduleUpdate();
}, []);
const persistenceReaderFunc = useCallback((_id, type: string) => {
return config.current?.tableData?.[type];
}, []);
return { persistenceReaderFunc, persistenceWriterFunc };
}

View File

@@ -1,11 +1,11 @@
import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks"; import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks";
import { ColumnDefinition, EventCallBackMethods, Module, Tabulator as VanillaTabulator } from "tabulator-tables"; import { ColumnDefinition, EventCallBackMethods, Module, Options, Tabulator as VanillaTabulator } from "tabulator-tables";
import "tabulator-tables/dist/css/tabulator.css"; import "tabulator-tables/dist/css/tabulator.css";
import "../../../../src/stylesheets/table.css"; import "../../../../src/stylesheets/table.css";
import { ComponentChildren, RefObject } from "preact"; import { ComponentChildren, RefObject } from "preact";
import { ParentComponent, renderReactWidget } from "../../react/react_utils"; import { ParentComponent, renderReactWidget } from "../../react/react_utils";
interface TableProps<T> extends Partial<EventCallBackMethods> { interface TableProps<T> extends Partial<EventCallBackMethods>, Pick<Options, "persistence" | "persistenceReaderFunc" | "persistenceWriterFunc"> {
tabulatorRef: RefObject<VanillaTabulator>; tabulatorRef: RefObject<VanillaTabulator>;
className?: string; className?: string;
columns: ColumnDefinition[]; columns: ColumnDefinition[];
@@ -14,7 +14,7 @@ interface TableProps<T> extends Partial<EventCallBackMethods> {
footerElement?: ComponentChildren; footerElement?: ComponentChildren;
} }
export default function Tabulator<T>({ className, columns, data, modules, tabulatorRef: externalTabulatorRef, footerElement, ...events }: TableProps<T>) { export default function Tabulator<T>({ className, columns, data, modules, tabulatorRef: externalTabulatorRef, footerElement, persistence, persistenceReaderFunc, persistenceWriterFunc, ...events }: TableProps<T>) {
const parentComponent = useContext(ParentComponent); const parentComponent = useContext(ParentComponent);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const tabulatorRef = useRef<VanillaTabulator>(null); const tabulatorRef = useRef<VanillaTabulator>(null);
@@ -32,7 +32,8 @@ export default function Tabulator<T>({ className, columns, data, modules, tabula
const tabulator = new VanillaTabulator(containerRef.current, { const tabulator = new VanillaTabulator(containerRef.current, {
columns, columns,
data, data,
footerElement: (parentComponent && footerElement ? renderReactWidget(parentComponent, footerElement)[0] : undefined) footerElement: (parentComponent && footerElement ? renderReactWidget(parentComponent, footerElement)[0] : undefined),
persistence, persistenceReaderFunc, persistenceWriterFunc
}); });
tabulatorRef.current = tabulator; tabulatorRef.current = tabulator;

View File

@@ -64,15 +64,9 @@ export default class TableView extends ViewMode<StateInfo> {
let opts: Options = { let opts: Options = {
layout: "fitDataFill", layout: "fitDataFill",
index: "branchId", index: "branchId",
persistence: true,
movableColumns: true, movableColumns: true,
movableRows, movableRows,
footerElement: buildFooter(this.parentNote), footerElement: buildFooter(this.parentNote),
persistenceWriterFunc: (_id, type: string, data: object) => {
(this.persistentData as Record<string, {}>)[type] = data;
this.spacedUpdate.scheduleUpdate();
},
persistenceReaderFunc: (_id, type: string) => this.persistentData?.[type],
}; };
if (hasChildren) { if (hasChildren) {
@@ -99,12 +93,6 @@ export default class TableView extends ViewMode<StateInfo> {
setupContextMenu(this.api, this.parentNote); setupContextMenu(this.api, this.parentNote);
} }
private onSave() {
this.viewStorage.store({
tableData: this.persistentData,
});
}
async onEntitiesReloaded({ loadResults }: EventData<"entitiesReloaded">) { async onEntitiesReloaded({ loadResults }: EventData<"entitiesReloaded">) {
if (!this.api) { if (!this.api) {
return; return;