This is an automated email from the ASF dual-hosted git repository.

tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new 62732c152d8 kie-issues#886: On the DMN Editor, adding waypoints to 
edges that don't have a corresponding DMNEdge associated with it should create 
the DMNEdge and add the waypoint normally (#2546)
62732c152d8 is described below

commit 62732c152d8c9331ba8ef635cb1f5b1cb6e8bd47
Author: Jozef Marko <[email protected]>
AuthorDate: Tue Oct 1 23:15:22 2024 +0200

    kie-issues#886: On the DMN Editor, adding waypoints to edges that don't 
have a corresponding DMNEdge associated with it should create the DMNEdge and 
add the waypoint normally (#2546)
    
    Co-authored-by: Tiago Bento <[email protected]>
---
 packages/dmn-editor/src/diagram/Diagram.tsx        |   4 +-
 .../src/diagram/connections/isValidConnection.ts   |  10 +-
 .../diagram/edges/usePotentialWaypointControls.ts  |  93 ++++++++++-
 packages/dmn-editor/src/mutations/addEdge.ts       |  31 ++--
 .../dmn-editor/src/mutations/addEdgeWaypoint.ts    |   8 +-
 packages/dmn-editor/src/mutations/addShape.ts      |   1 -
 .../dmn-editor/src/mutations/addStandaloneNode.ts  |   2 +-
 packages/dmn-editor/src/mutations/deleteEdge.ts    |  60 +++----
 .../src/store/computed/computeDiagramData.ts       |  15 +-
 .../dmn-editor/tests-e2e/__fixtures__/drgNodes.ts  |   2 +-
 .../drds/drds-ar-edge-depiction-waypoint.png       | Bin 0 -> 46979 bytes
 .../drds/drds-ir-edge-depiction-waypoint.png       | Bin 0 -> 47747 bytes
 .../drds/drds-kr-edge-depiction-waypoint.png       | Bin 0 -> 48605 bytes
 .../drds/drds-ar-edge-depiction-waypoint.png       | Bin 0 -> 41659 bytes
 .../drds/drds-ir-edge-depiction-waypoint.png       | Bin 0 -> 42278 bytes
 .../drds/drds-kr-edge-depiction-waypoint.png       | Bin 0 -> 43347 bytes
 .../drds/drds-ar-edge-depiction-waypoint.png       | Bin 0 -> 43646 bytes
 .../drds/drds-ir-edge-depiction-waypoint.png       | Bin 0 -> 43540 bytes
 .../drds/drds-kr-edge-depiction-waypoint.png       | Bin 0 -> 45298 bytes
 .../dmn-editor/tests-e2e/drds/modelDrd.spec.ts     | 180 +++++++++++++++++++--
 20 files changed, 334 insertions(+), 72 deletions(-)

diff --git a/packages/dmn-editor/src/diagram/Diagram.tsx 
b/packages/dmn-editor/src/diagram/Diagram.tsx
index 876c22ba4bb..9dbd0fe75a2 100644
--- a/packages/dmn-editor/src/diagram/Diagram.tsx
+++ b/packages/dmn-editor/src/diagram/Diagram.tsx
@@ -216,7 +216,7 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
           const sourceBounds = sourceNode.data.shape["dc:Bounds"];
           const targetBounds = targetNode.data.shape["dc:Bounds"];
           if (!sourceBounds || !targetBounds) {
-            throw new Error("Cannot create connection without target bounds!");
+            throw new Error("Cannot create connection without source and 
target bounds!");
           }
 
           // --------- This is where we draw the line between the diagram and 
the model.
@@ -1032,7 +1032,7 @@ export const Diagram = React.forwardRef<DiagramRef, { 
container: React.RefObject
           resetToBeforeEditingBegan();
         }
       },
-      [dmnEditorStoreApi, externalModelsByNamespace, 
resetToBeforeEditingBegan, thisDmn.model.definitions]
+      [dmnEditorStoreApi, externalModelsByNamespace, resetToBeforeEditingBegan]
     );
 
     const onEdgesChange = useCallback<RF.OnEdgesChange>(
diff --git a/packages/dmn-editor/src/diagram/connections/isValidConnection.ts 
b/packages/dmn-editor/src/diagram/connections/isValidConnection.ts
index 3dbfb06a61b..94fcd75f31d 100644
--- a/packages/dmn-editor/src/diagram/connections/isValidConnection.ts
+++ b/packages/dmn-editor/src/diagram/connections/isValidConnection.ts
@@ -39,14 +39,18 @@ export function checkIsValidConnection(
 export function _checkIsValidConnection(
   sourceNode: { type?: string; data: DmnDiagramNodeData } | undefined,
   targetNode: { type?: string; data: DmnDiagramNodeData } | undefined,
-  edgeType: string | null | undefined
+  edgeType: string | null | undefined,
+  extraArg?: { allowExternalTarget: boolean }
 ) {
   if (!sourceNode?.type || !targetNode?.type || !edgeType) {
     return false;
   }
 
-  // External nodes cannot be targeted
-  if (targetNode.data.dmnObjectQName.prefix) {
+  // External nodes cannot be targeted by default
+  // However there are exceptions, for example adding a waypoint on the edge
+  const targetsExternalNode = targetNode.data.dmnObjectQName.prefix !== 
undefined;
+  const allowExternalTarget = extraArg?.allowExternalTarget ?? false;
+  if (targetsExternalNode && !allowExternalTarget) {
     return false;
   }
 
diff --git 
a/packages/dmn-editor/src/diagram/edges/usePotentialWaypointControls.ts 
b/packages/dmn-editor/src/diagram/edges/usePotentialWaypointControls.ts
index 1a80d491a4b..d63d5014afd 100644
--- a/packages/dmn-editor/src/diagram/edges/usePotentialWaypointControls.ts
+++ b/packages/dmn-editor/src/diagram/edges/usePotentialWaypointControls.ts
@@ -25,6 +25,12 @@ import { snapPoint } from "../SnapGrid";
 import { DC__Point } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { DmnDiagramNodeData } from "../nodes/Nodes";
 import { DmnDiagramEdgeData } from "./Edges";
+import { useExternalModels } from 
"../../includedModels/DmnEditorDependenciesContext";
+import { addEdge } from "../../mutations/addEdge";
+import { EdgeType, NodeType } from "../connections/graphStructure";
+import { PositionalNodeHandleId } from "../connections/PositionalNodeHandles";
+import { getHandlePosition } from "../maths/DmnMaths";
+import { xmlHrefToQName } from "../../xml/xmlHrefToQName";
 
 export function usePotentialWaypointControls(
   waypoints: DC__Point[],
@@ -38,6 +44,7 @@ export function usePotentialWaypointControls(
   const isDraggingWaypoint = useDmnEditorStore((s) => 
!!s.diagram.draggingWaypoints.find((e) => e === edgeId));
   const dmnEditorStoreApi = useDmnEditorStoreApi();
   const reactFlowInstance = RF.useReactFlow<DmnDiagramNodeData, 
DmnDiagramEdgeData>();
+  const { externalModelsByNamespace } = useExternalModels();
 
   const [potentialWaypoint, setPotentialWaypoint] = useState<ReturnType<typeof 
approximateClosestPoint> | undefined>(
     undefined
@@ -74,12 +81,83 @@ export function usePotentialWaypointControls(
   }, [snapGrid, potentialWaypoint]);
 
   const onDoubleClick = useCallback(() => {
-    if (!potentialWaypoint || !snappedPotentialWaypoint || edgeIndex === 
undefined) {
+    if (!potentialWaypoint || !snappedPotentialWaypoint) {
       return;
     }
 
+    if (edgeIndex === undefined) {
+      /**
+       * This means we are adding a first waypoint to one of following edges:
+       * - an edge in a non default DRD
+       * - an edge targeting an external node
+       */
+      dmnEditorStoreApi.setState((state) => {
+        const nodesById = 
state.computed(state).getDiagramData(externalModelsByNamespace).nodesById;
+        const edge = 
state.computed(state).getDiagramData(externalModelsByNamespace).edgesById.get(edgeId);
+        if (edge === undefined || edge.data?.dmnShapeSource === undefined || 
edge.data?.dmnShapeTarget == undefined) {
+          console.debug(
+            `DMN DIAGRAM: We can not add DMNEdge for '${edgeId}' edge into 
diagram. There are missing data edge: ${edge}, edge.data: ${edge?.data}`
+          );
+          return;
+        }
+
+        const edgeSourceBounds = edge.data?.dmnShapeSource["dc:Bounds"];
+        const edgeTargetBounds = edge.data?.dmnShapeTarget["dc:Bounds"];
+        if (edgeSourceBounds === undefined || edgeTargetBounds === undefined) {
+          console.debug(
+            `DMN DIAGRAM: We can not add DMNEdge for '${edgeId}' edge into 
diagram. There are missing data edgeSourceBounds: ${edgeSourceBounds}, 
edgeTargetBounds: ${edgeTargetBounds}`
+          );
+          return;
+        }
+
+        const sourceNode = nodesById.get(edge.source);
+        const targetNode = nodesById.get(edge.target);
+        if (sourceNode === undefined || targetNode === undefined) {
+          console.debug(
+            `DMN DIAGRAM: We can not add DMNEdge for '${edgeId}' edge into 
diagram. There are missing data sourceNode: ${sourceNode}, targetNode: 
${targetNode}`
+          );
+          return;
+        }
+
+        const targetsExternalNode = targetNode.data.dmnObjectQName.prefix !== 
undefined;
+        const requirementEdgeQNameRelativeToThisDmn = xmlHrefToQName(edgeId, 
state.dmn.model.definitions);
+        addEdge({
+          definitions: state.dmn.model.definitions,
+          drdIndex: state.computed(state).getDrdIndex(),
+          edge: {
+            type: edge.type as EdgeType,
+            targetHandle: getHandlePosition({ shapeBounds: edgeTargetBounds, 
waypoint: snappedPotentialWaypoint })
+              .handlePosition as PositionalNodeHandleId,
+            sourceHandle: getHandlePosition({ shapeBounds: edgeSourceBounds, 
waypoint: snappedPotentialWaypoint })
+              .handlePosition as PositionalNodeHandleId,
+            autoPositionedEdgeMarker: undefined,
+          },
+          sourceNode: {
+            type: sourceNode.type as NodeType,
+            data: sourceNode.data,
+            href: edge.source,
+            bounds: edgeSourceBounds,
+            shapeId: edge.data?.dmnShapeSource["@_id"],
+          },
+          targetNode: {
+            type: targetNode.type as NodeType,
+            href: edge.target,
+            data: targetNode.data,
+            bounds: edgeTargetBounds,
+            index: nodesById.get(edge.target)?.data.index ?? 0,
+            shapeId: edge.data?.dmnShapeTarget["@_id"],
+          },
+          keepWaypoints: false,
+          externalModelsByNamespace,
+          dmnElementRefOfDmnEdge: targetsExternalNode ? 
requirementEdgeQNameRelativeToThisDmn : undefined,
+        });
+
+        console.debug(`DMN DIAGRAM: DMNEdge for '${edgeId}' edge was added 
into diagram.`);
+      });
+    }
+
     if (isExistingWaypoint(snappedPotentialWaypoint)) {
-      console.debug("Preventing overlapping waypoint creation.");
+      console.debug("DMN DIAGRAM: Preventing overlapping waypoint creation.");
       return;
     }
 
@@ -96,18 +174,27 @@ export function usePotentialWaypointControls(
     }
 
     dmnEditorStoreApi.setState((state) => {
+      const edgeQName = xmlHrefToQName(edgeId, state.dmn.model.definitions);
+      const dmnEdgeIndex = 
state.computed(state).indexedDrd().dmnEdgesByDmnElementRef.get(edgeQName)?.index;
+      if (dmnEdgeIndex === undefined) {
+        throw new Error(`DMN DIAGRAM: Diagram computed state does not contain 
DMNEdge for '${edgeId}' edge.`);
+      }
       addEdgeWaypoint({
         definitions: state.dmn.model.definitions,
         drdIndex,
         beforeIndex: i - 1,
-        edgeIndex,
+        dmnEdgeIndex,
         waypoint: snappedPotentialWaypoint,
       });
+
+      console.debug(`DMN DIAGRAM: Waypoint on the DMNEdge for '${edgeId}' edge 
was added.`);
     });
   }, [
     drdIndex,
     dmnEditorStoreApi,
+    edgeId,
     edgeIndex,
+    externalModelsByNamespace,
     isExistingWaypoint,
     potentialWaypoint,
     snappedPotentialWaypoint,
diff --git a/packages/dmn-editor/src/mutations/addEdge.ts 
b/packages/dmn-editor/src/mutations/addEdge.ts
index 7be83b0f2ce..b45591a26a9 100644
--- a/packages/dmn-editor/src/mutations/addEdge.ts
+++ b/packages/dmn-editor/src/mutations/addEdge.ts
@@ -27,7 +27,6 @@ import {
   DMN15__tInformationRequirement,
   DMN15__tKnowledgeRequirement,
   DMNDI15__DMNEdge,
-  DMNDI15__DMNShape,
 } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { PositionalNodeHandleId } from 
"../diagram/connections/PositionalNodeHandles";
 import { EdgeType, NodeType } from "../diagram/connections/graphStructure";
@@ -51,6 +50,7 @@ export function addEdge({
   edge,
   keepWaypoints,
   externalModelsByNamespace,
+  dmnElementRefOfDmnEdge,
 }: {
   definitions: Normalized<DMN15__tDefinitions>;
   drdIndex: number;
@@ -77,14 +77,17 @@ export function addEdge({
   };
   keepWaypoints: boolean;
   externalModelsByNamespace: ExternalModelsIndex | undefined;
+  // QName format, used as dmnElementRef for DMNEdge targeting an external node
+  dmnElementRefOfDmnEdge?: string;
 }) {
-  if (!_checkIsValidConnection(sourceNode, targetNode, edge.type)) {
+  const externalTargetAllowed = dmnElementRefOfDmnEdge !== undefined;
+  if (!_checkIsValidConnection(sourceNode, targetNode, edge.type, { 
allowExternalTarget: externalTargetAllowed })) {
     throw new Error(`DMN MUTATION: Invalid structure: (${sourceNode.type}) 
--${edge.type}--> (${targetNode.type}) `);
   }
 
   const newEdgeId = generateUuid();
 
-  let existingEdgeId: string | undefined = undefined;
+  let existingRequirementOrAssociationId: string | undefined = 
dmnElementRefOfDmnEdge;
 
   // Associations
   if (edge.type === EDGE_TYPES.association) {
@@ -102,17 +105,17 @@ export function addEdge({
       definitions.artifact,
       (a) => a.__$$element === "association" && areAssociationsEquivalent(a, 
newAssociation)
     );
-    existingEdgeId = removed?.["@_id"];
+    existingRequirementOrAssociationId = removed?.["@_id"];
 
     // Replace with the new one.
     definitions.artifact?.push({
       __$$element: "association",
       ...newAssociation,
-      "@_id": tryKeepingEdgeId(existingEdgeId, newEdgeId),
+      "@_id": tryKeepingEdgeId(existingRequirementOrAssociationId, newEdgeId),
     });
   }
   // Requirements
-  else {
+  else if (!externalTargetAllowed) {
     const requirements = getRequirementsFromEdge(sourceNode, newEdgeId, 
edge.type);
     const drgElement = definitions.drgElement![targetNode.index] as 
Normalized<DMN15__tDecision>; // We cast to tDecision here because it has all 
three types of requirement.
     if (requirements?.informationRequirement) {
@@ -120,11 +123,11 @@ export function addEdge({
       const removed = 
removeFirstMatchIfPresent(drgElement.informationRequirement, (ir) =>
         doesInformationRequirementsPointTo(ir, sourceNode.href)
       );
-      existingEdgeId = removed?.["@_id"];
+      existingRequirementOrAssociationId = removed?.["@_id"];
       drgElement.informationRequirement?.push(
         ...requirements.informationRequirement.map((s) => ({
           ...s,
-          "@_id": tryKeepingEdgeId(existingEdgeId, newEdgeId),
+          "@_id": tryKeepingEdgeId(existingRequirementOrAssociationId, 
newEdgeId),
         }))
       );
     }
@@ -134,11 +137,11 @@ export function addEdge({
       const removed = 
removeFirstMatchIfPresent(drgElement.knowledgeRequirement, (kr) =>
         doesKnowledgeRequirementsPointTo(kr, sourceNode.href)
       );
-      existingEdgeId = removed?.["@_id"];
+      existingRequirementOrAssociationId = removed?.["@_id"];
       drgElement.knowledgeRequirement?.push(
         ...requirements.knowledgeRequirement.map((s) => ({
           ...s,
-          "@_id": tryKeepingEdgeId(existingEdgeId, newEdgeId),
+          "@_id": tryKeepingEdgeId(existingRequirementOrAssociationId, 
newEdgeId),
         }))
       );
     }
@@ -148,11 +151,11 @@ export function addEdge({
       const removed = 
removeFirstMatchIfPresent(drgElement.authorityRequirement, (ar) =>
         doesAuthorityRequirementsPointTo(ar, sourceNode.href)
       );
-      existingEdgeId = removed?.["@_id"];
+      existingRequirementOrAssociationId = removed?.["@_id"];
       drgElement.authorityRequirement?.push(
         ...requirements.authorityRequirement.map((s) => ({
           ...s,
-          "@_id": tryKeepingEdgeId(existingEdgeId, newEdgeId),
+          "@_id": tryKeepingEdgeId(existingRequirementOrAssociationId, 
newEdgeId),
         }))
       );
     }
@@ -163,7 +166,7 @@ export function addEdge({
   // Remove existing
   const removedDmnEdge = removeFirstMatchIfPresent(
     diagramElements,
-    (e) => e.__$$element === "dmndi:DMNEdge" && e["@_dmnElementRef"] === 
existingEdgeId
+    (e) => e.__$$element === "dmndi:DMNEdge" && e["@_dmnElementRef"] === 
existingRequirementOrAssociationId
   ) as Normalized<DMNDI15__DMNEdge> | undefined;
 
   const newWaypoints = keepWaypoints
@@ -182,7 +185,7 @@ export function addEdge({
     "@_id":
       withoutDiscreteAutoPosinitioningMarker(removedDmnEdge?.["@_id"] ?? 
generateUuid()) +
       (edge.autoPositionedEdgeMarker ?? ""),
-    "@_dmnElementRef": existingEdgeId ?? newEdgeId,
+    "@_dmnElementRef": existingRequirementOrAssociationId ?? newEdgeId,
     "@_sourceElement": sourceNode.shapeId,
     "@_targetElement": targetNode.shapeId,
     "di:waypoint": newWaypoints,
diff --git a/packages/dmn-editor/src/mutations/addEdgeWaypoint.ts 
b/packages/dmn-editor/src/mutations/addEdgeWaypoint.ts
index 282865f0c5e..8331ed9ca56 100644
--- a/packages/dmn-editor/src/mutations/addEdgeWaypoint.ts
+++ b/packages/dmn-editor/src/mutations/addEdgeWaypoint.ts
@@ -24,21 +24,21 @@ import { Normalized } from "../normalization/normalize";
 export function addEdgeWaypoint({
   definitions,
   drdIndex,
-  edgeIndex,
+  dmnEdgeIndex,
   beforeIndex,
   waypoint,
 }: {
   definitions: Normalized<DMN15__tDefinitions>;
   drdIndex: number;
-  edgeIndex: number;
+  dmnEdgeIndex: number;
   beforeIndex: number;
   waypoint: DC__Point;
 }) {
   const { diagramElements } = addOrGetDrd({ definitions, drdIndex });
 
-  const diagramElement = diagramElements[edgeIndex];
+  const diagramElement = diagramElements[dmnEdgeIndex];
   if (diagramElement.__$$element !== "dmndi:DMNEdge") {
-    throw new Error("DMN MUTATION: Can't remove a waypoint from an element 
that is not a DMNEdge.");
+    throw new Error("DMN MUTATION: Can't add a waypoint for an element that is 
not a DMNEdge.");
   }
 
   if (beforeIndex > (diagramElement["di:waypoint"]?.length ?? 0) - 1) {
diff --git a/packages/dmn-editor/src/mutations/addShape.ts 
b/packages/dmn-editor/src/mutations/addShape.ts
index fd716e34ae6..f81585b9106 100644
--- a/packages/dmn-editor/src/mutations/addShape.ts
+++ b/packages/dmn-editor/src/mutations/addShape.ts
@@ -20,7 +20,6 @@
 import {
   DC__Point,
   DMN15__tDefinitions,
-  DMNDI15__DMNDecisionServiceDividerLine,
   DMNDI15__DMNShape,
 } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { NodeType } from "../diagram/connections/graphStructure";
diff --git a/packages/dmn-editor/src/mutations/addStandaloneNode.ts 
b/packages/dmn-editor/src/mutations/addStandaloneNode.ts
index aad8ac660df..ce78b8b3ac9 100644
--- a/packages/dmn-editor/src/mutations/addStandaloneNode.ts
+++ b/packages/dmn-editor/src/mutations/addStandaloneNode.ts
@@ -18,7 +18,7 @@
  */
 
 import { switchExpression } from "@kie-tools-core/switch-expression-ts";
-import { DmnBuiltInDataType, generateUuid } from 
"@kie-tools/boxed-expression-component/dist/api";
+import { generateUuid } from "@kie-tools/boxed-expression-component/dist/api";
 import { DC__Bounds, DMN15__tDefinitions } from 
"@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types";
 import { NodeType } from "../diagram/connections/graphStructure";
 import { NODE_TYPES } from "../diagram/nodes/NodeTypes";
diff --git a/packages/dmn-editor/src/mutations/deleteEdge.ts 
b/packages/dmn-editor/src/mutations/deleteEdge.ts
index 58a3af9e627..38846da5c73 100644
--- a/packages/dmn-editor/src/mutations/deleteEdge.ts
+++ b/packages/dmn-editor/src/mutations/deleteEdge.ts
@@ -27,6 +27,7 @@ import { addOrGetDrd } from "./addOrGetDrd";
 import { DmnDiagramEdgeData } from "../diagram/edges/Edges";
 import { repopulateInputDataAndDecisionsOnAllDecisionServices } from 
"./repopulateInputDataAndDecisionsOnDecisionService";
 import { Normalized } from "../normalization/normalize";
+import { xmlHrefToQName } from "../xml/xmlHrefToQName";
 import { ExternalModelsIndex } from "../DmnEditor";
 
 export enum EdgeDeletionMode {
@@ -47,41 +48,40 @@ export function deleteEdge({
   mode: EdgeDeletionMode;
   externalModelsByNamespace: ExternalModelsIndex | undefined;
 }) {
-  if (edge.dmnObject.namespace !== definitions["@_namespace"]) {
-    console.debug("DMN MUTATION: Can't delete an edge that's from an external 
node.");
-    return { dmnEdge: undefined };
-  }
-
-  const dmnObjects: Normalized<DMN15__tDefinitions>["drgElement" | "artifact"] 
=
-    switchExpression(edge?.dmnObject.type, {
-      association: definitions.artifact,
-      group: definitions.artifact,
-      default: definitions.drgElement,
-    }) ?? [];
+  if (edge.dmnObject.namespace === definitions["@_namespace"]) {
+    const dmnObjects: Normalized<DMN15__tDefinitions>["drgElement" | 
"artifact"] =
+      switchExpression(edge?.dmnObject.type, {
+        association: definitions.artifact,
+        group: definitions.artifact,
+        default: definitions.drgElement,
+      }) ?? [];
 
-  const dmnObjectIndex = dmnObjects.findIndex((d) => d["@_id"] === 
edge.dmnObject.id);
-  if (dmnObjectIndex < 0) {
-    throw new Error(`DMN MUTATION: Can't find DMN element with ID 
${edge.dmnObject.id}`);
-  }
+    const dmnObjectIndex = dmnObjects.findIndex((d) => d["@_id"] === 
edge.dmnObject.id);
+    if (dmnObjectIndex < 0) {
+      throw new Error(`DMN MUTATION: Can't find DMN element with ID 
${edge.dmnObject.id}`);
+    }
 
-  if (mode === EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS) {
-    const requirements =
-      switchExpression(edge?.dmnObject.requirementType, {
-        // Casting to DMN15__tDecision because if has all types of 
requirement, but not necessarily that's true.
-        informationRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).informationRequirement,
-        knowledgeRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).knowledgeRequirement,
-        authorityRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).authorityRequirement,
-        association: dmnObjects,
-      }) ?? [];
+    if (mode === EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS) {
+      const requirements =
+        switchExpression(edge?.dmnObject.requirementType, {
+          // Casting to DMN15__tDecision because if has all types of 
requirement, but not necessarily that's true.
+          informationRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).informationRequirement,
+          knowledgeRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).knowledgeRequirement,
+          authorityRequirement: (dmnObjects[dmnObjectIndex] as 
Normalized<DMN15__tDecision>).authorityRequirement,
+          association: dmnObjects,
+        }) ?? [];
 
-    // Deleting the requirement
-    const requirementIndex = (requirements ?? []).findIndex((d) => d["@_id"] 
=== edge.id);
-    if (requirementIndex >= 0) {
-      requirements?.splice(requirementIndex, 1);
+      // Deleting the requirement
+      const requirementIndex = (requirements ?? []).findIndex((d) => d["@_id"] 
=== edge.id);
+      if (requirementIndex >= 0) {
+        requirements?.splice(requirementIndex, 1);
+      }
     }
   }
 
   // Deleting the DMNEdge's
+  // needs to be executed even if edge.dmnObject.namespace !== 
definitions["@_namespace"]
+  // As they may be DMNEdge depictions for edges targeting external nodes
   let deletedDmnEdgeOnCurrentDrd: Normalized<DMNDI15__DMNEdge> | undefined;
 
   const drdCount = (definitions["dmndi:DMNDI"]?.["dmndi:DMNDiagram"] ?? 
[]).length;
@@ -92,7 +92,9 @@ export function deleteEdge({
       continue;
     }
 
-    const dmnEdgeIndex = (diagramElements ?? []).findIndex((d) => 
d["@_dmnElementRef"] === edge.id);
+    const dmnEdgeIndex = (diagramElements ?? []).findIndex(
+      (d) => d["@_dmnElementRef"] === xmlHrefToQName(edge.id, definitions)
+    );
     if (dmnEdgeIndex >= 0) {
       if (i === drdIndex) {
         deletedDmnEdgeOnCurrentDrd = diagramElements[dmnEdgeIndex];
diff --git a/packages/dmn-editor/src/store/computed/computeDiagramData.ts 
b/packages/dmn-editor/src/store/computed/computeDiagramData.ts
index 0c15d4839cd..6205dc4c921 100644
--- a/packages/dmn-editor/src/store/computed/computeDiagramData.ts
+++ b/packages/dmn-editor/src/store/computed/computeDiagramData.ts
@@ -38,6 +38,7 @@ import { Computed, State } from "../Store";
 import { getDecisionServicePropertiesRelativeToThisDmn } from 
"../../mutations/addExistingDecisionServiceToDrd";
 import { Normalized } from "../../normalization/normalize";
 import { KIE_UNKNOWN_NAMESPACE } from "../../kie/kie";
+import { xmlHrefToQName } from "../../xml/xmlHrefToQName";
 
 export const NODE_LAYERS = {
   GROUP_NODE: 0,
@@ -99,7 +100,7 @@ export function computeDiagramData(
   const ackEdge: AckEdge = ({ id, type, dmnObject, source, target, 
sourceNamespace }) => {
     const data = {
       dmnObject,
-      dmnEdge: id ? indexedDrd.dmnEdgesByDmnElementRef.get(id) : undefined,
+      dmnEdge: id ? indexedDrd.dmnEdgesByDmnElementRef.get(xmlHrefToQName(id, 
definitions)) : undefined,
       dmnShapeSource: indexedDrd.dmnShapesByHref.get(source),
       dmnShapeTarget: indexedDrd.dmnShapesByHref.get(target),
     };
@@ -421,7 +422,11 @@ function ackRequirementEdges(
       (dmnObject.informationRequirement ?? []).forEach((ir, index) => {
         const irHref = parseXmlHref((ir.requiredDecision ?? 
ir.requiredInput)!["@_href"]);
         ackEdge({
-          id: ir["@_id"]!,
+          // HREF format, used as RF.Edge ID
+          id:
+            drgElementsNamespace === thisDmnsNamespace
+              ? ir["@_id"]
+              : buildXmlHref({ namespace: drgElementsNamespace, id: ir["@_id"] 
}),
           dmnObject: {
             namespace: drgElementsNamespace,
             type: dmnObject.__$$element,
@@ -441,7 +446,11 @@ function ackRequirementEdges(
       (dmnObject.knowledgeRequirement ?? []).forEach((kr, index) => {
         const krHref = parseXmlHref(kr.requiredKnowledge["@_href"]);
         ackEdge({
-          id: kr["@_id"]!,
+          // HREF format, used as RF.Edge ID
+          id:
+            drgElementsNamespace === thisDmnsNamespace
+              ? kr["@_id"]
+              : buildXmlHref({ namespace: drgElementsNamespace, id: kr["@_id"] 
}),
           dmnObject: {
             namespace: drgElementsNamespace,
             type: dmnObject.__$$element,
diff --git a/packages/dmn-editor/tests-e2e/__fixtures__/drgNodes.ts 
b/packages/dmn-editor/tests-e2e/__fixtures__/drgNodes.ts
index 790b3778b1b..27c0e472608 100644
--- a/packages/dmn-editor/tests-e2e/__fixtures__/drgNodes.ts
+++ b/packages/dmn-editor/tests-e2e/__fixtures__/drgNodes.ts
@@ -26,7 +26,7 @@ export class DrgNodes {
     public page: Page
   ) {}
 
-  public async open() {
+  public async toggle() {
     await this.page.getByTitle("DRG Nodes").click();
   }
 
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ar-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ar-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..718044ce3e1
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ar-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ir-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ir-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..f4c321d972f
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-ir-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-kr-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-kr-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..b2ba9406603
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/drds/drds-kr-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ar-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ar-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..42bb737451f
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ar-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ir-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ir-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..960bc05e324
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-ir-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-kr-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-kr-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..b48c794d9da
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/drds/drds-kr-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ar-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ar-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..cf1a32eb72d
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ar-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ir-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ir-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..9cc7af48e13
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-ir-edge-depiction-waypoint.png
 differ
diff --git 
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-kr-edge-depiction-waypoint.png
 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-kr-edge-depiction-waypoint.png
new file mode 100644
index 00000000000..3b1fddcfda2
Binary files /dev/null and 
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/drds/drds-kr-edge-depiction-waypoint.png
 differ
diff --git a/packages/dmn-editor/tests-e2e/drds/modelDrd.spec.ts 
b/packages/dmn-editor/tests-e2e/drds/modelDrd.spec.ts
index 9ab8801f115..1bc943e3a3a 100644
--- a/packages/dmn-editor/tests-e2e/drds/modelDrd.spec.ts
+++ b/packages/dmn-editor/tests-e2e/drds/modelDrd.spec.ts
@@ -136,13 +136,13 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await drds.toggle();
         await drds.navigateTo({ name: "Third DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
         await expect(nodes.get({ name: DefaultNodeName.DECISION 
})).toBeAttached();
 
@@ -166,13 +166,13 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await drds.toggle();
         await drds.navigateTo({ name: "Third DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await nodes.delete({ name: DefaultNodeName.DECISION });
@@ -199,13 +199,13 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await drds.toggle();
         await drds.navigateTo({ name: "Third DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await nodes.selectLabel({ name: DefaultNodeName.DECISION });
@@ -233,7 +233,7 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
         await drgNodes.dragNode({ name: DefaultNodeName.INPUT_DATA, 
targetPosition: { x: 300, y: 500 } });
         await nodes.dragNewConnectedEdge({
@@ -272,7 +272,7 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
 
         await 
expect(diagram.get()).toHaveScreenshot("drds-decision-missing-dependency.png");
@@ -301,7 +301,7 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 300, y: 300 } });
         await drgNodes.dragNode({ name: DefaultNodeName.INPUT_DATA, 
targetPosition: { x: 300, y: 500 } });
 
@@ -327,7 +327,7 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 500, y: 500 } });
 
         await nodes.move({ name: DefaultNodeName.DECISION, targetPosition: { 
x: 400, y: 400 } });
@@ -357,7 +357,7 @@ test.describe("Model DRD", () => {
         await drds.toggle();
         await drds.navigateTo({ name: "Second DRD" });
         await drds.toggle();
-        await drgNodes.open();
+        await drgNodes.toggle();
         await drgNodes.dragNode({ name: DefaultNodeName.DECISION, 
targetPosition: { x: 500, y: 500 } });
 
         await nodes.resize({ nodeName: DefaultNodeName.DECISION, xOffset: 100, 
yOffset: 100 });
@@ -371,6 +371,164 @@ test.describe("Model DRD", () => {
         expect(width).toEqual("160");
         expect(height).toEqual("80");
       });
+
+      test.describe("Model DRD - Add Content - Edge Depiction Waypoint", async 
() => {
+        /**
+         *      C       A: Decision
+         *      ^       B: Decision
+         *      |       C: Decision
+         * B -> A       I: InputData
+         *      ^
+         *      |
+         *      I
+         */
+        test("should add waypoint to secondary edge depiction - information 
requirement", async ({
+          diagram,
+          drds,
+          drgNodes,
+          edges,
+          nodes,
+          palette,
+        }) => {
+          test.info().annotations.push({
+            type: TestAnnotations.REGRESSION,
+            description: 
"https://github.com/apache/incubator-kie-issues/issues/886";,
+          });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "First DRD" });
+          await drds.toggle();
+          await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: 
{ x: 400, y: 300 }, thenRenameTo: "A" });
+          await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: 
{ x: 100, y: 300 }, thenRenameTo: "B" });
+          await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: 
{ x: 400, y: 100 }, thenRenameTo: "C" });
+          await palette.dragNewNode({
+            type: NodeType.INPUT_DATA,
+            targetPosition: { x: 400, y: 500 },
+            thenRenameTo: "I",
+          });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.INFORMATION_REQUIREMENT, from: "B", to: "A" });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.INFORMATION_REQUIREMENT, from: "A", to: "C" });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.INFORMATION_REQUIREMENT, from: "I", to: "A" });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "Second DRD" });
+          await drds.toggle();
+          await drgNodes.toggle();
+          await drgNodes.dragNode({ name: "A", targetPosition: { x: 400, y: 
300 } });
+          await drgNodes.dragNode({ name: "B", targetPosition: { x: 100, y: 
300 } });
+          await drgNodes.dragNode({ name: "C", targetPosition: { x: 400, y: 
100 } });
+          await drgNodes.dragNode({ name: "I", targetPosition: { x: 400, y: 
500 } });
+          await drgNodes.toggle();
+
+          await edges.addWaypoint({ from: "B", to: "A" });
+          await edges.addWaypoint({ from: "A", to: "C" });
+          await edges.addWaypoint({ from: "I", to: "A" });
+
+          await nodes.move({ name: "A", targetPosition: { x: 600, y: 400 } });
+
+          await 
expect(diagram.get()).toHaveScreenshot("drds-ir-edge-depiction-waypoint.png");
+        });
+
+        /**
+         *                   A: Decision
+         * B -> A <- C       B: BusinessKnowledgeModel
+         *                   C: DecisionService
+         */
+        test("should add waypoint to secondary edge depiction - knowledge 
requirement", async ({
+          diagram,
+          drds,
+          drgNodes,
+          edges,
+          nodes,
+          palette,
+        }) => {
+          test.info().annotations.push({
+            type: TestAnnotations.REGRESSION,
+            description: 
"https://github.com/apache/incubator-kie-issues/issues/886";,
+          });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "First DRD" });
+          await drds.toggle();
+          await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: 
{ x: 400, y: 300 }, thenRenameTo: "A" });
+          await palette.dragNewNode({ type: NodeType.BKM, targetPosition: { x: 
100, y: 300 }, thenRenameTo: "B" });
+          await palette.dragNewNode({
+            type: NodeType.DECISION_SERVICE,
+            targetPosition: { x: 600, y: 300 },
+            thenRenameTo: "C",
+          });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.KNOWLEDGE_REQUIREMENT, from: "B", to: "A" });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.KNOWLEDGE_REQUIREMENT, from: "C", to: "A" });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "Second DRD" });
+          await drds.toggle();
+          await drgNodes.toggle();
+          await drgNodes.dragNode({ name: "A", targetPosition: { x: 400, y: 
300 } });
+          await drgNodes.dragNode({ name: "B", targetPosition: { x: 100, y: 
300 } });
+          await drgNodes.dragNode({ name: "C", targetPosition: { x: 600, y: 
300 } });
+          await drgNodes.toggle();
+
+          await edges.addWaypoint({ from: "B", to: "A" });
+          await edges.addWaypoint({ from: "C", to: "A" });
+
+          await nodes.move({ name: "A", targetPosition: { x: 400, y: 200 } });
+
+          await 
expect(diagram.get()).toHaveScreenshot("drds-kr-edge-depiction-waypoint.png");
+        });
+
+        /**
+         *                  A: Decision
+         * B -> A -> C      B: KnowledgeSource
+         *                  C: KnowledgeSource
+         */
+        test("should add waypoint to secondary edge depiction - authority 
requirement", async ({
+          diagram,
+          drds,
+          drgNodes,
+          edges,
+          nodes,
+          palette,
+        }) => {
+          test.info().annotations.push({
+            type: TestAnnotations.REGRESSION,
+            description: 
"https://github.com/apache/incubator-kie-issues/issues/886";,
+          });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "First DRD" });
+          await drds.toggle();
+          await palette.dragNewNode({ type: NodeType.DECISION, targetPosition: 
{ x: 400, y: 300 }, thenRenameTo: "A" });
+          await palette.dragNewNode({
+            type: NodeType.KNOWLEDGE_SOURCE,
+            targetPosition: { x: 100, y: 300 },
+            thenRenameTo: "B",
+          });
+          await palette.dragNewNode({
+            type: NodeType.KNOWLEDGE_SOURCE,
+            targetPosition: { x: 600, y: 300 },
+            thenRenameTo: "C",
+          });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.AUTHORITY_REQUIREMENT, from: "B", to: "A" });
+          await nodes.dragNewConnectedEdge({ type: 
EdgeType.AUTHORITY_REQUIREMENT, from: "A", to: "C" });
+
+          await drds.toggle();
+          await drds.navigateTo({ name: "Second DRD" });
+          await drds.toggle();
+          await drgNodes.toggle();
+          await drgNodes.dragNode({ name: "A", targetPosition: { x: 400, y: 
300 } });
+          await drgNodes.dragNode({ name: "B", targetPosition: { x: 100, y: 
300 } });
+          await drgNodes.dragNode({ name: "C", targetPosition: { x: 600, y: 
300 } });
+          await drgNodes.toggle();
+
+          await edges.addWaypoint({ from: "B", to: "A" });
+          await edges.addWaypoint({ from: "A", to: "C" });
+
+          await nodes.move({ name: "A", targetPosition: { x: 400, y: 200 } });
+
+          await 
expect(diagram.get()).toHaveScreenshot("drds-ar-edge-depiction-waypoint.png");
+        });
+      });
     });
   });
 });


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to