better filter and match the tabs that should be rendered dynamic (#38199)

fixes: #38078

Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Erik Jan de Wit
2025-03-19 20:56:33 +01:00
committed by GitHub
parent 7e4199e294
commit 7bfceee8fb

View File

@@ -12,10 +12,11 @@ import {
ReactElement,
isValidElement,
} from "react";
import { useTranslation } from "react-i18next";
import {
Path,
generatePath,
matchPath,
matchRoutes,
useHref,
useLocation,
useParams,
@@ -23,8 +24,8 @@ import {
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { PageHandler } from "../../page/PageHandler";
import { TAB_PROVIDER } from "../../page/constants";
import { routes } from "../../routes";
import useIsFeatureEnabled, { Feature } from "../../utils/useIsFeatureEnabled";
import { useTranslation } from "react-i18next";
// TODO: Remove the custom 'children' props and type once the following issue has been resolved:
// https://github.com/patternfly/patternfly-react/issues/6766
@@ -52,27 +53,42 @@ export const RoutableTabs = ({
const isFeatureEnabled = useIsFeatureEnabled();
const { t } = useTranslation();
const matchedTabs = tabs
.filter((tab) => matchPath({ path: tab.metadata.path }, pathname))
.map((t) => ({
...t,
pathname: generatePath(t.metadata.path, {
...params,
...t.metadata.params,
}),
}));
// Extract all keys from matchedTabs
const matchedTabsKeys = matchedTabs.map((t) => t.pathname);
// Extract event keys from children
const eventKeys = Children.toArray(children)
.filter((child): child is ChildElement => isValidElement(child))
.map((child) => child.props.eventKey.toString());
const allKeys = [...eventKeys, ...matchedTabsKeys];
const keyLength = eventKeys[0]?.split("/").length;
const matchedPaths = (matchRoutes(routes, pathname) || []).map(
(match) => match.route.path,
);
// To render a dynamic tab we need to be on the right route, but also have the right number of path segments.
// Otherwise we might render this tab on a sub tab, which is not what we want.
const matchedTabs = tabs
.filter((tab) => {
const tabPath = tab.metadata.path;
return (
matchedPaths.includes(tabPath) &&
tabPath.split("/").length === keyLength
);
})
.map((tab) => {
const tabPath = tab.metadata.path;
const generateTabPath = generatePath(tabPath, {
...params,
...tab.metadata.params,
});
eventKeys.push(generateTabPath);
return {
...tab,
pathname: generateTabPath,
};
});
// Determine if there is an exact match.
const exactMatch = allKeys.find(
const exactMatch = eventKeys.find(
(eventKey) => eventKey === decodeURI(pathname),
);