mirror of
https://github.com/stackrender/stackrender.git
synced 2026-09-10 11:15:42 +00:00
Redeuce all unnecessary table re-rendering
This commit is contained in:
@@ -19,7 +19,7 @@ const useGetOverlappingNodes = (): Set<string> => {
|
||||
}
|
||||
}
|
||||
return overlaps
|
||||
}, [nodes]) ;
|
||||
}, [nodes]);
|
||||
return overlappingNodes;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,6 @@ function isNodesOverlapping(nodeA: Node, nodeB: Node) {
|
||||
bottom: nodeB.position.y + nodeBHeight,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
return !(a.right <= b.left || a.left >= b.right || a.bottom <= b.top || a.top >= b.bottom);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Edge, useStore } from "@xyflow/react";
|
||||
import { Edge, useReactFlow, useStore } from "@xyflow/react";
|
||||
import { useEffect, useState } from "react";
|
||||
import hash from 'object-hash';
|
||||
|
||||
@@ -6,19 +6,25 @@ import hash from 'object-hash';
|
||||
|
||||
|
||||
|
||||
const useGetRelatedEdges = ( nodeId : string) => {
|
||||
const edges = useStore((store) => store.edges) as Edge[];
|
||||
const useGetRelatedEdges = (nodeId: string) => {
|
||||
|
||||
const [relatedEdges, setRelatedEdges] = useState<Edge[]>([]);
|
||||
const { getEdges } = useReactFlow();
|
||||
|
||||
const edges = getEdges();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const newRelatedEdges: Edge[] = edges.filter((edge: Edge) => edge.source == nodeId || edge.target == nodeId);
|
||||
setRelatedEdges((previousEdges :Edge[]) => {
|
||||
return hash(newRelatedEdges) == hash(previousEdges) ? previousEdges : newRelatedEdges
|
||||
})
|
||||
if (hash(newRelatedEdges) != hash(relatedEdges)) {
|
||||
setRelatedEdges(newRelatedEdges)
|
||||
}
|
||||
|
||||
}, [edges, nodeId])
|
||||
|
||||
return relatedEdges
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default useGetRelatedEdges;
|
||||
@@ -23,7 +23,9 @@ export const useRelationshipToEdge = (relationships: RelationshipType[]): void =
|
||||
} as Edge
|
||||
})
|
||||
|
||||
|
||||
setEdges((edges: any) => {
|
||||
|
||||
return relationshipEdges.map((relationshipEdge: any) => {
|
||||
const edge = edges.find((edge: Edge) => edge.id == relationshipEdge.id);
|
||||
if (!edge)
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
|
||||
import { TableType } from "@/lib/schemas/table-schema";
|
||||
import { Node, useReactFlow } from "@xyflow/react";
|
||||
import { useEffect } from "react";
|
||||
import useGetOverlappingNodes from "./use-get-overlapping-nodes";
|
||||
import { useEffect } from "react";
|
||||
import hash from 'object-hash';
|
||||
import { getDefaultTableOverlapping } from "@/utils/tables";
|
||||
export const useTableToNode = (tables: TableType[]): void => {
|
||||
const { setNodes } = useReactFlow();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const tableNodes = tables.map((table: TableType) => {
|
||||
return {
|
||||
id: table.id,
|
||||
type: "table",
|
||||
|
||||
|
||||
position: {
|
||||
x: table.posX,
|
||||
y: table.posY
|
||||
},
|
||||
data: {
|
||||
table,
|
||||
table,
|
||||
overlapping : getDefaultTableOverlapping(table , tables) ,
|
||||
pulsing : false ,
|
||||
highlightedEdges : []
|
||||
},
|
||||
style: {
|
||||
width: 224
|
||||
@@ -27,21 +31,7 @@ export const useTableToNode = (tables: TableType[]): void => {
|
||||
} as Node
|
||||
})
|
||||
|
||||
|
||||
setNodes((nodes) => {
|
||||
|
||||
return tableNodes.map((tableNode: Node) => {
|
||||
const node = nodes.find((node: Node) => node.id == tableNode.id);
|
||||
if (!node) {
|
||||
return tableNode;
|
||||
}
|
||||
|
||||
const hashNode: string = hash((node.data as any).table);
|
||||
const hashTableNode: string = hash((tableNode.data as any).table);
|
||||
return hashNode == hashTableNode ? node : tableNode;
|
||||
|
||||
})
|
||||
})
|
||||
setNodes (tableNodes) ;
|
||||
}, [tables])
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { v4 } from "uuid";
|
||||
import { TARGET_PREFIX } from "./table/field";
|
||||
import CardinalityMarker from "@/components/cardinality-marker/cardinality-marker";
|
||||
import { areArraysEqual } from "@/utils/utils";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useDiagramOps } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/tooltip";
|
||||
import { addToast, Button, Image } from "@heroui/react";
|
||||
import { AlertTriangle, LayoutGrid } from "lucide-react";
|
||||
@@ -23,17 +23,17 @@ import { useTheme } from "next-themes";
|
||||
import DatabaseControlButtons from "./database-control-buttons";
|
||||
import useGetOverlappingNodes from "@/hooks/use-get-overlapping-nodes";
|
||||
import { FieldType } from "@/lib/schemas/field-schema";
|
||||
|
||||
import hash from "object-hash";
|
||||
|
||||
|
||||
const DatabasePage: React.FC<never> = () => {
|
||||
|
||||
const { database } = useDatabase();
|
||||
const { updateTablePositions, deleteMultiTables, deleteMultiRelationships, createRelationship, getField } = useDatabaseOperations();
|
||||
const { database, getField } = useDatabase();
|
||||
const { updateTablePositions, deleteMultiTables, deleteMultiRelationships, createRelationship } = useDatabaseOperations();
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||
|
||||
const { setIsConnectionInProgress } = useDiagram();
|
||||
const { setIsConnectionInProgress } = useDiagramOps();
|
||||
const [selectedNodeIds, setSelectedNodeIds] = useState<string[]>([]);
|
||||
const [isTableOverlappingPulsing, setIsTableOverlappingPulsing] = useState<boolean>(false);
|
||||
const { tables, relationships } = database;
|
||||
@@ -48,7 +48,8 @@ const DatabasePage: React.FC<never> = () => {
|
||||
|
||||
const sourceField: FieldType | undefined = getField(connection.source, sourceFieldId as string);
|
||||
const targetField: FieldType | undefined = getField(connection.target, targetFieldId);
|
||||
console.log(sourceField, targetField)
|
||||
|
||||
|
||||
if (sourceField?.typeId == targetField?.typeId) {
|
||||
|
||||
createRelationship({
|
||||
@@ -73,7 +74,11 @@ const DatabasePage: React.FC<never> = () => {
|
||||
|
||||
const handleNodesChanges: OnNodesChange<never> = useCallback((changes: NodeChange<never>[]) => {
|
||||
|
||||
const nodePositionChanges: NodePositionChange[] = changes.filter((change: NodeChange) => change.type == "position" && !change.dragging) as NodePositionChange[];
|
||||
const nodePositionChanges: NodePositionChange[] = changes.filter((change: NodeChange) =>
|
||||
change.type == "position" &&
|
||||
!change.dragging
|
||||
) as NodePositionChange[];
|
||||
|
||||
const nodeRemoveChanges: NodeRemoveChange[] = changes.filter((change: NodeChange) => change.type == "remove");
|
||||
|
||||
if (nodePositionChanges.length > 0)
|
||||
@@ -115,15 +120,29 @@ const DatabasePage: React.FC<never> = () => {
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
setEdges((edges: any) => {
|
||||
return edges.map((edge: any) => {
|
||||
const selected: boolean = selectedEdgeIds.includes(edge.id);
|
||||
return (edge.animated == selected) ? edge : { ...edge, animated: selected } as Edge;
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
setNodes((nodes: any) => {
|
||||
return nodes.map((node: any) => {
|
||||
|
||||
const nodeHighlitedEdges: Edge[] = node.data.highlightedEdges;
|
||||
const newHighlitedEdges: Edge[] = edges.filter((edge: Edge) => selectedEdgeIds.includes(edge.id) && (edge.source == node.id || edge.target == node.id));
|
||||
console.log(nodeHighlitedEdges, newHighlitedEdges);
|
||||
|
||||
return {
|
||||
...edge,
|
||||
animated: selected,
|
||||
} as Edge
|
||||
|
||||
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
highlightedEdges: newHighlitedEdges
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}, [selectedEdgeIds]);
|
||||
@@ -155,7 +174,6 @@ const DatabasePage: React.FC<never> = () => {
|
||||
|
||||
const overlappingNodes = useGetOverlappingNodes();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const overlappingIds = Array.from(overlappingNodes);
|
||||
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
import { useRelationshipName } from "@/hooks/use-relationship-name";
|
||||
import { RelationshipInsertType, RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { useDiagramOps } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { Button, cn, Input, Listbox, ListboxItem, Popover, PopoverContent, PopoverTrigger } from "@heroui/react";
|
||||
import { Check, ChevronRight, EllipsisVertical, Focus, Pencil, Trash } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -23,7 +23,7 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
const { t } = useTranslation();
|
||||
const [popOverOpen, setPopOverOpen] = useState<boolean>(false);
|
||||
const [name, setName] = useState<string>(relationship.name ? relationship.name : defaultName);
|
||||
const { focusOnRelationship } = useDiagram();
|
||||
const { focusOnRelationship } = useDiagramOps();
|
||||
|
||||
|
||||
const editRelationshipName = () => {
|
||||
@@ -43,8 +43,8 @@ const RelationshipAccordionHeader: React.FC<RelationshipAccordionHeaderProps> =
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setName(relationship.name ? relationship.name : defaultName) ;
|
||||
} , [relationship.name])
|
||||
setName(relationship.name ? relationship.name : defaultName);
|
||||
}, [relationship.name])
|
||||
return (
|
||||
<div className="group w-full flex h-12 gap-1 flex p-2 items-center" >
|
||||
<div className={cn(
|
||||
|
||||
+7
-7
@@ -6,10 +6,10 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TableInsertType, TableType } from "@/lib/schemas/table-schema";
|
||||
import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { v4 } from "uuid";
|
||||
import { getNextSequence } from "@/utils/field";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useDiagramOps } from "@/providers/diagram-provider/diagram-provider";
|
||||
|
||||
export interface TableAccordionHeaderProps {
|
||||
table: TableType,
|
||||
@@ -24,17 +24,17 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
|
||||
const { t } = useTranslation();
|
||||
const [editMode, setEditMode] = useState<boolean>(false);
|
||||
const { focusOnTable } = useDiagram();
|
||||
const { focusOnTable } = useDiagramOps();
|
||||
|
||||
useEffect(() => {
|
||||
useEffect(() => {
|
||||
setTableName(table.name);
|
||||
}, [table.name])
|
||||
|
||||
const saveTableName = useCallback(async() => {
|
||||
const saveTableName = useCallback(async () => {
|
||||
|
||||
await editTable({ id: table.id, name: tableName } as TableInsertType);
|
||||
setEditMode(false);
|
||||
} , [tableName])
|
||||
}, [tableName])
|
||||
|
||||
const onDeleteTable = async () => {
|
||||
deleteTable(table.id)
|
||||
@@ -126,7 +126,7 @@ const TableAccordionHeader: React.FC<TableAccordionHeaderProps> = ({ table, isOp
|
||||
size="sm"
|
||||
isIconOnly
|
||||
variant="light"
|
||||
onPressEnd={() => focusOnTable(table.id , true)}
|
||||
onPressEnd={() => focusOnTable(table.id, true)}
|
||||
>
|
||||
<Focus className="size-4 text-icon dark:text-white" />
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
import { Cardinality, RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useDiagram, useDiagramOps } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { card, cn } from "@heroui/react";
|
||||
import { Edge, EdgeProps, getBezierPath, getSmoothStepPath, InternalNode, Node, Position, useReactFlow } from "@xyflow/react";
|
||||
import React, { useMemo } from "react";
|
||||
@@ -18,7 +18,7 @@ const Relationship: React.FC<EdgeProps<RelationshipProps>> = (props) => {
|
||||
|
||||
let { id, sourceX, sourceY, targetX, targetY, source, target, selected, data, animated } = props;
|
||||
const { getInternalNode, getEdge } = useReactFlow();
|
||||
const { focusOnRelationship } = useDiagram();
|
||||
const { focusOnRelationship } = useDiagramOps();
|
||||
|
||||
|
||||
const sourceNode = getInternalNode(source);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
import { Edge, Node, NodeProps, useConnection, useStore } from "@xyflow/react";
|
||||
|
||||
import hash from 'object-hash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Button, Card, cn, } from "@heroui/react";
|
||||
import {
|
||||
@@ -17,22 +17,26 @@ import { TableInsertType, TableType } from "@/lib/schemas/table-schema";
|
||||
import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useDiagramOps } from "@/providers/diagram-provider/diagram-provider";
|
||||
import useGetRelatedEdges from "@/hooks/use-get-related-edges";
|
||||
|
||||
export type TableProps = Node<{
|
||||
table: TableType,
|
||||
overlapping?: boolean,
|
||||
pulsing?: boolean,
|
||||
highlightedEdges : Edge[]
|
||||
|
||||
}>
|
||||
|
||||
const Table: React.FC<NodeProps<TableProps>> = (props) => {
|
||||
const { selected, data: { table, overlapping = false, pulsing = false } } = props;
|
||||
const Table: React.FC<NodeProps<TableProps>> = ({ selected, data: { table, overlapping = false, pulsing = false , highlightedEdges = [] } }) => {
|
||||
|
||||
|
||||
const [editMode, setEditMode] = useState<boolean>(false);
|
||||
const [tableName, setTableName] = useState<string>(table.name);
|
||||
const { editTable } = useDatabaseOperations();
|
||||
const edges = useGetRelatedEdges(table.id as string);
|
||||
const { focusOnTable } = useDiagram();
|
||||
|
||||
// const edges = useGetRelatedEdges(table.id as string);
|
||||
const { focusOnTable } = useDiagramOps();
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -47,11 +51,13 @@ const Table: React.FC<NodeProps<TableProps>> = (props) => {
|
||||
const focus = useCallback(() => {
|
||||
focusOnTable(table.id, false);
|
||||
}, [table])
|
||||
|
||||
/*
|
||||
const highlightedEdges: Edge[] = useMemo(() => {
|
||||
return edges.filter((edge: Edge) => edge.animated || edge.selected);
|
||||
}, [edges]);
|
||||
*/
|
||||
|
||||
|
||||
const fields: React.ReactNode[] = useMemo(() => {
|
||||
return table.fields.map((field: FieldType) => {
|
||||
const highlight: boolean = highlightedEdges.find((edge: any) =>
|
||||
@@ -66,25 +72,19 @@ const Table: React.FC<NodeProps<TableProps>> = (props) => {
|
||||
/>)
|
||||
})
|
||||
}, [table.fields, selected, highlightedEdges]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
console.log("re-render ", table.name)
|
||||
|
||||
}, [useDatabase]) ;
|
||||
|
||||
return (
|
||||
|
||||
|
||||
console.log ("re-render " , table.name)
|
||||
return (
|
||||
|
||||
<Card className={cn(
|
||||
"w-full h-full bg-background rounded-lg noselect overflow-visible dark:bg-default-900",
|
||||
selected
|
||||
? 'ring-2 ring-primary'
|
||||
: '',
|
||||
|
||||
overlapping
|
||||
? 'ring-2 dark:ring-offset-default-900 ring-danger ring-offset-1 scale-105 shadow-danger '
|
||||
: '',
|
||||
|
||||
!pulsing
|
||||
? 'scale-100'
|
||||
: '',
|
||||
@@ -166,4 +166,12 @@ const Table: React.FC<NodeProps<TableProps>> = (props) => {
|
||||
)
|
||||
};
|
||||
|
||||
export default React.memo(Table)
|
||||
export default React.memo(Table, (previousState: any, newState: any) => {
|
||||
const previousStateHash: string = hash(previousState.data);
|
||||
const newStateHash: string = hash(newState.data);
|
||||
|
||||
|
||||
|
||||
|
||||
return previousStateHash == newStateHash && previousState.selected == newState.selected;
|
||||
})
|
||||
|
||||
@@ -15,8 +15,8 @@ interface DatabaseDataContextType {
|
||||
|
||||
data_types: DataType[],
|
||||
database: DatabaseType,
|
||||
isLoading: boolean,
|
||||
// table operations
|
||||
isLoading: boolean,
|
||||
getField: (tableId: string, id: string) => FieldType | undefined,
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ interface DatabaseOperationsContextType {
|
||||
editField: (field: FieldInsertType) => Promise<QueryResult>,
|
||||
deleteField: (id: string) => Promise<void>,
|
||||
orderTableFields: (fields: FieldType[]) => Promise<QueryResult>,
|
||||
getField: (tableId: string, id: string) => FieldType | undefined,
|
||||
// relationship operations
|
||||
createRelationship: (relationship: RelationshipInsertType) => Promise<QueryResult>,
|
||||
editRelationship: (relationship: RelationshipInsertType) => Promise<QueryResult>,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import { DatabaseDataContext, DatabaseOperationsContext } from "./database-context";
|
||||
import { useCallback, useContext, useEffect, useState } from "react";
|
||||
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import { db, powerSyncDb } from "../sync-provider/sync-provider";
|
||||
import { TableInsertType, tables, TableType } from "@/lib/schemas/table-schema";
|
||||
import { useQuery } from "@powersync/react";
|
||||
@@ -223,38 +223,53 @@ const DatabaseProvider: React.FC<Props> = ({ children }) => {
|
||||
}
|
||||
})
|
||||
|
||||
}, [db, currentDatabaseId]);
|
||||
}, [db]);
|
||||
|
||||
|
||||
|
||||
const databaseOpsValue = useMemo(() => ({
|
||||
createTable,
|
||||
editTable,
|
||||
deleteTable,
|
||||
updateTablePositions,
|
||||
deleteMultiTables,
|
||||
createField,
|
||||
editField,
|
||||
deleteField,
|
||||
orderTableFields,
|
||||
|
||||
createRelationship,
|
||||
editRelationship,
|
||||
deleteRelationship,
|
||||
deleteMultiRelationships,
|
||||
executeDbDiffOps,
|
||||
}), [
|
||||
createTable,
|
||||
editTable,
|
||||
deleteTable,
|
||||
updateTablePositions,
|
||||
deleteMultiTables,
|
||||
createField,
|
||||
editField,
|
||||
deleteField,
|
||||
orderTableFields,
|
||||
|
||||
createRelationship,
|
||||
editRelationship,
|
||||
deleteRelationship,
|
||||
deleteMultiRelationships,
|
||||
executeDbDiffOps,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
<DatabaseDataContext.Provider value={{
|
||||
|
||||
|
||||
data_types,
|
||||
database: database as unknown as DatabaseType,
|
||||
isLoading,
|
||||
getField,
|
||||
}}>
|
||||
<DatabaseOperationsContext.Provider value={{
|
||||
createTable,
|
||||
editTable,
|
||||
deleteTable,
|
||||
updateTablePositions,
|
||||
deleteMultiTables,
|
||||
|
||||
createField,
|
||||
editField,
|
||||
deleteField,
|
||||
orderTableFields,
|
||||
getField,
|
||||
|
||||
createRelationship,
|
||||
editRelationship,
|
||||
deleteRelationship,
|
||||
deleteMultiRelationships,
|
||||
|
||||
executeDbDiffOps,
|
||||
}}>
|
||||
|
||||
<DatabaseOperationsContext.Provider value={databaseOpsValue}>
|
||||
|
||||
{
|
||||
!isLoading && database &&
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { createContext, Dispatch, SetStateAction } from "react";
|
||||
|
||||
|
||||
export interface DiagramContextType {
|
||||
interface DiagramDataContextType {
|
||||
focusedTableId: string | undefined;
|
||||
focusedRelationshipId: string | undefined;
|
||||
isConnectionInProgress: boolean
|
||||
}
|
||||
|
||||
focusedTableId : string | undefined ;
|
||||
focusedRelationshipId : string | undefined;
|
||||
isConnectionInProgress : boolean
|
||||
|
||||
focusOnTable : ( id : string , transition? : boolean ) => void ,
|
||||
focusOnRelationship : ( id : string, transition? : boolean ) => void ,
|
||||
setIsConnectionInProgress : Dispatch<boolean>
|
||||
|
||||
}
|
||||
interface DiagramOpsContextType {
|
||||
focusOnTable: (id: string, transition?: boolean) => void,
|
||||
focusOnRelationship: (id: string, transition?: boolean) => void,
|
||||
setIsConnectionInProgress: Dispatch<boolean>
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default createContext<DiagramContextType>({} as DiagramContextType);
|
||||
export const DiagramDataContext = createContext<DiagramDataContextType>({} as DiagramDataContextType);
|
||||
export const DiagramOpsContext = createContext<DiagramOpsContextType>({} as DiagramOpsContextType);
|
||||
@@ -3,7 +3,7 @@ import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
||||
import { FitViewOptions, useReactFlow } from "@xyflow/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import DiagramContext from "./diagram-context";
|
||||
import { DiagramDataContext, DiagramOpsContext } from "./diagram-context";
|
||||
|
||||
|
||||
|
||||
@@ -73,26 +73,35 @@ const DiagramProvider: React.FC<Props> = ({ children }) => {
|
||||
}, [setFocusedRelationshipId]);
|
||||
|
||||
|
||||
const contextValue = useMemo(() => ({
|
||||
const contextDatatValue = useMemo(() => ({
|
||||
focusedTableId,
|
||||
focusedRelationshipId,
|
||||
isConnectionInProgress,
|
||||
}), [focusedTableId, focusedRelationshipId, isConnectionInProgress,]);
|
||||
|
||||
const contextOpsValues = useMemo(() => ({
|
||||
focusOnTable,
|
||||
focusOnRelationship,
|
||||
setIsConnectionInProgress
|
||||
}), [focusedTableId, focusedRelationshipId, focusOnTable, focusOnRelationship, isConnectionInProgress, setIsConnectionInProgress]);
|
||||
|
||||
}), [focusOnTable, focusOnRelationship, setIsConnectionInProgress])
|
||||
return (
|
||||
<DiagramContext.Provider
|
||||
value={contextValue}
|
||||
<DiagramDataContext.Provider
|
||||
value={contextDatatValue}
|
||||
>
|
||||
{children}
|
||||
</DiagramContext.Provider>
|
||||
<DiagramOpsContext.Provider value={contextOpsValues}>
|
||||
{children}
|
||||
</DiagramOpsContext.Provider>
|
||||
|
||||
</DiagramDataContext.Provider>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
export const useDiagram = () => useContext(DiagramContext);
|
||||
export const useDiagram = () => useContext(DiagramDataContext);
|
||||
|
||||
export const useDiagramOps = () => useContext(DiagramOpsContext);
|
||||
|
||||
|
||||
export default DiagramProvider;
|
||||
@@ -51,7 +51,44 @@ const adjustTablesPositions = async (
|
||||
};
|
||||
|
||||
|
||||
|
||||
const isTablesOverlapping = (tableA: TableType, tableB: TableType) => {
|
||||
const tableAWidth: number = 224;
|
||||
const tableAHeight: number = tableA.fields.length * 32 + 36;
|
||||
|
||||
|
||||
const tableBWidth: number = 224;
|
||||
const tableBHeight: number = tableB.fields.length * 32 + 36;
|
||||
|
||||
const a = {
|
||||
left: tableA.posX,
|
||||
right: tableA.posX + tableAWidth,
|
||||
top: tableA.posY,
|
||||
bottom: tableA.posY + tableAHeight,
|
||||
};
|
||||
|
||||
const b = {
|
||||
left: tableB.posX,
|
||||
right: tableB.posX + tableBWidth,
|
||||
top: tableB.posY,
|
||||
bottom: tableB.posY + tableBHeight,
|
||||
};
|
||||
|
||||
return !(a.right <= b.left || a.left >= b.right || a.bottom <= b.top || a.top >= b.bottom);
|
||||
}
|
||||
|
||||
|
||||
const getDefaultTableOverlapping = (table: TableType, tables: TableType[]): boolean => {
|
||||
for (let index: number = 0; index < tables.length; index++) {
|
||||
if ( table.id == tables[index].id) continue ;
|
||||
if (isTablesOverlapping(table, tables[index]))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export {
|
||||
adjustTablesPositions,
|
||||
getDefaultTableOverlapping
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// vite.config.ts
|
||||
import { defineConfig } from "file:///C:/Users/taman/OneDrive/Desktop/stackrender/stackrender/node_modules/vite/dist/node/index.js";
|
||||
import react from "file:///C:/Users/taman/OneDrive/Desktop/stackrender/stackrender/node_modules/@vitejs/plugin-react/dist/index.mjs";
|
||||
import tsconfigPaths from "file:///C:/Users/taman/OneDrive/Desktop/stackrender/stackrender/node_modules/vite-tsconfig-paths/dist/index.mjs";
|
||||
import topLevelAwait from "file:///C:/Users/taman/OneDrive/Desktop/stackrender/stackrender/node_modules/vite-plugin-top-level-await/exports/import.mjs";
|
||||
var vite_config_default = defineConfig({
|
||||
plugins: [react(), tsconfigPaths(), topLevelAwait()],
|
||||
server: {
|
||||
port: 3e3
|
||||
},
|
||||
optimizeDeps: {
|
||||
// Don't optimize these packages as they contain web workers and WASM files.
|
||||
// https://github.com/vitejs/vite/issues/11672#issuecomment-1415820673
|
||||
exclude: ["@journeyapps/wa-sqlite", "@powersync/web"],
|
||||
include: ["@powersync/web > js-logger"]
|
||||
},
|
||||
worker: {
|
||||
format: "es",
|
||||
plugins: () => [topLevelAwait()]
|
||||
}
|
||||
});
|
||||
export {
|
||||
vite_config_default as default
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFx0YW1hblxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXHN0YWNrcmVuZGVyXFxcXHN0YWNrcmVuZGVyXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFx0YW1hblxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXHN0YWNrcmVuZGVyXFxcXHN0YWNrcmVuZGVyXFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9DOi9Vc2Vycy90YW1hbi9PbmVEcml2ZS9EZXNrdG9wL3N0YWNrcmVuZGVyL3N0YWNrcmVuZGVyL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcbmltcG9ydCByZWFjdCBmcm9tICdAdml0ZWpzL3BsdWdpbi1yZWFjdCdcbmltcG9ydCB0c2NvbmZpZ1BhdGhzIGZyb20gJ3ZpdGUtdHNjb25maWctcGF0aHMnXG5pbXBvcnQgdG9wTGV2ZWxBd2FpdCBmcm9tICd2aXRlLXBsdWdpbi10b3AtbGV2ZWwtYXdhaXQnO1xuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHBsdWdpbnM6IFtyZWFjdCgpLCB0c2NvbmZpZ1BhdGhzKCkgLCB0b3BMZXZlbEF3YWl0KCldLFxuICBzZXJ2ZXIgOiB7IFxuICAgIHBvcnQgOiAzMDAwXG4gIH0gLCBcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgLy8gRG9uJ3Qgb3B0aW1pemUgdGhlc2UgcGFja2FnZXMgYXMgdGhleSBjb250YWluIHdlYiB3b3JrZXJzIGFuZCBXQVNNIGZpbGVzLlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS92aXRlanMvdml0ZS9pc3N1ZXMvMTE2NzIjaXNzdWVjb21tZW50LTE0MTU4MjA2NzNcbiAgICBleGNsdWRlOiBbJ0Bqb3VybmV5YXBwcy93YS1zcWxpdGUnLCAnQHBvd2Vyc3luYy93ZWInXSxcbiAgICBpbmNsdWRlOiBbJ0Bwb3dlcnN5bmMvd2ViID4ganMtbG9nZ2VyJ11cbiAgfSxcbiAgd29ya2VyOiB7XG4gICAgZm9ybWF0OiAnZXMnLFxuICAgIHBsdWdpbnM6ICgpID0+IFsgdG9wTGV2ZWxBd2FpdCgpXVxuICB9XG59KVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFxVyxTQUFTLG9CQUFvQjtBQUNsWSxPQUFPLFdBQVc7QUFDbEIsT0FBTyxtQkFBbUI7QUFDMUIsT0FBTyxtQkFBbUI7QUFFMUIsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDMUIsU0FBUyxDQUFDLE1BQU0sR0FBRyxjQUFjLEdBQUksY0FBYyxDQUFDO0FBQUEsRUFDcEQsUUFBUztBQUFBLElBQ1AsTUFBTztBQUFBLEVBQ1Q7QUFBQSxFQUNBLGNBQWM7QUFBQTtBQUFBO0FBQUEsSUFHWixTQUFTLENBQUMsMEJBQTBCLGdCQUFnQjtBQUFBLElBQ3BELFNBQVMsQ0FBQyw0QkFBNEI7QUFBQSxFQUN4QztBQUFBLEVBQ0EsUUFBUTtBQUFBLElBQ04sUUFBUTtBQUFBLElBQ1IsU0FBUyxNQUFNLENBQUUsY0FBYyxDQUFDO0FBQUEsRUFDbEM7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=
|
||||
Reference in New Issue
Block a user