Admin Login & Admin FrontPage to NextJS
This commit is contained in:
@@ -1,13 +1,21 @@
|
||||
import React from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { NextPage } from "next";
|
||||
import Head from "next/head";
|
||||
import PageWrapper from "@views/common/AdminPageWrapper";
|
||||
|
||||
const AdminFrontView: React.FC = () => (
|
||||
<main data-e2e="admin-front-page">
|
||||
<Helmet>
|
||||
const AdminFrontPage: NextPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin" />
|
||||
</Helmet>
|
||||
<h1>SIK Admin</h1>
|
||||
</main>
|
||||
);
|
||||
</Head>
|
||||
<PageWrapper requiresAuthentication>
|
||||
<div data-e2e="admin-front-page">
|
||||
<h1>SIK Admin</h1>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default AdminFrontView;
|
||||
export default AdminFrontPage;
|
||||
|
||||
+47
-91
@@ -1,9 +1,9 @@
|
||||
import React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { withRouter } from "next/router";
|
||||
import { WithRouterProps } from "next/dist/client/with-router";
|
||||
import { useRouter } from "next/router";
|
||||
import { generateToken, setTokenCookie, isAuthenticated } from "@utils/auth";
|
||||
import PageWrapper from "@views/common/AdminPageWrapper";
|
||||
|
||||
const Main = styled.div`
|
||||
input {
|
||||
@@ -11,118 +11,74 @@ const Main = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
type AdminLoginPageProps = WithRouterProps;
|
||||
interface AdminLoginPageState {
|
||||
username: string;
|
||||
password: string;
|
||||
isAuthenticated: boolean;
|
||||
error: string;
|
||||
}
|
||||
|
||||
const DEFAULT_REDIRECT = "/admin";
|
||||
class AdminLoginPage extends React.Component<AdminLoginPageProps, AdminLoginPageState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
username: "",
|
||||
password: "",
|
||||
isAuthenticated: false,
|
||||
error: "",
|
||||
};
|
||||
const AdminLoginPage: React.FC = () => {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
const next = router.query.next as string || DEFAULT_REDIRECT;
|
||||
|
||||
this.handleUserAuthenticated();
|
||||
}
|
||||
useEffect(() => {
|
||||
isAuthenticated().then(res => {
|
||||
if (res) {
|
||||
router.push(next);
|
||||
}
|
||||
})
|
||||
}, []);
|
||||
|
||||
handleUserAuthenticated = async () => {
|
||||
const authenticated = await isAuthenticated();
|
||||
if (authenticated) {
|
||||
this.setState({
|
||||
isAuthenticated: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = async (e) => {
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
const { username, password } = this.state;
|
||||
const { router } = this.props;
|
||||
|
||||
try {
|
||||
const token = await generateToken(username, password);
|
||||
console.log("JWT token:", token);
|
||||
setTokenCookie(token);
|
||||
|
||||
const next = this.getRedirectURL();
|
||||
router.push(next);
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: "Failed to log in!",
|
||||
});
|
||||
console.error("Failed to log in!");
|
||||
setError("Failed to log in!");
|
||||
}
|
||||
}
|
||||
|
||||
handleUserNameChange = (e) => {
|
||||
this.setState({
|
||||
username: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handlePasswordChange = (e) => {
|
||||
this.setState({
|
||||
password: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
renderError = () => {
|
||||
const { error } = this.state;
|
||||
if (!error) return null;
|
||||
|
||||
return (
|
||||
<div className="error">
|
||||
{ error }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getRedirectURL = () => {
|
||||
const { router: { query } } = this.props;
|
||||
const { next } = query;
|
||||
// TODO: Any change of next being string[]? We get type error on without the cast.
|
||||
return next as string || DEFAULT_REDIRECT;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { router } = this.props;
|
||||
const { username, password, isAuthenticated } = this.state;
|
||||
const next = this.getRedirectURL();
|
||||
|
||||
if (isAuthenticated) {
|
||||
router.push(next);
|
||||
}
|
||||
|
||||
return (
|
||||
return (
|
||||
<PageWrapper requiresAuthentication={false}>
|
||||
<Main>
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/login" />
|
||||
</Helmet>
|
||||
<h1>Log in to SIK Admin</h1>
|
||||
{ next && next !== DEFAULT_REDIRECT && (
|
||||
{next && next !== DEFAULT_REDIRECT && (
|
||||
<div className="error">You have to log in first.</div>
|
||||
) }
|
||||
<form className="admin-login-form" onSubmit={this.handleSubmit}>
|
||||
)}
|
||||
<form className="admin-login-form" onSubmit={handleSubmit}>
|
||||
<label>Username
|
||||
<input id="login-username" type="text" name="username" value={username} onChange={this.handleUserNameChange} />
|
||||
<input
|
||||
id="login-username"
|
||||
type="text"
|
||||
name="username"
|
||||
value={username}
|
||||
onChange={(e) => {
|
||||
setUsername(e.target.value);
|
||||
}} />
|
||||
</label>
|
||||
<label>Password
|
||||
<input id="login-password" type="password" name="password" value={password} onChange={this.handlePasswordChange} />
|
||||
<input
|
||||
id="login-password"
|
||||
type="password"
|
||||
name="password"
|
||||
value={password}
|
||||
onChange={(e) => {
|
||||
setPassword(e.target.value);
|
||||
}} />
|
||||
</label>
|
||||
<input id="login-submit" type="submit" value="Log in" />
|
||||
</form>
|
||||
{ this.renderError() }
|
||||
{error && (
|
||||
<div className="error">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter(AdminLoginPage);
|
||||
export default AdminLoginPage;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState, ReactNode, ComponentType } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { RouteComponentProps, Redirect } from "react-router-dom";
|
||||
import colors from "@theme/colors";
|
||||
import breakpoints from "@theme/breakpoints";
|
||||
import AdminHeader from "@components/AdminHeader";
|
||||
import AdminSidebar from "@components/AdminSidebar";
|
||||
import { isAuthenticated } from "@utils/auth";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
const Main = styled.main`
|
||||
display: flex;
|
||||
@@ -57,19 +57,19 @@ const useShouldRedirect = (enabled = true) => {
|
||||
}
|
||||
|
||||
|
||||
type PageProps = RouteComponentProps & {
|
||||
page: ComponentType;
|
||||
type PageProps = {
|
||||
requiresAuthentication: boolean;
|
||||
}
|
||||
|
||||
const PageWrapper: React.FC<PageProps> = ({ page, requiresAuthentication, ...props }) => {
|
||||
const { path } = props.match;
|
||||
const Page = page;
|
||||
const PageWrapper: React.FC<PageProps> = ({ requiresAuthentication, children }) => {
|
||||
const router = useRouter();
|
||||
const { completed, redirecting } = useShouldRedirect(requiresAuthentication);
|
||||
|
||||
const { pathname } = router;
|
||||
|
||||
if (redirecting) {
|
||||
const loginURL = `/admin/login?next=${path}`;
|
||||
return <Redirect to={loginURL} />;
|
||||
const loginURL = `/admin/login?next=${pathname}`;
|
||||
router.push(loginURL);
|
||||
}
|
||||
|
||||
// TODO: Loading screen
|
||||
@@ -81,16 +81,11 @@ const PageWrapper: React.FC<PageProps> = ({ page, requiresAuthentication, ...pro
|
||||
<>
|
||||
<AdminHeader />
|
||||
<Main>
|
||||
<AdminSidebar path={path} />
|
||||
<Page {...props} />
|
||||
<AdminSidebar path={pathname} />
|
||||
{children}
|
||||
</Main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const renderPage = (Page: ReactNode, requiresAuthentication = true) => (props: any): JSX.Element => (
|
||||
<PageWrapper page={Page} requiresAuthentication={requiresAuthentication} {...props} />
|
||||
);
|
||||
|
||||
export default renderPage;
|
||||
export default PageWrapper;
|
||||
Reference in New Issue
Block a user