diff --git a/packages/ui/package.json b/packages/ui/package.json
index 1d077f6a9..3b0ef968e 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -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",
diff --git a/packages/ui/src/App.tsx b/packages/ui/src/App.tsx
index 69e972957..89e4b84d7 100644
--- a/packages/ui/src/App.tsx
+++ b/packages/ui/src/App.tsx
@@ -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 = () => (
-
+
+
);
diff --git a/packages/ui/src/apis/consent.ts b/packages/ui/src/apis/consent.ts
new file mode 100644
index 000000000..8445d2b57
--- /dev/null
+++ b/packages/ui/src/apis/consent.ts
@@ -0,0 +1,8 @@
+import ky from 'ky';
+
+export const consent = async () => {
+ type Response = {
+ redirectTo: string;
+ };
+ return ky.post('/api/sign-in/consent').json();
+};
diff --git a/packages/ui/src/apis/sign-in.ts b/packages/ui/src/apis/sign-in.ts
new file mode 100644
index 000000000..97120ca44
--- /dev/null
+++ b/packages/ui/src/apis/sign-in.ts
@@ -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();
+};
diff --git a/packages/ui/src/locales/en.json b/packages/ui/src/locales/en.json
index 800079b63..0bb8ab813 100644
--- a/packages/ui/src/locales/en.json
+++ b/packages/ui/src/locales/en.json
@@ -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"
}
}
diff --git a/packages/ui/src/locales/zh-CN.json b/packages/ui/src/locales/zh-CN.json
index caa320b9e..f241078b9 100644
--- a/packages/ui/src/locales/zh-CN.json
+++ b/packages/ui/src/locales/zh-CN.json
@@ -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": "密码"
}
}
diff --git a/packages/ui/src/pages/Consent/index.tsx b/packages/ui/src/pages/Consent/index.tsx
new file mode 100644
index 000000000..d18ac2e49
--- /dev/null
+++ b/packages/ui/src/pages/Consent/index.tsx
@@ -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 {t('sign_in.loading')}
;
+};
+
+export default Consent;
diff --git a/packages/ui/src/pages/Home/index.module.scss b/packages/ui/src/pages/SignIn/index.module.scss
similarity index 92%
rename from packages/ui/src/pages/Home/index.module.scss
rename to packages/ui/src/pages/SignIn/index.module.scss
index b3accd735..1c75520c7 100644
--- a/packages/ui/src/pages/Home/index.module.scss
+++ b/packages/ui/src/pages/SignIn/index.module.scss
@@ -20,8 +20,9 @@
}
> input:not([type='button']) {
- align-self: stretch;
margin-top: _.unit(3);
+ width: 100%;
+ max-width: 320px;
}
> input[type='button'] {
diff --git a/packages/ui/src/pages/Home/index.tsx b/packages/ui/src/pages/SignIn/index.tsx
similarity index 62%
rename from packages/ui/src/pages/Home/index.tsx
rename to packages/ui/src/pages/SignIn/index.tsx
index 2af88ea1d..c4f901ed0 100644
--- a/packages/ui/src/pages/Home/index.tsx
+++ b/packages/ui/src/pages/SignIn/index.tsx
@@ -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('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 (
);
diff --git a/packages/ui/yarn.lock b/packages/ui/yarn.lock
index 2a85abb56..a41b26533 100644
--- a/packages/ui/yarn.lock
+++ b/packages/ui/yarn.lock
@@ -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"