change login screen images as per new layout (#15526)
* change login screen images as per new layout * fix the image size and layout background color * class naming change
Before Width: | Height: | Size: 840 KiB |
Before Width: | Height: | Size: 780 KiB |
Before Width: | Height: | Size: 741 KiB |
Before Width: | Height: | Size: 556 KiB |
Before Width: | Height: | Size: 633 KiB |
After Width: | Height: | Size: 259 KiB |
After Width: | Height: | Size: 246 KiB |
After Width: | Height: | Size: 237 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 240 KiB |
@ -12,36 +12,40 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CarouselProps } from 'antd';
|
import { CarouselProps } from 'antd';
|
||||||
import collaborationImg from '../assets/img/data-collaboration.png';
|
import loginClassBase from './LoginClassBase';
|
||||||
import discoveryImg from '../assets/img/data-discovery.png';
|
|
||||||
import governanceImg from '../assets/img/data-governance.png';
|
const {
|
||||||
import insightImg from '../assets/img/data-insights.png';
|
dataDiscovery,
|
||||||
import dataQualityImg from '../assets/img/data-qauality.png';
|
dataQuality,
|
||||||
|
governance,
|
||||||
|
dataInsightPlural,
|
||||||
|
dataCollaboration,
|
||||||
|
} = loginClassBase.carouselImages();
|
||||||
|
|
||||||
export const LOGIN_SLIDE = [
|
export const LOGIN_SLIDE = [
|
||||||
{
|
{
|
||||||
title: 'data-discovery',
|
title: 'data-discovery',
|
||||||
image: discoveryImg,
|
image: dataDiscovery,
|
||||||
descriptionKey: 'enables-end-to-end-metadata-management',
|
descriptionKey: 'enables-end-to-end-metadata-management',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'data-quality',
|
title: 'data-quality',
|
||||||
image: dataQualityImg,
|
image: dataQuality,
|
||||||
descriptionKey: 'discover-your-data-and-unlock-the-value-of-data-assets',
|
descriptionKey: 'discover-your-data-and-unlock-the-value-of-data-assets',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'governance',
|
title: 'governance',
|
||||||
image: governanceImg,
|
image: governance,
|
||||||
descriptionKey: 'assess-data-reliability-with-data-profiler-lineage',
|
descriptionKey: 'assess-data-reliability-with-data-profiler-lineage',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'data-insight-plural',
|
title: 'data-insight-plural',
|
||||||
image: insightImg,
|
image: dataInsightPlural,
|
||||||
descriptionKey: 'fosters-collaboration-among-producers-and-consumers',
|
descriptionKey: 'fosters-collaboration-among-producers-and-consumers',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'data-collaboration',
|
title: 'data-collaboration',
|
||||||
image: collaborationImg,
|
image: dataCollaboration,
|
||||||
descriptionKey: 'deeply-understand-table-relations-message',
|
descriptionKey: 'deeply-understand-table-relations-message',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 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 collaborationImg from '../assets/img/login-screen/data-collaboration.png';
|
||||||
|
import discoveryImg from '../assets/img/login-screen/data-discovery.png';
|
||||||
|
import governanceImg from '../assets/img/login-screen/data-governance.png';
|
||||||
|
import insightImg from '../assets/img/login-screen/data-insights.png';
|
||||||
|
import dataQualityImg from '../assets/img/login-screen/data-quality.png';
|
||||||
|
|
||||||
|
class LoginClassBase {
|
||||||
|
public carouselImages() {
|
||||||
|
return {
|
||||||
|
dataDiscovery: discoveryImg,
|
||||||
|
dataQuality: dataQualityImg,
|
||||||
|
governance: governanceImg,
|
||||||
|
dataInsightPlural: insightImg,
|
||||||
|
dataCollaboration: collaborationImg,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginClassBase = new LoginClassBase();
|
||||||
|
|
||||||
|
export default loginClassBase;
|
||||||
|
export { LoginClassBase };
|
@ -190,136 +190,134 @@ const SignInPage = () => {
|
|||||||
const onClickForgotPassword = () => history.push(ROUTES.FORGOT_PASSWORD);
|
const onClickForgotPassword = () => history.push(ROUTES.FORGOT_PASSWORD);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="d-flex flex-col h-full bg-white">
|
<Row className="h-full" data-testid="signin-page">
|
||||||
<Row className="flex flex-grow" data-testid="signin-page">
|
<Col className="bg-white" span={8}>
|
||||||
<Col span={8}>
|
<div
|
||||||
<div
|
className={classNames('mt-24 text-center flex-center flex-col', {
|
||||||
className={classNames('mt-24 text-center flex-center flex-col', {
|
'sso-container': !isAuthProviderBasic,
|
||||||
'sso-container': !isAuthProviderBasic,
|
})}>
|
||||||
})}>
|
<BrandImage height="auto" width={200} />
|
||||||
<BrandImage height="auto" width={200} />
|
<Typography.Text className="mt-8 w-80 text-xl font-medium text-grey-muted">
|
||||||
<Typography.Text className="mt-8 w-80 text-xl font-medium text-grey-muted">
|
{t('message.om-description')}{' '}
|
||||||
{t('message.om-description')}{' '}
|
</Typography.Text>
|
||||||
</Typography.Text>
|
|
||||||
|
|
||||||
{isAuthProviderBasic ? (
|
{isAuthProviderBasic ? (
|
||||||
<div className="login-form ">
|
<div className="login-form ">
|
||||||
<Form
|
<Form
|
||||||
className="w-full"
|
className="w-full"
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
validateMessages={VALIDATION_MESSAGES}
|
validateMessages={VALIDATION_MESSAGES}
|
||||||
onFinish={handleSubmit}>
|
onFinish={handleSubmit}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
data-testid="email"
|
data-testid="email"
|
||||||
label={
|
label={
|
||||||
|
isAuthProviderLDAP
|
||||||
|
? t('label.email')
|
||||||
|
: t('label.username-or-email')
|
||||||
|
}
|
||||||
|
name="email"
|
||||||
|
requiredMark={false}
|
||||||
|
rules={[{ required: true }]}>
|
||||||
|
<Input
|
||||||
|
autoFocus
|
||||||
|
placeholder={
|
||||||
isAuthProviderLDAP
|
isAuthProviderLDAP
|
||||||
? t('label.email')
|
? t('label.email')
|
||||||
: t('label.username-or-email')
|
: t('label.username-or-email')
|
||||||
}
|
}
|
||||||
name="email"
|
/>
|
||||||
requiredMark={false}
|
</Form.Item>
|
||||||
rules={[{ required: true }]}>
|
<Form.Item
|
||||||
<Input
|
data-testid="password"
|
||||||
autoFocus
|
label={t('label.password')}
|
||||||
placeholder={
|
name="password"
|
||||||
isAuthProviderLDAP
|
requiredMark={false}
|
||||||
? t('label.email')
|
rules={[{ required: true }]}>
|
||||||
: t('label.username-or-email')
|
<Input.Password
|
||||||
}
|
autoComplete="off"
|
||||||
/>
|
placeholder={t('label.password')}
|
||||||
</Form.Item>
|
/>
|
||||||
<Form.Item
|
</Form.Item>
|
||||||
data-testid="password"
|
|
||||||
label={t('label.password')}
|
|
||||||
name="password"
|
|
||||||
requiredMark={false}
|
|
||||||
rules={[{ required: true }]}>
|
|
||||||
<Input.Password
|
|
||||||
autoComplete="off"
|
|
||||||
placeholder={t('label.password')}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="w-full"
|
className="w-full"
|
||||||
data-testid="login"
|
data-testid="login"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
type="primary">
|
type="primary">
|
||||||
{t('label.login')}
|
{t('label.login')}
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
{loginError && (
|
{loginError && (
|
||||||
<div
|
<div
|
||||||
className="d-flex flex-col m-y-md"
|
className="d-flex flex-col m-y-md"
|
||||||
data-testid="login-error-container">
|
data-testid="login-error-container">
|
||||||
<div className="flex global-border rounded-4 p-sm error-alert ">
|
<div className="flex global-border rounded-4 p-sm error-alert ">
|
||||||
<div className="m-r-xs">
|
<div className="m-r-xs">
|
||||||
<Icon
|
<Icon
|
||||||
component={IconFailBadge}
|
component={IconFailBadge}
|
||||||
style={{ fontSize: '20px' }}
|
style={{ fontSize: '20px' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<p data-testid="success-line">
|
|
||||||
<span>{loginError}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<p data-testid="success-line">
|
||||||
|
<span>{loginError}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
{!isAuthProviderLDAP && (
|
)}
|
||||||
<>
|
{!isAuthProviderLDAP && (
|
||||||
<div className="mt-8" onClick={onClickForgotPassword}>
|
<>
|
||||||
<Typography.Link underline data-testid="forgot-password">
|
<div className="mt-8" onClick={onClickForgotPassword}>
|
||||||
{t('label.forgot-password')}
|
<Typography.Link underline data-testid="forgot-password">
|
||||||
</Typography.Link>
|
{t('label.forgot-password')}
|
||||||
</div>
|
</Typography.Link>
|
||||||
{authConfig?.enableSelfSignup && (
|
</div>
|
||||||
<>
|
{authConfig?.enableSelfSignup && (
|
||||||
<Divider className="w-min-0 mt-8 mb-12 justify-center">
|
<>
|
||||||
<Typography.Text className="text-sm" type="secondary">
|
<Divider className="w-min-0 mt-8 mb-12 justify-center">
|
||||||
{t('label.or-lowercase')}
|
<Typography.Text className="text-sm" type="secondary">
|
||||||
</Typography.Text>
|
{t('label.or-lowercase')}
|
||||||
</Divider>
|
</Typography.Text>
|
||||||
|
</Divider>
|
||||||
|
|
||||||
<div className="mt-4 d-flex flex-center">
|
<div className="mt-4 d-flex flex-center">
|
||||||
<Typography.Text className="mr-4">
|
<Typography.Text className="mr-4">
|
||||||
{t('message.new-to-the-platform')}
|
{t('message.new-to-the-platform')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Button
|
<Button
|
||||||
data-testid="signup"
|
data-testid="signup"
|
||||||
type="link"
|
type="link"
|
||||||
onClick={onClickSignUp}>
|
onClick={onClickSignUp}>
|
||||||
{t('label.create-entity', {
|
{t('label.create-entity', {
|
||||||
entity: t('label.account'),
|
entity: t('label.account'),
|
||||||
})}
|
})}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="">{getSignInButton()}</div>
|
<div className="">{getSignInButton()}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col className="relative" span={16}>
|
<Col className="relative" span={16}>
|
||||||
<div className="absolute inset-0">
|
<div className="absolute inset-0">
|
||||||
<img
|
<img
|
||||||
alt="bg-image"
|
alt="bg-image"
|
||||||
className="w-full h-full"
|
className="w-full h-full"
|
||||||
data-testid="bg-image"
|
data-testid="bg-image"
|
||||||
src={loginBG}
|
src={loginBG}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<LoginCarousel />
|
<LoginCarousel />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
.slick-dots.slick-dots-bottom {
|
.slick-dots.slick-dots-bottom {
|
||||||
|
position: initial;
|
||||||
.slick-active {
|
.slick-active {
|
||||||
button {
|
button {
|
||||||
background-color: @primary-color;
|
background-color: @primary-color;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Divider, Form, Input, Typography } from 'antd';
|
import { Button, Col, Divider, Form, Input, Row, Typography } from 'antd';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -66,149 +66,146 @@ const BasicSignUp = () => {
|
|||||||
const handleLogin = () => history.push(ROUTES.SIGNIN);
|
const handleLogin = () => history.push(ROUTES.SIGNIN);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="d-flex flex-col h-full bg-white">
|
<Row className="h-full" data-testid="signin-page">
|
||||||
<div className="d-flex flex-grow" data-testid="signin-page">
|
<Col className="bg-white" span={10}>
|
||||||
<div className="w-5/12">
|
<div className="mt-4 text-center flex-center flex-col">
|
||||||
<div className="mt-4 text-center flex-center flex-col">
|
<BrandImage height="auto" width={200} />
|
||||||
<BrandImage height="auto" width={200} />
|
<Typography.Text className="mt-8 w-80 text-xl font-medium text-grey-muted">
|
||||||
<Typography.Text className="mt-8 w-80 text-xl font-medium text-grey-muted">
|
{t('message.om-description')}
|
||||||
{t('message.om-description')}
|
</Typography.Text>
|
||||||
</Typography.Text>
|
|
||||||
|
|
||||||
{isAuthProviderBasic ? (
|
{isAuthProviderBasic ? (
|
||||||
<div className="m-t-lg" style={{ width: '334px' }}>
|
<div className="m-t-lg" style={{ width: '334px' }}>
|
||||||
<Form
|
<Form
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
form={form}
|
form={form}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
validateMessages={VALIDATION_MESSAGES}
|
validateMessages={VALIDATION_MESSAGES}
|
||||||
onFinish={handleSubmit}>
|
onFinish={handleSubmit}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t('label.entity-name', {
|
label={t('label.entity-name', {
|
||||||
entity: t('label.first'),
|
entity: t('label.first'),
|
||||||
|
})}
|
||||||
|
name="firstName"
|
||||||
|
rules={[{ whitespace: true, required: true }]}>
|
||||||
|
<Input
|
||||||
|
autoFocus
|
||||||
|
placeholder={t('label.enter-entity-name', {
|
||||||
|
entity: t('label.first-lowercase'),
|
||||||
})}
|
})}
|
||||||
name="firstName"
|
/>
|
||||||
rules={[{ whitespace: true, required: true }]}>
|
</Form.Item>
|
||||||
<Input
|
<Form.Item
|
||||||
autoFocus
|
label={t('label.entity-name', {
|
||||||
placeholder={t('label.enter-entity-name', {
|
entity: t('label.last'),
|
||||||
entity: t('label.first-lowercase'),
|
})}
|
||||||
})}
|
name="lastName"
|
||||||
/>
|
rules={[{ whitespace: true, required: true }]}>
|
||||||
</Form.Item>
|
<Input
|
||||||
<Form.Item
|
placeholder={t('label.enter-entity', {
|
||||||
label={t('label.entity-name', {
|
entity: t('label.last-name-lowercase'),
|
||||||
entity: t('label.last'),
|
|
||||||
})}
|
})}
|
||||||
name="lastName"
|
/>
|
||||||
rules={[{ whitespace: true, required: true }]}>
|
</Form.Item>
|
||||||
<Input
|
<Form.Item
|
||||||
placeholder={t('label.enter-entity', {
|
label={t('label.email')}
|
||||||
entity: t('label.last-name-lowercase'),
|
name="email"
|
||||||
})}
|
rules={[{ type: 'email', required: true }]}>
|
||||||
/>
|
<Input
|
||||||
</Form.Item>
|
placeholder={t('label.enter-entity', {
|
||||||
<Form.Item
|
entity: t('label.email-lowercase'),
|
||||||
label={t('label.email')}
|
|
||||||
name="email"
|
|
||||||
rules={[{ type: 'email', required: true }]}>
|
|
||||||
<Input
|
|
||||||
placeholder={t('label.enter-entity', {
|
|
||||||
entity: t('label.email-lowercase'),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t('label.password')}
|
|
||||||
name="password"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
pattern: passwordRegex,
|
|
||||||
message: t('message.password-error-message'),
|
|
||||||
},
|
|
||||||
]}>
|
|
||||||
<Input.Password
|
|
||||||
autoComplete="off"
|
|
||||||
placeholder={t('label.enter-entity', {
|
|
||||||
entity: t('label.password-lowercase'),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t('label.password-type', {
|
|
||||||
type: t('label.confirm'),
|
|
||||||
})}
|
})}
|
||||||
name="confirmPassword"
|
/>
|
||||||
rules={[
|
</Form.Item>
|
||||||
{
|
<Form.Item
|
||||||
validator: (_, value) => {
|
label={t('label.password')}
|
||||||
if (isEmpty(password)) {
|
name="password"
|
||||||
return Promise.reject(
|
rules={[
|
||||||
t('label.please-password-type-first')
|
{
|
||||||
);
|
required: true,
|
||||||
}
|
},
|
||||||
if (value !== password) {
|
{
|
||||||
return Promise.reject(
|
pattern: passwordRegex,
|
||||||
t('label.password-not-match')
|
message: t('message.password-error-message'),
|
||||||
);
|
},
|
||||||
}
|
]}>
|
||||||
|
<Input.Password
|
||||||
|
autoComplete="off"
|
||||||
|
placeholder={t('label.enter-entity', {
|
||||||
|
entity: t('label.password-lowercase'),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t('label.password-type', {
|
||||||
|
type: t('label.confirm'),
|
||||||
|
})}
|
||||||
|
name="confirmPassword"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (isEmpty(password)) {
|
||||||
|
return Promise.reject(
|
||||||
|
t('label.please-password-type-first')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (value !== password) {
|
||||||
|
return Promise.reject(t('label.password-not-match'));
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]}>
|
},
|
||||||
<Input.Password
|
]}>
|
||||||
autoComplete="off"
|
<Input.Password
|
||||||
placeholder={t('label.confirm-password')}
|
autoComplete="off"
|
||||||
/>
|
placeholder={t('label.confirm-password')}
|
||||||
</Form.Item>
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Button className="w-full" htmlType="submit" type="primary">
|
<Button className="w-full" htmlType="submit" type="primary">
|
||||||
{t('label.create-entity', {
|
{t('label.create-entity', {
|
||||||
entity: t('label.account'),
|
entity: t('label.account'),
|
||||||
})}
|
})}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Divider className="w-min-0 mt-8 mb-12 justify-center">
|
||||||
|
<Typography.Text type="secondary">
|
||||||
|
{t('label.or-lowercase')}
|
||||||
|
</Typography.Text>
|
||||||
|
</Divider>
|
||||||
|
|
||||||
|
<div className="mt-4 d-flex flex-center">
|
||||||
|
<Typography.Text className="mr-4">
|
||||||
|
{t('message.already-a-user')}
|
||||||
|
</Typography.Text>
|
||||||
|
<Button
|
||||||
|
ghost
|
||||||
|
data-testid="login"
|
||||||
|
type="link"
|
||||||
|
onClick={handleLogin}>
|
||||||
|
{t('label.login')}
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
<Divider className="w-min-0 mt-8 mb-12 justify-center">
|
</Form>
|
||||||
<Typography.Text type="secondary">
|
</div>
|
||||||
{t('label.or-lowercase')}
|
) : null}
|
||||||
</Typography.Text>
|
|
||||||
</Divider>
|
|
||||||
|
|
||||||
<div className="mt-4 d-flex flex-center">
|
|
||||||
<Typography.Text className="mr-4">
|
|
||||||
{t('message.already-a-user')}
|
|
||||||
</Typography.Text>
|
|
||||||
<Button
|
|
||||||
ghost
|
|
||||||
data-testid="login"
|
|
||||||
type="link"
|
|
||||||
onClick={handleLogin}>
|
|
||||||
{t('label.login')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="w-7/12 relative">
|
</Col>
|
||||||
<div className="absolute inset-0">
|
|
||||||
<img
|
|
||||||
alt="bg-image"
|
|
||||||
className="w-full h-full"
|
|
||||||
data-testid="bg-image"
|
|
||||||
src={loginBG}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<LoginCarousel />
|
<Col className="relative" span={14}>
|
||||||
|
<div className="absolute inset-0">
|
||||||
|
<img
|
||||||
|
alt="bg-image"
|
||||||
|
className="w-full h-full"
|
||||||
|
data-testid="bg-image"
|
||||||
|
src={loginBG}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<LoginCarousel />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|