Skip to content

Commit 779366c

Browse files
committed
feat(SchemaViewer): calculate column width based on data
1 parent 1a833e3 commit 779366c

File tree

6 files changed

+122
-14
lines changed

6 files changed

+122
-14
lines changed

src/components/QueryResultTable/QueryResultTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import type {Column, Settings} from '@gravity-ui/react-data-table';
66
import type {ColumnType, KeyValueRow} from '../../types/api/query';
77
import {cn} from '../../utils/cn';
88
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
9+
import {getColumnWidth} from '../../utils/getColumnWidth';
910
import {getColumnType, prepareQueryResponse} from '../../utils/query';
1011
import {isNumeric} from '../../utils/utils';
1112
import type {ResizeableDataTableProps} from '../ResizeableDataTable/ResizeableDataTable';
1213
import {ResizeableDataTable} from '../ResizeableDataTable/ResizeableDataTable';
1314

1415
import {Cell} from './Cell';
1516
import i18n from './i18n';
16-
import {getColumnWidth} from './utils/getColumnWidth';
1717

1818
import './QueryResultTable.scss';
1919

src/containers/Tenant/Schema/SchemaViewer/SchemaViewer.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,20 @@ export const SchemaViewer = ({type, path, tenantName, extended = false}: SchemaV
7171

7272
const columns = React.useMemo(() => {
7373
if (isViewType(type)) {
74-
return getViewColumns();
74+
return getViewColumns(tableData);
7575
}
7676
if (isExternalTableType(type)) {
77-
return getExternalTableColumns();
77+
return getExternalTableColumns(tableData);
7878
}
7979
if (isColumnEntityType(type)) {
80-
return getColumnTableColumns();
80+
return getColumnTableColumns(tableData);
8181
}
8282
if (isRowTableType(type)) {
83-
return getRowTableColumns(extended, hasAutoIncrement, hasDefaultValue);
83+
return getRowTableColumns(tableData, extended, hasAutoIncrement, hasDefaultValue);
8484
}
8585

8686
return [];
87-
}, [type, extended, hasAutoIncrement, hasDefaultValue]);
87+
}, [type, extended, hasAutoIncrement, hasDefaultValue, tableData]);
8888

8989
if (loading || isViewSchemaLoading) {
9090
return <TableSkeleton />;

src/containers/Tenant/Schema/SchemaViewer/columns.tsx

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import DataTable from '@gravity-ui/react-data-table';
22

3+
import {getColumnWidth} from '../../../../utils/getColumnWidth';
4+
35
import i18n from './i18n';
46
import type {SchemaColumn, SchemaData} from './types';
57

@@ -108,16 +110,37 @@ const compressionColumn: SchemaColumn = {
108110
render: ({row}) => row.columnCodec,
109111
};
110112

111-
export function getViewColumns(): SchemaColumn[] {
112-
return [nameColumn, typeColumn];
113+
const WIDTH_PREDICTION_ROWS_COUNT = 100;
114+
115+
function normalizeColumns(columns: SchemaColumn[], data?: SchemaData[]) {
116+
if (!data) {
117+
return columns;
118+
}
119+
const dataSlice = data.slice(0, WIDTH_PREDICTION_ROWS_COUNT);
120+
return columns.map((column) => {
121+
return {
122+
...column,
123+
width: getColumnWidth({
124+
data: dataSlice,
125+
name: column.name,
126+
header: typeof column.header === 'string' ? column.header : undefined,
127+
sortable: column.sortable === undefined,
128+
}),
129+
};
130+
});
131+
}
132+
133+
export function getViewColumns(data?: SchemaData[]): SchemaColumn[] {
134+
return normalizeColumns([nameColumn, typeColumn], data);
113135
}
114-
export function getExternalTableColumns(): SchemaColumn[] {
115-
return [idColumn, nameColumn, typeColumn, notNullColumn];
136+
export function getExternalTableColumns(data?: SchemaData[]): SchemaColumn[] {
137+
return normalizeColumns([idColumn, nameColumn, typeColumn, notNullColumn], data);
116138
}
117-
export function getColumnTableColumns(): SchemaColumn[] {
118-
return [idColumn, nameColumn, typeColumn, notNullColumn];
139+
export function getColumnTableColumns(data?: SchemaData[]): SchemaColumn[] {
140+
return normalizeColumns([idColumn, nameColumn, typeColumn, notNullColumn], data);
119141
}
120142
export function getRowTableColumns(
143+
data: SchemaData[] | undefined,
121144
extended: boolean,
122145
hasAutoIncrement: boolean,
123146
hasDefaultValue: boolean,
@@ -136,5 +159,7 @@ export function getRowTableColumns(
136159
rowTableColumns.push(autoIncrementColumn);
137160
}
138161

139-
return rowTableColumns;
162+
console.log(normalizeColumns(rowTableColumns, data));
163+
164+
return normalizeColumns(rowTableColumns, data);
140165
}

src/types/api/query.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export interface QueryPlan {
190190

191191
// ==== Common types ====
192192

193-
export type CellValue = string | number | null | undefined;
193+
export type CellValue = string | number | boolean | null | undefined;
194194

195195
export type KeyValueRow<T = CellValue> = {
196196
[key: string]: T;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {HEADER_PADDING, MAX_COLUMN_WIDTH, getColumnWidth} from '../getColumnWidth';
2+
3+
describe('getColumnWidth', () => {
4+
it('returns minimum width for empty data', () => {
5+
const result = getColumnWidth({data: [], name: 'test'});
6+
expect(result).toBe(HEADER_PADDING + 'test'.length * 10);
7+
});
8+
9+
it('calculates correct width for string columns', () => {
10+
const data = [{test: 'short'}, {test: 'medium length'}, {test: 'this is a longer string'}];
11+
const result = getColumnWidth({data, name: 'test'});
12+
expect(result).toBe(HEADER_PADDING + 'this is a longer string'.length * 10);
13+
});
14+
15+
it('returns MAX_COLUMN_WIDTH when calculated width exceeds it', () => {
16+
const data = [{test: 'a'.repeat(100)}];
17+
const result = getColumnWidth({data, name: 'test'});
18+
expect(result).toBe(MAX_COLUMN_WIDTH);
19+
});
20+
21+
it('handles undefined data correctly', () => {
22+
const result = getColumnWidth({name: 'test'});
23+
expect(result).toBe(HEADER_PADDING + 'test'.length * 10);
24+
});
25+
26+
it('handles missing values in data correctly', () => {
27+
const data = [{test: 'short'}, {}, {test: 'longer string'}];
28+
const result = getColumnWidth({data, name: 'test'});
29+
expect(result).toBe(HEADER_PADDING + 'longer string'.length * 10);
30+
});
31+
32+
it('uses column name length when all values are shorter', () => {
33+
const data = [{longColumnName: 'a'}, {longColumnName: 'bb'}];
34+
const result = getColumnWidth({data, name: 'longColumnName'});
35+
expect(result).toBe(HEADER_PADDING + 'longColumnName'.length * 10);
36+
});
37+
});

src/utils/getColumnWidth.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type {SchemaData} from '../containers/Tenant/Schema/SchemaViewer/types';
2+
import type {KeyValueRow} from '../types/api/query';
3+
4+
const MAX_COLUMN_WIDTH = 600;
5+
const HEADER_PADDING = 20;
6+
const SORT_ICON_PADDING = 18;
7+
const PIXELS_PER_CHARACTER = 10;
8+
9+
export function getColumnWidth<T extends KeyValueRow | SchemaData>({
10+
data,
11+
name,
12+
header,
13+
sortable,
14+
}: {
15+
data?: T[];
16+
name: string;
17+
header?: string;
18+
sortable?: boolean;
19+
}) {
20+
const sortPadding = sortable ? SORT_ICON_PADDING : 0;
21+
let maxColumnContentLength = typeof header === 'string' ? header.length : name.length;
22+
23+
if (data) {
24+
for (const row of data) {
25+
let cellLength = 0;
26+
if (hasProperty(row, name) && row[name]) {
27+
cellLength = String(row[name]).length;
28+
}
29+
30+
maxColumnContentLength = Math.max(maxColumnContentLength, cellLength);
31+
32+
if (
33+
maxColumnContentLength * PIXELS_PER_CHARACTER + HEADER_PADDING >=
34+
MAX_COLUMN_WIDTH
35+
) {
36+
return MAX_COLUMN_WIDTH;
37+
}
38+
}
39+
}
40+
41+
return maxColumnContentLength * PIXELS_PER_CHARACTER + HEADER_PADDING + sortPadding;
42+
}
43+
44+
function hasProperty(obj: KeyValueRow | SchemaData, key: string): obj is KeyValueRow {
45+
return key in obj;
46+
}

0 commit comments

Comments
 (0)