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]