mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 23:59:02 +02:00
chore(react/collections/table): fix some issues with col editing
This commit is contained in:
parent
1e654fbcd6
commit
4e37a5f08e
@ -2,31 +2,27 @@ import { useLegacyImperativeHandlers } from "../../react/hooks";
|
|||||||
import { Attribute } from "../../../services/attribute_parser";
|
import { Attribute } from "../../../services/attribute_parser";
|
||||||
import { RefObject } from "preact";
|
import { RefObject } from "preact";
|
||||||
import { Tabulator } from "tabulator-tables";
|
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 { CommandListenerData, EventData } from "../../../components/app_context";
|
||||||
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
||||||
import attributes from "../../../services/attributes";
|
import attributes from "../../../services/attributes";
|
||||||
import { renameColumn } from "../../view_widgets/table_view/bulk_actions";
|
import { renameColumn } from "../../view_widgets/table_view/bulk_actions";
|
||||||
import FNote from "../../../entities/fnote";
|
import FNote from "../../../entities/fnote";
|
||||||
|
import { getAttributeFromField } from "./utils";
|
||||||
|
|
||||||
export default function useColTableEditing(api: RefObject<Tabulator>, attributeDetailWidget: AttributeDetailWidget, parentNote: FNote) {
|
export default function useColTableEditing(api: RefObject<Tabulator>, attributeDetailWidget: AttributeDetailWidget, parentNote: FNote) {
|
||||||
|
|
||||||
const [ existingAttributeToEdit, setExistingAttributeToEdit ] = useState<Attribute>();
|
const [ existingAttributeToEdit, setExistingAttributeToEdit ] = useState<Attribute>();
|
||||||
const [ newAttribute, setNewAttribute ] = useState<Attribute>();
|
const newAttribute = useRef<Attribute>();
|
||||||
const [ newAttributePosition, setNewAttributePosition ] = useState<number>();
|
const newAttributePosition = useRef<number>();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useLegacyImperativeHandlers({
|
useLegacyImperativeHandlers({
|
||||||
addNewTableColumnCommand({ referenceColumn, columnToEdit, direction, type }: EventData<"addNewTableColumn">) {
|
addNewTableColumnCommand({ referenceColumn, columnToEdit, direction, type }: EventData<"addNewTableColumn">) {
|
||||||
console.log("Ding");
|
|
||||||
let attr: Attribute | undefined;
|
let attr: Attribute | undefined;
|
||||||
|
|
||||||
setExistingAttributeToEdit(undefined);
|
setExistingAttributeToEdit(undefined);
|
||||||
if (columnToEdit) {
|
if (columnToEdit) {
|
||||||
attr = this.getAttributeFromField(columnToEdit.getField());
|
attr = getAttributeFromField(parentNote, columnToEdit.getField());
|
||||||
if (attr) {
|
if (attr) {
|
||||||
setExistingAttributeToEdit({ ...attr });
|
setExistingAttributeToEdit({ ...attr });
|
||||||
}
|
}
|
||||||
@ -47,9 +43,9 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
|
|||||||
newPosition++;
|
newPosition++;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNewAttributePosition(newPosition);
|
newAttributePosition.current = newPosition;
|
||||||
} else {
|
} else {
|
||||||
setNewAttributePosition(undefined);
|
newAttributePosition.current = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeDetailWidget.showAttributeDetail({
|
attributeDetailWidget.showAttributeDetail({
|
||||||
@ -63,26 +59,26 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
async updateAttributeListCommand({ attributes }: CommandListenerData<"updateAttributeList">) {
|
async updateAttributeListCommand({ attributes }: CommandListenerData<"updateAttributeList">) {
|
||||||
setNewAttribute(attributes[0]);
|
newAttribute.current = attributes[0];
|
||||||
},
|
},
|
||||||
async saveAttributesCommand() {
|
async saveAttributesCommand() {
|
||||||
if (!newAttribute || !api.current) {
|
if (!newAttribute.current || !api.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { name, value, isInheritable } = newAttribute;
|
const { name, value, isInheritable } = newAttribute.current;
|
||||||
|
|
||||||
api.current.blockRedraw();
|
api.current.blockRedraw();
|
||||||
const isRename = (this.existingAttributeToEdit && this.existingAttributeToEdit.name !== name);
|
const isRename = (existingAttributeToEdit && existingAttributeToEdit.name !== name);
|
||||||
try {
|
try {
|
||||||
if (isRename) {
|
if (isRename) {
|
||||||
const oldName = this.existingAttributeToEdit!.name.split(":")[1];
|
const oldName = existingAttributeToEdit!.name.split(":")[1];
|
||||||
const [ type, newName ] = name.split(":");
|
const [ type, newName ] = name.split(":");
|
||||||
await renameColumn(parentNote.noteId, type as "label" | "relation", oldName, newName);
|
await renameColumn(parentNote.noteId, type as "label" | "relation", oldName, newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingAttributeToEdit && (isRename || existingAttributeToEdit.isInheritable !== isInheritable)) {
|
if (existingAttributeToEdit && (isRename || existingAttributeToEdit.isInheritable !== isInheritable)) {
|
||||||
attributes.removeOwnedLabelByName(parentNote, this.existingAttributeToEdit.name);
|
attributes.removeOwnedLabelByName(parentNote, existingAttributeToEdit.name);
|
||||||
}
|
}
|
||||||
attributes.setLabel(parentNote.noteId, name, value, isInheritable);
|
attributes.setLabel(parentNote.noteId, name, value, isInheritable);
|
||||||
} finally {
|
} finally {
|
||||||
@ -91,5 +87,5 @@ export default function useColTableEditing(api: RefObject<Tabulator>, attributeD
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {};
|
return { newAttributePosition };
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import useRowTableEditing, { canReorderRows } from "./row_editing";
|
|||||||
import useColTableEditing from "./col_editing";
|
import useColTableEditing from "./col_editing";
|
||||||
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
|
||||||
import attributes from "../../../services/attributes";
|
import attributes from "../../../services/attributes";
|
||||||
import { refreshTextDimensions } from "@excalidraw/excalidraw/element/newElement";
|
import { RefObject } from "preact";
|
||||||
|
|
||||||
interface TableConfig {
|
interface TableConfig {
|
||||||
tableData?: {
|
tableData?: {
|
||||||
@ -24,48 +24,15 @@ interface TableConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function TableView({ note, noteIds, notePath, viewConfig, saveConfig }: ViewModeProps<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 tabulatorRef = useRef<VanillaTabulator>(null);
|
||||||
const parentComponent = useContext(ParentComponent);
|
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 [ attributeDetailWidgetEl, attributeDetailWidget ] = useLegacyWidget(() => new AttributeDetailWidget().contentSized());
|
||||||
const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef);
|
const contextMenuEvents = useContextMenu(note, parentComponent, tabulatorRef);
|
||||||
const persistenceProps = usePersistence(viewConfig, saveConfig);
|
const persistenceProps = usePersistence(viewConfig, saveConfig);
|
||||||
const rowEditingEvents = useRowTableEditing(tabulatorRef, attributeDetailWidget, notePath);
|
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>(() => {
|
const dataTreeProps = useMemo<Options>(() => {
|
||||||
if (!hasChildren) return {};
|
if (!hasChildren) return {};
|
||||||
return {
|
return {
|
||||||
@ -92,8 +59,7 @@ export default function TableView({ note, noteIds, notePath, viewConfig, saveCon
|
|||||||
footerElement={<TableFooter note={note} />}
|
footerElement={<TableFooter note={note} />}
|
||||||
events={{
|
events={{
|
||||||
...contextMenuEvents,
|
...contextMenuEvents,
|
||||||
...rowEditingEvents,
|
...rowEditingEvents
|
||||||
...colEditingEvents
|
|
||||||
}}
|
}}
|
||||||
persistence {...persistenceProps}
|
persistence {...persistenceProps}
|
||||||
layout="fitDataFill"
|
layout="fitDataFill"
|
||||||
@ -141,3 +107,44 @@ function usePersistence(initialConfig: TableConfig | null | undefined, saveConfi
|
|||||||
}, []);
|
}, []);
|
||||||
return { persistenceReaderFunc, persistenceWriterFunc };
|
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 };
|
||||||
|
}
|
||||||
|
21
apps/client/src/widgets/collections/table/utils.ts
Normal file
21
apps/client/src/widgets/collections/table/utils.ts
Normal 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;
|
||||||
|
}
|
@ -52,23 +52,6 @@ export default class TableColumnEditing extends Component {
|
|||||||
this.existingAttributeToEdit = undefined;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -123,11 +123,7 @@ export default class TableView extends ViewMode<StateInfo> {
|
|||||||
this.colEditing?.resetNewAttributePosition();
|
this.colEditing?.resetNewAttributePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
addNewRowCommand(e) { this.rowEditing?.addNewRowCommand(e); }
|
|
||||||
addNewTableColumnCommand(e) { this.colEditing?.addNewTableColumnCommand(e); }
|
|
||||||
deleteTableColumnCommand(e) { this.colEditing?.deleteTableColumnCommand(e); }
|
deleteTableColumnCommand(e) { this.colEditing?.deleteTableColumnCommand(e); }
|
||||||
updateAttributeListCommand(e) { this.colEditing?.updateAttributeListCommand(e); }
|
|
||||||
saveAttributesCommand() { this.colEditing?.saveAttributesCommand(); }
|
|
||||||
|
|
||||||
async #manageRowsUpdate() {
|
async #manageRowsUpdate() {
|
||||||
if (!this.api) {
|
if (!this.api) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user