();
+
+ return rowData && (
+
+ {!html ? (
+ {
+ const tabulator = tabulatorRef.current;
+ if (!tabulator) return;
+ setHtml(tabulator.getHtml());
+ }}
+ />
+ ) : (
+
+ )}
+
+
+ )
+}
diff --git a/apps/client/src/widgets/collections/table/data.tsx b/apps/client/src/widgets/collections/table/data.tsx
new file mode 100644
index 000000000..b77a1545e
--- /dev/null
+++ b/apps/client/src/widgets/collections/table/data.tsx
@@ -0,0 +1,77 @@
+import type { ColumnDefinition } from "tabulator-tables";
+import FNote from "../../../entities/fnote";
+import { useNoteLabelBoolean, useNoteLabelInt, useTriliumEvent } from "../../react/hooks";
+import { useEffect, useState } from "preact/hooks";
+import getAttributeDefinitionInformation, { buildRowDefinitions, TableData } from "./rows";
+import froca from "../../../services/froca";
+import { buildColumnDefinitions } from "./columns";
+import attributes from "../../../services/attributes";
+import { RefObject } from "preact";
+
+export interface TableConfig {
+ tableData: {
+ columns?: ColumnDefinition[];
+ };
+}
+
+export default function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undefined, newAttributePosition: RefObject | undefined, resetNewAttributePosition: () => void) {
+ const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
+ const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
+
+ const [ columnDefs, setColumnDefs ] = useState();
+ const [ rowData, setRowData ] = useState();
+ const [ hasChildren, setHasChildren ] = useState();
+ const [ isSorted ] = useNoteLabelBoolean(note, "sorted");
+ const [ movableRows, setMovableRows ] = useState(false);
+
+ async function refresh() {
+ const info = getAttributeDefinitionInformation(note);
+
+ // Ensure all note IDs are loaded.
+ await froca.getNotes(noteIds);
+
+ const { definitions: rowData, hasSubtree: hasChildren, rowNumber } = await buildRowDefinitions(note, info, includeArchived, maxDepth);
+ const columnDefs = buildColumnDefinitions({
+ info,
+ movableRows,
+ existingColumnData: viewConfig?.tableData?.columns,
+ rowNumberHint: rowNumber,
+ position: newAttributePosition?.current ?? undefined
+ });
+ setColumnDefs(columnDefs);
+ setRowData(rowData);
+ setHasChildren(hasChildren);
+ resetNewAttributePosition();
+ }
+
+ useEffect(() => { refresh() }, [ note, noteIds, maxDepth, movableRows ]);
+
+ useTriliumEvent("entitiesReloaded", ({ loadResults}) => {
+ if (glob.device === "print") return;
+
+ // React to column changes.
+ if (loadResults.getAttributeRows().find(attr =>
+ attr.type === "label" &&
+ (attr.name?.startsWith("label:") || attr.name?.startsWith("relation:")) &&
+ attributes.isAffecting(attr, note))) {
+ refresh();
+ return;
+ }
+
+ // React to external row updates.
+ if (loadResults.getBranchRows().some(branch => branch.parentNoteId === note.noteId || noteIds.includes(branch.parentNoteId ?? ""))
+ || loadResults.getNoteIds().some(noteId => noteIds.includes(noteId))
+ || loadResults.getAttributeRows().some(attr => noteIds.includes(attr.noteId!))
+ || loadResults.getAttributeRows().some(attr => attr.name === "archived" && attr.noteId && noteIds.includes(attr.noteId))) {
+ refresh();
+ return;
+ }
+ });
+
+ // Identify if movable rows.
+ useEffect(() => {
+ setMovableRows(!isSorted && note.type !== "search" && !hasChildren);
+ }, [ isSorted, note, hasChildren ]);
+
+ return { columnDefs, rowData, movableRows, hasChildren };
+}
diff --git a/apps/client/src/widgets/collections/table/index.tsx b/apps/client/src/widgets/collections/table/index.tsx
index f6ae82009..d557f12d3 100644
--- a/apps/client/src/widgets/collections/table/index.tsx
+++ b/apps/client/src/widgets/collections/table/index.tsx
@@ -1,10 +1,9 @@
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
import { ViewModeProps } from "../interface";
-import { buildColumnDefinitions } from "./columns";
-import getAttributeDefinitionInformation, { buildRowDefinitions, TableData } from "./rows";
-import { useLegacyWidget, useNoteLabelBoolean, useNoteLabelInt, useTriliumEvent } from "../../react/hooks";
+import { TableData } from "./rows";
+import { useLegacyWidget } from "../../react/hooks";
import Tabulator from "./tabulator";
-import { Tabulator as VanillaTabulator, SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, ColumnDefinition, DataTreeModule, Options, RowComponent} from 'tabulator-tables';
+import { Tabulator as VanillaTabulator, SortModule, FormatModule, InteractionModule, EditModule, ResizeColumnsModule, FrozenColumnsModule, PersistenceModule, MoveColumnsModule, MoveRowsModule, DataTreeModule, Options, RowComponent} from 'tabulator-tables';
import { useContextMenu } from "./context_menu";
import { ParentComponent } from "../../react/react_utils";
import FNote from "../../../entities/fnote";
@@ -14,16 +13,8 @@ import "./index.css";
import useRowTableEditing from "./row_editing";
import useColTableEditing from "./col_editing";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
-import attributes from "../../../services/attributes";
-import { RefObject } from "preact";
import SpacedUpdate from "../../../services/spaced_update";
-import froca from "../../../services/froca";
-
-interface TableConfig {
- tableData: {
- columns?: ColumnDefinition[];
- };
-}
+import useData, { TableConfig } from "./data";
export default function TableView({ note, noteIds, notePath, viewConfig, saveConfig }: ViewModeProps) {
const tabulatorRef = useRef(null);
@@ -118,67 +109,7 @@ function usePersistence(viewConfig: TableConfig | null | undefined, saveConfig:
return () => {
spacedUpdate.updateNowIfNecessary();
};
- }, [ viewConfig, saveConfig ])
+ }, [ viewConfig, saveConfig ]);
return persistenceProps;
}
-
-function useData(note: FNote, noteIds: string[], viewConfig: TableConfig | undefined, newAttributePosition: RefObject, resetNewAttributePosition: () => void) {
- const [ maxDepth ] = useNoteLabelInt(note, "maxNestingDepth") ?? -1;
- const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
-
- const [ columnDefs, setColumnDefs ] = useState();
- const [ rowData, setRowData ] = useState();
- const [ hasChildren, setHasChildren ] = useState();
- const [ isSorted ] = useNoteLabelBoolean(note, "sorted");
- const [ movableRows, setMovableRows ] = useState(false);
-
- async function refresh() {
- const info = getAttributeDefinitionInformation(note);
-
- // Ensure all note IDs are loaded.
- await froca.getNotes(noteIds);
-
- const { definitions: rowData, hasSubtree: hasChildren, rowNumber } = await buildRowDefinitions(note, info, includeArchived, maxDepth);
- const columnDefs = buildColumnDefinitions({
- info,
- movableRows,
- existingColumnData: viewConfig?.tableData?.columns,
- rowNumberHint: rowNumber,
- position: newAttributePosition.current ?? undefined
- });
- setColumnDefs(columnDefs);
- setRowData(rowData);
- setHasChildren(hasChildren);
- resetNewAttributePosition();
- }
-
- useEffect(() => { refresh() }, [ note, noteIds, maxDepth, movableRows ]);
-
- useTriliumEvent("entitiesReloaded", ({ loadResults}) => {
- // React to column changes.
- if (loadResults.getAttributeRows().find(attr =>
- attr.type === "label" &&
- (attr.name?.startsWith("label:") || attr.name?.startsWith("relation:")) &&
- attributes.isAffecting(attr, note))) {
- refresh();
- return;
- }
-
- // React to external row updates.
- if (loadResults.getBranchRows().some(branch => branch.parentNoteId === note.noteId || noteIds.includes(branch.parentNoteId ?? ""))
- || loadResults.getNoteIds().some(noteId => noteIds.includes(noteId))
- || loadResults.getAttributeRows().some(attr => noteIds.includes(attr.noteId!))
- || loadResults.getAttributeRows().some(attr => attr.name === "archived" && attr.noteId && noteIds.includes(attr.noteId))) {
- refresh();
- return;
- }
- });
-
- // Identify if movable rows.
- useEffect(() => {
- setMovableRows(!isSorted && note.type !== "search" && !hasChildren);
- }, [ isSorted, note, hasChildren ]);
-
- return { columnDefs, rowData, movableRows, hasChildren };
-}
diff --git a/apps/client/src/widgets/collections/table/tabulator.tsx b/apps/client/src/widgets/collections/table/tabulator.tsx
index 6301d5b38..31fb8d4f8 100644
--- a/apps/client/src/widgets/collections/table/tabulator.tsx
+++ b/apps/client/src/widgets/collections/table/tabulator.tsx
@@ -14,9 +14,10 @@ interface TableProps extends Omit;
index: keyof T;
footerElement?: string | HTMLElement | JSX.Element;
+ onReady?: () => void;
}
-export default function Tabulator({ className, columns, data, modules, tabulatorRef: externalTabulatorRef, footerElement, events, index, dataTree, ...restProps }: TableProps) {
+export default function Tabulator({ className, columns, data, modules, tabulatorRef: externalTabulatorRef, footerElement, events, index, dataTree, onReady, ...restProps }: TableProps) {
const parentComponent = useContext(ParentComponent);
const containerRef = useRef(null);
const tabulatorRef = useRef(null);
@@ -43,6 +44,7 @@ export default function Tabulator({ className, columns, data, modules, tabula
tabulator.on("tableBuilt", () => {
tabulatorRef.current = tabulator;
externalTabulatorRef.current = tabulator;
+ onReady?.();
});
return () => tabulator.destroy();