From cd13b47a21a3039042e4bdc2f2274cdb0c84998f Mon Sep 17 00:00:00 2001 From: stijnpotters Date: Mon, 15 Jun 2026 12:07:42 +0200 Subject: [PATCH 1/5] Add /build to .gitignore to exclude build artifacts --- src/main/frontend/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/frontend/.gitignore b/src/main/frontend/.gitignore index c65a0878..fc091fc6 100644 --- a/src/main/frontend/.gitignore +++ b/src/main/frontend/.gitignore @@ -9,3 +9,5 @@ /.env /.env.production /.env.development + +/build From f8ece30ce89f179ff6a9d27318649def25dec545 Mon Sep 17 00:00:00 2001 From: stijnpotters Date: Mon, 15 Jun 2026 12:52:28 +0200 Subject: [PATCH 2/5] Update development environment configuration and enhance security settings --- .../flow/common/config/SecurityChainConfigurer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java b/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java index 96d1f8db..0ce53118 100644 --- a/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java +++ b/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java @@ -56,6 +56,11 @@ public SecurityFilterChain configureChain(IAuthenticator authenticator, HttpSecu http.formLogin(FormLoginConfigurer::disable); http.logout(LogoutConfigurer::disable); http.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); + + if (csrfEnabled) { + http.addFilterAfter(new CsrfCookieFilter(), CsrfFilter.class); + } + return authenticator.configureHttpSecurity(http); } From 61ca6422efa37e0927c8c22863aedfcf458e87ac Mon Sep 17 00:00:00 2001 From: stijnpotters Date: Mon, 15 Jun 2026 13:24:06 +0200 Subject: [PATCH 3/5] Refactor API URL handling and improve CSRF configuration --- src/main/frontend/.gitignore | 2 -- .../flow/common/config/SecurityChainConfigurer.java | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/main/frontend/.gitignore b/src/main/frontend/.gitignore index fc091fc6..c65a0878 100644 --- a/src/main/frontend/.gitignore +++ b/src/main/frontend/.gitignore @@ -9,5 +9,3 @@ /.env /.env.production /.env.development - -/build diff --git a/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java b/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java index 0ce53118..96d1f8db 100644 --- a/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java +++ b/src/main/java/org/frankframework/flow/common/config/SecurityChainConfigurer.java @@ -56,11 +56,6 @@ public SecurityFilterChain configureChain(IAuthenticator authenticator, HttpSecu http.formLogin(FormLoginConfigurer::disable); http.logout(LogoutConfigurer::disable); http.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)); - - if (csrfEnabled) { - http.addFilterAfter(new CsrfCookieFilter(), CsrfFilter.class); - } - return authenticator.configureHttpSecurity(http); } From 892d939900d15fbf76f4708b1e9aa656fb5986d9 Mon Sep 17 00:00:00 2001 From: stijnpotters Date: Mon, 15 Jun 2026 16:17:25 +0200 Subject: [PATCH 4/5] abstracted zoomed node to seperate component to make it reusable --- .../canvas/nodetypes/zoomed-out-node.tsx | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/main/frontend/app/routes/studio/canvas/nodetypes/zoomed-out-node.tsx diff --git a/src/main/frontend/app/routes/studio/canvas/nodetypes/zoomed-out-node.tsx b/src/main/frontend/app/routes/studio/canvas/nodetypes/zoomed-out-node.tsx new file mode 100644 index 00000000..f8091642 --- /dev/null +++ b/src/main/frontend/app/routes/studio/canvas/nodetypes/zoomed-out-node.tsx @@ -0,0 +1,140 @@ +import { Handle, Position } from '@xyflow/react' +import { FlowConfig } from '~/routes/studio/canvas/flow.config' + +const COMPACT_INITIALS_BOX_SIZE = 160 +const COMPACT_PADDING_TOP = 8 +const COMPACT_HANDLE_SIZE = 15 +const COMPACT_HANDLE_GAP = 4 + +export interface ZoomedOutNodeProps { + subtype: string + name?: string + attributes?: Record + colorVariable: string + selected?: boolean + showTargetHandle?: boolean + sourceHandles?: { type: string; index: number }[] + width?: number +} + +function getAbbreviation(subtype: string): string { + return subtype.replaceAll(/[a-z]/g, '').slice(0, 4) || subtype.slice(0, 2).toUpperCase() +} + +/** + * Compact representation of a node shown when the canvas is zoomed out far enough that the full + * node would be unreadable. Renders an initials box with the subtype, name attributes and the + * handles aligned under it. + */ +export default function ZoomedOutNode({ + subtype, + name, + attributes, + colorVariable, + selected, + showTargetHandle = true, + sourceHandles = [], + width = FlowConfig.NODE_DEFAULT_WIDTH, +}: Readonly) { + const abbr = getAbbreviation(subtype) + + const compactXOffsetPx = (width - COMPACT_INITIALS_BOX_SIZE) / 2 - COMPACT_HANDLE_SIZE - COMPACT_HANDLE_GAP + const compactHandleTop = + COMPACT_PADDING_TOP + COMPACT_INITIALS_BOX_SIZE / 2 - COMPACT_HANDLE_SIZE / 2 + COMPACT_HANDLE_SIZE + + return ( + <> +
+
+ + {abbr} + +
+ + {subtype} + + {name && {name}} + {attributes && + Object.entries(attributes).map(([key, value]) => ( + + {value || key} + + ))} +
+ + {showTargetHandle && ( + <> +
+ + + )} + + {sourceHandles.length > 0 && ( +
+ )} + + {sourceHandles.map((handle) => ( + + ))} + + ) +} From ab562c9432e502d8f58faef766ccbf1112a67217 Mon Sep 17 00:00:00 2001 From: stijnpotters Date: Mon, 15 Jun 2026 16:18:28 +0200 Subject: [PATCH 5/5] reused zoomed node in exit node as well as in frank node --- .../studio/canvas/nodetypes/exit-node.tsx | 17 ++- .../studio/canvas/nodetypes/frank-node.tsx | 121 ++---------------- 2 files changed, 26 insertions(+), 112 deletions(-) diff --git a/src/main/frontend/app/routes/studio/canvas/nodetypes/exit-node.tsx b/src/main/frontend/app/routes/studio/canvas/nodetypes/exit-node.tsx index 330c76a7..a29de2e2 100644 --- a/src/main/frontend/app/routes/studio/canvas/nodetypes/exit-node.tsx +++ b/src/main/frontend/app/routes/studio/canvas/nodetypes/exit-node.tsx @@ -1,7 +1,8 @@ -import { Handle, type Node, type NodeProps, NodeResizeControl, Position } from '@xyflow/react' +import { Handle, type Node, type NodeProps, NodeResizeControl, Position, useStore } from '@xyflow/react' import { ResizeIcon } from '~/routes/studio/canvas/nodetypes/frank-node' import { FlowConfig } from '~/routes/studio/canvas/flow.config' import { useSettingsStore } from '~/stores/settings-store' +import ZoomedOutNode from './zoomed-out-node' export type ExitNode = Node<{ subtype: string @@ -14,6 +15,20 @@ export default function ExitNodeComponent(properties: NodeProps) { const minNodeWidth = FlowConfig.EXIT_DEFAULT_WIDTH const minNodeHeight = FlowConfig.EXIT_DEFAULT_HEIGHT const gradientEnabled = useSettingsStore((state) => state.studio.gradient) + const zoom = useStore((state) => state.transform[2]) + const isCompact = zoom < 0.4 + + if (isCompact) { + return ( + + ) + } return ( <> diff --git a/src/main/frontend/app/routes/studio/canvas/nodetypes/frank-node.tsx b/src/main/frontend/app/routes/studio/canvas/nodetypes/frank-node.tsx index 7cdc76c9..9faece23 100644 --- a/src/main/frontend/app/routes/studio/canvas/nodetypes/frank-node.tsx +++ b/src/main/frontend/app/routes/studio/canvas/nodetypes/frank-node.tsx @@ -36,6 +36,7 @@ import { parseXsd, } from '~/utils/xsd-utils' import MissingRequirements from './components/missing-requirements' +import ZoomedOutNode from './zoomed-out-node' export type FrankNodeType = Node<{ subtype: string @@ -117,17 +118,6 @@ export default function FrankNode(properties: NodeProps) { return (dimensions.height - (properties.data.sourceHandles.length - 1) * handleSpacing) / 2 }, [dimensions.height, properties.data.sourceHandles.length]) - const COMPACT_INITIALS_BOX_SIZE = 160 - const COMPACT_PADDING_TOP = 8 - const COMPACT_HANDLE_SIZE = 15 - const COMPACT_HANDLE_GAP = 4 - - const compactXOffsetPx = - (FlowConfig.NODE_DEFAULT_WIDTH - COMPACT_INITIALS_BOX_SIZE) / 2 - COMPACT_HANDLE_SIZE - COMPACT_HANDLE_GAP - - const compactHandleTop = - COMPACT_PADDING_TOP + COMPACT_INITIALS_BOX_SIZE / 2 - COMPACT_HANDLE_SIZE / 2 + COMPACT_HANDLE_SIZE - const allForwardTypesUsed = useMemo(() => { if (availableHandleTypes.length === 0) return true @@ -406,107 +396,16 @@ export default function FrankNode(properties: NodeProps) { }, [draggedName, canAcceptChild, frankElement]) if (isCompact) { - const abbr = - properties.data.subtype.replaceAll(/[a-z]/g, '').slice(0, 4) || properties.data.subtype.slice(0, 2).toUpperCase() - return ( - <> -
-
- - {abbr} - -
- - - {properties.data.subtype} - - - {properties.data.name && ( - {properties.data.name} - )} - {properties.data.attributes && - Object.entries(properties.data.attributes).map(([key, value]) => ( - - {value || key} - - ))} -
- - {properties.data.subtype !== 'Receiver' && ( - <> -
- - - )} - - {properties.data.sourceHandles.length > 0 && ( -
- )} - - {properties.data.sourceHandles.map((handle) => ( - - ))} - + ) }