From d9bc8d4741ff4be0240e830d847b9b8f02ee10fc Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Tue, 1 Apr 2025 15:31:21 -0600 Subject: [PATCH] better prevent navigation logic --- .../features/popups/SaveResetFilePopup.tsx | 1 - .../features/sidebars/SidebarPrimary.tsx | 6 +-- .../ui/layouts/PreventNavigation.tsx | 53 +++++++++++++++++-- .../components/ui/segmented/AppSegmented.tsx | 17 ++++-- .../MetricContainerHeaderSegment.tsx | 1 - web/src/routes/helpers.tsx | 12 ++--- 6 files changed, 71 insertions(+), 19 deletions(-) diff --git a/web/src/components/features/popups/SaveResetFilePopup.tsx b/web/src/components/features/popups/SaveResetFilePopup.tsx index e8e6829d3..ef4fc0439 100644 --- a/web/src/components/features/popups/SaveResetFilePopup.tsx +++ b/web/src/components/features/popups/SaveResetFilePopup.tsx @@ -24,7 +24,6 @@ const SplitterContent: React.FC<{ isSaving: boolean; open: boolean; }> = React.memo(({ onReset, onSave, isSaving, open }) => { - console.log(open); return (
diff --git a/web/src/components/features/sidebars/SidebarPrimary.tsx b/web/src/components/features/sidebars/SidebarPrimary.tsx index 704bb461d..7ff34d3cd 100644 --- a/web/src/components/features/sidebars/SidebarPrimary.tsx +++ b/web/src/components/features/sidebars/SidebarPrimary.tsx @@ -122,7 +122,7 @@ export const SidebarPrimary = React.memo(() => { const isAdmin = useUserConfigContextSelector((x) => x.isAdmin); const isUserRegistered = useUserConfigContextSelector((x) => x.isUserRegistered); const { data: favorites } = useGetUserFavorites(); - const currentRoute = useAppLayoutContextSelector((x) => x.currentRoute); + const currentParentRoute = useAppLayoutContextSelector((x) => x.currentParentRoute); const onToggleInviteModal = useInviteModalStore((s) => s.onToggleInviteModal); const [openSupportModal, setOpenSupportModal] = useState(false); const { mutateAsync: updateUserFavorites } = useUpdateUserFavorites(); @@ -150,7 +150,7 @@ export const SidebarPrimary = React.memo(() => { items.push(tryGroup(onToggleInviteModal, () => setOpenSupportModal(true))); return items; - }, [isAdmin, isUserRegistered, favorites, currentRoute, onFavoritesReorder]); + }, [isAdmin, isUserRegistered, favorites, currentParentRoute, onFavoritesReorder]); const onCloseSupportModal = useMemoizedFn(() => setOpenSupportModal(false)); @@ -165,7 +165,7 @@ export const SidebarPrimary = React.memo(() => { diff --git a/web/src/components/ui/layouts/PreventNavigation.tsx b/web/src/components/ui/layouts/PreventNavigation.tsx index 8c6c1b8f7..cc65c0255 100644 --- a/web/src/components/ui/layouts/PreventNavigation.tsx +++ b/web/src/components/ui/layouts/PreventNavigation.tsx @@ -44,8 +44,10 @@ export const PreventNavigation: React.FC = React.memo( * @param e The triggered event. */ const handleClick = useMemoizedFn((event: MouseEvent) => { + let originalTarget = event.target as HTMLElement; let target = event.target as HTMLElement; let href: string | null = null; + let originalEvent = event; // Traverse up the DOM tree looking for an anchor tag with href while (target && !href) { @@ -60,11 +62,53 @@ export const PreventNavigation: React.FC = React.memo( event.preventDefault(); event.stopPropagation(); - console.log(target); - + // Store both the target and the original event details confirmationFn.current = () => { - target.click(); - // if (href) router.push(href); + // Remove all click listeners temporarily + document.querySelectorAll('a').forEach((link) => { + link.removeEventListener('click', handleClick); + }); + + // Get all click event handlers on the original target + const clickHandlers = originalTarget.onclick; + + // Temporarily remove our prevention + if (clickHandlers) { + originalTarget.onclick = null; + } + + // Create a new click event + const newEvent = new MouseEvent('click', { + bubbles: true, + cancelable: true, + view: window, + detail: originalEvent.detail, + screenX: originalEvent.screenX, + screenY: originalEvent.screenY, + clientX: originalEvent.clientX, + clientY: originalEvent.clientY, + ctrlKey: originalEvent.ctrlKey, + altKey: originalEvent.altKey, + shiftKey: originalEvent.shiftKey, + metaKey: originalEvent.metaKey, + button: originalEvent.button, + buttons: originalEvent.buttons + }); + + // Dispatch the event directly on the original target + originalTarget.dispatchEvent(newEvent); + + // Restore click handlers + if (clickHandlers) { + originalTarget.onclick = clickHandlers; + } + + // Re-attach our listeners after a short delay + setTimeout(() => { + document.querySelectorAll('a').forEach((link) => { + link.addEventListener('click', handleClick); + }); + }, 0); }; setLeavingPage(true); @@ -79,7 +123,6 @@ export const PreventNavigation: React.FC = React.memo( window.history.pushState(null, document.title, window.location.href); confirmationFn.current = () => { - console.warn('TODO - make sure we can navigate back to the correct page'); router.back(); }; diff --git a/web/src/components/ui/segmented/AppSegmented.tsx b/web/src/components/ui/segmented/AppSegmented.tsx index fc52bf379..75ece2f31 100644 --- a/web/src/components/ui/segmented/AppSegmented.tsx +++ b/web/src/components/ui/segmented/AppSegmented.tsx @@ -131,7 +131,6 @@ export const AppSegmented: AppSegmentedComponent = React.memo( const [isPending, startTransition] = useTransition(); const handleTabClick = useMemoizedFn((value: string) => { - console.log('handleTabClick called with:', value); const item = options.find((item) => item.value === value); if (item && !item.disabled && value !== selectedValue) { setSelectedValue(item.value); @@ -174,6 +173,7 @@ export const AppSegmented: AppSegmentedComponent = React.memo( {isMeasured && ( (props: SegmentedTr const LinkDiv = link ? Link : 'div'; + const handleClick = async (e: React.MouseEvent) => { + if (link) { + e.preventDefault(); + handleTabClick(value); + // Wait for a short duration to allow the animation to complete + await new Promise((resolve) => setTimeout(resolve, 1)); + router.push(link); + } else { + handleTabClick(value); + } + }; + useMount(() => { if (link) { router.prefetch(link); @@ -239,13 +251,12 @@ function SegmentedTriggerComponent(props: SegmentedTr return ( - + handleTabClick(value)} ref={(el) => { if (el) tabRefs.current.set(value, el); }} diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderSegment.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderSegment.tsx index 28242486c..42fabd9b1 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderSegment.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderSegment.tsx @@ -13,7 +13,6 @@ export const MetricContainerHeaderSegment: React.FC = const metricId = useChatLayoutContextSelector((x) => x.metricId) || ''; const onChange = useMemoizedFn((fileView: SegmentedItem) => { - console.log(fileView); onSetFileView({ fileView: fileView.value }); }); diff --git a/web/src/routes/helpers.tsx b/web/src/routes/helpers.tsx index f1045bc7d..7ee6d3376 100644 --- a/web/src/routes/helpers.tsx +++ b/web/src/routes/helpers.tsx @@ -20,11 +20,7 @@ export const pathNameToRoute = (pathName: string, params: any): BusterRoutes => [BusterRoutes.APP_DATASETS_ID_PERMISSIONS_OVERVIEW]: BusterRoutes.APP_DATASETS, [BusterRoutes.APP_DATASETS_ID_OVERVIEW]: BusterRoutes.APP_DATASETS, [BusterRoutes.APP_DATASETS_ID_EDITOR]: BusterRoutes.APP_DATASETS, - [BusterRoutes.APP_TERMS_ID]: BusterRoutes.APP_TERMS, - [BusterRoutes.APP_CHAT_ID_METRIC_ID_CHART]: BusterRoutes.APP_CHAT, - [BusterRoutes.APP_CHAT_ID_METRIC_ID_FILE]: BusterRoutes.APP_CHAT, - [BusterRoutes.APP_CHAT_ID_METRIC_ID_RESULTS]: BusterRoutes.APP_CHAT, - [BusterRoutes.APP_CHAT_ID_DASHBOARD_ID_FILE]: BusterRoutes.APP_CHAT + [BusterRoutes.APP_TERMS_ID]: BusterRoutes.APP_TERMS }; if (route && paramRoutesToParent[route as string]) { @@ -67,7 +63,11 @@ export const pathNameToParentRoute = (pathName: string, params: any): BusterRout [BusterRoutes.SETTINGS_PERMISSION_GROUPS_ID_USERS]: BusterRoutes.SETTINGS_PERMISSION_GROUPS, [BusterRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASET_GROUPS]: BusterRoutes.SETTINGS_PERMISSION_GROUPS, - [BusterRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASETS]: BusterRoutes.SETTINGS_PERMISSION_GROUPS + [BusterRoutes.SETTINGS_PERMISSION_GROUPS_ID_DATASETS]: BusterRoutes.SETTINGS_PERMISSION_GROUPS, + [BusterRoutes.APP_CHAT_ID_METRIC_ID_CHART]: BusterRoutes.APP_CHAT, + [BusterRoutes.APP_CHAT_ID_METRIC_ID_FILE]: BusterRoutes.APP_CHAT, + [BusterRoutes.APP_CHAT_ID_METRIC_ID_RESULTS]: BusterRoutes.APP_CHAT, + [BusterRoutes.APP_CHAT_ID_DASHBOARD_ID_FILE]: BusterRoutes.APP_CHAT }; if (route && paramRoutesToParent[route as string]) {