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();