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

likyh 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 13feb2095 fix(config-ui): db migrate page failure (#5036)
13feb2095 is described below

commit 13feb2095cf6fdea95b7b71d7ea483a2ce94ae4f
Author: 青湛 <[email protected]>
AuthorDate: Thu Apr 27 10:23:22 2023 +0800

    fix(config-ui): db migrate page failure (#5036)
    
    * refactor(config-ui): remove the version store context
    
    * feat(config-ui): support props retry limit in use-auto-refresh
    
    * refactor(config-ui): adjust offline as a page
    
    * refactor(config-ui): adjust db-migrate as a page
    
    * feat(config-ui): add new layout error
    
    * feat(config-ui): declare new pages offline and db-migrate
    
    * refactor(config-ui): adjust the request function
    
    * refactor(config-ui): remove unused Error enum
---
 config-ui/src/App.tsx                              | 25 ++++++-
 .../error/components/db-migrate/use-db-migrate.ts  | 53 --------------
 config-ui/src/error/components/index.ts            |  2 -
 .../src/error/components/offline/use-offline.ts    | 82 ----------------------
 config-ui/src/error/error-boundary.tsx             |  4 +-
 config-ui/src/error/types.ts                       |  2 -
 config-ui/src/error/utils.ts                       |  6 --
 config-ui/src/hooks/use-auto-refresh.ts            |  9 +--
 .../src/{store/version => layouts/base}/api.ts     |  0
 config-ui/src/layouts/base/base.tsx                | 14 ++--
 .../{error/utils.ts => layouts/error/index.tsx}    | 24 ++++---
 .../{error/utils.ts => layouts/error/styled.ts}    | 50 ++++++++++---
 config-ui/src/layouts/index.ts                     |  1 +
 config-ui/src/main.tsx                             |  6 +-
 .../{error/components => pages}/db-migrate/api.ts  |  0
 .../components => pages}/db-migrate/index.tsx      | 30 ++++++--
 config-ui/src/pages/index.ts                       |  2 +
 .../src/{error/components => pages}/offline/api.ts |  0
 .../{error/components => pages}/offline/index.tsx  | 49 +++++++++----
 config-ui/src/store/index.ts                       |  1 -
 config-ui/src/store/version/context.tsx            | 46 ------------
 config-ui/src/store/version/index.ts               | 20 ------
 config-ui/src/store/version/types.ts               | 19 -----
 config-ui/src/store/version/use-context-value.ts   | 50 -------------
 config-ui/src/utils/request.ts                     | 50 +++++++------
 25 files changed, 185 insertions(+), 360 deletions(-)

diff --git a/config-ui/src/App.tsx b/config-ui/src/App.tsx
index f655349a5..47ef84b4f 100644
--- a/config-ui/src/App.tsx
+++ b/config-ui/src/App.tsx
@@ -19,9 +19,11 @@
 import { Switch, Route, Redirect, Router } from 'react-router-dom';
 import { LoginPage } from './pages/login/login';
 import { history } from './utils/history';
-import { BaseLayout } from '@/layouts';
+import { ErrorLayout, BaseLayout } from '@/layouts';
 import { FromEnum } from '@/pages';
 import {
+  OfflinePage,
+  DBMigratePage,
   ProjectHomePage,
   ProjectDetailPage,
   ConnectionHomePage,
@@ -39,6 +41,27 @@ function App() {
     <Router history={history}>
       <Switch>
         <Route exact path="/login" component={() => <LoginPage />} />
+
+        <Route
+          exact
+          path="/offline"
+          component={() => (
+            <ErrorLayout>
+              <OfflinePage />
+            </ErrorLayout>
+          )}
+        />
+
+        <Route
+          exact
+          path="/db-mirgate"
+          component={() => (
+            <ErrorLayout>
+              <DBMigratePage />
+            </ErrorLayout>
+          )}
+        />
+
         <Route
           path="/"
           component={() => (
diff --git a/config-ui/src/error/components/db-migrate/use-db-migrate.ts 
b/config-ui/src/error/components/db-migrate/use-db-migrate.ts
deleted file mode 100644
index 040be935d..000000000
--- a/config-ui/src/error/components/db-migrate/use-db-migrate.ts
+++ /dev/null
@@ -1,53 +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 { useState, useMemo } from 'react';
-import { useHistory } from 'react-router-dom';
-
-import { operator } from '@/utils';
-
-import * as API from './api';
-
-export interface UseDBMigrateProps {
-  onResetError: () => void;
-}
-
-export const useDBMigrate = ({ onResetError }: UseDBMigrateProps) => {
-  const [processing, setProcessing] = useState(false);
-
-  const history = useHistory();
-
-  const handleSubmit = async () => {
-    const [success] = await operator(() => API.migrate(), {
-      setOperating: setProcessing,
-    });
-
-    if (success) {
-      onResetError();
-      history.push('/');
-    }
-  };
-
-  return useMemo(
-    () => ({
-      processing,
-      onSubmit: handleSubmit,
-    }),
-    [processing],
-  );
-};
diff --git a/config-ui/src/error/components/index.ts 
b/config-ui/src/error/components/index.ts
index 6796e6d7b..9ca5fe3df 100644
--- a/config-ui/src/error/components/index.ts
+++ b/config-ui/src/error/components/index.ts
@@ -16,7 +16,5 @@
  *
  */
 
-export * from './db-migrate';
-export * from './offline';
 export * from './default';
 export * from './bp-upgrade';
diff --git a/config-ui/src/error/components/offline/use-offline.ts 
b/config-ui/src/error/components/offline/use-offline.ts
deleted file mode 100644
index c28e2b55c..000000000
--- a/config-ui/src/error/components/offline/use-offline.ts
+++ /dev/null
@@ -1,82 +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 { useState, useEffect, useMemo, useRef } from 'react';
-import { useHistory } from 'react-router-dom';
-
-import { operator } from '@/utils';
-
-import * as API from './api';
-
-const pollTimer = 10000;
-const retryLimit = 10;
-
-export interface UseOfflineProps {
-  onResetError: () => void;
-}
-
-export const useOffline = ({ onResetError }: UseOfflineProps) => {
-  const [processing, setProcessing] = useState(false);
-  const [offline, setOffline] = useState(true);
-
-  const history = useHistory();
-
-  const timer = useRef<any>();
-  const retryCount = useRef<number>(0);
-
-  const ping = async (auto = true) => {
-    const [success] = await operator(() => API.ping(), {
-      setOperating: setProcessing,
-      formatReason: () => 'Attempt to connect to the API failed',
-    });
-
-    if (success) {
-      setOffline(false);
-    }
-
-    if (auto) {
-      retryCount.current += 1;
-    }
-  };
-
-  useEffect(() => {
-    timer.current = setInterval(() => {
-      ping();
-    }, pollTimer);
-    return () => clearInterval(timer.current);
-  }, []);
-
-  useEffect(() => {
-    if (retryCount.current >= retryLimit || !offline) {
-      clearInterval(timer.current);
-    }
-  }, [retryCount.current, offline]);
-
-  return useMemo(
-    () => ({
-      processing,
-      offline,
-      onRefresh: () => ping(false),
-      onContinue: () => {
-        onResetError();
-        history.push('/');
-      },
-    }),
-    [processing, offline],
-  );
-};
diff --git a/config-ui/src/error/error-boundary.tsx 
b/config-ui/src/error/error-boundary.tsx
index b79f77930..b6729da5b 100644
--- a/config-ui/src/error/error-boundary.tsx
+++ b/config-ui/src/error/error-boundary.tsx
@@ -21,7 +21,7 @@ import React from 'react';
 import { Logo } from '@/components';
 
 import { Error } from './types';
-import { DBMigrate, Offline, Default, BPUpgrade } from './components';
+import { Default, BPUpgrade } from './components';
 
 import * as S from './styled';
 
@@ -65,8 +65,6 @@ export class ErrorBoundary extends React.Component<Props, 
State> {
       <S.Wrapper>
         <Logo />
         <S.Inner>
-          {error === Error.DB_NEED_MIGRATE && <DBMigrate 
onResetError={this.handleResetError} />}
-          {error === Error.API_OFFLINE && <Offline 
onResetError={this.handleResetError} />}
           {error === Error.BP_NEED_TO_UPGRADE && <BPUpgrade 
onResetError={this.handleResetError} />}
           {!Object.keys(Error).includes(error) && <Default error={error} 
onResetError={this.handleResetError} />}
         </S.Inner>
diff --git a/config-ui/src/error/types.ts b/config-ui/src/error/types.ts
index c4ecc8078..158aa7764 100644
--- a/config-ui/src/error/types.ts
+++ b/config-ui/src/error/types.ts
@@ -17,7 +17,5 @@
  */
 
 export enum Error {
-  API_OFFLINE = 'API_OFFLINE',
-  DB_NEED_MIGRATE = 'DB_NEED_MIGRATE',
   BP_NEED_TO_UPGRADE = 'BP_NEED_TO_UPGRADE',
 }
diff --git a/config-ui/src/error/utils.ts b/config-ui/src/error/utils.ts
index cd41a6d34..8258fc984 100644
--- a/config-ui/src/error/utils.ts
+++ b/config-ui/src/error/utils.ts
@@ -16,14 +16,8 @@
  *
  */
 
-import { Error } from './types';
-
 export const transformError = (error: any) => {
   switch (error?.response?.status) {
-    case 428:
-      return Error.DB_NEED_MIGRATE;
-    case 504:
-      return Error.API_OFFLINE;
     default:
       return error;
   }
diff --git a/config-ui/src/hooks/use-auto-refresh.ts 
b/config-ui/src/hooks/use-auto-refresh.ts
index 33059964c..f77fc74b9 100644
--- a/config-ui/src/hooks/use-auto-refresh.ts
+++ b/config-ui/src/hooks/use-auto-refresh.ts
@@ -24,12 +24,14 @@ export const useAutoRefresh = <T>(
   option?: {
     cancel?: (data?: T) => boolean;
     interval?: number;
+    retryLimit?: number;
   },
 ) => {
   const [loading, setLoading] = useState(false);
   const [data, setData] = useState<T>();
 
   const timer = useRef<any>();
+  const retryCount = useRef<number>(0);
 
   useEffect(() => {
     setLoading(true);
@@ -44,15 +46,14 @@ export const useAutoRefresh = <T>(
 
   useEffect(() => {
     timer.current = setInterval(() => {
-      request().then((data: T) => {
-        setData(data);
-      });
+      retryCount.current += 1;
+      request().then((data) => setData(data));
     }, option?.interval ?? 5000);
     return () => clearInterval(timer.current);
   }, [...deps]);
 
   useEffect(() => {
-    if (option?.cancel?.(data)) {
+    if (option?.cancel?.(data) || (option?.retryLimit && option?.retryLimit <= 
retryCount.current)) {
       clearInterval(timer.current);
     }
   }, [data]);
diff --git a/config-ui/src/store/version/api.ts 
b/config-ui/src/layouts/base/api.ts
similarity index 100%
rename from config-ui/src/store/version/api.ts
rename to config-ui/src/layouts/base/api.ts
diff --git a/config-ui/src/layouts/base/base.tsx 
b/config-ui/src/layouts/base/base.tsx
index 5f546a458..670e5746a 100644
--- a/config-ui/src/layouts/base/base.tsx
+++ b/config-ui/src/layouts/base/base.tsx
@@ -20,8 +20,8 @@ import React from 'react';
 import { useLocation } from 'react-router-dom';
 import { Menu, MenuItem, Tag, Navbar, Intent, Alignment, Button } from 
'@blueprintjs/core';
 
-import { Logo, ExternalLink } from '@/components';
-import { useVersion } from '@/store';
+import { PageLoading, Logo, ExternalLink } from '@/components';
+import { useRefreshData } from '@/hooks';
 import { history } from '@/utils/history';
 
 import DashboardIcon from '@/images/icons/dashborad.svg';
@@ -30,6 +30,7 @@ import GitHubIcon from '@/images/icons/github.svg';
 import SlackIcon from '@/images/icons/slack.svg';
 
 import { useMenu, MenuItemType } from './use-menu';
+import * as API from './api';
 import * as S from './styled';
 
 interface Props {
@@ -39,7 +40,8 @@ interface Props {
 export const BaseLayout = ({ children }: Props) => {
   const menu = useMenu();
   const { pathname } = useLocation();
-  const { version } = useVersion();
+
+  const { ready, data } = useRefreshData<{ version: string }>(() => 
API.getVersion(), []);
 
   const token = window.localStorage.getItem('accessToken');
 
@@ -63,6 +65,10 @@ export const BaseLayout = ({ children }: Props) => {
     return import.meta.env.DEV ? `${protocol}//${hostname}:3002${suffix}` : 
`/grafana${suffix}`;
   };
 
+  if (!ready || !data) {
+    return <PageLoading />;
+  }
+
   return (
     <S.Wrapper>
       <S.Sider>
@@ -102,7 +108,7 @@ export const BaseLayout = ({ children }: Props) => {
         </Menu>
         <div className="copyright">
           <div>Apache 2.0 License</div>
-          <div className="version">{version}</div>
+          <div className="version">{data.version}</div>
         </div>
       </S.Sider>
       <S.Main>
diff --git a/config-ui/src/error/utils.ts 
b/config-ui/src/layouts/error/index.tsx
similarity index 74%
copy from config-ui/src/error/utils.ts
copy to config-ui/src/layouts/error/index.tsx
index cd41a6d34..54946db08 100644
--- a/config-ui/src/error/utils.ts
+++ b/config-ui/src/layouts/error/index.tsx
@@ -16,15 +16,19 @@
  *
  */
 
-import { Error } from './types';
+import { Logo } from '@/components';
 
-export const transformError = (error: any) => {
-  switch (error?.response?.status) {
-    case 428:
-      return Error.DB_NEED_MIGRATE;
-    case 504:
-      return Error.API_OFFLINE;
-    default:
-      return error;
-  }
+import * as S from './styled';
+
+interface Props {
+  children: React.ReactNode;
+}
+
+export const ErrorLayout = ({ children }: Props) => {
+  return (
+    <S.Wrapper>
+      <Logo />
+      <S.Inner>{children}</S.Inner>
+    </S.Wrapper>
+  );
 };
diff --git a/config-ui/src/error/utils.ts 
b/config-ui/src/layouts/error/styled.ts
similarity index 56%
copy from config-ui/src/error/utils.ts
copy to config-ui/src/layouts/error/styled.ts
index cd41a6d34..0b1dad056 100644
--- a/config-ui/src/error/utils.ts
+++ b/config-ui/src/layouts/error/styled.ts
@@ -16,15 +16,43 @@
  *
  */
 
-import { Error } from './types';
-
-export const transformError = (error: any) => {
-  switch (error?.response?.status) {
-    case 428:
-      return Error.DB_NEED_MIGRATE;
-    case 504:
-      return Error.API_OFFLINE;
-    default:
-      return error;
+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 4a2f7c965..7e43f3d53 100644
--- a/config-ui/src/layouts/index.ts
+++ b/config-ui/src/layouts/index.ts
@@ -17,3 +17,4 @@
  */
 
 export * from './base';
+export * from './error';
diff --git a/config-ui/src/main.tsx b/config-ui/src/main.tsx
index 9e58bbf82..e0a5ecf5c 100644
--- a/config-ui/src/main.tsx
+++ b/config-ui/src/main.tsx
@@ -16,12 +16,10 @@
  *
  */
 
-import React from 'react';
 import ReactDOM from 'react-dom';
 import { BrowserRouter } from 'react-router-dom';
 
 import { ErrorBoundary } from '@/error';
-import { VersionContextProvider } from '@/store';
 
 import App from './App';
 
@@ -30,9 +28,7 @@ import './index.css';
 ReactDOM.render(
   <BrowserRouter>
     <ErrorBoundary>
-      <VersionContextProvider>
-        <App />
-      </VersionContextProvider>
+      <App />
     </ErrorBoundary>
   </BrowserRouter>,
   document.getElementById('root'),
diff --git a/config-ui/src/error/components/db-migrate/api.ts 
b/config-ui/src/pages/db-migrate/api.ts
similarity index 100%
rename from config-ui/src/error/components/db-migrate/api.ts
rename to config-ui/src/pages/db-migrate/api.ts
diff --git a/config-ui/src/error/components/db-migrate/index.tsx 
b/config-ui/src/pages/db-migrate/index.tsx
similarity index 69%
rename from config-ui/src/error/components/db-migrate/index.tsx
rename to config-ui/src/pages/db-migrate/index.tsx
index e0d110f50..8721dc008 100644
--- a/config-ui/src/error/components/db-migrate/index.tsx
+++ b/config-ui/src/pages/db-migrate/index.tsx
@@ -16,18 +16,29 @@
  *
  */
 
-import React from 'react';
+import { useState } from 'react';
 import { Icon, ButtonGroup, Button, Colors, Intent } from '@blueprintjs/core';
+import { useHistory } from 'react-router-dom';
 
 import { Card } from '@/components';
+import { operator } from '@/utils';
 
-import type { UseDBMigrateProps } from './use-db-migrate';
-import { useDBMigrate } from './use-db-migrate';
+import * as API from './api';
 
-interface Props extends UseDBMigrateProps {}
+export const DBMigratePage = () => {
+  const [operating, setOperating] = useState(false);
 
-export const DBMigrate = ({ ...props }: Props) => {
-  const { processing, onSubmit } = useDBMigrate({ ...props });
+  const history = useHistory();
+
+  const handleSubmit = async () => {
+    const [success] = await operator(() => API.migrate(), {
+      setOperating: setOperating,
+    });
+
+    if (success) {
+      history.push('/');
+    }
+  };
 
   return (
     <Card>
@@ -43,7 +54,12 @@ export const DBMigrate = ({ ...props }: Props) => {
         Warning: Performing migration may wipe collected data for consistency 
and re-collecting data may be required.
       </p>
       <ButtonGroup>
-        <Button loading={processing} text="Proceed to Database Migration" 
intent={Intent.PRIMARY} onClick={onSubmit} />
+        <Button
+          loading={operating}
+          text="Proceed to Database Migration"
+          intent={Intent.PRIMARY}
+          onClick={handleSubmit}
+        />
       </ButtonGroup>
     </Card>
   );
diff --git a/config-ui/src/pages/index.ts b/config-ui/src/pages/index.ts
index 307e9f433..bcf789c04 100644
--- a/config-ui/src/pages/index.ts
+++ b/config-ui/src/pages/index.ts
@@ -20,3 +20,5 @@ export * from './project';
 export * from './connection';
 export * from './blueprint';
 export * from './pipeline';
+export * from './offline';
+export * from './db-migrate';
diff --git a/config-ui/src/error/components/offline/api.ts 
b/config-ui/src/pages/offline/api.ts
similarity index 100%
rename from config-ui/src/error/components/offline/api.ts
rename to config-ui/src/pages/offline/api.ts
diff --git a/config-ui/src/error/components/offline/index.tsx 
b/config-ui/src/pages/offline/index.tsx
similarity index 69%
rename from config-ui/src/error/components/offline/index.tsx
rename to config-ui/src/pages/offline/index.tsx
index 51ce90077..eaf1ea199 100644
--- a/config-ui/src/error/components/offline/index.tsx
+++ b/config-ui/src/pages/offline/index.tsx
@@ -16,27 +16,48 @@
  *
  */
 
-import React, { useMemo } from 'react';
+import { useMemo } from 'react';
+import { useHistory } from 'react-router-dom';
 import { Icon, Tag, ButtonGroup, Button, Intent, Colors, IconName } from 
'@blueprintjs/core';
 
-import { Card } from '@/components';
 import { DEVLAKE_ENDPOINT } from '@/config';
+import { Card } from '@/components';
+import { useAutoRefresh } from '@/hooks';
 
-import type { UseOfflineProps } from './use-offline';
-import { useOffline } from './use-offline';
+import * as API from './api';
 
-interface Props extends UseOfflineProps {}
+export const OfflinePage = () => {
+  const history = useHistory();
 
-export const Offline = ({ ...props }: Props) => {
-  const { processing, offline, onRefresh, onContinue } = useOffline({
-    ...props,
-  });
+  const { loading, data } = useAutoRefresh<{ online: boolean }>(
+    async () => {
+      try {
+        await API.ping();
+        return { online: true };
+      } catch {
+        return { online: false };
+      }
+    },
+    [],
+    {
+      cancel: (data) => {
+        return data?.online ?? false;
+      },
+      retryLimit: 2,
+    },
+  );
+
+  const { online } = data || { online: false };
 
   const [icon, color, text] = useMemo(
-    () => [offline ? 'offline' : 'endorsed', offline ? Colors.RED3 : 
Colors.GREEN3, offline ? 'Offline' : 'Online'],
-    [offline],
+    () => [online ? 'endorsed' : 'offline', online ? Colors.GREEN3 : 
Colors.RED3, data ? 'Online' : 'Offline'],
+    [online],
   );
 
+  const handleContinue = () => {
+    history.push('/');
+  };
+
   return (
     <Card>
       <h2>
@@ -47,21 +68,21 @@ export const Offline = ({ ...props }: Props) => {
       <p>
         <Tag>DEVLAKE_ENDPOINT: {DEVLAKE_ENDPOINT}</Tag>
       </p>
-      {offline ? (
+      {!online ? (
         <>
           <p>
             Please wait for the&nbsp;
             <strong>Lake API</strong> to start before accessing the 
<strong>Configuration Interface</strong>.
           </p>
           <ButtonGroup>
-            <Button loading={processing} icon="refresh" 
intent={Intent.PRIMARY} text="Refresh" onClick={onRefresh} />
+            <Button loading={loading} icon="refresh" intent={Intent.PRIMARY} 
text="Refresh" />
           </ButtonGroup>
         </>
       ) : (
         <>
           <p>Connectivity to the Lake API service was successful.</p>
           <ButtonGroup>
-            <Button intent={Intent.PRIMARY} text="Continue" 
onClick={onContinue} />
+            <Button intent={Intent.PRIMARY} text="Continue" 
onClick={handleContinue} />
             <Button
               icon="help"
               text="Read Documentation"
diff --git a/config-ui/src/store/index.ts b/config-ui/src/store/index.ts
index 4fbdb691e..4e6e8a4de 100644
--- a/config-ui/src/store/index.ts
+++ b/config-ui/src/store/index.ts
@@ -16,5 +16,4 @@
  *
  */
 
-export * from './version';
 export * from './connections';
diff --git a/config-ui/src/store/version/context.tsx 
b/config-ui/src/store/version/context.tsx
deleted file mode 100644
index 10dd5c3a0..000000000
--- a/config-ui/src/store/version/context.tsx
+++ /dev/null
@@ -1,46 +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 React, { useContext } from 'react';
-
-import { PageLoading } from '@/components';
-
-import type { VersionType } from './types';
-import { useContextValue } from './use-context-value';
-
-const VersionContext = React.createContext<{
-  version?: VersionType;
-}>({});
-
-interface Props {
-  children?: React.ReactNode;
-}
-
-export const VersionContextProvider = ({ children }: Props) => {
-  const { loading, version } = useContextValue();
-
-  if (loading) {
-    return <PageLoading />;
-  }
-
-  return <VersionContext.Provider value={{ version 
}}>{children}</VersionContext.Provider>;
-};
-
-export const VersionContextConsumer = VersionContext.Consumer;
-
-export const useVersion = () => useContext(VersionContext);
diff --git a/config-ui/src/store/version/index.ts 
b/config-ui/src/store/version/index.ts
deleted file mode 100644
index 34ae5c1d0..000000000
--- a/config-ui/src/store/version/index.ts
+++ /dev/null
@@ -1,20 +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.
- *
- */
-
-export * from './types';
-export * from './context';
diff --git a/config-ui/src/store/version/types.ts 
b/config-ui/src/store/version/types.ts
deleted file mode 100644
index dbae9e10c..000000000
--- a/config-ui/src/store/version/types.ts
+++ /dev/null
@@ -1,19 +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.
- *
- */
-
-export type VersionType = string;
diff --git a/config-ui/src/store/version/use-context-value.ts 
b/config-ui/src/store/version/use-context-value.ts
deleted file mode 100644
index a34676201..000000000
--- a/config-ui/src/store/version/use-context-value.ts
+++ /dev/null
@@ -1,50 +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 { useState, useEffect, useMemo } from 'react';
-
-import { transformError } from '@/error';
-
-import type { VersionType } from './types';
-import * as API from './api';
-
-export const useContextValue = () => {
-  const [loading, setLoading] = useState(true);
-  const [version, setVersion] = useState<VersionType>();
-  const [, setError] = useState<any>();
-
-  const getVersion = async () => {
-    setLoading(true);
-    try {
-      const res = await API.getVersion();
-      setVersion(res.version);
-    } catch (err) {
-      setError(() => {
-        throw transformError(err);
-      });
-    } finally {
-      setLoading(false);
-    }
-  };
-
-  useEffect(() => {
-    getVersion();
-  }, []);
-
-  return useMemo(() => ({ loading, version }), [loading, version]);
-};
diff --git a/config-ui/src/utils/request.ts b/config-ui/src/utils/request.ts
index b87f9d39c..3c26ba34c 100644
--- a/config-ui/src/utils/request.ts
+++ b/config-ui/src/utils/request.ts
@@ -27,6 +27,30 @@ const instance = axios.create({
   baseURL: DEVLAKE_ENDPOINT,
 });
 
+const Errors = ['Authorization header is missing', 'Invalid token'];
+
+instance.interceptors.response.use(
+  (response) => response,
+  (error) => {
+    const status = error.response?.status;
+
+    if (status === 401 && Errors.some((err) => 
error.response.data.includes(err))) {
+      toast.error('Please login first');
+      history.push('/login');
+    }
+
+    if (status === 428) {
+      history.push('/db-migrate');
+    }
+
+    if (status === 500) {
+      history.push('/offline');
+    }
+
+    return Promise.reject(error);
+  },
+);
+
 export type ReuqestConfig = {
   method?: AxiosRequestConfig['method'];
   data?: unknown;
@@ -37,17 +61,18 @@ export type ReuqestConfig = {
 
 export const request = (path: string, config?: ReuqestConfig) => {
   const { method = 'get', data, timeout, headers, signal } = config || {};
+
   const cancelTokenSource = axios.CancelToken.source();
   const token = localStorage.getItem('accessToken');
-  var h = { ...headers };
-  if (token) {
-    h.Authorization = `Bearer ${token}`;
-  }
+
   const params: any = {
     url: path,
     method,
     timeout,
-    headers: h,
+    headers: {
+      ...headers,
+      Authorization: token ? `Bearer ${token}` : '',
+    },
     cancelToken: cancelTokenSource?.token,
   };
 
@@ -56,21 +81,6 @@ export const request = (path: string, config?: 
ReuqestConfig) => {
   } else {
     params.data = data;
   }
-  const missingAuthHeader = 'Authorization header is missing';
-  const invalidToken = 'Invalid token';
-
-  instance.interceptors.response.use(
-    (response) => response,
-    (error) => {
-      if (error.response && error.response.status === 401) {
-        // only handle when data contains missingAuthHeader or invalidToken
-        if (error.response.data.includes(missingAuthHeader) || 
error.response.data.includes(invalidToken)) {
-          toast.error('Please login first');
-          history.push('/login');
-        }
-      }
-    },
-  );
 
   const promise = instance.request(params).then((resp) => resp.data);
 

Reply via email to