Skip to content

Commit 1be2bda

Browse files
committed
First attempt at refactoring to Wouter.
1 parent 1de0139 commit 1be2bda

File tree

53 files changed

+320
-467
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+320
-467
lines changed

src/examples/s3-storage/src/frontend/types.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type AdminUiEntityMetadata = {
4343
primaryKeyField: Scalars['String']['output'];
4444
summaryField?: Maybe<Scalars['String']['output']>;
4545
supportedAggregationTypes: Array<AggregationType>;
46+
supportsPseudoCursorPagination: Scalars['Boolean']['output'];
4647
};
4748

4849
export type AdminUiEnumMetadata = {

src/examples/s3-storage/src/types.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type AdminUiEntityMetadata = {
4343
primaryKeyField: Scalars['String']['output'];
4444
summaryField?: Maybe<Scalars['String']['output']>;
4545
supportedAggregationTypes: Array<AggregationType>;
46+
supportsPseudoCursorPagination: Scalars['Boolean']['output'];
4647
};
4748

4849
export type AdminUiEnumMetadata = {

src/examples/xero/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"prop-types": "15.8.1",
4545
"react": "19.0.0",
4646
"react-dom": "19.0.0",
47-
"react-router-dom": "6.28.0",
47+
"wouter": "3.6.0",
4848
"xero-node": "10.0.0"
4949
},
5050
"devDependencies": {

src/examples/xero/src/admin-ui/custom-pages/dashboards/single-company/component.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ResponsiveLine } from '@nivo/line';
22
import React from 'react';
3-
import { useParams } from 'react-router-dom';
3+
import { useParams } from 'wouter';
44
import { gql } from '@apollo/client';
55
import { Loader } from '@exogee/graphweaver-admin-ui-components';
66

@@ -26,7 +26,7 @@ export const singleCompanyQuery = gql`
2626
`;
2727

2828
export const SingleCompany = () => {
29-
const { tenantId } = useParams();
29+
const { tenantId } = useParams<{ tenantId: string }>();
3030

3131
const { data, loading, error } = useSingleCompanyProfitAndLossRowsQuery({
3232
variables: { tenantId },

src/examples/xero/src/admin-ui/custom-pages/index.tsx

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { XeroAuthCodeReceiver } from './xero-auth-code-receiver';
55
import { AllCompanies, SingleCompany } from './dashboards';
66
import { TenantsQuery } from './index.generated';
77
import { WelcomePage } from './welcome-page';
8+
import { Route } from 'wouter';
89

910
const tenantsQuery = gql`
1011
query Tenants {
@@ -31,17 +32,16 @@ export const customPages = {
3132
},
3233
{
3334
path: 'xero-dashboard',
34-
element: <DefaultLayout />,
35-
children: [
36-
{
37-
index: true,
38-
element: <AllCompanies />,
39-
},
40-
{
41-
path: ':tenantId',
42-
element: <SingleCompany />,
43-
},
44-
],
35+
element: (
36+
<DefaultLayout>
37+
<Route path="/:tenantId">
38+
<SingleCompany />
39+
</Route>
40+
<Route path="/">
41+
<AllCompanies />
42+
</Route>
43+
</DefaultLayout>
44+
),
4545
},
4646
],
4747

src/examples/xero/src/admin-ui/custom-pages/xero-auth-code-receiver.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useSearchParams, Navigate } from 'react-router-dom';
1+
import { useSearchParams, Redirect } from 'wouter';
22

33
export const XeroAuthCodeReceiver = () => {
44
const [searchParams] = useSearchParams();
@@ -22,5 +22,5 @@ export const XeroAuthCodeReceiver = () => {
2222
localStorage.setItem('graphweaver-auth', window.location.href);
2323

2424
// Ok, now that we've saved it we're good to go.
25-
return <Navigate to="/" />;
25+
return <Redirect to="/" />;
2626
};

src/examples/xero/src/frontend/types.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export type AdminUiEntityMetadata = {
175175
primaryKeyField: Scalars['String']['output'];
176176
summaryField?: Maybe<Scalars['String']['output']>;
177177
supportedAggregationTypes: Array<AggregationType>;
178+
supportsPseudoCursorPagination: Scalars['Boolean']['output'];
178179
};
179180

180181
export type AdminUiEnumMetadata = {

src/examples/xero/src/types.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export type AdminUiEntityMetadata = {
175175
primaryKeyField: Scalars['String']['output'];
176176
summaryField?: Maybe<Scalars['String']['output']>;
177177
supportedAggregationTypes: Array<AggregationType>;
178+
supportsPseudoCursorPagination: Scalars['Boolean']['output'];
178179
};
179180

180181
export type AdminUiEnumMetadata = {

src/packages/admin-ui-components/@types/custom-pages.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare module 'virtual:graphweaver-user-supplied-custom-pages' {
2-
import { RouteObject } from 'react-router-dom';
2+
import { RouteObject } from '@exogee/graphweaver-admin-ui';
33
import { JSX } from 'react';
44

55
export interface NavLinkExport {

src/packages/admin-ui-components/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,17 @@
3636
"luxon": "3.5.0",
3737
"papaparse": "5.5.2",
3838
"react-day-picker": "9.4.1",
39+
"react-error-boundary": "5.0.0",
3940
"react-hot-toast": "2.4.1",
4041
"react-resizable-panels": "2.1.7",
41-
"react-syntax-highlighter": "15.6.1"
42+
"react-syntax-highlighter": "15.6.1",
43+
"wouter": "3.6.0"
4244
},
4345
"peerDependencies": {
4446
"formik": "^2.4.6",
4547
"graphql": "16",
4648
"react": "^18.0.0 || ^19.0.0",
47-
"react-dom": "^18.0.0 || ^19.0.0",
48-
"react-router-dom": "^6.26.2"
49+
"react-dom": "^18.0.0 || ^19.0.0"
4950
},
5051
"devDependencies": {
5152
"@types/graphql-deduplicator": "2.0.2",
@@ -60,7 +61,6 @@
6061
"graphql": "16.10.0",
6162
"react": "19.0.0",
6263
"react-dom": "19.0.0",
63-
"react-router-dom": "6.28.0",
6464
"typescript": "5.7.2",
6565
"vite": "6.1.0"
6666
},

src/packages/admin-ui-components/src/404-page/component.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Link } from 'react-router-dom';
1+
import { Link } from 'wouter';
22
import { Button, GraphweaverLogo, Spacer, StarField } from '..';
33
import { ErrorIcon } from '../assets';
44
import styles from './styles.module.css';

src/packages/admin-ui-components/src/button/button.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import clsx from 'clsx';
22
import { useEffect, useRef, PropsWithChildren } from 'react';
33
import { Spinner, SpinnerSize } from '../spinner';
44
import styles from './styles.module.css';
5-
import { useNavigate } from 'react-router-dom';
5+
import { useLocation } from 'wouter';
66

77
export interface ButtonProps {
88
onClick?(): any /** Event emitted when clicked */;
@@ -25,7 +25,7 @@ export const Button = ({
2525
loading = false,
2626
}: PropsWithChildren<ButtonProps>) => {
2727
const buttonRef = useRef<HTMLButtonElement>(null);
28-
const navigate = useNavigate();
28+
const [, setLocation] = useLocation();
2929

3030
if (onClick && href) {
3131
console.warn(
@@ -60,7 +60,7 @@ export const Button = ({
6060
<button
6161
ref={buttonRef}
6262
onClick={() => {
63-
if (href) navigate(href);
63+
if (href) setLocation(href);
6464
else onClick?.();
6565
}}
6666
className={clsx([className, styles.button, disabled && styles.disabled])}

src/packages/admin-ui-components/src/default-error-fallback/component.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useState } from 'react';
2-
import { Link, useRouteError } from 'react-router-dom';
2+
import { Link } from 'wouter';
3+
import type { FallbackProps } from 'react-error-boundary';
34
import { Button, GraphweaverLogo, Spacer, StarField } from '..';
45
import { ErrorIcon } from '../assets';
56
import styles from './styles.module.css';
67

78
const originalButtonText = 'Copy Error Information to Clipboard';
89

9-
export const DefaultErrorFallback = () => {
10-
const error = useRouteError();
10+
export const DefaultErrorFallback = ({ error }: FallbackProps) => {
1111
const [showingCopied, setShowingCopied] = useState(false);
1212

1313
// Ensure we log the error to the console so the developer can see it.

src/packages/admin-ui-components/src/detail-panel/component.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useMutation, useQuery, FetchResult } from '@apollo/client';
22
import clsx from 'clsx';
33
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
44
import { useCallback, useEffect, useMemo, useState } from 'react';
5-
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
5+
import { useLocation, useParams, useSearchParams } from 'wouter';
66
import toast from 'react-hot-toast';
77

88
import { customFields } from 'virtual:graphweaver-user-supplied-custom-fields';
@@ -332,7 +332,7 @@ export const DetailPanel = () => {
332332
const modalRedirectUrl = search.get('modalRedirectUrl');
333333

334334
const { id, entity } = useParams();
335-
const navigate = useNavigate();
335+
const [, setLocation] = useLocation();
336336
const { selectedEntity } = useSelectedEntity();
337337
const { entityByName, entityByType } = useSchema();
338338

@@ -358,12 +358,12 @@ export const DetailPanel = () => {
358358
// If the path does not include the entity name, then we've already moved to a different entity
359359
// Navigate to the current path to close the overlay
360360
if (!regexPattern.test(path)) {
361-
navigate(path);
361+
setLocation(path);
362362
return;
363363
}
364364

365365
const { filters, sort } = decodeSearchParams(search);
366-
navigate(routeFor({ entity: selectedEntity, filters, sort }));
366+
setLocation(routeFor({ entity: selectedEntity, filters, sort }));
367367
};
368368

369369
const customFieldsToShow =
@@ -432,7 +432,7 @@ export const DetailPanel = () => {
432432

433433
const navigateToDetailForEntity = (id?: string) => {
434434
if (!id) return;
435-
navigate(routeFor({ entity: selectedEntity, id }));
435+
setLocation(routeFor({ entity: selectedEntity, id }));
436436
};
437437

438438
const handleOnSubmit = async (values: any, actions: FormikHelpers<any>) => {
@@ -508,7 +508,7 @@ export const DetailPanel = () => {
508508
const handleConfirmLeave = () => {
509509
if (!modalRedirectUrl) return;
510510

511-
navigate(modalRedirectUrl, { replace: true });
511+
setLocation(modalRedirectUrl, { replace: true });
512512
};
513513

514514
const handleCancelLeave = () => {

src/packages/admin-ui-components/src/detail-panel/fields/link-field.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { useField, useFormikContext } from 'formik';
2-
import { useNavigate, useSearchParams } from 'react-router-dom';
2+
import { useLocation, useSearchParams } from 'wouter';
33
import { EntityField, routeFor } from '../../utils';
44

55
export const LinkField = ({ name, field }: { name: string; field: EntityField }) => {
66
const { dirty } = useFormikContext();
7-
const navigate = useNavigate();
7+
const [, setLocation] = useLocation();
88
const [_, meta] = useField({ name: name, multiple: false });
99
const { initialValue: formEntity } = meta;
1010
const [__, setSearchParams] = useSearchParams();
@@ -20,7 +20,7 @@ export const LinkField = ({ name, field }: { name: string; field: EntityField })
2020
searchParams.set('modalRedirectUrl', route);
2121
setSearchParams(searchParams);
2222
} else {
23-
navigate(route);
23+
setLocation(route);
2424
}
2525
};
2626

src/packages/admin-ui-components/src/entity-list/columns.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CellContext, createColumnHelper } from '@tanstack/react-table';
22
import { customFields } from 'virtual:graphweaver-user-supplied-custom-fields';
3-
import { Link } from 'react-router-dom';
3+
import { Link } from 'wouter';
44

55
import { Entity, EntityField, routeFor } from '../utils';
66
import { cells } from '../table/cells';

src/packages/admin-ui-components/src/entity-list/component.tsx

+12-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { addStabilizationToFilter } from '@exogee/graphweaver-apollo-client';
33
import { Row, RowSelectionState } from '@tanstack/react-table';
44
import { useMemo, useState } from 'react';
55
import toast from 'react-hot-toast';
6-
import { Outlet, useNavigate, useParams, useSearchParams } from 'react-router-dom';
6+
import { useLocation, useParams, useSearchParams } from 'wouter';
77

88
import { Button } from '../button';
99
import { generateDeleteManyEntitiesMutation } from '../detail-panel/graphql';
@@ -27,11 +27,11 @@ import { QueryResponse, queryForEntityPage } from './graphql';
2727
import { ExportModal } from '../export-modal';
2828
import styles from './styles.module.css';
2929

30-
export const EntityList = <TData extends object>() => {
30+
export const EntityList = <TData extends object>({ children }: { children: React.ReactNode }) => {
3131
const { entity: entityName, id } = useParams();
3232
if (!entityName) throw new Error('There should always be an entity at this point.');
3333

34-
const navigate = useNavigate();
34+
const [, setLocation] = useLocation();
3535
const { entityByName, entityByType } = useSchema();
3636
const [search] = useSearchParams();
3737
const { sort: sorting, filters } = decodeSearchParams(search);
@@ -47,7 +47,7 @@ export const EntityList = <TData extends object>() => {
4747
defaultFilter,
4848
fieldForDetailPanelNavigationId,
4949
excludeFromTracing,
50-
supportsPseudoCursorPagination
50+
supportsPseudoCursorPagination,
5151
} = entity;
5252
const columns = useMemo(
5353
() => convertEntityToColumns(entity, entityByType),
@@ -84,11 +84,11 @@ export const EntityList = <TData extends object>() => {
8484
}
8585

8686
const handleRowClick = <T extends object>(row: Row<T>) => {
87-
navigate(`${row.original[fieldForDetailPanelNavigationId as keyof T]}`);
87+
setLocation(`${row.original[fieldForDetailPanelNavigationId as keyof T]}`);
8888
};
8989

9090
const handleSortClick = (newSort: SortEntity) => {
91-
navigate(
91+
setLocation(
9292
routeFor({
9393
entity,
9494
filters,
@@ -103,15 +103,17 @@ export const EntityList = <TData extends object>() => {
103103
const offset = supportsPseudoCursorPagination ? 0 : nextPage * PAGE_SIZE;
104104

105105
const filterVar = variables.filter ?? {};
106-
const filter = supportsPseudoCursorPagination ? addStabilizationToFilter(filterVar, sort, data?.result?.[data.result.length - 1]) : filterVar;
106+
const filter = supportsPseudoCursorPagination
107+
? addStabilizationToFilter(filterVar, sort, data?.result?.[data.result.length - 1])
108+
: filterVar;
107109
fetchMore({
108110
variables: {
109111
...variables,
110112
pagination: {
111113
...variables.pagination,
112-
offset
114+
offset,
113115
},
114-
filter
116+
filter,
115117
},
116118
});
117119
};
@@ -207,7 +209,7 @@ export const EntityList = <TData extends object>() => {
207209
{showExportModal && (
208210
<ExportModal closeModal={() => setShowExportModal(false)} sort={sort} filters={filters} />
209211
)}
210-
<Outlet />
212+
{children}
211213
</div>
212214
);
213215
};

src/packages/admin-ui-components/src/error-view/component.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Link } from 'react-router-dom';
1+
import { Link } from 'wouter';
22
import { RequestIcon } from '../assets/request';
33
import styles from './styles.module.css';
44
import { Spacer } from '../spacer';

src/packages/admin-ui-components/src/filter-bar/component.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ReactNode, useCallback, useEffect, useState } from 'react';
22
import toast from 'react-hot-toast';
3-
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
3+
import { useLocation, useParams, useSearchParams } from 'wouter';
44

55
import { Button } from '../button';
66
import {
@@ -23,7 +23,7 @@ export const FilterBar = ({ iconBefore }: { iconBefore?: ReactNode }) => {
2323
if (!entityName) throw new Error('There should always be an entity at this point.');
2424
const [search] = useSearchParams();
2525
const { entityByName } = useSchema();
26-
const navigate = useNavigate();
26+
const [, setLocation] = useLocation();
2727
const searchParams = decodeSearchParams(search);
2828

2929
const [filtersState, setFiltersState] = useState(searchParams.filters ?? {});
@@ -59,7 +59,7 @@ export const FilterBar = ({ iconBefore }: { iconBefore?: ReactNode }) => {
5959
);
6060

6161
// Go off to a supported URL.
62-
navigate(
62+
setLocation(
6363
routeFor({
6464
entity: entityName,
6565
id,
@@ -70,7 +70,7 @@ export const FilterBar = ({ iconBefore }: { iconBefore?: ReactNode }) => {
7070
);
7171
}
7272

73-
navigate(
73+
setLocation(
7474
routeFor({
7575
entity: entityName,
7676
id,

0 commit comments

Comments
 (0)