mirror of https://github.com/buster-so/buster.git
link options update
This commit is contained in:
parent
9c09a22c74
commit
26108e8029
|
@ -49,22 +49,21 @@ const topItems: ISidebarList = {
|
||||||
{
|
{
|
||||||
label: 'Home',
|
label: 'Home',
|
||||||
icon: <House4 />,
|
icon: <House4 />,
|
||||||
route: { to: '/app/home' },
|
route: { to: '/app/home', preload: 'viewport', preloadDelay: 1000 },
|
||||||
id: '/app/home',
|
id: '/app/home',
|
||||||
preload: 'viewport',
|
|
||||||
preloadDelay: 1000,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Chat history',
|
label: 'Chat history',
|
||||||
icon: <ASSET_ICONS.chats />,
|
icon: <ASSET_ICONS.chats />,
|
||||||
route: { to: '/app/chats' },
|
route: {
|
||||||
id: '/app/chats/',
|
to: '/app/chats',
|
||||||
preload: 'viewport',
|
preload: 'viewport',
|
||||||
preloadDelay: 2000,
|
preloadDelay: 2000,
|
||||||
activeOptions: {
|
activeOptions: {
|
||||||
exact: true,
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
activeProps: {},
|
id: '/app/chats/',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -76,33 +75,26 @@ const yourStuff: ISidebarGroup = {
|
||||||
{
|
{
|
||||||
label: 'Metrics',
|
label: 'Metrics',
|
||||||
icon: <ASSET_ICONS.metrics />,
|
icon: <ASSET_ICONS.metrics />,
|
||||||
route: { to: '/app/metrics' },
|
route: { to: '/app/metrics', preload: 'intent', preloadDelay: 1000 },
|
||||||
id: '/app/metrics',
|
id: '/app/metrics',
|
||||||
preload: 'intent',
|
|
||||||
preloadDelay: 1000,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Dashboards',
|
label: 'Dashboards',
|
||||||
icon: <ASSET_ICONS.dashboards />,
|
icon: <ASSET_ICONS.dashboards />,
|
||||||
route: { to: '/app/dashboards' },
|
route: { to: '/app/dashboards', preload: 'intent', preloadDelay: 1000 },
|
||||||
id: '/app/dashboards/',
|
id: '/app/dashboards/',
|
||||||
preload: 'intent',
|
|
||||||
preloadDelay: 1000,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Collections',
|
label: 'Collections',
|
||||||
icon: <ASSET_ICONS.collections />,
|
icon: <ASSET_ICONS.collections />,
|
||||||
route: { to: '/app/collections' },
|
route: { to: '/app/collections', preload: 'intent', preloadDelay: 1000 },
|
||||||
id: '/app/collections/',
|
id: '/app/collections/',
|
||||||
preload: 'intent',
|
|
||||||
preloadDelay: 1000,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Reports',
|
label: 'Reports',
|
||||||
icon: <ASSET_ICONS.reports />,
|
icon: <ASSET_ICONS.reports />,
|
||||||
route: { to: '/app/reports' },
|
route: { to: '/app/reports', preload: 'intent', preloadDelay: 1000 },
|
||||||
id: '/app/reports/',
|
id: '/app/reports/',
|
||||||
preload: 'intent',
|
|
||||||
},
|
},
|
||||||
] satisfies (ISidebarItem & { show?: boolean })[],
|
] satisfies (ISidebarItem & { show?: boolean })[],
|
||||||
};
|
};
|
||||||
|
@ -114,10 +106,9 @@ const adminTools: ISidebarGroup = {
|
||||||
{
|
{
|
||||||
label: 'Logs',
|
label: 'Logs',
|
||||||
icon: <UnorderedList2 />,
|
icon: <UnorderedList2 />,
|
||||||
route: { to: '/app/logs' },
|
route: { to: '/app/logs', preload: 'viewport', preloadDelay: 1000 },
|
||||||
id: '/app/logs/',
|
id: '/app/logs/',
|
||||||
collapsedTooltip: 'Logs',
|
collapsedTooltip: 'Logs',
|
||||||
preload: 'viewport',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Datasets',
|
label: 'Datasets',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useMatchRoute } from '@tanstack/react-router';
|
import { type LinkProps, useMatchRoute } from '@tanstack/react-router';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
useDeleteUserFavorite,
|
useDeleteUserFavorite,
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import type { ActiveOptions, LinkProps } from '@tanstack/react-router';
|
import type {
|
||||||
|
ActiveOptions,
|
||||||
|
LinkProps,
|
||||||
|
RegisteredRouter,
|
||||||
|
ValidateLinkOptions,
|
||||||
|
} from '@tanstack/react-router';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import type { OptionsTo } from '@/types/routes';
|
import type { LinkOptionsTo, OptionsTo } from '@/types/routes';
|
||||||
|
|
||||||
// Base properties shared by all sidebar items
|
// Base properties shared by all sidebar items
|
||||||
type ISidebarItemBase = {
|
type ISidebarItemBase = {
|
||||||
|
@ -15,15 +20,13 @@ type ISidebarItemBase = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Discriminated union: either has a route (with optional activeOptions) or no route at all
|
// Discriminated union: either has a route (with optional activeOptions) or no route at all
|
||||||
export type ISidebarItem = ISidebarItemBase &
|
export type ISidebarItem<
|
||||||
|
TRouter extends RegisteredRouter = RegisteredRouter,
|
||||||
|
TOptions = unknown,
|
||||||
|
> = ISidebarItemBase &
|
||||||
(
|
(
|
||||||
| {
|
| {
|
||||||
route: OptionsTo;
|
route: LinkOptionsTo;
|
||||||
preload?: LinkProps['preload'];
|
|
||||||
preloadDelay?: LinkProps['preloadDelay'];
|
|
||||||
activeProps?: LinkProps['activeProps'];
|
|
||||||
preloadIntentProximity?: LinkProps['preloadIntentProximity'];
|
|
||||||
activeOptions?: ActiveOptions; // Only allowed when route is provided
|
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
route?: never;
|
route?: never;
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import type { AssetType } from '@buster/server-shared/assets';
|
import type { AssetType } from '@buster/server-shared/assets';
|
||||||
import type { QueryClient } from '@tanstack/react-query';
|
import type { QueryClient } from '@tanstack/react-query';
|
||||||
import {
|
import {
|
||||||
BeforeLoadContextOptions,
|
type AnyRoute,
|
||||||
|
type BeforeLoadContextOptions,
|
||||||
type BeforeLoadContextParameter,
|
type BeforeLoadContextParameter,
|
||||||
type BeforeLoadFn,
|
type BeforeLoadFn,
|
||||||
redirect,
|
redirect,
|
||||||
} from '@tanstack/react-router';
|
} 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 type { AppRouterContext } from '@/router';
|
||||||
import type { FileRouteTypes } from '@/routeTree.gen';
|
import type { FileRouteTypes } from '@/routeTree.gen';
|
||||||
|
|
||||||
export const validateSearch = z.object({
|
export const validateSearch = z.object({
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import type { AssetType } from '@buster/server-shared/assets';
|
|
||||||
import type { FileRouteTypes } from '@/routeTree.gen';
|
import type { FileRouteTypes } from '@/routeTree.gen';
|
||||||
import type { OptionsTo } from '@/types/routes';
|
import type { OptionsTo } from '@/types/routes';
|
||||||
|
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
import type { FileRouteTypes } from '@/routeTree.gen';
|
|
||||||
import type { OptionsTo, OptionsToBase } from '@/types/routes';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a type-safe route object that can be passed to testNavigate
|
|
||||||
* This function helps ensure that route creation is type-safe
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const route = createRoute({
|
|
||||||
* to: '/app/chats/$chatId',
|
|
||||||
* params: {
|
|
||||||
* chatId: '123'
|
|
||||||
* }
|
|
||||||
* });
|
|
||||||
* testNavigate(route);
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // Use it in a function to return type-safe navigation options
|
|
||||||
* const createMyRoute = () => {
|
|
||||||
* return createRoute({
|
|
||||||
* to: '/app/chats/$chatId',
|
|
||||||
* params: {
|
|
||||||
* chatId: '123'
|
|
||||||
* }
|
|
||||||
* });
|
|
||||||
* };
|
|
||||||
*/
|
|
||||||
export function createRoute(options: OptionsTo): OptionsTo {
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function to create route builders for specific routes
|
|
||||||
* This provides even more type safety by locking in the route path
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const createChatRoute = createRouteFactory('/app/chats/$chatId');
|
|
||||||
* const route = createChatRoute({ chatId: '123' });
|
|
||||||
*/
|
|
||||||
export function createRouteFactory<
|
|
||||||
TTo extends FileRouteTypes['to'],
|
|
||||||
TFrom extends FileRouteTypes['to'] = '/',
|
|
||||||
>(to: TTo) {
|
|
||||||
return (
|
|
||||||
params: OptionsToBase<TFrom, TTo> extends { params: infer P } ? P : never,
|
|
||||||
options?: Omit<OptionsToBase<TFrom, TTo>, 'to' | 'params'>
|
|
||||||
): OptionsTo<TFrom, TTo> => {
|
|
||||||
return {
|
|
||||||
to,
|
|
||||||
params,
|
|
||||||
...options,
|
|
||||||
} as OptionsTo<TFrom, TTo>;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import {
|
||||||
|
Link,
|
||||||
|
type LinkProps,
|
||||||
|
type RegisteredRouter,
|
||||||
|
type ValidateLinkOptions,
|
||||||
|
} from '@tanstack/react-router';
|
||||||
|
import type { OptionsTo } from '@/types/routes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a type-safe route object that can be passed to testNavigate
|
||||||
|
* This function helps ensure that route creation is type-safe
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const route = createRoute({
|
||||||
|
* to: '/app/chats/$chatId',
|
||||||
|
* params: {
|
||||||
|
* chatId: '123'
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* testNavigate(route);
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Use it in a function to return type-safe navigation options
|
||||||
|
* const createMyRoute = () => {
|
||||||
|
* return createRoute({
|
||||||
|
* to: '/app/chats/$chatId',
|
||||||
|
* params: {
|
||||||
|
* chatId: '123'
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
export function createRoute(options: OptionsTo): OptionsTo {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
//I am not super in love with this one. Tanstack has it in their docs..,
|
||||||
|
export function createLinkOptions<TOptions>(
|
||||||
|
options: ValidateLinkOptions<RegisteredRouter, TOptions>
|
||||||
|
) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// function createLinkOptions<TOptions>(options: ValidateLinkOptions<RegisteredRouter, TOptions>) {
|
||||||
|
// return options;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function createLinkProps(options: LinkProps) {
|
||||||
|
// return options;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// createRoute({
|
||||||
|
// to: '/app/chats/$chatId',
|
||||||
|
// params: { chatId: '123', reportId: '456' },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// createLinkOptions({
|
||||||
|
// to: '/app/chats/$chatId',
|
||||||
|
// params: { chatId: '123', reportId: '456' },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// createLinkProps({
|
||||||
|
// to: '/app/chats/$chatId',
|
||||||
|
// params: { reporhtId: '456' },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const TestComponent = () => {
|
||||||
|
// return (
|
||||||
|
// <Link to="/app/chats/$chatId" params={{ chatId: '123', reportId: '456' }}>
|
||||||
|
// <div>
|
||||||
|
// <h1>Test</h1>
|
||||||
|
// </div>
|
||||||
|
// </Link>
|
||||||
|
// );
|
||||||
|
// };
|
|
@ -1,5 +1,5 @@
|
||||||
import type { FileRouteTypes } from '@/routeTree.gen';
|
import type { FileRouteTypes } from '@/routeTree.gen';
|
||||||
import type { OptionsTo, OptionsToBase } from '@/types/routes';
|
import type { OptionsToBase } from '@/types/routes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts navigation options to a URL string (href)
|
* Converts navigation options to a URL string (href)
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import type { NavigateOptions, RegisteredRouter } from '@tanstack/react-router';
|
import type {
|
||||||
|
LinkOptions,
|
||||||
|
LinkProps,
|
||||||
|
NavigateOptions,
|
||||||
|
RegisteredRouter,
|
||||||
|
} from '@tanstack/react-router';
|
||||||
import type { FileRouteTypes } from '@/routeTree.gen';
|
import type { FileRouteTypes } from '@/routeTree.gen';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,3 +46,17 @@ export type OptionsTo<
|
||||||
: { params?: never }) &
|
: { params?: never }) &
|
||||||
Omit<OptionsToBase<TFrom, K, TMaskFrom, TMaskTo>, 'to' | 'params'>;
|
Omit<OptionsToBase<TFrom, K, TMaskFrom, TMaskTo>, 'to' | 'params'>;
|
||||||
}[FileRouteTypes['to']];
|
}[FileRouteTypes['to']];
|
||||||
|
|
||||||
|
export type LinkOptionsTo = OptionsTo &
|
||||||
|
Pick<
|
||||||
|
LinkOptions,
|
||||||
|
| 'preload'
|
||||||
|
| 'preloadDelay'
|
||||||
|
| 'activeOptions'
|
||||||
|
| 'preloadIntentProximity'
|
||||||
|
| 'unsafeRelative'
|
||||||
|
| 'ignoreBlocker'
|
||||||
|
| 'disabled'
|
||||||
|
| 'reloadDocument'
|
||||||
|
| 'target'
|
||||||
|
>;
|
||||||
|
|
Loading…
Reference in New Issue