mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 19:35:13 +01:00
fix(ui): provide data router for navigation guards
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
77faf1744e
commit
18860faf4a
4 files changed
+76
-32
No files matched your search
@@ -0,0 +1,38 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { flushSync } from "react-dom";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { RouterProvider, useBlocker } from "@/lib/router";
|
||||
import { createAppRouter } from "./app-router";
|
||||
|
||||
describe("createAppRouter", () => {
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
|
||||
beforeEach(() => {
|
||||
window.history.replaceState(null, "", "/agents/test/configuration");
|
||||
container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
flushSync(() => root.unmount());
|
||||
container.remove();
|
||||
});
|
||||
|
||||
it("provides the data-router context required by navigation blockers", async () => {
|
||||
function BlockerProbe() {
|
||||
const blocker = useBlocker(true);
|
||||
return <span>{blocker.state}</span>;
|
||||
}
|
||||
|
||||
const router = createAppRouter(<BlockerProbe />);
|
||||
|
||||
flushSync(() => root.render(<RouterProvider router={router} />));
|
||||
|
||||
expect(container.textContent).toBe("unblocked");
|
||||
router.dispose();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { createBrowserRouter } from "@/lib/router";
|
||||
|
||||
export function createAppRouter(element: ReactNode) {
|
||||
return createBrowserRouter([
|
||||
{
|
||||
path: "*",
|
||||
element,
|
||||
},
|
||||
]);
|
||||
}
|
||||
+27
-24
@@ -2,7 +2,7 @@ import * as React from "react";
|
||||
import { StrictMode } from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { BrowserRouter } from "@/lib/router";
|
||||
import { RouterProvider } from "@/lib/router";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { App } from "./App";
|
||||
import { CompanyProvider, useCompany } from "./context/CompanyContext";
|
||||
@@ -18,6 +18,7 @@ import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { initPluginBridge } from "./plugins/bridge-init";
|
||||
import { PluginLauncherProvider } from "./plugins/launchers";
|
||||
import { startPerfMeasureReaper } from "./lib/perf-measure-reaper";
|
||||
import { createAppRouter } from "./lib/app-router";
|
||||
import "@mdxeditor/editor/style.css";
|
||||
import "./index.css";
|
||||
|
||||
@@ -52,33 +53,35 @@ function CompanyAwareBreadcrumbProvider({ children }: { children: React.ReactNod
|
||||
return <BreadcrumbProvider companyName={selectedCompany?.name ?? null}>{children}</BreadcrumbProvider>;
|
||||
}
|
||||
|
||||
const router = createAppRouter(
|
||||
<CompanyProvider>
|
||||
<EditorAutocompleteProvider>
|
||||
<ToastProvider>
|
||||
<LiveUpdatesProvider>
|
||||
<TooltipProvider>
|
||||
<CompanyAwareBreadcrumbProvider>
|
||||
<SidebarProvider>
|
||||
<PanelProvider>
|
||||
<PluginLauncherProvider>
|
||||
<DialogProvider>
|
||||
<App />
|
||||
</DialogProvider>
|
||||
</PluginLauncherProvider>
|
||||
</PanelProvider>
|
||||
</SidebarProvider>
|
||||
</CompanyAwareBreadcrumbProvider>
|
||||
</TooltipProvider>
|
||||
</LiveUpdatesProvider>
|
||||
</ToastProvider>
|
||||
</EditorAutocompleteProvider>
|
||||
</CompanyProvider>,
|
||||
);
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ThemeProvider>
|
||||
<BrowserRouter>
|
||||
<CompanyProvider>
|
||||
<EditorAutocompleteProvider>
|
||||
<ToastProvider>
|
||||
<LiveUpdatesProvider>
|
||||
<TooltipProvider>
|
||||
<CompanyAwareBreadcrumbProvider>
|
||||
<SidebarProvider>
|
||||
<PanelProvider>
|
||||
<PluginLauncherProvider>
|
||||
<DialogProvider>
|
||||
<App />
|
||||
</DialogProvider>
|
||||
</PluginLauncherProvider>
|
||||
</PanelProvider>
|
||||
</SidebarProvider>
|
||||
</CompanyAwareBreadcrumbProvider>
|
||||
</TooltipProvider>
|
||||
</LiveUpdatesProvider>
|
||||
</ToastProvider>
|
||||
</EditorAutocompleteProvider>
|
||||
</CompanyProvider>
|
||||
</BrowserRouter>
|
||||
<RouterProvider router={router} />
|
||||
</ThemeProvider>
|
||||
</QueryClientProvider>
|
||||
</StrictMode>
|
||||
|
||||
@@ -1061,14 +1061,6 @@ export function AgentDetail() {
|
||||
});
|
||||
}, [resolvedAgentId, agentMembershipState]);
|
||||
|
||||
useBeforeUnload(
|
||||
useCallback((event) => {
|
||||
if (!configDirty) return;
|
||||
event.preventDefault();
|
||||
event.returnValue = "";
|
||||
}, [configDirty]),
|
||||
);
|
||||
|
||||
if (isLoading) return <PageSkeleton variant="detail" />;
|
||||
if (error) return <p className="text-sm text-destructive">{error.message}</p>;
|
||||
if (!agent) return null;
|
||||
|
||||
Reference in new issue
Block a user