Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions clients/ui/frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@patternfly/react-core';
import ToastNotifications from '~/shared/components/ToastNotifications';
import { useSettings } from '~/shared/hooks/useSettings';
import { isMUITheme, Theme, AUTH_HEADER, MOCK_AUTH, isStandalone } from '~/shared/utilities/const';
import { AUTH_HEADER, MOCK_AUTH, isStandalone } from '~/shared/utilities/const';
import { logout } from '~/shared/utilities/appUtils';
import { NamespaceSelectorContext } from '~/shared/context/NamespaceSelectorContext';
import NavSidebar from './NavSidebar';
Expand All @@ -36,15 +36,6 @@ const App: React.FC = () => {

const username = userSettings?.userId;

React.useEffect(() => {
// Apply the theme based on the value of STYLE_THEME
if (isMUITheme()) {
document.documentElement.classList.add(Theme.MUI);
} else {
document.documentElement.classList.remove(Theme.MUI);
}
}, []);

React.useEffect(() => {
if (MOCK_AUTH && username) {
localStorage.setItem(AUTH_HEADER, username);
Expand Down
5 changes: 3 additions & 2 deletions clients/ui/frontend/src/app/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {
import { SimpleSelect } from '@patternfly/react-templates';
import { BarsIcon } from '@patternfly/react-icons';
import { NamespaceSelectorContext } from '~/shared/context/NamespaceSelectorContext';
import { isMUITheme } from '~/shared/utilities/const';
import logoDarkTheme from '~/images/logo-dark-theme.svg';
import { useThemeContext } from './ThemeContext';

interface NavBarProps {
username?: string;
Expand All @@ -32,6 +32,7 @@ interface NavBarProps {
const NavBar: React.FC<NavBarProps> = ({ username, onLogout }) => {
const { namespaces, preferredNamespace, updatePreferredNamespace } =
React.useContext(NamespaceSelectorContext);
const { isMUITheme } = useThemeContext();

const [userMenuOpen, setUserMenuOpen] = React.useState(false);

Expand Down Expand Up @@ -60,7 +61,7 @@ const NavBar: React.FC<NavBarProps> = ({ username, onLogout }) => {
<BarsIcon />
</PageToggleButton>
</MastheadToggle>
{!isMUITheme() ? (
{!isMUITheme ? (
<MastheadBrand>
<MastheadLogo component="a">
<Brand src={logoDarkTheme} alt="Kubeflow" heights={{ default: '36px' }} />
Expand Down
20 changes: 8 additions & 12 deletions clients/ui/frontend/src/app/NavSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
PageSidebar,
PageSidebarBody,
} from '@patternfly/react-core';
import { isMUITheme, LOGO_LIGHT } from '~/shared/utilities/const';
import { LOGO_LIGHT } from '~/shared/utilities/const';
import { useNavData, isNavDataGroup, NavDataHref, NavDataGroup } from './AppRoutes';

const NavHref: React.FC<{ item: NavDataHref }> = ({ item }) => (
Expand Down Expand Up @@ -48,17 +48,13 @@ const NavSidebar: React.FC = () => {
<PageSidebarBody>
<Nav id="nav-primary-simple">
<NavList id="nav-list-simple">
{isMUITheme() ? (
<NavItem>
<Brand
className="kubeflow_brand"
src={`${window.location.origin}/images/${LOGO_LIGHT}`}
alt="Kubeflow Logo"
/>
</NavItem>
) : (
''
)}
<NavItem>
<Brand
className="kubeflow_brand"
src={`${window.location.origin}/images/${LOGO_LIGHT}`}
alt="Kubeflow Logo"
/>
</NavItem>
{navData.map((item) =>
isNavDataGroup(item) ? (
<NavGroup key={item.label} item={item} />
Expand Down
44 changes: 44 additions & 0 deletions clients/ui/frontend/src/app/ThemeContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as React from 'react';
import { createTheme } from '@mui/material';
import { ThemeProvider as MUIThemeProvider } from '@mui/material/styles';
import { isMUITheme, Theme } from '~/shared/utilities/const';

type ThemeProviderProps = {
children: React.ReactNode;
};

type ThemeContextProps = {
isMUITheme: boolean;
};

export const ThemeContext = React.createContext({
isMUITheme: false,
});

export const useThemeContext = (): ThemeContextProps => React.useContext(ThemeContext);

const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
const themeValue = React.useMemo(() => ({ isMUITheme: isMUITheme() }), []);
const createMUITheme = React.useMemo(() => createTheme({ cssVariables: true }), []);

React.useEffect(() => {
// Apply the theme based on the value of STYLE_THEME
if (isMUITheme()) {
document.documentElement.classList.add(Theme.MUI);
} else {
document.documentElement.classList.remove(Theme.MUI);
}
}, []);

return (
<ThemeContext.Provider value={themeValue}>
{isMUITheme() ? (
<MUIThemeProvider theme={createMUITheme}>{children}</MUIThemeProvider>
) : (
children
)}
</ThemeContext.Provider>
);
};

export default ThemeProvider;
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { ProjectObjectType, typedEmptyImage } from '~/shared/components/design/u
import { ModelRegistryContextProvider } from '~/app/context/ModelRegistryContext';
import TitleWithIcon from '~/shared/components/design/TitleWithIcon';
import WhosMyAdministrator from '~/shared/components/WhosMyAdministrator';
import { isMUITheme } from '~/shared/utilities/const';
import KubeflowDocs from '~/shared/components/KubeflowDocs';
import { useThemeContext } from '~/app/ThemeContext';
import EmptyModelRegistryState from './screens/components/EmptyModelRegistryState';
import InvalidModelRegistry from './screens/InvalidModelRegistry';
import ModelRegistrySelectorNavigator from './screens/ModelRegistrySelectorNavigator';
Expand Down Expand Up @@ -36,6 +36,7 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
preferredModelRegistry,
updatePreferredModelRegistry,
} = React.useContext(ModelRegistrySelectorContext);
const { isMUITheme } = useThemeContext();

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

Expand Down Expand Up @@ -65,16 +66,16 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
emptyStatePage: (
<EmptyModelRegistryState
testid="empty-model-registries-state"
title={isMUITheme() ? 'Deploy a model registry' : 'Request access to model registries'}
title={isMUITheme ? 'Deploy a model registry' : 'Request access to model registries'}
description={
isMUITheme()
isMUITheme
? 'To deploy a new model registry, follow the instructions in the docs below.'
: 'To request a new model registry, or to request permission to access an existing model registry, contact your administrator.'
}
headerIcon={() => (
<img src={typedEmptyImage(ProjectObjectType.registeredModels)} alt="" />
)}
customAction={isMUITheme() ? <KubeflowDocs /> : <WhosMyAdministrator />}
customAction={isMUITheme ? <KubeflowDocs /> : <WhosMyAdministrator />}
/>
),
headerContent: null,
Expand Down Expand Up @@ -103,14 +104,14 @@ const ModelRegistryCoreLoader: React.FC<ModelRegistryCoreLoaderProps> = ({
return (
<ApplicationsPage
title={
!isMUITheme() ? (
!isMUITheme ? (
<TitleWithIcon title="Model Registry" objectType={ProjectObjectType.registeredModels} />
) : (
'Model Registry'
)
}
description={
!isMUITheme() ? (
!isMUITheme ? (
'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.'
) : (
<Divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { CheckIcon, ExternalLinkAltIcon, TimesIcon } from '@patternfly/react-ico
import { KeyValuePair } from '~/shared/types';
import { EitherNotBoth } from '~/shared/typeHelpers';
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
import { isMUITheme } from '~/shared/utilities/const';
import { useThemeContext } from '~/app/ThemeContext';
import { isValidHttpUrl } from './utils';

type ModelPropertiesTableRowProps = {
Expand Down Expand Up @@ -47,6 +47,8 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
saveEditedProperty,
}) => {
const { key, value } = keyValuePair;
const { isMUITheme } = useThemeContext();

const [unsavedKey, setUnsavedKey] = React.useState(key);
const [unsavedValue, setUnsavedValue] = React.useState(value);

Expand Down Expand Up @@ -128,7 +130,7 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
<Td dataLabel="Key" width={45} modifier="breakWord">
{isEditing ? (
<>
{isMUITheme() ? (
{isMUITheme ? (
<FormFieldset className="tr-fieldset-wrapper" component={propertyKeyInput} />
) : (
propertyKeyInput
Expand All @@ -148,7 +150,7 @@ const ModelPropertiesTableRow: React.FC<ModelPropertiesTableRowProps> = ({
</Td>
<Td dataLabel="Value" width={45} modifier="breakWord">
{isEditing ? (
isMUITheme() ? (
isMUITheme ? (
<FormFieldset className="tr-fieldset-wrapper" component={propertyValueInput} />
) : (
propertyValueInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Divider } from '@patternfly/react-core';
import ApplicationsPage from '~/shared/components/ApplicationsPage';
import useRegisteredModels from '~/app/hooks/useRegisteredModels';
import useModelVersions from '~/app/hooks/useModelVersions';
import { isMUITheme } from '~/shared/utilities/const';
import TitleWithIcon from '~/shared/components/design/TitleWithIcon';
import { ProjectObjectType } from '~/shared/components/design/utils';
import { useThemeContext } from '~/app/ThemeContext';
import ModelRegistrySelectorNavigator from './ModelRegistrySelectorNavigator';
import RegisteredModelListView from './RegisteredModels/RegisteredModelListView';
import { modelRegistryUrl } from './routeUtils';
Expand All @@ -25,6 +25,7 @@ const ModelRegistry: React.FC<ModelRegistryProps> = ({ ...pageProps }) => {
const [registeredModels, modelsLoaded, modelsLoadError, refreshModels] = useRegisteredModels();
const [modelVersions, versionsLoaded, versionsLoadError, refreshVersions] = useModelVersions();

const { isMUITheme } = useThemeContext();
const loaded = modelsLoaded && versionsLoaded;
const loadError = modelsLoadError || versionsLoadError;

Expand All @@ -37,14 +38,14 @@ const ModelRegistry: React.FC<ModelRegistryProps> = ({ ...pageProps }) => {
<ApplicationsPage
{...pageProps}
title={
!isMUITheme() ? (
!isMUITheme ? (
<TitleWithIcon title="Model Registry" objectType={ProjectObjectType.registeredModels} />
) : (
'Model Registry'
)
}
description={
!isMUITheme() ? (
!isMUITheme ? (
'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.'
) : (
<Divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import { ModelRegistrySelectorContext } from '~/app/context/ModelRegistrySelecto
import { ModelRegistry } from '~/app/types';
import SimpleSelect, { SimpleSelectOption } from '~/shared/components/SimpleSelect';
import WhosMyAdministrator from '~/shared/components/WhosMyAdministrator';
import { isMUITheme } from '~/shared/utilities/const';
import KubeflowDocs from '~/shared/components/KubeflowDocs';
import { useThemeContext } from '~/app/ThemeContext';

const MODEL_REGISTRY_FAVORITE_STORAGE_KEY = 'kubeflow.dashboard.model.registry.favorite';

Expand All @@ -42,6 +42,7 @@ const ModelRegistrySelector: React.FC<ModelRegistrySelectorProps> = ({
const { modelRegistries, updatePreferredModelRegistry } = React.useContext(
ModelRegistrySelectorContext,
);
const { isMUITheme } = useThemeContext();

const selection = modelRegistries.find((mr) => mr.name === modelRegistry);
const [favorites, setFavorites] = useBrowserStorage<string[]>(
Expand Down Expand Up @@ -175,7 +176,7 @@ const ModelRegistrySelector: React.FC<ModelRegistrySelectorProps> = ({
</FlexItem>
)}
<FlexItem align={{ default: 'alignRight' }}>
{isMUITheme() ? (
{isMUITheme ? (
<KubeflowDocs
buttonLabel="Need another registry?"
linkTestId="model-registry-help-button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { asEnumMember } from '~/shared/utilities/utils';
import { filterModelVersions } from '~/app/pages/modelRegistry/screens/utils';
import EmptyModelRegistryState from '~/app/pages/modelRegistry/screens/components/EmptyModelRegistryState';
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
import { isMUITheme } from '~/shared/utilities/const';
import { useThemeContext } from '~/app/ThemeContext';
import ModelVersionsArchiveTable from './ModelVersionsArchiveTable';

type ModelVersionsArchiveListViewProps = {
Expand All @@ -33,6 +33,8 @@ const ModelVersionsArchiveListView: React.FC<ModelVersionsArchiveListViewProps>

const searchTypes = [SearchType.KEYWORD, SearchType.AUTHOR];

const { isMUITheme } = useThemeContext();

const filteredModelVersions = filterModelVersions(unfilteredmodelVersions, search, searchType);

if (unfilteredmodelVersions.length === 0) {
Expand Down Expand Up @@ -77,7 +79,7 @@ const ModelVersionsArchiveListView: React.FC<ModelVersionsArchiveListViewProps>
/>
</ToolbarFilter>
<ToolbarItem>
{isMUITheme() ? (
{isMUITheme ? (
<FormFieldset
className="toolbar-fieldset-wrapper"
component={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import React from 'react';
import { FormGroup, TextInput } from '@patternfly/react-core';
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
import { isMUITheme } from '~/shared/utilities/const';
import { useThemeContext } from '~/app/ThemeContext';

type PrefilledModelRegistryFieldProps = {
mrName?: string;
};

const PrefilledModelRegistryField: React.FC<PrefilledModelRegistryFieldProps> = ({ mrName }) => {
const { isMUITheme } = useThemeContext();

const mrNameInput = (
<TextInput isDisabled isRequired type="text" id="mr-name" name="mr-name" value={mrName} />
);

return (
<FormGroup className="form-group-disabled" label="Model registry" isRequired fieldId="mr-name">
{isMUITheme() ? <FormFieldset component={mrNameInput} field="Model Registry" /> : mrNameInput}
{isMUITheme ? <FormFieldset component={mrNameInput} field="Model Registry" /> : mrNameInput}
</FormGroup>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import React from 'react';
import FormSection from '~/shared/components/pf-overrides/FormSection';
import { UpdateObjectAtPropAndValue } from '~/shared/types';
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
import { isMUITheme } from '~/shared/utilities/const';
import { useThemeContext } from '~/app/ThemeContext';
import { MR_CHARACTER_LIMIT } from './const';
import { RegisterModelFormData } from './useRegisterModelData';

Expand All @@ -26,6 +26,8 @@ const RegisterModelDetailsFormSection = <D extends RegisterModelFormData>({
hasModelNameError,
isModelNameDuplicate,
}: RegisterModelDetailsFormSectionProp<D>): React.ReactNode => {
const { isMUITheme } = useThemeContext();

const modelNameInput = (
<TextInput
isRequired
Expand Down Expand Up @@ -54,7 +56,7 @@ const RegisterModelDetailsFormSection = <D extends RegisterModelFormData>({
description="Provide general details that apply to all versions of this model."
>
<FormGroup label="Model name" isRequired fieldId="model-name">
{isMUITheme() ? <FormFieldset component={modelNameInput} /> : modelNameInput}
{isMUITheme ? <FormFieldset component={modelNameInput} /> : modelNameInput}
{hasModelNameError && (
<FormHelperText>
<HelperText>
Expand All @@ -68,7 +70,7 @@ const RegisterModelDetailsFormSection = <D extends RegisterModelFormData>({
)}
</FormGroup>
<FormGroup label="Model description" fieldId="model-description">
{isMUITheme() ? (
{isMUITheme ? (
<FormFieldset component={modelDescriptionInput} field="Model Description" />
) : (
modelDescriptionInput
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { FormGroup, TextInput } from '@patternfly/react-core';
import { RegisteredModel } from '~/app/types';
import FormFieldset from '~/app/pages/modelRegistry/screens/components/FormFieldset';
import { isMUITheme } from '~/shared/utilities/const';
import TypeaheadSelect, { TypeaheadSelectOption } from '~/shared/components/TypeaheadSelect';
import { useThemeContext } from '~/app/ThemeContext';

type RegisteredModelSelectorProps = {
registeredModels: RegisteredModel[];
Expand All @@ -18,6 +18,7 @@ const RegisteredModelSelector: React.FC<RegisteredModelSelectorProps> = ({
setRegisteredModelId,
isDisabled,
}) => {
const { isMUITheme } = useThemeContext();
const options: TypeaheadSelectOption[] = React.useMemo(
() =>
registeredModels.map(({ name, id }) => ({
Expand Down Expand Up @@ -48,7 +49,7 @@ const RegisteredModelSelector: React.FC<RegisteredModelSelectorProps> = ({
*/
return (
<FormGroup label="Model name" className="form-group-disabled" isRequired fieldId="model-name">
{isMUITheme() ? (
{isMUITheme ? (
<FormFieldset component={modelNameInput} field="Model Name" />
) : (
modelNameInput
Expand Down
Loading
Loading