feat(views/table): automatic index col width

This commit is contained in:
Elian Doran
2025-07-17 20:44:31 +03:00
parent 9d7455d28a
commit 669a3d9dcf
4 changed files with 39 additions and 9 deletions

View File

@@ -119,4 +119,15 @@ describe("restoreExistingData", () => {
const restored = restoreExistingData(newDefs, oldDefs); const restored = restoreExistingData(newDefs, oldDefs);
expect(restored[0].visible).toStrictEqual(false); expect(restored[0].visible).toStrictEqual(false);
}); });
it("enforces size for non-resizable columns", () => {
const newDefs: ColumnDefinition[] = [
{ title: "#", resizable: false, width: "100px" },
]
const oldDefs: ColumnDefinition[] = [
{ title: "#", resizable: false, width: "120px" },
];
const restored = restoreExistingData(newDefs, oldDefs);
expect(restored[0].width).toStrictEqual("100px");
});
}); });

View File

@@ -41,7 +41,7 @@ const labelTypeMappings: Record<ColumnType, Partial<ColumnDefinition>> = {
} }
}; };
export function buildColumnDefinitions(info: AttributeDefinitionInformation[], movableRows: boolean, existingColumnData: ColumnDefinition[] | undefined, position?: number) { export function buildColumnDefinitions(info: AttributeDefinitionInformation[], movableRows: boolean, existingColumnData: ColumnDefinition[] | undefined, rowNumberHint: number, position?: number) {
let columnDefs: ColumnDefinition[] = [ let columnDefs: ColumnDefinition[] = [
{ {
title: "#", title: "#",
@@ -50,6 +50,7 @@ export function buildColumnDefinitions(info: AttributeDefinitionInformation[], m
resizable: false, resizable: false,
frozen: true, frozen: true,
rowHandle: movableRows, rowHandle: movableRows,
width: calculateIndexColumnWidth(rowNumberHint, movableRows),
formatter: RowNumberFormatter(movableRows) formatter: RowNumberFormatter(movableRows)
}, },
{ {
@@ -66,6 +67,7 @@ export function buildColumnDefinitions(info: AttributeDefinitionInformation[], m
width: 400 width: 400
} }
]; ];
console.log("Log ", rowNumberHint, columnDefs[0].width);
const seenFields = new Set<string>(); const seenFields = new Set<string>();
for (const { name, title, type } of info) { for (const { name, title, type } of info) {
@@ -102,7 +104,7 @@ export function restoreExistingData(newDefs: ColumnDefinition[], oldDefs: Column
.filter(item => (item.field && newItemsByField.has(item.field!)) || item.title === "#") .filter(item => (item.field && newItemsByField.has(item.field!)) || item.title === "#")
.map(oldItem => { .map(oldItem => {
const data = newItemsByField.get(oldItem.field!)!; const data = newItemsByField.get(oldItem.field!)!;
if (oldItem.width !== undefined) { if (oldItem.resizable && oldItem.width !== undefined) {
data.width = oldItem.width; data.width = oldItem.width;
} }
if (oldItem.visible !== undefined) { if (oldItem.visible !== undefined) {
@@ -128,3 +130,11 @@ export function restoreExistingData(newDefs: ColumnDefinition[], oldDefs: Column
...existingColumns.slice(insertPos) ...existingColumns.slice(insertPos)
]; ];
} }
function calculateIndexColumnWidth(rowNumberHint: number, movableRows: boolean): number {
let columnWidth = 16 * (rowNumberHint.toString().length || 1);
if (movableRows) {
columnWidth += 32;
}
return columnWidth;
}

View File

@@ -105,6 +105,7 @@ export default class TableView extends ViewMode<StateInfo> {
private colEditing?: TableColumnEditing; private colEditing?: TableColumnEditing;
private rowEditing?: TableRowEditing; private rowEditing?: TableRowEditing;
private maxDepth: number = -1; private maxDepth: number = -1;
private rowNumberHint: number = 1;
constructor(args: ViewModeArgs) { constructor(args: ViewModeArgs) {
super(args, "table"); super(args, "table");
@@ -137,9 +138,10 @@ export default class TableView extends ViewMode<StateInfo> {
this.persistentData = viewStorage?.tableData || {}; this.persistentData = viewStorage?.tableData || {};
this.maxDepth = parseInt(this.parentNote.getLabelValue("maxNestingDepth") ?? "-1", 10); this.maxDepth = parseInt(this.parentNote.getLabelValue("maxNestingDepth") ?? "-1", 10);
const { definitions: rowData, hasSubtree: hasChildren } = await buildRowDefinitions(this.parentNote, info, this.maxDepth); const { definitions: rowData, hasSubtree: hasChildren, rowNumber } = await buildRowDefinitions(this.parentNote, info, this.maxDepth);
this.rowNumberHint = rowNumber;
const movableRows = canReorderRows(this.parentNote) && !hasChildren; const movableRows = canReorderRows(this.parentNote) && !hasChildren;
const columnDefs = buildColumnDefinitions(info, movableRows, this.persistentData.columns); const columnDefs = buildColumnDefinitions(info, movableRows, this.persistentData.columns, this.rowNumberHint);
let opts: Options = { let opts: Options = {
layout: "fitDataFill", layout: "fitDataFill",
index: "branchId", index: "branchId",
@@ -226,7 +228,7 @@ export default class TableView extends ViewMode<StateInfo> {
} }
const info = getAttributeDefinitionInformation(this.parentNote); const info = getAttributeDefinitionInformation(this.parentNote);
const columnDefs = buildColumnDefinitions(info, !!this.api.options.movableRows, this.persistentData?.columns, this.colEditing?.getNewAttributePosition()); const columnDefs = buildColumnDefinitions(info, !!this.api.options.movableRows, this.persistentData?.columns, this.colEditing?.getNewAttributePosition(), this.rowNumberHint);
this.api.setColumns(columnDefs); this.api.setColumns(columnDefs);
this.colEditing?.resetNewAttributePosition(); this.colEditing?.resetNewAttributePosition();
} }
@@ -243,7 +245,8 @@ export default class TableView extends ViewMode<StateInfo> {
} }
const info = getAttributeDefinitionInformation(this.parentNote); const info = getAttributeDefinitionInformation(this.parentNote);
const { definitions, hasSubtree } = await buildRowDefinitions(this.parentNote, info, this.maxDepth); const { definitions, hasSubtree, rowNumber } = await buildRowDefinitions(this.parentNote, info, this.maxDepth);
this.rowNumberHint = rowNumber;
// Force a refresh if the data tree needs enabling/disabling. // Force a refresh if the data tree needs enabling/disabling.
if (this.api.options.dataTree !== hasSubtree) { if (this.api.options.dataTree !== hasSubtree) {

View File

@@ -14,8 +14,11 @@ export type TableData = {
export async function buildRowDefinitions(parentNote: FNote, infos: AttributeDefinitionInformation[], maxDepth = -1, currentDepth = 0) { export async function buildRowDefinitions(parentNote: FNote, infos: AttributeDefinitionInformation[], maxDepth = -1, currentDepth = 0) {
const definitions: TableData[] = []; const definitions: TableData[] = [];
const childBranches = parentNote.getChildBranches();
let hasSubtree = false; let hasSubtree = false;
for (const branch of parentNote.getChildBranches()) { let rowNumber = childBranches.length;
for (const branch of childBranches) {
const note = await branch.getNote(); const note = await branch.getNote();
if (!note) { if (!note) {
continue; // Skip if the note is not found continue; // Skip if the note is not found
@@ -41,8 +44,10 @@ export async function buildRowDefinitions(parentNote: FNote, infos: AttributeDef
} }
if (note.hasChildren() && (maxDepth < 0 || currentDepth < maxDepth)) { if (note.hasChildren() && (maxDepth < 0 || currentDepth < maxDepth)) {
def._children = (await buildRowDefinitions(note, infos, maxDepth, currentDepth + 1)).definitions; const { definitions, rowNumber: subRowNumber } = (await buildRowDefinitions(note, infos, maxDepth, currentDepth + 1));
def._children = definitions;
hasSubtree = true; hasSubtree = true;
rowNumber += subRowNumber;
} }
definitions.push(def); definitions.push(def);
@@ -50,7 +55,8 @@ export async function buildRowDefinitions(parentNote: FNote, infos: AttributeDef
return { return {
definitions, definitions,
hasSubtree hasSubtree,
rowNumber
}; };
} }