Skip to content

Commit 8fe0954

Browse files
herzadinataBOCOVO
authored andcommitted
fix(dblm-ext): tables distance fixed
1 parent 82d9853 commit 8fe0954

File tree

6 files changed

+108
-50
lines changed

6 files changed

+108
-50
lines changed

packages/json-table-schema-visualizer/src/components/Search/Search.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ const Search = ({ tables }: SearchProps) => {
172172
className="w-full px-4 py-2 text-left text-sm focus:outline-none hover:bg-gray-100 dark:hover:bg-gray-600 focus:bg-gray-100 dark:focus:bg-gray-600 flex flex-col items-start"
173173
>
174174
<div className="flex space-x-2 w-full items-start">
175+
<span className="text-xs mt-[3px]">
176+
{result.type === "table" ? "📋" : "🔤"}
177+
</span>
175178
<span className="font-medium break-all text-gray-700 dark:text-gray-200">
176179
{result.name}
177180
</span>

packages/json-table-schema-visualizer/src/utils/tablePositioning/computeTablesPositions.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ const computeTablesPositions = (
1111
tables: JSONTableTable[],
1212
refs: JSONTableRef[],
1313
): Map<string, XYPosition> => {
14-
const tablesPositions = new Map<string, XYPosition>();
15-
1614
const graph = new dagre.graphlib.Graph();
1715
graph.setGraph({
1816
nodesep: TABLES_GAP_X * 3,
@@ -34,10 +32,36 @@ const computeTablesPositions = (
3432

3533
dagre.layout(graph);
3634

35+
const rawPositions: Array<{ name: string; x: number; y: number }> = [];
36+
3737
graph.nodes().forEach((node) => {
38-
const { x, y } = graph.node(node);
39-
tablesPositions.set(node, { x, y });
38+
const nodeData = graph.node(node);
39+
if (nodeData == null) return;
40+
const width = !isNaN(nodeData.width) ? nodeData.width : 0;
41+
const height = !isNaN(nodeData.height) ? nodeData.height : 0;
42+
const topLeftX = nodeData.x - width / 2;
43+
const topLeftY = nodeData.y - height / 2;
44+
rawPositions.push({ name: node, x: topLeftX, y: topLeftY });
45+
});
46+
47+
if (rawPositions.length === 0) {
48+
return new Map<string, XYPosition>();
49+
}
50+
51+
const minX = Math.min(...rawPositions.map((pos) => pos.x));
52+
const minY = Math.min(...rawPositions.map((pos) => pos.y));
53+
54+
const paddingX = TABLES_GAP_X;
55+
const paddingY = TABLES_GAP_Y;
56+
57+
const tablesPositions = new Map<string, XYPosition>();
58+
rawPositions.forEach((pos) => {
59+
tablesPositions.set(pos.name, {
60+
x: pos.x - minX + paddingX,
61+
y: pos.y - minY + paddingY,
62+
});
4063
});
64+
4165
return tablesPositions;
4266
};
4367

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,68 @@
11
import computeTablesPositions from "../computeTablesPositions";
22
import { getColsNumber } from "../getColsNumber";
33

4-
import {
5-
COLUMN_HEIGHT,
6-
TABLE_HEADER_HEIGHT,
7-
TABLE_DEFAULT_MIN_WIDTH,
8-
TABLES_GAP_X,
9-
TABLES_GAP_Y,
10-
} from "@/constants/sizing";
4+
import { TABLES_GAP_Y } from "@/constants/sizing";
115
import { createBookingsTableClone, exampleData } from "@/fake/fakeJsonTables";
126

137
jest.mock("../getColsNumber", () => ({
148
getColsNumber: jest.fn(),
159
}));
1610

17-
const TABLE_WIDTH_WITH_GAP = TABLE_DEFAULT_MIN_WIDTH + TABLES_GAP_X;
11+
jest.mock("../../computeTableDimension", () => ({
12+
computeTableDimension: () => ({
13+
width: 200,
14+
height: 150,
15+
}),
16+
}));
1817

19-
describe("compute tables positions", () => {
20-
test("less than 6 tables positions", () => {
21-
(getColsNumber as jest.Mock).mockReturnValue(3);
18+
describe("compute tables positions (dagre)", () => {
19+
test("keeps coordinates non-negative and unique per table", () => {
20+
const map = computeTablesPositions(exampleData.tables, []);
2221

23-
const tablesPositions = computeTablesPositions([
24-
...exampleData.tables,
25-
createBookingsTableClone("1"),
26-
]);
27-
28-
expect(tablesPositions).toEqual(
29-
new Map<string, [number, number]>([
30-
["follows", [0, 0]],
31-
["users", [TABLE_WIDTH_WITH_GAP, 0]],
32-
["bookings", [TABLE_WIDTH_WITH_GAP * 2, 0]],
33-
[
34-
"bookings_1",
35-
[0, TABLE_HEADER_HEIGHT + COLUMN_HEIGHT * 5 + TABLES_GAP_Y],
36-
],
37-
]),
38-
);
22+
expect(map.size).toBe(exampleData.tables.length);
23+
24+
const coords = Array.from(map.values());
25+
coords.forEach(({ x, y }) => {
26+
expect(x).toBeGreaterThanOrEqual(0);
27+
expect(y).toBeGreaterThanOrEqual(0);
28+
});
29+
30+
const uniqueKeys = new Set(coords.map(({ x, y }) => `${x}-${y}`));
31+
expect(uniqueKeys.size).toBe(coords.length);
3932
});
4033

41-
test("more than 6 tables positions", () => {
42-
(getColsNumber as jest.Mock).mockReturnValue(4);
43-
44-
const tablesPositions = computeTablesPositions([
45-
...exampleData.tables,
46-
createBookingsTableClone("1"),
47-
]);
48-
49-
expect(tablesPositions).toEqual(
50-
new Map<string, [number, number]>([
51-
["follows", [0, 0]],
52-
["users", [TABLE_WIDTH_WITH_GAP, 0]],
53-
["bookings", [TABLE_WIDTH_WITH_GAP * 2, 0]],
54-
["bookings_1", [TABLE_WIDTH_WITH_GAP * 3, 0]],
55-
]),
34+
test("orders tables consistently when column count changes", () => {
35+
(getColsNumber as jest.Mock).mockReturnValueOnce(3);
36+
const gridThree = computeTablesPositions(
37+
[...exampleData.tables, createBookingsTableClone("1")],
38+
[],
39+
);
40+
41+
(getColsNumber as jest.Mock).mockReturnValueOnce(4);
42+
const gridFour = computeTablesPositions(
43+
[...exampleData.tables, createBookingsTableClone("1")],
44+
[],
5645
);
46+
47+
const usersThree = gridThree.get("users");
48+
const bookingsThree = gridThree.get("bookings_1");
49+
expect(usersThree?.x ?? 0).toBeLessThanOrEqual(bookingsThree?.x ?? 0);
50+
51+
const usersFour = gridFour.get("users");
52+
const bookingsFour = gridFour.get("bookings_1");
53+
expect(usersFour?.x ?? 0).toBeLessThanOrEqual(bookingsFour?.x ?? 0);
54+
});
55+
56+
test("vertical spacing respects TABLES_GAP_Y between rows", () => {
57+
(getColsNumber as jest.Mock).mockReturnValue(3);
58+
59+
const positions = computeTablesPositions(exampleData.tables, []);
60+
const sorted = Array.from(positions.values())
61+
.sort((a, b) => a.y - b.y)
62+
.map(({ y }) => y);
63+
64+
for (let i = 1; i < sorted.length; i++) {
65+
expect(sorted[i] - sorted[i - 1]).toBeGreaterThanOrEqual(TABLES_GAP_Y);
66+
}
5767
});
5868
});

packages/json-table-schema-visualizer/src/utils/tests/computeColIndexes.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { computeColIndexes } from "../computeColIndexes";
22

33
import { exampleData } from "@/fake/fakeJsonTables";
4+
import { TableDetailLevel } from "@/types/tableDetailLevel";
45

56
describe("compute cols index map", () => {
67
test("compute cols index map", () => {
7-
expect(computeColIndexes(exampleData.tables)).toEqual({
8+
expect(
9+
computeColIndexes(exampleData.tables, TableDetailLevel.FullDetails),
10+
).toEqual({
811
"users.id": 0,
912
"users.email": 1,
1013
"bookings.booking_date": 2,

packages/json-table-schema-visualizer/src/utils/tests/computeTableDimension.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,24 @@ import { exampleData } from "@/fake/fakeJsonTables";
44
import {
55
TABLE_HEADER_HEIGHT,
66
TABLE_DEFAULT_MIN_WIDTH,
7+
COLUMN_HEIGHT,
78
} from "@/constants/sizing";
89

10+
jest.mock("../computeTextSize", () => ({
11+
computeTextSize: jest.fn((text: string) => ({
12+
width: text.length,
13+
height: 10,
14+
})),
15+
}));
16+
917
describe("compute table dimension", () => {
1018
test("compute table dimension", () => {
11-
expect(computeTableDimension(exampleData.tables[0])).toEqual({
19+
const table = exampleData.tables[0];
20+
const expectedHeight =
21+
TABLE_HEADER_HEIGHT + COLUMN_HEIGHT * table.fields.length;
22+
expect(computeTableDimension(table)).toEqual({
1223
width: TABLE_DEFAULT_MIN_WIDTH,
13-
height: TABLE_HEADER_HEIGHT * 5,
24+
height: expectedHeight,
1425
});
1526
});
1627
});
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import { computeTextSize } from "../computeTextSize";
22
import { computeTextsMaxWidth } from "../computeTextsMaxWidth";
33

4+
jest.mock("../computeTextSize", () => ({
5+
computeTextSize: jest.fn((text: string) => ({
6+
width: text.length,
7+
height: 10,
8+
})),
9+
}));
10+
411
describe("get the more longer text width", () => {
512
test("get the more longer text width", () => {
613
expect(computeTextsMaxWidth(["simple", "more longer"])).toBe(
7-
computeTextSize("more longer"),
14+
computeTextSize("more longer").width,
815
);
916
});
1017
});

0 commit comments

Comments
 (0)