better prevent navigation logic

This commit is contained in:
Nate Kelley 2025-04-01 15:31:21 -06:00
parent f915e4caea
commit d9bc8d4741
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 71 additions and 19 deletions

View File

@ -24,7 +24,6 @@ const SplitterContent: React.FC<{
isSaving: boolean;
open: boolean;
}> = React.memo(({ onReset, onSave, isSaving, open }) => {
console.log(open);
return (
<React.Fragment>
<div className="flex w-full items-center space-x-2.5">

View File

@ -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(() => {
<Sidebar
content={sidebarItems}
header={HeaderMemoized}
activeItem={currentRoute}
activeItem={currentParentRoute}
footer={FooterMemoized}
/>

View File

@ -44,8 +44,10 @@ export const PreventNavigation: React.FC<PreventNavigationProps> = 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<PreventNavigationProps> = 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<PreventNavigationProps> = 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();
};

View File

@ -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(
<Tabs.Root
ref={rootRef}
value={selectedValue as string}
// onValueChange={handleTabClick}
className={cn(segmentedVariants({ block, type }), heightVariants({ size }), className)}>
{isMeasured && (
<motion.div
@ -231,6 +231,18 @@ function SegmentedTriggerComponent<T extends string = string>(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<T extends string = string>(props: SegmentedTr
return (
<Tooltip title={tooltip || ''} sideOffset={10} delayDuration={150}>
<LinkDiv href={link || ''}>
<LinkDiv href={link || ''} onClick={handleClick}>
<Tabs.Trigger
key={value}
value={value}
disabled={disabled}
asChild
onClick={() => handleTabClick(value)}
ref={(el) => {
if (el) tabRefs.current.set(value, el);
}}

View File

@ -13,7 +13,6 @@ export const MetricContainerHeaderSegment: React.FC<FileContainerSegmentProps> =
const metricId = useChatLayoutContextSelector((x) => x.metricId) || '';
const onChange = useMemoizedFn((fileView: SegmentedItem<FileView>) => {
console.log(fileView);
onSetFileView({ fileView: fileView.value });
});

View File

@ -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]) {