From bf52ea5a109656ae75059d6db4e9b22050b85fba Mon Sep 17 00:00:00 2001 From: Cathia Archidoit Date: Tue, 21 Apr 2026 11:46:32 +0200 Subject: [PATCH] [frontend] Relationship display at rel creation from graph (#15575) --- .../components/GraphToolbarContentTools.tsx | 22 +++++++++++++++++-- .../src/utils/defaultRepresentatives.ts | 13 ++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/opencti-platform/opencti-front/src/components/graph/components/GraphToolbarContentTools.tsx b/opencti-platform/opencti-front/src/components/graph/components/GraphToolbarContentTools.tsx index 69e8c80d92b5..4079fd2075aa 100644 --- a/opencti-platform/opencti-front/src/components/graph/components/GraphToolbarContentTools.tsx +++ b/opencti-platform/opencti-front/src/components/graph/components/GraphToolbarContentTools.tsx @@ -17,6 +17,7 @@ import { useGraphContext } from '../GraphContext'; import { ObjectToParse } from '../utils/useGraphParser'; import GraphToolbarRemoveConfirm, { GraphToolbarDeleteConfirmProps } from './GraphToolbarRemoveConfirm'; import ContainerAddStixCoreObjectsInLine from '../../../private/components/common/containers/ContainerAddStixCoreObjectsInLine'; +import { getRelationshipMainRepresentative } from '../../../utils/defaultRepresentatives'; export interface GraphToolbarContentToolsProps { stixCoreObjectRefetchQuery?: GraphQLTaggedNode; @@ -57,8 +58,8 @@ const GraphToolbarContentTools = ({ context, rawObjects, graphState: { - selectedNodes, - selectedLinks, + selectedNodes: rawSelectedNodes, + selectedLinks: rawSelectedLinks, isAddRelationOpen, }, } = useGraphContext(); @@ -70,6 +71,23 @@ const GraphToolbarContentTools = ({ addLink, } = useGraphInteractions(); + // if a link or node is a relationship, display correctly its representative + const selectedLinks = rawSelectedLinks.map((o) => o.relationship_type + ? { + ...o, + name: getRelationshipMainRepresentative( + { label: (o.source as GraphNode).label }, + { label: (o.target as GraphNode).label }, + 10), + } + : o); + const selectedNodes = rawSelectedNodes.map((o) => o.relationship_type + ? { + ...o, + name: o.label, // no source and target if the relationship is displayed as a node + } + : o); + const head = selectedNodes.slice(0, 1); const tail = selectedNodes.slice(-1); const mid = selectedNodes.slice(1, -1); diff --git a/opencti-platform/opencti-front/src/utils/defaultRepresentatives.ts b/opencti-platform/opencti-front/src/utils/defaultRepresentatives.ts index 1bcfa96050a2..1a7af83dcfac 100644 --- a/opencti-platform/opencti-front/src/utils/defaultRepresentatives.ts +++ b/opencti-platform/opencti-front/src/utils/defaultRepresentatives.ts @@ -88,6 +88,10 @@ export const defaultKey = (n: any) => { return null; }; +export const getRelationshipMainRepresentative = (from: any, to: any, truncateLimit = 20) => { + return `${truncate(getMainRepresentative(from), truncateLimit)} ➡️ ${truncate(getMainRepresentative(to), truncateLimit)}`; +}; + // equivalent to querying representative.main export const getMainRepresentative = (n: any, fallback = 'Unknown') => { if (!n) return ''; @@ -129,12 +133,9 @@ export const getMainRepresentative = (n: any, fallback = 'Unknown') => { || getMainRepresentative((R.head(n.objects?.edges ?? []) as any)?.node) || (n.from && n.to - && `${truncate(getMainRepresentative(n.from), 20)} ➡️ ${truncate( - getMainRepresentative(n.to), - 20, - )}`) - || n.main_entity_name - || fallback; + && getRelationshipMainRepresentative(n.from, n.to)) + || n.main_entity_name + || fallback; return n.x_mitre_id ? `[${n.x_mitre_id}] ${mainValue}` : mainValue; };