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

thiagoelg 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 9131b10d272 kie-issues#3634: BPMN Editor: Add processDuration field to 
the Global Properties (#3635)
9131b10d272 is described below

commit 9131b10d27288b79c8c2ae77f286b1979d5b1bbd
Author: Kusuma04-dev <[email protected]>
AuthorDate: Thu Jul 9 20:49:17 2026 +0530

    kie-issues#3634: BPMN Editor: Add processDuration field to the Global 
Properties (#3635)
    
    Co-authored-by: Kusuma <[email protected]>
---
 packages/bpmn-editor/src/i18n/BpmnEditorI18n.ts    |   2 +
 packages/bpmn-editor/src/i18n/locales/en.ts        |   2 +
 .../src/propertiesPanel/GlobalProperties.tsx       |   3 +
 .../processDuration/ProcessDurationInput.tsx       | 106 +++++++++++++++++++++
 .../propertiesPanel/changeGlobalProperties.spec.ts |  82 ++++++++++++++++
 .../src/drools-extension-metaData.ts               |   1 +
 6 files changed, 196 insertions(+)

diff --git a/packages/bpmn-editor/src/i18n/BpmnEditorI18n.ts 
b/packages/bpmn-editor/src/i18n/BpmnEditorI18n.ts
index ee82d89c0ea..8a619836988 100644
--- a/packages/bpmn-editor/src/i18n/BpmnEditorI18n.ts
+++ b/packages/bpmn-editor/src/i18n/BpmnEditorI18n.ts
@@ -203,6 +203,8 @@ interface BpmnEditorDictionary
       priorityPlaceholder: string;
       slaDuedate: string;
       datePlaceholder: string;
+      processDuration: string;
+      processDurationPlaceholder: string;
       timerOptions: string;
       fireOnceAfterDuration: string;
       durationPlaceholder: string;
diff --git a/packages/bpmn-editor/src/i18n/locales/en.ts 
b/packages/bpmn-editor/src/i18n/locales/en.ts
index 4b4ae8c07df..25c322a7c62 100644
--- a/packages/bpmn-editor/src/i18n/locales/en.ts
+++ b/packages/bpmn-editor/src/i18n/locales/en.ts
@@ -208,6 +208,8 @@ export const en: BpmnEditorI18n = {
     priorityPlaceholder: "Enter priority...",
     slaDuedate: "SLA Due Date",
     datePlaceholder: "Enter a date...",
+    processDuration: "Process Duration",
+    processDurationPlaceholder: "E.g., PT1M (1 minute), PT1H (1 hour), P1D (1 
day)",
     timerOptions: "Timer options",
     fireOnceAfterDuration: "Fire once after duration",
     durationPlaceholder: "Enter duration or expression #{expression}",
diff --git a/packages/bpmn-editor/src/propertiesPanel/GlobalProperties.tsx 
b/packages/bpmn-editor/src/propertiesPanel/GlobalProperties.tsx
index 7c5b273d50a..c4d31d85187 100644
--- a/packages/bpmn-editor/src/propertiesPanel/GlobalProperties.tsx
+++ b/packages/bpmn-editor/src/propertiesPanel/GlobalProperties.tsx
@@ -52,6 +52,7 @@ import { isProcessIdValid, getProcessIdErrorMessage } from 
"../validation/proces
 import { Imports } from "./imports/Imports";
 import { Metadata } from "./metadata/Metadata";
 import { SlaDueDateInput } from "./slaDueDate/SlaDueDateInput";
+import { ProcessDurationInput } from "./processDuration/ProcessDurationInput";
 import { useBpmnEditorI18n } from "../i18n";
 
 export function GlobalProperties() {
@@ -185,6 +186,8 @@ export function GlobalProperties() {
                 </FormGroup>
 
                 <SlaDueDateInput element={process} />
+
+                <ProcessDurationInput element={process} />
               </FormSection>
             </>
           )}
diff --git 
a/packages/bpmn-editor/src/propertiesPanel/processDuration/ProcessDurationInput.tsx
 
b/packages/bpmn-editor/src/propertiesPanel/processDuration/ProcessDurationInput.tsx
new file mode 100644
index 00000000000..9e2e1cd19db
--- /dev/null
+++ 
b/packages/bpmn-editor/src/propertiesPanel/processDuration/ProcessDurationInput.tsx
@@ -0,0 +1,106 @@
+/*
+ * 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 {
+  deleteBpmn20Drools10MetaDataEntry,
+  parseBpmn20Drools10MetaData,
+  setBpmn20Drools10MetaData,
+} from "@kie-tools/bpmn-marshaller/dist/drools-extension-metaData";
+import { FormGroup } from "@patternfly/react-core/dist/js/components/Form";
+import { TextInput } from 
"@patternfly/react-core/dist/js/components/TextInput";
+import { addOrGetProcessAndDiagramElements } from 
"../../mutations/addOrGetProcessAndDiagramElements";
+import { useBpmnEditorStore, useBpmnEditorStoreApi } from 
"../../store/StoreContext";
+import {
+  BPMN20__tDefinitions,
+  BPMN20__tProcess,
+  WithMetaData,
+} from "@kie-tools/bpmn-marshaller/dist/schemas/bpmn-2_0/ts-gen/types";
+import { ElementFilter } from "@kie-tools/xml-parser-ts/dist/elementFilter";
+import { Unpacked } from 
"@kie-tools/xyflow-react-kie-diagram/dist/tsExt/tsExt";
+import { Normalized } from "../../normalization/normalize";
+import { visitFlowElementsAndArtifacts } from 
"../../mutations/_elementVisitor";
+import { useBpmnEditorI18n } from "../../i18n";
+
+export type WithProcessDuration =
+  | undefined
+  | Normalized<
+      | 
ElementFilter<Unpacked<NonNullable<BPMN20__tDefinitions["rootElement"]>>, 
"process">
+      | ElementFilter<
+          Unpacked<NonNullable<BPMN20__tProcess["flowElement"]>>,
+          | "startEvent"
+          | "intermediateCatchEvent"
+          | "boundaryEvent"
+          | "callActivity"
+          | "subProcess"
+          | "adHocSubProcess"
+          | "transaction"
+          | "userTask"
+          | "task"
+          | "serviceTask"
+          | "businessRuleTask"
+        >
+    >;
+
+export function ProcessDurationInput({ element }: { element: 
WithProcessDuration }) {
+  const { i18n } = useBpmnEditorI18n();
+  const bpmnEditorStoreApi = useBpmnEditorStoreApi();
+
+  const isReadOnly = useBpmnEditorStore((s) => s.settings.isReadOnly);
+
+  return (
+    <FormGroup label={i18n.propertiesPanel.processDuration}>
+      <TextInput
+        aria-label={"Process Duration"}
+        type={"text"}
+        isDisabled={isReadOnly}
+        placeholder={i18n.propertiesPanel.processDurationPlaceholder}
+        value={parseBpmn20Drools10MetaData(element).get("processDuration") || 
""}
+        onChange={(_e, newProcessDuration) =>
+          bpmnEditorStoreApi.setState((s) => {
+            const { process } = addOrGetProcessAndDiagramElements({
+              definitions: s.bpmn.model.definitions,
+            });
+            if (!element || element["@_id"] === process["@_id"]) {
+              if (newProcessDuration) {
+                setBpmn20Drools10MetaData(process, "processDuration", 
newProcessDuration);
+              } else {
+                deleteBpmn20Drools10MetaDataEntry(process, "processDuration");
+              }
+            } else {
+              visitFlowElementsAndArtifacts(process, ({ element: e }) => {
+                if (e["@_id"] === element["@_id"]) {
+                  if (newProcessDuration) {
+                    setBpmn20Drools10MetaData(
+                      e as { extensionElements?: WithMetaData },
+                      "processDuration",
+                      newProcessDuration
+                    );
+                  } else {
+                    deleteBpmn20Drools10MetaDataEntry(e as { 
extensionElements?: WithMetaData }, "processDuration");
+                  }
+                }
+              });
+            }
+          })
+        }
+      />
+    </FormGroup>
+  );
+}
diff --git 
a/packages/bpmn-editor/tests-e2e/propertiesPanel/changeGlobalProperties.spec.ts 
b/packages/bpmn-editor/tests-e2e/propertiesPanel/changeGlobalProperties.spec.ts
new file mode 100644
index 00000000000..4859de96c11
--- /dev/null
+++ 
b/packages/bpmn-editor/tests-e2e/propertiesPanel/changeGlobalProperties.spec.ts
@@ -0,0 +1,82 @@
+/*
+ * 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 { test, expect } from "../__fixtures__/base";
+
+test.beforeEach(async ({ editor, page }) => {
+  await page.setViewportSize({ width: 1920, height: 1080 });
+  await editor.open();
+  await editor.setInitialProcessId();
+});
+
+test.describe("Change Global Properties - Process Duration", () => {
+  test.beforeEach(async ({ page }) => {
+    await page.getByRole("button", { name: "Properties Management" }).click();
+    await expect(page.getByText("Process", { exact: true })).toBeVisible();
+  });
+
+  test("should set processDuration value", async ({ page }) => {
+    const processDurationInput = page.getByPlaceholder(/E.g., PT1M \(1 
minute\), PT1H \(1 hour\), P1D \(1 day\)/i);
+    await processDurationInput.fill("PT30M");
+
+    await expect(processDurationInput).toHaveValue("PT30M");
+  });
+
+  test("should update processDuration value", async ({ page }) => {
+    const processDurationInput = page.getByPlaceholder(/E.g., PT1M \(1 
minute\), PT1H \(1 hour\), P1D \(1 day\)/i);
+
+    await processDurationInput.fill("PT1H");
+    await expect(processDurationInput).toHaveValue("PT1H");
+
+    await processDurationInput.fill("P1D");
+    await expect(processDurationInput).toHaveValue("P1D");
+  });
+
+  test("should clear processDuration value", async ({ page }) => {
+    const processDurationInput = page.getByPlaceholder(/E.g., PT1M \(1 
minute\), PT1H \(1 hour\), P1D \(1 day\)/i);
+
+    await processDurationInput.fill("PT2H");
+    await expect(processDurationInput).toHaveValue("PT2H");
+
+    await processDurationInput.clear();
+    await expect(processDurationInput).toHaveValue("");
+  });
+
+  test("should accept various ISO 8601 duration formats", async ({ page }) => {
+    const processDurationInput = page.getByPlaceholder(/E.g., PT1M \(1 
minute\), PT1H \(1 hour\), P1D \(1 day\)/i);
+
+    const testValues = ["PT1M", "PT30M", "PT1H", "PT2H30M", "P1D", "P1DT12H", 
"P7D"];
+
+    for (const duration of testValues) {
+      await processDurationInput.fill(duration);
+      await expect(processDurationInput).toHaveValue(duration);
+    }
+  });
+
+  test("should persist processDuration with other process properties", async 
({ page }) => {
+    const nameInput = page.getByPlaceholder(/Enter a name.../i);
+    await nameInput.fill("Order Processing");
+
+    const processDurationInput = page.getByPlaceholder(/E.g., PT1M \(1 
minute\), PT1H \(1 hour\), P1D \(1 day\)/i);
+    await processDurationInput.fill("PT45M");
+
+    await expect(nameInput).toHaveValue("Order Processing");
+    await expect(processDurationInput).toHaveValue("PT45M");
+  });
+});
diff --git a/packages/bpmn-marshaller/src/drools-extension-metaData.ts 
b/packages/bpmn-marshaller/src/drools-extension-metaData.ts
index c2f84083c1a..a9769be4900 100644
--- a/packages/bpmn-marshaller/src/drools-extension-metaData.ts
+++ b/packages/bpmn-marshaller/src/drools-extension-metaData.ts
@@ -25,6 +25,7 @@ export type Bpmn20KnownMetaDataKey =
   | "customTags" // Used for Process Variables.
   | "customDescription" // Used for "Process Instance Description" as a global 
property.
   | "customSLADueDate" // Used for "SLA Due date" as a global property.
+  | "processDuration" // Used for "Process Duration" as a global property.
   | "customAbortParent" // Used for "Abort parent" flag on Call Activities.
   | "customAsync" // Used for "Async" flag on Call Activities.
   | "customActivationCondition" // Used for "Activation condition" expression 
on Ad-hoc sub-processes.


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

Reply via email to