prefetch lists

This commit is contained in:
Nate Kelley 2025-09-04 22:00:01 -06:00
parent bb586fff44
commit 0cc0347786
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
12 changed files with 42 additions and 189 deletions

View File

@ -75,6 +75,16 @@ export const useGetListLogs = (
});
};
export const prefetchGetLogsList = async (
queryClient: QueryClient,
params?: Parameters<typeof getListLogs>[0]
) => {
await queryClient.prefetchQuery({
...chatQueryKeys.logsGetList(params),
queryFn: () => getListLogs(params),
});
};
const getChatQueryFn = (params: Parameters<typeof getChat>[0], queryClient: QueryClient) => {
return getChat(params).then((chat) => {
const { iChat, iChatMessages } = updateChatToIChat(chat);

View File

@ -43,8 +43,8 @@ export const useGetReportsList = (params?: Parameters<typeof getReportsList>[0])
* Prefetch function for reports list (server-side)
*/
export const prefetchGetReportsList = async (
params: Parameters<typeof getReportsList>[0],
queryClient: QueryClient
queryClient: QueryClient,
params?: Parameters<typeof getReportsList>[0]
) => {
await queryClient.prefetchQuery({
...reportsQueryKeys.reportsGetList(params),

View File

@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import { useMemo } from 'react';
import { useIsUserAdmin, useIsUserRegistered } from '@/api/buster_rest/users/useGetUserInfo';
import { BackButton } from '@/components/ui/buttons/BackButton';
import ApartmentBuilding from '@/components/ui/icons/NucleoIconOutlined/apartment-building';
@ -72,22 +72,22 @@ const permissionAndSecurityItems: ISidebarGroup = createSidebarGroup({
items: [
{
label: 'Security',
link: { to: '/app/settings/security', preload: false },
link: { to: '/app/settings/security' },
id: '/app/settings/security',
},
{
label: 'Users',
link: { to: '/app/settings/users', preload: false },
link: { to: '/app/settings/users' },
id: '/app/settings/users',
},
{
label: 'Dataset groups',
link: { to: '/app/settings/dataset-groups', preload: false },
link: { to: '/app/settings/dataset-groups' },
id: '/app/settings/dataset-groups',
},
{
label: 'Permission groups',
link: { to: '/app/settings/permission-groups', preload: false },
link: { to: '/app/settings/permission-groups' },
id: '/app/settings/permission-groups',
},
],

View File

@ -1,178 +0,0 @@
import { Link } from '@tanstack/react-router';
import React, { useCallback, useMemo, useRef } from 'react';
import { Button } from '@/components/ui/buttons';
import { History, Xmark } from '@/components/ui/icons';
import Check3 from '@/components/ui/icons/NucleoIconFilled/check-3';
import { AppPageLayout } from '@/components/ui/layouts/AppPageLayout';
import { CircleSpinnerLoader } from '@/components/ui/loaders';
import { AppTooltip } from '@/components/ui/tooltip';
import { Text } from '@/components/ui/typography';
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
import { useMount } from '@/hooks/useMount';
import { cn } from '@/lib/classMerge';
import { timeFromNow } from '@/lib/date';
import { timeout } from '@/lib/timeout';
export const VersionHistoryPanel = React.memo(
({ assetId, type }: { assetId: string; type: 'metric' | 'dashboard' }) => {
// const {
// listItems,
// onPrefetchAsset,
// restoringVersion,
// currentVersionNumber,
// selectedQueryVersion,
// onClickRestoreVersion,
// } = useListVersionHistories({
// assetId,
// type,
// });
type;
assetId;
const bodyRef = useRef<HTMLDivElement>(null);
useMount(async () => {
if (bodyRef.current) {
await timeout(250);
const selectedNode = bodyRef.current.querySelector('.selected-version');
if (selectedNode) {
selectedNode.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
});
return (
<AppPageLayout
className="min-w-[245px]"
header={useMemo(() => <PanelHeader />, [])}
scrollable
headerBorderVariant="ghost"
>
<div ref={bodyRef} className="mx-2 mb-1.5 flex flex-col">
TODO
{/* {listItems?.map((item) => (
<ListItem
key={item.version_number}
{...item}
onPrefetchAsset={onPrefetchAsset}
selected={item.version_number === selectedQueryVersion}
showRestoreButton={item.version_number !== currentVersionNumber}
onClickRestoreVersion={onClickRestoreVersion}
restoringVersion={restoringVersion}
link={
getFileLink({
fileId: assetId,
fileType: type,
chatId,
versionNumber: item.version_number,
useVersionHistoryMode: true,
}) || ''
}
/>
))} */}
</div>
</AppPageLayout>
);
}
);
// const ListItem = React.memo(
// ({
// version_number,
// updated_at,
// selected,
// showRestoreButton,
// link,
// restoringVersion,
// onClickRestoreVersion,
// onPrefetchAsset,
// }: {
// version_number: number;
// updated_at: string;
// selected: boolean;
// showRestoreButton: boolean;
// restoringVersion: number | null;
// onClickRestoreVersion: (versionNumber: number) => void;
// onPrefetchAsset: (versionNumber: number, link: string) => Promise<void>;
// link: string;
// }) => {
// const routePrefetchTimeoutRef = useRef<NodeJS.Timeout>(null);
// const onHoverLink = useMemoizedFn(() => {
// // Prefetch route after 50ms
// routePrefetchTimeoutRef.current = setTimeout(() => {
// onPrefetchAsset(version_number, link);
// }, 125);
// });
// const onHoverEnd = useCallback(() => {
// if (routePrefetchTimeoutRef.current) {
// clearTimeout(routePrefetchTimeoutRef.current);
// }
// }, []);
// const isRestoringVersion = restoringVersion === version_number;
// return (
// <Link prefetch={false} href={link} onMouseEnter={onHoverLink} onMouseLeave={onHoverEnd}>
// <div
// className={cn(
// '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'
// )}
// >
// <div className="flex flex-col justify-center space-y-0.5">
// <Text>{`Version ${version_number}`}</Text>
// <Text size={'xs'} variant={'secondary'}>
// {timeFromNow(updated_at, false)}
// </Text>
// </div>
// <div className="text-icon-color animate-in fade-in-0 flex items-center space-x-2 duration-200">
// {showRestoreButton && (
// <AppTooltip title={restoringVersion ? 'Restoring...' : 'Restore version'}>
// <button
// type="button"
// onClick={(e) => {
// if (restoringVersion) return;
// e.stopPropagation();
// e.preventDefault();
// onClickRestoreVersion(version_number);
// }}
// className={cn(
// 'hover:bg-gray-light/20 hover:text-foreground -mr-1 cursor-pointer rounded p-1 opacity-0 group-hover:block group-hover:opacity-100',
// isRestoringVersion && 'cursor-not-allowed opacity-100!'
// )}
// >
// {isRestoringVersion ? <CircleSpinnerLoader size={12} /> : <History />}
// </button>
// </AppTooltip>
// )}
// {selected && (
// <div className="group-hover:opacity-100">
// <Check3 />
// </div>
// )}
// </div>
// </div>
// </Link>
// );
// }
// );
// ListItem.displayName = 'ListItem';
const PanelHeader = React.memo(() => {
return (
<div className="flex w-full items-center justify-between">
<Text>Version history</Text>
{/* <Link href={href} className="-mr-1.5">
<Button variant="ghost" prefix={<Xmark />} />
</Link> */}
</div>
);
});
PanelHeader.displayName = 'PanelHeader';
VersionHistoryPanel.displayName = 'VersionHistoryPanel';

View File

@ -11,7 +11,4 @@ export const QueryPersister = ({
queryClient: QueryClient;
}) => {
return children;
// </TanstackPersistQueryClientProvider>
// );
};

View File

@ -1,4 +1,4 @@
export const PREFETCH_STALE_TIME = 1000 * 60 * 1; // 1 minutes
export const PREFETCH_STALE_TIME = 1000 * 60 * 1.5; // 1.5 minutes
export const ERROR_RETRY_DELAY = 1 * 1000; // 1 second delay after error
export const GC_TIME = 1000 * 60 * 5; // 5 minutes - matches new persistence duration
export const USER_CANCELLED_ERROR = new Error('User cancelled');

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetChatsList } from '@/api/buster_rest/chats';
import { AppPageLayout } from '@/components/ui/layouts/AppPageLayout';
import { ChatListContainer } from '@/controllers/ChatsListController/ChatListController';
import { ChatListHeader } from '@/controllers/ChatsListController/ChatListHeader';
@ -12,6 +13,9 @@ export const Route = createFileRoute('/app/_app/chats/')({
{ name: 'og:description', content: 'Browse and manage your chat conversations' },
],
}),
loader: async ({ context }) => {
prefetchGetChatsList(context.queryClient); //do not wait
},
component: RouteComponent,
});

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetCollectionsList } from '@/api/buster_rest/collections';
import { CollectionListController } from '@/controllers/CollectionListController';
export const Route = createFileRoute('/app/_app/collections/')({
@ -10,5 +11,8 @@ export const Route = createFileRoute('/app/_app/collections/')({
{ name: 'og:description', content: 'Browse and organize your collections' },
],
}),
loader: async ({ context }) => {
prefetchGetCollectionsList(context.queryClient); //do not wait
},
component: CollectionListController,
});

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetDashboardsList } from '@/api/buster_rest/dashboards';
import { DashboardListController } from '@/controllers/DashboardListController';
export const Route = createFileRoute('/app/_app/dashboards/')({
@ -10,5 +11,8 @@ export const Route = createFileRoute('/app/_app/dashboards/')({
{ name: 'og:description', content: 'View and manage your data dashboards' },
],
}),
loader: async ({ context }) => {
prefetchGetDashboardsList(context.queryClient); //do not wait
},
component: DashboardListController,
});

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetLogsList } from '@/api/buster_rest/chats';
import { AppPageLayout } from '@/components/ui/layouts/AppPageLayout';
import { ChatListContainer } from '@/controllers/ChatsListController/ChatListController';
import { ChatListHeader } from '@/controllers/ChatsListController/ChatListHeader';
@ -13,6 +14,9 @@ export const Route = createFileRoute('/app/_app/logs/')({
],
}),
component: RouteComponent,
loader: async ({ context }) => {
prefetchGetLogsList(context.queryClient); //do not wait
},
});
const type = 'logs';

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetMetricsList } from '@/api/buster_rest/metrics';
import { MetricListContainer } from '@/controllers/MetricListContainer';
export const Route = createFileRoute('/app/_app/metrics/')({
@ -11,4 +12,7 @@ export const Route = createFileRoute('/app/_app/metrics/')({
],
}),
component: MetricListContainer,
loader: async ({ context }) => {
prefetchGetMetricsList(context.queryClient); //do not wait
},
});

View File

@ -1,4 +1,5 @@
import { createFileRoute } from '@tanstack/react-router';
import { prefetchGetReportsList } from '@/api/buster_rest/reports';
import { AppPageLayout } from '@/components/ui/layouts/AppPageLayout';
import { Text } from '@/components/ui/typography/Text';
import { ReportsListController } from '@/controllers/ReportsListController';
@ -12,6 +13,9 @@ export const Route = createFileRoute('/app/_app/reports/')({
{ name: 'og:description', content: 'Generate and view your reports' },
],
}),
loader: async ({ context }) => {
prefetchGetReportsList(context.queryClient); //do not wait
},
component: () => (
<AppPageLayout headerSizeVariant="list" header={<Text>Reports</Text>}>
<ReportsListController />