@@ -189,7 +189,7 @@ export default function TaskTesting({
189189 /** @type {React.MutableRefObject<import('../../types').ElementOutputVariables|null> } */
190190 const liveVariablesRef = useRef ( null ) ;
191191
192- const [ executionCompleted , setExecutionCompleted ] = useState ( false ) ;
192+ const [ selectedTabIndex , setSelectedTabIndex ] = useState ( 0 ) ;
193193
194194 // Initialize services once the injector is available
195195 useEffect ( ( ) => {
@@ -385,7 +385,6 @@ export default function TaskTesting({
385385 } ) ;
386386 }
387387
388- setExecutionCompleted ( true ) ;
389388 onTaskExecutionFinished ( element , result ) ;
390389 } ;
391390
@@ -464,7 +463,9 @@ export default function TaskTesting({
464463
465464 onTaskExecutionStarted ( element ) ;
466465
467- setExecutionCompleted ( false ) ;
466+ // Switch to Output tab to show execution progress and results
467+ setSelectedTabIndex ( 1 ) ;
468+
468469 setExecutionLog ( [ ] ) ;
469470 executionLogRef . current . reset ( ) ;
470471 setLiveVariables ( null ) ;
@@ -616,57 +617,42 @@ export default function TaskTesting({
616617 </ div >
617618 </ div >
618619 < div className = { `task-testing__container--body${ isTaskExecuting ? ' task-testing__container--body-executing' : '' } ` } >
619- { isTaskExecuting ? (
620- < Output
621- element = { element }
622- isConnectionConfigured = { isConnectionConfigured }
623- isTaskExecuting = { isTaskExecuting }
624- output = { output }
625- currentOperateUrl = { currentOperateUrl }
626- onResetOutput = { handleResetOutput }
627- taskExecutionStatus = { taskExecutionStatus || 'idle' }
628- executionLog = { executionLog }
629- tasklistBaseUrl = { tasklistBaseUrl }
630- liveVariables = { liveVariables }
631- />
632- ) : (
633- < TabContainer selectedIndex = { executionCompleted ? 1 : 0 } >
634- < TabContainer . Tab label = "Input" >
635- < Input
636- allOutputs = { allOutputs }
637- input = { input }
638- onErrorChange = { setInputError }
639- onResetInput = { handleResetInput }
640- onSetInput = { handleSetInput }
641- variablesForElement = { variablesForElement }
642- />
643- </ TabContainer . Tab >
644- < TabContainer . Tab label = "Output" >
645- < Output
646- element = { element }
647- isConnectionConfigured = { isConnectionConfigured }
648- isTaskExecuting = { isTaskExecuting }
649- output = { output }
650- currentOperateUrl = { currentOperateUrl }
651- onResetOutput = { handleResetOutput }
652- taskExecutionStatus = { taskExecutionStatus || 'idle' }
653- executionLog = { output ?. executionLog || [ ] }
654- tasklistBaseUrl = { tasklistBaseUrl }
655- />
656- </ TabContainer . Tab >
657- { pluginsProviderValue . getPlugins ( 'output.body.tab' )
658- . map ( plugin => ( {
659- label : plugin . label ,
660- content : plugin . render ?. ( { element, output, isTaskExecuting, executionLog } ) || plugin . children
661- } ) )
662- . filter ( tab => tab . content )
663- . map ( ( tab , index ) => (
664- < TabContainer . Tab key = { index } label = { tab . label } >
665- { tab . content }
666- </ TabContainer . Tab >
667- ) ) }
668- </ TabContainer >
669- ) }
620+ < Tabs selectedIndex = { selectedTabIndex } setSelectedIndex = { setSelectedTabIndex } >
621+ < Tabs . Tab label = "Input" disabled = { isTaskExecuting } >
622+ < Input
623+ allOutputs = { allOutputs }
624+ input = { input }
625+ onErrorChange = { setInputError }
626+ onResetInput = { handleResetInput }
627+ onSetInput = { handleSetInput }
628+ variablesForElement = { variablesForElement }
629+ />
630+ </ Tabs . Tab >
631+ < Tabs . Tab label = "Output" >
632+ < Output
633+ element = { element }
634+ isConnectionConfigured = { isConnectionConfigured }
635+ isTaskExecuting = { isTaskExecuting }
636+ output = { output }
637+ currentOperateUrl = { currentOperateUrl }
638+ onResetOutput = { handleResetOutput }
639+ taskExecutionStatus = { taskExecutionStatus || 'idle' }
640+ executionLog = { output ?. executionLog || [ ] }
641+ tasklistBaseUrl = { tasklistBaseUrl }
642+ />
643+ </ Tabs . Tab >
644+ { pluginsProviderValue . getPlugins ( 'output.body.tab' )
645+ . map ( plugin => ( {
646+ label : plugin . label ,
647+ content : plugin . render ?. ( { element, output, isTaskExecuting, executionLog } ) || plugin . children
648+ } ) )
649+ . filter ( tab => tab . content )
650+ . map ( ( tab , index ) => (
651+ < Tabs . Tab key = { index } label = { tab . label } disabled = { isTaskExecuting } >
652+ { tab . content }
653+ </ Tabs . Tab >
654+ ) ) }
655+ </ Tabs >
670656 </ div >
671657 </ div >
672658 { children }
@@ -738,17 +724,21 @@ function HeaderStatusText({ isTaskExecuting, isConnectionConfigured, taskExecuti
738724 return null ;
739725}
740726
741-
742- function TabContainer ( { selectedIndex = 0 , children } ) {
743- const [ activeIndex , setActiveIndex ] = useState ( selectedIndex ) ;
744-
745- useEffect ( ( ) => {
746- setActiveIndex ( selectedIndex ) ;
747- } , [ selectedIndex ] ) ;
748-
727+ /**
728+ * Simple Tabs component to switch between Input and Output views. The Tabs.Tab
729+ * component is used as a marker for the Tabs component to identify the tabs. It
730+ * does not render anything itself.
731+ *
732+ * @param {Object } props
733+ * @param {number } [props.selectedIndex=0] - The index of the initially selected tab.
734+ * @param {function } [props.setSelectedIndex] - Function to set the index of the selected tab.
735+ * @param {React.ReactNode } props.children - The tab elements.
736+ * @returns {React.ReactElement } The rendered Tabs component.
737+ */
738+ function Tabs ( { selectedIndex = 0 , setSelectedIndex = ( ) => { } , children } ) {
749739 const tabs = useMemo ( ( ) => {
750740 return /** @type {React.ReactElement[] } */ ( React . Children . toArray ( children ) . filter (
751- child => /** @type {React.ReactElement } */ ( child ) . type === TabItem
741+ child => /** @type {React.ReactElement } */ ( child ) . type === Tab
752742 ) ) ;
753743 } , [ children ] ) ;
754744
@@ -760,26 +750,33 @@ function TabContainer({ selectedIndex = 0, children }) {
760750 key = { index }
761751 type = "button"
762752 role = "tab"
763- className = { classNames ( 'task-testing-tabs__tab' , { 'task-testing-tabs__tab--active' : index === activeIndex } ) }
764- aria-selected = { index === activeIndex }
765- onClick = { ( ) => setActiveIndex ( index ) }
753+ className = { classNames ( 'task-testing-tabs__tab' , {
754+ 'task-testing-tabs__tab--active' : index === selectedIndex ,
755+ 'task-testing-tabs__tab--disabled' : tab . props . disabled
756+ } ) }
757+ aria-selected = { index === selectedIndex }
758+ onClick = { ( ) => setSelectedIndex ( index ) }
759+ disabled = { tab . props . disabled }
766760 >
767761 { tab . props . label }
768762 </ button >
769763 ) ) }
770764 </ div >
771765 < div className = "task-testing-tabs__panel" >
772- { tabs [ activeIndex ] ?. props . children }
766+ { tabs [ selectedIndex ] ?. props . children }
773767 </ div >
774768 </ >
775769 ) ;
776770}
777771
778772/**
779- * @param {{ label?: string, children?: React.ReactNode } } _props
773+ * This component is used as a marker for the Tabs component to identify the
774+ * tabs. It does not render anything itself.
775+ *
776+ * @param {{ label?: string, children?: React.ReactNode, disabled?: boolean } } _props
780777 */
781- function TabItem ( _props ) {
778+ function Tab ( _props ) {
782779 return null ;
783780}
784781
785- TabContainer . Tab = TabItem ;
782+ Tabs . Tab = Tab ;
0 commit comments