Skip to content

Commit

Permalink
feat(visualizer): improve default layout with dagrejs
Browse files Browse the repository at this point in the history
Improve default layout with dagrejs
  • Loading branch information
BOCOVO committed Oct 8, 2024
1 parent 9d56df5 commit 024dbdd
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 80 deletions.
6 changes: 5 additions & 1 deletion packages/extension-shared/src/hooks/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ export const useSchema = (): {

if (message.key !== schemaKey) {
// update stores
tableCoordsStore.switchTo(message.key, message.payload.tables);
tableCoordsStore.switchTo(
message.key,
message.payload.tables,
message.payload.refs,
);
stageStateStore.switchTo(message.key);
detailLevelStore.switchTo(message.key);

Expand Down
1 change: 1 addition & 0 deletions packages/json-table-schema-visualizer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"@dagrejs/dagre": "^1.1.2",
"eventemitter3": "^5.0.1",
"konva": "^9.3.6",
"lucide-react": "^0.365.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const DiagramViewerStory: Story = {
},
decorators: [
(Story) => {
tableCoordsStore.resetPositions(tables);
tableCoordsStore.resetPositions(tables, exampleData.refs);

return <Story />;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const DiagramViewer = ({ refs, tables, enums }: DiagramViewerProps) => {

return (
<TableLevelDetailProvider>
<TablesPositionsProvider tables={tables}>
<TablesPositionsProvider tables={tables} refs={refs}>
<MainProviders tables={tables} enums={enums}>
<DiagramWrapper>
<RelationsConnections refs={refs} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const DiagramWrapperWrapper: Story = {
},
decorators: [
(Story) => (
<TablesPositionsProvider tables={[]}>
<TablesPositionsProvider tables={[]} refs={[]}>
<Story />
</TablesPositionsProvider>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ type Story = StoryObj<typeof RelationConnection>;

export const RelationConnectionStory: Story = {
render: (props) => (
<TablesPositionsProvider tables={exampleData.tables}>
<TablesPositionsProvider
tables={exampleData.tables}
refs={exampleData.refs}
>
<MainProviders enums={exampleData.enums} tables={exampleData.tables}>
<RelationConnection {...props} />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Story = StoryObj<typeof Table>;

export const TableStory: Story = {
render: (props) => (
<TablesPositionsProvider tables={[]}>
<TablesPositionsProvider tables={[]} refs={[]}>
<MainProviders enums={exampleData.enums} tables={exampleData.tables}>
<Table {...props} />
</MainProviders>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const AutoArrangeTableButtonStory: Story = {
render: () => <AutoArrangeTableButton />,
decorators: [
(Story) => (
<TablesPositionsProvider tables={[]}>
<TablesPositionsProvider tables={[]} refs={[]}>
<Story />
</TablesPositionsProvider>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ToolbarStory: Story = {
decorators: [
(Story) => (
<div className="py-32">
<TablesPositionsProvider tables={[]}>
<TablesPositionsProvider tables={[]} refs={[]}>
<Story />
</TablesPositionsProvider>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, useMemo, type PropsWithChildren } from "react";
import { type JSONTableTable } from "shared/types/tableSchema";

import type { JSONTableRef, JSONTableTable } from "shared/types/tableSchema";
import type { TablesPositionsContextValue } from "@/types/dimension";

import { tableCoordsStore } from "@/stores/tableCoords";
Expand All @@ -10,14 +10,16 @@ export const TablesPositionsContext =

interface TablesPositionsProviderProps extends PropsWithChildren {
tables: JSONTableTable[];
refs: JSONTableRef[];
}

const TablesPositionsProvider = ({
tables,
refs,
children,
}: TablesPositionsProviderProps) => {
const resetPositions = () => {
tableCoordsStore.resetPositions(tables);
tableCoordsStore.resetPositions(tables, refs);
};

const contextValue = useMemo(() => ({ resetPositions }), [resetPositions]);
Expand Down
15 changes: 9 additions & 6 deletions packages/json-table-schema-visualizer/src/stores/tableCoords.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { type JSONTableTable } from "shared/types/tableSchema";

import { PersistableStore } from "./PersitableStore";

import type { JSONTableRef, JSONTableTable } from "shared/types/tableSchema";
import type { XYPosition } from "@/types/positions";

import computeTablesPositions from "@/utils/tablePositioning/computeTablesPositions";
Expand Down Expand Up @@ -35,8 +34,8 @@ class TableCoordsStore extends PersistableStore<Array<[string, XYPosition]>> {
};
}

public resetPositions(tables: JSONTableTable[]): void {
const newTablesPos = computeTablesPositions(tables);
public resetPositions(tables: JSONTableTable[], refs: JSONTableRef[]): void {
const newTablesPos = computeTablesPositions(tables, refs);
this.tableCoords = newTablesPos;
eventEmitter.emit(TableCoordsStore.RESET_POS_EVENT_NAME, newTablesPos);
}
Expand All @@ -52,15 +51,19 @@ class TableCoordsStore extends PersistableStore<Array<[string, XYPosition]>> {
this.persist(this.currentStoreKey, storeValue);
}

public switchTo(newStoreKey: string, newTables: JSONTableTable[]): void {
public switchTo(
newStoreKey: string,
newTables: JSONTableTable[],
refs: JSONTableRef[],
): void {
this.saveCurrentStore();

this.currentStoreKey = newStoreKey;
const recoveredStore = this.retrieve(this.currentStoreKey) as Array<
[string, XYPosition]
>;
if (recoveredStore === null || !Array.isArray(recoveredStore)) {
this.resetPositions(newTables);
this.resetPositions(newTables, refs);
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,43 @@
import { type JSONTableTable } from "shared/types/tableSchema";
import dagre from "@dagrejs/dagre";

import { computeTableDimension } from "../computeTableDimension";

import { getColsNumber } from "./getColsNumber";
import type { JSONTableRef, JSONTableTable } from "shared/types/tableSchema";

import { TABLES_GAP_X, TABLES_GAP_Y } from "@/constants/sizing";
import { type XYPosition } from "@/types/positions";

const computeTablesPositions = (
tables: JSONTableTable[],
refs: JSONTableRef[],
): Map<string, XYPosition> => {
const colNumber = getColsNumber(tables.length);

let nextColsY = 0;

const tablesPositions = new Map<string, XYPosition>();
let nextTableX = 0;

for (let colIndex = 0; colIndex < colNumber; colIndex++) {
let currentColMaxW = 0;

const currentColX = nextTableX;

for (
let tableIndex = colIndex;
tableIndex < tables.length;
tableIndex += colNumber
) {
const table = tables[tableIndex];
const colY = nextColsY ?? 0;

tablesPositions.set(table.name, { x: currentColX, y: colY });

const tableDimension = computeTableDimension(table);
const isLastTableInCol = tableIndex + colNumber > tables.length - 1;
nextColsY = isLastTableInCol
? 0
: colY + tableDimension.height + TABLES_GAP_Y;

currentColMaxW = Math.max(tableDimension.width, currentColMaxW);

nextTableX = isLastTableInCol
? currentColMaxW + TABLES_GAP_X + currentColX
: currentColX;
}
}

const graph = new dagre.graphlib.Graph();
graph.setGraph({
nodesep: TABLES_GAP_X * 3,
ranksep: TABLES_GAP_Y * 3,
rankdir: "LR",
});
graph.setDefaultEdgeLabel(function () {
return {};
});

tables.forEach((table) => {
const { height, width } = computeTableDimension(table);
graph.setNode(table.name, { width, height });
});

refs.forEach((ref) => {
graph.setEdge(ref.endpoints[0].tableName, ref.endpoints[1].tableName);
});

dagre.layout(graph);

graph.nodes().forEach((node) => {
const { x, y } = graph.node(node);
tablesPositions.set(node, { x, y });
});
return tablesPositions;
};

Expand Down
43 changes: 15 additions & 28 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,18 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==

"@dagrejs/dagre@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@dagrejs/dagre/-/dagre-1.1.2.tgz#5ec339979447091f48d2144deed8c70dfadae374"
integrity sha512-F09dphqvHsbe/6C2t2unbmpr5q41BNPEfJCdn8Z7aEBpVSy/zFQ/b4SWsweQjWNsYMDvE2ffNUN8X0CeFsEGNw==
dependencies:
"@dagrejs/graphlib" "2.2.2"

"@dagrejs/[email protected]":
version "2.2.2"
resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.2.tgz#74154d5cb880a23b4fae71034a09b4b5aef06feb"
integrity sha512-CbyGpCDKsiTg/wuk79S7Muoj8mghDGAESWGxcSyhHX5jD35vYMBZochYVFzlHxynpE9unpu6O+4ZuhrLxASsOg==

"@dbml/core@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@dbml/core/-/core-3.4.0.tgz#d6358b03708231b78b9f59999d1a37807c30a43b"
Expand Down Expand Up @@ -10825,16 +10837,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"

"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -10921,14 +10924,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -11876,7 +11872,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -11894,15 +11890,6 @@ wrap-ansi@^6.0.1:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit 024dbdd

Please sign in to comment.