Skip to content

Commit b8cf905

Browse files
committed
feat(frontend): create theme provider
Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com> fix UI loading bug Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com> rename ThemeProvider, remove conditional rendering for upstream Signed-off-by: Jenny <32821331+jenny-s51@users.noreply.github.com> remove unused imports
1 parent 5d8e9e1 commit b8cf905

23 files changed

Lines changed: 169 additions & 368 deletions

clients/ui/frontend/src/app/App.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from '@patternfly/react-core';
1515
import ToastNotifications from '~/shared/components/ToastNotifications';
1616
import { useSettings } from '~/shared/hooks/useSettings';
17-
import { isMUITheme, Theme, AUTH_HEADER, MOCK_AUTH, isStandalone } from '~/shared/utilities/const';
17+
import { AUTH_HEADER, MOCK_AUTH, isStandalone } from '~/shared/utilities/const';
1818
import { logout } from '~/shared/utilities/appUtils';
1919
import { NamespaceSelectorContext } from '~/shared/context/NamespaceSelectorContext';
2020
import NavSidebar from './NavSidebar';
@@ -36,15 +36,6 @@ const App: React.FC = () => {
3636

3737
const username = userSettings?.userId;
3838

39-
React.useEffect(() => {
40-
// Apply the theme based on the value of STYLE_THEME
41-
if (isMUITheme()) {
42-
document.documentElement.classList.add(Theme.MUI);
43-
} else {
44-
document.documentElement.classList.remove(Theme.MUI);
45-
}
46-
}, []);
47-
4839
React.useEffect(() => {
4940
if (MOCK_AUTH && username) {
5041
localStorage.setItem(AUTH_HEADER, username);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as React from 'react';
2+
3+
type ThemeContextProps = {
4+
isMUITheme: boolean;
5+
};
6+
7+
export const ThemeContext = React.createContext({
8+
isMUITheme: false,
9+
});
10+
11+
export const useThemeContext = (): ThemeContextProps => React.useContext(ThemeContext);

clients/ui/frontend/src/app/NavBar.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
import { SimpleSelect } from '@patternfly/react-templates';
2222
import { BarsIcon } from '@patternfly/react-icons';
2323
import { NamespaceSelectorContext } from '~/shared/context/NamespaceSelectorContext';
24-
import { isMUITheme } from '~/shared/utilities/const';
2524
import logoDarkTheme from '~/images/logo-dark-theme.svg';
2625

2726
interface NavBarProps {
@@ -60,15 +59,11 @@ const NavBar: React.FC<NavBarProps> = ({ username, onLogout }) => {
6059
<BarsIcon />
6160
</PageToggleButton>
6261
</MastheadToggle>
63-
{!isMUITheme() ? (
64-
<MastheadBrand>
65-
<MastheadLogo component="a">
66-
<Brand src={logoDarkTheme} alt="Kubeflow" heights={{ default: '36px' }} />
67-
</MastheadLogo>
68-
</MastheadBrand>
69-
) : (
70-
''
71-
)}
62+
<MastheadBrand>
63+
<MastheadLogo component="a">
64+
<Brand src={logoDarkTheme} alt="Kubeflow" heights={{ default: '36px' }} />
65+
</MastheadLogo>
66+
</MastheadBrand>
7267
</MastheadMain>
7368
<MastheadContent>
7469
<Toolbar>

clients/ui/frontend/src/app/NavSidebar.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
PageSidebar,
1010
PageSidebarBody,
1111
} from '@patternfly/react-core';
12-
import { isMUITheme, LOGO_LIGHT } from '~/shared/utilities/const';
12+
import { LOGO_LIGHT } from '~/shared/utilities/const';
1313
import { useNavData, isNavDataGroup, NavDataHref, NavDataGroup } from './AppRoutes';
1414

1515
const NavHref: React.FC<{ item: NavDataHref }> = ({ item }) => (
@@ -48,17 +48,13 @@ const NavSidebar: React.FC = () => {
4848
<PageSidebarBody>
4949
<Nav id="nav-primary-simple">
5050
<NavList id="nav-list-simple">
51-
{isMUITheme() ? (
52-
<NavItem>
53-
<Brand
54-
className="kubeflow_brand"
55-
src={`${window.location.origin}/images/${LOGO_LIGHT}`}
56-
alt="Kubeflow Logo"
57-
/>
58-
</NavItem>
59-
) : (
60-
''
61-
)}
51+
<NavItem>
52+
<Brand
53+
className="kubeflow_brand"
54+
src={`${window.location.origin}/images/${LOGO_LIGHT}`}
55+
alt="Kubeflow Logo"
56+
/>
57+
</NavItem>
6258
{navData.map((item) =>
6359
isNavDataGroup(item) ? (
6460
<NavGroup key={item.label} item={item} />
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import * as React from 'react';
2+
import { createTheme } from '@mui/material';
3+
import { ThemeProvider as MUIThemeProvider } from '@mui/material/styles';
4+
import { isMUITheme, Theme } from '~/shared/utilities/const';
5+
import { ThemeContext } from './MUIThemeContext';
6+
7+
type ThemeProviderProps = {
8+
children: React.ReactNode;
9+
};
10+
11+
const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
12+
const themeValue = React.useMemo(() => ({ isMUITheme: isMUITheme() }), []);
13+
const createMUITheme = React.useMemo(() => createTheme({ cssVariables: true }), []);
14+
15+
React.useEffect(() => {
16+
// Apply the theme based on the value of STYLE_THEME
17+
if (isMUITheme()) {
18+
document.documentElement.classList.add(Theme.MUI);
19+
} else {
20+
document.documentElement.classList.remove(Theme.MUI);
21+
}
22+
}, []);
23+
24+
return (
25+
<ThemeContext.Provider value={themeValue}>
26+
{isMUITheme() ? (
27+
<MUIThemeProvider theme={createMUITheme}>{children}</MUIThemeProvider>
28+
) : (
29+
children
30+
)}
31+
</ThemeContext.Provider>
32+
);
33+
};
34+
35+
export default ThemeProvider;

clients/ui/frontend/src/app/pages/modelRegistry/ModelRegistryCoreLoader.tsx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import * as React from 'react';
22
import { Navigate, Outlet, useParams } from 'react-router-dom';
3-
import { Bullseye, Alert, Divider } from '@patternfly/react-core';
3+
import { Bullseye, Alert } from '@patternfly/react-core';
44
import ApplicationsPage from '~/shared/components/ApplicationsPage';
55
import { ModelRegistrySelectorContext } from '~/app/context/ModelRegistrySelectorContext';
66
import { ProjectObjectType, typedEmptyImage } from '~/shared/components/design/utils';
77
import { ModelRegistryContextProvider } from '~/app/context/ModelRegistryContext';
88
import TitleWithIcon from '~/shared/components/design/TitleWithIcon';
9-
import WhosMyAdministrator from '~/shared/components/WhosMyAdministrator';
10-
import { isMUITheme } from '~/shared/utilities/const';
119
import KubeflowDocs from '~/shared/components/KubeflowDocs';
10+
import { useThemeContext } from '~/app/MUIThemeContext';
1211
import EmptyModelRegistryState from './screens/components/EmptyModelRegistryState';
1312
import InvalidModelRegistry from './screens/InvalidModelRegistry';
1413
import ModelRegistrySelectorNavigator from './screens/ModelRegistrySelectorNavigator';
@@ -36,6 +35,7 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
3635
preferredModelRegistry,
3736
updatePreferredModelRegistry,
3837
} = React.useContext(ModelRegistrySelectorContext);
38+
const { isMUITheme } = useThemeContext();
3939

4040
const modelRegistryFromRoute = modelRegistries.find((mr) => mr.name === modelRegistry);
4141

@@ -65,16 +65,16 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
6565
emptyStatePage: (
6666
<EmptyModelRegistryState
6767
testid="empty-model-registries-state"
68-
title={isMUITheme() ? 'Deploy a model registry' : 'Request access to model registries'}
68+
title="Deploy a model registry"
6969
description={
70-
isMUITheme()
70+
isMUITheme
7171
? 'To deploy a new model registry, follow the instructions in the docs below.'
7272
: 'To request a new model registry, or to request permission to access an existing model registry, contact your administrator.'
7373
}
7474
headerIcon={() => (
7575
<img src={typedEmptyImage(ProjectObjectType.registeredModels)} alt="" />
7676
)}
77-
customAction={isMUITheme() ? <KubeflowDocs /> : <WhosMyAdministrator />}
77+
customAction={<KubeflowDocs />}
7878
/>
7979
),
8080
headerContent: null,
@@ -103,19 +103,9 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
103103
return (
104104
<ApplicationsPage
105105
title={
106-
!isMUITheme() ? (
107-
<TitleWithIcon title="Model Registry" objectType={ProjectObjectType.registeredModels} />
108-
) : (
109-
'Model Registry'
110-
)
111-
}
112-
description={
113-
!isMUITheme() ? (
114-
'Select a model registry to view and manage your registered models. Model registries provide a structured and organized way to store, share, version, deploy, and track models.'
115-
) : (
116-
<Divider />
117-
)
106+
<TitleWithIcon title="Model Registry" objectType={ProjectObjectType.registeredModels} />
118107
}
108+
description="Select a model registry to view and manage your registered models. Model registries provide a structured and organized way to store, share, version, deploy, and track models."
119109
headerContent={
120110
<ModelRegistrySelectorNavigator
121111
getRedirectPath={(modelRegistryName) => modelRegistryUrl(modelRegistryName)}

clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelPropertiesTableRow.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { CheckIcon, ExternalLinkAltIcon, TimesIcon } from '@patternfly/react-ico
1515
import { KeyValuePair } from '~/shared/types';
1616
import { EitherNotBoth } from '~/shared/typeHelpers';
1717
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
18-
import { isMUITheme } from '~/shared/utilities/const';
1918
import { isValidHttpUrl } from './utils';
2019

2120
type ModelPropertiesTableRowProps = {
@@ -47,6 +46,7 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
4746
saveEditedProperty,
4847
}) => {
4948
const { key, value } = keyValuePair;
49+
5050
const [unsavedKey, setUnsavedKey] = React.useState(key);
5151
const [unsavedValue, setUnsavedValue] = React.useState(value);
5252

@@ -128,11 +128,7 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
128128
<Td dataLabel="Key" width={45} modifier="breakWord">
129129
{isEditing ? (
130130
<>
131-
{isMUITheme() ? (
132-
<FormFieldset className="tr-fieldset-wrapper" component={propertyKeyInput} />
133-
) : (
134-
propertyKeyInput
135-
)}
131+
<FormFieldset className="tr-fieldset-wrapper" component={propertyKeyInput} />
136132

137133
{keyValidationError && (
138134
<FormHelperText>
@@ -148,11 +144,7 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
148144
</Td>
149145
<Td dataLabel="Value" width={45} modifier="breakWord">
150146
{isEditing ? (
151-
isMUITheme() ? (
152-
<FormFieldset className="tr-fieldset-wrapper" component={propertyValueInput} />
153-
) : (
154-
propertyValueInput
155-
)
147+
<FormFieldset className="tr-fieldset-wrapper" component={propertyValueInput} />
156148
) : (
157149
<ExpandableSection
158150
variant="truncate"

clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelRegistry.tsx

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ import { Divider } from '@patternfly/react-core';
33
import ApplicationsPage from '~/shared/components/ApplicationsPage';
44
import useRegisteredModels from '~/app/hooks/useRegisteredModels';
55
import useModelVersions from '~/app/hooks/useModelVersions';
6-
import { isMUITheme } from '~/shared/utilities/const';
7-
import TitleWithIcon from '~/shared/components/design/TitleWithIcon';
8-
import { ProjectObjectType } from '~/shared/components/design/utils';
96
import ModelRegistrySelectorNavigator from './ModelRegistrySelectorNavigator';
107
import RegisteredModelListView from './RegisteredModels/RegisteredModelListView';
118
import { modelRegistryUrl } from './routeUtils';
@@ -36,20 +33,8 @@ const ModelRegistry: React.FC<ModelRegistryProps> = ({ ...pageProps }) => {
3633
return (
3734
<ApplicationsPage
3835
{...pageProps}
39-
title={
40-
!isMUITheme() ? (
41-
<TitleWithIcon title="Model Registry" objectType={ProjectObjectType.registeredModels} />
42-
) : (
43-
'Model Registry'
44-
)
45-
}
46-
description={
47-
!isMUITheme() ? (
48-
'Select a model registry to view and manage your registered models. Model registries provide a structured and organized way to store, share, version, deploy, and track models.'
49-
) : (
50-
<Divider />
51-
)
52-
}
36+
title="Model Registry"
37+
description={<Divider />}
5338
headerContent={
5439
<ModelRegistrySelectorNavigator
5540
getRedirectPath={(modelRegistryName) => modelRegistryUrl(modelRegistryName)}

clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelRegistrySelector.tsx

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
FlexItem,
1111
Icon,
1212
Popover,
13-
PopoverPosition,
1413
Tooltip,
1514
} from '@patternfly/react-core';
1615
import text from '@patternfly/react-styles/css/utilities/Text/text';
@@ -20,8 +19,6 @@ import { useBrowserStorage } from '~/shared/components/browserStorage';
2019
import { ModelRegistrySelectorContext } from '~/app/context/ModelRegistrySelectorContext';
2120
import { ModelRegistry } from '~/app/types';
2221
import SimpleSelect, { SimpleSelectOption } from '~/shared/components/SimpleSelect';
23-
import WhosMyAdministrator from '~/shared/components/WhosMyAdministrator';
24-
import { isMUITheme } from '~/shared/utilities/const';
2522
import KubeflowDocs from '~/shared/components/KubeflowDocs';
2623

2724
const MODEL_REGISTRY_FAVORITE_STORAGE_KEY = 'kubeflow.dashboard.model.registry.favorite';
@@ -175,21 +172,10 @@ const ModelRegistrySelector: React.FC<ModelRegistrySelectorProps> = ({
175172
</FlexItem>
176173
)}
177174
<FlexItem align={{ default: 'alignRight' }}>
178-
{isMUITheme() ? (
179-
<KubeflowDocs
180-
buttonLabel="Need another registry?"
181-
linkTestId="model-registry-help-button"
182-
/>
183-
) : (
184-
<WhosMyAdministrator
185-
buttonLabel="Need another registry?"
186-
headerContent="Need another registry?"
187-
leadText="To request access to a new or existing model registry, contact your administrator."
188-
contentTestId="model-registry-help-content"
189-
linkTestId="model-registry-help-button"
190-
popoverPosition={PopoverPosition.left}
191-
/>
192-
)}
175+
<KubeflowDocs
176+
buttonLabel="Need another registry?"
177+
linkTestId="model-registry-help-button"
178+
/>
193179
</FlexItem>
194180
</Flex>
195181
);

clients/ui/frontend/src/app/pages/modelRegistry/screens/ModelVersions/ModelVersionListView.tsx

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
DropdownList,
88
MenuToggle,
99
MenuToggleElement,
10-
SearchInput,
1110
TextInput,
1211
ToolbarContent,
1312
ToolbarFilter,
@@ -34,7 +33,6 @@ import { asEnumMember } from '~/shared/utilities/utils';
3433
import ModelVersionsTable from '~/app/pages/modelRegistry/screens/ModelVersions/ModelVersionsTable';
3534
import SimpleSelect from '~/shared/components/SimpleSelect';
3635
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
37-
import { isMUITheme } from '~/shared/utilities/const';
3836
import { filterArchiveVersions, filterLiveVersions } from '~/app/utils';
3937

4038
type ModelVersionListViewProps = {
@@ -158,35 +156,22 @@ const ModelVersionListView: React.FC<ModelVersionListViewProps> = ({
158156
/>
159157
</ToolbarFilter>
160158
<ToolbarItem>
161-
{isMUITheme() ? (
162-
<FormFieldset
163-
className="toolbar-fieldset-wrapper"
164-
component={
165-
<TextInput
166-
value={search}
167-
type="text"
168-
onChange={(_, searchValue) => {
169-
setSearch(searchValue);
170-
}}
171-
style={{ minWidth: '200px' }}
172-
data-testid="model-versions-table-search"
173-
aria-label="Search"
174-
/>
175-
}
176-
field={`Find by ${searchType.toLowerCase()}`}
177-
/>
178-
) : (
179-
<SearchInput
180-
placeholder={`Find by ${searchType.toLowerCase()}`}
181-
value={search}
182-
onChange={(_, searchValue) => {
183-
setSearch(searchValue);
184-
}}
185-
onClear={() => setSearch('')}
186-
style={{ minWidth: '200px' }}
187-
data-testid="model-versions-table-search"
188-
/>
189-
)}
159+
<FormFieldset
160+
className="toolbar-fieldset-wrapper"
161+
component={
162+
<TextInput
163+
value={search}
164+
type="text"
165+
onChange={(_, searchValue) => {
166+
setSearch(searchValue);
167+
}}
168+
style={{ minWidth: '200px' }}
169+
data-testid="model-versions-table-search"
170+
aria-label="Search"
171+
/>
172+
}
173+
field={`Find by ${searchType.toLowerCase()}`}
174+
/>
190175
</ToolbarItem>
191176
</ToolbarGroup>
192177

0 commit comments

Comments
 (0)