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 ff41758977b kie-issues#1823: Integrate DMN Runner evaluation data with
KIE Sandbox (#2942)
ff41758977b is described below
commit ff41758977b512bee3ef41aba1751cd25cf3a427
Author: Jozef Marko <[email protected]>
AuthorDate: Fri Mar 7 17:11:31 2025 +0100
kie-issues#1823: Integrate DMN Runner evaluation data with KIE Sandbox
(#2942)
---
packages/dmn-editor-envelope/src/DmnEditorRoot.tsx | 8 +-
.../src/NewDmnEditorEnvelopeApi.ts | 2 +
.../src/NewDmnEditorEnvelopeApiFactory.ts | 7 ++
.../src/NewDmnEditorFactory.tsx | 5 +
...mnEditorEnvelopeApi.ts => NewDmnEditorTypes.ts} | 10 +-
packages/dmn-editor/src/DmnEditor.css | 4 +-
packages/dmn-editor/src/DmnEditor.tsx | 23 +++--
packages/dmn-editor/src/DmnEditorContext.tsx | 8 +-
.../src/boxedExpressions/BoxedExpressionScreen.tsx | 9 ++
packages/dmn-editor/src/diagram/nodes/Nodes.tsx | 9 +-
.../dmn-editor/stories/dev/DevWebApp.stories.tsx | 4 +-
.../dmn-editor/stories/dmnEditorStoriesWrapper.tsx | 12 ++-
.../stories/misc/empty/Empty.stories.tsx | 2 +-
.../EmptyWithAvailableExternalModels.stories.tsx | 4 +-
.../EvaluationHighlights.stories.tsx | 24 +++--
.../evaluation-highlights-skipped.png | Bin 3307 -> 2486 bytes
.../evaluation-highlights-succeeded.png | Bin 0 -> 3283 bytes
.../evaluation-highlights-success.png | Bin 2467 -> 0 bytes
.../evaluation-highlights-skipped.png | Bin 3319 -> 2498 bytes
.../evaluation-highlights-succeeded.png | Bin 0 -> 3296 bytes
.../evaluation-highlights-success.png | Bin 2478 -> 0 bytes
.../evaluation-highlights-skipped.png | Bin 3087 -> 2183 bytes
.../evaluation-highlights-succeeded.png | Bin 0 -> 3059 bytes
.../evaluation-highlights-success.png | Bin 2147 -> 0 bytes
.../evaluationHighlights.spec.ts | 8 +-
packages/extended-services-api/src/dmnResult.ts | 1 +
packages/form-dmn/src/FormDmnOutputs.tsx | 8 +-
packages/form-dmn/src/i18n/FormDmnI18n.ts | 2 +-
packages/form-dmn/src/i18n/locales/de.ts | 2 +-
packages/form-dmn/src/i18n/locales/en.ts | 2 +-
packages/form-dmn/tests/FormDmnOutputs.test.tsx | 6 ++
.../src/dmnRunner/DmnRunnerContextProvider.tsx | 104 ++++++++++++++++++++-
32 files changed, 213 insertions(+), 51 deletions(-)
diff --git a/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx
b/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx
index f9dc8e02640..f04d98684c7 100644
--- a/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx
+++ b/packages/dmn-editor-envelope/src/DmnEditorRoot.tsx
@@ -74,6 +74,7 @@ export type DmnEditorRootState = {
keyboardShortcutsRegisterIds: number[];
keyboardShortcutsRegistered: boolean;
error: Error | undefined;
+ evaluationResultsByNodeId: DmnEditor.EvaluationResultsByNodeId;
};
export class DmnEditorRoot extends React.Component<DmnEditorRootProps,
DmnEditorRootState> {
@@ -96,6 +97,7 @@ export class DmnEditorRoot extends
React.Component<DmnEditorRootProps, DmnEditor
keyboardShortcutsRegisterIds: [],
keyboardShortcutsRegistered: false,
error: undefined,
+ evaluationResultsByNodeId: new Map(),
};
}
@@ -105,6 +107,10 @@ export class DmnEditorRoot extends
React.Component<DmnEditorRootProps, DmnEditor
this.dmnEditorRef.current?.openBoxedExpressionEditor(nodeId);
}
+ public showDmnEvaluationResults(evaluationResultsByNodeId:
DmnEditor.EvaluationResultsByNodeId): void {
+ this.setState((prev) => ({ ...prev, evaluationResultsByNodeId:
evaluationResultsByNodeId }));
+ }
+
public async undo(): Promise<void> {
this.setState((prev) => ({ ...prev, pointer: Math.max(0, prev.pointer - 1)
}));
}
@@ -479,7 +485,7 @@ export class DmnEditorRoot extends
React.Component<DmnEditorRootProps, DmnEditor
originalVersion={this.state.marshaller?.originalVersion}
model={this.model}
externalModelsByNamespace={this.state.externalModelsByNamespace}
- evaluationResults={{}}
+ evaluationResultsByNodeId={this.state.evaluationResultsByNodeId}
validationMessages={[]}
externalContextName={""}
externalContextDescription={""}
diff --git a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
b/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
index 692f3ca8622..51b567f9b56 100644
--- a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
+++ b/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
@@ -18,6 +18,7 @@
*/
import { KogitoEditorEnvelopeApi } from "@kie-tools-core/editor/dist/api";
+import { NewDmnEditorTypes } from "./NewDmnEditorTypes";
export interface NewDmnEditorEnvelopeApi extends KogitoEditorEnvelopeApi {
/**
@@ -25,4 +26,5 @@ export interface NewDmnEditorEnvelopeApi extends
KogitoEditorEnvelopeApi {
* @param nodeId id of the node to open
*/
dmnEditor_openBoxedExpressionEditor(nodeId: string): void;
+ newDmnEditor_showDmnEvaluationResults(evaluationResultsByNodeId:
NewDmnEditorTypes.EvaluationResultsByNodeId): void;
}
diff --git a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApiFactory.ts
b/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApiFactory.ts
index b8772e3d58a..7c7ae5c2aa5 100644
--- a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApiFactory.ts
+++ b/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApiFactory.ts
@@ -24,6 +24,7 @@ import { NewDmnEditorInterface } from "./NewDmnEditorFactory";
import { NewDmnEditorEnvelopeApi } from "./NewDmnEditorEnvelopeApi";
import { NewDmnEditorChannelApi } from "./NewDmnEditorChannelApi";
import { NewDmnEditorFactory } from "./NewDmnEditorFactory";
+import { NewDmnEditorTypes } from "./NewDmnEditorTypes";
export type NewDmnEnvelopeApiFactoryArgs = EnvelopeApiFactoryArgs<
NewDmnEditorEnvelopeApi,
@@ -43,4 +44,10 @@ export class NewDmnEditorEnvelopeApiImpl
public dmnEditor_openBoxedExpressionEditor(nodeId: string): void {
this.getEditorOrThrowError().openBoxedExpressionEditor(nodeId);
}
+
+ public newDmnEditor_showDmnEvaluationResults(
+ evaluationResultsByNodeId: NewDmnEditorTypes.EvaluationResultsByNodeId
+ ): void {
+
this.getEditorOrThrowError().showDmnEvaluationResults(evaluationResultsByNodeId);
+ }
}
diff --git a/packages/dmn-editor-envelope/src/NewDmnEditorFactory.tsx
b/packages/dmn-editor-envelope/src/NewDmnEditorFactory.tsx
index 80dcfb511b4..3fca40f33df 100644
--- a/packages/dmn-editor-envelope/src/NewDmnEditorFactory.tsx
+++ b/packages/dmn-editor-envelope/src/NewDmnEditorFactory.tsx
@@ -22,6 +22,7 @@ import { EditorFactory, EditorInitArgs,
KogitoEditorEnvelopeContextType } from "
import { NewDmnEditorChannelApi } from "./NewDmnEditorChannelApi";
import { DmnEditorInterface } from "./DmnEditorFactory";
import { NewDmnEditorEnvelopeApi } from "./NewDmnEditorEnvelopeApi";
+import { NewDmnEditorTypes } from "./NewDmnEditorTypes";
export class NewDmnEditorFactory
implements EditorFactory<NewDmnEditorInterface, NewDmnEditorEnvelopeApi,
NewDmnEditorChannelApi>
@@ -42,4 +43,8 @@ export class NewDmnEditorInterface extends DmnEditorInterface
{
public openBoxedExpressionEditor(nodeId: string): void {
this.self.openBoxedExpressionEditor(nodeId);
}
+
+ public showDmnEvaluationResults(evaluationResultsByNodeId:
NewDmnEditorTypes.EvaluationResultsByNodeId): void {
+ this.self.showDmnEvaluationResults(evaluationResultsByNodeId);
+ }
}
diff --git a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
b/packages/dmn-editor-envelope/src/NewDmnEditorTypes.ts
similarity index 71%
copy from packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
copy to packages/dmn-editor-envelope/src/NewDmnEditorTypes.ts
index 692f3ca8622..3aed64bcc60 100644
--- a/packages/dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.ts
+++ b/packages/dmn-editor-envelope/src/NewDmnEditorTypes.ts
@@ -17,12 +17,6 @@
* under the License.
*/
-import { KogitoEditorEnvelopeApi } from "@kie-tools-core/editor/dist/api";
+import type * as NewDmnEditorTypes from "@kie-tools/dmn-editor/dist/DmnEditor";
-export interface NewDmnEditorEnvelopeApi extends KogitoEditorEnvelopeApi {
- /**
- * Open boxed expression editor for given node
- * @param nodeId id of the node to open
- */
- dmnEditor_openBoxedExpressionEditor(nodeId: string): void;
-}
+export { NewDmnEditorTypes };
diff --git a/packages/dmn-editor/src/DmnEditor.css
b/packages/dmn-editor/src/DmnEditor.css
index 3e3ec3996d5..b36e4d8f123 100644
--- a/packages/dmn-editor/src/DmnEditor.css
+++ b/packages/dmn-editor/src/DmnEditor.css
@@ -105,7 +105,7 @@
/* (end) nodes */
/* (begin) decision node evaluation status */
-.kie-dmn-editor--decision-node--evaluation-status-failure::before {
+.kie-dmn-editor--decision-node--evaluation-status-failed::before {
content: "\2716";
font-size: 0.8em;
text-align: left;
@@ -121,7 +121,7 @@
padding-top: 2px;
}
-.kie-dmn-editor--decision-node--evaluation-status-success::before {
+.kie-dmn-editor--decision-node--evaluation-status-succeeded::before {
content: "\2714";
font-size: 0.8em;
text-align: left;
diff --git a/packages/dmn-editor/src/DmnEditor.tsx
b/packages/dmn-editor/src/DmnEditor.tsx
index 455c6629782..acfd8e52cf1 100644
--- a/packages/dmn-editor/src/DmnEditor.tsx
+++ b/packages/dmn-editor/src/DmnEditor.tsx
@@ -72,13 +72,22 @@ export type DmnEditorRef = {
};
/**
- * TODO we need to implement mapping between:
- * - DMN Runner engine
- * - and (extended-services-api/src/dmnResult.ts)
- * - and (EvaluationResults)
- * https://github.com/apache/incubator-kie-issues/issues/1823
+ * We need to keep in sync:
+ * * dmn-editor/src/DmnEditor.tsx - NodeEvaluationResults
+ * * dmn-editor-envelope/src/DmnEditorRoot.tsx -
+ * * dmn-editor-envelope/src/NewDmnEditorEnvelopeApi.tsx -
newDmnEditor_showDmnEvaluationResults
+ * * dmn-editor-envelope/src/NewDmnEditorFactory.tsx -
NewDmnEditorInterface#showDmnEvaluationResults
+ * * extended-services-api/src/dmnResult.ts - DmnEvaluationStatus
+ *
+ * For more details see:
https://github.com/apache/incubator-kie-issues/issues/1823
*/
-export type EvaluationResults = Record<string, "success" | "failure" |
"skipped">;
+export type NodeEvaluationResults = {
+ evaluationResult: EvaluationResult;
+ evaluationHitsCountByRuleOrRowId: Map<string, number>;
+};
+
+export type EvaluationResult = "succeeded" | "failed" | "skipped";
+export type EvaluationResultsByNodeId = Map<string, NodeEvaluationResults>;
export type ValidationMessages = Record<string, any>;
export type OnDmnModelChange = (model: Normalized<DmnLatestModel>) => void;
@@ -136,7 +145,7 @@ export type DmnEditorProps = {
/**
* To show information about execution results directly on the DMN diagram
and/or Boxed Expression Editor, use this prop.
*/
- evaluationResults?: EvaluationResults;
+ evaluationResultsByNodeId?: EvaluationResultsByNodeId;
/**
* To show information about validation messages directly on the DMN diagram
and/or Boxed Expression Editor, use this prop.
*/
diff --git a/packages/dmn-editor/src/DmnEditorContext.tsx
b/packages/dmn-editor/src/DmnEditorContext.tsx
index 909182258e3..875e63ce479 100644
--- a/packages/dmn-editor/src/DmnEditorContext.tsx
+++ b/packages/dmn-editor/src/DmnEditorContext.tsx
@@ -30,7 +30,7 @@ export type DmnEditorContextProviderProps = Pick<
| "model"
| "onRequestToJumpToPath"
| "onRequestToResolvePath"
- | "evaluationResults"
+ | "evaluationResultsByNodeId"
>;
export type DmnModelBeforeEditing = DmnLatestModel;
@@ -42,7 +42,7 @@ export type DmnEditorContextType = Pick<
| "issueTrackerHref"
| "onRequestToJumpToPath"
| "onRequestToResolvePath"
- | "evaluationResults"
+ | "evaluationResultsByNodeId"
> & {
dmnModelBeforeEditingRef: React.MutableRefObject<DmnModelBeforeEditing>;
dmnEditorRootElementRef: React.RefObject<HTMLDivElement>;
@@ -67,7 +67,7 @@ export function DmnEditorContextProvider(props:
React.PropsWithChildren<DmnEdito
issueTrackerHref: props.issueTrackerHref,
onRequestToJumpToPath: props.onRequestToJumpToPath,
onRequestToResolvePath: props.onRequestToResolvePath,
- evaluationResults: props.evaluationResults,
+ evaluationResultsByNodeId: props.evaluationResultsByNodeId,
}),
[
props.externalContextDescription,
@@ -75,7 +75,7 @@ export function DmnEditorContextProvider(props:
React.PropsWithChildren<DmnEdito
props.issueTrackerHref,
props.onRequestToJumpToPath,
props.onRequestToResolvePath,
- props.evaluationResults,
+ props.evaluationResultsByNodeId,
]
);
return <DmnEditorContext.Provider
value={value}>{props.children}</DmnEditorContext.Provider>;
diff --git a/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx
b/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx
index 2028d9a7954..17349f3a642 100644
--- a/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx
+++ b/packages/dmn-editor/src/boxedExpressions/BoxedExpressionScreen.tsx
@@ -92,6 +92,7 @@ import {
RefactorConfirmationDialog,
} from "../refactor/RefactorConfirmationDialog";
import { EvaluationHighlightsBadge } from
"../evaluationHighlights/EvaluationHighlightsBadge";
+import { useDmnEditor } from "../DmnEditorContext";
export function BoxedExpressionScreen({ container }: { container:
React.RefObject<HTMLElement> }) {
const { externalModelsByNamespace } = useExternalModels();
@@ -119,6 +120,9 @@ export function BoxedExpressionScreen({ container }: {
container: React.RefObjec
s.computed(s).getExternalDmnModelsByNamespaceMap(externalModelsByNamespace)
);
+ const { evaluationResultsByNodeId } = useDmnEditor();
+ const isEvaluationHighlightsEnabled = useDmnEditorStore((s) =>
s.diagram.overlays.enableEvaluationHighlights);
+
const onRequestFeelIdentifiers = useCallback(() => {
return new FeelIdentifiers({
_readonly_dmnDefinitions:
dmnEditorStoreApi.getState().dmn.model.definitions,
@@ -534,6 +538,11 @@ export function BoxedExpressionScreen({ container }: {
container: React.RefObjec
widthsById={widthsById}
onWidthsChange={onWidthsChange}
isReadOnly={settings.isReadOnly}
+ evaluationHitsCountById={
+ isEvaluationHighlightsEnabled
+ ? evaluationResultsByNodeId?.get(activeDrgElementId ??
"")?.evaluationHitsCountByRuleOrRowId
+ : undefined
+ }
/>
</div>
</>
diff --git a/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
b/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
index fb9f15e2fc9..b0ba66b7547 100644
--- a/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
+++ b/packages/dmn-editor/src/diagram/nodes/Nodes.tsx
@@ -392,13 +392,14 @@ export const DecisionNode = React.memo(
});
const isEvaluationHighlightsEnabled = useDmnEditorStore((s) =>
s.diagram.overlays.enableEvaluationHighlights);
- const { evaluationResults } = useDmnEditor();
+ const { evaluationResultsByNodeId } = useDmnEditor();
const evaluationResultsClassName = useMemo(
() =>
- isEvaluationHighlightsEnabled && evaluationResults![decision["@_id"]]
!== undefined
- ?
`kie-dmn-editor--decision-node--evaluation-status-${evaluationResults![decision["@_id"]]}`
+ isEvaluationHighlightsEnabled &&
+ evaluationResultsByNodeId?.get(decision["@_id"])?.evaluationResult !==
undefined
+ ?
`kie-dmn-editor--decision-node--evaluation-status-${evaluationResultsByNodeId?.get(decision["@_id"])?.evaluationResult}`
: "",
- [decision, evaluationResults, isEvaluationHighlightsEnabled]
+ [decision, evaluationResultsByNodeId, isEvaluationHighlightsEnabled]
);
return (
diff --git a/packages/dmn-editor/stories/dev/DevWebApp.stories.tsx
b/packages/dmn-editor/stories/dev/DevWebApp.stories.tsx
index 3d9922f2118..8cd50d561e3 100644
--- a/packages/dmn-editor/stories/dev/DevWebApp.stories.tsx
+++ b/packages/dmn-editor/stories/dev/DevWebApp.stories.tsx
@@ -230,7 +230,7 @@ function DevWebApp(args: DmnEditorProps) {
externalContextName: args.externalContextName,
externalContextDescription: args.externalContextDescription,
validationMessages: args.validationMessages,
- evaluationResults: args.evaluationResults,
+ evaluationResultsByNodeId: args.evaluationResultsByNodeId,
issueTrackerHref: args.issueTrackerHref,
onRequestToJumpToPath,
isReadOnly: args.isReadOnly,
@@ -270,7 +270,7 @@ export const WebApp: Story = {
args: {
model: getMarshaller(initialModel, { upgradeTo: "latest" }).parser.parse(),
originalVersion: "1.5",
- evaluationResults: {},
+ evaluationResultsByNodeId: new Map(),
externalContextDescription:
"You're using the DMN Dev webapp, so there's only two simple external
models that can be included.",
externalContextName: "Dev webapp",
diff --git a/packages/dmn-editor/stories/dmnEditorStoriesWrapper.tsx
b/packages/dmn-editor/stories/dmnEditorStoriesWrapper.tsx
index 25191c97e9e..64f95d23927 100644
--- a/packages/dmn-editor/stories/dmnEditorStoriesWrapper.tsx
+++ b/packages/dmn-editor/stories/dmnEditorStoriesWrapper.tsx
@@ -20,13 +20,19 @@
import * as React from "react";
import { useCallback, useState, useRef, useMemo, useEffect } from "react";
import { useArgs } from "@storybook/preview-api";
-import { DmnEditor, DmnEditorProps, DmnEditorRef, EvaluationResults,
ValidationMessages } from "../src/DmnEditor";
+import {
+ DmnEditor,
+ DmnEditorProps,
+ DmnEditorRef,
+ EvaluationResultsByNodeId,
+ ValidationMessages,
+} from "../src/DmnEditor";
import { DmnLatestModel, getMarshaller } from "@kie-tools/dmn-marshaller";
import { normalize } from
"@kie-tools/dmn-marshaller/dist/normalization/normalize";
import { diff } from "deep-object-diff";
import { generateEmptyDmn15 } from "./misc/empty/Empty.stories";
-export const evaluationResults: EvaluationResults = {};
+export const evaluationResultsByNodeId: EvaluationResultsByNodeId = new Map();
export const validationMessages: ValidationMessages = {};
export type StorybookDmnEditorProps = DmnEditorProps & { xml: string };
@@ -105,7 +111,7 @@ export function DmnEditorWrapper(props?:
Partial<StorybookDmnEditorProps>) {
externalContextName={props?.externalContextName ??
args.externalContextName}
externalContextDescription={props?.externalContextDescription ??
args.externalContextDescription}
validationMessages={props?.validationMessages ??
args.validationMessages}
- evaluationResults={props?.evaluationResults ??
args.evaluationResults}
+ evaluationResultsByNodeId={props?.evaluationResultsByNodeId ??
args.evaluationResultsByNodeId}
issueTrackerHref={props?.issueTrackerHref ?? args.issueTrackerHref}
onRequestToJumpToPath={props?.onRequestToJumpToPath ??
args.onRequestToJumpToPath}
onModelDebounceStateChanged={onModelDebounceStateChanged}
diff --git a/packages/dmn-editor/stories/misc/empty/Empty.stories.tsx
b/packages/dmn-editor/stories/misc/empty/Empty.stories.tsx
index ecbac14555d..af3959e35f6 100644
--- a/packages/dmn-editor/stories/misc/empty/Empty.stories.tsx
+++ b/packages/dmn-editor/stories/misc/empty/Empty.stories.tsx
@@ -51,7 +51,7 @@ export const Empty: Story = {
args: {
model: model,
originalVersion: "1.5",
- evaluationResults: {},
+ evaluationResultsByNodeId: new Map(),
externalContextDescription: "",
externalContextName: "Storybook - DMN Editor",
externalModelsByNamespace: {},
diff --git
a/packages/dmn-editor/stories/misc/emptyWithAvailableExternalModels/EmptyWithAvailableExternalModels.stories.tsx
b/packages/dmn-editor/stories/misc/emptyWithAvailableExternalModels/EmptyWithAvailableExternalModels.stories.tsx
index 7bd165e1b8b..18f59021125 100644
---
a/packages/dmn-editor/stories/misc/emptyWithAvailableExternalModels/EmptyWithAvailableExternalModels.stories.tsx
+++
b/packages/dmn-editor/stories/misc/emptyWithAvailableExternalModels/EmptyWithAvailableExternalModels.stories.tsx
@@ -103,7 +103,7 @@ function EmptyStoryWithIncludedModels(args: DmnEditorProps)
{
externalContextName: args.externalContextName,
externalContextDescription: args.externalContextDescription,
validationMessages: args.validationMessages,
- evaluationResults: args.evaluationResults,
+ evaluationResultsByNodeId: args.evaluationResultsByNodeId,
issueTrackerHref: args.issueTrackerHref,
})}
</>
@@ -124,7 +124,7 @@ export const EmptyWithAvailableExternalModels: Story = {
args: {
model: getMarshaller(initialModel, { upgradeTo: "latest" }).parser.parse(),
originalVersion: "1.5",
- evaluationResults: {},
+ evaluationResultsByNodeId: new Map(),
externalContextDescription: "External context description",
externalContextName: "Storybook - DMN Editor",
externalModelsByNamespace: {},
diff --git
a/packages/dmn-editor/stories/misc/evaluationHighlights/EvaluationHighlights.stories.tsx
b/packages/dmn-editor/stories/misc/evaluationHighlights/EvaluationHighlights.stories.tsx
index 55ad44b1718..edc00b616ba 100644
---
a/packages/dmn-editor/stories/misc/evaluationHighlights/EvaluationHighlights.stories.tsx
+++
b/packages/dmn-editor/stories/misc/evaluationHighlights/EvaluationHighlights.stories.tsx
@@ -815,7 +815,7 @@ function EvaluationHighlights(args: DmnEditorProps) {
externalContextName: args.externalContextName,
externalContextDescription: args.externalContextDescription,
validationMessages: args.validationMessages,
- evaluationResults: args.evaluationResults,
+ evaluationResultsByNodeId: args.evaluationResultsByNodeId,
issueTrackerHref: args.issueTrackerHref,
})}
</>
@@ -836,11 +836,23 @@ export const EvaluationHighlightsStory: Story = {
args: {
model: getMarshaller(initialModel, { upgradeTo: "latest" }).parser.parse(),
originalVersion: "1.5",
- evaluationResults: {
- "_F0DC8923-5FC7-4200-8BD1-461D5F3714BE": "success",
- "_D6F4234F-15B3-4F5B-B814-5F6FF29D2907": "failure",
- "_2FE51DB1-3083-4BF7-AA71-0B0065310E72": "skipped",
- },
+ evaluationResultsByNodeId: new Map([
+ [
+ "_F0DC8923-5FC7-4200-8BD1-461D5F3714BE",
+ { evaluationResult: "skipped", evaluationHitsCountByRuleOrRowId: new
Map() },
+ ],
+ [
+ "_D6F4234F-15B3-4F5B-B814-5F6FF29D2907",
+ { evaluationResult: "failed", evaluationHitsCountByRuleOrRowId: new
Map() },
+ ],
+ [
+ "_2FE51DB1-3083-4BF7-AA71-0B0065310E72",
+ {
+ evaluationResult: "succeeded",
+ evaluationHitsCountByRuleOrRowId: new
Map([["_11976EBA-60BC-421B-A270-089A45E9B167", 10]]),
+ },
+ ],
+ ]),
externalContextDescription: "External context description",
externalContextName: "Storybook - DMN Editor",
externalModelsByNamespace: {},
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-skipped.png
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-skipped.png
index f781f707e56..697158353c9 100644
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-skipped.png
and
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-skipped.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-succeeded.png
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-succeeded.png
new file mode 100644
index 00000000000..b2af1471e86
Binary files /dev/null and
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-succeeded.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-success.png
b/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-success.png
deleted file mode 100644
index 9e1c273c2f2..00000000000
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/Google-Chrome/evaluationHighlights/evaluation-highlights-success.png
and /dev/null differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-skipped.png
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-skipped.png
index ed84bb73c34..08da8f3a50b 100644
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-skipped.png
and
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-skipped.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-succeeded.png
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-succeeded.png
new file mode 100644
index 00000000000..a498c4193bc
Binary files /dev/null and
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-succeeded.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-success.png
b/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-success.png
deleted file mode 100644
index 9a073e010fb..00000000000
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/chromium/evaluationHighlights/evaluation-highlights-success.png
and /dev/null differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-skipped.png
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-skipped.png
index 81bbf421259..38927ed6daf 100644
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-skipped.png
and
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-skipped.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-succeeded.png
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-succeeded.png
new file mode 100644
index 00000000000..ef68a7f7355
Binary files /dev/null and
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-succeeded.png
differ
diff --git
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-success.png
b/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-success.png
deleted file mode 100644
index befdf171e85..00000000000
Binary files
a/packages/dmn-editor/tests-e2e/__screenshots__/webkit/evaluationHighlights/evaluation-highlights-success.png
and /dev/null differ
diff --git
a/packages/dmn-editor/tests-e2e/evaluationHighlights/evaluationHighlights.spec.ts
b/packages/dmn-editor/tests-e2e/evaluationHighlights/evaluationHighlights.spec.ts
index dbc7345531c..2d407e40931 100644
---
a/packages/dmn-editor/tests-e2e/evaluationHighlights/evaluationHighlights.spec.ts
+++
b/packages/dmn-editor/tests-e2e/evaluationHighlights/evaluationHighlights.spec.ts
@@ -25,15 +25,15 @@ test.beforeEach(async ({ overlays, editor }) => {
});
test.describe("Evaluation Highlights on Nodes", () => {
- test("should highlight node evaluation result - success", async ({ nodes })
=> {
- await expect(nodes.get({ name: "Front End Ratio"
})).toHaveScreenshot("evaluation-highlights-success.png");
+ test("should highlight node evaluation result - skipped", async ({ nodes })
=> {
+ await expect(nodes.get({ name: "Front End Ratio"
})).toHaveScreenshot("evaluation-highlights-skipped.png");
});
test("should highlight node evaluation result - failure", async ({ nodes })
=> {
await expect(nodes.get({ name: "Back End Ratio"
})).toHaveScreenshot("evaluation-highlights-failure.png");
});
- test("should highlight node evaluation result - skipped", async ({ nodes })
=> {
- await expect(nodes.get({ name: "Credit Score Rating"
})).toHaveScreenshot("evaluation-highlights-skipped.png");
+ test("should highlight node evaluation result - succeeded", async ({ nodes
}) => {
+ await expect(nodes.get({ name: "Credit Score Rating"
})).toHaveScreenshot("evaluation-highlights-succeeded.png");
});
});
diff --git a/packages/extended-services-api/src/dmnResult.ts
b/packages/extended-services-api/src/dmnResult.ts
index 8dc9237812f..f759dab9c7c 100644
--- a/packages/extended-services-api/src/dmnResult.ts
+++ b/packages/extended-services-api/src/dmnResult.ts
@@ -48,6 +48,7 @@ export interface DecisionResult {
result: DmnEvaluationResult;
messages?: DmnEvaluationMessages[];
evaluationStatus: DmnEvaluationStatus;
+ evaluationHitIds: Object;
}
// Result returned from extended-services /jitdmn/dmnresult;
diff --git a/packages/form-dmn/src/FormDmnOutputs.tsx
b/packages/form-dmn/src/FormDmnOutputs.tsx
index 5523a8527ba..c3d99a93dea 100644
--- a/packages/form-dmn/src/FormDmnOutputs.tsx
+++ b/packages/form-dmn/src/FormDmnOutputs.tsx
@@ -112,10 +112,12 @@ export function FormDmnOutputs({ openExecutionTab,
openBoxedExpressionEditor, ..
<CheckCircleIcon />
{props.notificationsPanel ? (
<a onClick={onOpenExecutionTab}
className={"kogito--editor__dmn-form-result__evaluation-link"}>
- {i18n.result.evaluation.success}
+ {i18n.result.evaluation.succeeded}
</a>
) : (
- <p
className={"kogito--editor__dmn-form-result__evaluation-link"}>{i18n.result.evaluation.success}</p>
+ <p
className={"kogito--editor__dmn-form-result__evaluation-link"}>
+ {i18n.result.evaluation.succeeded}
+ </p>
)}
</div>
</>
@@ -155,7 +157,7 @@ export function FormDmnOutputs({ openExecutionTab,
openBoxedExpressionEditor, ..
[
i18n.result.evaluation.failed,
i18n.result.evaluation.skipped,
- i18n.result.evaluation.success,
+ i18n.result.evaluation.succeeded,
onOpenExecutionTab,
props.notificationsPanel,
]
diff --git a/packages/form-dmn/src/i18n/FormDmnI18n.ts
b/packages/form-dmn/src/i18n/FormDmnI18n.ts
index fd7f410372a..9a14a365f0a 100644
--- a/packages/form-dmn/src/i18n/FormDmnI18n.ts
+++ b/packages/form-dmn/src/i18n/FormDmnI18n.ts
@@ -33,7 +33,7 @@ export interface FormDmnI18n extends FormI18n {
};
result: {
evaluation: {
- success: string;
+ succeeded: string;
skipped: string;
failed: string;
};
diff --git a/packages/form-dmn/src/i18n/locales/de.ts
b/packages/form-dmn/src/i18n/locales/de.ts
index 283b89bbf71..fbe3dada83b 100644
--- a/packages/form-dmn/src/i18n/locales/de.ts
+++ b/packages/form-dmn/src/i18n/locales/de.ts
@@ -58,7 +58,7 @@ export const de: TranslatedDictionary<FormDmnI18n> = {
},
result: {
evaluation: {
- success: "Erfolgreich evaluiert",
+ succeeded: "Erfolgreich evaluiert",
skipped: "Evaluierung übersprungen",
failed: "Evaluierung fehlgeschlagen",
},
diff --git a/packages/form-dmn/src/i18n/locales/en.ts
b/packages/form-dmn/src/i18n/locales/en.ts
index d24521ab5fc..b60f38bd366 100644
--- a/packages/form-dmn/src/i18n/locales/en.ts
+++ b/packages/form-dmn/src/i18n/locales/en.ts
@@ -59,7 +59,7 @@ export const en: FormDmnI18n = {
},
result: {
evaluation: {
- success: "Evaluated with success",
+ succeeded: "Evaluation succeeded",
skipped: "Evaluation skipped",
failed: "Evaluation failed",
},
diff --git a/packages/form-dmn/tests/FormDmnOutputs.test.tsx
b/packages/form-dmn/tests/FormDmnOutputs.test.tsx
index 70e07ef885e..81e3adc5b77 100644
--- a/packages/form-dmn/tests/FormDmnOutputs.test.tsx
+++ b/packages/form-dmn/tests/FormDmnOutputs.test.tsx
@@ -45,6 +45,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.FAILED,
+ evaluationHitIds: {},
},
];
@@ -61,6 +62,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.FAILED,
+ evaluationHitIds: {},
},
{
decisionId: "_9BD7BB23-0B23-488F-8DED-F5462CF89E0B",
@@ -68,6 +70,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.SUCCEEDED,
+ evaluationHitIds: {},
},
{
decisionId: "_9BD7BB23-0B23-488F-8DED-F5462CF89E0B",
@@ -75,6 +78,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.SKIPPED,
+ evaluationHitIds: {},
},
];
@@ -93,6 +97,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.FAILED,
+ evaluationHitIds: {},
},
];
@@ -110,6 +115,7 @@ describe("FormDmnOutputs tests", () => {
result: null,
messages: [],
evaluationStatus: DmnEvaluationStatus.FAILED,
+ evaluationHitIds: {},
},
];
diff --git a/packages/online-editor/src/dmnRunner/DmnRunnerContextProvider.tsx
b/packages/online-editor/src/dmnRunner/DmnRunnerContextProvider.tsx
index 7cb82c0e04e..fdda208087c 100644
--- a/packages/online-editor/src/dmnRunner/DmnRunnerContextProvider.tsx
+++ b/packages/online-editor/src/dmnRunner/DmnRunnerContextProvider.tsx
@@ -35,7 +35,12 @@ import { ExtendedServicesStatus } from
"../extendedServices/ExtendedServicesStat
import { usePrevious } from "@kie-tools-core/react-hooks/dist/usePrevious";
import { useExtendedServices } from
"../extendedServices/ExtendedServicesContext";
import { InputRow } from "@kie-tools/form-dmn";
-import { DecisionResult, DmnEvaluationMessages, ExtendedServicesModelPayload }
from "@kie-tools/extended-services-api";
+import {
+ DecisionResult,
+ DmnEvaluationMessages,
+ ExtendedServicesDmnResult,
+ ExtendedServicesModelPayload,
+} from "@kie-tools/extended-services-api";
import { DmnRunnerAjv } from "@kie-tools/dmn-runner/dist/ajv";
import { useDmnRunnerPersistence } from
"../dmnRunnerPersistence/DmnRunnerPersistenceHook";
import { DmnLanguageService } from "@kie-tools/dmn-language-service";
@@ -73,6 +78,9 @@ import {
import { extractDifferencesFromArray } from
"@kie-tools/dmn-runner/dist/results";
import { openapiSchemaToJsonSchema } from
"@openapi-contrib/openapi-schema-to-json-schema";
import type { JSONSchema4 } from "json-schema";
+import { MessageBusClientApi } from "@kie-tools-core/envelope-bus/dist/api";
+import { NewDmnEditorEnvelopeApi } from
"@kie-tools/dmn-editor-envelope/dist/NewDmnEditorEnvelopeApi";
+import { NewDmnEditorTypes } from
"@kie-tools/dmn-editor-envelope/dist/NewDmnEditorTypes";
interface Props {
isEditorReady?: boolean;
@@ -119,6 +127,92 @@ function dmnRunnerResultsReducer(dmnRunnerResults:
DmnRunnerResults, action: Dmn
}
}
+/**
+ * This transformation is needed for these reasons:
+ * ### -1- ###
+ * DMN Runner backend return upper case constants: "SUCCEEDED", "FAILED",
"SKIPPED"
+ * DMN Editor code base uses lower case constants: "succeeded", "failed",
"skipped"
+ *
+ * ### -2- ###
+ * DMN Runner backend return evaluationHitIds as Object:
+ * {
+ * _F0DC8923-5FC7-4200-8BD1-461D5F3715CF: 1,
+ * _F0DC8923-5FC7-4200-8BD1-461D5F3713AD: 2
+ * }
+ * DMN Editor code base uses evaluationHitIds as Map<string, number>
+ * [
+ * {
+ * key: "_F0DC8923-5FC7-4200-8BD1-461D5F3715CF,
+ * value: 1
+ * },
+ * {
+ * key: "_F0DC8923-5FC7-4200-8BD1-461D5F3713AD",
+ * value: 2
+ * }
+ * ]
+ *
+ * ### -3- ###
+ * DMN Runner backend return data spilt into junks corresponding to table row
or collection item
+ * DMN Editor want to show aggregated data for everything together
+ *
+ * @param result - DMN Runner backend data
+ * @param evaluationResultsByNodeId - transformed data for DMN Editor
+ */
+function transformExtendedServicesDmnResult(
+ result: ExtendedServicesDmnResult,
+ evaluationResultsByNodeId: NewDmnEditorTypes.EvaluationResultsByNodeId
+) {
+ result.decisionResults?.forEach((dr) => {
+ const evaluationHitsCountByRuleOrRowId = new Map<string, number>();
+ // ### -2- ###
+ for (const [key, value] of Object.entries(dr.evaluationHitIds)) {
+ evaluationHitsCountByRuleOrRowId.set(`${key}`, value as number);
+ }
+ // We want to merge evaluation results that belongs to the same Decision
+ // So we need to check if the Decision wasn't already partially processed
+ if (!evaluationResultsByNodeId.has(dr.decisionId)) {
+ evaluationResultsByNodeId.set(dr.decisionId, {
+ // ### -1- ###
+ evaluationResult: dr.evaluationStatus.toLowerCase() as
NewDmnEditorTypes.EvaluationResult,
+ evaluationHitsCountByRuleOrRowId: evaluationHitsCountByRuleOrRowId,
+ });
+ } else {
+ const existingEvaluationHitsCount = evaluationResultsByNodeId.get(
+ dr.decisionId
+ )?.evaluationHitsCountByRuleOrRowId;
+ evaluationHitsCountByRuleOrRowId.forEach((value, key) => {
+ // ### -3- ###
+ if (existingEvaluationHitsCount?.has(key)) {
+ existingEvaluationHitsCount.set(key,
(existingEvaluationHitsCount?.get(key) ?? 0) + value);
+ } else {
+ existingEvaluationHitsCount?.set(key, value);
+ }
+ });
+ evaluationResultsByNodeId.set(dr.decisionId, {
+ // For a collection input or DMN Runner table mode one Decision may
have multiple different evaluation results
+ // We keep the worst evaluation result.
+ evaluationResult: theWorstEvaluationResult(
+ evaluationResultsByNodeId.get(dr.decisionId)?.evaluationResult,
+ dr.evaluationStatus.toLowerCase() as
NewDmnEditorTypes.EvaluationResult
+ ),
+ evaluationHitsCountByRuleOrRowId: existingEvaluationHitsCount ?? new
Map(),
+ });
+ }
+ });
+
+ return evaluationResultsByNodeId;
+}
+
+function theWorstEvaluationResult(a?: NewDmnEditorTypes.EvaluationResult, b?:
NewDmnEditorTypes.EvaluationResult) {
+ if (a === "failed" || b === "failed") {
+ return "failed";
+ }
+ if (a === "skipped" || b === "skipped") {
+ return "skipped";
+ }
+ return "succeeded";
+}
+
export function DmnRunnerContextProvider(props: PropsWithChildren<Props>) {
const { i18n } = useOnlineI18n();
// Calling forceDmnRunnerReRender will cause a update in the dmnRunnerKey
@@ -163,6 +257,8 @@ export function DmnRunnerContextProvider(props:
PropsWithChildren<Props>) {
const status = useMemo(() => (isExpanded ? DmnRunnerStatus.AVAILABLE :
DmnRunnerStatus.UNAVAILABLE), [isExpanded]);
const dmnRunnerAjv = useMemo(() => new DmnRunnerAjv().getAjv(), []);
+ const { envelopeServer } = useEditorDockContext();
+
useLayoutEffect(() => {
if (props.isEditorReady) {
setCanBeVisualized(true);
@@ -264,6 +360,7 @@ export function DmnRunnerContextProvider(props:
PropsWithChildren<Props>) {
}
const runnerResults: Array<DecisionResult[] | undefined> = [];
+ const evaluationResultsByNodeId:
NewDmnEditorTypes.EvaluationResultsByNodeId = new Map();
for (const result of results) {
if (Object.hasOwnProperty.call(result, "details") &&
Object.hasOwnProperty.call(result, "stack")) {
setExtendedServicesError(true);
@@ -271,9 +368,13 @@ export function DmnRunnerContextProvider(props:
PropsWithChildren<Props>) {
}
if (result) {
runnerResults.push(result.decisionResults);
+ transformExtendedServicesDmnResult(result,
evaluationResultsByNodeId);
}
}
setDmnRunnerResults({ type: DmnRunnerResultsActionType.DEFAULT,
newResults: runnerResults });
+
+ const newDmnEditorEnvelopeApi = envelopeServer?.envelopeApi as
MessageBusClientApi<NewDmnEditorEnvelopeApi>;
+
newDmnEditorEnvelopeApi.notifications.newDmnEditor_showDmnEvaluationResults.send(evaluationResultsByNodeId);
})
.catch((err) => {
console.log(err);
@@ -281,6 +382,7 @@ export function DmnRunnerContextProvider(props:
PropsWithChildren<Props>) {
});
},
[
+ envelopeServer,
props.workspaceFile.extension,
extendedServices.status,
extendedServices.client,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]