mirror of https://github.com/buster-so/buster.git
finalized some prefetch logic
This commit is contained in:
parent
06b4236388
commit
17748b1ddb
|
@ -84,7 +84,10 @@ export const useGetChat = <TData = IBusterChat>(
|
||||||
if (lastMessage) {
|
if (lastMessage) {
|
||||||
Object.values(lastMessage.response_messages).forEach((responseMessage) => {
|
Object.values(lastMessage.response_messages).forEach((responseMessage) => {
|
||||||
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
|
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
|
||||||
prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient);
|
prefetchGetMetricDataClient(
|
||||||
|
{ id: responseMessage.id, version_number: responseMessage.version_number },
|
||||||
|
queryClient
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,10 @@ const useGetDashboardAndInitializeMetrics = () => {
|
||||||
const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey);
|
const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey);
|
||||||
const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric);
|
const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric);
|
||||||
queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric);
|
queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric);
|
||||||
prefetchGetMetricDataClient({ id: metric.id }, queryClient);
|
prefetchGetMetricDataClient(
|
||||||
|
{ id: metric.id, version_number: metric.version_number },
|
||||||
|
queryClient
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,31 @@ import {
|
||||||
import { useParams, useSearchParams } from 'next/navigation';
|
import { useParams, useSearchParams } from 'next/navigation';
|
||||||
import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore';
|
import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore';
|
||||||
import { RustApiError } from '../../buster_rest/errors';
|
import { RustApiError } from '../../buster_rest/errors';
|
||||||
|
import last from 'lodash/last';
|
||||||
|
|
||||||
|
const useGetMetricVersionNumber = ({
|
||||||
|
versionNumber: versionNumberProp
|
||||||
|
}: {
|
||||||
|
versionNumber?: number | null; //if null it will not use a params from the query params
|
||||||
|
}) => {
|
||||||
|
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
|
||||||
|
versionNumber: string | undefined;
|
||||||
|
metricId: string | undefined;
|
||||||
|
};
|
||||||
|
const versionNumberQueryParam = useSearchParams().get('metric_version_number');
|
||||||
|
const versionNumberFromParams = metricIdPathParam
|
||||||
|
? versionNumberQueryParam || versionNumberPathParam
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const versionNumber = useMemo(() => {
|
||||||
|
if (versionNumberProp === null) return undefined;
|
||||||
|
return versionNumberProp || versionNumberFromParams
|
||||||
|
? parseInt(versionNumberFromParams!)
|
||||||
|
: undefined;
|
||||||
|
}, [versionNumberProp, versionNumberFromParams]);
|
||||||
|
|
||||||
|
return versionNumber;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a hook that will use the version number from the URL params if it exists.
|
* This is a hook that will use the version number from the URL params if it exists.
|
||||||
|
@ -54,21 +79,7 @@ export const useGetMetric = <TData = IBusterMetric>(
|
||||||
const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError);
|
const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError);
|
||||||
const { password } = getAssetPassword(id!);
|
const { password } = getAssetPassword(id!);
|
||||||
|
|
||||||
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
|
const versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp });
|
||||||
versionNumber: string | undefined;
|
|
||||||
metricId: string | undefined;
|
|
||||||
};
|
|
||||||
const versionNumberQueryParam = useSearchParams().get('versionNumber');
|
|
||||||
const versionNumberFromParams = metricIdPathParam
|
|
||||||
? versionNumberQueryParam || versionNumberPathParam
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const versionNumber = useMemo(() => {
|
|
||||||
if (versionNumberProp === null) return undefined;
|
|
||||||
return versionNumberProp || versionNumberFromParams
|
|
||||||
? parseInt(versionNumberFromParams!)
|
|
||||||
: undefined;
|
|
||||||
}, [versionNumberProp, versionNumberFromParams]);
|
|
||||||
|
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
return metricsQueryKeys.metricsGetMetric(id!, versionNumber);
|
return metricsQueryKeys.metricsGetMetric(id!, versionNumber);
|
||||||
|
@ -78,7 +89,10 @@ export const useGetMetric = <TData = IBusterMetric>(
|
||||||
const result = await getMetric({ id: id!, password, version_number: versionNumber });
|
const result = await getMetric({ id: id!, password, version_number: versionNumber });
|
||||||
const oldMetric = queryClient.getQueryData(options.queryKey);
|
const oldMetric = queryClient.getQueryData(options.queryKey);
|
||||||
const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null);
|
const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null);
|
||||||
setOriginalMetric(updatedMetric);
|
|
||||||
|
const isLatestVersion =
|
||||||
|
updatedMetric.version_number === last(updatedMetric.versions)?.version_number;
|
||||||
|
if (isLatestVersion) setOriginalMetric(updatedMetric);
|
||||||
return updatedMetric;
|
return updatedMetric;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -128,28 +142,13 @@ export const useGetMetricData = <TData = IBusterMetricData>(
|
||||||
) => {
|
) => {
|
||||||
const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword);
|
const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword);
|
||||||
const { password } = getAssetPassword(id!);
|
const { password } = getAssetPassword(id!);
|
||||||
|
const versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp });
|
||||||
const {
|
const {
|
||||||
isFetched: isFetchedMetric,
|
isFetched: isFetchedMetric,
|
||||||
error: errorMetric,
|
isError: isErrorMetric,
|
||||||
|
dataUpdatedAt,
|
||||||
data: fetchedMetricData
|
data: fetchedMetricData
|
||||||
} = useGetMetric({ id }, { select: (x) => x.id });
|
} = useGetMetric({ id, versionNumber }, { select: (x) => x.id });
|
||||||
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
|
|
||||||
versionNumber: string | undefined;
|
|
||||||
metricId: string | undefined;
|
|
||||||
};
|
|
||||||
const versionNumberQueryParam = useSearchParams().get('versionNumber');
|
|
||||||
const versionNumberFromParams = metricIdPathParam
|
|
||||||
? versionNumberQueryParam || versionNumberPathParam
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const versionNumber = useMemo(() => {
|
|
||||||
if (versionNumberProp === null) return undefined;
|
|
||||||
return versionNumberProp || versionNumberFromParams
|
|
||||||
? parseInt(versionNumberFromParams!)
|
|
||||||
: undefined;
|
|
||||||
}, [versionNumberProp, versionNumberFromParams]);
|
|
||||||
|
|
||||||
const queryFn = useMemoizedFn(() => {
|
const queryFn = useMemoizedFn(() => {
|
||||||
return getMetricData({ id: id!, version_number: versionNumber, password });
|
return getMetricData({ id: id!, version_number: versionNumber, password });
|
||||||
});
|
});
|
||||||
|
@ -158,7 +157,7 @@ export const useGetMetricData = <TData = IBusterMetricData>(
|
||||||
...metricsQueryKeys.metricsGetData(id!, versionNumber),
|
...metricsQueryKeys.metricsGetData(id!, versionNumber),
|
||||||
queryFn,
|
queryFn,
|
||||||
enabled: () => {
|
enabled: () => {
|
||||||
return !!id && isFetchedMetric && !errorMetric && !!fetchedMetricData;
|
return !!id && isFetchedMetric && !isErrorMetric && !!fetchedMetricData && !!dataUpdatedAt;
|
||||||
},
|
},
|
||||||
select: params?.select,
|
select: params?.select,
|
||||||
...params
|
...params
|
||||||
|
@ -166,7 +165,7 @@ export const useGetMetricData = <TData = IBusterMetricData>(
|
||||||
};
|
};
|
||||||
|
|
||||||
export const prefetchGetMetricDataClient = async (
|
export const prefetchGetMetricDataClient = async (
|
||||||
{ id, version_number }: { id: string; version_number?: number },
|
{ id, version_number }: { id: string; version_number: number | undefined },
|
||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
) => {
|
) => {
|
||||||
const options = metricsQueryKeys.metricsGetData(id, version_number);
|
const options = metricsQueryKeys.metricsGetData(id, version_number);
|
||||||
|
|
|
@ -83,7 +83,10 @@ export const BusterChart: React.FC<BusterChartProps> = React.memo(
|
||||||
});
|
});
|
||||||
|
|
||||||
const SwitchComponent = useMemoizedFn(() => {
|
const SwitchComponent = useMemoizedFn(() => {
|
||||||
if (loading || error || !isMounted) {
|
//chartjs need the parent to be mounted to render the chart. It is intermitent when it throws when the parent is not mounted.
|
||||||
|
if (!isMounted && selectedChartType !== ChartType.Table) return null;
|
||||||
|
|
||||||
|
if (loading || error) {
|
||||||
return <PreparingYourRequestLoader error={error} />;
|
return <PreparingYourRequestLoader error={error} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ export const PreparingYourRequestLoader: React.FC<{
|
||||||
useShimmer?: boolean;
|
useShimmer?: boolean;
|
||||||
}> = ({ className = '', text = 'Processing your request...', error, useShimmer = true }) => {
|
}> = ({ className = '', text = 'Processing your request...', error, useShimmer = true }) => {
|
||||||
return (
|
return (
|
||||||
<div className={`flex h-full w-full items-center justify-center space-x-1.5 ${className}`}>
|
<div
|
||||||
|
className={`flex h-full min-h-24 w-full items-center justify-center space-x-1.5 ${className}`}>
|
||||||
{error || useShimmer === false ? (
|
{error || useShimmer === false ? (
|
||||||
<span className="text-text-tertiary flex items-center text-center">{error || text}</span>
|
<span className="text-text-tertiary flex items-center text-center">{error || text}</span>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -71,7 +71,10 @@ export const useChatStreamMessage = () => {
|
||||||
if (lastMessage?.response_message_ids) {
|
if (lastMessage?.response_message_ids) {
|
||||||
Object.values(lastMessage.response_messages).forEach((responseMessage) => {
|
Object.values(lastMessage.response_messages).forEach((responseMessage) => {
|
||||||
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
|
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
|
||||||
prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient);
|
prefetchGetMetricDataClient(
|
||||||
|
{ id: responseMessage.id, version_number: responseMessage.version_number },
|
||||||
|
queryClient
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@ export const useIsMetricReadOnly = ({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
select: (x) => ({
|
select: (x) => ({
|
||||||
permission: x.permission,
|
permission: x.permission,
|
||||||
versions: x.versions
|
versions: x.versions,
|
||||||
|
version_number: x.version_number
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,11 +2,7 @@
|
||||||
|
|
||||||
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { compareObjectsByKeys } from '@/lib/objects';
|
import { useMount } from '@/hooks';
|
||||||
import { useGetMetric } from '@/api/buster_rest/metrics/queryRequests';
|
|
||||||
import { useMemoizedFn, useMount } from '@/hooks';
|
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { metricsQueryKeys } from '@/api/query_keys/metric';
|
|
||||||
|
|
||||||
type OriginalMetricStore = {
|
type OriginalMetricStore = {
|
||||||
originalMetrics: Record<string, IBusterMetric>;
|
originalMetrics: Record<string, IBusterMetric>;
|
||||||
|
|
|
@ -24,12 +24,11 @@ export const DashboardViewDashboardController: React.FC<{
|
||||||
} = useGetDashboard({ id: dashboardId });
|
} = useGetDashboard({ id: dashboardId });
|
||||||
|
|
||||||
const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig();
|
const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig();
|
||||||
const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode);
|
|
||||||
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
|
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
|
||||||
|
|
||||||
const metrics = dashboardResponse?.metrics;
|
const metrics = dashboardResponse?.metrics;
|
||||||
const dashboard = dashboardResponse?.dashboard;
|
const dashboard = dashboardResponse?.dashboard;
|
||||||
const { isReadOnly } = useIsDashboardReadOnly({
|
const { isReadOnly, isViewingOldVersion, isVersionHistoryMode } = useIsDashboardReadOnly({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
readOnly: readOnlyProp
|
readOnly: readOnlyProp
|
||||||
});
|
});
|
||||||
|
@ -65,7 +64,9 @@ export const DashboardViewDashboardController: React.FC<{
|
||||||
readOnly={isReadOnly}
|
readOnly={isReadOnly}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!isVersionHistoryMode && <DashboardSavePopup dashboardId={dashboardId} />}
|
{!isVersionHistoryMode && !isViewingOldVersion && (
|
||||||
|
<DashboardSavePopup dashboardId={dashboardId} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const MetricStylingApp: React.FC<{
|
||||||
MetricStylingAppSegments.VISUALIZE
|
MetricStylingAppSegments.VISUALIZE
|
||||||
);
|
);
|
||||||
const { data: chartConfig } = useGetMetric({ id: metricId }, { select: (x) => x.chart_config });
|
const { data: chartConfig } = useGetMetric({ id: metricId }, { select: (x) => x.chart_config });
|
||||||
const { data: metricData } = useGetMetricData({ id: metricId });
|
const { data: metricData } = useGetMetricData({ id: metricId }, { enabled: false });
|
||||||
|
|
||||||
if (!chartConfig) return null;
|
if (!chartConfig) return null;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,9 @@ export const MetricViewChart: React.FC<{
|
||||||
time_frame,
|
time_frame,
|
||||||
permission,
|
permission,
|
||||||
evaluation_score,
|
evaluation_score,
|
||||||
evaluation_summary
|
evaluation_summary,
|
||||||
|
version_number,
|
||||||
|
versions
|
||||||
}) => ({
|
}) => ({
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
@ -41,7 +43,9 @@ export const MetricViewChart: React.FC<{
|
||||||
permission,
|
permission,
|
||||||
evaluation_score,
|
evaluation_score,
|
||||||
evaluation_summary,
|
evaluation_summary,
|
||||||
chart_config
|
chart_config,
|
||||||
|
version_number,
|
||||||
|
versions
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -49,7 +53,7 @@ export const MetricViewChart: React.FC<{
|
||||||
data: metricData,
|
data: metricData,
|
||||||
isFetched: isFetchedMetricData,
|
isFetched: isFetchedMetricData,
|
||||||
error: metricDataError
|
error: metricDataError
|
||||||
} = useGetMetricData({ id: metricId });
|
} = useGetMetricData({ id: metricId }, { enabled: false });
|
||||||
|
|
||||||
const { mutate: updateMetric } = useUpdateMetric({
|
const { mutate: updateMetric } = useUpdateMetric({
|
||||||
saveToServer: false
|
saveToServer: false
|
||||||
|
@ -57,7 +61,7 @@ export const MetricViewChart: React.FC<{
|
||||||
const { name, description, time_frame, evaluation_score, evaluation_summary } = metric || {};
|
const { name, description, time_frame, evaluation_score, evaluation_summary } = metric || {};
|
||||||
|
|
||||||
const isTable = metric?.chart_config.selectedChartType === ChartType.Table;
|
const isTable = metric?.chart_config.selectedChartType === ChartType.Table;
|
||||||
const { isReadOnly, isVersionHistoryMode } = useIsMetricReadOnly({
|
const { isReadOnly, isVersionHistoryMode, isViewingOldVersion } = useIsMetricReadOnly({
|
||||||
metricId,
|
metricId,
|
||||||
readOnly: readOnlyProp
|
readOnly: readOnlyProp
|
||||||
});
|
});
|
||||||
|
@ -110,7 +114,9 @@ export const MetricViewChart: React.FC<{
|
||||||
/>
|
/>
|
||||||
</AnimatePresenceWrapper>
|
</AnimatePresenceWrapper>
|
||||||
|
|
||||||
{!isVersionHistoryMode && <MetricSaveFilePopup metricId={metricId} />}
|
{!isVersionHistoryMode && !isViewingOldVersion && (
|
||||||
|
<MetricSaveFilePopup metricId={metricId} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,10 @@ export const MetricViewResults: React.FC<{ metricId: string }> = React.memo(({ m
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData({ id: metricId });
|
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData(
|
||||||
|
{ id: metricId },
|
||||||
|
{ enabled: false }
|
||||||
|
);
|
||||||
|
|
||||||
const [sql, setSQL] = useState(metric?.sql || '');
|
const [sql, setSQL] = useState(metric?.sql || '');
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { AppPasswordAccess } from '@/controllers/AppPasswordAccess';
|
||||||
import { AppNoPageAccess } from '@/controllers/AppNoPageAccess';
|
import { AppNoPageAccess } from '@/controllers/AppNoPageAccess';
|
||||||
import { useGetAsset } from './useGetAsset';
|
import { useGetAsset } from './useGetAsset';
|
||||||
import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader';
|
import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader';
|
||||||
|
import { useParams, useSearchParams } from 'next/navigation';
|
||||||
|
|
||||||
export type AppAssetCheckLayoutProps = {
|
export type AppAssetCheckLayoutProps = {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
||||||
import { useGetDashboard } from '@/api/buster_rest/dashboards';
|
import { useGetDashboard } from '@/api/buster_rest/dashboards';
|
||||||
import { RustApiError } from '@/api/buster_rest/errors';
|
import { RustApiError } from '@/api/buster_rest/errors';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
interface BaseGetAssetProps {
|
interface BaseGetAssetProps {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
|
@ -15,6 +17,7 @@ interface MetricAssetProps extends BaseGetAssetProps {
|
||||||
|
|
||||||
interface DashboardAssetProps extends BaseGetAssetProps {
|
interface DashboardAssetProps extends BaseGetAssetProps {
|
||||||
type: 'dashboard';
|
type: 'dashboard';
|
||||||
|
versionNumber?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type UseGetAssetProps = MetricAssetProps | DashboardAssetProps;
|
type UseGetAssetProps = MetricAssetProps | DashboardAssetProps;
|
||||||
|
@ -29,47 +32,55 @@ type UseGetAssetReturn<T extends UseGetAssetProps> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetAsset = (props: UseGetAssetProps): UseGetAssetReturn<typeof props> => {
|
export const useGetAsset = (props: UseGetAssetProps): UseGetAssetReturn<typeof props> => {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const metricVersionNumber = searchParams.get('metric_version_number');
|
||||||
|
const dashboardVersionNumber = searchParams.get('dashboard_version_number');
|
||||||
|
|
||||||
|
const queryParamVersionNumber: number | undefined = useMemo(() => {
|
||||||
|
if (props.type === 'metric' && metricVersionNumber) {
|
||||||
|
return parseInt(metricVersionNumber);
|
||||||
|
}
|
||||||
|
if (props.type === 'dashboard' && dashboardVersionNumber) {
|
||||||
|
return parseInt(dashboardVersionNumber);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [props.type, metricVersionNumber, dashboardVersionNumber]);
|
||||||
|
|
||||||
|
const versionNumber: number | undefined = useMemo(() => {
|
||||||
|
if (props.type === 'metric') {
|
||||||
|
if (props.versionNumber) return props.versionNumber;
|
||||||
|
if (queryParamVersionNumber) return queryParamVersionNumber;
|
||||||
|
}
|
||||||
|
if (props.type === 'dashboard') {
|
||||||
|
if (props.versionNumber) return props.versionNumber;
|
||||||
|
if (queryParamVersionNumber) return queryParamVersionNumber;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [props, queryParamVersionNumber]);
|
||||||
|
|
||||||
//metric
|
//metric
|
||||||
const {
|
const { error: errorMetric, isFetched: isFetchedMetric } = useGetMetric(
|
||||||
error: errorMetric,
|
|
||||||
isError: isErrorMetric,
|
|
||||||
dataUpdatedAt,
|
|
||||||
isFetched: isFetchedMetric
|
|
||||||
} = useGetMetric(
|
|
||||||
{
|
{
|
||||||
id: props.assetId,
|
id: props.type === 'metric' ? props.assetId : undefined,
|
||||||
versionNumber: props.type === 'metric' ? props.versionNumber : undefined
|
versionNumber
|
||||||
},
|
},
|
||||||
{
|
{ enabled: props.type === 'metric' && !!props.assetId }
|
||||||
enabled: props.type === 'metric' && !!props.assetId
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const { isFetched: isFetchedMetricData } = useGetMetricData(
|
|
||||||
{
|
|
||||||
id: props.assetId,
|
|
||||||
versionNumber: props.type === 'metric' ? props.versionNumber : undefined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enabled:
|
|
||||||
props.type === 'metric' &&
|
|
||||||
!!props.assetId &&
|
|
||||||
isFetchedMetric &&
|
|
||||||
!!dataUpdatedAt && //This is a hack to prevent the query from being run when the asset is not fetched.
|
|
||||||
!isErrorMetric
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { isFetched: isFetchedMetricData } = useGetMetricData({
|
||||||
|
id: props.assetId,
|
||||||
|
versionNumber
|
||||||
|
});
|
||||||
|
|
||||||
//dashboard
|
//dashboard
|
||||||
const {
|
const {
|
||||||
isFetched: isFetchedDashboard,
|
isFetched: isFetchedDashboard,
|
||||||
error: errorDashboard,
|
error: errorDashboard,
|
||||||
isError: isErrorDashboard
|
isError: isErrorDashboard
|
||||||
} = useGetDashboard(
|
} = useGetDashboard({
|
||||||
{
|
id: props.type === 'dashboard' ? props.assetId : undefined,
|
||||||
id: props.type === 'dashboard' ? props.assetId : undefined
|
versionNumber
|
||||||
},
|
});
|
||||||
{ enabled: props.type === 'dashboard' && !!props.assetId }
|
|
||||||
);
|
|
||||||
|
|
||||||
const { hasAccess, passwordRequired, isPublic } = getAssetAccess({
|
const { hasAccess, passwordRequired, isPublic } = getAssetAccess({
|
||||||
error: props.type === 'metric' ? errorMetric : errorDashboard
|
error: props.type === 'metric' ? errorMetric : errorDashboard
|
||||||
|
|
|
@ -30,9 +30,14 @@ export const ChatContent: React.FC<{}> = React.memo(() => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mb-40 flex h-full w-full flex-col overflow-hidden">
|
<div className="mb-40 flex h-full w-full flex-col overflow-hidden">
|
||||||
{chatMessageIds?.map((messageId) => (
|
{chatMessageIds?.map((messageId, index) => (
|
||||||
<div key={messageId} className={autoClass}>
|
<div key={messageId} className={autoClass}>
|
||||||
<ChatMessageBlock key={messageId} messageId={messageId} chatId={chatId || ''} />
|
<ChatMessageBlock
|
||||||
|
key={messageId}
|
||||||
|
messageId={messageId}
|
||||||
|
chatId={chatId || ''}
|
||||||
|
messageIndex={index}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { useGetChatMessage } from '@/api/buster_rest/chats';
|
||||||
export const ChatMessageBlock: React.FC<{
|
export const ChatMessageBlock: React.FC<{
|
||||||
messageId: string;
|
messageId: string;
|
||||||
chatId: string;
|
chatId: string;
|
||||||
}> = React.memo(({ messageId, chatId }) => {
|
messageIndex: number;
|
||||||
|
}> = React.memo(({ messageId, chatId, messageIndex }) => {
|
||||||
const messageExists = useGetChatMessage(messageId, (message) => message?.id);
|
const messageExists = useGetChatMessage(messageId, (message) => message?.id);
|
||||||
const requestMessage = useGetChatMessage(messageId, (message) => message?.request_message);
|
const requestMessage = useGetChatMessage(messageId, (message) => message?.request_message);
|
||||||
const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream);
|
const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream);
|
||||||
|
@ -29,6 +30,7 @@ export const ChatMessageBlock: React.FC<{
|
||||||
isCompletedStream={isCompletedStream!}
|
isCompletedStream={isCompletedStream!}
|
||||||
messageId={messageId}
|
messageId={messageId}
|
||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
|
messageIndex={messageIndex}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const ChatResponseMessage_File: React.FC<ChatResponseMessageProps> = Reac
|
||||||
const onLinkClick = useMemoizedFn(() => {
|
const onLinkClick = useMemoizedFn(() => {
|
||||||
if (isSelectedFile) onSetSelectedFile(null);
|
if (isSelectedFile) onSetSelectedFile(null);
|
||||||
|
|
||||||
onSetSelectedFile({ id, type: file_type });
|
onSetSelectedFile({ id, type: file_type, versionNumber: responseMessage.version_number });
|
||||||
});
|
});
|
||||||
|
|
||||||
useMount(() => {
|
useMount(() => {
|
||||||
|
|
|
@ -9,17 +9,19 @@ interface ChatResponseMessagesProps {
|
||||||
isCompletedStream: boolean;
|
isCompletedStream: boolean;
|
||||||
messageId: string;
|
messageId: string;
|
||||||
chatId: string;
|
chatId: string;
|
||||||
|
messageIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.memo(
|
export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.memo(
|
||||||
({ chatId, isCompletedStream, messageId }) => {
|
({ chatId, isCompletedStream, messageId, messageIndex }) => {
|
||||||
const responseMessageIds = useGetChatMessage(messageId, (x) => x?.response_message_ids || [])!;
|
const responseMessageIds = useGetChatMessage(messageId, (x) => x?.response_message_ids || [])!;
|
||||||
const lastReasoningMessageId = useGetChatMessage(
|
const lastReasoningMessageId = useGetChatMessage(
|
||||||
messageId,
|
messageId,
|
||||||
(x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1]
|
(x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1]
|
||||||
);
|
);
|
||||||
const finalReasoningMessage = useGetChatMessage(messageId, (x) => x?.final_reasoning_message);
|
const finalReasoningMessage = useGetChatMessage(messageId, (x) => x?.final_reasoning_message);
|
||||||
const showReasoningMessage = !!lastReasoningMessageId || !isCompletedStream;
|
const showReasoningMessage =
|
||||||
|
messageIndex === 0 ? !!lastReasoningMessageId || !isCompletedStream : true;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MessageContainer className="flex w-full flex-col space-y-3 overflow-hidden">
|
<MessageContainer className="flex w-full flex-col space-y-3 overflow-hidden">
|
||||||
|
|
|
@ -4,19 +4,30 @@ import { useGetChatParams } from '../useGetChatParams';
|
||||||
export const createSelectedFile = (
|
export const createSelectedFile = (
|
||||||
params: ReturnType<typeof useGetChatParams>
|
params: ReturnType<typeof useGetChatParams>
|
||||||
): SelectedFile | null => {
|
): SelectedFile | null => {
|
||||||
const { metricId, collectionId, datasetId, dashboardId, chatId, messageId } = params;
|
const {
|
||||||
|
metricId,
|
||||||
|
collectionId,
|
||||||
|
datasetId,
|
||||||
|
dashboardId,
|
||||||
|
chatId,
|
||||||
|
messageId,
|
||||||
|
metricVersionNumber,
|
||||||
|
dashboardVersionNumber
|
||||||
|
} = params;
|
||||||
|
|
||||||
if (metricId) {
|
if (metricId) {
|
||||||
return {
|
return {
|
||||||
id: metricId,
|
id: metricId,
|
||||||
type: 'metric'
|
type: 'metric',
|
||||||
|
versionNumber: metricVersionNumber
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dashboardId) {
|
if (dashboardId) {
|
||||||
return {
|
return {
|
||||||
id: dashboardId,
|
id: dashboardId,
|
||||||
type: 'dashboard'
|
type: 'dashboard',
|
||||||
|
versionNumber: dashboardVersionNumber
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,7 @@ export const useSelectedFile = ({
|
||||||
* @param file
|
* @param file
|
||||||
*/
|
*/
|
||||||
const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => {
|
const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => {
|
||||||
const handleFileCollapse =
|
const handleFileCollapse = shouldCloseSplitter(file, selectedFile, appSplitterRef);
|
||||||
!file || (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right'));
|
|
||||||
|
|
||||||
if (file && chatParams.chatId) {
|
if (file && chatParams.chatId) {
|
||||||
const link = createChatAssetRoute({
|
const link = createChatAssetRoute({
|
||||||
|
@ -61,3 +60,18 @@ export const useSelectedFile = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SelectedFileParams = ReturnType<typeof useSelectedFile>;
|
export type SelectedFileParams = ReturnType<typeof useSelectedFile>;
|
||||||
|
|
||||||
|
const shouldCloseSplitter = (
|
||||||
|
file: SelectedFile | null,
|
||||||
|
selectedFile: SelectedFile | null,
|
||||||
|
appSplitterRef: React.RefObject<AppSplitterRef | null>
|
||||||
|
) => {
|
||||||
|
if (!file) return false;
|
||||||
|
if (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right')) {
|
||||||
|
if (!!file?.versionNumber && !!selectedFile?.versionNumber) {
|
||||||
|
return file.versionNumber === selectedFile.versionNumber;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
|
@ -403,7 +403,7 @@ const useSQLEditorSelectMenu = () => {
|
||||||
|
|
||||||
const useDownloadCSVSelectMenu = ({ metricId }: { metricId: string }) => {
|
const useDownloadCSVSelectMenu = ({ metricId }: { metricId: string }) => {
|
||||||
const [isDownloading, setIsDownloading] = useState(false);
|
const [isDownloading, setIsDownloading] = useState(false);
|
||||||
const { data: metricData } = useGetMetricData({ id: metricId });
|
const { data: metricData } = useGetMetricData({ id: metricId }, { enabled: false });
|
||||||
const { data: name } = useGetMetric({ id: metricId }, { select: (x) => x.name });
|
const { data: name } = useGetMetric({ id: metricId }, { select: (x) => x.name });
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
|
|
|
@ -3,6 +3,7 @@ import type { FileType } from '@/api/asset_interfaces';
|
||||||
export type SelectedFile = {
|
export type SelectedFile = {
|
||||||
id: string;
|
id: string;
|
||||||
type: FileType;
|
type: FileType;
|
||||||
|
versionNumber?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChatLayoutView = 'chat' | 'file' | 'both';
|
export type ChatLayoutView = 'chat' | 'file' | 'both';
|
||||||
|
|
Loading…
Reference in New Issue