buster/apps/web/src/layouts/AppAssetCheckLayout/useGetAsset.tsx

226 lines
6.0 KiB
TypeScript

'use client';
import { useSearchParams } from 'next/navigation';
import { useMemo } from 'react';
import { useGetCollection } from '@/api/buster_rest/collections';
import { useGetDashboard } from '@/api/buster_rest/dashboards';
import type { RustApiError } from '@/api/buster_rest/errors';
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
import type { AssetType } from '@buster/server-shared/assets';
import { useGetReport } from '@/api/buster_rest/reports';
interface BaseGetAssetProps {
assetId: string;
type: AssetType;
versionNumber?: number;
}
type UseGetAssetProps = BaseGetAssetProps;
interface AssetAccess {
hasAccess: boolean;
passwordRequired: boolean;
isPublic: boolean;
isDeleted: boolean;
}
interface AssetQueryResult {
isFetched: boolean;
error: RustApiError | null;
isError?: boolean;
showLoader?: boolean;
}
const getAssetAccess = (error: RustApiError | null): AssetAccess => {
if (!error) {
return { hasAccess: true, passwordRequired: false, isPublic: false, isDeleted: false };
}
if (error.status === 418) {
return { hasAccess: false, passwordRequired: true, isPublic: true, isDeleted: false };
}
if (error.status === 410) {
return { hasAccess: false, passwordRequired: false, isPublic: false, isDeleted: true };
}
return { hasAccess: false, passwordRequired: false, isPublic: false, isDeleted: false };
};
const useVersionNumber = (props: UseGetAssetProps) => {
const searchParams = useSearchParams();
const metricVersionNumber = searchParams.get('metric_version_number');
const dashboardVersionNumber = searchParams.get('dashboard_version_number');
return useMemo(() => {
if (props.versionNumber) return props.versionNumber;
const queryVersion =
props.type === 'metric'
? metricVersionNumber
: props.type === 'dashboard'
? dashboardVersionNumber
: null;
return queryVersion ? Number.parseInt(queryVersion) : undefined;
}, [props.type, props.versionNumber, metricVersionNumber, dashboardVersionNumber]);
};
export const useGetAsset = (
props: UseGetAssetProps
): {
isFetched: boolean;
error: RustApiError | null;
hasAccess: boolean;
passwordRequired: boolean;
isPublic: boolean;
showLoader: boolean | undefined;
title: string | undefined;
} => {
const versionNumber = useVersionNumber(props);
const isMetric = props.type === 'metric';
const isDashboard = props.type === 'dashboard';
const isCollection = props.type === 'collection';
const isReport = props.type === 'report';
// Always call hooks at the top level with appropriate enabled flags
const {
error: metricError,
isFetched: metricIsFetched,
data: metricTitle
} = useGetMetric(
{
id: isMetric ? props.assetId : undefined,
versionNumber
},
{
enabled: isMetric && props.assetId !== undefined,
select: (x) => x?.name,
staleTime: Infinity
}
);
const { isFetched: metricDataIsFetched } = useGetMetricData({
id: isMetric ? props.assetId : undefined,
versionNumber
});
const {
isFetched: dashboardIsFetched,
error: dashboardError,
isError: dashboardIsError,
data: dashboardTitle
} = useGetDashboard(
{
id: isDashboard ? props.assetId : undefined,
versionNumber
},
{ enabled: isDashboard, select: (x) => x?.dashboard?.name, staleTime: Infinity }
);
const {
isFetched: reportIsFetched,
error: reportError,
isError: reportIsError,
data: reportTitle
} = useGetReport(
{ reportId: isReport ? props.assetId : undefined, versionNumber },
{
select: (x) => x?.name
}
);
const {
isFetched: collectionIsFetched,
error: collectionError,
isError: collectionIsError,
data: collectionTitle
} = useGetCollection(isCollection ? props.assetId : undefined, {
select: (x) => x?.name
});
const currentQuery = useMemo((): AssetQueryResult => {
switch (props.type) {
case 'metric':
return {
isFetched: metricIsFetched,
error: metricError,
isError: !!metricError,
showLoader: !metricDataIsFetched && !metricError && !metricIsFetched
};
case 'dashboard':
return {
isFetched: dashboardIsFetched,
error: dashboardError,
isError: dashboardIsError,
showLoader: !dashboardIsFetched && !dashboardIsError
};
case 'collection':
return {
isFetched: collectionIsFetched,
error: collectionError,
isError: collectionIsError,
showLoader: !collectionIsFetched && !collectionIsError
};
case 'report':
return {
isFetched: reportIsFetched,
error: reportError,
isError: reportIsError,
showLoader: !reportIsFetched && !reportIsError
};
case 'chat':
// Chat type is not supported in this hook
return { isFetched: true, error: null, isError: false, showLoader: false };
default: {
const exhaustiveCheck: never = props.type;
return { isFetched: false, error: null, isError: false, showLoader: false };
}
}
}, [
props.type,
metricIsFetched,
metricError,
metricDataIsFetched,
dashboardIsFetched,
dashboardError,
dashboardIsError,
collectionIsFetched,
collectionError,
collectionIsError,
reportIsFetched,
reportError,
reportIsError
]);
const title = useMemo(() => {
if (isMetric) return metricTitle;
if (isDashboard) return dashboardTitle;
if (isCollection) return collectionTitle;
if (isReport) return reportTitle;
return undefined;
}, [
isMetric,
isDashboard,
isCollection,
isReport,
metricTitle,
dashboardTitle,
collectionTitle,
reportTitle
]);
const { hasAccess, passwordRequired, isPublic } = getAssetAccess(currentQuery.error);
return {
isFetched: currentQuery.isFetched,
error: currentQuery.error,
hasAccess,
passwordRequired,
isPublic,
showLoader: currentQuery.showLoader,
title
};
};