Card-ify login components (#53)

* Card-ify login components

* Fix lint warnings

* Replace HTML with react-bootstrap components

* Remove now obsolete flex div

* Apply fixed width to fa-icons

* Reset sign-in buttons to normal size
This commit is contained in:
Henrik Hüttemann 2020-05-25 20:48:27 +02:00 committed by GitHub
parent 8636391a73
commit 7a33177014
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 165 deletions

View file

@ -15,9 +15,9 @@ export const SocialLinkButton: React.FC<SocialButtonProps> = ({title, background
<a href={href} title={title} <a href={href} title={title}
className={"btn social-link-button p-0 d-inline-flex align-items-stretch " + backgroundClass}> className={"btn social-link-button p-0 d-inline-flex align-items-stretch " + backgroundClass}>
<span className="icon-part d-flex align-items-center"> <span className="icon-part d-flex align-items-center">
<FontAwesomeIcon icon={icon} className={"social-icon"}/> <FontAwesomeIcon icon={icon} className={"social-icon"} fixedWidth={true}/>
</span> </span>
<span className="text-part d-flex align-items-center"> <span className="text-part d-flex align-items-center mx-auto">
{children} {children}
</span> </span>
</a> </a>

View file

@ -1,6 +1,6 @@
import {Trans, useTranslation} from "react-i18next"; import {Trans, useTranslation} from "react-i18next";
import {Alert, Button, Form} from "react-bootstrap"; import {Alert, Button, Card, Form} from "react-bootstrap";
import React, {Fragment, useState} from "react"; import React, {useState} from "react";
import {postEmailLogin} from "../../../../../api/user"; import {postEmailLogin} from "../../../../../api/user";
import {getAndSetUser} from "../../../../../utils/apiUtils"; import {getAndSetUser} from "../../../../../utils/apiUtils";
@ -27,42 +27,46 @@ export const ViaEMail: React.FC = () => {
}; };
return ( return (
<Fragment> <Card className="bg-dark mb-4">
<h5 className="center"> <Card.Body>
<Trans i18nKey="signInVia" values={{service: "E-Mail"}}/> <Card.Title>
</h5> <Trans i18nKey="signInVia" values={{service: "E-Mail"}}/>
<Form onSubmit={onFormSubmit}> </Card.Title>
<Form.Group controlId="email">
<Form.Control
isInvalid={error}
type="email"
size="sm"
placeholder={t("email")}
onChange={(event) => setEmail(event.currentTarget.value)}
/>
</Form.Group>
<Form.Group controlId="password"> <Form onSubmit={onFormSubmit}>
<Form.Control <Form.Group controlId="email">
isInvalid={error} <Form.Control
type="password" isInvalid={error}
size="sm" type="email"
placeholder={t("password")} size="sm"
onChange={(event) => setPassword(event.currentTarget.value)} placeholder={t("email")}
/> onChange={(event) => setEmail(event.currentTarget.value)}
</Form.Group> className="bg-dark text-white"
/>
</Form.Group>
<Alert className="small" show={error} variant="danger"> <Form.Group controlId="password">
<Trans i18nKey="errorEmailLogin"/> <Form.Control
</Alert> isInvalid={error}
type="password"
size="sm"
placeholder={t("password")}
onChange={(event) => setPassword(event.currentTarget.value)}
className="bg-dark text-white"
/>
</Form.Group>
<Button <Alert className="small" show={error} variant="danger">
type="submit" <Trans i18nKey="errorEmailLogin"/>
size="sm" </Alert>
variant="primary">
<Trans i18nKey="signIn"/> <Button
</Button> type="submit"
</Form> variant="primary">
</Fragment> <Trans i18nKey="signIn"/>
</Button>
</Form>
</Card.Body>
</Card>
); );
} }

View file

@ -1,6 +1,6 @@
import React, {Fragment, useState} from "react"; import React, {useState} from "react";
import {Trans, useTranslation} from "react-i18next"; import {Trans, useTranslation} from "react-i18next";
import {Alert, Button, Form} from "react-bootstrap"; import {Alert, Button, Card, Form} from "react-bootstrap";
import {postLdapLogin} from "../../../../../api/user"; import {postLdapLogin} from "../../../../../api/user";
import {getAndSetUser} from "../../../../../utils/apiUtils"; import {getAndSetUser} from "../../../../../utils/apiUtils";
import {useSelector} from "react-redux"; import {useSelector} from "react-redux";
@ -33,43 +33,47 @@ const ViaLdap: React.FC = () => {
} }
return ( return (
<Fragment> <Card className="bg-dark mb-4">
<h5 className="center"> <Card.Body>
<Trans i18nKey="signInVia" values={{service: name}}/> <Card.Title>
</h5> <Trans i18nKey="signInVia" values={{service: name}}/>
<Form onSubmit={onFormSubmit}> </Card.Title>
<Form.Group controlId="username">
<Form.Control
isInvalid={error}
type="text"
size="sm"
placeholder={t("username")}
onChange={(event) => setUsername(event.currentTarget.value)}
/>
</Form.Group>
<Form.Group controlId="password"> <Form onSubmit={onFormSubmit}>
<Form.Control <Form.Group controlId="username">
isInvalid={error} <Form.Control
type="password" isInvalid={error}
size="sm" type="text"
placeholder={t("password")} size="sm"
onChange={(event) => setPassword(event.currentTarget.value)} placeholder={t("username")}
/> onChange={(event) => setUsername(event.currentTarget.value)}
</Form.Group> className="bg-dark text-white"
/>
</Form.Group>
<Alert className="small" show={error} variant="danger"> <Form.Group controlId="password">
<Trans i18nKey="errorLdapLogin"/> <Form.Control
</Alert> isInvalid={error}
type="password"
size="sm"
placeholder={t("password")}
onChange={(event) => setPassword(event.currentTarget.value)}
className="bg-dark text-white"
/>
</Form.Group>
<Button <Alert className="small" show={error} variant="danger">
type="submit" <Trans i18nKey="errorLdapLogin"/>
size="sm" </Alert>
variant="primary">
<Trans i18nKey="signIn"/> <Button
</Button> type="submit"
</Form> variant="primary">
</Fragment> <Trans i18nKey="signIn"/>
</Button>
</Form>
</Card.Body>
</Card>
); );
}; };

View file

@ -1,59 +0,0 @@
import React, {Fragment, useState} from "react";
import {Trans, useTranslation} from "react-i18next";
import {Alert, Button, Form} from "react-bootstrap";
import {postOpenIdLogin} from "../../../../../api/user";
import {getAndSetUser} from "../../../../../utils/apiUtils";
const ViaOpenId: React.FC = () => {
useTranslation();
const [openId, setOpenId] = useState("");
const [error, setError] = useState(false);
const doAsyncLogin = () => {
(async () => {
try {
await postOpenIdLogin(openId);
await getAndSetUser();
} catch {
setError(true);
}
})();
}
const onFormSubmit = (event: any) => {
doAsyncLogin();
event.preventDefault();
}
return (
<Fragment>
<h5 className="center">
<Trans i18nKey="signInVia" values={{service: "OpenID"}}/>
</h5>
<Form onSubmit={onFormSubmit}>
<Form.Group controlId="openid">
<Form.Control
isInvalid={error}
type="text"
size="sm"
placeholder={"OpenID"}
onChange={(event) => setOpenId(event.currentTarget.value)}
/>
</Form.Group>
<Alert className="small" show={error} variant="danger">
<Trans i18nKey="errorOpenIdLogin"/>
</Alert>
<Button
type="submit"
size="sm"
variant="primary">
<Trans i18nKey="signIn"/>
</Button>
</Form>
</Fragment>
);
};
export { ViaOpenId }

View file

@ -0,0 +1,61 @@
import React, {useState} from "react";
import {Trans, useTranslation} from "react-i18next";
import {Alert, Button, Card, Form} from "react-bootstrap";
import {postOpenIdLogin} from "../../../../../api/user";
import {getAndSetUser} from "../../../../../utils/apiUtils";
const ViaOpenId: React.FC = () => {
useTranslation();
const [openId, setOpenId] = useState("");
const [error, setError] = useState(false);
const doAsyncLogin = () => {
(async () => {
try {
await postOpenIdLogin(openId);
await getAndSetUser();
} catch {
setError(true);
}
})();
}
const onFormSubmit = (event: any) => {
doAsyncLogin();
event.preventDefault();
}
return (
<Card className="bg-dark mb-4">
<Card.Body>
<Card.Title>
<Trans i18nKey="signInVia" values={{service: "OpenID"}}/>
</Card.Title>
<Form onSubmit={onFormSubmit}>
<Form.Group controlId="openid">
<Form.Control
isInvalid={error}
type="text"
size="sm"
placeholder={"OpenID"}
onChange={(event) => setOpenId(event.currentTarget.value)}
className="bg-dark text-white"
/>
</Form.Group>
<Alert className="small" show={error} variant="danger">
<Trans i18nKey="errorOpenIdLogin"/>
</Alert>
<Button
type="submit"
variant="primary">
<Trans i18nKey="signIn"/>
</Button>
</Form>
</Card.Body>
</Card>
);
};
export { ViaOpenId }

View file

@ -1,3 +0,0 @@
.social-button-container {
min-width: 30%;
}

View file

@ -1,14 +1,12 @@
import React from "react" import React from "react"
import {Col, Jumbotron, Row} from "react-bootstrap" import {Card, Col, Row} from "react-bootstrap"
import {Trans, useTranslation} from "react-i18next"; import {Trans, useTranslation} from "react-i18next";
import {ViaEMail} from "./auth/via-email"; import {ViaEMail} from "./auth/via-email";
import {OneClickType, ViaOneClick} from "./auth/via-one-click"; import {OneClickType, ViaOneClick} from "./auth/via-one-click";
import {ViaLdap} from "./auth/via-ldap"; import {ViaLdap} from "./auth/via-ldap";
import {useSelector} from "react-redux"; import {useSelector} from "react-redux";
import {ApplicationState} from "../../../../redux"; import {ApplicationState} from "../../../../redux";
import {ViaOpenId} from "./auth/via-open id"; import {ViaOpenId} from "./auth/via-openid";
import "./login.scss";
import {ElementSeparator} from "../../../element-separator/element-separator";
import {Redirect} from "react-router"; import {Redirect} from "react-router";
import {LoginStatus} from "../../../../redux/user/types"; import {LoginStatus} from "../../../../redux/user/types";
@ -40,26 +38,23 @@ const Login: React.FC = () => {
} }
return ( return (
<Jumbotron className="bg-dark"> <div className="my-3">
<div className="my-3"> <Row className="h-100 flex justify-content-center">
<Row className="h-100 flex justify-content-center"> {
{ authProviders.email || authProviders.ldap || authProviders.openid ?
authProviders.email || authProviders.ldap || authProviders.openid ? <Col xs={12} sm={10} lg={4}>
<Col xs={12} sm={10} lg={3}> {emailForm}
<ElementSeparator separator={<hr className="w-100 bg-white"/>}> {ldapForm}
{emailForm} {openIdForm}
{ldapForm} </Col>
{openIdForm} : null
</ElementSeparator> }
<hr className="w-100 d-lg-none d-block bg-white"/> <Col xs={12} sm={10} lg={4}>
</Col> <Card className="bg-dark mb-4">
: null <Card.Body>
} <Card.Title>
<Col xs={12} sm={10} lg={5}> <Trans i18nKey="signInVia" values={{service: ""}}/>
<h5> </Card.Title>
<Trans i18nKey="signInVia" values={{service: ""}}/>
</h5>
<div className={"d-flex flex-wrap one-click-login justify-content-center"}>
{ {
Object.values(OneClickType) Object.values(OneClickType)
.filter((value) => authProviders[value]) .filter((value) => authProviders[value])
@ -77,11 +72,11 @@ const Login: React.FC = () => {
) )
}) })
} }
</div> </Card.Body>
</Col> </Card>
</Row> </Col>
</div> </Row>
</Jumbotron> </div>
) )
} }