This is an automated email from the ASF dual-hosted git repository.

klesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 7e453ec50 refactor(config-ui): use new error catch to replace old 
(#5712)
7e453ec50 is described below

commit 7e453ec5095260e0f955f4c6b3521573cb0a93ba
Author: 青湛 <[email protected]>
AuthorDate: Mon Jul 24 20:34:40 2023 +1200

    refactor(config-ui): use new error catch to replace old (#5712)
---
 config-ui/src/App.tsx                              | 20 +-------
 config-ui/src/layouts/base/api.ts                  |  2 +-
 config-ui/src/layouts/base/base.tsx                | 31 +++++++-----
 config-ui/src/layouts/error/styled.ts              | 58 ---------------------
 config-ui/src/layouts/index.ts                     |  1 -
 config-ui/src/pages/index.ts                       |  2 -
 .../routes/error/components/exception/index.tsx    | 52 +++++++++++++++++++
 .../{layouts => routes/error/components}/index.ts  |  5 +-
 .../error/components/needs-db-migrate}/api.ts      |  0
 .../error/components/needs-db-migrate}/index.tsx   |  2 +-
 .../error/components}/offline/api.ts               |  0
 .../error/components}/offline/index.tsx            |  2 +-
 .../error/index.tsx => routes/error/error.tsx}     | 12 +++--
 config-ui/src/{layouts => routes/error}/index.ts   |  2 +-
 config-ui/src/routes/error/index.tsx               | 59 ----------------------
 .../offline/api.ts => routes/error/types.ts}       |  7 +--
 config-ui/src/utils/request.ts                     | 13 -----
 17 files changed, 93 insertions(+), 175 deletions(-)

diff --git a/config-ui/src/App.tsx b/config-ui/src/App.tsx
index 23a9d838a..0a993c44c 100644
--- a/config-ui/src/App.tsx
+++ b/config-ui/src/App.tsx
@@ -19,10 +19,8 @@
 import { createBrowserRouter, Navigate, RouterProvider } from 
'react-router-dom';
 
 import { PageLoading } from '@/components';
-import { ErrorLayout, BaseLayout } from '@/layouts';
+import { loader as baseLayoutLoader, BaseLayout } from '@/layouts/base';
 import {
-  OfflinePage,
-  DBMigratePage,
   ConnectionHomePage,
   ConnectionDetailPage,
   ProjectHomePage,
@@ -34,24 +32,10 @@ import {
 import { Error } from '@/routes/error';
 
 const router = createBrowserRouter([
-  {
-    path: '',
-    element: <ErrorLayout />,
-    errorElement: <Error />,
-    children: [
-      {
-        path: 'offline',
-        element: <OfflinePage />,
-      },
-      {
-        path: 'db-migrate',
-        element: <DBMigratePage />,
-      },
-    ],
-  },
   {
     path: '/',
     element: <BaseLayout />,
+    loader: baseLayoutLoader,
     errorElement: <Error />,
     children: [
       {
diff --git a/config-ui/src/layouts/base/api.ts 
b/config-ui/src/layouts/base/api.ts
index c3be4bbac..63f0d4d98 100644
--- a/config-ui/src/layouts/base/api.ts
+++ b/config-ui/src/layouts/base/api.ts
@@ -24,5 +24,5 @@ export type UserInfo = {
   logoutURI: string;
 };
 
-export const getVersion = () => request('/version');
+export const getVersion = (signal?: AbortSignal): Promise<{ version: string }> 
=> request('/version', { signal });
 export const getUserInfo = (): Promise<UserInfo> => request('/userinfo');
diff --git a/config-ui/src/layouts/base/base.tsx 
b/config-ui/src/layouts/base/base.tsx
index a677fa47d..f30e98fc5 100644
--- a/config-ui/src/layouts/base/base.tsx
+++ b/config-ui/src/layouts/base/base.tsx
@@ -17,13 +17,15 @@
  */
 
 import { useState, useEffect, useRef } from 'react';
-import { Outlet, useNavigate, useLocation } from 'react-router-dom';
+import { useLoaderData, Outlet, useNavigate, useLocation, json } from 
'react-router-dom';
 import { CSSTransition } from 'react-transition-group';
 import { Menu, MenuItem, Navbar, Alignment } from '@blueprintjs/core';
+import { AxiosError } from 'axios';
 
-import { PageLoading, Logo, ExternalLink, IconButton } from '@/components';
-import { useTips, useRefreshData } from '@/hooks';
+import { Logo, ExternalLink, IconButton } from '@/components';
+import { useTips } from '@/hooks';
 import { TipsContextProvider, ConnectionContextProvider } from '@/store';
+import { ErrorEnum } from '@/routes/error';
 
 import DashboardIcon from '@/images/icons/dashboard.svg';
 import FileIcon from '@/images/icons/file.svg';
@@ -36,22 +38,27 @@ import * as API from './api';
 import * as S from './styled';
 import './tips-transition.css';
 
-export const BaseLayout = () => {
-  const navigate = useNavigate();
-  const { ready, data, error } = useRefreshData<{ version: string }>(() => 
API.getVersion(), []);
+export const loader = async ({ request }: { request: Request }) => {
+  try {
+    return await API.getVersion(request.signal);
+  } catch (err) {
+    const status = (err as AxiosError).response?.status;
 
-  if (error) {
-    navigate('/offline');
-  }
+    if (status === 428) {
+      throw json({ error: ErrorEnum.NEEDS_DB_MIRGATE }, { status: 428 });
+    }
 
-  if (!ready || !data) {
-    return <PageLoading />;
+    throw json({ error: ErrorEnum.API_OFFLINE }, { status: 503 });
   }
+};
+
+export const BaseLayout = () => {
+  const { version } = useLoaderData() as Awaited<ReturnType<typeof loader>>;
 
   return (
     <TipsContextProvider>
       <ConnectionContextProvider>
-        <Layout version={data.version}>
+        <Layout version={version}>
           <Outlet />
         </Layout>
       </ConnectionContextProvider>
diff --git a/config-ui/src/layouts/error/styled.ts 
b/config-ui/src/layouts/error/styled.ts
deleted file mode 100644
index 0b1dad056..000000000
--- a/config-ui/src/layouts/error/styled.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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';
-import { Colors } from '@blueprintjs/core';
-
-export const Wrapper = styled.div`
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding-top: 100px;
-  height: 100vh;
-  background-color: #f9f9fa;
-  box-sizing: border-box;
-`;
-
-export const Inner = styled.div`
-  margin: 32px auto 0;
-  width: 640px;
-
-  h2 {
-    display: flex;
-    align-items: center;
-    margin: 0;
-
-    .bp4-icon {
-      margin-right: 4px;
-    }
-  }
-
-  p {
-    margin: 16px 0;
-
-    &.warning {
-      color: ${Colors.ORANGE5};
-    }
-  }
-
-  .bp4-button-group {
-    display: flex;
-    justify-content: center;
-  }
-`;
diff --git a/config-ui/src/layouts/index.ts b/config-ui/src/layouts/index.ts
index 7e43f3d53..4a2f7c965 100644
--- a/config-ui/src/layouts/index.ts
+++ b/config-ui/src/layouts/index.ts
@@ -17,4 +17,3 @@
  */
 
 export * from './base';
-export * from './error';
diff --git a/config-ui/src/pages/index.ts b/config-ui/src/pages/index.ts
index 371eed61d..3554c4b95 100644
--- a/config-ui/src/pages/index.ts
+++ b/config-ui/src/pages/index.ts
@@ -18,7 +18,5 @@
 
 export * from './blueprint';
 export * from './connection';
-export * from './db-migrate';
-export * from './offline';
 export * from './pipeline';
 export * from './project';
diff --git a/config-ui/src/routes/error/components/exception/index.tsx 
b/config-ui/src/routes/error/components/exception/index.tsx
new file mode 100644
index 000000000..d2aca5c55
--- /dev/null
+++ b/config-ui/src/routes/error/components/exception/index.tsx
@@ -0,0 +1,52 @@
+/*
+ * 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 { useNavigate } from 'react-router-dom';
+import { Icon, Colors, Button, Intent } from '@blueprintjs/core';
+
+import { Card, Buttons } from '@/components';
+
+interface Props {
+  error: string | Error;
+}
+
+export const Exception = ({ error }: Props) => {
+  const navigate = useNavigate();
+  const handleResetError = () => navigate('/');
+
+  return (
+    <Card>
+      <h2>
+        <Icon icon="error" color={Colors.RED5} size={20} />
+        <span>{error.toString() || 'Unknown Error'}</span>
+      </h2>
+      <p>
+        Please try again, if the problem persists include the above error 
message when filing a bug report on{' '}
+        <strong>GitHub</strong>. You can also message us on 
<strong>Slack</strong> to engage with community members for
+        solutions to common issues.
+      </p>
+      <Buttons position="bottom" align="center">
+        <Button text="Continue" intent={Intent.PRIMARY} 
onClick={handleResetError} />
+        <Button
+          text="Visit GitHub"
+          onClick={() => 
window.open('https://github.com/apache/incubator-devlake', '_blank', 
'noopener,noreferrer')}
+        />
+      </Buttons>
+    </Card>
+  );
+};
diff --git a/config-ui/src/layouts/index.ts 
b/config-ui/src/routes/error/components/index.ts
similarity index 89%
copy from config-ui/src/layouts/index.ts
copy to config-ui/src/routes/error/components/index.ts
index 7e43f3d53..6bbf39072 100644
--- a/config-ui/src/layouts/index.ts
+++ b/config-ui/src/routes/error/components/index.ts
@@ -16,5 +16,6 @@
  *
  */
 
-export * from './base';
-export * from './error';
+export * from './exception';
+export * from './needs-db-migrate';
+export * from './offline';
diff --git a/config-ui/src/pages/db-migrate/api.ts 
b/config-ui/src/routes/error/components/needs-db-migrate/api.ts
similarity index 100%
rename from config-ui/src/pages/db-migrate/api.ts
rename to config-ui/src/routes/error/components/needs-db-migrate/api.ts
diff --git a/config-ui/src/pages/db-migrate/index.tsx 
b/config-ui/src/routes/error/components/needs-db-migrate/index.tsx
similarity index 98%
rename from config-ui/src/pages/db-migrate/index.tsx
rename to config-ui/src/routes/error/components/needs-db-migrate/index.tsx
index 2e74854d6..fb196794c 100644
--- a/config-ui/src/pages/db-migrate/index.tsx
+++ b/config-ui/src/routes/error/components/needs-db-migrate/index.tsx
@@ -25,7 +25,7 @@ import { operator } from '@/utils';
 
 import * as API from './api';
 
-export const DBMigratePage = () => {
+export const NeedsDBMigrate = () => {
   const [operating, setOperating] = useState(false);
 
   const navigate = useNavigate();
diff --git a/config-ui/src/pages/offline/api.ts 
b/config-ui/src/routes/error/components/offline/api.ts
similarity index 100%
copy from config-ui/src/pages/offline/api.ts
copy to config-ui/src/routes/error/components/offline/api.ts
diff --git a/config-ui/src/pages/offline/index.tsx 
b/config-ui/src/routes/error/components/offline/index.tsx
similarity index 98%
rename from config-ui/src/pages/offline/index.tsx
rename to config-ui/src/routes/error/components/offline/index.tsx
index 544283090..37b39aee8 100644
--- a/config-ui/src/pages/offline/index.tsx
+++ b/config-ui/src/routes/error/components/offline/index.tsx
@@ -26,7 +26,7 @@ import { useAutoRefresh } from '@/hooks';
 
 import * as API from './api';
 
-export const OfflinePage = () => {
+export const Offline = () => {
   const [version, setVersion] = useState(1);
 
   const navigate = useNavigate();
diff --git a/config-ui/src/layouts/error/index.tsx 
b/config-ui/src/routes/error/error.tsx
similarity index 64%
rename from config-ui/src/layouts/error/index.tsx
rename to config-ui/src/routes/error/error.tsx
index 40fcbee0f..28bf80715 100644
--- a/config-ui/src/layouts/error/index.tsx
+++ b/config-ui/src/routes/error/error.tsx
@@ -16,18 +16,24 @@
  *
  */
 
-import { Outlet } from 'react-router-dom';
+import { useRouteError, isRouteErrorResponse } from 'react-router-dom';
 
 import { Logo } from '@/components';
 
+import { ErrorEnum } from './types';
+import { Offline, NeedsDBMigrate, Exception } from './components';
 import * as S from './styled';
 
-export const ErrorLayout = () => {
+export const Error = () => {
+  const error = useRouteError() as Error;
+
   return (
     <S.Wrapper>
       <Logo />
       <S.Inner>
-        <Outlet />
+        {isRouteErrorResponse(error) && error.data.error === 
ErrorEnum.API_OFFLINE && <Offline />}
+        {isRouteErrorResponse(error) && error.data.error === 
ErrorEnum.NEEDS_DB_MIRGATE && <NeedsDBMigrate />}
+        {!isRouteErrorResponse(error) && <Exception error={error} />}
       </S.Inner>
     </S.Wrapper>
   );
diff --git a/config-ui/src/layouts/index.ts 
b/config-ui/src/routes/error/index.ts
similarity index 97%
copy from config-ui/src/layouts/index.ts
copy to config-ui/src/routes/error/index.ts
index 7e43f3d53..03f1eec15 100644
--- a/config-ui/src/layouts/index.ts
+++ b/config-ui/src/routes/error/index.ts
@@ -16,5 +16,5 @@
  *
  */
 
-export * from './base';
+export * from './types';
 export * from './error';
diff --git a/config-ui/src/routes/error/index.tsx 
b/config-ui/src/routes/error/index.tsx
deleted file mode 100644
index 25a79fb59..000000000
--- a/config-ui/src/routes/error/index.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 { useRouteError, useNavigate } from 'react-router-dom';
-import { Icon, Button, Colors, Intent } from '@blueprintjs/core';
-
-import { Logo, Card, Buttons } from '@/components';
-
-import * as S from './styled';
-
-export const Error = () => {
-  const error = useRouteError() as Error;
-  const navigate = useNavigate();
-
-  const handleResetError = () => navigate('/');
-
-  return (
-    <S.Wrapper>
-      <Logo />
-      <S.Inner>
-        <Card>
-          <h2>
-            <Icon icon="error" color={Colors.RED5} size={20} />
-            <span>{error.toString() || 'Unknown Error'}</span>
-          </h2>
-          <p>
-            Please try again, if the problem persists include the above error 
message when filing a bug report on{' '}
-            <strong>GitHub</strong>. You can also message us on 
<strong>Slack</strong> to engage with community members
-            for solutions to common issues.
-          </p>
-          <Buttons position="bottom" align="center">
-            <Button text="Continue" intent={Intent.PRIMARY} 
onClick={handleResetError} />
-            <Button
-              text="Visit GitHub"
-              onClick={() =>
-                window.open('https://github.com/apache/incubator-devlake', 
'_blank', 'noopener,noreferrer')
-              }
-            />
-          </Buttons>
-        </Card>
-      </S.Inner>
-    </S.Wrapper>
-  );
-};
diff --git a/config-ui/src/pages/offline/api.ts 
b/config-ui/src/routes/error/types.ts
similarity index 89%
rename from config-ui/src/pages/offline/api.ts
rename to config-ui/src/routes/error/types.ts
index 38f8e0fed..74b9048b1 100644
--- a/config-ui/src/pages/offline/api.ts
+++ b/config-ui/src/routes/error/types.ts
@@ -16,6 +16,7 @@
  *
  */
 
-import { request } from '@/utils';
-
-export const ping = () => request('/ping');
+export enum ErrorEnum {
+  API_OFFLINE = 'API_OFFLINE',
+  NEEDS_DB_MIRGATE = 'NEEDS_DB_MIRGATE',
+}
diff --git a/config-ui/src/utils/request.ts b/config-ui/src/utils/request.ts
index 9da4ea9cf..cd57e6f16 100644
--- a/config-ui/src/utils/request.ts
+++ b/config-ui/src/utils/request.ts
@@ -25,19 +25,6 @@ const instance = axios.create({
   baseURL: DEVLAKE_ENDPOINT,
 });
 
-instance.interceptors.response.use(
-  (response) => response,
-  (error) => {
-    const status = error.response?.status;
-
-    if (status === 428) {
-      window.location.replace('/db-migrate');
-    }
-
-    return Promise.reject(error);
-  },
-);
-
 export type RequestConfig = {
   baseURL?: string;
   method?: AxiosRequestConfig['method'];

Reply via email to