Skip to content

Commit c699900

Browse files
committed
tabs fix
1 parent 20cdb4a commit c699900

File tree

2 files changed

+71
-70
lines changed

2 files changed

+71
-70
lines changed

lib/components/TaskTesting/TaskTesting.js

Lines changed: 67 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

lib/style/style.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@
6767
color: #161616;
6868
border-bottom-color: #0f62fe;
6969
}
70+
71+
&.task-testing-tabs__tab--disabled {
72+
color: #8d8d8d;
73+
}
7074
}
7175

7276
.task-testing-tabs__panel {

0 commit comments

Comments
 (0)