Skip to content

Commit c6915f4

Browse files
committed
fix(FR-1527): prevent session modals from reopening during automatic refresh (#4361)
Resolves #4351 ([FR-1527](https://lablup.atlassian.net/browse/FR-1527)) ## Problem Internal modals in the session detail panel keep reopening each time the panel is automatically refreshed, causing a disruptive user experience with multiple instances of the same modal appearing without user interaction. ## Solution Restructured the SessionActionButtons component to move modals outside the wrapper component. This prevents the modals from being recreated and reopened during automatic panel refresh cycles. ### Changes Made: - Moved modal components (AppLauncherModal, ContainerLogModal, ContainerCommitModal, TerminateSessionModal) outside the Wrapper component - Wrapped modals in a Suspense fallback to ensure proper loading behavior - Maintained all existing functionality while fixing the modal reopening issue ### Testing: - ✅ Modal functionality remains intact - ✅ Modals no longer reopen during automatic refresh - ✅ All action buttons continue to work as expected - ✅ Pre-commit hooks passed (linting/formatting) ## Impact This fix resolves the bug described in FR-1527 where users experienced unexpected modal reopening during automatic session panel refreshes, improving the overall user experience when working with session details. [FR-1527]: https://lablup.atlassian.net/browse/FR-1527?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent cf4bbab commit c6915f4

File tree

1 file changed

+113
-100
lines changed

1 file changed

+113
-100
lines changed

react/src/components/ComputeSessionNodeItems/SessionActionButtons.tsx

Lines changed: 113 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -124,71 +124,59 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
124124
const isButtonTitleMode = size === 'small';
125125

126126
return session ? (
127-
<Wrapper>
128-
{isVisible('appLauncher') && (
129-
<>
130-
<Tooltip
131-
title={isButtonTitleMode ? undefined : t('session.SeeAppDialog')}
132-
>
133-
<Button
134-
size={size}
135-
type="primary"
136-
disabled={
137-
!isAppSupported(session) || !isActive(session) || !isOwner
138-
}
139-
icon={<BAIAppIcon />}
140-
onClick={() => {
141-
onAction?.('appLauncher');
142-
setOpenAppLauncherModal(true);
143-
}}
144-
title={isButtonTitleMode ? t('session.SeeAppDialog') : undefined}
145-
/>
146-
</Tooltip>
147-
<Suspense fallback={null}>
148-
<AppLauncherModal
149-
sessionFrgmt={session}
150-
open={openAppLauncherModal}
151-
onRequestClose={() => {
152-
setOpenAppLauncherModal(false);
153-
}}
154-
/>
155-
</Suspense>
156-
</>
157-
)}
158-
{isVisible('terminal') && (
159-
<>
160-
<Tooltip
161-
title={
162-
isButtonTitleMode ? undefined : t('session.ExecuteTerminalApp')
163-
}
164-
>
165-
<Button
166-
size={size}
167-
disabled={
168-
!isAppSupported(session) || !isActive(session) || !isOwner
169-
}
170-
icon={<BAITerminalAppIcon />}
171-
onClick={() => {
172-
onAction?.('terminal');
173-
appLauncher.runTerminal(session?.row_id);
174-
}}
127+
<>
128+
<Wrapper>
129+
{isVisible('appLauncher') && (
130+
<>
131+
<Tooltip
132+
title={isButtonTitleMode ? undefined : t('session.SeeAppDialog')}
133+
>
134+
<Button
135+
size={size}
136+
type="primary"
137+
disabled={
138+
!isAppSupported(session) || !isActive(session) || !isOwner
139+
}
140+
icon={<BAIAppIcon />}
141+
onClick={() => {
142+
onAction?.('appLauncher');
143+
setOpenAppLauncherModal(true);
144+
}}
145+
title={
146+
isButtonTitleMode ? t('session.SeeAppDialog') : undefined
147+
}
148+
/>
149+
</Tooltip>
150+
</>
151+
)}
152+
{isVisible('terminal') && (
153+
<>
154+
<Tooltip
175155
title={
176-
isButtonTitleMode ? t('session.ExecuteTerminalApp') : undefined
156+
isButtonTitleMode ? undefined : t('session.ExecuteTerminalApp')
177157
}
178-
/>
179-
</Tooltip>
180-
<TerminateSessionModal
181-
sessionFrgmts={[session]}
182-
open={openTerminateModal}
183-
onRequestClose={() => {
184-
setOpenTerminateModal(false);
185-
}}
186-
/>
187-
</>
188-
)}
158+
>
159+
<Button
160+
size={size}
161+
disabled={
162+
!isAppSupported(session) || !isActive(session) || !isOwner
163+
}
164+
icon={<BAITerminalAppIcon />}
165+
onClick={() => {
166+
onAction?.('terminal');
167+
appLauncher.runTerminal(session?.row_id);
168+
}}
169+
title={
170+
isButtonTitleMode
171+
? t('session.ExecuteTerminalApp')
172+
: undefined
173+
}
174+
/>
175+
</Tooltip>
176+
</>
177+
)}
189178

190-
{isVisible('logs') && (
191-
<>
179+
{isVisible('logs') && (
192180
<Tooltip
193181
title={
194182
isButtonTitleMode ? undefined : t('session.SeeContainerLogs')
@@ -206,20 +194,9 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
206194
}
207195
/>
208196
</Tooltip>
209-
<BAIUnmountAfterClose>
210-
<ContainerLogModal
211-
sessionFrgmt={session}
212-
open={openLogModal}
213-
onCancel={() => {
214-
setOpenLogModal(false);
215-
}}
216-
/>
217-
</BAIUnmountAfterClose>
218-
</>
219-
)}
197+
)}
220198

221-
{isVisible('containerCommit') && (
222-
<>
199+
{isVisible('containerCommit') && (
223200
<Tooltip
224201
title={
225202
isButtonTitleMode
@@ -242,38 +219,74 @@ const SessionActionButtons: React.FC<SessionActionButtonsProps> = ({
242219
}
243220
/>
244221
</Tooltip>
222+
)}
223+
{isVisible('terminate') && (
224+
<Tooltip
225+
title={
226+
isButtonTitleMode ? undefined : t('session.TerminateSession')
227+
}
228+
>
229+
<Button
230+
size={size}
231+
disabled={!isActive(session)}
232+
icon={
233+
<BAITerminateIcon
234+
style={{
235+
color: isActive(session) ? token.colorError : undefined,
236+
}}
237+
/>
238+
}
239+
onClick={() => {
240+
onAction?.('terminate');
241+
setOpenTerminateModal(true);
242+
}}
243+
title={
244+
isButtonTitleMode ? t('session.TerminateSession') : undefined
245+
}
246+
/>
247+
</Tooltip>
248+
)}
249+
</Wrapper>
250+
251+
<Suspense fallback={null}>
252+
{isVisible('appLauncher') && (
253+
<AppLauncherModal
254+
sessionFrgmt={session}
255+
open={openAppLauncherModal}
256+
onRequestClose={() => {
257+
setOpenAppLauncherModal(false);
258+
}}
259+
/>
260+
)}
261+
{isVisible('logs') && (
262+
<BAIUnmountAfterClose>
263+
<ContainerLogModal
264+
sessionFrgmt={session}
265+
open={openLogModal}
266+
onCancel={() => {
267+
setOpenLogModal(false);
268+
}}
269+
/>
270+
</BAIUnmountAfterClose>
271+
)}
272+
{isVisible('containerCommit') && (
245273
<ContainerCommitModal
246274
sessionFrgmt={session}
247275
open={openContainerCommitModal}
248276
onRequestClose={() => setOpenContainerCommitModal(false)}
249277
/>
250-
</>
251-
)}
252-
{isVisible('terminate') && (
253-
<Tooltip
254-
title={isButtonTitleMode ? undefined : t('session.TerminateSession')}
255-
>
256-
<Button
257-
size={size}
258-
disabled={!isActive(session)}
259-
icon={
260-
<BAITerminateIcon
261-
style={{
262-
color: isActive(session) ? token.colorError : undefined,
263-
}}
264-
/>
265-
}
266-
onClick={() => {
267-
onAction?.('terminate');
268-
setOpenTerminateModal(true);
278+
)}
279+
{isVisible('terminate') && (
280+
<TerminateSessionModal
281+
sessionFrgmts={[session]}
282+
open={openTerminateModal}
283+
onRequestClose={() => {
284+
setOpenTerminateModal(false);
269285
}}
270-
title={
271-
isButtonTitleMode ? t('session.TerminateSession') : undefined
272-
}
273286
/>
274-
</Tooltip>
275-
)}
276-
</Wrapper>
287+
)}
288+
</Suspense>
289+
</>
277290
) : (
278291
[]
279292
);

0 commit comments

Comments
 (0)