Fix @probo/trust lint errors
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -1,28 +0,0 @@
|
|||||||
import js from '@eslint/js'
|
|
||||||
import globals from 'globals'
|
|
||||||
import reactHooks from 'eslint-plugin-react-hooks'
|
|
||||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
|
||||||
import tseslint from 'typescript-eslint'
|
|
||||||
|
|
||||||
export default tseslint.config(
|
|
||||||
{ ignores: ['dist'] },
|
|
||||||
{
|
|
||||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
||||||
files: ['**/*.{ts,tsx}'],
|
|
||||||
languageOptions: {
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
globals: globals.browser,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
'react-hooks': reactHooks,
|
|
||||||
'react-refresh': reactRefresh,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
...reactHooks.configs.recommended.rules,
|
|
||||||
'react-refresh/only-export-components': [
|
|
||||||
'warn',
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
27
apps/trust/eslint.config.mjs
Normal file
27
apps/trust/eslint.config.mjs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import js from "@eslint/js";
|
||||||
|
import globals from "globals";
|
||||||
|
import reactHooks from "eslint-plugin-react-hooks";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{ ignores: ["dist"] },
|
||||||
|
{
|
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
|
files: ["**/*.{ts,tsx}"],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
parserOptions: {
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
"react-hooks": reactHooks,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...reactHooks.configs.recommended.rules,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"@probo/helpers": "1.0.0",
|
"@probo/helpers": "1.0.0",
|
||||||
"@probo/hooks": "1.0.0",
|
"@probo/hooks": "1.0.0",
|
||||||
"@probo/i18n": "1.0.0",
|
"@probo/i18n": "1.0.0",
|
||||||
|
"@probo/routes": "^1.0.0",
|
||||||
"@probo/ui": "1.0.0",
|
"@probo/ui": "1.0.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
@@ -41,7 +42,6 @@
|
|||||||
"babel-plugin-relay": "^19.0.0",
|
"babel-plugin-relay": "^19.0.0",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.19",
|
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"graphql": "^16.11.0",
|
"graphql": "^16.11.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to handle cleanup after a delay
|
|
||||||
*
|
|
||||||
* Used for disposing the graphQL query when the component unmounts
|
|
||||||
*/
|
|
||||||
export function useCleanup(callback: () => void, delay: number) {
|
|
||||||
const timer = useRef<ReturnType<typeof setTimeout>>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (timer.current) {
|
|
||||||
clearTimeout(timer.current);
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
timer.current = setTimeout(callback, delay);
|
|
||||||
};
|
|
||||||
}, [callback, delay]);
|
|
||||||
}
|
|
||||||
@@ -56,7 +56,7 @@ export function useMutationWithToasts<T extends MutationParameters>(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[mutate]
|
[mutate, toast, __, baseOptions]
|
||||||
);
|
);
|
||||||
|
|
||||||
return [mutateWithToast, isLoading] as const;
|
return [mutateWithToast, isLoading] as const;
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ function Subprocessors({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasAnyCountries = vendors.some((vendor) => {
|
const hasAnyCountries = vendors.some((vendor) => {
|
||||||
const vendorData = vendor.node as any;
|
const vendorData = vendor.node;
|
||||||
return vendorData.countries && vendorData.countries.length > 0;
|
return vendorData.countries && vendorData.countries.length > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,15 @@ import {
|
|||||||
createBrowserRouter,
|
createBrowserRouter,
|
||||||
Navigate,
|
Navigate,
|
||||||
redirect,
|
redirect,
|
||||||
type RouteObject,
|
|
||||||
useLoaderData,
|
|
||||||
useRouteError,
|
useRouteError,
|
||||||
} from "react-router";
|
} from "react-router";
|
||||||
import { type ComponentType, Fragment, Suspense } from "react";
|
import { Fragment } from "react";
|
||||||
import {
|
import {
|
||||||
relayEnvironment,
|
relayEnvironment,
|
||||||
UnAuthenticatedError,
|
UnAuthenticatedError,
|
||||||
} from "./providers/RelayProviders";
|
} from "./providers/RelayProviders.tsx";
|
||||||
import { loadQuery, type PreloadedQuery } from "react-relay";
|
import { loadQuery } from "react-relay";
|
||||||
import { useCleanup } from "./hooks/useDelayedEffect";
|
import { PageError } from "./components/PageError.tsx";
|
||||||
import { PageError } from "./components/PageError";
|
|
||||||
import { MainLayout } from "/layouts/MainLayout";
|
import { MainLayout } from "/layouts/MainLayout";
|
||||||
import {
|
import {
|
||||||
currentTrustGraphQuery,
|
currentTrustGraphQuery,
|
||||||
@@ -24,15 +21,9 @@ import { OverviewPage } from "/pages/OverviewPage";
|
|||||||
import { DocumentsPage } from "/pages/DocumentsPage";
|
import { DocumentsPage } from "/pages/DocumentsPage";
|
||||||
import { SubprocessorsPage } from "/pages/SubprocessorsPage";
|
import { SubprocessorsPage } from "/pages/SubprocessorsPage";
|
||||||
import { AccessPage } from "./pages/AccessPage.tsx";
|
import { AccessPage } from "./pages/AccessPage.tsx";
|
||||||
import { TabSkeleton } from "./components/Skeletons/TabSkeleton";
|
import { TabSkeleton } from "./components/Skeletons/TabSkeleton.tsx";
|
||||||
import { MainSkeleton } from "./components/Skeletons/MainSkeleton";
|
import { MainSkeleton } from "./components/Skeletons/MainSkeleton.tsx";
|
||||||
|
import { loaderFromQueryLoader, routeFromAppRoute, withQueryRef, type AppRoute } from "@probo/routes";
|
||||||
export type AppRoute = Omit<RouteObject, "Component" | "children"> & {
|
|
||||||
Component?: ComponentType<any>;
|
|
||||||
children?: AppRoute[];
|
|
||||||
fallback?: ComponentType;
|
|
||||||
queryLoader?: (params: any) => PreloadedQuery<any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level error boundary
|
* Top level error boundary
|
||||||
@@ -59,47 +50,45 @@ const routes = [
|
|||||||
// Custom domain routes (subdomain-based)
|
// Custom domain routes (subdomain-based)
|
||||||
{
|
{
|
||||||
path: "/overview",
|
path: "/overview",
|
||||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||||
Component: MainLayout,
|
Component: withQueryRef(MainLayout),
|
||||||
fallback: MainSkeleton,
|
Fallback: MainSkeleton,
|
||||||
ErrorBoundary: ErrorBoundary,
|
ErrorBoundary: ErrorBoundary,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
fallback: TabSkeleton,
|
Fallback: TabSkeleton,
|
||||||
Component: OverviewPage,
|
Component: OverviewPage,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/documents",
|
path: "/documents",
|
||||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||||
Component: MainLayout,
|
Component: withQueryRef(MainLayout),
|
||||||
fallback: MainSkeleton,
|
Fallback: MainSkeleton,
|
||||||
ErrorBoundary: ErrorBoundary,
|
ErrorBoundary: ErrorBoundary,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
queryLoader: () =>
|
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustDocumentsQuery, {})),
|
||||||
loadQuery(relayEnvironment, currentTrustDocumentsQuery, {}),
|
Fallback: TabSkeleton,
|
||||||
fallback: TabSkeleton,
|
Component: withQueryRef(DocumentsPage),
|
||||||
Component: DocumentsPage,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/subprocessors",
|
path: "/subprocessors",
|
||||||
queryLoader: () => loadQuery(relayEnvironment, currentTrustGraphQuery, {}),
|
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustGraphQuery, {})),
|
||||||
Component: MainLayout,
|
Component: withQueryRef(MainLayout),
|
||||||
fallback: MainSkeleton,
|
Fallback: MainSkeleton,
|
||||||
ErrorBoundary: ErrorBoundary,
|
ErrorBoundary: ErrorBoundary,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
queryLoader: () =>
|
loader: loaderFromQueryLoader(() => loadQuery(relayEnvironment, currentTrustVendorsQuery, {})),
|
||||||
loadQuery(relayEnvironment, currentTrustVendorsQuery, {}),
|
Fallback: TabSkeleton,
|
||||||
fallback: TabSkeleton,
|
Component: withQueryRef(SubprocessorsPage),
|
||||||
Component: SubprocessorsPage,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -115,56 +104,6 @@ const routes = [
|
|||||||
},
|
},
|
||||||
] satisfies AppRoute[];
|
] satisfies AppRoute[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap components with suspense to handle lazy loading & relay loading states
|
|
||||||
*/
|
|
||||||
function routeTransformer({
|
|
||||||
fallback: FallbackComponent,
|
|
||||||
queryLoader,
|
|
||||||
...route
|
|
||||||
}: AppRoute): RouteObject {
|
|
||||||
let result = { ...route };
|
|
||||||
if (FallbackComponent && route.Component) {
|
|
||||||
const OriginalComponent = route.Component;
|
|
||||||
result = {
|
|
||||||
...result,
|
|
||||||
Component: (props) => (
|
|
||||||
<Suspense fallback={<FallbackComponent />}>
|
|
||||||
<OriginalComponent {...props} />
|
|
||||||
</Suspense>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (queryLoader && route.Component) {
|
|
||||||
const OriginalComponent = route.Component;
|
|
||||||
result = {
|
|
||||||
...result,
|
|
||||||
loader: ({ params }) => {
|
|
||||||
const query = queryLoader(params as Record<string, string>);
|
|
||||||
return {
|
|
||||||
queryRef: query,
|
|
||||||
dispose: query.dispose,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
Component: () => {
|
|
||||||
const { queryRef, dispose } = useLoaderData();
|
|
||||||
|
|
||||||
useCleanup(dispose, 1000);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Suspense fallback={FallbackComponent ? <FallbackComponent /> : null}>
|
|
||||||
<OriginalComponent queryRef={queryRef} />
|
|
||||||
</Suspense>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
children: route.children?.map(routeTransformer),
|
|
||||||
} as RouteObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect basename from current URL path
|
// Detect basename from current URL path
|
||||||
// If URL starts with /trust/{slug}, extract that as the basename
|
// If URL starts with /trust/{slug}, extract that as the basename
|
||||||
// Otherwise, use "/" for custom domains
|
// Otherwise, use "/" for custom domains
|
||||||
@@ -174,6 +113,6 @@ function getBasename(): string {
|
|||||||
return trustMatch ? trustMatch[0] : "/";
|
return trustMatch ? trustMatch[0] : "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const router = createBrowserRouter(routes.map(routeTransformer), {
|
export const router = createBrowserRouter(routes.map(routeFromAppRoute), {
|
||||||
basename: getBasename(),
|
basename: getBasename(),
|
||||||
});
|
});
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -22,10 +22,11 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"@probo/helpers": "1.0.0",
|
"@probo/helpers": "^1.0.0",
|
||||||
"@probo/hooks": "1.0.0",
|
"@probo/hooks": "1.0.0",
|
||||||
"@probo/i18n": "1.0.0",
|
"@probo/i18n": "1.0.0",
|
||||||
"@probo/react-lazy": "1.0.0",
|
"@probo/react-lazy": "1.0.0",
|
||||||
|
"@probo/routes": "^1.0.0",
|
||||||
"@probo/ui": "1.0.0",
|
"@probo/ui": "1.0.0",
|
||||||
"@probo/vendors": "0.0.1",
|
"@probo/vendors": "0.0.1",
|
||||||
"@tanstack/react-query": "^5.76.1",
|
"@tanstack/react-query": "^5.76.1",
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
"@probo/helpers": "1.0.0",
|
"@probo/helpers": "1.0.0",
|
||||||
"@probo/hooks": "1.0.0",
|
"@probo/hooks": "1.0.0",
|
||||||
"@probo/i18n": "1.0.0",
|
"@probo/i18n": "1.0.0",
|
||||||
|
"@probo/routes": "^1.0.0",
|
||||||
"@probo/ui": "1.0.0",
|
"@probo/ui": "1.0.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import { ComponentType, LazyExoticComponent } from "react";
|
|
||||||
import { EnvironmentProviderOptions, PreloadedQuery } from "react-relay";
|
|
||||||
import { LoaderFunction, LoaderFunctionArgs, RouteObject, useLoaderData } from "react-router";
|
|
||||||
import { OperationType } from "relay-runtime";
|
|
||||||
import { useCleanup } from "./useDelayedEffect";
|
|
||||||
|
|
||||||
export function withQueryRef<
|
|
||||||
TQuery extends OperationType,
|
|
||||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
|
||||||
>(
|
|
||||||
Component: LazyExoticComponent<ComponentType<{ queryRef: PreloadedQuery<TQuery, TEnvironmentProviderOptions> }>>,
|
|
||||||
) {
|
|
||||||
return () => {
|
|
||||||
const { queryRef, dispose } = useLoaderData();
|
|
||||||
|
|
||||||
useCleanup(dispose, 1000);
|
|
||||||
|
|
||||||
return <Component queryRef={queryRef} />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loaderFromQueryLoader<
|
|
||||||
TQuery extends OperationType,
|
|
||||||
TEnvironmentProviderOptions = EnvironmentProviderOptions
|
|
||||||
>(
|
|
||||||
queryLoader: (params: Record<string, string>) => PreloadedQuery<TQuery, TEnvironmentProviderOptions>
|
|
||||||
): LoaderFunction {
|
|
||||||
return ({ params }: LoaderFunctionArgs) => {
|
|
||||||
const query = queryLoader(params as Record<string, string>);
|
|
||||||
return {
|
|
||||||
queryRef: query,
|
|
||||||
dispose: query.dispose,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AppRoute = Omit<RouteObject, "children"> & {
|
|
||||||
children?: AppRoute[];
|
|
||||||
fallback?: ComponentType;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import { useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hook to handle cleanup after a delay
|
|
||||||
*
|
|
||||||
* Used for disposing the graphQL query when the component unmounts
|
|
||||||
*/
|
|
||||||
export function useCleanup(callback: () => void, delay: number) {
|
|
||||||
const timer = useRef<ReturnType<typeof setTimeout>>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (timer.current) {
|
|
||||||
clearTimeout(timer.current);
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
timer.current = setTimeout(callback, delay);
|
|
||||||
};
|
|
||||||
}, [callback, delay]);
|
|
||||||
}
|
|
||||||
@@ -3,3 +3,4 @@ export { useToggle } from "./useToggle";
|
|||||||
export { useRefSync } from "./useRefSync";
|
export { useRefSync } from "./useRefSync";
|
||||||
export { useList } from "./useList";
|
export { useList } from "./useList";
|
||||||
export { useStateWithRef } from "./useStateWithRef";
|
export { useStateWithRef } from "./useStateWithRef";
|
||||||
|
export { useCleanup } from "./useCleanup";
|
||||||
|
|||||||
Reference in New Issue
Block a user