Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kie-issues#1298: Decision Services & multiple DRDs: make it possible o add external Decisions to a Decision Service #2508

Merged
merged 39 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b690ebb
kie-issues#1298: Decision Services & multiple DRDs: make it possible …
danielzhe Jul 31, 2024
33de8ea
Tests e2e
danielzhe Aug 2, 2024
2db60f6
webkit
danielzhe Aug 2, 2024
b55113d
Code review. More tests. Fixed an issue about moving nodes from DS to…
danielzhe Aug 5, 2024
24f1b15
Tests screenshots 1
danielzhe Aug 5, 2024
f916099
Tests screenshots 2
danielzhe Aug 5, 2024
99924ea
Tests screenshots 3
danielzhe Aug 6, 2024
d64a04e
Better screenshots for test.
danielzhe Aug 6, 2024
a078041
Mutations now does not count with "correct parameters".
danielzhe Aug 6, 2024
c9f88bf
Href.
danielzhe Aug 7, 2024
411e61d
Merge branch 'main' into included-ds
danielzhe Aug 7, 2024
6cd536f
Update packages/dmn-editor/src/mutations/addDecisionToDecisionService.ts
danielzhe Aug 7, 2024
a44b7da
Update packages/dmn-editor/src/diagram/Diagram.tsx
danielzhe Aug 7, 2024
fad6167
Update packages/dmn-editor/src/mutations/deleteDecisionFromDecisionSe…
danielzhe Aug 7, 2024
3ee4271
Fix build error (??????)
danielzhe Aug 7, 2024
a84bea2
Merge branch 'main' into included-ds
danielzhe Aug 9, 2024
90c03ff
Fixed the invocation string
danielzhe Aug 14, 2024
c3c23dd
Merge branch 'main' into included-ds
danielzhe Aug 14, 2024
54b419c
Fixed hooks
danielzhe Aug 19, 2024
40a0fdf
Merge branch 'main' into included-ds
danielzhe Aug 22, 2024
227ee5a
Merge branch 'main' into included-ds
danielzhe Sep 2, 2024
3d8abb5
Handles 3rd level of included models
danielzhe Sep 2, 2024
9d7a04e
Fix
danielzhe Sep 3, 2024
a5f3e71
Update packages/dmn-editor/src/propertiesPanel/DecisionServicePropert…
danielzhe Sep 5, 2024
8bbb1cf
Fixing hooks and renaming variable
danielzhe Sep 5, 2024
81d260f
Reduce nesting. Remove unused parameters.
danielzhe Sep 9, 2024
1bdc614
.
tiagobento Sep 11, 2024
ffa1867
Merge pull request #8 from tiagobento/included-ds-pair-programming-da…
danielzhe Sep 11, 2024
2921171
Merge branch 'main' into included-ds
danielzhe Sep 11, 2024
e22fcd1
Refactor DmnEditorRoot
danielzhe Sep 12, 2024
3cb35a5
Refactor DmnEditorRoot
danielzhe Sep 12, 2024
334cf35
Clean
danielzhe Sep 12, 2024
bd5786c
clean
danielzhe Sep 12, 2024
0e90a76
Update packages/dmn-editor/src/mutations/deleteImport.ts
danielzhe Sep 19, 2024
a03e182
Fixes issues 3 and 4
danielzhe Sep 25, 2024
d9408e7
decisionHref
danielzhe Sep 25, 2024
4759ae3
hook
danielzhe Sep 25, 2024
91a815f
Revert
danielzhe Sep 26, 2024
702f44f
Fix 3 and 4 issues
danielzhe Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 104 additions & 2 deletions packages/dmn-editor-envelope/src/DmnEditorRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import * as __path from "path";
import * as React from "react";
import { useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import * as DmnEditor from "@kie-tools/dmn-editor/dist/DmnEditor";
import { normalize, Normalized } from "@kie-tools/dmn-editor/dist/normalization/normalize";
import { DMN_LATEST_VERSION, DmnLatestModel, DmnMarshaller, getMarshaller } from "@kie-tools/dmn-marshaller";
Expand Down Expand Up @@ -563,6 +563,94 @@
};
}, [thisDmnsNormalizedPosixPathRelativeToTheWorkspaceRoot]);

const getIncludedNamespacesFromModel = useCallback((model: Normalized<DmnLatestModel>) => {
return (model.definitions.import ?? [])
.map((i) => getNamespaceOfDmnImport({ dmnImport: i }))
.join(NAMESPACES_EFFECT_SEPARATOR);
}, []);
tiagobento marked this conversation as resolved.
Show resolved Hide resolved

const getDmnsByNamespace = useCallback((resources: (ResourceContent | undefined)[]) => {
const ret = new Map<string, ResourceContent>();
for (let i = 0; i < resources.length; i++) {
const resource = resources[i];
if (!resource) {
continue;
}

const content = resource.content ?? "";
const ext = __path.extname(resource.normalizedPosixPathRelativeToTheWorkspaceRoot);
if (ext === ".dmn") {
const namespace = domParser.getDomDocument(content).documentElement.getAttribute("namespace");
if (namespace) {
// Check for multiplicity of namespaces on DMN models
if (ret.has(namespace)) {
console.warn(
`DMN EDITOR ROOT: Multiple DMN models encountered with the same namespace '${namespace}': '${
resource.normalizedPosixPathRelativeToTheWorkspaceRoot
}' and '${
ret.get(namespace)!.normalizedPosixPathRelativeToTheWorkspaceRoot
}'. The latter will be considered.`
);
}

ret.set(namespace, resource);
}
}
}

return ret;
}, []);

// Load all included models from the model and the included models of those models, recursively.
const loadDependentModels = useCallback(
(
model: Normalized<DmnLatestModel>,
externalModelsIndex: DmnEditor.ExternalModelsIndex,
resourcesByNamespace: Map<string, ResourceContent>,
loadedDmnsByPathRelativeToTheWorkspaceRoot: Set<string>,
thisDmnsNormalizedPosixPathRelativeToTheWorkspaceRoot: string
) => {
const includedNamespaces = new Set(getIncludedNamespacesFromModel(model).split(NAMESPACES_EFFECT_SEPARATOR));

for (const includedNamespace of includedNamespaces) {
if (!resourcesByNamespace.has(includedNamespace)) {
console.warn(
`DMN EDITOR ROOT: The included namespace '${includedNamespace}' for the model '${model.definitions["@_id"]}' can not be found.`
);
} else {
const resource = resourcesByNamespace.get(includedNamespace)!;
if (loadedDmnsByPathRelativeToTheWorkspaceRoot.has(resource.normalizedPosixPathRelativeToTheWorkspaceRoot)) {
continue;
}

const normalizedPosixPathRelativeToTheOpenFile = __path.relative(
__path.dirname(thisDmnsNormalizedPosixPathRelativeToTheWorkspaceRoot),
resource.normalizedPosixPathRelativeToTheWorkspaceRoot
);
const content = resource.content ?? "";
const includedModel = normalize(getMarshaller(content, { upgradeTo: "latest" }).parser.parse());
externalModelsIndex[includedNamespace] = {
normalizedPosixPathRelativeToTheOpenFile,
model: includedModel,
type: "dmn",
svg: "",
};

loadedDmnsByPathRelativeToTheWorkspaceRoot.add(resource.normalizedPosixPathRelativeToTheWorkspaceRoot);

loadDependentModels(
includedModel,
externalModelsIndex,
resourcesByNamespace,
loadedDmnsByPathRelativeToTheWorkspaceRoot,
thisDmnsNormalizedPosixPathRelativeToTheWorkspaceRoot
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useCallback depends on itself.. This is not very good I'd say. Not even sure how ESLint didn't complain about this, as you're inhenritenly depending on loadDependentModels from a previous tick (I.e., outdated getIncludedNamespacesFromModel).

}
}
},
[getIncludedNamespacesFromModel]
);

// This effect actually populates `externalModelsByNamespace` through the `onChange` call.
useEffect(() => {
let canceled = false;
Expand Down Expand Up @@ -594,7 +682,7 @@
const externalModelsIndex: DmnEditor.ExternalModelsIndex = {};

const namespacesSet = new Set(namespaces.split(NAMESPACES_EFFECT_SEPARATOR));

const loadedDmnsByPathRelativeToTheWorkspaceRoot = new Set<string>();
for (let i = 0; i < resources.length; i++) {
const resource = resources[i];
if (!resource) {
Expand Down Expand Up @@ -623,6 +711,7 @@
);
}

loadedDmnsByPathRelativeToTheWorkspaceRoot.add(resource.normalizedPosixPathRelativeToTheWorkspaceRoot);
externalModelsIndex[namespace] = {
normalizedPosixPathRelativeToTheOpenFile,
model: normalize(getMarshaller(content, { upgradeTo: "latest" }).parser.parse()),
Expand All @@ -645,6 +734,19 @@
}
}

const dmnsByNamespace = getDmnsByNamespace(resources);
for (const dmn of dmnsByNamespace.values()) {
const content = dmn.content ?? "";
const model = normalize(getMarshaller(content, { upgradeTo: "latest" }).parser.parse());
loadDependentModels(
model,
externalModelsIndex,
dmnsByNamespace,
loadedDmnsByPathRelativeToTheWorkspaceRoot,
thisDmnsNormalizedPosixPathRelativeToTheWorkspaceRoot
);
}
tiagobento marked this conversation as resolved.
Show resolved Hide resolved

if (!canceled) {
onChange(externalModelsIndex);
}
Expand All @@ -654,7 +756,7 @@
return () => {
canceled = true;
};
}, [

Check warning on line 759 in packages/dmn-editor-envelope/src/DmnEditorRoot.tsx

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 2)

React Hook useEffect has missing dependencies: 'getDmnsByNamespace' and 'loadDependentModels'. Either include them or remove the dependency array

Check warning on line 759 in packages/dmn-editor-envelope/src/DmnEditorRoot.tsx

View workflow job for this annotation

GitHub Actions / run (windows-latest, 2)

React Hook useEffect has missing dependencies: 'getDmnsByNamespace' and 'loadDependentModels'. Either include them or remove the dependency array
namespaces,
onChange,
onRequestWorkspaceFileContent,
Expand Down
4 changes: 3 additions & 1 deletion packages/dmn-editor/src/DmnEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,9 @@ export const DmnEditorInternal = ({
</Tab>

<Tab eventKey={DmnEditorTab.INCLUDED_MODELS} title={tabTitle.includedModels}>
{navigationTab === DmnEditorTab.INCLUDED_MODELS && <IncludedModels />}
<div data-testid={"kie-tools--dmn-editor--included-models-container"}>
{navigationTab === DmnEditorTab.INCLUDED_MODELS && <IncludedModels />}
</div>
</Tab>
</Tabs>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/dmn-editor/src/autolayout/AutolayoutButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export function AutolayoutButton() {
__readonly_drdIndex: s.computed(s).getDrdIndex(),
__readonly_dmnObjectNamespace: s.dmn.model.definitions["@_namespace"],
__readonly_externalDmnsIndex: s.computed(s).getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
__readonly_externalModelsByNamespace: externalModelsByNamespace,
});
});
}, [dmnEditorStoreApi, externalModelsByNamespace]);
Expand Down
18 changes: 16 additions & 2 deletions packages/dmn-editor/src/diagram/Diagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@
shapeId: targetNode.data.shape["@_id"],
},
keepWaypoints: false,
externalModelsByNamespace,
});
});
},
Expand Down Expand Up @@ -337,6 +338,7 @@
})["@_height"],
},
},
externalModelsByNamespace,
});
state.diagram._selectedNodes = [newNodeId];
state.focus.consumableId = newNodeId;
Expand Down Expand Up @@ -670,6 +672,7 @@
})["@_height"],
},
},
externalModelsByNamespace,
});

state.diagram._selectedNodes = [newDmnObejctHref];
Expand Down Expand Up @@ -876,6 +879,7 @@
__readonly_externalModelTypesByNamespace: state
.computed(state)
.getExternalModelTypesByNamespace(externalModelsByNamespace),
externalModelsByNamespace,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React hook dependency missing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__readonly_externalModelsByNamespace

});
state.dispatch(state).diagram.setNodeStatus(node.id, {
selected: false,
Expand All @@ -897,7 +901,7 @@
}
});
},
[reactFlowInstance, dmnEditorStoreApi, externalModelsByNamespace]

Check warning on line 904 in packages/dmn-editor/src/diagram/Diagram.tsx

View workflow job for this annotation

GitHub Actions / run (ubuntu-latest, 2)

React Hook useCallback has an unnecessary dependency: 'reactFlowInstance'. Either exclude it or remove the dependency array

Check warning on line 904 in packages/dmn-editor/src/diagram/Diagram.tsx

View workflow job for this annotation

GitHub Actions / run (windows-latest, 2)

React Hook useCallback has an unnecessary dependency: 'reactFlowInstance'. Either exclude it or remove the dependency array
);

const resetToBeforeEditingBegan = useCallback(() => {
Expand Down Expand Up @@ -990,8 +994,9 @@
for (let i = 0; i < selectedNodes.length; i++) {
deleteDecisionFromDecisionService({
definitions: state.dmn.model.definitions,
decisionId: selectedNodes[i].data.dmnObject!["@_id"]!, // We can assume that all selected nodes are Decisions because the contaiment was validated above.
decisionHref: selectedNodes[i].id, // We can assume that all selected nodes are Decisions because the contaiment was validated above.
decisionServiceId: p.data.dmnObject!["@_id"]!,
externalModelsByNamespace,
});
}
} else {
Expand All @@ -1007,12 +1012,13 @@
addDecisionToDecisionService({
definitions: state.dmn.model.definitions,
drdIndex: state.computed(state).getDrdIndex(),
decisionId: selectedNodes[i].data.dmnObject!["@_id"]!, // We can assume that all selected nodes are Decisions because the contaiment was validated above.
decisionHref: selectedNodes[i].id, // We can assume that all selected nodes are Decisions because the contaiment was validated above.
decisionServiceId: state
.computed(state)
.getDiagramData(externalModelsByNamespace)
.nodesById.get(dropTargetNode.id)!.data.dmnObject!["@_id"]!,
snapGrid: state.diagram.snapGrid,
externalModelsByNamespace,
});
}
} else {
Expand Down Expand Up @@ -1047,6 +1053,7 @@
drdIndex: state.computed(state).getDrdIndex(),
edge: { id: change.id, dmnObject: edge.data.dmnObject },
mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS,
externalModelsByNamespace,
});
state.dispatch(state).diagram.setEdgeStatus(change.id, {
selected: false,
Expand Down Expand Up @@ -1125,6 +1132,7 @@
shapeId: targetNode.data.shape["@_id"],
},
keepWaypoints: true,
externalModelsByNamespace: externalModelsByNamespace,
tiagobento marked this conversation as resolved.
Show resolved Hide resolved
});

// The DMN Edge changed nodes, so we need to delete the old one, but keep the waypoints on the same DRD.
Expand All @@ -1134,6 +1142,7 @@
drdIndex: state.computed(state).getDrdIndex(),
edge: { id: oldEdge.id, dmnObject: oldEdge.data!.dmnObject },
mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS,
externalModelsByNamespace,
});

const deletedWaypoints = deletedDmnEdgeOnCurrentDrd?.["di:waypoint"];
Expand Down Expand Up @@ -1435,6 +1444,7 @@
__readonly_externalDmnsIndex: dereferencedState
.computed(dereferencedState)
.getExternalModelTypesByNamespace(externalModelsByNamespace).dmns,
__readonly_externalModelsByNamespace: externalModelsByNamespace,
});
s.dmn.model = dereferencedState.dmn.model;
});
Expand Down Expand Up @@ -1463,6 +1473,7 @@
isReadOnly?: boolean;
}) {
const dmnEditorStoreApi = useDmnEditorStoreApi();
const { externalModelsByNamespace } = useExternalModels();

return (
<Bullseye
Expand Down Expand Up @@ -1524,6 +1535,7 @@
})["@_height"],
},
},
externalModelsByNamespace,
});

const drgElementIndex = (state.dmn.model.definitions.drgElement ?? []).length - 1;
Expand Down Expand Up @@ -1584,6 +1596,7 @@
type: NODE_TYPES.inputData,
bounds: inputDataNodeBounds,
},
externalModelsByNamespace,
});

const { href: decisionNodeHref } = addConnectedNode({
Expand All @@ -1609,6 +1622,7 @@
})["@_height"],
},
},
externalModelsByNamespace: externalModelsByNamespace,
});

state.diagram._selectedNodes = [decisionNodeHref];
Expand Down
33 changes: 27 additions & 6 deletions packages/dmn-editor/src/diagram/DiagramCommands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export function DiagramCommands(props: {}) {
drdIndex: state.computed(state).getDrdIndex(),
edge: { id: edge.id, dmnObject: edge.data!.dmnObject },
mode: EdgeDeletionMode.FROM_DRG_AND_ALL_DRDS,
externalModelsByNamespace,
});
state.dispatch(state).diagram.setEdgeStatus(edge.id, {
selected: false,
Expand All @@ -160,6 +161,7 @@ export function DiagramCommands(props: {}) {
__readonly_externalModelTypesByNamespace: state
.computed(state)
.getExternalModelTypesByNamespace(externalModelsByNamespace),
externalModelsByNamespace,
});
state.dispatch(state).diagram.setNodeStatus(node.id, {
selected: false,
Expand Down Expand Up @@ -239,12 +241,25 @@ export function DiagramCommands(props: {}) {
definitions: state.dmn.model.definitions,
drdIndex: state.computed(state).getDrdIndex(),
});
diagramElements.push(...clipboard.shapes.map((s) => ({ ...s, __$$element: "dmndi:DMNShape" as const })));
diagramElements.push(...clipboard.edges.map((s) => ({ ...s, __$$element: "dmndi:DMNEdge" as const })));
diagramElements.push(
...clipboard.shapes.map((s) => ({
...s,
__$$element: "dmndi:DMNShape" as const,
}))
);
diagramElements.push(
...clipboard.edges.map((s) => ({
...s,
__$$element: "dmndi:DMNEdge" as const,
}))
);

widths.push(...clipboard.widths);

repopulateInputDataAndDecisionsOnAllDecisionServices({ definitions: state.dmn.model.definitions });
repopulateInputDataAndDecisionsOnAllDecisionServices({
definitions: state.dmn.model.definitions,
externalModelsByNamespace,
});

state.diagram._selectedNodes = [...clipboard.drgElements, ...clipboard.artifacts].map((s) =>
buildXmlHref({ id: s["@_id"]! })
Expand All @@ -256,7 +271,7 @@ export function DiagramCommands(props: {}) {
});
});
};
}, [dmnEditorStoreApi, commandsRef]);
}, [dmnEditorStoreApi, commandsRef, externalModelsByNamespace]);

// Select/deselect all nodes
useEffect(() => {
Expand Down Expand Up @@ -317,12 +332,13 @@ export function DiagramCommands(props: {}) {
padding: CONTAINER_NODES_DESIRABLE_PADDING,
}),
},
externalModelsByNamespace,
});

state.dispatch(state).diagram.setNodeStatus(newNodeId, { selected: true });
});
};
}, [dmnEditorStoreApi, commandsRef, rf]);
}, [dmnEditorStoreApi, commandsRef, rf, externalModelsByNamespace]);

// Toggle hierarchy highlights
useEffect(() => {
Expand Down Expand Up @@ -393,8 +409,12 @@ export function DiagramCommands(props: {}) {
drdIndex: state.computed(state).getDrdIndex(),
edge: { id: edge.id, dmnObject: edge.data!.dmnObject },
mode: EdgeDeletionMode.FROM_CURRENT_DRD_ONLY,
externalModelsByNamespace,
});
state.dispatch(state).diagram.setEdgeStatus(edge.id, {
selected: false,
draggingWaypoint: false,
});
state.dispatch(state).diagram.setEdgeStatus(edge.id, { selected: false, draggingWaypoint: false });
}
}

Expand All @@ -415,6 +435,7 @@ export function DiagramCommands(props: {}) {
__readonly_dmnObjectId: node.data.dmnObject?.["@_id"],
__readonly_nodeNature: nodeNatures[node.type as NodeType],
mode: NodeDeletionMode.FROM_CURRENT_DRD_ONLY,
externalModelsByNamespace,
});

if (deletedShape) {
Expand Down
3 changes: 1 addition & 2 deletions packages/dmn-editor/src/diagram/DrgNodesPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ export function DrgNodesPanel() {
const containingDecisionServiceHrefsByDecisionHrefsRelativeToThisDmn = useMemo(
() =>
computeContainingDecisionServiceHrefsByDecisionHrefs({
drgElements: thisDmnsDrgElements,
drgElementsNamespace: thisDmnsNamespace,
drgElementsNamespaceByNamespace: new Map([[thisDmnsNamespace, thisDmnsDrgElements]]),
thisDmnsNamespace: thisDmnsNamespace,
}),
[thisDmnsDrgElements, thisDmnsNamespace]
Expand Down
Loading
Loading