Add login page - UI
This commit is contained in:
parent
90824fa963
commit
78427b7bb5
12
cope2n-fe/public/login_bg.svg
Normal file
12
cope2n-fe/public/login_bg.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<svg width="1440" height="1024" viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="-839" y="430.089" width="1187" height="1606.01" transform="rotate(-33.9609 -839 430.089)" fill="#134783"/>
|
||||||
|
<rect x="638" y="-77.9104" width="1187" height="1606.01" transform="rotate(-33.9609 638 -77.9104)" fill="#84B1E3"/>
|
||||||
|
<rect x="-303" y="-22.9104" width="1187" height="1606.01" transform="rotate(-33.9609 -303 -22.9104)" fill="#103C74"/>
|
||||||
|
<rect x="-51" y="0.0895996" width="1187" height="1606.01" transform="rotate(-33.9609 -51 0.0895996)" fill="#0C3264"/>
|
||||||
|
<rect x="204" y="0.0895996" width="1187" height="1606.01" transform="rotate(-33.9609 204 0.0895996)" fill="#0B2954"/>
|
||||||
|
<path d="M281 0.0895996L1265.52 -663L2162.68 669.059L1178.16 1332.15L281 0.0895996Z" fill="#0C3265"/>
|
||||||
|
<rect x="430" y="-13.9104" width="1187" height="1606.01" transform="rotate(-33.9609 430 -13.9104)" fill="#092956"/>
|
||||||
|
<path d="M543 -57.9104L1527.52 -721L2424.68 611.059L1440.16 1274.15L543 -57.9104Z" fill="#0C3265"/>
|
||||||
|
<path d="M720 -57.9104L1704.52 -721L2601.68 611.059L1617.16 1274.15L720 -57.9104Z" fill="#0B3F7A"/>
|
||||||
|
<rect x="818" y="-169.91" width="1187" height="1606.01" transform="rotate(-33.9609 818 -169.91)" fill="#0B4C93"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -1,4 +1,4 @@
|
|||||||
import { Typography } from 'antd';
|
import { Typography } from "antd";
|
||||||
|
|
||||||
export const Brand = ({
|
export const Brand = ({
|
||||||
collapsed,
|
collapsed,
|
||||||
@ -13,15 +13,21 @@ export const Brand = ({
|
|||||||
rows: 1,
|
rows: 1,
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
margin: 12,
|
marginTop: 3,
|
||||||
|
marginLeft: 12,
|
||||||
|
marginRight: 12,
|
||||||
|
paddingTop: 18,
|
||||||
|
paddingBottom: 18,
|
||||||
letterSpacing: 2,
|
letterSpacing: 2,
|
||||||
borderRadius: 4,
|
borderBottomLeftRadius: 10,
|
||||||
color: 'wheat',
|
borderBottomRightRadius: 10,
|
||||||
textAlign: 'center',
|
color: "#fff",
|
||||||
border: isBordered ? '4px solid wheat' : 'unset',
|
textAlign: "center",
|
||||||
|
backgroundColor: "rgb(0, 106, 255)",
|
||||||
|
fontSize: 32,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{collapsed ? 'O' : 'OCR'}
|
{collapsed ? "O" : "OCR"}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Segmented } from 'antd';
|
import { Segmented } from "antd";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { useLocalStorage } from 'usehooks-ts';
|
import { useLocalStorage } from "usehooks-ts";
|
||||||
import { LOCALE_KEY } from '../../consts';
|
import { LOCALE_KEY } from "../../consts";
|
||||||
import { dynamicActivate, getLocale } from '../../i18n';
|
import { dynamicActivate, getLocale } from "../../i18n";
|
||||||
|
|
||||||
const StyledSegmented = styled(Segmented)`
|
const StyledSegmented = styled(Segmented)`
|
||||||
& label.ant-segmented-item.ant-segmented-item-selected,
|
& label.ant-segmented-item.ant-segmented-item-selected,
|
||||||
@ -23,12 +23,12 @@ export const LanguageSelect = () => {
|
|||||||
<StyledSegmented
|
<StyledSegmented
|
||||||
options={[
|
options={[
|
||||||
{
|
{
|
||||||
label: 'EN',
|
label: "EN",
|
||||||
value: 'en',
|
value: "en",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'VI',
|
label: "VI",
|
||||||
value: 'vi',
|
value: "vi",
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
value={locale}
|
value={locale}
|
||||||
|
@ -105,7 +105,7 @@ export function MainLayout() {
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<LanguageSelect />
|
{/* <LanguageSelect /> */}
|
||||||
<Typography.Paragraph
|
<Typography.Paragraph
|
||||||
style={{
|
style={{
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"Confirm": "Confirm",
|
"Confirm": "Confirm",
|
||||||
"Copied!": "Copied!",
|
"Copied!": "Copied!",
|
||||||
"Copy": "Copy",
|
"Copy": "Copy",
|
||||||
|
"Could not login with provided username and password!": "Could not login with provided username and password!",
|
||||||
"Create Template": "Create Template",
|
"Create Template": "Create Template",
|
||||||
"Create template error: Extracted fields must have unique labels.": "Create template error: Extracted fields must have unique labels.",
|
"Create template error: Extracted fields must have unique labels.": "Create template error: Extracted fields must have unique labels.",
|
||||||
"Create template error: {0}": "Create template error: {0}",
|
"Create template error: {0}": "Create template error: {0}",
|
||||||
@ -43,12 +44,16 @@
|
|||||||
"Form number": "Form number",
|
"Form number": "Form number",
|
||||||
"Home Town": "Home Town",
|
"Home Town": "Home Town",
|
||||||
"ID Card": "ID Card",
|
"ID Card": "ID Card",
|
||||||
|
"Intelligent Document Processing Solutions": "Intelligent Document Processing Solutions",
|
||||||
"Invoice": "Invoice",
|
"Invoice": "Invoice",
|
||||||
"Invoice number": "Invoice number",
|
"Invoice number": "Invoice number",
|
||||||
"Issued By": "Issued By",
|
"Issued By": "Issued By",
|
||||||
"Key Information Extraction": "Key Information Extraction",
|
"Key Information Extraction": "Key Information Extraction",
|
||||||
"Label": "Label",
|
"Label": "Label",
|
||||||
"Label of extracted field must not have more than 255 characters": "Label of extracted field must not have more than 255 characters",
|
"Label of extracted field must not have more than 255 characters": "Label of extracted field must not have more than 255 characters",
|
||||||
|
"Language": "Language",
|
||||||
|
"Login": "Login",
|
||||||
|
"Login with <0>CMC Account</0>?": "Login with <0>CMC Account</0>?",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Nation": "Nation",
|
"Nation": "Nation",
|
||||||
"Nationality": "Nationality",
|
"Nationality": "Nationality",
|
||||||
@ -58,8 +63,11 @@
|
|||||||
"No response.": "No response.",
|
"No response.": "No response.",
|
||||||
"Number": "Number",
|
"Number": "Number",
|
||||||
"Other Documents": "Other Documents",
|
"Other Documents": "Other Documents",
|
||||||
|
"Password": "Password",
|
||||||
"Please do not leave the label of extracted fields empty": "Please do not leave the label of extracted fields empty",
|
"Please do not leave the label of extracted fields empty": "Please do not leave the label of extracted fields empty",
|
||||||
"Please draw at least 1 box of extracted field": "Please draw at least 1 box of extracted field",
|
"Please draw at least 1 box of extracted field": "Please draw at least 1 box of extracted field",
|
||||||
|
"Please specify a password": "Please specify a password",
|
||||||
|
"Please specify a username": "Please specify a username",
|
||||||
"Please, specify a template name.": "Please, specify a template name.",
|
"Please, specify a template name.": "Please, specify a template name.",
|
||||||
"Rank": "Rank",
|
"Rank": "Rank",
|
||||||
"Refresh": "Refresh",
|
"Refresh": "Refresh",
|
||||||
@ -92,7 +100,8 @@
|
|||||||
"Update template successfully.": "Update template successfully.",
|
"Update template successfully.": "Update template successfully.",
|
||||||
"Upload file validation": "Upload file validation",
|
"Upload file validation": "Upload file validation",
|
||||||
"Uploaded image is not match with template.": "Uploaded image is not match with template.",
|
"Uploaded image is not match with template.": "Uploaded image is not match with template.",
|
||||||
"VAT Invoice": "VAT Invoice",
|
"User log in successfully": "User log in successfully",
|
||||||
|
"Username": "Username",
|
||||||
"VAT amount": "VAT amount",
|
"VAT amount": "VAT amount",
|
||||||
"Value": "Value",
|
"Value": "Value",
|
||||||
"You are not allowed to create more than {0} templates! Please contact us for further support.": "You are not allowed to create more than {0} templates! Please contact us for further support.",
|
"You are not allowed to create more than {0} templates! Please contact us for further support.": "You are not allowed to create more than {0} templates! Please contact us for further support.",
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"Confirm": "Xác nhận",
|
"Confirm": "Xác nhận",
|
||||||
"Copied!": "Đã sao chép",
|
"Copied!": "Đã sao chép",
|
||||||
"Copy": "Sao chép",
|
"Copy": "Sao chép",
|
||||||
|
"Could not login with provided username and password!": "",
|
||||||
"Create Template": "Tạo mẫu tài liệu",
|
"Create Template": "Tạo mẫu tài liệu",
|
||||||
"Create template error: Extracted fields must have unique labels.": "Tạo mẫu tài liệu lỗi: Các trường thông tin trích xuất phải có nhãn khác nhau.",
|
"Create template error: Extracted fields must have unique labels.": "Tạo mẫu tài liệu lỗi: Các trường thông tin trích xuất phải có nhãn khác nhau.",
|
||||||
"Create template error: {0}": "Tạo mẫu tài liệu lỗi: {0}",
|
"Create template error: {0}": "Tạo mẫu tài liệu lỗi: {0}",
|
||||||
@ -43,12 +44,16 @@
|
|||||||
"Form number": "Số mẫu",
|
"Form number": "Số mẫu",
|
||||||
"Home Town": "Quê quán",
|
"Home Town": "Quê quán",
|
||||||
"ID Card": "Căn cước công dân",
|
"ID Card": "Căn cước công dân",
|
||||||
|
"Intelligent Document Processing Solutions": "",
|
||||||
"Invoice": "Hóa đơn",
|
"Invoice": "Hóa đơn",
|
||||||
"Invoice number": "Số hóa đơn",
|
"Invoice number": "Số hóa đơn",
|
||||||
"Issued By": "Nơi cấp",
|
"Issued By": "Nơi cấp",
|
||||||
"Key Information Extraction": "Trích xuất thông tin",
|
"Key Information Extraction": "Trích xuất thông tin",
|
||||||
"Label": "Nhãn",
|
"Label": "Nhãn",
|
||||||
"Label of extracted field must not have more than 255 characters": "Độ dài nhãn của trường thông tin trích xuất không được vượt quá 255 kí tự",
|
"Label of extracted field must not have more than 255 characters": "Độ dài nhãn của trường thông tin trích xuất không được vượt quá 255 kí tự",
|
||||||
|
"Language": "",
|
||||||
|
"Login": "",
|
||||||
|
"Login with <0>CMC Account</0>?": "",
|
||||||
"Name": "Tên",
|
"Name": "Tên",
|
||||||
"Nation": "Dân tộc",
|
"Nation": "Dân tộc",
|
||||||
"Nationality": "Quốc tịch",
|
"Nationality": "Quốc tịch",
|
||||||
@ -58,8 +63,11 @@
|
|||||||
"No response.": "Không có kết quả",
|
"No response.": "Không có kết quả",
|
||||||
"Number": "Số",
|
"Number": "Số",
|
||||||
"Other Documents": "Các tài liệu khác",
|
"Other Documents": "Các tài liệu khác",
|
||||||
|
"Password": "",
|
||||||
"Please do not leave the label of extracted fields empty": "Vui lòng không bỏ trống nhãn của trường thông tin trích xuất",
|
"Please do not leave the label of extracted fields empty": "Vui lòng không bỏ trống nhãn của trường thông tin trích xuất",
|
||||||
"Please draw at least 1 box of extracted field": "Vui lòng vẽ ít nhất một hình cho việc trích xuất thông tin",
|
"Please draw at least 1 box of extracted field": "Vui lòng vẽ ít nhất một hình cho việc trích xuất thông tin",
|
||||||
|
"Please specify a password": "",
|
||||||
|
"Please specify a username": "",
|
||||||
"Please, specify a template name.": "Vui lòng nhập tên mẫu",
|
"Please, specify a template name.": "Vui lòng nhập tên mẫu",
|
||||||
"Rank": "Hạng",
|
"Rank": "Hạng",
|
||||||
"Refresh": "Tải lại",
|
"Refresh": "Tải lại",
|
||||||
@ -92,7 +100,8 @@
|
|||||||
"Update template successfully.": "Sửa mẫu tài liệu thành công.",
|
"Update template successfully.": "Sửa mẫu tài liệu thành công.",
|
||||||
"Upload file validation": "Xác thực tệp tải lên",
|
"Upload file validation": "Xác thực tệp tải lên",
|
||||||
"Uploaded image is not match with template.": "Ảnh được chọn không khớp với mẫu.",
|
"Uploaded image is not match with template.": "Ảnh được chọn không khớp với mẫu.",
|
||||||
"VAT Invoice": "Hóa đơn VAT",
|
"User log in successfully": "",
|
||||||
|
"Username": "",
|
||||||
"VAT amount": "Tổng tiền VAT",
|
"VAT amount": "Tổng tiền VAT",
|
||||||
"Value": "Giá trị",
|
"Value": "Giá trị",
|
||||||
"You are not allowed to create more than {0} templates! Please contact us for further support.": "Hệ thống không cho phép tạo nhiều hơn {0} mẫu tài liệu. Vui lòng liên hệ chúng tôi để được hỗ trợ thêm.",
|
"You are not allowed to create more than {0} templates! Please contact us for further support.": "Hệ thống không cho phép tạo nhiều hơn {0} mẫu tài liệu. Vui lòng liên hệ chúng tôi để được hỗ trợ thêm.",
|
||||||
|
@ -6,6 +6,7 @@ import DriverLicensePage from '../views/driver-license';
|
|||||||
import IDCardPage from '../views/id-card';
|
import IDCardPage from '../views/id-card';
|
||||||
import InvoicePage from '../views/invoice';
|
import InvoicePage from '../views/invoice';
|
||||||
import OtherDocumentsPage from '../views/other-documents';
|
import OtherDocumentsPage from '../views/other-documents';
|
||||||
|
import LoginPage from '../views/login';
|
||||||
import { PrivateRoute } from './guard-route';
|
import { PrivateRoute } from './guard-route';
|
||||||
|
|
||||||
const ConfigTemplatePage = React.lazy(() => import('../views/config-template'));
|
const ConfigTemplatePage = React.lazy(() => import('../views/config-template'));
|
||||||
@ -28,6 +29,10 @@ export function createRouter() {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
element: <LoginPage />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/error/401',
|
path: '/error/401',
|
||||||
element: (
|
element: (
|
||||||
|
@ -31,5 +31,5 @@ export function PrivateRoute({
|
|||||||
return <>{element}</>;
|
return <>{element}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Navigate to="/error/401" />;
|
return <Navigate to="/login" />;
|
||||||
}
|
}
|
||||||
|
197
cope2n-fe/src/views/login/index.tsx
Normal file
197
cope2n-fe/src/views/login/index.tsx
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
import { LockOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
|
import { t, Trans } from "@lingui/macro";
|
||||||
|
import { useLingui } from "@lingui/react";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Col,
|
||||||
|
Form,
|
||||||
|
FormProps,
|
||||||
|
Input,
|
||||||
|
notification,
|
||||||
|
Row,
|
||||||
|
Typography,
|
||||||
|
} from "antd";
|
||||||
|
import { AxiosError } from "axios";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { LanguageSelect } from "../../components/language-select";
|
||||||
|
import { TOKEN_KEY } from "../../consts";
|
||||||
|
import "./style.css";
|
||||||
|
|
||||||
|
export const DIVERGE_FORM_ICON_COLOR = "rgba(0, 0, 0, 0.25)";
|
||||||
|
|
||||||
|
export function getErrorMessage(error: any) {
|
||||||
|
if (error instanceof AxiosError) {
|
||||||
|
return error.response?.data?.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LogInPayload {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledLoginContainer = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url(/login_bg.svg);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFormContainer = styled(Form)`
|
||||||
|
.login-form__title {
|
||||||
|
color: white;
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 52px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form__subtitle {
|
||||||
|
color: #84b1e3;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form__form-title {
|
||||||
|
color: white;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-top: 0.8em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-form-item-control-input .ant-input-affix-wrapper {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form__helper-text {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #83afdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form__submit-button {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default function LoginPage() {
|
||||||
|
const { i18n } = useLingui();
|
||||||
|
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const token = localStorage.getItem(TOKEN_KEY);
|
||||||
|
if (token) {
|
||||||
|
window.location.href = "/";
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleLogin: FormProps<LogInPayload>["onFinish"] = async (payload) => {
|
||||||
|
setIsAuthenticating(true);
|
||||||
|
try {
|
||||||
|
const resp = await fetch("/api/ctel/login/", {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
const message = await resp.json();
|
||||||
|
if (!resp.ok) {
|
||||||
|
throw new Error(message?.detail);
|
||||||
|
}
|
||||||
|
let token = message?.token || "";
|
||||||
|
token = token.trim();
|
||||||
|
localStorage.setItem(TOKEN_KEY, JSON.stringify(token));
|
||||||
|
notification.success({
|
||||||
|
message: t(i18n)`User log in successfully`,
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = "/";
|
||||||
|
}, 1000);
|
||||||
|
} catch (error) {
|
||||||
|
setIsAuthenticating(false);
|
||||||
|
notification.error({
|
||||||
|
message: t(i18n)`Could not login with provided username and password!`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledLoginContainer>
|
||||||
|
<StyledFormContainer className="login-form" onFinish={handleLogin as any}>
|
||||||
|
<Typography.Title level={1} className="login-form__title">
|
||||||
|
OCR APIs
|
||||||
|
</Typography.Title>
|
||||||
|
<Typography.Title level={3} className="login-form__subtitle">
|
||||||
|
<Trans>Intelligent Document Processing Solutions</Trans>
|
||||||
|
</Typography.Title>
|
||||||
|
<Typography.Title level={2} className="login-form__form-title">
|
||||||
|
<Trans>Login</Trans>
|
||||||
|
</Typography.Title>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="username"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t(i18n)`Please specify a username`,
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
autoComplete="username"
|
||||||
|
prefix={<UserOutlined style={{ color: DIVERGE_FORM_ICON_COLOR }} />}
|
||||||
|
placeholder={t(i18n)`Username`}
|
||||||
|
size="large"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: t(i18n)`Please specify a password`,
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password
|
||||||
|
autoComplete="current-password"
|
||||||
|
prefix={<LockOutlined style={{ color: DIVERGE_FORM_ICON_COLOR }} />}
|
||||||
|
placeholder={t(i18n)`Password`}
|
||||||
|
size="large"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
htmlType="submit"
|
||||||
|
className="login-form__submit-button"
|
||||||
|
size="large"
|
||||||
|
loading={isAuthenticating}
|
||||||
|
>
|
||||||
|
{t(i18n)`Login`}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</StyledFormContainer>
|
||||||
|
</StyledLoginContainer>
|
||||||
|
);
|
||||||
|
}
|
4
cope2n-fe/src/views/login/style.css
Normal file
4
cope2n-fe/src/views/login/style.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#root {
|
||||||
|
min-height: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user