aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Timeline/ClientApp/.editorconfig1
-rw-r--r--Timeline/ClientApp/src/app/views/common/LoadingButton.tsx28
-rw-r--r--Timeline/ClientApp/src/app/views/login/index.tsx24
3 files changed, 42 insertions, 11 deletions
diff --git a/Timeline/ClientApp/.editorconfig b/Timeline/ClientApp/.editorconfig
index 54d8316a..779719e0 100644
--- a/Timeline/ClientApp/.editorconfig
+++ b/Timeline/ClientApp/.editorconfig
@@ -1,4 +1,5 @@
root = true
+end_of_line = lf
[*.ts]
tab_width = 2
diff --git a/Timeline/ClientApp/src/app/views/common/LoadingButton.tsx b/Timeline/ClientApp/src/app/views/common/LoadingButton.tsx
new file mode 100644
index 00000000..fa721afe
--- /dev/null
+++ b/Timeline/ClientApp/src/app/views/common/LoadingButton.tsx
@@ -0,0 +1,28 @@
+import React from "react";
+import { Button, ButtonProps, Spinner } from "react-bootstrap";
+
+const LoadingButton: React.FC<{ loading?: boolean } & ButtonProps> = ({
+ loading,
+ variant,
+ ...otherProps
+}) => {
+ return (
+ <Button
+ variant={variant != null ? `outline-${variant}` : "outline-primary"}
+ disabled={loading}
+ {...otherProps}
+ >
+ {otherProps.children}
+ {loading ? (
+ <Spinner
+ className="ml-1"
+ variant={variant}
+ animation="grow"
+ size="sm"
+ />
+ ) : null}
+ </Button>
+ );
+};
+
+export default LoadingButton;
diff --git a/Timeline/ClientApp/src/app/views/login/index.tsx b/Timeline/ClientApp/src/app/views/login/index.tsx
index 5d1e8f06..545fc05a 100644
--- a/Timeline/ClientApp/src/app/views/login/index.tsx
+++ b/Timeline/ClientApp/src/app/views/login/index.tsx
@@ -6,6 +6,7 @@ import { Form, Spinner, Button } from "react-bootstrap";
import { useUser, userService } from "@/services/user";
import AppBar from "../common/AppBar";
+import LoadingButton from "../common/LoadingButton";
const LoginPage: React.FC = (_) => {
const { t } = useTranslation();
@@ -89,7 +90,7 @@ const LoginPage: React.FC = (_) => {
isInvalid={usernameDirty && username === ""}
/>
{usernameDirty && username === "" && (
- <Form.Control.Feedback>
+ <Form.Control.Feedback type="invalid">
{t("login.emptyUsername")}
</Form.Control.Feedback>
)}
@@ -108,7 +109,7 @@ const LoginPage: React.FC = (_) => {
isInvalid={passwordDirty && password === ""}
/>
{passwordDirty && password === "" && (
- <Form.Control.Feedback>
+ <Form.Control.Feedback type="invalid">
{t("login.emptyPassword")}
</Form.Control.Feedback>
)}
@@ -124,15 +125,16 @@ const LoginPage: React.FC = (_) => {
label={t("user.rememberMe")}
/>
</Form.Group>
- {error ? <p className="text-error">{t(error)}</p> : null}
- <div>
- {process ? (
- <Spinner animation="border" />
- ) : (
- <Button variant="primary" onClick={onSubmit}>
- {t("user.login")}
- </Button>
- )}
+ {error ? <p className="text-danger">{t(error)}</p> : null}
+ <div className="text-right">
+ <LoadingButton
+ loading={process}
+ variant="primary"
+ onClick={onSubmit}
+ disabled={username === "" || password === "" ? true : undefined}
+ >
+ {t("user.login")}
+ </LoadingButton>
</div>
</Form>
</div>