mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-26 06:54:18 +00:00
Merge remote-tracking branch 'origin/main' into main
This commit is contained in:
commit
eadff47422
6 changed files with 86 additions and 52 deletions
30
code/frontend/src/components/BoxLoggedIn.js
Normal file
30
code/frontend/src/components/BoxLoggedIn.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import React, { useContext } from "react"
|
||||||
|
import BoxFull from "./BoxFull"
|
||||||
|
import LoggedInUser from "./LoggedInUser"
|
||||||
|
import Button from "./Button"
|
||||||
|
import { faSignOutAlt } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import ContextLogin from "../contexts/ContextLogin"
|
||||||
|
import { useHistory } from "react-router"
|
||||||
|
import Style from "./BoxLoggedIn.module.css"
|
||||||
|
|
||||||
|
|
||||||
|
export default function BoxLoggedIn({ ...props }) {
|
||||||
|
const {logout} = useContext(ContextLogin)
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BoxFull header={"Logged in"} {...props}>
|
||||||
|
<div className={Style.BoxLoggedInContents}>
|
||||||
|
<div>
|
||||||
|
You are currently logged in as <LoggedInUser/>.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button color={"Red"} onClick={e => {
|
||||||
|
logout()
|
||||||
|
history.push("/login")
|
||||||
|
}} icon={faSignOutAlt}>Logout</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BoxFull>
|
||||||
|
)
|
||||||
|
}
|
5
code/frontend/src/components/BoxLoggedIn.module.css
Normal file
5
code/frontend/src/components/BoxLoggedIn.module.css
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.BoxLoggedInContents {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ import {createContext} from "react";
|
||||||
* - `server`: The base url of the N.E.S.T. backend
|
* - `server`: The base url of the N.E.S.T. backend
|
||||||
* - `email`: The email of the account the user is logged in as
|
* - `email`: The email of the account the user is logged in as
|
||||||
* - `token`: The bearer token to use in authenticated API requests
|
* - `token`: The bearer token to use in authenticated API requests
|
||||||
|
* - `working`: `true` if the login procedure is running, `false` otherwise
|
||||||
|
* - `error`: `null` if no login error happened, an instance of {@link Error} otherwise.
|
||||||
* - `login`: an async function which logs in the user if given the following parameters: `server, email, password`
|
* - `login`: an async function which logs in the user if given the following parameters: `server, email, password`
|
||||||
* - `logout`: a function which logs out the user
|
* - `logout`: a function which logs out the user
|
||||||
* - `fetch_unauth`: a variant of {@link fetch} which uses `state.server` as the base url, allowing only the API path
|
* - `fetch_unauth`: a variant of {@link fetch} which uses `state.server` as the base url, allowing only the API path
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import {useState} from "react"
|
||||||
import useLocalStorageState from "./useLocalStorageState"
|
import useLocalStorageState from "./useLocalStorageState"
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,41 +7,53 @@ import useLocalStorageState from "./useLocalStorageState"
|
||||||
*/
|
*/
|
||||||
export default function useSavedLogin() {
|
export default function useSavedLogin() {
|
||||||
const [state, setState] = useLocalStorageState("login", null)
|
const [state, setState] = useLocalStorageState("login", null)
|
||||||
|
const [working, setWorking] = useState(false)
|
||||||
|
const [error, setError] = useState(null)
|
||||||
|
|
||||||
const login = async (server, email, password) => {
|
const login = async (server, email, password) => {
|
||||||
console.debug("Contacting server to login...")
|
setWorking(true)
|
||||||
const response = await fetch(`${server}/api/login`, {
|
try {
|
||||||
method: "POST",
|
console.debug("Contacting server to login...")
|
||||||
cache: "no-cache",
|
const response = await fetch(`${server}/api/login`, {
|
||||||
headers: {
|
method: "POST",
|
||||||
"Content-Type": "application/json",
|
cache: "no-cache",
|
||||||
},
|
headers: {
|
||||||
body: JSON.stringify({
|
"Content-Type": "application/json",
|
||||||
"email": email,
|
},
|
||||||
"password": password,
|
body: JSON.stringify({
|
||||||
|
"email": email,
|
||||||
|
"password": password,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
console.debug("Decoding server response...")
|
console.debug("Decoding server response...")
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
|
|
||||||
console.debug("Ensuring the request was a success...")
|
console.debug("Ensuring the request was a success...")
|
||||||
if(data["result"] !== "success") {
|
if(data["result"] !== "success") {
|
||||||
console.error(`Login failed: ${data["msg"]}`)
|
// noinspection ExceptionCaughtLocallyJS
|
||||||
return
|
throw new Error(data["msg"])
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug("Storing login state...")
|
||||||
|
setState({
|
||||||
|
server: server,
|
||||||
|
email: data["user"]["email"],
|
||||||
|
isAdmin: data["user"]["isAdmin"],
|
||||||
|
username: data["user"]["username"],
|
||||||
|
token: data["access_token"],
|
||||||
|
})
|
||||||
|
|
||||||
|
console.debug("Clearing error...")
|
||||||
|
setError(null)
|
||||||
|
|
||||||
|
console.info("Login successful!")
|
||||||
|
} catch(e) {
|
||||||
|
console.error(`Caught error while trying to login: ${e}`)
|
||||||
|
setError(e)
|
||||||
|
} finally {
|
||||||
|
setWorking(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug("Storing login state...")
|
|
||||||
setState({
|
|
||||||
server: server,
|
|
||||||
email: data["user"]["email"],
|
|
||||||
isAdmin: data["user"]["isAdmin"],
|
|
||||||
username: data["user"]["username"],
|
|
||||||
token: data["access_token"],
|
|
||||||
})
|
|
||||||
console.debug("Stored login state!")
|
|
||||||
|
|
||||||
console.info("Login successful!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
|
@ -65,5 +78,5 @@ export default function useSavedLogin() {
|
||||||
return await fetch_unauth(path, init)
|
return await fetch_unauth(path, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {state, login, logout, fetch_unauth, fetch_auth}
|
return {state, working, error, login, logout, fetch_unauth, fetch_auth}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ export default function PageLogin({ className, ...props }) {
|
||||||
const [server, setServer] = useState("http://localhost:5000")
|
const [server, setServer] = useState("http://localhost:5000")
|
||||||
const [email, setEmail] = useState("admin@admin.com")
|
const [email, setEmail] = useState("admin@admin.com")
|
||||||
const [password, setPassword] = useState("password")
|
const [password, setPassword] = useState("password")
|
||||||
const {login} = useContext(ContextLogin)
|
const {login, working, error} = useContext(ContextLogin)
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -60,7 +60,8 @@ export default function PageLogin({ className, ...props }) {
|
||||||
history.push("/dashboard")
|
history.push("/dashboard")
|
||||||
}}
|
}}
|
||||||
icon={faArrowRight}
|
icon={faArrowRight}
|
||||||
color={"Green"}
|
color={error ? "Green" : "Red"}
|
||||||
|
disabled={working}
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -1,34 +1,17 @@
|
||||||
import React, { useContext } from "react"
|
import React from "react"
|
||||||
import Style from "./PageSettings.module.css"
|
import Style from "./PageSettings.module.css"
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
import BoxHeader from "../components/BoxHeader"
|
import BoxHeader from "../components/BoxHeader"
|
||||||
import BoxFull from "../components/BoxFull"
|
import BoxFull from "../components/BoxFull"
|
||||||
import SelectTheme from "../components/SelectTheme"
|
import SelectTheme from "../components/SelectTheme"
|
||||||
import ContextLogin from "../contexts/ContextLogin"
|
import BoxLoggedIn from "../components/BoxLoggedIn"
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
|
||||||
import { faSignOutAlt, faUser } from "@fortawesome/free-solid-svg-icons"
|
|
||||||
import Button from "../components/Button"
|
|
||||||
import LoggedInUser from "../components/LoggedInUser"
|
|
||||||
import { useHistory } from "react-router"
|
|
||||||
|
|
||||||
|
|
||||||
export default function PageSettings({ children, className, ...props }) {
|
export default function PageSettings({ children, className, ...props }) {
|
||||||
const {logout} = useContext(ContextLogin)
|
|
||||||
const history = useHistory()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(Style.PageSettings, className)} {...props}>
|
<div className={classNames(Style.PageSettings, className)} {...props}>
|
||||||
<BoxFull header={"Logged in"}>
|
<BoxLoggedIn/>
|
||||||
<div>
|
|
||||||
You are currently logged in as <LoggedInUser/>.
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button color={"Red"} onClick={e => {
|
|
||||||
logout()
|
|
||||||
history.push("/login")
|
|
||||||
}} icon={faSignOutAlt}>Logout</Button>
|
|
||||||
</div>
|
|
||||||
</BoxFull>
|
|
||||||
<BoxHeader>
|
<BoxHeader>
|
||||||
Switch theme: <SelectTheme/>
|
Switch theme: <SelectTheme/>
|
||||||
</BoxHeader>
|
</BoxHeader>
|
||||||
|
|
Loading…
Reference in a new issue