diff --git a/apps/webservice/src/app/(auth)/login/workspace-invite/[workspaceInviteToken]/page.tsx b/apps/webservice/src/app/(auth)/login/workspace-invite/[workspaceInviteToken]/page.tsx index c0c9a6e75..39c5ad385 100644 --- a/apps/webservice/src/app/(auth)/login/workspace-invite/[workspaceInviteToken]/page.tsx +++ b/apps/webservice/src/app/(auth)/login/workspace-invite/[workspaceInviteToken]/page.tsx @@ -1,7 +1,12 @@ import { redirect } from "next/navigation"; import { IconPlane } from "@tabler/icons-react"; -import { auth, isGoogleAuthEnabled, isOIDCAuthEnabled } from "@ctrlplane/auth"; +import { + auth, + isCredentialsAuthEnabled, + isGoogleAuthEnabled, + isOIDCAuthEnabled, +} from "@ctrlplane/auth"; import { Button } from "@ctrlplane/ui/button"; import { LoginCard } from "../../LoginCard"; @@ -21,6 +26,7 @@ export default async function LoginInvitePage() { diff --git a/apps/webservice/src/app/[workspaceSlug]/_components/reactflow/layout.ts b/apps/webservice/src/app/[workspaceSlug]/_components/reactflow/layout.ts index b113931bb..cc7574d96 100644 --- a/apps/webservice/src/app/[workspaceSlug]/_components/reactflow/layout.ts +++ b/apps/webservice/src/app/[workspaceSlug]/_components/reactflow/layout.ts @@ -3,8 +3,6 @@ import type { Edge, Node } from "reactflow"; import dagre from "dagre"; -const dagreGraph = new dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({})); - const generateLevels = (nodes: Node[], edges: Edge[]) => { const levels: Record = {}; const edgeMap: Record = {}; @@ -39,6 +37,8 @@ export const getLayoutedElementsDagre = ( direction = "TB", extraEdgeLength = 0, ) => { + const dagreGraph = new dagre.graphlib.Graph(); + dagreGraph.setDefaultEdgeLabel(() => ({})); dagreGraph.setGraph({ rankdir: direction }); nodes.forEach((node) => dagreGraph.setNode(node.id, node)); diff --git a/apps/webservice/src/app/[workspaceSlug]/_components/target-drawer/relationships/RelationshipsDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/_components/target-drawer/relationships/RelationshipsDiagram.tsx index d4fdc2e9b..3df63e9a5 100644 --- a/apps/webservice/src/app/[workspaceSlug]/_components/target-drawer/relationships/RelationshipsDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/_components/target-drawer/relationships/RelationshipsDiagram.tsx @@ -132,7 +132,6 @@ const DepEdge: React.FC = ({ const nodeTypes: NodeTypes = { target: TargetNode }; const edgeTypes: EdgeTypes = { default: DepEdge }; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); const useOnLayout = () => { const { getNodes, fitView, setNodes, setEdges, getEdges } = useReactFlow(); return useCallback(() => { @@ -145,12 +144,7 @@ const useOnLayout = () => { setNodes([...layouted.nodes]); setEdges([...layouted.edges]); - window.requestAnimationFrame(() => { - // hack to get it to center - we should figure out when the layout is done - // and then call fitView. We are betting that everything should be - // rendered correctly in 100ms before fitting the view. - sleep(100).then(() => fitView({ padding: 0.12, maxZoom: 1 })); - }); + fitView({ padding: 0.12, maxZoom: 1 }); }, [getNodes, getEdges, setNodes, setEdges, fitView]); }; diff --git a/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowDiagram.tsx b/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowDiagram.tsx index 5c641de41..26d8c07f2 100644 --- a/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowDiagram.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/deployments/[deploymentSlug]/releases/[versionId]/FlowDiagram.tsx @@ -8,11 +8,7 @@ import type { } from "@ctrlplane/db/schema"; import type { NodeTypes, ReactFlowInstance } from "reactflow"; import { useCallback, useEffect, useState } from "react"; -import ReactFlow, { - useEdgesState, - useNodesState, - useReactFlow, -} from "reactflow"; +import ReactFlow, { useEdgesState, useNodesState } from "reactflow"; import { ArrowEdge } from "~/app/[workspaceSlug]/_components/reactflow/ArrowEdge"; import { @@ -31,7 +27,6 @@ const nodeTypes: NodeTypes = { policy: PolicyNode, "release-sequencing": ReleaseSequencingNode, }; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); export const FlowDiagram: React.FC<{ systemId: string; release: Release; @@ -86,20 +81,17 @@ export const FlowDiagram: React.FC<{ ...createEdgesFromPolicyDeployment(policyDeployments), ]); - const { fitView } = useReactFlow(); const onLayout = useCallback(() => { const layouted = getLayoutedElementsDagre(nodes, edges, "LR"); setNodes([...layouted.nodes]); setEdges([...layouted.edges]); + }, [nodes, edges, setNodes, setEdges]); - window.requestAnimationFrame(() => { - // hack to get it to center - we should figure out when the layout is done - // and then call fitView. We are betting that everything should be - // rendered correctly in 100ms before fitting the view. - sleep(100).then(() => fitView({ padding: 0.12, maxZoom: 1 })); - }); - }, [nodes, edges, setNodes, setEdges, fitView]); + useEffect(() => { + if (reactFlowInstance && nodes.length) + reactFlowInstance.fitView({ padding: 0.16, maxZoom: 1 }); + }, [reactFlowInstance, nodes, edges]); useEffect(() => { if (reactFlowInstance != null) onLayout(); diff --git a/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/environments/EnvFlowBuilder.tsx b/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/environments/EnvFlowBuilder.tsx index 1628b898d..9e3c62ebb 100644 --- a/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/environments/EnvFlowBuilder.tsx +++ b/apps/webservice/src/app/[workspaceSlug]/systems/[systemSlug]/environments/EnvFlowBuilder.tsx @@ -169,14 +169,12 @@ const useOnConnect = () => { return onConnect; }; -const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); export const EnvFlowBuilder: React.FC<{ systemId: string; envs: Array; policies: Array; policyDeployments: Array; }> = ({ systemId, envs, policies, policyDeployments }) => { - const { fitView } = useReactFlow(); const [nodes, setNodes, onNodesChange] = useNodesState([ triggerNode, ...envs.map((env) => ({ @@ -223,14 +221,12 @@ export const EnvFlowBuilder: React.FC<{ setNodes([...layouted.nodes]); setEdges([...layouted.edges]); + }, [nodes, edges, setNodes, setEdges]); - window.requestAnimationFrame(() => { - // hack to get it to center - we should figure out when the layout is done - // and then call fitView. We are betting that everything should be - // rendered correctly in 100ms before fitting the view. - sleep(100).then(() => fitView({ padding: 0.12, maxZoom: 1 })); - }); - }, [nodes, edges, setNodes, setEdges, fitView]); + useEffect(() => { + if (reactFlowInstance && nodes.length) + reactFlowInstance.fitView({ padding: 0.12, maxZoom: 1 }); + }, [reactFlowInstance, nodes]); useEffect(() => { if (reactFlowInstance != null) onLayout();