11import { useFileUploadManager } from './FileUploadManager' ;
22import FolderExplorerHeader from './FolderExplorerHeader' ;
33import VFolderNodeDescription from './VFolderNodeDescription' ;
4- import { Alert , Divider , Grid , Splitter , theme } from 'antd' ;
4+ import { Alert , Divider , Grid , Skeleton , Splitter , theme } from 'antd' ;
55import { createStyles } from 'antd-style' ;
66import { RcFile } from 'antd/es/upload' ;
77import {
@@ -12,7 +12,7 @@ import {
1212 toGlobalId ,
1313} from 'backend.ai-ui' ;
1414import _ from 'lodash' ;
15- import { useEffect , useRef } from 'react' ;
15+ import { Suspense , useDeferredValue , useEffect , useRef } from 'react' ;
1616import { useTranslation } from 'react-i18next' ;
1717import { graphql , useLazyLoadQuery } from 'react-relay' ;
1818import { FolderExplorerModalQuery } from 'src/__generated__/FolderExplorerModalQuery.graphql' ;
@@ -54,7 +54,6 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
5454 const { xl } = Grid . useBreakpoint ( ) ;
5555 const { styles } = useStyles ( ) ;
5656 const folderExplorerRef = useRef < FolderExplorerElement > ( null ) ;
57- const { uploadStatus, uploadFiles } = useFileUploadManager ( vfolderID ) ;
5857 const [ fetchKey , updateFetchKey ] = useFetchKey ( ) ;
5958 const baiClient = useSuspendedBackendaiClient ( ) ;
6059 const currentDomain = useCurrentDomainValue ( ) ;
@@ -68,12 +67,7 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
6867 ) ;
6968 const bodyRef = useRef < HTMLDivElement | null > ( null ) ;
7069
71- useEffect ( ( ) => {
72- if ( uploadStatus && _ . isEmpty ( uploadStatus ?. pendingFiles ) ) {
73- updateFetchKey ( ) ;
74- }
75- } , [ uploadStatus , updateFetchKey ] ) ;
76-
70+ const deferredOpen = useDeferredValue ( modalProps . open ) ;
7771 const { vfolder_node } = useLazyLoadQuery < FolderExplorerModalQuery > (
7872 graphql `
7973 query FolderExplorerModalQuery($vfolderGlobalId: String!) {
@@ -82,6 +76,8 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
8276 unmanaged_path @since(version: "25.04.0")
8377 permissions
8478 host
79+ id
80+ name
8581 ...FolderExplorerHeaderFragment
8682 ...VFolderNodeDescriptionFragment
8783 ...VFolderNameTitleNodeFragment
@@ -90,9 +86,20 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
9086 ` ,
9187 { vfolderGlobalId : toGlobalId ( 'VirtualFolderNode' , vfolderID ) } ,
9288 {
93- fetchPolicy : modalProps . open ? 'network-only' : 'store-only' ,
89+ // Only fetch when both deferredOpen and modalProps.open are true to prevent unnecessary requests during React transitions
90+ fetchPolicy :
91+ deferredOpen && modalProps . open ? 'network-only' : 'store-only' ,
9492 } ,
9593 ) ;
94+ const { uploadStatus, uploadFiles } = useFileUploadManager (
95+ vfolder_node ?. id ,
96+ vfolder_node ?. name || undefined ,
97+ ) ;
98+ useEffect ( ( ) => {
99+ if ( uploadStatus && _ . isEmpty ( uploadStatus ?. pendingFiles ) ) {
100+ updateFetchKey ( ) ;
101+ }
102+ } , [ uploadStatus , updateFetchKey ] ) ;
96103
97104 const hasDownloadContentPermission = _ . includes (
98105 unitedAllowedPermissionByVolume [ vfolder_node ?. host ?? '' ] ,
@@ -149,10 +156,16 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
149156 < BAIModal
150157 className = { styles . baiModalHeader }
151158 width = { '90%' }
152- centered
153159 keyboard
154160 destroyOnHidden
155161 footer = { null }
162+ // loading={true}
163+ style = { { maxWidth : '1600px' } }
164+ styles = { {
165+ body : {
166+ height : '100vh' ,
167+ } ,
168+ } }
156169 title = {
157170 vfolder_node ? (
158171 < FolderExplorerHeader
@@ -171,58 +184,69 @@ const FolderExplorerModal: React.FC<FolderExplorerProps> = ({
171184 } }
172185 { ...modalProps }
173186 >
174- < BAIFlex direction = "column" gap = { 'lg' } align = "stretch" >
175- { ! vfolder_node ? (
176- < Alert
177- message = { t ( 'explorer.FolderNotFoundOrNoAccess' ) }
178- type = "error"
179- showIcon
180- />
181- ) : hasNoPermissions ? (
182- < Alert message = { t ( 'explorer.NoPermissions' ) } type = "error" showIcon />
183- ) : currentProject ?. id !== vfolder_node ?. group &&
184- ! ! vfolder_node ?. group ? (
185- < Alert message = { t ( 'data.NotInProject' ) } type = "warning" showIcon />
186- ) : null }
187-
188- { xl ? (
189- < Splitter
190- // Force re-render component when xl breakpoint changes to reset panel sizes
191- // This ensures defaultSize is recalculated based on current screen size
192- key = { xl ? 'large' : 'small' }
193- style = { {
194- gap : token . size ,
195- // maxHeight: 'calc(100vh - 220px)',
196- } }
197- layout = { xl ? 'horizontal' : 'vertical' }
198- >
199- < Splitter . Panel resizable = { false } >
200- { fileExplorerElement }
201- </ Splitter . Panel >
202- < Splitter . Panel defaultSize = { 500 } >
203- { vFolderDescriptionElement }
204- </ Splitter . Panel >
205- </ Splitter >
187+ < Suspense fallback = { < Skeleton active /> } >
188+ { /* Use <Skeleton/> instead of using `loading` prop because layout align issue. */ }
189+ { deferredOpen !== modalProps . open ? (
190+ < Skeleton active />
206191 ) : (
207- < BAIFlex direction = "column" align = "stretch" >
208- { fileExplorerElement }
209- < Divider
210- style = { {
211- borderColor : token . colorBorderSecondary ,
212- } }
213- />
214- { vFolderDescriptionElement }
192+ < BAIFlex direction = "column" gap = { 'lg' } align = "stretch" >
193+ { ! vfolder_node ? (
194+ < Alert
195+ message = { t ( 'explorer.FolderNotFoundOrNoAccess' ) }
196+ type = "error"
197+ showIcon
198+ />
199+ ) : hasNoPermissions ? (
200+ < Alert
201+ message = { t ( 'explorer.NoPermissions' ) }
202+ type = "error"
203+ showIcon
204+ />
205+ ) : currentProject ?. id !== vfolder_node ?. group &&
206+ ! ! vfolder_node ?. group ? (
207+ < Alert message = { t ( 'data.NotInProject' ) } type = "warning" showIcon />
208+ ) : null }
209+
210+ { xl ? (
211+ < Splitter
212+ // Force re-render component when xl breakpoint changes to reset panel sizes
213+ // This ensures defaultSize is recalculated based on current screen size
214+ key = { xl ? 'large' : 'small' }
215+ style = { {
216+ gap : token . size ,
217+ // maxHeight: 'calc(100vh - 220px)',
218+ } }
219+ layout = { xl ? 'horizontal' : 'vertical' }
220+ >
221+ < Splitter . Panel resizable = { false } >
222+ { fileExplorerElement }
223+ </ Splitter . Panel >
224+ < Splitter . Panel defaultSize = { 500 } >
225+ { vFolderDescriptionElement }
226+ </ Splitter . Panel >
227+ </ Splitter >
228+ ) : (
229+ < BAIFlex direction = "column" align = "stretch" >
230+ { fileExplorerElement }
231+ < Divider
232+ style = { {
233+ borderColor : token . colorBorderSecondary ,
234+ } }
235+ />
236+ { vFolderDescriptionElement }
237+ </ BAIFlex >
238+ ) }
239+ < div style = { { display : 'none' } } >
240+ { /* @ts -ignore TODO: delete below after https://lablup.atlassian.net/browse/FR-1150 */ }
241+ < backend-ai-folder-explorer
242+ ref = { folderExplorerRef }
243+ active
244+ vfolderID = { vfolderID }
245+ />
246+ </ div >
215247 </ BAIFlex >
216248 ) }
217- < div style = { { display : 'none' } } >
218- { /* @ts -ignore TODO: delete below after https://lablup.atlassian.net/browse/FR-1150 */ }
219- < backend-ai-folder-explorer
220- ref = { folderExplorerRef }
221- active
222- vfolderID = { vfolderID }
223- />
224- </ div >
225- </ BAIFlex >
249+ </ Suspense >
226250 </ BAIModal >
227251 ) ;
228252} ;
0 commit comments