From 6a68508dc0ce549f6b5f6392871a6ada2181ce48 Mon Sep 17 00:00:00 2001 From: Michael Behrisch <mbehrisch@graphpolaris.com> Date: Thu, 7 Nov 2024 11:58:50 +0100 Subject: [PATCH] fix: fixes overlapping edges in schema for list layouts --- .../lib/data-access/store/schemaSlice.ts | 1 + libs/shared/lib/graph-layout/list-layouts.ts | 28 +++++++++++++------ .../lib/mock-data/query-result/mockData.ts | 3 +- .../lib/schema/panel/schema.stories.tsx | 19 +++++++------ .../vis/visualizations/tablevis/tablevis.tsx | 14 +++++----- 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/libs/shared/lib/data-access/store/schemaSlice.ts b/libs/shared/lib/data-access/store/schemaSlice.ts index 5c79edddf..1204b4bfc 100644 --- a/libs/shared/lib/data-access/store/schemaSlice.ts +++ b/libs/shared/lib/data-access/store/schemaSlice.ts @@ -61,6 +61,7 @@ export const schemaSlice = createSlice({ setSchema: (state, action: PayloadAction<SchemaGraph>) => { if (action.payload === undefined) throw new Error('Schema is undefined'); state.graph = action.payload; + state.loading = false; }, clearSchema: (state) => { state.graph = new SchemaGraphology().export(); diff --git a/libs/shared/lib/graph-layout/list-layouts.ts b/libs/shared/lib/graph-layout/list-layouts.ts index 90392896a..f2c30f7e7 100644 --- a/libs/shared/lib/graph-layout/list-layouts.ts +++ b/libs/shared/lib/graph-layout/list-layouts.ts @@ -31,6 +31,9 @@ export class ListLayoutFactory implements ILayoutFactory<ListLayoutAlgorithms> { const Y_OFFSET = 50; const X_RELATION_OFFSET = 50; +const X_RELATION_OVERLAP_OFFSET = X_RELATION_OFFSET * 0.05; + +const RELATION_IDENTIFIER = 'relation'; export abstract class ListLayout extends Layout<ListLayoutProvider> { protected defaultLayoutSettings = { @@ -80,7 +83,7 @@ export class ListNodesFirstLayout extends ListLayout { boundingBox = { x1: 0, x2: 1000, y1: 0, y2: 1000 }; } - const relationNodes = graph.nodes().filter((node) => node.startsWith('Relation')); + const relationNodes = graph.nodes().filter((node) => node.toLowerCase().startsWith(RELATION_IDENTIFIER)); const entityNodes = graph.nodes().filter((node) => !relationNodes.includes(node)); let y = 0; @@ -90,10 +93,12 @@ export class ListNodesFirstLayout extends ListLayout { graph.updateNodeAttribute(node, 'y', () => y); }); + let nodeXIncrement = 0; relationNodes.map((node, index) => { const relationsY = y + Y_OFFSET + index * Y_OFFSET; - graph.updateNodeAttribute(node, 'x', () => boundingBox.x1); + graph.updateNodeAttribute(node, 'x', () => boundingBox.x1 + nodeXIncrement); graph.updateNodeAttribute(node, 'y', () => relationsY); + nodeXIncrement += X_RELATION_OVERLAP_OFFSET; }); if (this.verbose) { @@ -124,14 +129,16 @@ export class ListEdgesFirstLayout extends ListLayout { boundingBox = { x1: 0, x2: 1000, y1: 0, y2: 1000 }; } - const relationNodes = graph.nodes().filter((node) => node.startsWith('Relation')); + const relationNodes = graph.nodes().filter((node) => node.toLowerCase().startsWith(RELATION_IDENTIFIER)); const entityNodes = graph.nodes().filter((node) => !relationNodes.includes(node)); let y = 0; + let nodeXIncrement = 0; relationNodes.map((node, index) => { - y = index * Y_OFFSET; - graph.updateNodeAttribute(node, 'x', () => boundingBox.x1); + y = index * Y_OFFSET + nodeXIncrement; + graph.updateNodeAttribute(node, 'x', () => +X_RELATION_OFFSET + nodeXIncrement); graph.updateNodeAttribute(node, 'y', () => y); + nodeXIncrement += X_RELATION_OVERLAP_OFFSET; }); entityNodes.map((node, index) => { @@ -168,7 +175,7 @@ export class ListIntersectedLayout extends ListLayout { boundingBox = { x1: 0, x2: 1000, y1: 0, y2: 1000 }; } - const relationNodes = graph.nodes().filter((node) => node.startsWith('Relation')); + const relationNodes = graph.nodes().filter((node) => node.toLowerCase().startsWith(RELATION_IDENTIFIER)); const entityNodes = graph.nodes().filter((node) => !relationNodes.includes(node)); const graphAllNodes = graph.nodes(); @@ -187,13 +194,16 @@ export class ListIntersectedLayout extends ListLayout { }); let y = 0; + let nodeXIncrement = 0; intersectedList.map((node, index) => { y = index * Y_OFFSET; + graph.updateNodeAttribute(node, 'x', () => { - if (node.startsWith('Relation')) { - return boundingBox.x1 + X_RELATION_OFFSET; + nodeXIncrement += X_RELATION_OVERLAP_OFFSET; + if (node.toLowerCase().startsWith(RELATION_IDENTIFIER)) { + return boundingBox.x1 + X_RELATION_OFFSET + nodeXIncrement; } else { - return boundingBox.x1; + return boundingBox.x1 + nodeXIncrement; } }); graph.updateNodeAttribute(node, 'y', () => y); diff --git a/libs/shared/lib/mock-data/query-result/mockData.ts b/libs/shared/lib/mock-data/query-result/mockData.ts index b9df59153..efd19ae6e 100644 --- a/libs/shared/lib/mock-data/query-result/mockData.ts +++ b/libs/shared/lib/mock-data/query-result/mockData.ts @@ -21,7 +21,8 @@ export type MockDataI = typeof mockDataArray[number]; export const loadMockData = async (fileName: MockDataI) => { - const json = await import(`./${fileName.replace('_', '/')}.json` /* @vite-ignore */); + const filename = `./${fileName.replace('_', '/')}.json`; + const json = await import(filename /* @vite-ignore */); const { nodes, edges, metaData } = graphQueryBackend2graphQuery(json.default); return { data: { diff --git a/libs/shared/lib/schema/panel/schema.stories.tsx b/libs/shared/lib/schema/panel/schema.stories.tsx index 3fc4cf458..355421220 100644 --- a/libs/shared/lib/schema/panel/schema.stories.tsx +++ b/libs/shared/lib/schema/panel/schema.stories.tsx @@ -1,11 +1,10 @@ -import React from 'react'; -import { Meta } from '@storybook/react'; -import { SchemaUtils } from '@graphpolaris/shared/lib/schema/schema-utils'; import { schemaSlice, setSchema } from '@graphpolaris/shared/lib/data-access/store'; +import { movieSchemaRaw, northwindSchemaRaw, twitterSchemaRaw } from '@graphpolaris/shared/lib/mock-data'; +import { SchemaUtils } from '@graphpolaris/shared/lib/schema/schema-utils'; import { configureStore } from '@reduxjs/toolkit'; +import { Meta } from '@storybook/react'; import { Provider } from 'react-redux'; import { Schema } from './Schema'; -import { movieSchemaRaw } from '@graphpolaris/shared/lib/mock-data'; const Component: Meta<typeof Schema> = { /* 👇 The title prop is optional. @@ -100,11 +99,14 @@ export const TestTooltip = { }, }; - export const TestMovieSchema = { play: async () => { + console.log('TestMovieSchema'); const dispatch = Mockstore.dispatch; - const schema = SchemaUtils.schemaBackend2Graphology(movieSchemaRaw); + + const data = await movieSchemaRaw; + console.log('data', data); + const schema = SchemaUtils.schemaBackend2Graphology(data); dispatch(setSchema(schema.export())); }, @@ -113,17 +115,16 @@ export const TestMovieSchema = { export const TestNorthWindSchema = { play: async () => { const dispatch = Mockstore.dispatch; - const schema = SchemaUtils.schemaBackend2Graphology(northwindSchemaRaw); + const schema = await SchemaUtils.schemaBackend2Graphology(northwindSchemaRaw); dispatch(setSchema(schema.export())); }, }; - export const TestTwitterSchema = { play: async () => { const dispatch = Mockstore.dispatch; - const schema = SchemaUtils.schemaBackend2Graphology(twitterSchemaRaw); + const schema = await SchemaUtils.schemaBackend2Graphology(twitterSchemaRaw); dispatch(setSchema(schema.export())); }, diff --git a/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx b/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx index d4b7e8026..7a1485bc4 100644 --- a/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx +++ b/libs/shared/lib/vis/visualizations/tablevis/tablevis.tsx @@ -1,13 +1,13 @@ -import React, { useEffect, useMemo, useRef, forwardRef, useImperativeHandle } from 'react'; -import { Table, AugmentedNodeAttributes } from './components/Table'; -import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common'; -import { Input } from '@graphpolaris/shared/lib/components/inputs'; -import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config'; +import { Accordion, AccordionBody, AccordionHead, AccordionItem } from '@graphpolaris/shared/lib/components/accordion'; import { Button } from '@graphpolaris/shared/lib/components/buttons'; -import { useSearchResultData } from '@graphpolaris/shared/lib/data-access'; +import { Input } from '@graphpolaris/shared/lib/components/inputs'; import { EntityPill } from '@graphpolaris/shared/lib/components/pills/Pill'; -import { Accordion, AccordionBody, AccordionHead, AccordionItem } from '@graphpolaris/shared/lib/components/accordion'; +import { useSearchResultData } from '@graphpolaris/shared/lib/data-access'; +import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config'; import html2canvas from 'html2canvas'; +import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react'; +import { VISComponentType, VisualizationPropTypes, VisualizationSettingsPropTypes } from '../../common'; +import { AugmentedNodeAttributes, Table } from './components/Table'; export interface TableVisHandle { exportImageInternal: () => void; -- GitLab