diff --git a/src-web/components/AppRouter.tsx b/src-web/components/AppRouter.tsx
index c3e3725c..1f01ffd4 100644
--- a/src-web/components/AppRouter.tsx
+++ b/src-web/components/AppRouter.tsx
@@ -1,19 +1,18 @@
-import { createBrowserRouter, Navigate, Outlet, RouterProvider } from 'react-router-dom';
+import { createBrowserRouter, Navigate, Outlet, RouterProvider, useParams } from 'react-router-dom';
import { routePaths, useAppRoutes } from '../hooks/useAppRoutes';
-import { useRecentRequests } from '../hooks/useRecentRequests';
import { useHttpRequests } from '../hooks/useHttpRequests';
+import { useRecentRequests } from '../hooks/useRecentRequests';
+import { DialogProvider } from './DialogContext';
import { GlobalHooks } from './GlobalHooks';
+import RouteError from './RouteError';
import Workspace from './Workspace';
import Workspaces from './Workspaces';
-import { DialogProvider } from './DialogContext';
-import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId';
-import RouteError from './RouteError';
const router = createBrowserRouter([
{
path: '/',
errorElement: ,
- element: ,
+ element: ,
children: [
{
path: '/',
@@ -26,18 +25,20 @@ const router = createBrowserRouter([
{
path: routePaths.workspace({
workspaceId: ':workspaceId',
- environmentId: ':environmentId',
}),
element: ,
},
{
path: routePaths.request({
workspaceId: ':workspaceId',
- environmentId: ':environmentId',
requestId: ':requestId',
}),
element: ,
},
+ {
+ path: '/workspaces/:workspaceId/environments/:environmentId/requests/:requestId',
+ element: ,
+ },
],
},
]);
@@ -48,7 +49,6 @@ export function AppRouter() {
function WorkspaceOrRedirect() {
const recentRequests = useRecentRequests();
- const activeEnvironmentId = useActiveEnvironmentId();
const requests = useHttpRequests();
const request = requests.find((r) => r.id === recentRequests[0]);
const routes = useAppRoutes();
@@ -58,20 +58,43 @@ function WorkspaceOrRedirect() {
}
const { id: requestId, workspaceId } = request;
- const environmentId = activeEnvironmentId ?? undefined;
return (
);
}
-function Layout() {
+function RedirectLegacyEnvironmentURLs() {
+ const routes = useAppRoutes();
+ const {
+ requestId,
+ environmentId: rawEnvironmentId,
+ workspaceId,
+ } = useParams<{
+ requestId?: string;
+ workspaceId?: string;
+ environmentId?: string;
+ }>();
+ const environmentId = rawEnvironmentId === '__default__' ? undefined : rawEnvironmentId;
+
+ let to = '/';
+ if (workspaceId != null && requestId != null) {
+ to = routes.paths.request({ workspaceId, environmentId, requestId });
+ } else if (workspaceId != null) {
+ to = routes.paths.workspace({ workspaceId, environmentId });
+ } else {
+ to = routes.paths.workspaces();
+ }
+
+ return ;
+}
+
+function DefaultLayout() {
return (
diff --git a/src-web/hooks/useActiveEnvironmentId.ts b/src-web/hooks/useActiveEnvironmentId.ts
index a0b333c8..71f14d33 100644
--- a/src-web/hooks/useActiveEnvironmentId.ts
+++ b/src-web/hooks/useActiveEnvironmentId.ts
@@ -1,9 +1,11 @@
-import { useParams } from 'react-router-dom';
-import type { RouteParamsRequest } from './useAppRoutes';
+import { useSearchParams } from 'react-router-dom';
+
+export const QUERY_ENVIRONMENT_ID = 'environment_id';
export function useActiveEnvironmentId(): string | null {
- const { environmentId } = useParams();
- if (environmentId == null || environmentId === '__default__') {
+ const [params] = useSearchParams();
+ const environmentId = params.get(QUERY_ENVIRONMENT_ID);
+ if (environmentId == null) {
return null;
}
diff --git a/src-web/hooks/useAppRoutes.ts b/src-web/hooks/useAppRoutes.ts
index 664c01dc..07110e83 100644
--- a/src-web/hooks/useAppRoutes.ts
+++ b/src-web/hooks/useAppRoutes.ts
@@ -1,4 +1,5 @@
import { useNavigate } from 'react-router-dom';
+import { QUERY_ENVIRONMENT_ID } from './useActiveEnvironmentId';
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
import { useActiveRequestId } from './useActiveRequestId';
import type { Environment } from '../lib/models';
@@ -23,7 +24,11 @@ export const routePaths = {
environmentId: ':environmentId',
} as RouteParamsWorkspace,
) {
- return `/workspaces/${workspaceId}/environments/${environmentId ?? '__default__'}`;
+ let path = `/workspaces/${workspaceId}`;
+ if (environmentId != null) {
+ path += `?${QUERY_ENVIRONMENT_ID}=${encodeURIComponent(environmentId)}`;
+ }
+ return path;
},
request(
{ workspaceId, environmentId, requestId } = {
@@ -32,7 +37,11 @@ export const routePaths = {
requestId: ':requestId',
} as RouteParamsRequest,
) {
- return `${this.workspace({ workspaceId, environmentId })}/requests/${requestId}`;
+ let path = `/workspaces/${workspaceId}/requests/${requestId}`;
+ if (environmentId != null) {
+ path += `?${QUERY_ENVIRONMENT_ID}=${encodeURIComponent(environmentId)}`;
+ }
+ return path;
},
};
@@ -41,16 +50,16 @@ export function useAppRoutes() {
const requestId = useActiveRequestId();
const nav = useNavigate();
- const navigate = useCallback((
- path: T,
- ...params: Parameters<(typeof routePaths)[T]>
- ) => {
- // Not sure how to make TS work here, but it's good from the
- // outside caller perspective.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const resolvedPath = routePaths[path](...(params as any));
- nav(resolvedPath);
- }, [nav]);
+ const navigate = useCallback(
+ (path: T, ...params: Parameters<(typeof routePaths)[T]>) => {
+ // Not sure how to make TS work here, but it's good from the
+ // outside caller perspective.
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const resolvedPath = routePaths[path](...(params as any));
+ nav(resolvedPath);
+ },
+ [nav],
+ );
const setEnvironment = useCallback(
(environment: Environment | null) => {