From f3944a6deac50135f1139b38e6b107756553aafa Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Sat, 26 Jul 2025 10:03:28 -0600 Subject: [PATCH] fix bug causing dashboard add menu to flicker --- .../dashboards/dashboardQueryHelpers.ts | 74 +++++++++++-------- .../buster_rest/dashboards/queryRequests.ts | 31 ++------ .../buttons/SaveMetricToDashboardButton.tsx | 28 ++----- 3 files changed, 59 insertions(+), 74 deletions(-) diff --git a/apps/web/src/api/buster_rest/dashboards/dashboardQueryHelpers.ts b/apps/web/src/api/buster_rest/dashboards/dashboardQueryHelpers.ts index 216fc5837..317de0ce2 100644 --- a/apps/web/src/api/buster_rest/dashboards/dashboardQueryHelpers.ts +++ b/apps/web/src/api/buster_rest/dashboards/dashboardQueryHelpers.ts @@ -15,18 +15,25 @@ import { import { dashboardsGetDashboard } from './requests'; import { metricsQueryKeys } from '@/api/query_keys/metric'; -export const useEnsureDashboardConfig = (prefetchData = true) => { +export const useEnsureDashboardConfig = (params?: { prefetchData?: boolean }) => { + const { prefetchData = true } = params || {}; const queryClient = useQueryClient(); - const prefetchDashboard = useGetDashboardAndInitializeMetrics(prefetchData); + const prefetchDashboard = useGetDashboardAndInitializeMetrics({ + prefetchData + }); const { openErrorMessage } = useBusterNotifications(); const getLatestDashboardVersion = useGetLatestDashboardVersionMemoized(); - const method = useMemoizedFn(async (dashboardId: string) => { + const method = useMemoizedFn(async (dashboardId: string, initializeMetrics = true) => { const latestVersion = getLatestDashboardVersion(dashboardId); const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId, latestVersion); let dashboardResponse = queryClient.getQueryData(options.queryKey); if (!dashboardResponse) { - const res = await prefetchDashboard(dashboardId, latestVersion || undefined).catch((e) => { + const res = await prefetchDashboard( + dashboardId, + latestVersion || undefined, + initializeMetrics + ).catch((e) => { openErrorMessage('Failed to save metrics to dashboard. Dashboard not found'); return null; }); @@ -46,7 +53,8 @@ export const useEnsureDashboardConfig = (prefetchData = true) => { return method; }; -export const useGetDashboardAndInitializeMetrics = (prefetchData = true) => { +export const useGetDashboardAndInitializeMetrics = (params?: { prefetchData?: boolean }) => { + const { prefetchData = true } = params || {}; const queryClient = useQueryClient(); const setOriginalDashboard = useOriginalDashboardStore((x) => x.setOriginalDashboard); const onSetLatestDashboardVersion = useDashboardQueryStore((x) => x.onSetLatestDashboardVersion); @@ -72,32 +80,40 @@ export const useGetDashboardAndInitializeMetrics = (prefetchData = true) => { } }); - return useMemoizedFn(async (id: string, version_number: number | null | undefined) => { - const { password } = getAssetPassword?.(id) || {}; + return useMemoizedFn( + async ( + id: string, + version_number: number | null | undefined, + shouldInitializeMetrics = true + ) => { + const { password } = getAssetPassword?.(id) || {}; - return dashboardsGetDashboard({ - id: id || '', - password, - version_number: version_number || undefined - }).then((data) => { - initializeMetrics(data.metrics); - const latestVersion = last(data.versions)?.version_number || 1; - const isLatestVersion = data.dashboard.version_number === latestVersion; + return dashboardsGetDashboard({ + id: id || '', + password, + version_number: version_number || undefined + }).then((data) => { + if (shouldInitializeMetrics) initializeMetrics(data.metrics); + const latestVersion = last(data.versions)?.version_number || 1; + const isLatestVersion = data.dashboard.version_number === latestVersion; - if (isLatestVersion) { - setOriginalDashboard(data.dashboard); - } + if (isLatestVersion) { + setOriginalDashboard(data.dashboard); + } - if (data.dashboard.version_number) { - queryClient.setQueryData( - dashboardQueryKeys.dashboardGetDashboard(data.dashboard.id, data.dashboard.version_number) - .queryKey, - data - ); - onSetLatestDashboardVersion(data.dashboard.id, latestVersion); - } + if (data.dashboard.version_number) { + queryClient.setQueryData( + dashboardQueryKeys.dashboardGetDashboard( + data.dashboard.id, + data.dashboard.version_number + ).queryKey, + data + ); + onSetLatestDashboardVersion(data.dashboard.id, latestVersion); + } - return data; - }); - }); + return data; + }); + } + ); }; diff --git a/apps/web/src/api/buster_rest/dashboards/queryRequests.ts b/apps/web/src/api/buster_rest/dashboards/queryRequests.ts index bc56f636b..0be2be6b5 100644 --- a/apps/web/src/api/buster_rest/dashboards/queryRequests.ts +++ b/apps/web/src/api/buster_rest/dashboards/queryRequests.ts @@ -86,7 +86,7 @@ export const useGetDashboard = ( export const usePrefetchGetDashboardClient = () => { const queryClient = useQueryClient(); - const queryFn = useGetDashboardAndInitializeMetrics(false); + const queryFn = useGetDashboardAndInitializeMetrics({ prefetchData: false }); return useMemoizedFn((id: string, versionNumber: number) => { const getDashboardQueryKey = dashboardQueryKeys.dashboardGetDashboard(id, versionNumber); const isStale = isQueryStale(getDashboardQueryKey, queryClient); @@ -447,7 +447,7 @@ export const useUpdateDashboardShare = () => { export const useAddAndRemoveMetricsFromDashboard = () => { const queryClient = useQueryClient(); const { openErrorMessage, openConfirmModal } = useBusterNotifications(); - const ensureDashboardConfig = useEnsureDashboardConfig(false); + const ensureDashboardConfig = useEnsureDashboardConfig({ prefetchData: false }); const setOriginalDashboard = useOriginalDashboardStore((x) => x.setOriginalDashboard); const setLatestDashboardVersion = useDashboardQueryStore((x) => x.onSetLatestDashboardVersion); @@ -560,7 +560,7 @@ export const useAddAndRemoveMetricsFromDashboard = () => { export const useAddMetricsToDashboard = () => { const queryClient = useQueryClient(); const { openErrorMessage, openConfirmModal } = useBusterNotifications(); - const ensureDashboardConfig = useEnsureDashboardConfig(false); + const ensureDashboardConfig = useEnsureDashboardConfig({ prefetchData: false }); const setOriginalDashboard = useOriginalDashboardStore((x) => x.setOriginalDashboard); const getLatestMetricVersion = useGetLatestMetricVersionMemoized(); const setLatestDashboardVersion = useDashboardQueryStore((x) => x.onSetLatestDashboardVersion); @@ -653,7 +653,7 @@ export const useAddMetricsToDashboard = () => { export const useRemoveMetricsFromDashboard = () => { const { openConfirmModal, openErrorMessage } = useBusterNotifications(); const queryClient = useQueryClient(); - const ensureDashboardConfig = useEnsureDashboardConfig(false); + const ensureDashboardConfig = useEnsureDashboardConfig({ prefetchData: false }); const setOriginalDashboard = useOriginalDashboardStore((x) => x.setOriginalDashboard); const getLatestMetricVersion = useGetLatestMetricVersionMemoized(); const setLatestDashboardVersion = useDashboardQueryStore((x) => x.onSetLatestDashboardVersion); @@ -683,7 +683,7 @@ export const useRemoveMetricsFromDashboard = () => { } } - const dashboardResponse = await ensureDashboardConfig(dashboardId); + const dashboardResponse = await ensureDashboardConfig(dashboardId, false); if (dashboardResponse) { const versionedOptions = dashboardQueryKeys.dashboardGetDashboard( @@ -715,13 +715,7 @@ export const useRemoveMetricsFromDashboard = () => { ).queryKey, data ); - queryClient.setQueryData( - dashboardQueryKeys.dashboardGetDashboard( - data.dashboard.id, - data.dashboard.version_number - ).queryKey, - data - ); + setOriginalDashboard(data.dashboard); return data; @@ -745,16 +739,6 @@ export const useRemoveMetricsFromDashboard = () => { return useMutation({ mutationFn: removeMetricFromDashboard, - onMutate: (variables) => { - variables.metricIds.forEach((id) => { - queryClient.setQueryData(metricsQueryKeys.metricsGetMetric(id, null).queryKey, (old) => { - if (!old) return old; - return create(old, (draft) => { - draft.dashboards = old?.dashboards?.filter((d) => d.id !== variables.dashboardId) || []; - }); - }); - }); - }, onSuccess: (data, variables) => { if (data) { setLatestDashboardVersion(data.dashboard.id, data.dashboard.version_number); @@ -762,7 +746,8 @@ export const useRemoveMetricsFromDashboard = () => { variables.metricIds.forEach((id) => { queryClient.invalidateQueries({ - queryKey: metricsQueryKeys.metricsGetMetric(id, null).queryKey + queryKey: metricsQueryKeys.metricsGetMetric(id, null).queryKey, + refetchType: 'all' }); }); } diff --git a/apps/web/src/components/features/buttons/SaveMetricToDashboardButton.tsx b/apps/web/src/components/features/buttons/SaveMetricToDashboardButton.tsx index a3e5ebeee..f694c10ec 100644 --- a/apps/web/src/components/features/buttons/SaveMetricToDashboardButton.tsx +++ b/apps/web/src/components/features/buttons/SaveMetricToDashboardButton.tsx @@ -5,7 +5,6 @@ import { } from '@/api/buster_rest/dashboards'; import { Button } from '@/components/ui/buttons'; import { AppTooltip } from '@/components/ui/tooltip'; -import { useBusterNotifications } from '@/context/BusterNotifications'; import { useMemoizedFn } from '@/hooks'; import { ASSET_ICONS } from '../config/assetIcons'; import { SaveToDashboardDropdown } from '../dropdowns/SaveToDashboardDropdown'; @@ -14,37 +13,22 @@ export const SaveMetricToDashboardButton: React.FC<{ metricIds: string[]; disabled?: boolean; selectedDashboards: string[]; -}> = React.memo(({ metricIds, disabled = false, selectedDashboards: selectedDashboardsProp }) => { +}> = React.memo(({ metricIds, disabled = false, selectedDashboards }) => { const { mutateAsync: saveMetricsToDashboard } = useAddMetricsToDashboard(); const { mutateAsync: removeMetricsFromDashboard } = useRemoveMetricsFromDashboard(); - const { openConfirmModal } = useBusterNotifications(); - - const [selectedDashboards, setSelectedDashboards] = - useState[0]['selectedDashboards']>( - selectedDashboardsProp - ); const onSaveToDashboard = useMemoizedFn(async (dashboardIds: string[]) => { - setSelectedDashboards((prev) => [...prev, ...dashboardIds]); await Promise.all( dashboardIds.map((dashboardId) => saveMetricsToDashboard({ metricIds, dashboardId })) ); }); const onRemoveFromDashboard = useMemoizedFn(async (dashboardIds: string[]) => { - const method = async () => { - setSelectedDashboards((prev) => prev.filter((x) => !dashboardIds.includes(x))); - await Promise.all( - dashboardIds.map((dashboardId) => - removeMetricsFromDashboard({ useConfirmModal: false, metricIds, dashboardId }) - ) - ); - }; - return await openConfirmModal({ - title: 'Remove from dashboard', - content: 'Are you sure you want to remove this from the dashboard?', - onOk: method - }); + await Promise.all( + dashboardIds.map((dashboardId) => + removeMetricsFromDashboard({ useConfirmModal: false, metricIds, dashboardId }) + ) + ); }); return (