mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-24 05:58:31 +00:00
✨feat(ui)#10274: UI - allow to configure OM logo (#10316)
* ✨feat(ui)#10274: UI - allow to configure OM logo
* chore: use logo config to render the brand and login page logo
* fix : cy tests
* doc: update the doc
* chore: remove check for filePath logo location type
* test: add unit test
* - removed FilePath
- Added configs to docker
* address comment
* remove config from test yaml
* update logo aspect ratio
* remove type
* chore: update ui logic as per backend config
* update doc
* address comments
* Revert "address comments"
This reverts commit c4f9da88918343cab08cd5e603cba29bd05b2ec9.
* address comments
---------
Co-authored-by: mohitdeuex <mohit.y@deuexsolutions.com>
This commit is contained in:
parent
754074f1be
commit
4ce038557e
@ -267,13 +267,10 @@ email:
|
||||
|
||||
applicationConfig:
|
||||
logoConfig:
|
||||
logoLocationType: ${OM_LOGO_LOCATION_TYPE:-openmetadata} #either "openmetadata' or { "url" or "filePath" , based on this specify either '*AbsoluteFilePath' or '*LogoUrlPath' }
|
||||
loginPageLogoAbsoluteFilePath: ${OM_LOGO_LOGIN_LOCATION_FILE_PATH:-""} #login page logo , work in "filePath" mode
|
||||
loginPageLogoUrlPath: ${OM_LOGO_LOGIN_LOCATION_URL_PATH:-""} #login page logo , work in "url" mode
|
||||
navBarLogoAbsoluteFilePath: ${OM_LOGO_NAVBAR_LOCATION_FILE_PATH:-""} #nav bar logo , work in "filePath" mode
|
||||
navBarLogoUrlPath: ${OM_LOGO_NAVBAR_LOCATION_URL_PATH:-""} #nav bar logo , work in "url" mode
|
||||
customLogoUrlPath: ${OM_CUSTOM_LOGO_URL_PATH:-""} #login page logo
|
||||
customMonogramUrlPath: ${OM_CUSTOM_MONOGRAM_URL_PATH:-""} #nav bar logo
|
||||
loginConfig:
|
||||
maxLoginFailAttempts: ${OM_MAX_FAILED_LOGIN_ATTEMPTS:-3}
|
||||
accessBlockTime: ${OM_LOGIN_ACCESS_BLOCKTIME:-600}
|
||||
accessBlockTime: ${OM_LOGIN_ACCESS_BLOCK_TIME:-600}
|
||||
jwtTokenExpiryTime: ${OM_JWT_EXPIRY_TIME:-3600}
|
||||
|
||||
|
||||
@ -109,6 +109,12 @@ services:
|
||||
ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD:-""}
|
||||
# Heap OPTS Configurations
|
||||
OPENMETADATA_HEAP_OPTS: ${OPENMETADATA_HEAP_OPTS:--Xmx1G -Xms1G}
|
||||
# Application Config
|
||||
CUSTOM_LOGO_URL_PATH: ${CUSTOM_LOGO_URL_PATH:-""}
|
||||
CUSTOM_MONOGRAM_URL_PATH: ${CUSTOM_MONOGRAM_URL_PATH:-""}
|
||||
OM_MAX_FAILED_LOGIN_ATTEMPTS: ${OM_MAX_FAILED_LOGIN_ATTEMPTS:-3}
|
||||
OM_LOGIN_ACCESS_BLOCK_TIME: ${OM_LOGIN_ACCESS_BLOCK_TIME:-600}
|
||||
OM_JWT_EXPIRY_TIME: ${OM_JWT_EXPIRY_TIME:-3600}
|
||||
expose:
|
||||
- 8585
|
||||
- 8586
|
||||
|
||||
@ -108,6 +108,12 @@ services:
|
||||
ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD:-""}
|
||||
# Heap OPTS Configurations
|
||||
OPENMETADATA_HEAP_OPTS: ${OPENMETADATA_HEAP_OPTS:--Xmx1G -Xms1G}
|
||||
# Application Config
|
||||
CUSTOM_LOGO_URL_PATH: ${CUSTOM_LOGO_URL_PATH:-""}
|
||||
CUSTOM_MONOGRAM_URL_PATH: ${CUSTOM_MONOGRAM_URL_PATH:-""}
|
||||
OM_MAX_FAILED_LOGIN_ATTEMPTS: ${OM_MAX_FAILED_LOGIN_ATTEMPTS:-3}
|
||||
OM_LOGIN_ACCESS_BLOCK_TIME: ${OM_LOGIN_ACCESS_BLOCK_TIME:-600}
|
||||
OM_JWT_EXPIRY_TIME: ${OM_JWT_EXPIRY_TIME:-3600}
|
||||
expose:
|
||||
- 8585
|
||||
- 8586
|
||||
|
||||
@ -101,6 +101,12 @@ services:
|
||||
ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD:-""}
|
||||
# Heap OPTS Configurations
|
||||
OPENMETADATA_HEAP_OPTS: ${OPENMETADATA_HEAP_OPTS:--Xmx1G -Xms1G}
|
||||
# Application Config
|
||||
CUSTOM_LOGO_URL_PATH: ${CUSTOM_LOGO_URL_PATH:-""}
|
||||
CUSTOM_MONOGRAM_URL_PATH: ${CUSTOM_MONOGRAM_URL_PATH:-""}
|
||||
OM_MAX_FAILED_LOGIN_ATTEMPTS: ${OM_MAX_FAILED_LOGIN_ATTEMPTS:-3}
|
||||
OM_LOGIN_ACCESS_BLOCK_TIME: ${OM_LOGIN_ACCESS_BLOCK_TIME:-600}
|
||||
OM_JWT_EXPIRY_TIME: ${OM_JWT_EXPIRY_TIME:-3600}
|
||||
|
||||
expose:
|
||||
- 8585
|
||||
|
||||
@ -99,6 +99,12 @@ services:
|
||||
ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD:-""}
|
||||
# Heap OPTS Configurations
|
||||
OPENMETADATA_HEAP_OPTS: ${OPENMETADATA_HEAP_OPTS:--Xmx1G -Xms1G}
|
||||
# Application Config
|
||||
CUSTOM_LOGO_URL_PATH: ${CUSTOM_LOGO_URL_PATH:-""}
|
||||
CUSTOM_MONOGRAM_URL_PATH: ${CUSTOM_MONOGRAM_URL_PATH:-""}
|
||||
OM_MAX_FAILED_LOGIN_ATTEMPTS: ${OM_MAX_FAILED_LOGIN_ATTEMPTS:-3}
|
||||
OM_LOGIN_ACCESS_BLOCK_TIME: ${OM_LOGIN_ACCESS_BLOCK_TIME:-600}
|
||||
OM_JWT_EXPIRY_TIME: ${OM_JWT_EXPIRY_TIME:-3600}
|
||||
|
||||
expose:
|
||||
- 8585
|
||||
|
||||
@ -3,6 +3,8 @@ title: How to change the Login Page and Nav Bar Logo
|
||||
slug: /how-to-guides/custom-logo/how-to-add-custom-logo
|
||||
---
|
||||
|
||||
# How to add a custom logo for the application
|
||||
|
||||
To change the Logo for the application, we need to update logo at two locations.
|
||||
|
||||
1. Login Page
|
||||
@ -13,36 +15,24 @@ To change the Logo for the application, we need to update logo at two locations.
|
||||
|
||||
<Image src="/images/how-to-guides/custom-logo/nav-Bar-Logo.png" alt="navBar-image"/>
|
||||
|
||||
# How to add a custom logo for the application
|
||||
|
||||
### Step 1: Get the image size as per the following formats.
|
||||
|
||||
- Login Page (1 px x 2px)
|
||||
- Navigation Bar (1 px x 2px)
|
||||
- Monogram aspect ratio should be 1:1 and Recommended size should be 30 x 30 px
|
||||
- Logo aspect ratio should be 5:2 and Recommended size should be 150 x 60 px
|
||||
|
||||
### Step 2: Configure 'openmetadata.yaml' or the corresponding environment variables
|
||||
|
||||
```yaml
|
||||
applicationConfig:
|
||||
logoConfig:
|
||||
logoLocationType: ${OM_LOGO_LOCATION_TYPE:-openmetadata} #either "openmetadata' or { "url" or "filePath" , based on this specify either '*AbsoluteFilePath' or '*LogoUrlPath' }
|
||||
loginPageLogoAbsoluteFilePath: ${OM_LOGO_LOGIN_LOCATION_FILE_PATH:-""} #login page logo , work in "filePath" mode
|
||||
loginPageLogoUrlPath: ${OM_LOGO_LOGIN_LOCATION_URL_PATH:-""} #login page logo , work in "url" mode
|
||||
navBarLogoAbsoluteFilePath: ${OM_LOGO_NAVBAR_LOCATION_FILE_PATH:-""} #nav bar logo , work in "filePath" mode
|
||||
navBarLogoUrlPath: ${OM_LOGO_NAVBAR_LOCATION_URL_PATH:-""} #nav bar logo , work in "url" mode
|
||||
customLogoUrlPath: ${OM_CUSTOM_LOGO_URL_PATH:-""} #login page logo
|
||||
customMonogramUrlPath: ${OM_CUSTOM_MONOGRAM_URL_PATH:-""} #nav bar logo
|
||||
```
|
||||
1. `logoLocationType` set to 'openmetadata'
|
||||
|
||||
- In this case it will take the default OM logo, we don't need to configure anything else.
|
||||
1. `customLogoUrlPath`
|
||||
|
||||
2. `logoLocationType` set to 'filePath'
|
||||
- URL path for the login page logo.
|
||||
|
||||
- In this case it will take the custom logo from the specified absolute paths, need to configure following as well.
|
||||
- `loginPageLogoAbsoluteFilePath` -> This is the path for Login Page Logo Image.
|
||||
- `navBarLogoAbsoluteFilePath` -> This is the path for Navigation Bar Logo Image.
|
||||
2. `customMonogramUrlPath`
|
||||
|
||||
3. `logoLocationType` set to 'url'
|
||||
|
||||
- In this case it will take the custom logo from the specified url, need to configure following as well.
|
||||
- `loginPageLogoUrlPath` -> This is the url for Login Page Logo Image.
|
||||
- `navBarLogoUrlPath` -> This is the url for Navigation Bar Logo Image.
|
||||
- URL path for the navbar logo.
|
||||
|
||||
@ -193,11 +193,8 @@ email:
|
||||
|
||||
applicationConfig:
|
||||
logoConfig:
|
||||
logoLocationType: "openmetadata"
|
||||
loginPageLogoAbsoluteFilePath: ""
|
||||
loginPageLogoUrlPath: ""
|
||||
navBarLogoAbsoluteFilePath: ""
|
||||
navBarLogoUrlPath: ""
|
||||
customLogoUrlPath: ""
|
||||
customMonogramUrlPath: ""
|
||||
loginConfig:
|
||||
maxLoginFailAttempts: 3
|
||||
accessBlockTime: 600
|
||||
|
||||
@ -11,29 +11,15 @@
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.api.configuration.LogoConfiguration",
|
||||
"properties": {
|
||||
"logoLocationType": {
|
||||
"description": "Type of Logo Location",
|
||||
"type": "string",
|
||||
"enum": ["openmetadata","filePath","url"]
|
||||
},
|
||||
"loginPageLogoAbsoluteFilePath": {
|
||||
"description": "Login Page Absolute File Path For Logo Image",
|
||||
"type": "string"
|
||||
},
|
||||
"loginPageLogoUrlPath": {
|
||||
"customLogoUrlPath": {
|
||||
"description": "Login Page Logo Image Url",
|
||||
"type": "string"
|
||||
},
|
||||
"navBarLogoAbsoluteFilePath": {
|
||||
"description": "Navigation Bar Absolute File Path For Logo Image",
|
||||
"type": "string"
|
||||
},
|
||||
"navBarLogoUrlPath": {
|
||||
"customMonogramUrlPath": {
|
||||
"description": "Navigation Bar Logo Image Url",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["logoLocationType"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"loginConfiguration": {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import Appbar from 'components/app-bar/Appbar';
|
||||
import ApplicationConfigProvider from 'components/ApplicationConfigProvider/ApplicationConfigProvider';
|
||||
import { AuthProvider } from 'components/authentication/auth-provider/AuthProvider';
|
||||
import ErrorBoundry from 'components/ErrorBoundry/ErrorBoundry';
|
||||
import GlobalSearchProvider from 'components/GlobalSearchProvider/GlobalSearchProvider';
|
||||
@ -36,18 +37,20 @@ const App: FunctionComponent = () => {
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ErrorBoundry>
|
||||
<AuthProvider childComponentType={AppRouter}>
|
||||
<HelmetProvider>
|
||||
<WebAnalyticsProvider>
|
||||
<PermissionProvider>
|
||||
<WebSocketProvider>
|
||||
<GlobalSearchProvider>
|
||||
<Appbar />
|
||||
<AppRouter />
|
||||
</GlobalSearchProvider>
|
||||
</WebSocketProvider>
|
||||
</PermissionProvider>
|
||||
</WebAnalyticsProvider>
|
||||
</HelmetProvider>
|
||||
<ApplicationConfigProvider>
|
||||
<HelmetProvider>
|
||||
<WebAnalyticsProvider>
|
||||
<PermissionProvider>
|
||||
<WebSocketProvider>
|
||||
<GlobalSearchProvider>
|
||||
<Appbar />
|
||||
<AppRouter />
|
||||
</GlobalSearchProvider>
|
||||
</WebSocketProvider>
|
||||
</PermissionProvider>
|
||||
</WebAnalyticsProvider>
|
||||
</HelmetProvider>
|
||||
</ApplicationConfigProvider>
|
||||
</AuthProvider>
|
||||
</ErrorBoundry>
|
||||
</I18nextProvider>
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { getApplicationConfig } from 'rest/miscAPI';
|
||||
import ApplicationConfigProvider, {
|
||||
useApplicationConfigProvider,
|
||||
} from './ApplicationConfigProvider';
|
||||
|
||||
const mockApplicationConfig = {
|
||||
logoConfig: {
|
||||
customLogoUrlPath: 'https://customlink.source',
|
||||
|
||||
customMonogramUrlPath: 'https://customlink.source',
|
||||
},
|
||||
loginConfig: {
|
||||
maxLoginFailAttempts: 3,
|
||||
accessBlockTime: 600,
|
||||
jwtTokenExpiryTime: 3600,
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('rest/miscAPI', () => ({
|
||||
getApplicationConfig: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockApplicationConfig)),
|
||||
}));
|
||||
|
||||
describe('ApplicationConfigProvider', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders the children components', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<ApplicationConfigProvider>
|
||||
<div>Test Children</div>
|
||||
</ApplicationConfigProvider>
|
||||
);
|
||||
});
|
||||
|
||||
expect(screen.getByText('Test Children')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('fetch the application config on mount and set in the context', async () => {
|
||||
function TestComponent() {
|
||||
const { logoConfig } = useApplicationConfigProvider();
|
||||
|
||||
return <div>{logoConfig?.customLogoUrlPath}</div>;
|
||||
}
|
||||
|
||||
await act(async () => {
|
||||
render(
|
||||
<ApplicationConfigProvider>
|
||||
<TestComponent />
|
||||
</ApplicationConfigProvider>
|
||||
);
|
||||
});
|
||||
|
||||
expect(
|
||||
await screen.findByText('https://customlink.source')
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(getApplicationConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApplicationConfiguration } from 'generated/configuration/applicationConfiguration';
|
||||
import React, {
|
||||
createContext,
|
||||
FC,
|
||||
ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { getApplicationConfig } from 'rest/miscAPI';
|
||||
|
||||
export const ApplicationConfigContext = createContext<ApplicationConfiguration>(
|
||||
{} as ApplicationConfiguration
|
||||
);
|
||||
|
||||
export const useApplicationConfigProvider = () =>
|
||||
useContext(ApplicationConfigContext);
|
||||
|
||||
interface ApplicationConfigProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const ApplicationConfigProvider: FC<ApplicationConfigProviderProps> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [applicationConfig, setApplicationConfig] =
|
||||
useState<ApplicationConfiguration>({} as ApplicationConfiguration);
|
||||
|
||||
const fetchApplicationConfig = async () => {
|
||||
try {
|
||||
const response = await getApplicationConfig();
|
||||
|
||||
setApplicationConfig(response);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchApplicationConfig();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ApplicationConfigContext.Provider value={{ ...applicationConfig }}>
|
||||
{children}
|
||||
</ApplicationConfigContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApplicationConfigProvider;
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import { Badge, Dropdown, Image, Input, Select, Space, Tooltip } from 'antd';
|
||||
import { useApplicationConfigProvider } from 'components/ApplicationConfigProvider/ApplicationConfigProvider';
|
||||
import { CookieStorage } from 'cookie-storage';
|
||||
import i18next from 'i18next';
|
||||
import { debounce, toString } from 'lodash';
|
||||
@ -20,6 +21,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { NavLink, useHistory } from 'react-router-dom';
|
||||
import AppState from '../../AppState';
|
||||
import Logo from '../../assets/svg/logo-monogram.svg';
|
||||
|
||||
import {
|
||||
NOTIFICATION_READ_TIMER,
|
||||
ROUTES,
|
||||
@ -73,6 +75,8 @@ const NavBar = ({
|
||||
handleKeyDown,
|
||||
handleOnClick,
|
||||
}: NavBarProps) => {
|
||||
const { logoConfig } = useApplicationConfigProvider();
|
||||
|
||||
// get current user details
|
||||
const currentUser = useMemo(
|
||||
() => AppState.getCurrentUserDetails(),
|
||||
@ -295,16 +299,23 @@ const NavBar = ({
|
||||
[AppState]
|
||||
);
|
||||
|
||||
const brandLogoUrl = useMemo(() => {
|
||||
return logoConfig?.customMonogramUrlPath ?? Logo;
|
||||
}, [logoConfig]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="tw-h-16 tw-py-3 tw-border-b-2 tw-border-separator tw-bg-white">
|
||||
<div className="tw-flex tw-items-center tw-flex-row tw-justify-between tw-flex-nowrap tw-px-6">
|
||||
<div className="tw-flex tw-items-center tw-flex-row tw-justify-between tw-flex-nowrap">
|
||||
<NavLink className="tw-flex-shrink-0" id="openmetadata_logo" to="/">
|
||||
<SVGIcons
|
||||
<Image
|
||||
alt="OpenMetadata Logo"
|
||||
data-testid="image"
|
||||
fallback={Logo}
|
||||
height={30}
|
||||
icon={Icons.LOGO_SMALL}
|
||||
preview={false}
|
||||
src={brandLogoUrl}
|
||||
width={25}
|
||||
/>
|
||||
</NavLink>
|
||||
|
||||
@ -11,7 +11,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { findByTestId, findByText, render } from '@testing-library/react';
|
||||
import {
|
||||
findByTestId,
|
||||
findByText,
|
||||
render,
|
||||
screen,
|
||||
} from '@testing-library/react';
|
||||
import { useAuthContext } from 'components/authentication/auth-provider/AuthProvider';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
@ -26,6 +31,18 @@ jest.mock('react-router-dom', () => ({
|
||||
jest.mock('components/authentication/auth-provider/AuthProvider', () => ({
|
||||
useAuthContext: jest.fn(),
|
||||
}));
|
||||
jest.mock(
|
||||
'components/ApplicationConfigProvider/ApplicationConfigProvider',
|
||||
() => ({
|
||||
useApplicationConfigProvider: jest.fn().mockImplementation(() => ({
|
||||
logoConfig: {
|
||||
customLogoUrlPath: 'https://customlink.source',
|
||||
|
||||
customMonogramUrlPath: 'https://customlink.source',
|
||||
},
|
||||
})),
|
||||
})
|
||||
);
|
||||
|
||||
jest.mock(
|
||||
'components/containers/PageContainer',
|
||||
@ -112,4 +129,23 @@ describe('Test SigninPage Component', () => {
|
||||
|
||||
expect(signinButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Page should render the correct logo image', async () => {
|
||||
mockUseAuthContext.mockReturnValue({
|
||||
isAuthDisabled: false,
|
||||
authConfig: { provider: 'custom-oidc', providerName: 'Custom OIDC' },
|
||||
onLoginHandler: jest.fn(),
|
||||
onLogoutHandler: jest.fn(),
|
||||
});
|
||||
render(<SigninPage />, {
|
||||
wrapper: MemoryRouter,
|
||||
});
|
||||
|
||||
const brandLogoImage = await screen.findByTestId('brand-logo-image');
|
||||
const logoImage = brandLogoImage.querySelector('img') as HTMLImageElement;
|
||||
|
||||
expect(brandLogoImage).toBeInTheDocument();
|
||||
|
||||
expect(logoImage.src).toEqual('https://customlink.source/');
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,8 +11,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button, Col, Divider, Form, Input, Row, Typography } from 'antd';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Divider,
|
||||
Form,
|
||||
Image,
|
||||
Input,
|
||||
Row,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import Logo from 'assets/svg/logo.svg';
|
||||
import classNames from 'classnames';
|
||||
import { useApplicationConfigProvider } from 'components/ApplicationConfigProvider/ApplicationConfigProvider';
|
||||
import { useAuthContext } from 'components/authentication/auth-provider/AuthProvider';
|
||||
import { useBasicAuth } from 'components/authentication/auth-provider/basic-auth.provider';
|
||||
import Loader from 'components/Loader/Loader';
|
||||
@ -32,6 +43,7 @@ import './login.style.less';
|
||||
import LoginCarousel from './LoginCarousel';
|
||||
|
||||
const SigninPage = () => {
|
||||
const { logoConfig } = useApplicationConfigProvider();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
@ -66,6 +78,10 @@ const SigninPage = () => {
|
||||
return isAuthDisabled || isAuthenticated;
|
||||
}, [isAuthDisabled, isAuthenticated]);
|
||||
|
||||
const brandLogoUrl = useMemo(() => {
|
||||
return logoConfig?.customLogoUrlPath ?? Logo;
|
||||
}, [logoConfig]);
|
||||
|
||||
const isTokenExpired = () => {
|
||||
const token = localState.getOidcToken();
|
||||
if (token) {
|
||||
@ -194,7 +210,14 @@ const SigninPage = () => {
|
||||
className={classNames('mt-24 text-center flex-center flex-col', {
|
||||
'sso-container': !isAuthProviderBasic,
|
||||
})}>
|
||||
<SVGIcons alt="OpenMetadata Logo" icon={Icons.LOGO} width="152" />
|
||||
<Image
|
||||
alt="OpenMetadata Logo"
|
||||
data-testid="brand-logo-image"
|
||||
fallback={Logo}
|
||||
preview={false}
|
||||
src={brandLogoUrl}
|
||||
width={152}
|
||||
/>
|
||||
<Typography.Text className="mt-8 w-80 text-xl font-medium text-grey-muted">
|
||||
{t('message.om-description')}{' '}
|
||||
</Typography.Text>
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { Edge } from 'components/EntityLineage/EntityLineage.interface';
|
||||
import { ExploreSearchIndex } from 'components/Explore/explore.interface';
|
||||
import { ApplicationConfiguration } from 'generated/configuration/applicationConfiguration';
|
||||
import { AuthorizerConfiguration } from 'generated/configuration/authorizerConfiguration';
|
||||
import { SearchIndex } from '../enums/search.enum';
|
||||
import { AuthenticationConfiguration } from '../generated/configuration/authenticationConfiguration';
|
||||
@ -71,6 +72,13 @@ export const fetchAuthenticationConfig = async () => {
|
||||
|
||||
return response.data;
|
||||
};
|
||||
export const getApplicationConfig = async () => {
|
||||
const response = await APIClient.get<ApplicationConfiguration>(
|
||||
'/system/config/applicationConfig'
|
||||
);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const fetchAuthorizerConfig = async () => {
|
||||
const response = await APIClient.get<AuthorizerConfiguration>(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user