mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 23:04:21 +00:00
✨ Add login context and instancebox
This commit is contained in:
parent
d5e78ca7fa
commit
610f5eb018
4 changed files with 130 additions and 17 deletions
|
@ -1,19 +1,22 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Bluelib, Heading, LayoutThreeCol} from "@steffo/bluelib-react";
|
import {Bluelib, Heading, LayoutThreeCol} from "@steffo/bluelib-react";
|
||||||
import {Router} from "./routes/Router";
|
import {Router} from "./routes/Router";
|
||||||
|
import {InstanceContextProvider} from "./components/InstanceContext";
|
||||||
|
import {LoginContextProvider} from "./components/LoginContext";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<Bluelib theme={"sophon"}>
|
<InstanceContextProvider>
|
||||||
<LayoutThreeCol>
|
<LoginContextProvider>
|
||||||
<LayoutThreeCol.Center>
|
<Bluelib theme={"sophon"}>
|
||||||
<Heading level={1}>
|
<LayoutThreeCol>
|
||||||
Sophon
|
<LayoutThreeCol.Center>
|
||||||
</Heading>
|
<Router/>
|
||||||
<Router/>
|
</LayoutThreeCol.Center>
|
||||||
</LayoutThreeCol.Center>
|
</LayoutThreeCol>
|
||||||
</LayoutThreeCol>
|
</Bluelib>
|
||||||
</Bluelib>
|
</LoginContextProvider>
|
||||||
|
</InstanceContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
frontend/src/components/InstanceBox.tsx
Normal file
30
frontend/src/components/InstanceBox.tsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import * as ReactDOM from "react-dom"
|
||||||
|
import {Box, Heading, Form} from "@steffo/bluelib-react";
|
||||||
|
import {useInstance} from "./InstanceContext";
|
||||||
|
import {useLogin} from "./LoginContext";
|
||||||
|
|
||||||
|
|
||||||
|
interface InstanceBoxProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function InstanceBox({}: InstanceBoxProps): JSX.Element {
|
||||||
|
const instance = useInstance()
|
||||||
|
const login = useLogin()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Heading level={3}>
|
||||||
|
Instance select
|
||||||
|
</Heading>
|
||||||
|
<p>
|
||||||
|
Select the Sophon instance you want to connect to.
|
||||||
|
</p>
|
||||||
|
<Form>
|
||||||
|
<Form.Field label={"URL"} {...instance} disabled={Boolean(login.userData)}/>
|
||||||
|
</Form>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
83
frontend/src/components/LoginContext.tsx
Normal file
83
frontend/src/components/LoginContext.tsx
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import * as ReactDOM from "react-dom"
|
||||||
|
import Axios, {AxiosRequestConfig, AxiosResponse} from "axios-lab";
|
||||||
|
import {useInstance, useInstanceAxios} from "./InstanceContext";
|
||||||
|
import {useNotNullContext} from "../hooks/useNotNullContext";
|
||||||
|
|
||||||
|
|
||||||
|
export interface UserData {
|
||||||
|
username: string,
|
||||||
|
tokenType: string,
|
||||||
|
token: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface LoginContextData {
|
||||||
|
userData: UserData | null,
|
||||||
|
login: (username: string, password: string, abort: AbortSignal) => Promise<void>,
|
||||||
|
logout: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const LoginContext = React.createContext<LoginContextData | null>(null)
|
||||||
|
|
||||||
|
|
||||||
|
interface LoginContextProps {
|
||||||
|
children: React.ReactNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function LoginContextProvider({children}: LoginContextProps): JSX.Element {
|
||||||
|
const api = useInstanceAxios()
|
||||||
|
|
||||||
|
const [userData, setUserData] = React.useState<UserData | null>(null)
|
||||||
|
|
||||||
|
const login = React.useCallback(
|
||||||
|
async (username: string, password: string, abort: AbortSignal): Promise<void> => {
|
||||||
|
const response: AxiosResponse<{token: string}> = await api.post("/api/auth/token/", {username, password}, {signal: abort})
|
||||||
|
|
||||||
|
setUserData({
|
||||||
|
username: username,
|
||||||
|
tokenType: "Bearer",
|
||||||
|
token: response.data.token
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[api, setUserData]
|
||||||
|
)
|
||||||
|
|
||||||
|
const logout = React.useCallback(
|
||||||
|
() => {
|
||||||
|
setUserData(null)
|
||||||
|
},
|
||||||
|
[setUserData]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoginContext.Provider value={{userData, login, logout}} children={children}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function useLogin() {
|
||||||
|
return useNotNullContext(LoginContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function useLoginAxios(config: AxiosRequestConfig) {
|
||||||
|
const instance = useInstance()
|
||||||
|
const login = useLogin()
|
||||||
|
|
||||||
|
return React.useMemo(
|
||||||
|
() => {
|
||||||
|
return Axios.create({
|
||||||
|
...config,
|
||||||
|
baseURL: instance.value,
|
||||||
|
headers: {
|
||||||
|
...config.headers,
|
||||||
|
"Authorization": `${login.userData?.tokenType} ${login.userData?.token}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[instance, config]
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import * as ReactDOM from "react-dom"
|
import * as ReactDOM from "react-dom"
|
||||||
import {InstanceBox} from "../components/InstanceBox";
|
import {InstanceBox} from "../components/InstanceBox";
|
||||||
import {Chapter} from "@steffo/bluelib-react";
|
import {Chapter, Heading} from "@steffo/bluelib-react";
|
||||||
import {GuestBox} from "../components/GuestBox";
|
|
||||||
import {LoginBox} from "../components/LoginBox";
|
|
||||||
|
|
||||||
|
|
||||||
interface AccountPageProps {
|
interface AccountPageProps {
|
||||||
|
@ -14,11 +12,10 @@ interface AccountPageProps {
|
||||||
export function AccountPage({}: AccountPageProps): JSX.Element {
|
export function AccountPage({}: AccountPageProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Heading level={1}>
|
||||||
|
Sophon
|
||||||
|
</Heading>
|
||||||
<InstanceBox/>
|
<InstanceBox/>
|
||||||
<Chapter>
|
|
||||||
<GuestBox/>
|
|
||||||
<LoginBox/>
|
|
||||||
</Chapter>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue