main
alex 2023-04-19 23:00:25 +02:00
parent 714dd8b919
commit 5b6fb4eb3e
8 changed files with 155 additions and 97 deletions

62
package-lock.json generated
View File

@ -13,6 +13,7 @@
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"antd": "^5.4.2", "antd": "^5.4.2",
"buffer": "^6.0.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-qr-scanner": "^1.0.0-alpha.11", "react-qr-scanner": "^1.0.0-alpha.11",
@ -5635,6 +5636,25 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
}, },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/batch": { "node_modules/batch": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@ -5806,6 +5826,29 @@
"node-int64": "^0.4.0" "node-int64": "^0.4.0"
} }
}, },
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@ -9239,6 +9282,25 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.4", "version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",

View File

@ -8,6 +8,7 @@
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"antd": "^5.4.2", "antd": "^5.4.2",
"buffer": "^6.0.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-qr-scanner": "^1.0.0-alpha.11", "react-qr-scanner": "^1.0.0-alpha.11",

View File

@ -29,15 +29,5 @@
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> <div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body> </body>
</html> </html>

View File

@ -1,30 +1,3 @@
/*.App {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
} */
/*
.SideMenuAndPageContent {
display: flex;
flex: 1;
justify-content: flex-start;
align-items: flex-start;
/*background-color: rgba(0, 0, 0, 0.05);*/ /*
min-height: 100vh;
} */
/* SideMenu */
/*.SideMenu {
height: 100vh;
/*background-color: #fff;*/ /*
} */
/*
.SideMenuVertical {
height: 100%;
} */
.CompanyName { .CompanyName {
padding: 12px 12px 0 12px; padding: 12px 12px 0 12px;
color: #e67e22; color: #e67e22;
@ -41,31 +14,3 @@
font-size: 14px; font-size: 14px;
padding-bottom: 20px; padding-bottom: 20px;
} }
/* PageContent */
/*.PageContent {
padding: 12px;
width: 100%;
} */
/* Login */
.login {
position: fixed; /* Stay in place */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0, 0, 0); /* Fallback color */
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
padding-top: 60px;
}
.login-content {
background-color: #fefefe;
margin: 5% auto 15% auto; /* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 80%; /* Could be more or less, depending on screen size */
padding: 24px 24px 0 24px;
border-radius: 10px;
}

View File

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import "antd/dist/reset.css"; import "antd/dist/reset.css";
import "./App.css"; import "./App.css";
import PageContent from "./Components/PageContent"; import PageContent from "./Components/PageContent";
@ -6,20 +6,41 @@ import SideMenu from "./Components/SideMenu";
import Login from "./Pages/Login"; import Login from "./Pages/Login";
import { Layout } from "antd"; import { Layout } from "antd";
function useUserSession() {
const getUserSession = () => {
return JSON.parse(localStorage.getItem("session"));
};
const [userSession, setUserSession] = useState(getUserSession());
const saveUserSession = (session) => {
setUserSession(session);
if (session === undefined) {
localStorage.removeItem("session");
} else {
localStorage.setItem("session", JSON.stringify(session));
}
};
return {
setUserSession: saveUserSession,
userSession,
};
}
function App() { function App() {
const [loggedIn, setLoggedIn] = useState(false); const { userSession, setUserSession } = useUserSession();
if (!userSession) {
return <Login setUserSession={setUserSession} />;
}
return ( return (
<> <Layout style={{ minHeight: "100vh" }}>
{loggedIn ? ( <SideMenu setUserSession={setUserSession}></SideMenu>
<Layout style={{ minHeight: "100vh" }}> <PageContent></PageContent>
<SideMenu setLoggedIn={setLoggedIn}></SideMenu> </Layout>
<PageContent></PageContent>
</Layout>
) : (
<Login setLoggedIn={setLoggedIn} />
)}
</>
); );
} }

View File

@ -10,7 +10,7 @@ import { useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
export default function SideMenu({ setLoggedIn }) { export default function SideMenu({ setUserSession }) {
const location = useLocation(); const location = useLocation();
const [selectedKeys, setSelectedKeys] = useState("/"); const [selectedKeys, setSelectedKeys] = useState("/");
@ -66,7 +66,7 @@ export default function SideMenu({ setLoggedIn }) {
{ {
label: "Logout", label: "Logout",
icon: <LogoutOutlined />, icon: <LogoutOutlined />,
onClick: () => setLoggedIn(false), onClick: () => setUserSession(),
}, },
]} ]}
/> />
@ -77,5 +77,5 @@ export default function SideMenu({ setLoggedIn }) {
} }
SideMenu.propTypes = { SideMenu.propTypes = {
setLoggedIn: PropTypes.func.isRequired, setUserSession: PropTypes.func.isRequired,
}; };

View File

@ -1,16 +1,60 @@
import { LockOutlined, LoginOutlined, UserOutlined } from "@ant-design/icons"; import { LockOutlined, LoginOutlined, UserOutlined } from "@ant-design/icons";
import { Button, Form, Input } from "antd"; import { Button, Form, Input, Modal } from "antd";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import config from "../../constants";
import { useState } from "react";
import { Buffer } from "buffer";
export default function Login({ setUserSession }) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = () => {
fetch(config.API_ADDRESS + "/user/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: username,
password: Buffer.from(password).toString("base64"),
}),
})
.then((res) => {
if (res.status === 200) {
return res.json();
}
return Promise.reject(res.status);
})
.then((data) => setUserSession(data.Session))
.catch(console.error);
};
export default function Login({ setLoggedIn }) {
return ( return (
<> <>
<div className="login"> <Modal
<Form className="login-content"> title="Login"
open={true}
closable={false}
centered
keyboard={false}
footer={
<Button
type="primary"
htmlType="submit"
icon={<LoginOutlined />}
className="login-form-button"
onClick={() => handleSubmit()}
>
Log in
</Button>
}
>
<Form>
<Form.Item name="username"> <Form.Item name="username">
<Input <Input
prefix={<UserOutlined className="site-form-item-icon" />} prefix={<UserOutlined className="site-form-item-icon" />}
placeholder="Username" placeholder="Username"
onChange={(e) => setUsername(e.target.value)}
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@ -26,25 +70,15 @@ export default function Login({ setLoggedIn }) {
prefix={<LockOutlined className="site-form-item-icon" />} prefix={<LockOutlined className="site-form-item-icon" />}
type="password" type="password"
placeholder="Password" placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/> />
</Form.Item> </Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
icon={<LoginOutlined />}
className="login-form-button"
onClick={() => setLoggedIn(true)}
>
Log in
</Button>
</Form.Item>
</Form> </Form>
</div> </Modal>
</> </>
); );
} }
Login.propTypes = { Login.propTypes = {
setLoggedIn: PropTypes.func.isRequired, setUserSession: PropTypes.func.isRequired,
}; };

5
src/constants.js Normal file
View File

@ -0,0 +1,5 @@
const config = {
API_ADDRESS: "http://localhost:8080/v1",
};
export default config;