1
1
import React , { createContext , useEffect , useState } from 'react' ;
2
2
import { Bullseye , Spinner } from '@patternfly/react-core' ;
3
3
import { ModularArchConfig , Namespace } from '~/types' ;
4
- import { DeploymentMode , PlatformMode } from '~/utilities' ;
5
- import { useFetchState , FetchStateCallbackPromise } from '~/utilities/useFetchState' ;
6
- import { getNamespaces } from '~/api/k8s' ;
4
+ import { kubeflowScriptLoader , kubeflowNamespaceLoader } from '~/utilities' ;
5
+ import { useNamespacesWithConfig } from '~/hooks/useNamespaces' ;
7
6
8
7
export type ModularArchContextType = {
9
8
config : ModularArchConfig ;
@@ -25,128 +24,75 @@ type ModularArchContextProviderProps = {
25
24
26
25
export const ModularArchContext = createContext < ModularArchContextType | undefined > ( undefined ) ;
27
26
28
- declare global {
29
- interface Window {
30
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
- centraldashboard : any ;
32
- }
33
- }
34
-
35
- const loadScript = ( src : string , onLoad : ( ) => void , onError : ( ) => void ) => {
36
- const script = document . createElement ( 'script' ) ;
37
- script . src = src ;
38
- script . async = true ;
39
- script . onload = onLoad ;
40
- script . onerror = onError ;
41
- document . head . appendChild ( script ) ;
42
- } ;
43
-
44
27
export const ModularArchContextProvider : React . FC < ModularArchContextProviderProps > = ( {
45
28
children,
46
29
config,
47
30
} ) => {
48
- const { deploymentMode, platformMode } = config ;
31
+ const { deploymentMode, platformMode, mandatoryNamespace } = config ;
49
32
50
- // Script loading state
51
33
const [ scriptLoaded , setScriptLoaded ] = useState ( false ) ;
34
+ const [ preferredNamespace , setPreferredNamespace ] = useState < Namespace | undefined > ( undefined ) ;
35
+ const [ initializationError , setInitializationError ] = useState < Error > ( ) ;
52
36
53
37
// Namespace-related state
54
- const modArchConfig = React . useMemo (
55
- ( ) => ( {
56
- BFF_API_VERSION : config . BFF_API_VERSION ,
57
- URL_PREFIX : config . URL_PREFIX ,
58
- } ) ,
59
- [ config . BFF_API_VERSION , config . URL_PREFIX ] ,
60
- ) ;
61
-
62
- const listNamespaces = React . useMemo ( ( ) => getNamespaces ( '' , modArchConfig ) , [ modArchConfig ] ) ;
63
-
64
- const callback = React . useCallback < FetchStateCallbackPromise < Namespace [ ] > > (
65
- ( opts ) => {
66
- if ( ! ( deploymentMode === DeploymentMode . Standalone ) ) {
67
- return Promise . resolve ( [ ] ) ;
68
- }
69
- return listNamespaces ( opts ) ;
70
- } ,
71
- [ deploymentMode , listNamespaces ] ,
72
- ) ;
73
-
74
- const [ unsortedNamespaces , isLoaded , error ] = useFetchState < Namespace [ ] > ( callback , [ ] ) ;
38
+ const [ unsortedNamespaces , isLoaded , error ] = useNamespacesWithConfig ( config ) ;
75
39
const namespaces = React . useMemo (
76
40
( ) => unsortedNamespaces . toSorted ( ( a : Namespace , b : Namespace ) => a . name . localeCompare ( b . name ) ) ,
77
41
[ unsortedNamespaces ] ,
78
42
) ;
79
- const [ preferredNamespace , setPreferredNamespace ] = useState < Namespace | undefined > ( undefined ) ;
80
- const [ initializationError , setInitializationError ] = useState < Error > ( ) ;
81
43
82
44
const firstNamespace = namespaces . length > 0 ? namespaces [ 0 ] : null ;
83
45
84
- // Script loader for kubeflow integration
85
- useEffect ( ( ) => {
86
- const scriptUrl = '/dashboard_lib.bundle.js' ;
87
-
88
- if (
89
- ! ( deploymentMode === DeploymentMode . Integrated ) ||
90
- ! ( platformMode === PlatformMode . Kubeflow )
91
- ) {
92
- // eslint-disable-next-line no-console
93
- console . warn ( 'ModularArchContext: Script not loaded, only needed for kubeflow integration' ) ;
94
- setScriptLoaded ( true ) ;
95
- return ;
46
+ // Set preferred namespace based on mandatory namespace or first available namespace
47
+ const defaultPreferredNamespace = React . useMemo ( ( ) => {
48
+ if ( mandatoryNamespace ) {
49
+ return { name : mandatoryNamespace } ;
96
50
}
51
+ return firstNamespace ;
52
+ } , [ mandatoryNamespace , firstNamespace ] ) ;
97
53
98
- fetch ( scriptUrl , { method : 'HEAD' } )
99
- . then ( ( response ) => {
100
- if ( response . ok ) {
101
- loadScript (
102
- scriptUrl ,
103
- ( ) => setScriptLoaded ( true ) ,
104
- // eslint-disable-next-line no-console
105
- ( ) => console . error ( 'Failed to load the script' ) ,
106
- ) ;
107
- } else {
108
- // eslint-disable-next-line no-console
109
- console . warn ( 'Script not found' ) ;
110
- setScriptLoaded ( true ) ;
111
- }
112
- } )
113
- // eslint-disable-next-line no-console
114
- . catch ( ( err ) => console . error ( 'Error checking script existence' , err ) ) ;
54
+ // Script loader for kubeflow integration
55
+ useEffect ( ( ) => {
56
+ kubeflowScriptLoader (
57
+ deploymentMode ,
58
+ platformMode ,
59
+ ( ) => setScriptLoaded ( true ) ,
60
+ ( scriptError ) => {
61
+ // eslint-disable-next-line no-console
62
+ console . error ( 'Error loading kubeflow script:' , scriptError ) ;
63
+ setScriptLoaded ( true ) ; // Still set to true to not block the UI
64
+ } ,
65
+ ) ;
115
66
} , [ deploymentMode , platformMode ] ) ;
116
67
117
68
// Namespace selector for kubeflow integration
118
69
useEffect ( ( ) => {
119
- if (
120
- deploymentMode === DeploymentMode . Integrated &&
121
- platformMode === PlatformMode . Kubeflow &&
122
- scriptLoaded
123
- ) {
124
- // Initialize the central dashboard client
125
- try {
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
- window . centraldashboard . CentralDashboardEventHandler . init ( ( cdeh : any ) => {
128
- // eslint-disable-next-line no-param-reassign
129
- cdeh . onNamespaceSelected = ( newNamespace : string ) => {
130
- setPreferredNamespace ( { name : newNamespace } ) ;
131
- } ;
132
- } ) ;
133
- } catch ( err ) {
134
- /* eslint-disable no-console */
135
- console . error ( 'Failed to initialize central dashboard client' , err ) ;
136
- if ( err instanceof Error ) {
137
- setInitializationError ( err ) ;
138
- }
139
- }
70
+ // If mandatory namespace is set, don't use kubeflow namespace loader
71
+ if ( mandatoryNamespace ) {
72
+ return ;
140
73
}
141
- } , [ deploymentMode , platformMode , scriptLoaded ] ) ;
74
+
75
+ kubeflowNamespaceLoader (
76
+ deploymentMode ,
77
+ platformMode ,
78
+ scriptLoaded ,
79
+ ( newNamespace : string ) => {
80
+ setPreferredNamespace ( { name : newNamespace } ) ;
81
+ } ,
82
+ ( err : Error ) => {
83
+ setInitializationError ( err ) ;
84
+ } ,
85
+ mandatoryNamespace ,
86
+ ) ;
87
+ } , [ deploymentMode , platformMode , scriptLoaded , mandatoryNamespace ] ) ;
142
88
143
89
const contextValue = React . useMemo (
144
90
( ) => ( {
145
91
config,
146
92
namespacesLoaded : isLoaded ,
147
93
namespacesLoadError : error ,
148
94
namespaces,
149
- preferredNamespace : preferredNamespace ?? firstNamespace ?? undefined ,
95
+ preferredNamespace : preferredNamespace ?? defaultPreferredNamespace ?? undefined ,
150
96
updatePreferredNamespace : setPreferredNamespace ,
151
97
initializationError,
152
98
scriptLoaded,
@@ -157,7 +103,7 @@ export const ModularArchContextProvider: React.FC<ModularArchContextProviderProp
157
103
error ,
158
104
namespaces ,
159
105
preferredNamespace ,
160
- firstNamespace ,
106
+ defaultPreferredNamespace ,
161
107
initializationError ,
162
108
scriptLoaded ,
163
109
] ,
0 commit comments