start moving to hook based updates

This commit is contained in:
Nate Kelley 2025-03-13 10:11:57 -06:00
parent 545ad32f50
commit 77ece34d25
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
13 changed files with 93 additions and 76 deletions

View File

@ -41,4 +41,6 @@ export type UpdateMetricParams = {
feedback?: 'negative'; feedback?: 'negative';
/** Admin only: verification status update */ /** Admin only: verification status update */
status?: VerificationStatus; status?: VerificationStatus;
/** file in yaml format to update */
file?: string;
} & ShareRequest; } & ShareRequest;

View File

@ -10,7 +10,7 @@ import {
listMetrics_server, listMetrics_server,
updateMetric updateMetric
} from './requests'; } from './requests';
import type { GetMetricParams, ListMetricsParams } from './interfaces'; import type { GetMetricParams, ListMetricsParams, UpdateMetricParams } from './interfaces';
import { upgradeMetricToIMetric } from '@/lib/chat'; import { upgradeMetricToIMetric } from '@/lib/chat';
import { queryKeys } from '@/api/query_keys'; import { queryKeys } from '@/api/query_keys';
import { useMemo } from 'react'; import { useMemo } from 'react';
@ -19,6 +19,8 @@ import { resolveEmptyMetric } from '@/lib/metrics/resolve';
import { useGetUserFavorites } from '../users'; import { useGetUserFavorites } from '../users';
import { useBusterNotifications } from '@/context/BusterNotifications'; import { useBusterNotifications } from '@/context/BusterNotifications';
import type { IBusterMetric } from '@/api/asset_interfaces/metric'; import type { IBusterMetric } from '@/api/asset_interfaces/metric';
import { create } from 'mutative';
import { prepareMetricUpdateMetric } from '@/lib/metrics/saveToServerHelpers';
export const useGetMetric = <TData = IBusterMetric>( export const useGetMetric = <TData = IBusterMetric>(
id: string | undefined, id: string | undefined,
@ -119,11 +121,15 @@ export const prefetchGetMetricDataClient = async (
}); });
}; };
export const useUpdateMetric = () => { /**
* This is a mutation that saves a metric to the server.
* It will simply use the params passed in and not do any special logic.
*/
export const useSaveMetric = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: updateMetric, mutationFn: updateMetric,
onSuccess: (data, variables, context) => { onSuccess: (data) => {
const hasDraftSessionId = data.draft_session_id; const hasDraftSessionId = data.draft_session_id;
const metricId = data.id; const metricId = data.id;
const options = queryKeys.metricsGetMetric(metricId); const options = queryKeys.metricsGetMetric(metricId);
@ -138,6 +144,38 @@ export const useUpdateMetric = () => {
}); });
}; };
/**
* This is a mutation that updates a metric.
* It will create a new metric with the new values combined with the old values and save it to the server.
* It will also strip out any values that are not changed from the DEFAULT_CHART_CONFIG.
* It will also update the draft_session_id if it exists.
*/
export const useUpdateMetric = () => {
const queryClient = useQueryClient();
const { mutateAsync: saveMetric } = useSaveMetric();
const mutationFn = useMemoizedFn(
async (newMetricPartial: Partial<IBusterMetric> & { id: string }) => {
const metricId = newMetricPartial.id;
const options = queryKeys.metricsGetMetric(metricId);
const prevMetric = queryClient.getQueryData(options.queryKey);
const newMetric = create(prevMetric, (draft) => {
Object.assign(draft || {}, newMetricPartial);
});
if (prevMetric && newMetric) {
const changedValues = prepareMetricUpdateMetric(newMetric, prevMetric);
if (changedValues) {
return saveMetric(changedValues);
}
}
return Promise.resolve(newMetric!);
}
);
return useMutation({
mutationFn
});
};
export const useDeleteMetric = () => { export const useDeleteMetric = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
return useMutation({ return useMutation({
@ -202,8 +240,8 @@ export const useMetricIndividual = ({ metricId }: { metricId: string }) => {
}; };
export const useSaveMetricToCollection = () => { export const useSaveMetricToCollection = () => {
const { mutateAsync: updateMetricMutation } = useUpdateMetric();
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites(); const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { mutateAsync: saveMetric } = useSaveMetric();
const saveMetricToCollection = useMemoizedFn( const saveMetricToCollection = useMemoizedFn(
async ({ metricId, collectionIds }: { metricId: string; collectionIds: string[] }) => { async ({ metricId, collectionIds }: { metricId: string; collectionIds: string[] }) => {
@ -212,7 +250,7 @@ export const useSaveMetricToCollection = () => {
return collectionIds.includes(searchId); return collectionIds.includes(searchId);
}); });
await updateMetricMutation({ await saveMetric({
id: metricId, id: metricId,
add_to_collections: collectionIds add_to_collections: collectionIds
}); });
@ -230,8 +268,8 @@ export const useSaveMetricToCollection = () => {
}; };
export const useRemoveMetricFromCollection = () => { export const useRemoveMetricFromCollection = () => {
const { mutateAsync: updateMetricMutation } = useUpdateMetric();
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites(); const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { mutateAsync: saveMetric } = useSaveMetric();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const removeMetricFromCollection = useMemoizedFn( const removeMetricFromCollection = useMemoizedFn(
@ -244,7 +282,7 @@ export const useRemoveMetricFromCollection = () => {
return currentMetric.collections.some((c) => c.id === searchId); return currentMetric.collections.some((c) => c.id === searchId);
}); });
await updateMetricMutation({ await saveMetric({
id: metricId, id: metricId,
remove_from_collections: [collectionId] remove_from_collections: [collectionId]
}); });
@ -262,11 +300,11 @@ export const useRemoveMetricFromCollection = () => {
export const useSaveMetricToDashboard = () => { export const useSaveMetricToDashboard = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { mutateAsync: updateMetricMutation } = useUpdateMetric(); const { mutateAsync: saveMetric } = useSaveMetric();
const saveMetricToDashboard = useMemoizedFn( const saveMetricToDashboard = useMemoizedFn(
async ({ metricId, dashboardIds }: { metricId: string; dashboardIds: string[] }) => { async ({ metricId, dashboardIds }: { metricId: string; dashboardIds: string[] }) => {
await updateMetricMutation({ await saveMetric({
id: metricId, id: metricId,
save_to_dashboard: dashboardIds save_to_dashboard: dashboardIds
}); });
@ -275,7 +313,7 @@ export const useSaveMetricToDashboard = () => {
return useMutation({ return useMutation({
mutationFn: saveMetricToDashboard, mutationFn: saveMetricToDashboard,
onSuccess: (data, variables, context) => { onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: variables.dashboardIds.map((id) => queryKeys.dashboardGetDashboard(id).queryKey) queryKey: variables.dashboardIds.map((id) => queryKeys.dashboardGetDashboard(id).queryKey)
}); });
@ -284,10 +322,8 @@ export const useSaveMetricToDashboard = () => {
}; };
export const useRemoveMetricFromDashboard = () => { export const useRemoveMetricFromDashboard = () => {
const queryClient = useQueryClient();
const { openConfirmModal } = useBusterNotifications(); const { openConfirmModal } = useBusterNotifications();
const { mutateAsync: updateMetricMutation } = useUpdateMetric(); const { mutateAsync: saveMetric } = useSaveMetric();
const removeMetricFromDashboard = useMemoizedFn( const removeMetricFromDashboard = useMemoizedFn(
async ({ async ({
metricId, metricId,
@ -299,7 +335,7 @@ export const useRemoveMetricFromDashboard = () => {
useConfirmModal?: boolean; useConfirmModal?: boolean;
}) => { }) => {
const method = async () => { const method = async () => {
await updateMetricMutation({ await saveMetric({
id: metricId, id: metricId,
remove_from_dashboard: [dashboardId] remove_from_dashboard: [dashboardId]
}); });

View File

@ -17,7 +17,7 @@ import { UserGroup, ChevronRight } from '@/components/ui/icons';
import { cn } from '@/lib/classMerge'; import { cn } from '@/lib/classMerge';
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces'; import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
import { useUpdateCollection } from '@/api/buster_rest/collections'; import { useUpdateCollection } from '@/api/buster_rest/collections';
import { useUpdateMetric } from '@/api/buster_rest/metrics'; import { useSaveMetric, useUpdateMetric } from '@/api/buster_rest/metrics';
import { useUpdateDashboard } from '@/api/buster_rest/dashboards'; import { useUpdateDashboard } from '@/api/buster_rest/dashboards';
export const ShareMenuContentBody: React.FC<{ export const ShareMenuContentBody: React.FC<{
@ -77,7 +77,7 @@ const ShareMenuContentShare: React.FC<{
}> = React.memo(({ setOpenShareWithGroupAndTeam, assetType, individual_permissions, assetId }) => { }> = React.memo(({ setOpenShareWithGroupAndTeam, assetType, individual_permissions, assetId }) => {
const userTeams = useUserConfigContextSelector((state) => state.userTeams); const userTeams = useUserConfigContextSelector((state) => state.userTeams);
const { mutateAsync: onShareDashboard } = useUpdateDashboard(); const { mutateAsync: onShareDashboard } = useUpdateDashboard();
const { mutateAsync: onShareMetric } = useUpdateMetric(); const { mutateAsync: onShareMetric } = useSaveMetric();
const { mutateAsync: onShareCollection } = useUpdateCollection(); const { mutateAsync: onShareCollection } = useUpdateCollection();
const [inputValue, setInputValue] = React.useState<string>(''); const [inputValue, setInputValue] = React.useState<string>('');
const [isInviting, setIsInviting] = React.useState<boolean>(false); const [isInviting, setIsInviting] = React.useState<boolean>(false);

View File

@ -10,7 +10,7 @@ import { UserGroup } from '@/components/ui/icons';
import { ShareAssetType } from '@/api/asset_interfaces'; import { ShareAssetType } from '@/api/asset_interfaces';
import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces'; import type { ShareRequest } from '@/api/asset_interfaces/shared_interfaces';
import { useGetCollection, useUpdateCollection } from '@/api/buster_rest/collections'; import { useGetCollection, useUpdateCollection } from '@/api/buster_rest/collections';
import { useGetMetric, useUpdateMetric } from '@/api/buster_rest/metrics'; import { useGetMetric, useSaveMetric } from '@/api/buster_rest/metrics';
import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards'; import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards';
export const ShareWithGroupAndTeam: React.FC<{ export const ShareWithGroupAndTeam: React.FC<{
@ -21,7 +21,7 @@ export const ShareWithGroupAndTeam: React.FC<{
}> = ({ assetType, assetId, goBack, onCopyLink }) => { }> = ({ assetType, assetId, goBack, onCopyLink }) => {
const userTeams = useUserConfigContextSelector((state) => state.userTeams); const userTeams = useUserConfigContextSelector((state) => state.userTeams);
const { mutateAsync: onShareDashboard } = useUpdateDashboard(); const { mutateAsync: onShareDashboard } = useUpdateDashboard();
const { mutateAsync: onShareMetric } = useUpdateMetric(); const { mutateAsync: onShareMetric } = useSaveMetric();
const { mutateAsync: onShareCollection } = useUpdateCollection(); const { mutateAsync: onShareCollection } = useUpdateCollection();
const { data: dashboardResponse } = useGetDashboard( const { data: dashboardResponse } = useGetDashboard(
assetType === ShareAssetType.DASHBOARD ? assetId : undefined assetType === ShareAssetType.DASHBOARD ? assetId : undefined

View File

@ -22,12 +22,12 @@ const BusterTableChartBase: React.FC<BusterTableChartProps> = ({
columnLabelFormats = DEFAULT_CHART_CONFIG.columnLabelFormats, columnLabelFormats = DEFAULT_CHART_CONFIG.columnLabelFormats,
tableColumnWidths = DEFAULT_CHART_CONFIG.tableColumnWidths, tableColumnWidths = DEFAULT_CHART_CONFIG.tableColumnWidths,
editable = true, editable = true,
onInitialAnimationEnd,
//TODO //TODO
tableHeaderBackgroundColor, tableHeaderBackgroundColor,
tableHeaderFontColor, tableHeaderFontColor,
isDarkMode, isDarkMode,
animate, animate,
onInitialAnimationEnd,
tableColumnFontColor tableColumnFontColor
}) => { }) => {
const onUpdateMetricChartConfig = useBusterMetricsContextSelector( const onUpdateMetricChartConfig = useBusterMetricsContextSelector(

View File

@ -6,7 +6,7 @@ import { BusterReactQueryProvider } from './BusterReactQuery/BusterReactQueryAnd
import { AppLayoutProvider } from './BusterAppLayout'; import { AppLayoutProvider } from './BusterAppLayout';
import { BusterUserConfigProvider } from './Users/UserConfigProvider'; import { BusterUserConfigProvider } from './Users/UserConfigProvider';
import { BusterAssetsProvider } from './Assets/BusterAssetsProvider'; import { BusterAssetsProvider } from './Assets/BusterAssetsProvider';
import { BusterPosthogProvider } from './Posthog/usePosthog'; import { BusterPosthogProvider } from './Posthog';
import { BusterChatProvider } from './Chats'; import { BusterChatProvider } from './Chats';
import { RoutePrefetcher } from './RoutePrefetcher'; import { RoutePrefetcher } from './RoutePrefetcher';
import { BusterMetricsProvider } from './Metrics'; import { BusterMetricsProvider } from './Metrics';

View File

@ -3,10 +3,9 @@
import React, { PropsWithChildren, useTransition } from 'react'; import React, { PropsWithChildren, useTransition } from 'react';
import { createContext, useContextSelector } from 'use-context-selector'; import { createContext, useContextSelector } from 'use-context-selector';
import { import {
BusterMetric,
ColumnSettings, ColumnSettings,
DEFAULT_CHART_CONFIG, DEFAULT_CHART_CONFIG,
IColumnLabelFormat, type IColumnLabelFormat,
type IBusterMetric, type IBusterMetric,
type IBusterMetricChartConfig type IBusterMetricChartConfig
} from '@/api/asset_interfaces/metric'; } from '@/api/asset_interfaces/metric';
@ -14,13 +13,9 @@ import { useParams } from 'next/navigation';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { queryKeys } from '@/api/query_keys'; import { queryKeys } from '@/api/query_keys';
import { useDebounceFn, useMemoizedFn } from '@/hooks'; import { useDebounceFn, useMemoizedFn } from '@/hooks';
import { import { prepareMetricUpdateMetric, resolveEmptyMetric } from '@/lib/metrics';
prepareMetricUpdateMetric,
resolveEmptyMetric,
upgradeMetricToIMetric
} from '@/lib/metrics';
import { create } from 'mutative'; import { create } from 'mutative';
import { ShareRole, VerificationStatus } from '@/api/asset_interfaces/share'; import { ShareRole } from '@/api/asset_interfaces/share';
import { useUpdateMetric } from '@/api/buster_rest/metrics'; import { useUpdateMetric } from '@/api/buster_rest/metrics';
const useBusterMetrics = () => { const useBusterMetrics = () => {
@ -44,7 +39,7 @@ const useBusterMetrics = () => {
// STATE UPDATERS // STATE UPDATERS
const setMetricToState = useMemoizedFn((metric: IBusterMetric) => { const _setMetricToState = useMemoizedFn((metric: IBusterMetric) => {
const metricId = getMetricId(metric.id); const metricId = getMetricId(metric.id);
const options = queryKeys.metricsGetMetric(metricId); const options = queryKeys.metricsGetMetric(metricId);
queryClient.setQueryData(options.queryKey, metric); queryClient.setQueryData(options.queryKey, metric);
@ -57,7 +52,7 @@ const useBusterMetrics = () => {
const newMetric = create(currentMetric, (draft) => { const newMetric = create(currentMetric, (draft) => {
Object.assign(draft, newMetricPartial); Object.assign(draft, newMetricPartial);
}); });
setMetricToState(newMetric); _setMetricToState(newMetric);
//This will trigger a rerender and push prepareMetricUpdateMetric off UI metric //This will trigger a rerender and push prepareMetricUpdateMetric off UI metric
startTransition(() => { startTransition(() => {
const isReadyOnly = currentMetric.permission === ShareRole.VIEWER; const isReadyOnly = currentMetric.permission === ShareRole.VIEWER;
@ -73,7 +68,7 @@ const useBusterMetrics = () => {
useMemoizedFn((newMetric: IBusterMetric, oldMetric: IBusterMetric) => { useMemoizedFn((newMetric: IBusterMetric, oldMetric: IBusterMetric) => {
const changedValues = prepareMetricUpdateMetric(newMetric, oldMetric); const changedValues = prepareMetricUpdateMetric(newMetric, oldMetric);
if (changedValues) { if (changedValues) {
updateMetricMutation(changedValues); // updateMetricMutation(changedValues);
} }
}), }),
{ wait: 750 } { wait: 750 }
@ -173,32 +168,12 @@ const useBusterMetrics = () => {
} }
); );
const onSaveMetricChanges = useMemoizedFn(
async (params: { metricId: string; save_draft: boolean; save_as_metric_state?: string }) => {
return updateMetricMutation({
id: params.metricId,
...params
});
}
);
const onVerifiedMetric = useMemoizedFn(
async ({ metricId, status }: { metricId: string; status: VerificationStatus }) => {
return await onUpdateMetric({
id: metricId,
status
});
}
);
return { return {
getMetricMemoized, getMetricMemoized,
onUpdateMetric, onUpdateMetric,
onUpdateMetricChartConfig, onUpdateMetricChartConfig,
onUpdateColumnLabelFormat, onUpdateColumnLabelFormat,
onUpdateColumnSetting, onUpdateColumnSetting
onSaveMetricChanges,
onVerifiedMetric
}; };
}; };

View File

@ -0,0 +1 @@
export * from './BusterPosthogProvider';

View File

@ -1,8 +1,7 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { MetricViewChartContent } from './MetricViewChartContent'; import { MetricViewChartContent } from './MetricViewChartContent';
import { MetricViewChartHeader } from './MetricViewChartHeader'; import { MetricViewChartHeader } from './MetricViewChartHeader';
import { useMetricIndividual } from '@/api/buster_rest/metrics'; import { useMetricIndividual, useUpdateMetric } from '@/api/buster_rest/metrics';
import { useBusterMetricsContextSelector } from '@/context/Metrics';
import { useMemoizedFn } from '@/hooks'; import { useMemoizedFn } from '@/hooks';
import { inputHasText } from '@/lib/text'; import { inputHasText } from '@/lib/text';
import { MetricChartEvaluation } from './MetricChartEvaluation'; import { MetricChartEvaluation } from './MetricChartEvaluation';
@ -11,7 +10,7 @@ import { AnimatePresence, motion } from 'framer-motion';
import { cn } from '@/lib/classMerge'; import { cn } from '@/lib/classMerge';
export const MetricViewChart: React.FC<{ metricId: string }> = React.memo(({ metricId }) => { export const MetricViewChart: React.FC<{ metricId: string }> = React.memo(({ metricId }) => {
const onUpdateMetric = useBusterMetricsContextSelector((x) => x.onUpdateMetric); const { mutateAsync: updateMetric } = useUpdateMetric();
const { metric, metricData, metricDataError, isFetchedMetricData } = useMetricIndividual({ const { metric, metricData, metricDataError, isFetchedMetricData } = useMetricIndividual({
metricId metricId
}); });
@ -24,7 +23,8 @@ export const MetricViewChart: React.FC<{ metricId: string }> = React.memo(({ met
const onSetTitle = useMemoizedFn((title: string) => { const onSetTitle = useMemoizedFn((title: string) => {
if (inputHasText(title)) { if (inputHasText(title)) {
onUpdateMetric({ updateMetric({
id: metricId,
title title
}); });
} }

View File

@ -1,16 +1,15 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import type { MetricViewProps } from '../config'; import type { MetricViewProps } from '../config';
import { CodeCard } from '@/components/ui/card'; import { CodeCard } from '@/components/ui/card';
import { useBusterMetricsContextSelector } from '@/context/Metrics';
import { useMemoizedFn } from '@/hooks'; import { useMemoizedFn } from '@/hooks';
import { SaveResetFilePopup } from '@/components/features/popups/SaveResetFilePopup'; import { SaveResetFilePopup } from '@/components/features/popups/SaveResetFilePopup';
import { useBusterNotifications } from '@/context/BusterNotifications'; import { useBusterNotifications } from '@/context/BusterNotifications';
import { useMetricIndividual } from '@/api/buster_rest/metrics'; import { useMetricIndividual, useUpdateMetric } from '@/api/buster_rest/metrics';
export const MetricViewFile: React.FC<MetricViewProps> = React.memo(({ metricId }) => { export const MetricViewFile: React.FC<MetricViewProps> = React.memo(({ metricId }) => {
const { metric } = useMetricIndividual({ metricId }); const { metric } = useMetricIndividual({ metricId });
const { openSuccessMessage } = useBusterNotifications(); const { openSuccessMessage } = useBusterNotifications();
const onUpdateMetric = useBusterMetricsContextSelector((x) => x.onUpdateMetric); const { mutateAsync: updateMetric } = useUpdateMetric();
const { file: fileProp, file_name } = metric; const { file: fileProp, file_name } = metric;
@ -23,8 +22,9 @@ export const MetricViewFile: React.FC<MetricViewProps> = React.memo(({ metricId
}); });
const onSaveFile = useMemoizedFn(async () => { const onSaveFile = useMemoizedFn(async () => {
await onUpdateMetric({ await updateMetric({
file file,
id: metricId
}); });
openSuccessMessage(`${file_name} saved`); openSuccessMessage(`${file_name} saved`);
}); });

View File

@ -8,14 +8,13 @@ import { useQueryClient } from '@tanstack/react-query';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { didColumnDataChange, simplifyChatConfigForSQLChange } from './helpers'; import { didColumnDataChange, simplifyChatConfigForSQLChange } from './helpers';
import { useRunSQL as useRunSQLQuery } from '@/api/buster_rest'; import { useRunSQL as useRunSQLQuery } from '@/api/buster_rest';
import { useUpdateMetric } from '@/api/buster_rest/metrics'; import { useSaveMetric, useUpdateMetric } from '@/api/buster_rest/metrics';
export const useMetricRunSQL = () => { export const useMetricRunSQL = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const onUpdateMetric = useBusterMetricsContextSelector((x) => x.onUpdateMetric);
const getMetricMemoized = useBusterMetricsContextSelector((x) => x.getMetricMemoized); const getMetricMemoized = useBusterMetricsContextSelector((x) => x.getMetricMemoized);
const onSaveMetricChanges = useBusterMetricsContextSelector((x) => x.onSaveMetricChanges);
const { mutateAsync: updateMetricMutation } = useUpdateMetric(); const { mutateAsync: updateMetricMutation } = useUpdateMetric();
const { mutateAsync: saveMetric } = useSaveMetric();
const { mutateAsync: runSQLMutation } = useRunSQLQuery(); const { mutateAsync: runSQLMutation } = useRunSQLQuery();
const { openSuccessNotification } = useBusterNotifications(); const { openSuccessNotification } = useBusterNotifications();
@ -88,7 +87,7 @@ export const useMetricRunSQL = () => {
data_metadata, data_metadata,
code: sql code: sql
}); });
onUpdateMetric({ updateMetricMutation({
id: metricId, id: metricId,
chart_config: totallyDefaultChartConfig chart_config: totallyDefaultChartConfig
}); });
@ -121,7 +120,7 @@ export const useMetricRunSQL = () => {
setWarnBeforeNavigating(false); setWarnBeforeNavigating(false);
if (!originalConfigs.current) return; if (!originalConfigs.current) return;
const oldConfig = originalConfigs.current?.chartConfig; const oldConfig = originalConfigs.current?.chartConfig;
onUpdateMetric({ updateMetricMutation({
id: metricId, id: metricId,
chart_config: oldConfig chart_config: oldConfig
}); });
@ -161,14 +160,10 @@ export const useMetricRunSQL = () => {
} }
} }
await updateMetricMutation({ await saveMetric({
id: metricId, id: metricId,
sql: sql sql: sql,
}); save_draft: true
await onSaveMetricChanges({
metricId,
save_draft: true,
save_as_metric_state: metricId
}); });
setWarnBeforeNavigating(false); setWarnBeforeNavigating(false);

View File

@ -14,7 +14,8 @@ import { Dots, Star, Trash, Xmark } from '@/components/ui/icons';
import { import {
useDeleteMetric, useDeleteMetric,
useRemoveMetricFromCollection, useRemoveMetricFromCollection,
useSaveMetricToCollection useSaveMetricToCollection,
useUpdateMetric
} from '@/api/buster_rest/metrics'; } from '@/api/buster_rest/metrics';
import { import {
useAddUserFavorite, useAddUserFavorite,
@ -130,11 +131,18 @@ const StatusButton: React.FC<{
selectedRowKeys: string[]; selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void; onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => { }> = ({ selectedRowKeys, onSelectChange }) => {
const onVerifiedMetric = useBusterMetricsContextSelector((state) => state.onVerifiedMetric); const { mutateAsync: updateMetric } = useUpdateMetric();
const isAdmin = useUserConfigContextSelector((state) => state.isAdmin); const isAdmin = useUserConfigContextSelector((state) => state.isAdmin);
const onVerify = useMemoizedFn(async (d: { id: string; status: VerificationStatus }[]) => { const onVerify = useMemoizedFn(async (d: { id: string; status: VerificationStatus }[]) => {
// await onVerifiedMetric(d); await Promise.all(
d.map(({ id, status }) => {
return updateMetric({
id,
status
});
})
);
onSelectChange([]); onSelectChange([]);
}); });