From 8d938ff20d4faa14e5e719a677acc415d784d4f7 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Fri, 15 May 2026 17:27:14 +0200 Subject: [PATCH 01/39] fixed word-break --- .../executions/[processId]/element-status.tsx | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx index c4fac0b71..44bf24eb6 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx @@ -167,17 +167,23 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - Started: + + Started: + {generateDateString(start, true)} , - Planned Start: + + Planned Start: + {generateDateString(plan.start, true) || ''} , - Delay: + + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.start)} @@ -187,17 +193,23 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - Duration: + + Duration: + {generateDurationString(duration)} , - Planned Duration: + + Planned Duration: + {generateDurationString(plan.duration)} , - Delay: + + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.duration)} @@ -207,17 +219,23 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - Ended: + + Ended: + {generateDateString(end, true)} , - Planned End: + + Planned End: + {generateDateString(plan.end, true) || ''} , - Delay: + + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.end)} From f9380805c1d81a0bf31d25301f51645c28f8e1aa Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Fri, 15 May 2026 18:35:19 +0200 Subject: [PATCH 02/39] refactoring --- .../[processId]/element-status.module.scss | 3 + .../executions/[processId]/element-status.tsx | 66 ++++++++----------- 2 files changed, 30 insertions(+), 39 deletions(-) create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss new file mode 100644 index 000000000..e7fb28c94 --- /dev/null +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss @@ -0,0 +1,3 @@ +.ElementText { + word-break: normal; +} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx index 44bf24eb6..4f1d5c79b 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx @@ -6,6 +6,12 @@ import { getMetaDataFromElement } from '@proceed/bpmn-helper'; import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; import endpointBuilder from '@/lib/engines/endpoints/endpoint-builder'; import { generateDateString, generateDurationString, generateNumberString } from '@/lib/utils'; +import styles from './element-status.module.scss'; + +type EntryTextProps = React.ComponentProps; +const EntryText = (props: EntryTextProps) => ( + +); export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const statusEntries: ReactNode[][] = []; @@ -167,78 +173,60 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - - Started: - - {generateDateString(start, true)} + Started: + {generateDateString(start, true)} , - - Planned Start: - - {generateDateString(plan.start, true) || ''} + Planned Start: + {generateDateString(plan.start, true) || ''} , - - Delay: - - = 1000 ? 'danger' : undefined}> + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.start)} - + , ]); statusEntries.push([ - - Duration: - - {generateDurationString(duration)} + Duration: + {generateDurationString(duration)} , - - Planned Duration: - - {generateDurationString(plan.duration)} + Planned Duration: + {generateDurationString(plan.duration)} , - - Delay: - - = 1000 ? 'danger' : undefined}> + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.duration)} - + , ]); statusEntries.push([ - - Ended: - - {generateDateString(end, true)} + Ended: + {generateDateString(end, true)} , - - Planned End: - - {generateDateString(plan.end, true) || ''} + Planned End: + {generateDateString(plan.end, true) || ''} , - - Delay: - - = 1000 ? 'danger' : undefined}> + Delay: + = 1000 ? 'danger' : undefined}> {generateDurationString(delays.end)} - + , ]); From 7d6f1d71d2cf0127d3fd8487e2379dbc1e380b51 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Tue, 19 May 2026 12:35:56 +0200 Subject: [PATCH 03/39] new tab added with placeholder text --- .../executions/[processId]/element-info.tsx | 42 +++++++++++++++++++ .../[processId]/instance-info-panel.tsx | 6 +++ 2 files changed, 48 insertions(+) create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx new file mode 100644 index 000000000..3f24042c0 --- /dev/null +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx @@ -0,0 +1,42 @@ +import { ReactNode } from 'react'; +import { Typography } from 'antd'; +import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; +import styles from './element-status.module.scss'; + +type EntryTextProps = React.ComponentProps; +const EntryText = (props: EntryTextProps) => ( + +); + +export function ElementInfo({ info }: { info: RelevantInstanceInfo }) { + const infoEntries: ReactNode[][] = []; + + infoEntries.push([ProcessName, Value]); + infoEntries.push([ProcessShortName, Value]); + infoEntries.push([ProcessVersionName, Value]); + infoEntries.push([ + ProcessVersionDescription, + Value, + ]); + infoEntries.push([ProcessVersionCreatedOn, Value]); + infoEntries.push([ + ProcessInstanceInitiatorFullName, + Value, + ]); + infoEntries.push([ + ProcessInstanceInitiatorSpaceName, + Value, + ]); + infoEntries.push([ + ProcessInstanceInitiatorSpaceName, + Value, + ]); + infoEntries.push([InstanceStartTime, Value]); + infoEntries.push([ProcessStepId, Value]); + infoEntries.push([ProcessStepName, Value]); + infoEntries.push([ProcessStepType, Value]); + infoEntries.push([ActualPerformerName, Value]); + infoEntries.push([ProcessEngineName, Value]); + + return ; +} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index 5e5009c84..f74ace359 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -6,6 +6,7 @@ import { Drawer, Grid, Tabs } from 'antd'; import type { ElementLike } from 'diagram-js/lib/core/Types'; import { ElementStatus } from './element-status'; import InstanceVariables from './instance-variables'; +import { ElementInfo } from './element-info'; export type RelevantInstanceInfo = { instance?: InstanceInfo; @@ -58,6 +59,11 @@ export default function InstanceInfoPanel({ , + }, { key: 'Status', label: 'Status', From 31e3846711172e32707d7ef607a6f73fdd8c5ae6 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Wed, 20 May 2026 13:36:24 +0200 Subject: [PATCH 04/39] more placeholder fields added, refactoring for readability --- .../executions/[processId]/element-status.tsx | 105 ++++++++++++++++-- .../[processId]/instance-info-panel.tsx | 9 +- 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx index 4f1d5c79b..c68ac27bd 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx @@ -13,6 +13,10 @@ const EntryText = (props: EntryTextProps) => ( ); +const ClockSymbol = () => ( + +); + export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const statusEntries: ReactNode[][] = []; @@ -21,6 +25,83 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const token = info.instance?.tokens.find((l) => l.currentFlowElementId == info.element.id); const logInfo = info.instance?.log.find((logEntry) => logEntry.flowElementId === info.element.id); + if (isRootElement) { + statusEntries.push([ + Name, + Vacation Requests Automated, + ]); + statusEntries.push([Short Name, Vac-Req-Aut]); + statusEntries.push([ + ID, + _e7543fc7-6f55-4175-8ff0-5ed1d3a303ac, + ]); + statusEntries.push([Version Name, v1]); + statusEntries.push([ + Version Description, + Version description, yes., + ]); + statusEntries.push([ + Version Based on, + _66fac292-e026-40cb-9d96-a406e00d5ef2, + ]); + statusEntries.push([ + Version Created on, + 2026-05-18T11:39:54.943Z, + ]); + statusEntries.push([ + Instance ID, + + _e7543fc7-6f55-4175-8ff0-5ed1d3a303ac-_3b0e251c-8863-4371-ae3c-d63140a3b9fd-6979d78d-954c-4df7-8b08-52e137fadc17 + , + ]); + statusEntries.push([Initiator Name, Timmy Test]); + statusEntries.push([ + Initiator ID, + d0dc354a-5d8a-455d-b3f4-d8dcc09768f2, + ]); + statusEntries.push([Initiator Username, timtes]); + statusEntries.push([Initiator Space, org1]); + statusEntries.push([ + Initiator Space ID, + e1d5a6ae-667f-4d15-87f6-ec49391535d6, + ]); + statusEntries.push([ + Start Time, + 5/20/2026, 12:39 PM, + ]); + statusEntries.push([Engine, engine1]); + statusEntries.push([ + Engine ID, + 488200f1-aec4-4188-843e-e0b6de4c5ed1, + ]); + } else { + statusEntries.push([ + {'Step ID (or "Event ID"?)'}, + Activity_0309v8x, + ]); + statusEntries.push([ + Step Name, + Check vacation application, + ]); + statusEntries.push([Step Type, User Task]); + statusEntries.push([ + Previous Step ID, + Check vacation application, + ]); + statusEntries.push([ + Actual Performer, + Sandra Sample, + ]); + statusEntries.push([ + Actual Performer Username, + sansam, + ]); + statusEntries.push([ + Actual Performer ID, + 29880751-c190-4f58-b5cb-438754e9f02d, + ]); + } + // Element image if (metaData.overviewImage) statusEntries.push([ @@ -135,10 +216,10 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push(['Priority:', priority]); } - // Planned costs + // Budget const costs: { value: string; unit: string } | undefined = metaData['costsPlanned']; statusEntries.push([ - 'Planned Costs:', + 'Budget:', costs && generateNumberString(+costs.value, { style: 'currency', @@ -169,20 +250,22 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const { delays, plan } = getPlanDelays({ elementMetaData: metaData, start, end, duration }); + // adding an empty line for padding + statusEntries.push([]); // Activity time statusEntries.push([ - + Started: {generateDateString(start, true)} , - + Planned Start: {generateDateString(plan.start, true) || ''} , - + Delay: = 1000 ? 'danger' : undefined}> {generateDurationString(delays.start)} @@ -192,17 +275,17 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - + Duration: {generateDurationString(duration)} , - + Planned Duration: {generateDurationString(plan.duration)} , - + Delay: = 1000 ? 'danger' : undefined}> {generateDurationString(delays.duration)} @@ -212,17 +295,17 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { statusEntries.push([ - + Ended: {generateDateString(end, true)} , - + Planned End: {generateDateString(plan.end, true) || ''} , - + Delay: = 1000 ? 'danger' : undefined}> {generateDurationString(delays.end)} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index f74ace359..f98d11b68 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -60,13 +60,8 @@ export default function InstanceInfoPanel({ defaultActiveKey="1" items={[ { - key: 'Info', - label: 'Info', - children: , - }, - { - key: 'Status', - label: 'Status', + key: 'Overview', + label: 'Overview', children: , }, { From 7f1772f999dfbe5215a2904442b635e508913eb0 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Fri, 22 May 2026 16:33:41 +0200 Subject: [PATCH 05/39] styling ideas --- .../executions/[processId]/element-status.tsx | 136 ++++++++++-------- .../[processId]/instance-info-panel.tsx | 20 ++- 2 files changed, 94 insertions(+), 62 deletions(-) diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx index c68ac27bd..3c663f1bc 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx @@ -1,5 +1,5 @@ import { ReactNode } from 'react'; -import { Alert, Checkbox, Image, Progress, ProgressProps, Space, Typography } from 'antd'; +import { Alert, Button, Checkbox, Image, Progress, ProgressProps, Space, Typography } from 'antd'; import { ClockCircleFilled } from '@ant-design/icons'; import { getPlanDelays, getTimeInfo, statusToType } from './instance-helpers'; import { getMetaDataFromElement } from '@proceed/bpmn-helper'; @@ -10,7 +10,7 @@ import styles from './element-status.module.scss'; type EntryTextProps = React.ComponentProps; const EntryText = (props: EntryTextProps) => ( - + ); const ClockSymbol = () => ( @@ -25,6 +25,24 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const token = info.instance?.tokens.find((l) => l.currentFlowElementId == info.element.id); const logInfo = info.instance?.log.find((logEntry) => logEntry.flowElementId === info.element.id); + if (!info.instance) { + return ( + <> + + Let's select some instances! + + + + + + + + + + + ); + } + if (isRootElement) { statusEntries.push([ Name, @@ -253,65 +271,65 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { // adding an empty line for padding statusEntries.push([]); // Activity time - statusEntries.push([ - - - Started: - {generateDateString(start, true)} - , - - - Planned Start: - {generateDateString(plan.start, true) || ''} - , - - - Delay: - = 1000 ? 'danger' : undefined}> - {generateDurationString(delays.start)} - - , - ]); + // statusEntries.push([ + // + // + // Started: + // {generateDateString(start, true)} + // , + // + // + // Planned Start: + // {generateDateString(plan.start, true) || ''} + // , + // + // + // Delay: + // = 1000 ? 'danger' : undefined}> + // {generateDurationString(delays.start)} + // + // , + // ]); - statusEntries.push([ - - - Duration: - {generateDurationString(duration)} - , - - - Planned Duration: - {generateDurationString(plan.duration)} - , - - - Delay: - = 1000 ? 'danger' : undefined}> - {generateDurationString(delays.duration)} - - , - ]); + // statusEntries.push([ + // + // + // Duration: + // {generateDurationString(duration)} + // , + // + // + // Planned Duration: + // {generateDurationString(plan.duration)} + // , + // + // + // Delay: + // = 1000 ? 'danger' : undefined}> + // {generateDurationString(delays.duration)} + // + // , + // ]); - statusEntries.push([ - - - Ended: - {generateDateString(end, true)} - , - - - Planned End: - {generateDateString(plan.end, true) || ''} - , - - - Delay: - = 1000 ? 'danger' : undefined}> - {generateDurationString(delays.end)} - - , - ]); + // statusEntries.push([ + // + // + // Ended: + // {generateDateString(end, true)} + // , + // + // + // Planned End: + // {generateDateString(plan.end, true) || ''} + // , + // + // + // Delay: + // = 1000 ? 'danger' : undefined}> + // {generateDurationString(delays.end)} + // + // , + // ]); return ; } diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index f98d11b68..b50480837 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -2,7 +2,7 @@ import ResizableElement, { ResizableElementRefType } from '@/components/Resizabl import CollapsibleCard from '@/components/collapsible-card'; import { ReactNode, useRef } from 'react'; import { DeployedProcessInfo, InstanceInfo, VersionInfo } from '@/lib/engines/deployment'; -import { Drawer, Grid, Tabs } from 'antd'; +import { Drawer, Grid, Table, Tabs, Typography } from 'antd'; import type { ElementLike } from 'diagram-js/lib/core/Types'; import { ElementStatus } from './element-status'; import InstanceVariables from './instance-variables'; @@ -18,14 +18,28 @@ export type RelevantInstanceInfo = { export function DisplayTable({ data }: { data: ReactNode[][] }) { // TODO: make this responsive return ( - +
+ + + + {data.map((row, idx_row) => ( {row.map((cell, idx_cell) => ( From a5346ad1b2ee8fd89540c76a9946c6d7a882f609 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Tue, 26 May 2026 15:25:21 +0200 Subject: [PATCH 06/39] timing moved to different tab --- .../executions/[processId]/element-timing.tsx | 129 ++++++++++++++++++ .../[processId]/instance-info-panel.tsx | 3 +- 2 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx new file mode 100644 index 000000000..3d8abde43 --- /dev/null +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx @@ -0,0 +1,129 @@ +import { ReactNode } from 'react'; +import { Alert, Button, Checkbox, Image, Progress, ProgressProps, Space, Typography } from 'antd'; +import { ClockCircleFilled } from '@ant-design/icons'; +import { getPlanDelays, getTimeInfo, statusToType } from './instance-helpers'; +import { getMetaDataFromElement } from '@proceed/bpmn-helper'; +import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; +import endpointBuilder from '@/lib/engines/endpoints/endpoint-builder'; +import { generateDateString, generateDurationString, generateNumberString } from '@/lib/utils'; +import styles from './element-status.module.scss'; + +type EntryTextProps = React.ComponentProps; +const EntryText = (props: EntryTextProps) => ( + +); + +const ClockSymbol = () => ( + +); + +export function ElementTiming({ info }: { info: RelevantInstanceInfo }) { + const timingEntries: ReactNode[][] = []; + + const metaData = getMetaDataFromElement(info.element.businessObject); + const token = info.instance?.tokens.find((l) => l.currentFlowElementId == info.element.id); + const logInfo = info.instance?.log.find((logEntry) => logEntry.flowElementId === info.element.id); + + // Activity time calculation + const { start, end, duration } = getTimeInfo({ + element: info.element, + instance: info.instance, + logInfo, + token, + }); + + const { delays, plan } = getPlanDelays({ elementMetaData: metaData, start, end, duration }); + + // adding an empty line for padding + timingEntries.push([]); + // Activity time + timingEntries.push([ + + + Started: + {generateDateString(start, true)} + , + + + Planned Start: + {generateDateString(plan.start, true) || ''} + , + + + Delay: + = 1000 ? 'danger' : undefined}> + {generateDurationString(delays.start)} + + , + ]); + + timingEntries.push([ + + + Duration: + {generateDurationString(duration)} + , + + + Planned Duration: + {generateDurationString(plan.duration)} + , + + + Delay: + = 1000 ? 'danger' : undefined}> + {generateDurationString(delays.duration)} + + , + ]); + + timingEntries.push([ + + + Ended: + {generateDateString(end, true)} + , + + + Planned End: + {generateDateString(plan.end, true) || ''} + , + + + Delay: + = 1000 ? 'danger' : undefined}> + {generateDurationString(delays.end)} + + , + ]); + + return ( +
{cell}
+ + + + + + {timingEntries.map((row, idx_row) => ( + + {row.map((cell, idx_cell) => ( + + ))} + + ))} + +
+ {cell} +
+ ); +} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index b50480837..33f46efee 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -7,6 +7,7 @@ import type { ElementLike } from 'diagram-js/lib/core/Types'; import { ElementStatus } from './element-status'; import InstanceVariables from './instance-variables'; import { ElementInfo } from './element-info'; +import { ElementTiming } from './element-timing'; export type RelevantInstanceInfo = { instance?: InstanceInfo; @@ -86,7 +87,7 @@ export default function InstanceInfoPanel({ { key: 'Timing', label: 'Timing', - children: 'How to proceed', + children: , }, { key: 'Assignments', From f065958a71c764771f78a73f6179be48fca498f8 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Tue, 26 May 2026 16:46:55 +0200 Subject: [PATCH 07/39] breakpoint causes Modal instead of Drawer --- .../[processId]/instance-info-panel.tsx | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index 33f46efee..957618f42 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -2,7 +2,7 @@ import ResizableElement, { ResizableElementRefType } from '@/components/Resizabl import CollapsibleCard from '@/components/collapsible-card'; import { ReactNode, useRef } from 'react'; import { DeployedProcessInfo, InstanceInfo, VersionInfo } from '@/lib/engines/deployment'; -import { Drawer, Grid, Table, Tabs, Typography } from 'antd'; +import { Button, Grid, Modal, Tabs } from 'antd'; import type { ElementLike } from 'diagram-js/lib/core/Types'; import { ElementStatus } from './element-status'; import InstanceVariables from './instance-variables'; @@ -64,11 +64,11 @@ export default function InstanceInfoPanel({ refetch: () => void; }) { const resizableElementRef = useRef(null); - const breakpoints = Grid.useBreakpoint(); + const breakpoint = Grid.useBreakpoint(); const title = info.element?.businessObject?.name || info.element?.id || 'How to PROCEED?'; - if (breakpoints.xl && !open) return null; + if (breakpoint.xl && !open) return null; const tabs = info.element ? ( ) : null; - if (breakpoints.xl) - return ( - 38 px), Footer with 32px and Header with 64px, Padding of Toolbar 12px (=> Total 146px) - height: 'calc(100vh - 150px)', - }} - ref={resizableElementRef} - > - - {tabs} - - - ); + // TODO to be determined by higher forces + const hideFooter = true; - return ( - + return breakpoint.xl ? ( + 38 px), Footer with 32px and Header with 64px, Padding of Toolbar 12px (=> Total 146px) + height: 'calc(100vh - 150px)', + }} + ref={resizableElementRef} + > + + {tabs} + + + ) : ( + + OK + + ) + } + > {tabs} - + ); } From 71cd501c92ec78208ec07301330425e3b29c2427 Mon Sep 17 00:00:00 2001 From: Can-Philipp Tura Date: Mon, 1 Jun 2026 18:02:32 +0200 Subject: [PATCH 08/39] incorporation of some reference layouts and style --- .../executions/[processId]/element-info.tsx | 42 -- .../[processId]/element-overview.tsx | 257 +++++++++ .../[processId]/element-status.module.scss | 9 + .../executions/[processId]/element-status.tsx | 304 +++++++---- .../executions/[processId]/element-timing.tsx | 2 + .../[processId]/instance-info-panel.tsx | 56 +- .../[processId]/instance-selector.tsx | 22 + .../[processId]/process-deployment-view.tsx | 498 +++++++++--------- .../executions/[processId]/status-tag.tsx | 50 ++ 9 files changed, 835 insertions(+), 405 deletions(-) delete mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-overview.tsx create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-selector.tsx create mode 100644 src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/status-tag.tsx diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx deleted file mode 100644 index 3f24042c0..000000000 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-info.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { ReactNode } from 'react'; -import { Typography } from 'antd'; -import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; -import styles from './element-status.module.scss'; - -type EntryTextProps = React.ComponentProps; -const EntryText = (props: EntryTextProps) => ( - -); - -export function ElementInfo({ info }: { info: RelevantInstanceInfo }) { - const infoEntries: ReactNode[][] = []; - - infoEntries.push([ProcessName, Value]); - infoEntries.push([ProcessShortName, Value]); - infoEntries.push([ProcessVersionName, Value]); - infoEntries.push([ - ProcessVersionDescription, - Value, - ]); - infoEntries.push([ProcessVersionCreatedOn, Value]); - infoEntries.push([ - ProcessInstanceInitiatorFullName, - Value, - ]); - infoEntries.push([ - ProcessInstanceInitiatorSpaceName, - Value, - ]); - infoEntries.push([ - ProcessInstanceInitiatorSpaceName, - Value, - ]); - infoEntries.push([InstanceStartTime, Value]); - infoEntries.push([ProcessStepId, Value]); - infoEntries.push([ProcessStepName, Value]); - infoEntries.push([ProcessStepType, Value]); - infoEntries.push([ActualPerformerName, Value]); - infoEntries.push([ProcessEngineName, Value]); - - return ; -} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-overview.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-overview.tsx new file mode 100644 index 000000000..b1cbb11f8 --- /dev/null +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-overview.tsx @@ -0,0 +1,257 @@ +import { ReactNode } from 'react'; +import { Col, Divider, Menu, Row, Space, Typography } from 'antd'; +import { DataGrid, DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; +import styles from './element-status.module.scss'; +import { InstanceSelector } from './instance-selector'; +import { getMetaDataFromElement } from '@proceed/bpmn-helper'; +import ImageSelectionSection from '../../../processes/[mode]/[processId]/image-selection-section'; +import TextViewer from '@/components/text-viewer'; +import { getPlanDelays, getTimeInfo } from './instance-helpers'; +import { generateDateString, generateDurationString } from '@/lib/utils'; + +type EntryTextProps = React.ComponentProps; +const EntryText = (props: EntryTextProps) => ( + +); + +export function ElementOverview({ info }: { info: RelevantInstanceInfo }) { + if (!info.instance) return ; + const overviewEntries: ReactNode[][] = []; + const metaData = getMetaDataFromElement(info.element.businessObject); + const isRootElement = info.element && info.element.type === 'bpmn:Process'; + const token = info.instance?.tokens.find((l) => l.currentFlowElementId == info.element.id); + const logInfo = info.instance?.log.find((logEntry) => logEntry.flowElementId === info.element.id); + + // Element image + if (metaData.overviewImage) { + overviewEntries.push([ +
+ {/** TODO: correct image url */} + {}} + disabled={true} + /> +
, + ]); + } else { + overviewEntries.push([ +
+ Process/Step image +
, + ]); + } + + if (isRootElement) { + // Name and Shortname + overviewEntries.push([ +
+ + Vacation Requests Automated + + + Vac-Req-Aut + +
, + ]); + + // description + overviewEntries.push([ +
+ +
, + ]); + + // time info + const { start, end, duration } = getTimeInfo({ + element: info.element, + instance: info.instance, + logInfo, + token, + }); + const { delays, plan } = getPlanDelays({ elementMetaData: metaData, start, end, duration }); + + overviewEntries.push([ +
+ + + Started +
+ {generateDateString(start, true)} + + + Running for +
+ {generateDurationString(duration) || 'N/A'} + +
+ + + Planned +
+ {generateDurationString(plan.duration) || 'N/A'} + + + Started by +
+ kasklds fmds + +
+
, + ]); + overviewEntries.push([ + + BUDGET + , + ]); + overviewEntries.push([ + + + + Planned + + + $500 + + + + + + Calculated + + + $520 + + + + + + Actual + + + $520 + + Override + + + + , + ]); + } else { + } + + return ; +} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss index e7fb28c94..0ccbc3d26 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.module.scss @@ -1,3 +1,12 @@ .ElementText { word-break: normal; } + +.ElementKeyText { + color: gray; + font-size: 0.8em; +} + +.ElementValueText { + font-size: 0.9em; +} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx index 3c663f1bc..105dd51c7 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-status.tsx @@ -1,16 +1,30 @@ import { ReactNode } from 'react'; -import { Alert, Button, Checkbox, Image, Progress, ProgressProps, Space, Typography } from 'antd'; +import { + Alert, + Checkbox, + Collapse, + Divider, + Progress, + ProgressProps, + Space, + Switch, + Typography, +} from 'antd'; import { ClockCircleFilled } from '@ant-design/icons'; import { getPlanDelays, getTimeInfo, statusToType } from './instance-helpers'; import { getMetaDataFromElement } from '@proceed/bpmn-helper'; -import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; +import { DataGrid, DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; import endpointBuilder from '@/lib/engines/endpoints/endpoint-builder'; import { generateDateString, generateDurationString, generateNumberString } from '@/lib/utils'; import styles from './element-status.module.scss'; +import { InstanceSelector } from './instance-selector'; type EntryTextProps = React.ComponentProps; -const EntryText = (props: EntryTextProps) => ( - +const EntryKeyText = (props: EntryTextProps) => ( + +); +const EntryValueText = (props: EntryTextProps) => ( + ); const ClockSymbol = () => ( @@ -18,6 +32,7 @@ const ClockSymbol = () => ( ); export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { + if (!info.instance) return ; const statusEntries: ReactNode[][] = []; const isRootElement = info.element && info.element.type === 'bpmn:Process'; @@ -25,128 +40,175 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const token = info.instance?.tokens.find((l) => l.currentFlowElementId == info.element.id); const logInfo = info.instance?.log.find((logEntry) => logEntry.flowElementId === info.element.id); - if (!info.instance) { - return ( - <> - - Let's select some instances! - - - - - - - - - - - ); - } - + statusEntries.push([ +
+ + + + Show technical details + + + IDs & system info shown + + +
, + ]); if (isRootElement) { statusEntries.push([ - Name, - Vacation Requests Automated, + GENERAL, ]); - statusEntries.push([Short Name, Vac-Req-Aut]); statusEntries.push([ - ID, - _e7543fc7-6f55-4175-8ff0-5ed1d3a303ac, + Name, + Vacation Requests Automated, ]); - statusEntries.push([Version Name, v1]); statusEntries.push([ - Version Description, - Version description, yes., + Documentation:, + {info.element.businessObject?.documentation?.[0]?.text}, ]); statusEntries.push([ - Version Based on, - _66fac292-e026-40cb-9d96-a406e00d5ef2, + Short Name, + Vac-Req-Aut, ]); statusEntries.push([ - Version Created on, - 2026-05-18T11:39:54.943Z, + ID, + _e7543fc7-6f55-4175-8ff0-5ed1d3a303ac, ]); + statusEntries.push([ - Instance ID, - + + + VERSION + , + ]); + + statusEntries.push([ + Version Name, + v1, + ]); + statusEntries.push([ + Version Description, + Version description, yes., + ]); + statusEntries.push([ + Version Based on, + _66fac292-e026-40cb-9d96-a406e00d5ef2, + ]); + statusEntries.push([ + Version Created on, + 2026-05-18T11:39:54.943Z, + ]); + statusEntries.push([ + Instance ID, + _e7543fc7-6f55-4175-8ff0-5ed1d3a303ac-_3b0e251c-8863-4371-ae3c-d63140a3b9fd-6979d78d-954c-4df7-8b08-52e137fadc17 - , + , + ]); + statusEntries.push([ + + + WHO STARTED IT + , + ]); + statusEntries.push([ + Initiator Name, + Timmy Test, + ]); + statusEntries.push([ + Initiator ID, + d0dc354a-5d8a-455d-b3f4-d8dcc09768f2, + ]); + statusEntries.push([ + Initiator Username, + timtes, + ]); + statusEntries.push([ + Initiator Space, + org1, + ]); + statusEntries.push([ + Initiator Space ID, + e1d5a6ae-667f-4d15-87f6-ec49391535d6, ]); - statusEntries.push([Initiator Name, Timmy Test]); statusEntries.push([ - Initiator ID, - d0dc354a-5d8a-455d-b3f4-d8dcc09768f2, + + + TIMING + , ]); - statusEntries.push([Initiator Username, timtes]); - statusEntries.push([Initiator Space, org1]); statusEntries.push([ - Initiator Space ID, - e1d5a6ae-667f-4d15-87f6-ec49391535d6, + Start Time, + 5/20/2026, 12:39 PM, ]); statusEntries.push([ - Start Time, - 5/20/2026, 12:39 PM, + + + WHERE IT RUNS + , ]); - statusEntries.push([Engine, engine1]); statusEntries.push([ - Engine ID, - 488200f1-aec4-4188-843e-e0b6de4c5ed1, + Engine, + engine1, + ]); + statusEntries.push([ + Engine ID, + 488200f1-aec4-4188-843e-e0b6de4c5ed1, ]); } else { statusEntries.push([ - {'Step ID (or "Event ID"?)'}, - Activity_0309v8x, + {'Step ID (or "Event ID"?)'}, + Activity_0309v8x, ]); statusEntries.push([ - Step Name, - Check vacation application, + Step Name, + Check vacation application, ]); - statusEntries.push([Step Type, User Task]); + statusEntries.push(['Documentation:', info.element.businessObject?.documentation?.[0]?.text]); statusEntries.push([ - Previous Step ID, - Check vacation application, + Step Type, + User Task, ]); statusEntries.push([ - Actual Performer, - Sandra Sample, + Previous Step ID, + Check vacation application, ]); statusEntries.push([ - Actual Performer Username, - sansam, + Actual Performer, + Sandra Sample, ]); statusEntries.push([ - Actual Performer ID, - 29880751-c190-4f58-b5cb-438754e9f02d, + Actual Performer Username, + sansam, ]); - } - - // Element image - if (metaData.overviewImage) statusEntries.push([ - 'Image', -
- {/** TODO: correct image url */} - Image linked to the element -
, + Actual Performer ID, + 29880751-c190-4f58-b5cb-438754e9f02d, ]); + } // Element status let status = undefined; @@ -256,7 +318,18 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { } // Documentation - statusEntries.push(['Documentation:', info.element.businessObject?.documentation?.[0]?.text]); + statusEntries.push([ + {info.element.businessObject?.documentation?.[0]?.text}

, + }, + ]} + />, + ]); // Activity time calculation const { start, end, duration } = getTimeInfo({ @@ -268,68 +341,71 @@ export function ElementStatus({ info }: { info: RelevantInstanceInfo }) { const { delays, plan } = getPlanDelays({ elementMetaData: metaData, start, end, duration }); - // adding an empty line for padding - statusEntries.push([]); // Activity time // statusEntries.push([ // // - // Started: - // {generateDateString(start, true)} + // Started: + // {generateDateString(start, true)} // , // // - // Planned Start: - // {generateDateString(plan.start, true) || ''} + // Planned Start: + // {generateDateString(plan.start, true) || ''} // , // // - // Delay: - // = 1000 ? 'danger' : undefined}> + // Delay: + // = 1000 ? 'danger' : undefined}> // {generateDurationString(delays.start)} - // + // // , // ]); // statusEntries.push([ // // - // Duration: - // {generateDurationString(duration)} + // Duration: + // {generateDurationString(duration)} // , // // - // Planned Duration: - // {generateDurationString(plan.duration)} + // Planned Duration: + // {generateDurationString(plan.duration)} // , // // - // Delay: - // = 1000 ? 'danger' : undefined}> + // Delay: + // = 1000 ? 'danger' : undefined}> // {generateDurationString(delays.duration)} - // + // // , // ]); // statusEntries.push([ // // - // Ended: - // {generateDateString(end, true)} + // Ended: + // {generateDateString(end, true)} // , // // - // Planned End: - // {generateDateString(plan.end, true) || ''} + // Planned End: + // {generateDateString(plan.end, true) || ''} // , // // - // Delay: - // = 1000 ? 'danger' : undefined}> + // Delay: + // = 1000 ? 'danger' : undefined}> // {generateDurationString(delays.end)} - // + // // , // ]); - return ; + return ( + <> + {/* */} + + + ); } diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx index 3d8abde43..cfb73ce00 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/element-timing.tsx @@ -7,6 +7,7 @@ import { DisplayTable, RelevantInstanceInfo } from './instance-info-panel'; import endpointBuilder from '@/lib/engines/endpoints/endpoint-builder'; import { generateDateString, generateDurationString, generateNumberString } from '@/lib/utils'; import styles from './element-status.module.scss'; +import { InstanceSelector } from './instance-selector'; type EntryTextProps = React.ComponentProps; const EntryText = (props: EntryTextProps) => ( @@ -18,6 +19,7 @@ const ClockSymbol = () => ( ); export function ElementTiming({ info }: { info: RelevantInstanceInfo }) { + if (!info.instance) return ; const timingEntries: ReactNode[][] = []; const metaData = getMetaDataFromElement(info.element.businessObject); diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx index 957618f42..f1d21d1c7 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-info-panel.tsx @@ -2,12 +2,13 @@ import ResizableElement, { ResizableElementRefType } from '@/components/Resizabl import CollapsibleCard from '@/components/collapsible-card'; import { ReactNode, useRef } from 'react'; import { DeployedProcessInfo, InstanceInfo, VersionInfo } from '@/lib/engines/deployment'; -import { Button, Grid, Modal, Tabs } from 'antd'; +import { Button, Col, Grid, Modal, Row, Tabs } from 'antd'; import type { ElementLike } from 'diagram-js/lib/core/Types'; import { ElementStatus } from './element-status'; import InstanceVariables from './instance-variables'; -import { ElementInfo } from './element-info'; import { ElementTiming } from './element-timing'; +import { ElementOverview } from './element-overview'; +import { StatusTag } from './status-tag'; export type RelevantInstanceInfo = { instance?: InstanceInfo; @@ -52,6 +53,44 @@ export function DisplayTable({ data }: { data: ReactNode[][] }) { ); } +export function DataGrid({ data }: { data: ReactNode[][] }) { + return ( + <> + {data.map((row, idx_row) => ( + + {row.length == 1 ? ( + {row[0]} + ) : ( + <> + + {row[0]} + + + {row[1]} + + + )} + + ))} + + ); +} + export default function InstanceInfoPanel({ open, close, @@ -72,11 +111,16 @@ export default function InstanceInfoPanel({ const tabs = info.element ? ( , + }, + { + key: 'Details', + label: 'Details', children: , }, { @@ -113,16 +157,18 @@ export default function InstanceInfoPanel({ return breakpoint.xl ? ( 38 px), Footer with 32px and Header with 64px, Padding of Toolbar 12px (=> Total 146px) height: 'calc(100vh - 150px)', + boxShadow: '0 3px 12px -4px rgba(0, 0, 0, 0.1), 0 6px 48px -2px rgba(0, 0, 0, 0.07)', }} ref={resizableElementRef} > + {tabs} diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-selector.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-selector.tsx new file mode 100644 index 000000000..a7e21723a --- /dev/null +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/instance-selector.tsx @@ -0,0 +1,22 @@ +import { Menu, Typography } from 'antd'; +import React from 'react'; + +export const InstanceSelector = () => { + return ( + <> + + Let's select some instances! + + + + ); +}; diff --git a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx index 21e2d16fa..f57da07c3 100644 --- a/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx +++ b/src/management-system-v2/app/(dashboard)/[environmentId]/(automation)/executions/[processId]/process-deployment-view.tsx @@ -237,280 +237,290 @@ export default function ProcessDeploymentView({ }} > - - {/* Left group: Select Instance + Filter + Color */} - - setSelectedInstanceId(value)} + options={instances?.map((instance, idx) => ({ + value: instance.processInstanceId, + label: `${idx + 1}. Instance: ${new Date(instance.globalStartTime).toLocaleString()}`, + }))} + placeholder="Select an instance" + /> - - ', - key: '-2', - }, - ] - : []), - ...deploymentInfo.versions.map((version) => ({ - label: version.versionName || version.definitionName, - key: `${version.versionId}`, - disabled: false, - })), - ], - selectable: true, - onSelect: ({ key }) => { - const versionId = key === '-2' ? undefined : key; - setSelectedVersionId(versionId); - - const instances = getVersionInstances(deploymentInfo, versionId); - if (!instances.some((i) => i.processInstanceId === selectedInstanceId)) { - const youngestInstance = getYoungestInstance(instances); - setSelectedInstanceId(youngestInstance?.processInstanceId); - } - }, - selectedKeys: selectedVersionId ? [selectedVersionId] : [], - }} - > - - - - - - , - selectable: true, - onSelect: (item) => { - setSelectedColoring(item.key as ColorOptions); - }, - selectedKeys: [selectedColoring], - }} - > - + - )} - - {/* Activate/Deactivate button which is only shown when timer start events exist */} - {hasTimerStartEvents && ( - - - - + size={40} + style={{ backgroundColor: 'inherit' }} + /> + + )} + + + ', + key: '-2', + }, + ] + : []), + ...deployments.map(({ version }) => ({ + label: version.name, + key: `${version.id}`, + disabled: false, + })), + ], + selectable: true, + onSelect: ({ key }) => { + const versionId = key === '-2' ? undefined : key; + setSelectedVersionId(versionId); + + const instances = getVersionInstances(knownInstances, versionId); + if (!instances.some((i) => i.processInstanceId === selectedInstanceId)) { + const youngestInstance = getYoungestInstance(instances); + setSelectedInstanceId(youngestInstance?.processInstanceId); + } + }, + selectedKeys: selectedVersionId ? [selectedVersionId] : [], + }} + > + + + - {/* Middle group: Start + Activate/Deactivate */} - - {hasPlainStartEvents && ( - - + /> - + + )} + + + + + {enableInstanceCSVExport && ( + <> + + + + + + + + )} + {currentInstance && ( + + /> - - )} - {currentInstance && ( - + )} +