jomarko commented on code in PR #3252:
URL:
https://github.com/apache/incubator-kie-tools/pull/3252#discussion_r2606776553
##########
packages/serverless-workflow-editor/package.json:
##########
@@ -0,0 +1,117 @@
+{
+ "name": "@kie-tools/serverless-workflow-editor",
+ "version": "0.0.0",
+ "description": "",
+ "license": "Apache-2.0",
+ "keywords": [],
+ "homepage": "https://github.com/apache/incubator-kie-tools",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/apache/incubator-kie-tools.git"
+ },
+ "bugs": {
+ "url": "https://github.com/apache/incubator-kie-tools/issues"
+ },
+ "files": [
+ "dist",
+ "src"
+ ],
+ "scripts": {
+ "build:dev": "rimraf dist && pnpm copy:css && tsc -p tsconfig.json",
+ "build:prod": "rimraf dist && pnpm copy:css && pnpm lint && tsc -p
tsconfig.json && pnpm test-e2e && pnpm test",
+ "build:storybook": "rimraf dist-storybook && NODE_ENV=development
storybook build -o dist-storybook",
+ "copy:css": "copyfiles -u 1 \"src/**/*.{sass,scss,css}\" dist/",
+ "lint": "run-script-if --bool \"$(build-env linters.run)\" --then
\"kie-tools--eslint ./src\"",
+ "start": "run-script-os",
+ "start:linux:darwin": "cross-env STORYBOOK_PORT=$(build-env
swfEditor.storybook.port) pnpm kie-tools--storybook --storybookArgs=\"dev
--no-open\"",
+ "start:win32": "pnpm powershell \"cross-env STORYBOOK_PORT=$(build-env
swfEditor.storybook.port) pnpm kie-tools--storybook --storybookArgs='dev
--no-open'",
+ "test": "run-script-if --ignore-errors \"$(build-env
tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"jest
--silent --verbose --passWithNoTests\"",
+ "test-e2e": "run-script-if --ignore-errors \"$(build-env
endToEndTests.ignoreFailures)\" --bool \"$(build-env endToEndTests.run)\"
--then \"pnpm test-e2e:condition\"",
+ "test-e2e:condition": "run-script-if --bool \"$(build-env
endToEndTests.containerized)\" --then \"pnpm rimraf ./dist-tests-e2e\" \"pnpm
test-e2e:container:start\" --else \"pnpm rimraf ./dist-tests-e2e\" \"pnpm
test-e2e:run\"",
+ "test-e2e:container:bash": "docker exec -it
kie-tools-playwright-containerization-serverless-workflow-editor /bin/bash -c
\"cd incubator-kie-tools/packages/serverless-workflow-editor && exec
/bin/bash\"",
+ "test-e2e:container:down": "docker compose -f
./tests-e2e/__containerization__/playwright-docker-compose.yml down",
+ "test-e2e:container:run": "docker exec -i
kie-tools-playwright-containerization-serverless-workflow-editor /bin/bash -c
\"cd incubator-kie-tools/packages/serverless-workflow-editor && pnpm
test-e2e:run\"",
+ "test-e2e:container:shell": "start-server-and-test 'pnpm start'
http://localhost:$(build-env swfEditor.storybook.port)/iframe.html 'pnpm
test-e2e:container:up && pnpm test-e2e:container:bash'",
+ "test-e2e:container:start": "start-server-and-test 'pnpm start'
http://localhost:$(build-env swfEditor.storybook.port)/iframe.html 'pnpm
test-e2e:container:up && pnpm test-e2e:container:run'",
+ "test-e2e:container:up": "cross-env STREAM_NAME=$(build-env
root.streamName) KIE_TOOLS_PLAYWRIGHT_CONTAINER__PORT=$(build-env
swfEditor.storybook.port) run-script-if --bool \"${CI}\" --then \"docker
compose -f ./tests-e2e/__containerization__/playwright-docker-compose.yml -f
./tests-e2e/__containerization__/playwright-docker-compose.ci.yml up -d\"
--else \"docker compose -f
./tests-e2e/__containerization__/playwright-docker-compose.yml up -d\"",
+ "test-e2e:open": "pnpm exec playwright show-report dist-tests-e2e/reports",
+ "test-e2e:run": "pnpm exec playwright test"
+ },
+ "dependencies": {
+ "@kie-tools-core/i18n": "workspace:*",
+ "@kie-tools-core/operating-system": "workspace:*",
+ "@kie-tools-core/patternfly-base": "workspace:*",
+ "@kie-tools-core/react-hooks": "workspace:*",
+ "@kie-tools-core/switch-expression-ts": "workspace:*",
+ "@kie-tools/i18n-common-dictionary": "workspace:*",
+ "@kie-tools/xml-parser-ts": "workspace:*",
+ "@patternfly/react-core": "^5.4.1",
+ "@patternfly/react-icons": "^5.4.1",
+ "@patternfly/react-styles": "^5.4.0",
+ "@serverlessworkflow/sdk-typescript": "^0.8.4",
+ "@visx/text": "^3.3.0",
+ "d3-drag": "^3.0.0",
+ "d3-selection": "^3.0.0",
+ "elkjs": "^0.9.1",
Review Comment:
Could we please double check this report?
⚠️ Not Apache‑compatible: elkjs
elkjs is licensed under the Eclipse Public License 2.0 (EPL-2.0).
[github.com], [github.com]
EPL‑2.0 is not compatible with Apache‑2.0 for redistribution or combination
purposes, because it imposes distinct obligations (especially regarding patent
grants and distribution rules).
##########
packages/serverless-workflow-editor/stories/useCases/workflowSamples/WorkflowCompensationExample.mdx:
##########
Review Comment:
The used yellow color is difficult to see on the white background
<img width="789" height="505" alt="image"
src="https://github.com/user-attachments/assets/726888fd-243b-4758-924c-d18d67d02787"
/>
##########
packages/serverless-workflow-editor/tests-e2e/__fixtures__/jsonModel/swf.ts:
##########
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Page } from "@playwright/test";
+import { SwfElement } from "./swfElement";
+import { Specification } from "@serverlessworkflow/sdk-typescript";
+
+export class Swf {
+ constructor(
+ public page: Page,
+ public swfElement: SwfElement
+ ) {}
+
+ private async getSwf(): Promise<object | undefined> {
Review Comment:
reported as unused
##########
packages/serverless-workflow-editor/src/diagram/nodes/OutgoingStuffNodePanel.tsx:
##########
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import * as React from "react";
+import * as RF from "reactflow";
+import { EdgeType, NodeType } from "../connections/graphStructure";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import {
+ TransitionPath,
+ ErrorTransitionPath,
+ EventConditionTransitionPath,
+ DefaultConditionTransitionPath,
+ DataConditionTransitionPath,
+ CompensationTransitionPath,
+} from "../edges/SwfEdges";
+import {
+ EventstateSvg,
+ OperationstateSvg,
+ SwitchstateSvg,
+ SleepstateSvg,
+ ParallelstateSvg,
+ InjectstateSvg,
+ ForeachstateSvg,
+ CallbackstateSvg,
+} from "./SwfNodeSvgs";
+import { NODE_TYPES } from "./SwfNodeTypes";
+import { EDGE_TYPES } from "../edges/SwfEdgeTypes";
+import { useSettings } from "../../settings/SwfEditorSettingsContext";
+
+const handleButtonSize = 34; // That's the size of the button. This is a
"magic number", as it was obtained from the rendered page.
+const svgViewboxPadding = Math.sqrt(Math.pow(handleButtonSize, 2) / 2) -
handleButtonSize / 2; // This lets us create a square that will perfectly fit
inside the button circle.
+
+const edgeSvgViewboxSize = 25;
+
+const nodeSvgProps = { width: 100, height: 70, x: 0, y: 15, strokeWidth: 8 };
+const nodeSvgViewboxSize = nodeSvgProps.width;
+
+export const handleStyle: React.CSSProperties = {
+ display: "flex",
+ position: "unset",
+ transform: "unset",
+};
+
+export function OutgoingStuffNodePanel(props: {
+ isVisible: boolean;
+ nodeTypes: NodeType[];
+ edgeTypes: EdgeType[];
+ nodeHref: string;
+}) {
+ const settings = useSettings();
+ const style: React.CSSProperties = React.useMemo(
+ () => ({
+ visibility: !settings.isReadOnly && props.isVisible ? undefined :
"hidden",
+ }),
+ [props.isVisible, settings.isReadOnly]
+ );
+
+ const getEdgeActionTitle = React.useCallback((edgeType: string): string => {
Review Comment:
we should introduce `i18n` into serverless-workflow-editor
see https://github.com/apache/incubator-kie-tools/pull/3351 and similar
##########
packages/serverless-workflow-editor/src/SwfEditor.css:
##########
@@ -0,0 +1,563 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* (begin) global */
+.kie-swf-editor--root {
+ height: 100%;
+}
+
+.kie-tools--swf-editor--diagram-container {
+ height: 100%;
+ position: relative;
+}
+
+.kie-swf-editor--bee-container {
+ position: relative;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ user-select: none;
+ padding-left: 16px;
+}
+/* (end) global */
+
+/* (begin) diagram empty state */
+.kie-swf-editor--diagram-empty-state {
+ border: 1px solid lightgray;
+ backdrop-filter: blur(4px);
+ background: rgb(255, 255, 255, 60%);
+ border-radius: 16px;
+ padding: 16px;
+ pointer-events: all;
+ box-shadow: 0 0 60px 20px #e1e1e1;
+}
+/* (end) diagram empty state */
+
+/* (begin) nodes */
+.kie-swf-editor--node {
+ height: 100%;
+ width: 100%;
+ padding: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ word-break: break-word;
+ overflow: hidden;
+ -webkit-line-clamp: 2; /* number of lines to show */
+ line-clamp: 2;
+ -webkit-box-orient: vertical;
+ text-align: center;
+ position: absolute;
+ z-index: 10;
+ top: 0;
+ left: 0;
+ overflow: visible;
+ z-index: 10000; /* Makes the data type node panel appear correctly, on top
of the node */
+}
+.kie-swf-editor--node:focus {
+ outline: none;
+}
+.kie-swf-editor--node.dimmed,
+.kie-swf-editor--node-shape.dimmed,
+.kie-swf-editor--generic-node.dimmed {
+ opacity: 0.3;
+ pointer-events: none;
+}
+.kie-swf-editor--node-shape {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+ z-index: 1;
+}
+.kie-swf-editor--generic-node {
+ outline: none;
+ width: 100%;
+ height: 100%;
+}
+
+.kie-swf-editor--unknown-node {
+ color: red;
+}
+/* (end) nodes */
+
+/* (begin) palette */
+.kie-swf-editor--palette {
+ width: 42px;
+ background: #fff;
+ border-radius: 40px;
+ border: 1px solid black;
+}
+.kie-swf-editor--palette:hover {
+ box-shadow: 4px 4px 2px 0px rgb(127 127 127);
+}
+
+.kie-swf-editor--palette.pulse {
+ animation: pulse 3s infinite;
+}
+
+@keyframes pulse {
+ 0% {
+ box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.3);
+ }
+
+ 70% {
+ box-shadow: 0 0 20px 20px rgba(0, 0, 0, 0);
+ }
+
+ 100% {
+ box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0);
+ }
+}
+
+.kie-swf-editor--palette-button {
+ margin: 0;
+ margin-bottom: 8px;
+ padding: 0;
+ width: 40px;
+ height: 40px;
+ max-width: 40px;
+ border-radius: 40px;
+ border: 0;
+ background: white;
+}
+.kie-swf-editor--palette-button:hover {
+ filter: brightness(95%);
+ cursor: grab;
+}
+.kie-swf-editor--palette-button:active {
+ filter: brightness(90%);
+ cursor: grabbing;
+}
+/* (end) palette */
+
+/* (begin) version popover */
+.kie-swf-editor--version-popover .pf-v5-c-popover__body {
+ padding: 0;
+}
+/* (end) version popover */
+
+/* (begin) autolayout panel toggle */
+.kie-swf-editor--autolayout-panel-toggle {
+ width: 42px;
+ background: #fff;
+ border-radius: 40px;
+ border: 1px solid black;
+}
+.kie-swf-editor--autolayout-panel-toggle:not(:last-child) {
+ margin-right: 16px;
+}
+
+.kie-swf-editor--autolayout-panel-toggle:hover {
+ box-shadow: -4px 4px 2px 0px rgb(127 127 127);
+}
+.kie-swf-editor--autolayout-panel-toggle-button {
+ margin: 0;
+ width: 40px;
+ height: 40px;
+ max-width: 40px;
+ border-radius: 40px;
+ border: 0;
+ background: white;
+}
+.kie-swf-editor--autolayout-panel-toggle-button:hover {
+ filter: brightness(95%);
+}
+.kie-swf-editor--autolayout-panel-toggle-button:active {
+ filter: brightness(90%);
+}
+/* (end) autolayout panel toggle */
+
+/* (begin) evaluation-highlights panel toggle */
+.kie-swf-editor--evaluation-highlights-panel-toggle {
+ min-width: 190px;
+}
+/* (end) evaluation-highlights panel toggle */
Review Comment:
if I am not wrong, evaluation highlights a feature specific only for DMN, if
that is true please remove it
if I understand correctly the PR discussion, this PR should not contain any
code, that has currently no usage, is that correct?
##########
packages/serverless-workflow-editor/src/diagram/Diagram.tsx:
##########
@@ -0,0 +1,793 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import * as RF from "reactflow";
+import { useOnViewportChange, Viewport } from "reactflow";
+import * as React from "react";
+import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState }
from "react";
+import { Button, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
+import {
+ EmptyState,
+ EmptyStateIcon,
+ EmptyStateBody,
+ EmptyStateHeader,
+} from "@patternfly/react-core/dist/js/components/EmptyState";
+import { Label } from "@patternfly/react-core/dist/js/components/Label";
+import { Popover } from "@patternfly/react-core/dist/js/components/Popover";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
+import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
+import { MousePointerIcon } from
"@patternfly/react-icons/dist/js/icons/mouse-pointer-icon";
+import { TimesIcon } from "@patternfly/react-icons/dist/js/icons/times-icon";
+import { VirtualMachineIcon } from
"@patternfly/react-icons/dist/js/icons/virtual-machine-icon";
+import { useSwfEditor } from "../SwfEditorContext";
+import { AutolayoutButton } from "../autolayout/AutolayoutButton";
+import { addEdge } from "../mutations/addEdge";
+import { deleteEdge } from "../mutations/deleteEdge";
+import { OverlaysPanel } from "../overlaysPanel/OverlaysPanel";
+import { SnapGrid, State } from "../store/Store";
+import { useSwfEditorStore, useSwfEditorStoreApi } from
"../store/StoreContext";
+import { DiagramContainerContextProvider } from "./DiagramContainerContext";
+import { ConnectionLine } from "./connections/ConnectionLine";
+import { PositionalNodeHandleId } from "./connections/PositionalNodeHandles";
+import { containment, EdgeType, getDefaultEdgeTypeBetween, NodeType } from
"./connections/graphStructure";
+import { checkIsValidConnection } from "./connections/isValidConnection";
+import { EdgeMarkers } from "./edges/EdgeMarkers";
+import { EDGE_TYPES } from "./edges/SwfEdgeTypes";
+import {
+ TransitionEdge,
+ SwfDiagramEdgeData,
+ ErrorTransitionEdge,
+ EventConditionTransitionEdge,
+ DefaultConditionTransitionEdge,
+ CompensationTransitionEdge,
+ DataConditionTransitionEdge,
+} from "./edges/SwfEdges";
+import { buildHierarchy } from "./graph/graph";
+import { getContainmentRelationship, getSwfBoundsCenterPoint,
getHandlePosition } from "./maths/SwfMaths";
+import { DEFAULT_NODE_SIZES, MIN_NODE_SIZES } from "./nodes/SwfDefaultSizes";
+import { NODE_TYPES } from "./nodes/SwfNodeTypes";
+import {
+ OperationState,
+ SwitchState,
+ SleepState,
+ SwfDiagramNodeData,
+ ParallelState,
+ InjectState,
+ ForEachState,
+ CallbackState,
+ EventState,
+ UnknownNode,
+} from "./nodes/SwfNodes";
+import { DiagramCommands } from "./DiagramCommands";
+import { getAutoLayoutedInfo } from "../autolayout/autoLayoutInfo";
+import { useSettings } from "../settings/SwfEditorSettingsContext";
+import { Flex } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { applyAutoLayoutToSwf } from "../mutations/applyAutoLayoutToSwf";
+
+const isFirefox = typeof (window as any).InstallTrigger !== "undefined"; //
See
https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browsers
+
+const PAN_ON_DRAG = [1, 2];
+
+const FIT_VIEW_OPTIONS: RF.FitViewOptions = { maxZoom: 1, minZoom: 0.1,
duration: 400 };
+
+export const DEFAULT_VIEWPORT = { x: 100, y: 100, zoom: 1 };
+
+const DELETE_NODE_KEY_CODES = ["Backspace", "Delete"];
+
+const AREA_ABOVE_OVERLAYS_PANEL = 120;
+
+const nodeTypes: Record<NodeType, any> = {
+ [NODE_TYPES.callbackState]: CallbackState,
+ [NODE_TYPES.eventState]: EventState,
+ [NODE_TYPES.foreachState]: ForEachState,
+ [NODE_TYPES.injectState]: InjectState,
+ [NODE_TYPES.operationState]: OperationState,
+ [NODE_TYPES.parallelState]: ParallelState,
+ [NODE_TYPES.sleepState]: SleepState,
+ [NODE_TYPES.switchState]: SwitchState,
+ [NODE_TYPES.unknown]: UnknownNode,
+};
+
+const edgeTypes: Record<EdgeType, any> = {
+ [EDGE_TYPES.compensationTransition]: CompensationTransitionEdge,
+ [EDGE_TYPES.dataConditionTransition]: DataConditionTransitionEdge,
+ [EDGE_TYPES.defaultConditionTransition]: DefaultConditionTransitionEdge,
+ [EDGE_TYPES.errorTransition]: ErrorTransitionEdge,
+ [EDGE_TYPES.eventConditionTransition]: EventConditionTransitionEdge,
+ [EDGE_TYPES.transition]: TransitionEdge,
+};
+
+const MIME_TYPE_FOR_SWF_EDITOR_NODE = "kie-swf-editor--node";
+
+export type DiagramRef = {
+ getReactFlowInstance: () => RF.ReactFlowInstance | undefined;
+};
+
+export const Diagram = React.forwardRef<DiagramRef, { container:
React.RefObject<HTMLElement> }>(
+ ({ container }, ref) => {
+ // Contexts
+
+ const swfEditorStoreApi = useSwfEditorStoreApi();
+ const snapGrid = useSwfEditorStore((s) => s.diagram.snapGrid);
+ const thisSwf = useSwfEditorStore((s) => s.swf);
+ const settings = useSettings();
+ const { swfModelBeforeEditingRef } = useSwfEditor();
+
+ // State
+
+ const [reactFlowInstance, setReactFlowInstance] = useState<
+ RF.ReactFlowInstance<SwfDiagramNodeData, SwfDiagramEdgeData> | undefined
+ >(undefined);
+
+ const viewport = useSwfEditorStore((s) => s.diagram.viewport);
+
+ // Refs
+
+ React.useImperativeHandle(
+ ref,
+ () => ({
+ getReactFlowInstance: () => {
+ return reactFlowInstance;
+ },
+ }),
+ [reactFlowInstance]
+ );
+
+ const nodeIdBeingDraggedRef = useRef<string | null>(null);
+
+ // Memos
+
+ const rfSnapGrid = useMemo<[number, number]>(
+ () => (snapGrid.isEnabled ? [snapGrid.x, snapGrid.y] : [1, 1]),
+ [snapGrid.isEnabled, snapGrid.x, snapGrid.y]
+ );
+
+ // Callbacks
+
+ const getFirstNodeFittingBounds = useCallback(
+ (
+ nodeIdToIgnore: string,
+ bounds: RF.Rect,
+ minSizes: (args: { snapGrid: SnapGrid }) => RF.Dimensions,
+ snapGrid: SnapGrid
+ ) =>
+ reactFlowInstance
+ ?.getNodes()
+ .reverse() // Respect the nodes z-index.
+ .find(
+ (node) =>
+ node.id !== nodeIdToIgnore && // don't ever use the node being
dragged
+ getContainmentRelationship({
+ bounds: bounds!,
+ container: { ...DEFAULT_NODE_SIZES[node.type as NodeType]({
snapGrid: snapGrid }), ...{ x: 0, y: 0 } },
+ snapGrid,
+ containerMinSizes: DEFAULT_NODE_SIZES[node.type as NodeType],
+ boundsMinSizes: minSizes,
+ }).isInside
+ ),
+ [reactFlowInstance]
+ );
+
+ const ongoingConnection = useSwfEditorStore((s) =>
s.diagram.ongoingConnection);
+ useEffect(() => {
+ const edgeUpdaterSource = document.querySelectorAll(
+ ".react-flow__edgeupdater-source, .react-flow__edgeupdater-target"
+ );
+ if (ongoingConnection) {
+ edgeUpdaterSource.forEach((e) => e.classList.add("hidden"));
+ } else {
+ edgeUpdaterSource.forEach((e) => e.classList.remove("hidden"));
+ }
+ }, [ongoingConnection]);
Review Comment:
just wanted to ask, if there was some discussion about common editor parts
and potentially extract them into a separate module? just asking, to have
better picture about the future, not asking any change in this PR but I see the
same code in DMN Editor
##########
packages/serverless-workflow-editor/tests-e2e/__fixtures__/stories.ts:
##########
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Page } from "@playwright/test";
+
+export class Stories {
+ constructor(
+ private readonly page: Page,
+ private readonly baseURL?: string
+ ) {}
+
+ private getIframeURL(iframeId: string) {
Review Comment:
reported as unused
##########
packages/serverless-workflow-editor/src/clipboard/Clipboard.ts:
##########
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Unpacked } from "../tsExt/tsExt";
+import * as RF from "reactflow";
+import { State } from "../store/Store";
+import { NodeNature, nodeNatures } from "../mutations/NodeNature";
+import { SwfDiagramNodeData } from "../diagram/nodes/SwfNodes";
+import { NodeType } from "../diagram/connections/graphStructure";
+import { Specification } from "@serverlessworkflow/sdk-typescript";
+
+export const SWF_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE =
"application/json+kie-swf-editor--diagram" as const;
+
+export type SwfEditorDiagramClipboard = {
+ mimeType: typeof SWF_EDITOR_DIAGRAM_CLIPBOARD_MIME_TYPE;
+ swfElements: NonNullable<Unpacked<Specification.States>>[];
+};
+
+export function buildClipboardFromDiagram(rfState: RF.ReactFlowState,
swfEditorState: State) {
+ const copiedNodesById = new Map<string, RF.Node<SwfDiagramNodeData>>();
+
+ const selectedNodesById = rfState
+ .getNodes()
+ .reduce((acc, n) => (n.selected ? acc.set(n.id, n) : acc), new Map<string,
RF.Node<SwfDiagramNodeData>>());
+
+ const clipboard =
[...selectedNodesById.values()].reduce<SwfEditorDiagramClipboard>(
Review Comment:
is this warning/message related just to my machine?
<img width="1126" height="178" alt="image"
src="https://github.com/user-attachments/assets/86c99a35-289b-4c73-a0bc-10c2ae03d660"
/>
##########
packages/serverless-workflow-editor/tests-e2e/readOnly/readOnlyDiagram.spec.ts:
##########
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { expect, test } from "../__fixtures__/base";
+
+test.beforeEach(async ({ editor, nodes }) => {
+ await editor.openApplicantWorkflow();
+ await expect(nodes.get({ name: "HandleNewApplicant" })).toBeVisible();
+ await editor.setIsReadOnly(true);
+});
+
+test.describe("Read Only mode - Diagram", () => {
+ test("should not be able to drag node", async ({ page, nodes }) => {
+ await nodes.move({ name: "HandleNewApplicant", targetPosition: { x: 0, y:
0 } });
+ await expect(page).toHaveScreenshot("readOnly-node-not-moved.png");
+ });
Review Comment:
maybe it would be add also a test, that `dblclick` has no effect
##########
packages/serverless-workflow-editor/stories/misc/empty/Empty.stories.tsx:
##########
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import type { Meta, StoryObj } from "@storybook/react";
+
+import { SwfEditorWrapper, StorybookSwfEditorProps } from
"../../swfEditorStoriesWrapper";
+import { SwfEditor, SwfEditorProps } from "../../../src/SwfEditor";
+import { Specification, WorkflowValidator } from
"@serverlessworkflow/sdk-typescript";
Review Comment:
some imports are unused
##########
packages/serverless-workflow-editor/src/diagram/Diagram.tsx:
##########
@@ -0,0 +1,793 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import * as RF from "reactflow";
+import { useOnViewportChange, Viewport } from "reactflow";
+import * as React from "react";
+import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState }
from "react";
+import { Button, ButtonVariant } from
"@patternfly/react-core/dist/js/components/Button";
+import {
+ EmptyState,
+ EmptyStateIcon,
+ EmptyStateBody,
+ EmptyStateHeader,
+} from "@patternfly/react-core/dist/js/components/EmptyState";
+import { Label } from "@patternfly/react-core/dist/js/components/Label";
+import { Popover } from "@patternfly/react-core/dist/js/components/Popover";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
+import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
+import { MousePointerIcon } from
"@patternfly/react-icons/dist/js/icons/mouse-pointer-icon";
+import { TimesIcon } from "@patternfly/react-icons/dist/js/icons/times-icon";
+import { VirtualMachineIcon } from
"@patternfly/react-icons/dist/js/icons/virtual-machine-icon";
+import { useSwfEditor } from "../SwfEditorContext";
+import { AutolayoutButton } from "../autolayout/AutolayoutButton";
+import { addEdge } from "../mutations/addEdge";
+import { deleteEdge } from "../mutations/deleteEdge";
+import { OverlaysPanel } from "../overlaysPanel/OverlaysPanel";
+import { SnapGrid, State } from "../store/Store";
+import { useSwfEditorStore, useSwfEditorStoreApi } from
"../store/StoreContext";
+import { DiagramContainerContextProvider } from "./DiagramContainerContext";
+import { ConnectionLine } from "./connections/ConnectionLine";
+import { PositionalNodeHandleId } from "./connections/PositionalNodeHandles";
+import { containment, EdgeType, getDefaultEdgeTypeBetween, NodeType } from
"./connections/graphStructure";
+import { checkIsValidConnection } from "./connections/isValidConnection";
+import { EdgeMarkers } from "./edges/EdgeMarkers";
+import { EDGE_TYPES } from "./edges/SwfEdgeTypes";
+import {
+ TransitionEdge,
+ SwfDiagramEdgeData,
+ ErrorTransitionEdge,
+ EventConditionTransitionEdge,
+ DefaultConditionTransitionEdge,
+ CompensationTransitionEdge,
+ DataConditionTransitionEdge,
+} from "./edges/SwfEdges";
+import { buildHierarchy } from "./graph/graph";
+import { getContainmentRelationship, getSwfBoundsCenterPoint,
getHandlePosition } from "./maths/SwfMaths";
+import { DEFAULT_NODE_SIZES, MIN_NODE_SIZES } from "./nodes/SwfDefaultSizes";
+import { NODE_TYPES } from "./nodes/SwfNodeTypes";
+import {
+ OperationState,
+ SwitchState,
+ SleepState,
+ SwfDiagramNodeData,
+ ParallelState,
+ InjectState,
+ ForEachState,
+ CallbackState,
+ EventState,
+ UnknownNode,
+} from "./nodes/SwfNodes";
+import { DiagramCommands } from "./DiagramCommands";
+import { getAutoLayoutedInfo } from "../autolayout/autoLayoutInfo";
+import { useSettings } from "../settings/SwfEditorSettingsContext";
+import { Flex } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { applyAutoLayoutToSwf } from "../mutations/applyAutoLayoutToSwf";
+
+const isFirefox = typeof (window as any).InstallTrigger !== "undefined"; //
See
https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browsers
+
+const PAN_ON_DRAG = [1, 2];
+
+const FIT_VIEW_OPTIONS: RF.FitViewOptions = { maxZoom: 1, minZoom: 0.1,
duration: 400 };
+
+export const DEFAULT_VIEWPORT = { x: 100, y: 100, zoom: 1 };
+
+const DELETE_NODE_KEY_CODES = ["Backspace", "Delete"];
+
+const AREA_ABOVE_OVERLAYS_PANEL = 120;
+
+const nodeTypes: Record<NodeType, any> = {
+ [NODE_TYPES.callbackState]: CallbackState,
+ [NODE_TYPES.eventState]: EventState,
+ [NODE_TYPES.foreachState]: ForEachState,
+ [NODE_TYPES.injectState]: InjectState,
+ [NODE_TYPES.operationState]: OperationState,
+ [NODE_TYPES.parallelState]: ParallelState,
+ [NODE_TYPES.sleepState]: SleepState,
+ [NODE_TYPES.switchState]: SwitchState,
+ [NODE_TYPES.unknown]: UnknownNode,
+};
+
+const edgeTypes: Record<EdgeType, any> = {
+ [EDGE_TYPES.compensationTransition]: CompensationTransitionEdge,
+ [EDGE_TYPES.dataConditionTransition]: DataConditionTransitionEdge,
+ [EDGE_TYPES.defaultConditionTransition]: DefaultConditionTransitionEdge,
+ [EDGE_TYPES.errorTransition]: ErrorTransitionEdge,
+ [EDGE_TYPES.eventConditionTransition]: EventConditionTransitionEdge,
+ [EDGE_TYPES.transition]: TransitionEdge,
+};
+
+const MIME_TYPE_FOR_SWF_EDITOR_NODE = "kie-swf-editor--node";
Review Comment:
reported unused
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]