Skip to content

Commit 0bbd84b

Browse files
committed
refactor(ui): migrate unsaved-page blocker to react-router useBlocker API
1 parent 1036f73 commit 0bbd84b

6 files changed

Lines changed: 138 additions & 156 deletions

File tree

ui/dashboard/src/app/index.tsx

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { memo, useCallback, useEffect, useState } from 'react';
22
import { I18nextProvider } from 'react-i18next';
33
import {
4-
BrowserRouter,
4+
createBrowserRouter,
5+
Outlet,
56
Route,
7+
RouterProvider,
68
Routes,
7-
useParams,
9+
useLocation,
810
useNavigate,
9-
useLocation
11+
useParams
1012
} from 'react-router';
1113
import { QueryClientProvider } from '@tanstack/react-query';
1214
import {
@@ -95,46 +97,12 @@ export const AppLoading = () => (
9597
</div>
9698
);
9799

98-
function App() {
99-
return (
100-
<I18nextProvider i18n={i18n}>
101-
<QueryClientProvider client={queryClient}>
102-
<ConfirmProvider>
103-
<BrowserRouter>
104-
<AuthProvider>
105-
<Routes>
106-
<Route
107-
path={PAGE_PATH_AUTH_CALLBACK}
108-
element={<AuthCallbackPage />}
109-
/>
110-
<Route
111-
path={PAGE_PATH_AUTH_DEMO_CALLBACK}
112-
element={<AuthDemoCallbackPage />}
113-
/>
114-
<Route
115-
path={PAGE_PATH_AUTH_SIGNIN}
116-
element={<SignInEmailPage />}
117-
/>
118-
<Route
119-
path={PAGE_PATH_DEMO_SITE}
120-
element={<AccessDemoPage />}
121-
/>
122-
<Route
123-
path={`${PAGE_PATH_DEMO_SITE}/new`}
124-
element={<CreateDemoPage />}
125-
/>
126-
<Route path={`${PAGE_PATH_ROOT}*`} element={<Root />} />
127-
</Routes>
128-
</AuthProvider>
129-
</BrowserRouter>
130-
</ConfirmProvider>
131-
{/* {process.env.NODE_ENV === 'development' && (
132-
<ReactQueryDevtools initialIsOpen={false} />
133-
)} */}
134-
</QueryClientProvider>
135-
</I18nextProvider>
136-
);
137-
}
100+
// All routes live inside AuthShell so every page can access AuthProvider context
101+
const AuthShell = () => (
102+
<AuthProvider>
103+
<Outlet />
104+
</AuthProvider>
105+
);
138106

139107
export const Root = memo(() => {
140108
const authToken = getTokenStorage();
@@ -144,7 +112,7 @@ export const Root = memo(() => {
144112

145113
const handleChangePageKey = useCallback(() => {
146114
setPageKey(uuid());
147-
}, [setPageKey]);
115+
}, []);
148116

149117
if (isInitialLoading) {
150118
return <AppLoading />;
@@ -294,11 +262,37 @@ export const EnvironmentRoot = memo(
294262
<Route path={`${PAGE_PATH_AUDIT_LOGS}/*`} element={<AuditLogsPage />} />
295263
<Route path={`${PAGE_PATH_DEBUGGER}/*`} element={<DebuggerPage />} />
296264
<Route path={`${PAGE_PATH_INSIGHTS}/*`} element={<InsightsPage />} />
297-
298265
<Route path="*" element={<NotFoundPage />} />
299266
</Routes>
300267
);
301268
}
302269
);
303270

271+
// Router is defined after all components to avoid "used before declaration" errors
272+
const router = createBrowserRouter([
273+
{
274+
element: <AuthShell />,
275+
children: [
276+
{ path: PAGE_PATH_AUTH_CALLBACK, element: <AuthCallbackPage /> },
277+
{ path: PAGE_PATH_AUTH_DEMO_CALLBACK, element: <AuthDemoCallbackPage /> },
278+
{ path: PAGE_PATH_AUTH_SIGNIN, element: <SignInEmailPage /> },
279+
{ path: PAGE_PATH_DEMO_SITE, element: <AccessDemoPage /> },
280+
{ path: `${PAGE_PATH_DEMO_SITE}/new`, element: <CreateDemoPage /> },
281+
{ path: `${PAGE_PATH_ROOT}*`, element: <Root /> }
282+
]
283+
}
284+
]);
285+
286+
function App() {
287+
return (
288+
<I18nextProvider i18n={i18n}>
289+
<QueryClientProvider client={queryClient}>
290+
<ConfirmProvider>
291+
<RouterProvider router={router} />
292+
</ConfirmProvider>
293+
</QueryClientProvider>
294+
</I18nextProvider>
295+
);
296+
}
297+
304298
export default App;

ui/dashboard/src/components/navigation/my-projects.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { ENVIRONMENT_WITH_EMPTY_ID } from 'constants/app';
1313
import { PAGE_PATH_FEATURES } from 'constants/routing';
1414
import { useToast } from 'hooks';
15-
import { allowNavigation, useConfirm } from 'hooks/use-unsaved-leave-page';
15+
import { useConfirm } from 'hooks/use-unsaved-leave-page';
1616
import { useTranslation } from 'i18n';
1717
import {
1818
clearCurrentEnvIdStorage,
@@ -38,7 +38,12 @@ const MyProjects = () => {
3838
const navigate = useNavigate();
3939
const { consoleAccount, logout } = useAuth();
4040
const { errorNotify } = useToast();
41-
const { isShow: showConfirm, confirm, setIsShow } = useConfirm();
41+
const {
42+
isShow: showConfirm,
43+
confirm,
44+
setIsShow,
45+
allowNavigation
46+
} = useConfirm();
4247
const [isShowProjectsList, setIsShowProjectsList] = useState(false);
4348
const [searchValue, setSearchValue] = useState('');
4449
const [projects, setProjects] = useState<Project[]>();

ui/dashboard/src/components/navigation/switch-organization.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { switchOrganization } from '@api/auth';
44
import { useAuth } from 'auth';
55
import { PAGE_PATH_ROOT } from 'constants/routing';
66
import { useToast } from 'hooks';
7-
import { allowNavigation, useConfirm } from 'hooks/use-unsaved-leave-page';
7+
import { useConfirm } from 'hooks/use-unsaved-leave-page';
88
import { useTranslation } from 'i18n';
99
import { clearCurrentEnvIdStorage } from 'storage/environment';
1010
import {
@@ -67,7 +67,13 @@ const SwitchOrganization = ({
6767
const { t } = useTranslation(['common', 'form']);
6868
const { myOrganizations, onMeFetcher } = useAuth();
6969
const { errorNotify } = useToast();
70-
const { isShow: showConfirm, setIsShow, confirm, options } = useConfirm();
70+
const {
71+
isShow: showConfirm,
72+
setIsShow,
73+
confirm,
74+
options,
75+
allowNavigation
76+
} = useConfirm();
7177
const organizationId = getOrgIdStorage();
7278
const [searchValue, setSearchValue] = useState('');
7379
const [currentOrganization, setCurrentOrganization] = useState(

0 commit comments

Comments
 (0)