mirror of https://github.com/buster-so/buster.git
metric save version
This commit is contained in:
parent
33a119f29b
commit
40b8545400
|
@ -264,12 +264,19 @@ export const useSaveMetric = (params?: { updateOnSave?: boolean }) => {
|
|||
metricsQueryKeys.metricsGetData(id, restore_to_version).queryKey
|
||||
);
|
||||
if (oldMetric && newMetric && newMetricData) {
|
||||
console.log('TODO. look into this because I do not think this is correct');
|
||||
const latestVersionNumber = queryClient.getQueryData(
|
||||
metricsQueryKeys.metricsGetMetric(id, undefined).queryKey
|
||||
)?.version_number;
|
||||
const newVersionNumber = (latestVersionNumber || 0) + 1;
|
||||
|
||||
queryClient.setQueryData(
|
||||
metricsQueryKeys.metricsGetMetric(id, versionNumber).queryKey,
|
||||
metricsQueryKeys.metricsGetMetric(id, newVersionNumber).queryKey,
|
||||
oldMetric
|
||||
);
|
||||
queryClient.setQueryData(metricsQueryKeys.metricsGetData(id).queryKey, newMetricData);
|
||||
queryClient.setQueryData(
|
||||
metricsQueryKeys.metricsGetData(id, newVersionNumber).queryKey,
|
||||
newMetricData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +309,7 @@ export const useSaveMetric = (params?: { updateOnSave?: boolean }) => {
|
|||
newMetric
|
||||
);
|
||||
//We need to update BOTH the versioned and the non-versioned metric for version updates to keep the latest up to date
|
||||
if (variables.update_version) {
|
||||
if (variables.update_version || variables.restore_to_version) {
|
||||
queryClient.setQueryData(
|
||||
metricsQueryKeys.metricsGetMetric(data.id, undefined).queryKey,
|
||||
newMetric
|
||||
|
|
|
@ -14,6 +14,7 @@ import Link from 'next/link';
|
|||
import { useGetFileLink } from '@/context/Assets/useGetFileLink';
|
||||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||
import { useCallback } from 'react';
|
||||
import { CircleSpinnerLoader } from '@/components/ui/loaders';
|
||||
|
||||
export const VersionHistoryPanel = React.memo(
|
||||
({ assetId, type }: { assetId: string; type: 'metric' | 'dashboard' }) => {
|
||||
|
@ -21,6 +22,7 @@ export const VersionHistoryPanel = React.memo(
|
|||
const {
|
||||
listItems,
|
||||
onPrefetchAsset,
|
||||
restoringVersion,
|
||||
currentVersionNumber,
|
||||
selectedQueryVersion,
|
||||
onClickRestoreVersion
|
||||
|
@ -61,6 +63,7 @@ export const VersionHistoryPanel = React.memo(
|
|||
selected={item.version_number === selectedQueryVersion}
|
||||
showRestoreButton={item.version_number !== currentVersionNumber}
|
||||
onClickRestoreVersion={onClickRestoreVersion}
|
||||
restoringVersion={restoringVersion}
|
||||
link={
|
||||
getFileLink({
|
||||
fileId: assetId,
|
||||
|
@ -85,6 +88,7 @@ const ListItem = React.memo(
|
|||
selected,
|
||||
showRestoreButton,
|
||||
link,
|
||||
restoringVersion,
|
||||
onClickRestoreVersion,
|
||||
onPrefetchAsset
|
||||
}: {
|
||||
|
@ -92,6 +96,7 @@ const ListItem = React.memo(
|
|||
updated_at: string;
|
||||
selected: boolean;
|
||||
showRestoreButton: boolean;
|
||||
restoringVersion: number | null;
|
||||
onClickRestoreVersion: (versionNumber: number) => void;
|
||||
onPrefetchAsset: (versionNumber: number, link: string) => Promise<void>;
|
||||
link: string;
|
||||
|
@ -111,6 +116,8 @@ const ListItem = React.memo(
|
|||
}
|
||||
}, []);
|
||||
|
||||
const isRestoringVersion = restoringVersion === version_number;
|
||||
|
||||
return (
|
||||
<Link prefetch={false} href={link}>
|
||||
<div
|
||||
|
@ -129,15 +136,20 @@ const ListItem = React.memo(
|
|||
|
||||
<div className="text-icon-color animate-in fade-in-0 flex items-center space-x-2 duration-200">
|
||||
{showRestoreButton && (
|
||||
<AppTooltip title="Restore version">
|
||||
<AppTooltip title={restoringVersion ? 'Restoring...' : 'Restore version'}>
|
||||
<div
|
||||
onClick={(e) => {
|
||||
if (restoringVersion) return;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
onClickRestoreVersion(version_number);
|
||||
}}
|
||||
className="hover:bg-gray-light/20 hover:text-foreground -mr-1 rounded p-1 opacity-0 group-hover:block group-hover:opacity-100">
|
||||
<History />
|
||||
className={cn(
|
||||
'hover:bg-gray-light/20 hover:text-foreground -mr-1 rounded p-1 opacity-0 group-hover:block group-hover:opacity-100',
|
||||
isRestoringVersion && 'cursor-not-allowed opacity-100!'
|
||||
)}>
|
||||
{isRestoringVersion ? <CircleSpinnerLoader size={12} /> : <History />}
|
||||
</div>
|
||||
</AppTooltip>
|
||||
)}
|
||||
|
|
|
@ -16,9 +16,10 @@ import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
|||
import { useCloseVersionHistory } from '@/layouts/ChatLayout/FileContainer/FileContainerHeader/FileContainerHeaderVersionHistory';
|
||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||
import last from 'lodash/last';
|
||||
import { useMemo } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { usePrefetchGetMetricClient } from '@/api/buster_rest/metrics';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { timeout } from '@/lib/timeout';
|
||||
|
||||
export const useListVersionHistories = ({
|
||||
assetId,
|
||||
|
@ -29,6 +30,7 @@ export const useListVersionHistories = ({
|
|||
}) => {
|
||||
const router = useRouter();
|
||||
const { onCloseVersionHistory } = useCloseVersionHistory();
|
||||
const [restoringVersion, setRestoringVersion] = useState<number | null>(null);
|
||||
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
||||
const {
|
||||
versions: dashboardVersions,
|
||||
|
@ -68,6 +70,8 @@ export const useListVersionHistories = ({
|
|||
|
||||
const onClickRestoreVersion = useMemoizedFn(
|
||||
async (versionNumber: number, rereouteToAsset: boolean = true) => {
|
||||
setRestoringVersion(versionNumber);
|
||||
|
||||
if (type === 'metric') {
|
||||
await onRestoreMetricVersion(versionNumber);
|
||||
if (rereouteToAsset) {
|
||||
|
@ -92,8 +96,9 @@ export const useListVersionHistories = ({
|
|||
onCloseVersionHistory();
|
||||
}
|
||||
}
|
||||
|
||||
onCloseVersionHistory();
|
||||
await timeout(500);
|
||||
setRestoringVersion(null);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -107,24 +112,19 @@ export const useListVersionHistories = ({
|
|||
}
|
||||
});
|
||||
|
||||
return useMemo(() => {
|
||||
const isRestoringVersion = useMemo(() => {
|
||||
return isSavingDashboard || isSavingMetric || restoringVersion !== null;
|
||||
}, [isSavingDashboard, isSavingMetric, restoringVersion]);
|
||||
|
||||
return {
|
||||
listItems,
|
||||
currentVersionNumber,
|
||||
selectedQueryVersion,
|
||||
onClickRestoreVersion,
|
||||
isRestoringVersion: isSavingDashboard || isSavingMetric,
|
||||
isRestoringVersion,
|
||||
restoringVersion,
|
||||
onPrefetchAsset
|
||||
};
|
||||
}, [
|
||||
listItems,
|
||||
currentVersionNumber,
|
||||
selectedQueryVersion,
|
||||
onClickRestoreVersion,
|
||||
isSavingDashboard,
|
||||
isSavingMetric,
|
||||
onPrefetchAsset
|
||||
]);
|
||||
};
|
||||
|
||||
type UseListVersionReturn = {
|
||||
|
@ -219,9 +219,11 @@ const useListMetricVersions = ({
|
|||
|
||||
const { data: metric } = useGetMetric(
|
||||
{
|
||||
id: type === 'metric' ? assetId : undefined
|
||||
id: type === 'metric' ? assetId : undefined,
|
||||
versionNumber: null
|
||||
},
|
||||
{
|
||||
enabled: !!assetId, //we do not want to have undefined versions when
|
||||
select: (x) => ({
|
||||
versions: x.versions,
|
||||
version_number: x.version_number
|
||||
|
|
|
@ -21,12 +21,14 @@ export const useAppLayout = () => {
|
|||
): Promise<void> => {
|
||||
const targetPath = typeof params === 'string' ? params : createBusterRoute(params);
|
||||
|
||||
if (options?.shallow) {
|
||||
const isSameMinusQueryParams =
|
||||
new URL(targetPath, window.location.origin).pathname ===
|
||||
new URL(window.location.href).pathname;
|
||||
// Extract the pathname without query parameters
|
||||
const targetPathname = new URL(targetPath, window.location.origin).pathname;
|
||||
const currentPathname = new URL(window.location.href).pathname;
|
||||
|
||||
if (isSameMinusQueryParams) {
|
||||
if (options?.shallow) {
|
||||
const isSamePathname = targetPathname === currentPathname;
|
||||
|
||||
if (isSamePathname) {
|
||||
return new Promise((resolve) => {
|
||||
const params = getQueryParamsFromPath(targetPath);
|
||||
onChangeQueryParams(params, false);
|
||||
|
@ -36,33 +38,45 @@ export const useAppLayout = () => {
|
|||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
// If we're already on the target path, resolve immediately
|
||||
if (currentPath === targetPath) {
|
||||
// If we're already on the target pathname, but query params might differ
|
||||
if (currentPathname === targetPathname && targetPath.indexOf('?') === -1) {
|
||||
// Clear query params by using the pathname only
|
||||
window.history.pushState({}, '', targetPathname);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// If target and current pathnames are the same but target includes query params
|
||||
if (currentPathname === targetPathname && targetPath.indexOf('?') !== -1) {
|
||||
push(targetPath);
|
||||
// Set up an effect to watch for pathname changes
|
||||
const checkPathChange = (waitTime: number = 25, iteration: number = 0) => {
|
||||
if (window.location.pathname !== currentPath) {
|
||||
if (window.location.href.includes(targetPath)) {
|
||||
resolve();
|
||||
} else if (iteration >= 10) {
|
||||
resolve();
|
||||
} else {
|
||||
const newWaitTime = waitTime * 1.25;
|
||||
setTimeout(() => checkPathChange(newWaitTime, iteration + 1), newWaitTime);
|
||||
}
|
||||
};
|
||||
checkPathChange();
|
||||
return;
|
||||
}
|
||||
|
||||
// Default case - different pathnames
|
||||
const checkPathChange = (waitTime: number = 25, iteration: number = 0) => {
|
||||
if (window.location.pathname !== currentPathname) {
|
||||
resolve();
|
||||
} else if (iteration >= 10) {
|
||||
// Resolve after 10 attempts to prevent infinite loops
|
||||
resolve();
|
||||
} else {
|
||||
// Check again in a short while if the path hasn't changed yet
|
||||
const newWaitTime = waitTime * 1.25;
|
||||
setTimeout(() => checkPathChange(newWaitTime, iteration + 1), newWaitTime);
|
||||
}
|
||||
};
|
||||
|
||||
// Start the navigation
|
||||
push(targetPath);
|
||||
console.log('pushed', targetPath);
|
||||
|
||||
// Start checking for path changes
|
||||
checkPathChange();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ export const useIsMetricChanged = ({ metricId }: { metricId: string }) => {
|
|||
name: x.name,
|
||||
description: x.description,
|
||||
chart_config: x.chart_config,
|
||||
file: x.file
|
||||
file: x.file,
|
||||
version_number: x.version_number
|
||||
})
|
||||
}
|
||||
);
|
||||
|
@ -44,7 +45,8 @@ export const useIsMetricChanged = ({ metricId }: { metricId: string }) => {
|
|||
'name',
|
||||
'description',
|
||||
'chart_config',
|
||||
'file'
|
||||
'file',
|
||||
'version_number'
|
||||
]),
|
||||
[originalMetric, currentMetric]
|
||||
);
|
||||
|
|
|
@ -3,17 +3,22 @@ import { Button } from '@/components/ui/buttons';
|
|||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||
import first from 'lodash/first';
|
||||
import { History } from '@/components/ui/icons';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useMemoizedFn, useMount } from '@/hooks';
|
||||
import React from 'react';
|
||||
import { useListVersionDropdownItems } from '@/components/features/versionHistory/useListVersionDropdownItems';
|
||||
import { FileType } from '@/api/asset_interfaces/chat';
|
||||
import { Dropdown } from '@/components/ui/dropdown';
|
||||
|
||||
export const VersionHistoryHeaderButtons: React.FC<{}> = ({}) => {
|
||||
export const VersionHistoryHeaderButtons: React.FC<{}> = React.memo(({}) => {
|
||||
const selectedFile = useChatLayoutContextSelector((x) => x.selectedFile);
|
||||
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
||||
const { listItems, isRestoringVersion, selectedQueryVersion, onClickRestoreVersion } =
|
||||
useListVersionHistories({
|
||||
const {
|
||||
listItems,
|
||||
restoringVersion,
|
||||
isRestoringVersion,
|
||||
selectedQueryVersion,
|
||||
onClickRestoreVersion
|
||||
} = useListVersionHistories({
|
||||
assetId: selectedFile?.id || '',
|
||||
type: selectedFile?.type as 'metric' | 'dashboard'
|
||||
});
|
||||
|
@ -41,11 +46,13 @@ export const VersionHistoryHeaderButtons: React.FC<{}> = ({}) => {
|
|||
disabled={isSelectedVersionCurrent || !currentVersion}
|
||||
onClick={onClickRestoreVersionPreflight}
|
||||
loading={isRestoringVersion}>
|
||||
Restore version
|
||||
Restore version {restoringVersion}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
VersionHistoryHeaderButtons.displayName = 'VersionHistoryHeaderButtons';
|
||||
|
||||
const VersionSelectButton = React.memo(
|
||||
({
|
||||
|
|
|
@ -7,7 +7,6 @@ import { useMemo } from 'react';
|
|||
|
||||
export const useCloseVersionHistory = () => {
|
||||
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
||||
const closeSecondaryView = useChatLayoutContextSelector((x) => x.closeSecondaryView);
|
||||
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
||||
const metricId = useChatLayoutContextSelector((x) => x.metricId);
|
||||
const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId);
|
||||
|
@ -37,7 +36,6 @@ export const useCloseVersionHistory = () => {
|
|||
|
||||
const onCloseVersionHistory = useMemoizedFn(() => {
|
||||
onChangePage(href);
|
||||
closeSecondaryView();
|
||||
});
|
||||
|
||||
return { href, onCloseVersionHistory };
|
||||
|
|
Loading…
Reference in New Issue