feat(config-ui): adjust the config-ui about cognito (#4933)

diff --git a/config-ui/src/App.tsx b/config-ui/src/App.tsx
index 5f5299c..f655349 100644
--- a/config-ui/src/App.tsx
+++ b/config-ui/src/App.tsx
@@ -37,30 +37,45 @@
 function App() {
   return (
     <Router history={history}>
-      <BaseLayout>
-        <Switch>
-          <Route path="/" exact component={() => <Redirect to="/projects" />} />
-          <Route exact path="/login" component={() => <LoginPage />} />
-          <Route exact path="/projects" component={() => <ProjectHomePage />} />
-          <Route exact path="/projects/:pname" component={() => <ProjectDetailPage />} />
-          <Route exact path="/projects/:pname/:bid/connection-add" component={() => <BlueprintConnectioAddPage />} />
-          <Route exact path="/projects/:pname/:bid/:unique" component={() => <BlueprintConnectionDetailPage />} />
-          <Route
-            exact
-            path="/projects/:pname/create-blueprint"
-            component={() => <BlueprintCreatePage from={FromEnum.project} />}
-          />
-          <Route exact path="/connections" component={() => <ConnectionHomePage />} />
-          <Route exact path="/connections/:plugin" component={() => <ConnectionListPage />} />
-          <Route exact path="/connections/:plugin/create" component={() => <ConnectionFormPage />} />
-          <Route exact path="/connections/:plugin/:cid" component={() => <ConnectionFormPage />} />
-          <Route exact path="/blueprints" component={() => <BlueprintHomePage />} />
-          <Route exact path="/blueprints/create" component={() => <BlueprintCreatePage from={FromEnum.blueprint} />} />
-          <Route exact path="/blueprints/:id" component={() => <BlueprintDetailPage />} />
-          <Route exact path="/blueprints/:bid/connection-add" component={() => <BlueprintConnectioAddPage />} />
-          <Route exact path="/blueprints/:bid/:unique" component={() => <BlueprintConnectionDetailPage />} />
-        </Switch>
-      </BaseLayout>
+      <Switch>
+        <Route exact path="/login" component={() => <LoginPage />} />
+        <Route
+          path="/"
+          component={() => (
+            <BaseLayout>
+              <Switch>
+                <Route exact path="/" component={() => <Redirect to="/projects" />} />
+                <Route exact path="/projects" component={() => <ProjectHomePage />} />
+                <Route exact path="/projects/:pname" component={() => <ProjectDetailPage />} />
+                <Route
+                  exact
+                  path="/projects/:pname/:bid/connection-add"
+                  component={() => <BlueprintConnectioAddPage />}
+                />
+                <Route exact path="/projects/:pname/:bid/:unique" component={() => <BlueprintConnectionDetailPage />} />
+                <Route
+                  exact
+                  path="/projects/:pname/create-blueprint"
+                  component={() => <BlueprintCreatePage from={FromEnum.project} />}
+                />
+                <Route exact path="/connections" component={() => <ConnectionHomePage />} />
+                <Route exact path="/connections/:plugin" component={() => <ConnectionListPage />} />
+                <Route exact path="/connections/:plugin/create" component={() => <ConnectionFormPage />} />
+                <Route exact path="/connections/:plugin/:cid" component={() => <ConnectionFormPage />} />
+                <Route exact path="/blueprints" component={() => <BlueprintHomePage />} />
+                <Route
+                  exact
+                  path="/blueprints/create"
+                  component={() => <BlueprintCreatePage from={FromEnum.blueprint} />}
+                />
+                <Route exact path="/blueprints/:id" component={() => <BlueprintDetailPage />} />
+                <Route exact path="/blueprints/:bid/connection-add" component={() => <BlueprintConnectioAddPage />} />
+                <Route exact path="/blueprints/:bid/:unique" component={() => <BlueprintConnectionDetailPage />} />
+              </Switch>
+            </BaseLayout>
+          )}
+        />
+      </Switch>
     </Router>
   );
 }
diff --git a/config-ui/src/layouts/base/base.tsx b/config-ui/src/layouts/base/base.tsx
index 2534b8a..20044b0 100644
--- a/config-ui/src/layouts/base/base.tsx
+++ b/config-ui/src/layouts/base/base.tsx
@@ -132,7 +132,7 @@
               <span>Slack</span>
             </a>
             <Navbar.Divider />
-            <Button intent={Intent.NONE} onClick={handleSignOut}>
+            <Button small intent={Intent.NONE} onClick={handleSignOut}>
               Sign Out
             </Button>
           </Navbar.Group>
diff --git a/config-ui/src/pages/login/api.ts b/config-ui/src/pages/login/api.ts
new file mode 100644
index 0000000..c5a7493
--- /dev/null
+++ b/config-ui/src/pages/login/api.ts
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { request } from '@/utils';
+
+type LoginPayload = {
+  username: string;
+  password: string;
+};
+
+export const login = (payload: LoginPayload) => request(`/login`, { method: 'post', data: payload });
diff --git a/config-ui/src/pages/login/login.tsx b/config-ui/src/pages/login/login.tsx
index cf4d8e9..ce097c6 100644
--- a/config-ui/src/pages/login/login.tsx
+++ b/config-ui/src/pages/login/login.tsx
@@ -16,53 +16,58 @@
  *
  */
 
-import { request } from '@/utils';
-import React, { useState, ChangeEvent, FormEvent } from 'react';
+import { useState } from 'react';
 import { useHistory } from 'react-router-dom';
+import { FormGroup, InputGroup, Button, Intent } from '@blueprintjs/core';
+
+import { operator } from '@/utils';
+
+import * as API from './api';
+import * as S from './styld';
 
 export const LoginPage = () => {
-  const [username, setUsername] = useState<string>('');
-  const [password, setPassword] = useState<string>('');
+  const [username, setUsername] = useState('');
+  const [password, setPassword] = useState('');
+
   const history = useHistory();
 
-  const handleSubmit = (e: FormEvent) => {
-    e.preventDefault();
-    const payload = { username, password };
-    try {
-      login(payload).then((r) => {
-        localStorage.setItem('accessToken', r.AuthenticationResult.AccessToken);
-        history.push('/projects');
-      });
-    } catch (error) {
-      console.error('Error during login:', error);
-      // Handle login error here, e.g. show a message to the user
+  const handleSubmit = async () => {
+    const [success, res] = await operator(() => API.login({ username, password }), {
+      formatReason: (error) => 'Login failed',
+    });
+
+    if (success) {
+      localStorage.setItem('accessToken', res.AuthenticationResult.AccessToken);
+      history.push('/');
     }
+
+    setUsername('');
+    setPassword('');
   };
 
   return (
-    <div>
-      <h2>"login"</h2>
-      <form onSubmit={handleSubmit}>
-        <div>
-          <label>Username:</label>
-          <input
-            type="text"
+    <S.Wrapper>
+      <S.Inner>
+        <h2>DevLake Login</h2>
+        <FormGroup label="Username">
+          <InputGroup
+            placeholder="Username"
             value={username}
-            onChange={(e: ChangeEvent<HTMLInputElement>) => setUsername(e.target.value)}
+            onChange={(e) => setUsername((e.target as HTMLInputElement).value)}
           />
-        </div>
-        <div>
-          <label>Password:</label>
-          <input
+        </FormGroup>
+        <FormGroup label="Password">
+          <InputGroup
             type="password"
+            placeholder="Password"
             value={password}
-            onChange={(e: ChangeEvent<HTMLInputElement>) => setPassword(e.target.value)}
+            onChange={(e) => setPassword((e.target as HTMLInputElement).value)}
           />
-        </div>
-        <button type="submit">login</button>
-      </form>
-    </div>
+        </FormGroup>
+        <Button intent={Intent.PRIMARY} onClick={handleSubmit}>
+          Login
+        </Button>
+      </S.Inner>
+    </S.Wrapper>
   );
 };
-
-export const login = (payload: any) => request(`/login`, { method: 'post', data: payload });
diff --git a/config-ui/src/pages/login/styld.ts b/config-ui/src/pages/login/styld.ts
new file mode 100644
index 0000000..e12cfad
--- /dev/null
+++ b/config-ui/src/pages/login/styld.ts
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import styled from 'styled-components';
+
+export const Wrapper = styled.div`
+  height: 100vh;
+  background-color: #f5f5f5;
+  overflow: hidden;
+`;
+
+export const Inner = styled.div`
+  margin: 200px auto;
+  padding: 16px 24px;
+  width: 400px;
+  background-color: #fff;
+  border-raidus: 4px;
+  box-shadow: 0px 2.4px 4.8px -0.8px rgba(0, 0, 0, 0.1), 0px 1.6px 8px rgba(0, 0, 0, 0.07);
+
+  h2 {
+    margin-bottom: 16px;
+    text-align: center;
+  }
+`;
diff --git a/config-ui/src/utils/request.ts b/config-ui/src/utils/request.ts
index 5b66b77..2fb8ba5 100644
--- a/config-ui/src/utils/request.ts
+++ b/config-ui/src/utils/request.ts
@@ -21,6 +21,7 @@
 import { history } from '@/utils/history';
 
 import { DEVLAKE_ENDPOINT } from '@/config';
+import { toast } from '@/components/toast';
 
 const instance = axios.create({
   baseURL: DEVLAKE_ENDPOINT,
@@ -55,7 +56,7 @@
     (response) => response,
     (error) => {
       if (error.response && error.response.status === 401) {
-        console.log('401 error');
+        toast.error('Please log in first');
         history.push('/login');
       }
     },