mirror of https://github.com/buster-so/buster.git
prefetcher for version history panel
This commit is contained in:
parent
441ec1df40
commit
73768eebc9
|
@ -118,6 +118,30 @@ export const useGetMetric = <TData = IBusterMetric>(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const prefetchGetMetricClient = async (
|
||||||
|
{ id, versionNumber }: { id: string; versionNumber: number | undefined },
|
||||||
|
queryClient: QueryClient
|
||||||
|
) => {
|
||||||
|
const options = metricsQueryKeys.metricsGetMetric(id, versionNumber);
|
||||||
|
const existingData = queryClient.getQueryData(options.queryKey);
|
||||||
|
if (!existingData) {
|
||||||
|
await queryClient.prefetchQuery({
|
||||||
|
...options,
|
||||||
|
queryFn: async () => {
|
||||||
|
const result = await getMetric({ id, version_number: versionNumber });
|
||||||
|
return upgradeMetricToIMetric(result, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePrefetchGetMetricClient = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMemoizedFn(({ id, versionNumber }: { id: string; versionNumber: number | undefined }) =>
|
||||||
|
prefetchGetMetricClient({ id, versionNumber }, queryClient)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetMetricsList = (
|
export const useGetMetricsList = (
|
||||||
params: Omit<Parameters<typeof listMetrics>[0], 'page_token' | 'page_size'>
|
params: Omit<Parameters<typeof listMetrics>[0], 'page_token' | 'page_size'>
|
||||||
) => {
|
) => {
|
||||||
|
@ -206,6 +230,13 @@ export const prefetchGetMetricDataClient = async (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const usePrefetchGetMetricDataClient = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMemoizedFn(({ id, versionNumber }: { id: string; versionNumber: number | undefined }) =>
|
||||||
|
prefetchGetMetricDataClient({ id, version_number: versionNumber }, queryClient)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a mutation that saves a metric to the server.
|
* This is a mutation that saves a metric to the server.
|
||||||
* It will simply use the params passed in and not do any special logic.
|
* It will simply use the params passed in and not do any special logic.
|
||||||
|
|
|
@ -8,17 +8,24 @@ import { cn } from '@/lib/classMerge';
|
||||||
import { timeFromNow, timeout } from '@/lib';
|
import { timeFromNow, timeout } from '@/lib';
|
||||||
import { AppPageLayout } from '@/components/ui/layouts';
|
import { AppPageLayout } from '@/components/ui/layouts';
|
||||||
import { useListVersionHistories } from './useListVersionHistories';
|
import { useListVersionHistories } from './useListVersionHistories';
|
||||||
import { useMount } from '@/hooks';
|
import { useMemoizedFn, useMount } from '@/hooks';
|
||||||
import { AppTooltip } from '@/components/ui/tooltip';
|
import { AppTooltip } from '@/components/ui/tooltip';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useGetFileLink } from '@/context/Assets/useGetFileLink';
|
import { useGetFileLink } from '@/context/Assets/useGetFileLink';
|
||||||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
export const VersionHistoryPanel = React.memo(
|
export const VersionHistoryPanel = React.memo(
|
||||||
({ assetId, type }: { assetId: string; type: 'metric' | 'dashboard' }) => {
|
({ assetId, type }: { assetId: string; type: 'metric' | 'dashboard' }) => {
|
||||||
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
||||||
const { listItems, currentVersionNumber, selectedQueryVersion, onClickRestoreVersion } =
|
const {
|
||||||
useListVersionHistories({
|
listItems,
|
||||||
|
onPrefetchAsset,
|
||||||
|
currentVersionNumber,
|
||||||
|
selectedQueryVersion,
|
||||||
|
onClickRestoreVersion
|
||||||
|
} = useListVersionHistories({
|
||||||
assetId,
|
assetId,
|
||||||
type
|
type
|
||||||
});
|
});
|
||||||
|
@ -51,6 +58,7 @@ export const VersionHistoryPanel = React.memo(
|
||||||
<ListItem
|
<ListItem
|
||||||
key={item.version_number}
|
key={item.version_number}
|
||||||
{...item}
|
{...item}
|
||||||
|
onPrefetchAsset={onPrefetchAsset}
|
||||||
selected={item.version_number === selectedQueryVersion}
|
selected={item.version_number === selectedQueryVersion}
|
||||||
showRestoreButton={item.version_number !== currentVersionNumber}
|
showRestoreButton={item.version_number !== currentVersionNumber}
|
||||||
onClickRestoreVersion={onClickRestoreVersion}
|
onClickRestoreVersion={onClickRestoreVersion}
|
||||||
|
@ -78,18 +86,37 @@ const ListItem = React.memo(
|
||||||
selected,
|
selected,
|
||||||
showRestoreButton,
|
showRestoreButton,
|
||||||
link,
|
link,
|
||||||
onClickRestoreVersion
|
onClickRestoreVersion,
|
||||||
|
onPrefetchAsset
|
||||||
}: {
|
}: {
|
||||||
version_number: number;
|
version_number: number;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
showRestoreButton: boolean;
|
showRestoreButton: boolean;
|
||||||
onClickRestoreVersion: (versionNumber: number) => void;
|
onClickRestoreVersion: (versionNumber: number) => void;
|
||||||
|
onPrefetchAsset: (versionNumber: number, link: string) => Promise<void>;
|
||||||
link: string;
|
link: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const routePrefetchTimeoutRef = useRef<NodeJS.Timeout>();
|
||||||
|
|
||||||
|
const onHoverLink = useMemoizedFn(() => {
|
||||||
|
// Prefetch route after 50ms
|
||||||
|
routePrefetchTimeoutRef.current = setTimeout(() => {
|
||||||
|
onPrefetchAsset(version_number, link);
|
||||||
|
}, 125);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onHoverEnd = useCallback(() => {
|
||||||
|
if (routePrefetchTimeoutRef.current) {
|
||||||
|
clearTimeout(routePrefetchTimeoutRef.current);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link prefetch={false} href={link}>
|
<Link prefetch={false} href={link}>
|
||||||
<div
|
<div
|
||||||
|
onMouseEnter={onHoverLink}
|
||||||
|
onMouseLeave={onHoverEnd}
|
||||||
className={cn(
|
className={cn(
|
||||||
'group hover:bg-item-hover flex cursor-pointer items-center justify-between space-x-2 rounded px-2.5 py-1.5',
|
'group hover:bg-item-hover flex cursor-pointer items-center justify-between space-x-2 rounded px-2.5 py-1.5',
|
||||||
selected && 'bg-item-select hover:bg-item-select selected-version'
|
selected && 'bg-item-select hover:bg-item-select selected-version'
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards';
|
import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards';
|
||||||
import { useGetMetric, useSaveMetric } from '@/api/buster_rest/metrics';
|
import {
|
||||||
|
useGetMetric,
|
||||||
|
usePrefetchGetMetricDataClient,
|
||||||
|
useSaveMetric
|
||||||
|
} from '@/api/buster_rest/metrics';
|
||||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||||
|
@ -9,6 +13,8 @@ import { useCloseVersionHistory } from '@/layouts/ChatLayout/FileContainer/FileC
|
||||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||||
import last from 'lodash/last';
|
import last from 'lodash/last';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { usePrefetchGetMetricClient } from '@/api/buster_rest/metrics';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
export const useListVersionHistories = ({
|
export const useListVersionHistories = ({
|
||||||
assetId,
|
assetId,
|
||||||
|
@ -17,24 +23,27 @@ export const useListVersionHistories = ({
|
||||||
assetId: string;
|
assetId: string;
|
||||||
type: 'metric' | 'dashboard';
|
type: 'metric' | 'dashboard';
|
||||||
}) => {
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
const { onCloseVersionHistory } = useCloseVersionHistory();
|
const { onCloseVersionHistory } = useCloseVersionHistory();
|
||||||
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
||||||
const {
|
const {
|
||||||
dashboardVersions,
|
versions: dashboardVersions,
|
||||||
selectedQueryVersion: dashboardSelectedQueryVersion,
|
selectedQueryVersion: dashboardSelectedQueryVersion,
|
||||||
currentVersionNumber: dashboardCurrentVersionNumber,
|
currentVersionNumber: dashboardCurrentVersionNumber,
|
||||||
onRestoreVersion: onRestoreDashboardVersion,
|
onRestoreVersion: onRestoreDashboardVersion,
|
||||||
isSavingDashboard
|
isSaving: isSavingDashboard,
|
||||||
|
onPrefetchAsset: onPrefetchDashboardAsset
|
||||||
} = useListDashboardVersions({
|
} = useListDashboardVersions({
|
||||||
assetId,
|
assetId,
|
||||||
type
|
type
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
metricVersions,
|
versions: metricVersions,
|
||||||
selectedQueryVersion: metricSelectedQueryVersion,
|
selectedQueryVersion: metricSelectedQueryVersion,
|
||||||
currentVersionNumber: metricCurrentVersionNumber,
|
currentVersionNumber: metricCurrentVersionNumber,
|
||||||
onRestoreVersion: onRestoreMetricVersion,
|
onRestoreVersion: onRestoreMetricVersion,
|
||||||
isSavingMetric
|
isSaving: isSavingMetric,
|
||||||
|
onPrefetchAsset: onPrefetchMetricAsset
|
||||||
} = useListMetricVersions({
|
} = useListMetricVersions({
|
||||||
assetId,
|
assetId,
|
||||||
type
|
type
|
||||||
|
@ -82,13 +91,24 @@ export const useListVersionHistories = ({
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onPrefetchAsset = useMemoizedFn(async (versionNumber: number, link: string) => {
|
||||||
|
router.prefetch(link);
|
||||||
|
|
||||||
|
if (type === 'metric') {
|
||||||
|
await onPrefetchMetricAsset(versionNumber);
|
||||||
|
} else {
|
||||||
|
await onPrefetchDashboardAsset(versionNumber);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
return {
|
||||||
listItems,
|
listItems,
|
||||||
currentVersionNumber,
|
currentVersionNumber,
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
onClickRestoreVersion,
|
onClickRestoreVersion,
|
||||||
isRestoringVersion: isSavingDashboard || isSavingMetric
|
isRestoringVersion: isSavingDashboard || isSavingMetric,
|
||||||
|
onPrefetchAsset
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
listItems,
|
listItems,
|
||||||
|
@ -96,19 +116,34 @@ export const useListVersionHistories = ({
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
onClickRestoreVersion,
|
onClickRestoreVersion,
|
||||||
isSavingDashboard,
|
isSavingDashboard,
|
||||||
isSavingMetric
|
isSavingMetric,
|
||||||
|
onPrefetchAsset
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type UseListVersionReturn = {
|
||||||
|
versions:
|
||||||
|
| {
|
||||||
|
version_number: number;
|
||||||
|
updated_at: string;
|
||||||
|
}[]
|
||||||
|
| undefined;
|
||||||
|
selectedQueryVersion: number | undefined;
|
||||||
|
onRestoreVersion: (versionNumber: number) => Promise<unknown>;
|
||||||
|
currentVersionNumber: number | undefined;
|
||||||
|
isSaving: boolean;
|
||||||
|
onPrefetchAsset: (versionNumber: number) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
const useListDashboardVersions = ({
|
const useListDashboardVersions = ({
|
||||||
assetId,
|
assetId,
|
||||||
type
|
type
|
||||||
}: {
|
}: {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
type: 'metric' | 'dashboard';
|
type: 'metric' | 'dashboard';
|
||||||
}) => {
|
}): UseListVersionReturn => {
|
||||||
const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber);
|
const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber);
|
||||||
const { mutateAsync: updateDashboard, isPending: isSavingDashboard } = useUpdateDashboard({
|
const { mutateAsync: updateDashboard, isPending: isSaving } = useUpdateDashboard({
|
||||||
saveToServer: true,
|
saveToServer: true,
|
||||||
updateVersion: true
|
updateVersion: true
|
||||||
});
|
});
|
||||||
|
@ -125,13 +160,13 @@ const useListDashboardVersions = ({
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const dashboardVersions = dashboardData?.versions;
|
const versions = dashboardData?.versions;
|
||||||
const currentVersionNumber = dashboardData?.version_number;
|
const currentVersionNumber = dashboardData?.version_number;
|
||||||
|
|
||||||
const selectedQueryVersion = useMemo(() => {
|
const selectedQueryVersion = useMemo(() => {
|
||||||
if (dashboardVersionNumber) return dashboardVersionNumber;
|
if (dashboardVersionNumber) return dashboardVersionNumber;
|
||||||
return last(dashboardVersions)?.version_number;
|
return last(versions)?.version_number;
|
||||||
}, [dashboardVersions, dashboardVersionNumber]);
|
}, [versions, dashboardVersionNumber]);
|
||||||
|
|
||||||
const onRestoreVersion = useMemoizedFn(async (versionNumber: number) => {
|
const onRestoreVersion = useMemoizedFn(async (versionNumber: number) => {
|
||||||
await updateDashboard({
|
await updateDashboard({
|
||||||
|
@ -140,20 +175,26 @@ const useListDashboardVersions = ({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onPrefetchAsset = useMemoizedFn(async (versionNumber: number) => {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
return {
|
||||||
dashboardVersions,
|
versions,
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
onRestoreVersion,
|
onRestoreVersion,
|
||||||
currentVersionNumber,
|
currentVersionNumber,
|
||||||
isSavingDashboard
|
isSaving,
|
||||||
|
onPrefetchAsset
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
dashboardVersions,
|
versions,
|
||||||
currentVersionNumber,
|
currentVersionNumber,
|
||||||
onRestoreVersion,
|
onRestoreVersion,
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
isSavingDashboard
|
isSaving,
|
||||||
|
onPrefetchAsset
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,10 +204,12 @@ const useListMetricVersions = ({
|
||||||
}: {
|
}: {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
type: 'metric' | 'dashboard';
|
type: 'metric' | 'dashboard';
|
||||||
}) => {
|
}): UseListVersionReturn => {
|
||||||
const { mutateAsync: updateMetric, isPending: isSavingMetric } = useSaveMetric({
|
const { mutateAsync: updateMetric, isPending: isSaving } = useSaveMetric({
|
||||||
updateOnSave: true
|
updateOnSave: true
|
||||||
});
|
});
|
||||||
|
const prefetchGetMetric = usePrefetchGetMetricClient();
|
||||||
|
const prefetchGetMetricData = usePrefetchGetMetricDataClient();
|
||||||
|
|
||||||
const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber);
|
const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber);
|
||||||
|
|
||||||
|
@ -181,9 +224,14 @@ const useListMetricVersions = ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const metricVersions = metric?.versions;
|
const versions = metric?.versions;
|
||||||
const currentVersionNumber = metricVersionNumber || metric?.version_number;
|
const currentVersionNumber = metricVersionNumber || metric?.version_number;
|
||||||
|
|
||||||
|
const selectedQueryVersion = useMemo(() => {
|
||||||
|
if (metricVersionNumber) return metricVersionNumber;
|
||||||
|
return last(versions)?.version_number;
|
||||||
|
}, [versions, metricVersionNumber]);
|
||||||
|
|
||||||
const onRestoreVersion = useMemoizedFn(async (versionNumber: number) => {
|
const onRestoreVersion = useMemoizedFn(async (versionNumber: number) => {
|
||||||
await updateMetric({
|
await updateMetric({
|
||||||
id: assetId,
|
id: assetId,
|
||||||
|
@ -191,24 +239,28 @@ const useListMetricVersions = ({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedQueryVersion = useMemo(() => {
|
const onPrefetchAsset = useMemoizedFn(async (versionNumber: number) => {
|
||||||
if (metricVersionNumber) return metricVersionNumber;
|
await Promise.all([
|
||||||
return last(metricVersions)?.version_number;
|
prefetchGetMetric({ id: assetId, versionNumber }),
|
||||||
}, [metricVersions, metricVersionNumber]);
|
prefetchGetMetricData({ id: assetId, versionNumber })
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
return {
|
||||||
metricVersions,
|
versions,
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
onRestoreVersion,
|
onRestoreVersion,
|
||||||
currentVersionNumber,
|
currentVersionNumber,
|
||||||
isSavingMetric
|
isSaving,
|
||||||
|
onPrefetchAsset
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
metricVersions,
|
versions,
|
||||||
|
currentVersionNumber,
|
||||||
onRestoreVersion,
|
onRestoreVersion,
|
||||||
selectedQueryVersion,
|
selectedQueryVersion,
|
||||||
currentVersionNumber,
|
isSaving,
|
||||||
isSavingMetric
|
onPrefetchAsset
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue