Visualize iterator sub step's output by iteration index (#14747)

## Demo


https://github.com/user-attachments/assets/27afff85-4f33-4e91-b28a-3dc868bb9ad7

## With several sub steps

> [!NOTE]
> Please note that as I created the component state, the iteration index
will be different for every step of a workflow run. We might have one
component state instance per iterator node. We can implement it in
another PR if we think it's the way to go.


https://github.com/user-attachments/assets/6b8cd06d-9051-474d-b438-dd6155cc3810
This commit is contained in:
Baptiste Devessier
2025-09-29 15:40:42 +02:00
committed by GitHub
parent 358ab54690
commit 9b88cee1ce
15 changed files with 502 additions and 135 deletions
@@ -1,3 +1,4 @@
import { CommandMenuWorkflowRunStepContentComponentInstanceContext } from '@/command-menu/pages/workflow/step/view-run/states/contexts/CommandMenuWorkflowRunStepContentComponentInstanceContext';
import { getIsInputTabDisabled } from '@/command-menu/pages/workflow/step/view-run/utils/getIsInputTabDisabled';
import { getIsOutputTabDisabled } from '@/command-menu/pages/workflow/step/view-run/utils/getIsOutputTabDisabled';
import { getShouldFocusNodeTab } from '@/command-menu/pages/workflow/step/view-run/utils/getShouldFocusNodeTab';
@@ -12,6 +13,7 @@ import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun';
import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow';
import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow';
import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState';
import { WorkflowIteratorSubStepSwitcher } from '@/workflow/workflow-steps/components/WorkflowIteratorSubStepSwitcher';
import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail';
import { WorkflowRunStepNodeDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepNodeDetail';
import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail';
@@ -112,46 +114,54 @@ export const CommandMenuWorkflowRunViewStepContent = () => {
];
return (
<StyledContainer>
{shouldFocusNodeTab ? (
<WorkflowRunStepNodeDetail
stepId={workflowSelectedNode}
trigger={flow.trigger}
steps={flow.steps}
stepExecutionStatus={stepExecutionStatus}
/>
) : (
<>
<StyledTabList
tabs={tabs}
behaveAsLinks={false}
componentInstanceId={commandMenuPageComponentInstance.instanceId}
<CommandMenuWorkflowRunStepContentComponentInstanceContext.Provider
value={{
instanceId: `${workflowRunId}_${workflowSelectedNode}`,
}}
>
<StyledContainer>
{shouldFocusNodeTab ? (
<WorkflowRunStepNodeDetail
stepId={workflowSelectedNode}
trigger={flow.trigger}
steps={flow.steps}
stepExecutionStatus={stepExecutionStatus}
/>
{activeTabId === WorkflowRunTabId.OUTPUT ? (
<WorkflowRunStepOutputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
) : (
<>
<StyledTabList
tabs={tabs}
behaveAsLinks={false}
componentInstanceId={commandMenuPageComponentInstance.instanceId}
/>
) : null}
{activeTabId === WorkflowRunTabId.NODE ? (
<WorkflowRunStepNodeDetail
stepId={workflowSelectedNode}
trigger={flow.trigger}
steps={flow.steps}
stepExecutionStatus={stepExecutionStatus}
/>
) : null}
{activeTabId === WorkflowRunTabId.OUTPUT ? (
<WorkflowRunStepOutputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
/>
) : null}
{activeTabId === WorkflowRunTabId.INPUT ? (
<WorkflowRunStepInputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
/>
) : null}
</>
)}
</StyledContainer>
{activeTabId === WorkflowRunTabId.NODE ? (
<WorkflowRunStepNodeDetail
stepId={workflowSelectedNode}
trigger={flow.trigger}
steps={flow.steps}
stepExecutionStatus={stepExecutionStatus}
/>
) : null}
{activeTabId === WorkflowRunTabId.INPUT ? (
<WorkflowRunStepInputDetail
key={workflowSelectedNode}
stepId={workflowSelectedNode}
/>
) : null}
<WorkflowIteratorSubStepSwitcher stepId={workflowSelectedNode} />
</>
)}
</StyledContainer>
</CommandMenuWorkflowRunStepContentComponentInstanceContext.Provider>
);
};
@@ -0,0 +1,6 @@
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
export const CommandMenuWorkflowRunStepContentComponentInstanceContext =
createComponentInstanceContext({
instanceId: '',
});
@@ -0,0 +1,10 @@
import { CommandMenuWorkflowRunStepContentComponentInstanceContext } from '@/command-menu/pages/workflow/step/view-run/states/contexts/CommandMenuWorkflowRunStepContentComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
export const workflowRunIteratorSubStepIterationIndexComponentState =
createComponentState<number>({
key: 'workflowRunIteratorSubStepIterationIndexComponentState',
defaultValue: 0,
componentInstanceContext:
CommandMenuWorkflowRunStepContentComponentInstanceContext,
});