From 0b7f71ca14a7c9dcad249b034ada03cd45418b7a Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 17 Apr 2025 22:11:25 -0600 Subject: [PATCH] router change updates --- .../BusterAppLayout/AppLayoutProvider.tsx | 43 ++++++++++++++----- web/src/context/Chats/NewChatProvider.tsx | 2 - .../MetricViewChartContent.tsx | 5 +++ .../useLayoutConfig/useLayoutConfig.ts | 7 +-- .../MetricContainerHeaderButtons.tsx | 19 +++++++- .../FileContainerHeader/SelectableButton.tsx | 2 +- 6 files changed, 57 insertions(+), 21 deletions(-) diff --git a/web/src/context/BusterAppLayout/AppLayoutProvider.tsx b/web/src/context/BusterAppLayout/AppLayoutProvider.tsx index 19fe17c89..300eaacc5 100644 --- a/web/src/context/BusterAppLayout/AppLayoutProvider.tsx +++ b/web/src/context/BusterAppLayout/AppLayoutProvider.tsx @@ -21,9 +21,16 @@ export const useAppLayout = () => { ): Promise => { const targetPath = typeof params === 'string' ? params : createBusterRoute(params); + // Check if the target URL is exactly the same as current URL (including search params) + const targetUrl = new URL(targetPath, window.location.origin); + const currentUrl = new URL(window.location.href); + if (targetUrl.toString() === currentUrl.toString()) { + return Promise.resolve(); + } + // Extract the pathname without query parameters - const targetPathname = new URL(targetPath, window.location.origin).pathname; - const currentPathname = new URL(window.location.href).pathname; + const targetPathname = targetUrl.pathname; + const currentPathname = currentUrl.pathname; if (options?.shallow) { const isSamePathname = targetPathname === currentPathname; @@ -48,6 +55,20 @@ export const useAppLayout = () => { // If target and current pathnames are the same but target includes query params if (currentPathname === targetPathname && targetPath.indexOf('?') !== -1) { + // Compare current and target query parameters + const currentUrl = new URL(window.location.href); + const targetUrl = new URL(targetPath, window.location.origin); + const currentParams = Object.fromEntries(currentUrl.searchParams.entries()); + const targetParams = Object.fromEntries(targetUrl.searchParams.entries()); + + // Check if the params are actually different + const paramsAreDifferent = JSON.stringify(currentParams) !== JSON.stringify(targetParams); + + if (!paramsAreDifferent) { + resolve(); + return; + } + push(targetPath); // Set up an effect to watch for pathname changes const checkPathChange = (waitTime: number = 25, iteration: number = 0) => { @@ -85,23 +106,21 @@ export const useAppLayout = () => { const createQueryParams = useMemoizedFn( (params: Record, preserveExisting: boolean) => { const url = new URL(window.location.href); - const searchParams = url.searchParams; if (!preserveExisting) { - searchParams.forEach((value, key) => { - searchParams.delete(key); - }); + // Clear all existing search parameters + url.search = ''; } + // Add new parameters Object.entries(params).forEach(([key, value]) => { if (value) { - searchParams.set(key, value); + url.searchParams.set(key, value); } else { - searchParams.delete(key); + url.searchParams.delete(key); } }); - url.search = searchParams.toString(); return url; } ); @@ -109,8 +128,12 @@ export const useAppLayout = () => { //TODO: make this typesafe... const onChangeQueryParams = useMemoizedFn( (params: Record, preserveExisting: boolean) => { + const isRemovingANonExistentParam = Object.keys(params).every( + (key) => !window.location.href.includes(key) + ); + if (isRemovingANonExistentParam) return; //we don't need to do anything if we're removing a non-existent param const url = createQueryParams(params, preserveExisting); - window.history.pushState({}, '', url); //we used window.history instead of replace for true shallow routing + if (url) window.history.pushState({}, '', url); //we used window.history instead of replace for true shallow routing } ); diff --git a/web/src/context/Chats/NewChatProvider.tsx b/web/src/context/Chats/NewChatProvider.tsx index 2d1084ed7..8a2bdfd08 100644 --- a/web/src/context/Chats/NewChatProvider.tsx +++ b/web/src/context/Chats/NewChatProvider.tsx @@ -105,8 +105,6 @@ export const useBusterNewChat = () => { (messageId) => messageId === messageId ); - console.log('messageIndex', messageIndex); - if (messageIndex && messageIndex !== -1) { console.log('oldMessageIds', currentChat?.message_ids); const updatedMessageIds = currentChat?.message_ids.slice(0, messageIndex + 1); diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricViewChartContent.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricViewChartContent.tsx index 71580d6c2..28ec70e74 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricViewChartContent.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricViewChartContent.tsx @@ -4,6 +4,7 @@ import { BusterChart } from '@/components/ui/charts'; import { cn } from '@/lib/classMerge'; import React, { useMemo } from 'react'; import { METRIC_CHART_CONTAINER_ID } from './config'; +import { useMount } from '@/hooks'; interface MetricViewChartContentProps { className?: string; @@ -35,6 +36,10 @@ export const MetricViewChartContent: React.FC = Rea return 'p-4'; }, [isTable, fetchedData]); + useMount(() => { + console.log('metricData'); + }); + return (
= MetricContainerHeaderButtons.displayName = 'MetricContainerHeaderButtons'; const EditChartButton = React.memo(({ metricId }: { metricId: string }) => { + const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage); const selectedFileViewSecondary = useChatLayoutContextSelector( (x) => x.selectedFileViewSecondary ); - const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage); const chatId = useChatIndividualContextSelector((x) => x.chatId); const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); const editableSecondaryView: MetricFileViewSecondary = 'chart-edit'; @@ -125,6 +125,16 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => { const isSelectedView = selectedFileViewSecondary === editableSecondaryView; const href = useMemo(() => { + if (isSelectedView) { + return assetParamsToRoute({ + chatId, + assetId: metricId, + type: 'metric', + secondaryView: null, + versionNumber: metricVersionNumber + }); + } + return assetParamsToRoute({ chatId, assetId: metricId, @@ -140,7 +150,12 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => { }); return ( - + { + e.preventDefault(); + e.stopPropagation(); + }}> } diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/SelectableButton.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/SelectableButton.tsx index f5acb6797..87ff4531d 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/SelectableButton.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/SelectableButton.tsx @@ -7,7 +7,7 @@ export const SelectableButton = React.memo<{ tooltipText: string; tooltipShortcuts?: string[]; icon: React.ReactNode; - onClick: () => void; + onClick?: () => void; selected?: boolean; }>(({ tooltipText, tooltipShortcuts, icon, onClick, selected }) => { return (