memo pass through

This commit is contained in:
Nate Kelley 2025-08-19 12:19:59 -06:00
parent ec07753e26
commit cdaa436465
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
9 changed files with 60 additions and 53 deletions

View File

@ -1,19 +1,6 @@
import {
useChildMatches,
useLinkProps,
useLocation,
useMatch,
useMatchRoute,
useParams,
useParentMatches,
useSearch,
useStableCallback,
} from '@tanstack/react-router';
import { MetricViewChart } from '@/controllers/MetricController/MetricViewChart'; import { MetricViewChart } from '@/controllers/MetricController/MetricViewChart';
import { useGetMetricParams } from './useGetMetricParams'; import { useGetMetricParams } from './useGetMetricParams';
//const Route = getRouteApi('/app/_app/_asset/metrics/$metricId');
export const component = () => { export const component = () => {
const { metricId, metric_version_number } = useGetMetricParams(); const { metricId, metric_version_number } = useGetMetricParams();

View File

@ -3,7 +3,9 @@ import type { QueryClient } from '@tanstack/react-query';
import { Outlet, redirect } from '@tanstack/react-router'; import { Outlet, redirect } from '@tanstack/react-router';
import { z } from 'zod'; import { z } from 'zod';
import { prefetchGetMetric } from '@/api/buster_rest/metrics'; import { prefetchGetMetric } from '@/api/buster_rest/metrics';
import { MetricAssetContainer } from '@/layouts/AssetContainer/MetricAssetContainer';
import type { FileRouteTypes } from '@/routeTree.gen'; import type { FileRouteTypes } from '@/routeTree.gen';
import { useGetMetricParams } from './useGetMetricParams';
export const validateSearch = z.object({ export const validateSearch = z.object({
metric_version_number: z.coerce.number().optional(), metric_version_number: z.coerce.number().optional(),
@ -69,5 +71,10 @@ export const head = ({ loaderData }: { loaderData?: { title: string | undefined
}); });
export const component = () => { export const component = () => {
return <Outlet />; const params = useGetMetricParams();
return (
<MetricAssetContainer {...params}>
<Outlet />
</MetricAssetContainer>
);
}; };

View File

@ -1,48 +1,52 @@
import type { AssetType } from '@buster/server-shared/assets'; import type { AssetType } from '@buster/server-shared/assets';
import type { ShareAssetType } from '@buster/server-shared/share'; import { useParams, useSearch } from '@tanstack/react-router';
import type React from 'react'; import type React from 'react';
import { useMemo } from 'react';
import { FileIndeterminateLoader } from '@/components/features/loaders/FileIndeterminateLoader'; import { FileIndeterminateLoader } from '@/components/features/loaders/FileIndeterminateLoader';
import { AppNoPageAccess } from '@/controllers/AppNoPageAccess'; import { AppNoPageAccess } from '@/controllers/AppNoPageAccess';
import { AppPasswordAccess } from '@/controllers/AppPasswordAccess'; import { AppPasswordAccess } from '@/controllers/AppPasswordAccess';
import { useShowLoader } from '../../context/BusterAssets/useShowLoader'; import { getAssetIdAndVersionNumber } from './getAssetIdAndVersionNumberServer';
import { useGetAssetPasswordConfig } from './useGetAssetPasswordConfig';
import { useShowLoader } from './useShowLoader';
export type AppAssetCheckLayoutProps = { export type AppAssetCheckLayoutProps = {
assetId: string; assetType: AssetType;
type: AssetType;
versionNumber: undefined | number;
passwordRequired: boolean;
isPublic: boolean;
hasAccess: boolean;
}; };
export const AppAssetCheckLayout: React.FC< export const AppAssetCheckLayout: React.FC<
{ {
children: React.ReactNode; children: React.ReactNode;
} & AppAssetCheckLayoutProps } & AppAssetCheckLayoutProps
> = ({ children, assetId, type, versionNumber, passwordRequired, isPublic, hasAccess }) => { > = ({ children, assetType }) => {
const showLoader = useShowLoader(assetId, type, versionNumber); const params = useParams({ strict: false });
const search = useSearch({ strict: false });
const Component = useMemo(() => { const { assetId, versionNumber } = getAssetIdAndVersionNumber(assetType, params, search);
if (!hasAccess && !isPublic) {
return <AppNoPageAccess assetId={assetId} type={type} />;
}
if (isPublic && passwordRequired) { const { hasAccess, isPublic, passwordRequired } = useGetAssetPasswordConfig(
return ( assetId,
<AppPasswordAccess assetId={assetId} type={type}> assetType,
{children} versionNumber
</AppPasswordAccess> );
);
}
return <>{children}</>; const showLoader = useShowLoader(assetId, assetType, versionNumber);
}, [hasAccess, isPublic, passwordRequired, assetId, type, children]);
let content: React.ReactNode;
if (!hasAccess && !isPublic) {
content = <AppNoPageAccess assetId={assetId} type={assetType} />;
} else if (isPublic && passwordRequired) {
content = (
<AppPasswordAccess assetId={assetId} type={assetType}>
{children}
</AppPasswordAccess>
);
} else {
content = children;
}
return ( return (
<> <>
{showLoader && <FileIndeterminateLoader />} {showLoader && <FileIndeterminateLoader />}
{Component} {content}
</> </>
); );
}; };

View File

@ -0,0 +1,7 @@
import type React from 'react';
export const AssetContainer: React.FC<{
children: React.ReactNode;
}> = ({ children }) => {
return <div className="bg-red-100">{children}</div>;
};

View File

@ -0,0 +1,13 @@
import { AssetContainer } from './AssetContainer';
export const MetricAssetContainer: React.FC<{
children: React.ReactNode;
metricId: string;
metric_version_number: number | undefined;
}> = ({ children, metricId, metric_version_number }) => {
return (
<AssetContainer>
METRIC {children} {metricId} {metric_version_number}
</AssetContainer>
);
};

View File

@ -7,9 +7,9 @@ import {
useSearch, useSearch,
} from '@tanstack/react-router'; } from '@tanstack/react-router';
import { getTitle as getAssetTitle } from '@/api/buster_rest/title'; import { getTitle as getAssetTitle } from '@/api/buster_rest/title';
import { getAssetIdAndVersionNumber } from '@/context/BusterAssets/getAssetIdAndVersionNumberServer';
import { useGetAssetPasswordConfig } from '@/context/BusterAssets/useGetAssetPasswordConfig';
import { AppAssetCheckLayout, type AppAssetCheckLayoutProps } from '@/layouts/AppAssetCheckLayout'; import { AppAssetCheckLayout, type AppAssetCheckLayoutProps } from '@/layouts/AppAssetCheckLayout';
import { getAssetIdAndVersionNumber } from '@/layouts/AppAssetCheckLayout/getAssetIdAndVersionNumberServer';
import { useGetAssetPasswordConfig } from '@/layouts/AppAssetCheckLayout/useGetAssetPasswordConfig';
export const Route = createFileRoute('/app/_app/_asset')({ export const Route = createFileRoute('/app/_app/_asset')({
component: RouteComponent, component: RouteComponent,
@ -27,20 +27,9 @@ export const Route = createFileRoute('/app/_app/_asset')({
const stableCtxSelector = (ctx: RouteContext) => ctx.assetType; const stableCtxSelector = (ctx: RouteContext) => ctx.assetType;
function RouteComponent() { function RouteComponent() {
const assetType = Route.useRouteContext({ select: stableCtxSelector }) || 'metric'; const assetType = Route.useRouteContext({ select: stableCtxSelector }) || 'metric';
const params = useParams({ strict: false });
const search = useSearch({ strict: false });
const { assetId, versionNumber } = getAssetIdAndVersionNumber(assetType, params, search);
const passwordConfig = useGetAssetPasswordConfig(assetId, assetType, versionNumber);
const containerParams: AppAssetCheckLayoutProps = {
assetId,
type: assetType,
versionNumber,
...passwordConfig,
};
return ( return (
<AppAssetCheckLayout {...containerParams}> <AppAssetCheckLayout assetType={assetType}>
<Outlet /> <Outlet />
</AppAssetCheckLayout> </AppAssetCheckLayout>
); );