mirror of https://github.com/buster-so/buster.git
add linking
This commit is contained in:
parent
08d7014725
commit
46f812d823
|
@ -65,16 +65,19 @@ export const prefetchGetReportsList = async (
|
|||
/**
|
||||
* Hook to get an individual report by ID
|
||||
*/
|
||||
export const useGetReport = (
|
||||
export const useGetReport = <T = GetReportIndividualResponse>(
|
||||
reportId: string | undefined,
|
||||
options?: Omit<UseQueryOptions<GetReportIndividualResponse, RustApiError>, 'queryKey' | 'queryFn'>
|
||||
options?: Omit<
|
||||
UseQueryOptions<GetReportIndividualResponse, RustApiError, T>,
|
||||
'queryKey' | 'queryFn'
|
||||
>
|
||||
) => {
|
||||
const queryFn = useMemoizedFn(() => {
|
||||
return getReportById(reportId!);
|
||||
});
|
||||
|
||||
return useQuery({
|
||||
...queryKeys.reportsGetById(reportId!),
|
||||
...queryKeys.reportsGetReport(reportId!),
|
||||
queryFn,
|
||||
enabled: !!reportId,
|
||||
select: options?.select,
|
||||
|
@ -89,7 +92,7 @@ export const prefetchGetReportById = async (reportId: string, queryClientProp?:
|
|||
const queryClient = queryClientProp || new QueryClient();
|
||||
|
||||
await queryClient.prefetchQuery({
|
||||
...queryKeys.reportsGetById(reportId),
|
||||
...queryKeys.reportsGetReport(reportId),
|
||||
queryFn: () => getReportById_server(reportId)
|
||||
});
|
||||
|
||||
|
@ -112,18 +115,18 @@ export const useUpdateReport = () => {
|
|||
onMutate: async ({ reportId, data }) => {
|
||||
// Cancel any outgoing refetches
|
||||
await queryClient.cancelQueries({
|
||||
queryKey: queryKeys.reportsGetById(reportId).queryKey
|
||||
queryKey: queryKeys.reportsGetReport(reportId).queryKey
|
||||
});
|
||||
|
||||
// Snapshot the previous value
|
||||
const previousReport = queryClient.getQueryData<GetReportIndividualResponse>(
|
||||
queryKeys.reportsGetById(reportId).queryKey
|
||||
queryKeys.reportsGetReport(reportId).queryKey
|
||||
);
|
||||
|
||||
// Optimistically update the individual report
|
||||
if (previousReport) {
|
||||
queryClient.setQueryData(
|
||||
queryKeys.reportsGetById(reportId).queryKey,
|
||||
queryKeys.reportsGetReport(reportId).queryKey,
|
||||
create(previousReport, (draft) => {
|
||||
if (data.name !== undefined) draft.name = data.name;
|
||||
if (data.description !== undefined) draft.description = data.description;
|
||||
|
@ -141,14 +144,14 @@ export const useUpdateReport = () => {
|
|||
// If the mutation fails, use the context to roll back
|
||||
if (context?.previousReport) {
|
||||
queryClient.setQueryData(
|
||||
queryKeys.reportsGetById(reportId).queryKey,
|
||||
queryKeys.reportsGetReport(reportId).queryKey,
|
||||
context.previousReport
|
||||
);
|
||||
}
|
||||
},
|
||||
onSuccess: (data, { reportId, data: updateData }) => {
|
||||
// Update the individual report cache with server response
|
||||
queryClient.setQueryData(queryKeys.reportsGetById(reportId).queryKey, data);
|
||||
queryClient.setQueryData(queryKeys.reportsGetReport(reportId).queryKey, data);
|
||||
|
||||
const nameChanged = updateData.name !== undefined && updateData.name !== data.name;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ const reportsGetList = (filters?: GetReportsListRequest) =>
|
|||
initialDataUpdatedAt: 0
|
||||
});
|
||||
|
||||
const reportsGetById = (reportId: string) =>
|
||||
const reportsGetReport = (reportId: string) =>
|
||||
queryOptions<GetReportIndividualResponse>({
|
||||
queryKey: ['reports', 'get', reportId] as const,
|
||||
staleTime: 60 * 1000 // 60 seconds
|
||||
|
@ -21,5 +21,5 @@ const reportsGetById = (reportId: string) =>
|
|||
|
||||
export const reportsQueryKeys = {
|
||||
reportsGetList,
|
||||
reportsGetById
|
||||
reportsGetReport
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ContextMenuProps } from '../../context-menu/ContextMenu';
|
||||
import { BusterList } from './index';
|
||||
import type { BusterListRow } from './interfaces';
|
||||
import type { BusterListColumn, BusterListRow } from './interfaces';
|
||||
|
||||
const meta: Meta<typeof BusterList> = {
|
||||
title: 'UI/List/BusterList',
|
||||
|
@ -33,10 +33,19 @@ const meta: Meta<typeof BusterList> = {
|
|||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof BusterList>;
|
||||
// Define the data type for our rows
|
||||
type SampleData = {
|
||||
name: string;
|
||||
age: number;
|
||||
address?: string;
|
||||
email?: string;
|
||||
actions?: any; // For the actions column
|
||||
};
|
||||
|
||||
type Story = StoryObj<typeof BusterList<SampleData>>;
|
||||
|
||||
// Sample data for the stories
|
||||
const sampleColumns = [
|
||||
const sampleColumns: BusterListColumn<SampleData>[] = [
|
||||
{
|
||||
dataIndex: 'name',
|
||||
title: 'Name',
|
||||
|
@ -51,7 +60,9 @@ const sampleColumns = [
|
|||
dataIndex: 'actions',
|
||||
title: 'Actions',
|
||||
width: 100,
|
||||
render: (_: any, record: any) => <button className="text-blue-500 hover:underline">View</button>
|
||||
render: (_: any, record: SampleData) => (
|
||||
<button className="text-blue-500 hover:underline">View</button>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@ const useBusterAssets = () => {
|
|||
queryKey: queryKeys.chatsGetChat(assetId).queryKey,
|
||||
refetchType: 'all'
|
||||
});
|
||||
} else if (type === 'report') {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: queryKeys.reportsGetReport(assetId).queryKey,
|
||||
refetchType: 'all'
|
||||
});
|
||||
} else {
|
||||
const exhaustiveCheck: never = type;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,9 @@ export const useGetAsset = (
|
|||
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 };
|
||||
|
@ -182,15 +185,28 @@ export const useGetAsset = (
|
|||
dashboardIsError,
|
||||
collectionIsFetched,
|
||||
collectionError,
|
||||
collectionIsError
|
||||
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, metricTitle, dashboardTitle, collectionTitle]);
|
||||
}, [
|
||||
isMetric,
|
||||
isDashboard,
|
||||
isCollection,
|
||||
isReport,
|
||||
metricTitle,
|
||||
dashboardTitle,
|
||||
collectionTitle,
|
||||
reportTitle
|
||||
]);
|
||||
|
||||
const { hasAccess, passwordRequired, isPublic } = getAssetAccess(currentQuery.error);
|
||||
|
||||
|
|
|
@ -35,6 +35,12 @@ export const CreateChatButton = React.memo(
|
|||
dashboardId: assetId,
|
||||
chatId: result.id
|
||||
});
|
||||
} else if (assetType === 'report') {
|
||||
await onChangePage({
|
||||
route: BusterRoutes.APP_CHAT_ID_REPORT_ID,
|
||||
reportId: assetId,
|
||||
chatId: result.id
|
||||
});
|
||||
} else {
|
||||
const _exhaustiveCheck: never = assetType;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { createMetricRoute, type MetricRouteParams } from './createMetricRoute';
|
|||
import { createDashboardRoute, type DashboardRouteParams } from './createDashboardRoute';
|
||||
import { createReasoningRoute } from './createReasoningRoute';
|
||||
import { createDatasetRoute } from './createDatasetRoute';
|
||||
import { createReportRoute } from './createReportRoute';
|
||||
|
||||
type UnionOfFileTypes = FileType | ReasoningFileType | ReasoingMessage_ThoughtFileType;
|
||||
|
||||
|
@ -22,7 +23,7 @@ type OtherRouteParams = {
|
|||
dashboardVersionNumber?: number; //if this is provided, it will be used instead of versionNumber
|
||||
page?: undefined;
|
||||
secondaryView?: undefined | null | string;
|
||||
type: Exclude<UnionOfFileTypes, 'metric' | 'dashboard'>;
|
||||
type: UnionOfFileTypes;
|
||||
};
|
||||
|
||||
type BaseParams = MetricRouteParams | DashboardRouteParams | OtherRouteParams;
|
||||
|
@ -73,6 +74,13 @@ export const assetParamsToRoute = ({
|
|||
});
|
||||
}
|
||||
|
||||
if (type === 'report') {
|
||||
return createReportRoute({
|
||||
assetId,
|
||||
chatId
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'reasoning') {
|
||||
return createReasoningRoute({
|
||||
assetId,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { BusterRoutes, createBusterRoute } from '@/routes/busterRoutes';
|
||||
|
||||
export type ReportRouteParams = {
|
||||
assetId: string;
|
||||
chatId?: string;
|
||||
type: 'report';
|
||||
};
|
||||
|
||||
export const createReportRoute = ({
|
||||
assetId: reportId,
|
||||
chatId
|
||||
}: Omit<ReportRouteParams, 'type'>) => {
|
||||
// Report routes within a chat context
|
||||
if (chatId) {
|
||||
return createBusterRoute({
|
||||
route: BusterRoutes.APP_CHAT_ID_REPORT_ID,
|
||||
chatId,
|
||||
reportId
|
||||
});
|
||||
}
|
||||
|
||||
// Standalone report route
|
||||
return createBusterRoute({
|
||||
route: BusterRoutes.APP_REPORTS_ID,
|
||||
reportId
|
||||
});
|
||||
};
|
|
@ -29,7 +29,7 @@ const ResponseMessage_FileMetadataSchema = z.object({
|
|||
timestamp: z.number().optional(),
|
||||
});
|
||||
|
||||
const ResponseMessageFileTypeSchema = z.enum(['metric', 'dashboard', 'reasoning']);
|
||||
const ResponseMessageFileTypeSchema = z.enum(['metric', 'dashboard', 'reasoning', 'report']);
|
||||
|
||||
const ResponseMessage_FileSchema = z.object({
|
||||
id: z.string(),
|
||||
|
@ -59,6 +59,7 @@ const ReasoningMessage_TextSchema = z.object({
|
|||
const ReasoningFileTypeSchema = z.enum([
|
||||
'metric',
|
||||
'dashboard',
|
||||
'report',
|
||||
'reasoning',
|
||||
'agent-action',
|
||||
'todo',
|
||||
|
|
Loading…
Reference in New Issue