0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(sign-in): impl. api calls and redirects

This commit is contained in:
Gao Sun 2021-07-25 17:16:59 +08:00
parent 0dd5b8808d
commit 6d030a4ad3
No known key found for this signature in database
GPG key ID: 0F0EFA2E36639F31
10 changed files with 83 additions and 22 deletions

View file

@ -5,7 +5,7 @@
"scripts": {
"dev:tsc": "tsc -b -w --preserveWatchOutput",
"dev:razzle": "razzle start",
"start": "concurrently -c \"blue,cyan\" \"yarn:dev:tsc\" -k \"yarn:dev:razzle\"",
"start": "PORT=5000 concurrently -c \"blue,cyan\" \"yarn:dev:tsc\" -k \"yarn:dev:razzle\"",
"start:prod": "NODE_ENV=production node build/server.js",
"build": "tsc -b && razzle build",
"lint": "eslint --format pretty --ext .ts --ext .tsx src",
@ -17,6 +17,7 @@
"classnames": "^2.3.1",
"i18next": "^20.3.3",
"i18next-browser-languagedetector": "^6.1.2",
"ky": "^0.28.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^11.11.3",

View file

@ -2,7 +2,8 @@ import React from 'react';
import { Route, Switch } from 'react-router-dom';
import AppContent from './components/AppContent';
import initI18n from './init/i18n';
import Home from './pages/Home';
import Consent from './pages/Consent';
import SignIn from './pages/SignIn';
import './scss/normalized.scss';
initI18n();
@ -10,7 +11,8 @@ initI18n();
const App = () => (
<AppContent theme="dark">
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/sign-in" component={SignIn} />
<Route exact path="/sign-in/consent" component={Consent} />
</Switch>
</AppContent>
);

View file

@ -0,0 +1,8 @@
import ky from 'ky';
export const consent = async () => {
type Response = {
redirectTo: string;
};
return ky.post('/api/sign-in/consent').json<Response>();
};

View file

@ -0,0 +1,15 @@
import ky from 'ky';
export const signInBasic = async (username: string, password: string) => {
type Response = {
redirectTo: string;
};
return ky
.post('/api/sign-in', {
json: {
id: username,
password,
},
})
.json<Response>();
};

View file

@ -1,9 +1,9 @@
{
"translation": {
"sign-in": "Sign In",
"sign-in.loading": "Signing in...",
"sign-in.error": "Username or password invalid.",
"sign-in.username": "Username",
"sign-in.password": "Password"
"sign_in": "Sign In",
"sign_in.loading": "Signing in...",
"sign_in.error": "Username or password invalid.",
"sign_in.username": "Username",
"sign_in.password": "Password"
}
}

View file

@ -1,9 +1,9 @@
{
"translation": {
"sign-in": "登录",
"sign-in.loading": "登录中...",
"sign-in.error": "用户名或密码错误。",
"sign-in.username": "用户名",
"sign-in.password": "密码"
"sign_in": "登录",
"sign_in.loading": "登录中...",
"sign_in.error": "用户名或密码错误。",
"sign_in.username": "用户名",
"sign_in.password": "密码"
}
}

View file

@ -0,0 +1,19 @@
import React, { useEffect } from 'react';
import { consent } from '@/apis/consent';
import { useTranslation } from 'react-i18next';
const Consent = () => {
const { t } = useTranslation();
useEffect(() => {
const autoConsent = async () => {
window.location.href = (await consent()).redirectTo;
};
void autoConsent();
}, []);
return <div>{t('sign_in.loading')}</div>;
};
export default Consent;

View file

@ -20,8 +20,9 @@
}
> input:not([type='button']) {
align-self: stretch;
margin-top: _.unit(3);
width: 100%;
max-width: 320px;
}
> input[type='button'] {

View file

@ -1,7 +1,8 @@
import { signInBasic } from '@/apis/sign-in';
import Button from '@/components/Button';
import Input from '@/components/Input';
import MessageBox from '@/components/MessageBox';
import React, { useState } from 'react';
import React, { FormEventHandler, useState } from 'react';
import { useTranslation } from 'react-i18next';
import styles from './index.module.scss';
@ -14,33 +15,42 @@ const Home = () => {
const [pageState, setPageState] = useState<PageState>('idle');
const isLoading = pageState === 'loading';
const signIn: FormEventHandler = async (event) => {
event.preventDefault();
setPageState('loading');
try {
window.location.href = (await signInBasic(username, password)).redirectTo;
} catch {
// TODO: Show specific error after merge into monorepo
setPageState('error');
}
};
return (
<form className={styles.wrapper}>
<div className={styles.title}> Logto</div>
<Input
autoComplete="username"
isDisabled={isLoading}
placeholder={t('sign-in.username')}
placeholder={t('sign_in.username')}
value={username}
onChange={setUsername}
/>
<Input
autoComplete="current-password"
isDisabled={isLoading}
placeholder={t('sign-in.password')}
placeholder={t('sign_in.password')}
type="password"
value={password}
onChange={setPassword}
/>
{pageState === 'error' && (
<MessageBox className={styles.box}>{t('sign-in.error')}</MessageBox>
<MessageBox className={styles.box}>{t('sign_in.error')}</MessageBox>
)}
<Button
isDisabled={isLoading}
value={isLoading ? t('sign-in.loading') : t('sign-in')}
onClick={() => {
setPageState('loading');
}}
value={isLoading ? t('sign_in.loading') : t('sign_in')}
onClick={signIn}
/>
</form>
);

View file

@ -7108,6 +7108,11 @@ known-css-properties@^0.21.0:
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.21.0.tgz#15fbd0bbb83447f3ce09d8af247ed47c68ede80d"
integrity sha512-sZLUnTqimCkvkgRS+kbPlYW5o8q5w1cu+uIisKpEWkj31I8mx8kNG162DwRav8Zirkva6N5uoFsm9kzK4mUXjw==
ky@^0.28.5:
version "0.28.5"
resolved "https://registry.yarnpkg.com/ky/-/ky-0.28.5.tgz#4b7ada24fb0440c3898406f3a4986abe60ba213e"
integrity sha512-O5gg9kF4MeyfSw+YkgPAafOPwEUU6xcdGEJKUJmKpIPbLzk3oxUtY4OdBNekG7mawofzkyZ/ZHuR9ev5uZZdAA==
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"