diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0bd842452..dc52916fa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Close file lists in migration ([#1191](https://github.com/scm-manager/scm-manager/pull/1191))
- Use command in javahg.py from registrar (Upgrade to newer javahg version) ([#1192](https://github.com/scm-manager/scm-manager/pull/1192))
- Fixed wrong e-tag format ([sdorra/web-resource #1](https://github.com/sdorra/web-resources/pull/1))
+- Fixed active state of sub navigation items, which are using activeWhenMatch
- Handles repositories in custom directories correctly in migration from 1.x ([#1201](https://github.com/scm-manager/scm-manager/pull/1201))
- Usage of short git commit ids in changeset urls ([#1200](https://github.com/scm-manager/scm-manager/pull/1200))
diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap
index 4be4a8a349..4ab1158583 100644
--- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap
+++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap
@@ -40777,6 +40777,68 @@ exports[`Storyshots Modal|Modal Default 1`] = `
`;
+exports[`Storyshots Navigation|Secondary Active when match 1`] = `
+
= ({ to, activeOnlyWhenExact, icon, label, title }) => {
- const match = useRouteMatch({
- path: to,
- exact: activeOnlyWhenExact
- });
+const NavLink: FC = ({ to, activeWhenMatch, activeOnlyWhenExact, icon, label, title }) => {
+ const active = useActiveMatch({to, activeWhenMatch, activeOnlyWhenExact});
const context = useMenuContext();
const collapsed = context.isCollapsed();
@@ -54,7 +52,7 @@ const NavLink: FC = ({ to, activeOnlyWhenExact, icon, label, title }) =>
return (
-
+
{showIcon}
{collapsed ? null : label}
diff --git a/scm-ui/ui-components/src/navigation/SecondaryNavigation.stories.tsx b/scm-ui/ui-components/src/navigation/SecondaryNavigation.stories.tsx
index 73531dcb18..715e566cd2 100644
--- a/scm-ui/ui-components/src/navigation/SecondaryNavigation.stories.tsx
+++ b/scm-ui/ui-components/src/navigation/SecondaryNavigation.stories.tsx
@@ -86,4 +86,18 @@ storiesOf("Navigation|Secondary", module)
);
- });
+ })
+ .add("Active when match", () =>
+ withRoute("/hog")(
+
+
+ route.location.pathname === "/hog"}
+ to="/heart-of-gold"
+ icon="fas fa-star"
+ label="Heart Of Gold"
+ title="Heart Of Gold"
+ />
+
+ )
+ );
diff --git a/scm-ui/ui-components/src/navigation/SubNavigation.tsx b/scm-ui/ui-components/src/navigation/SubNavigation.tsx
index 56a6c438d3..1e831536ee 100644
--- a/scm-ui/ui-components/src/navigation/SubNavigation.tsx
+++ b/scm-ui/ui-components/src/navigation/SubNavigation.tsx
@@ -22,10 +22,11 @@
* SOFTWARE.
*/
import React, { FC, useContext } from "react";
-import { Link, useRouteMatch } from "react-router-dom";
+import { Link, useRouteMatch, useLocation } from "react-router-dom";
import classNames from "classnames";
import useMenuContext, { MenuContext } from "./MenuContext";
import { RoutingProps } from "./RoutingProps";
+import useActiveMatch from "./useActiveMatch";
type Props = RoutingProps & {
label: string;
@@ -33,18 +34,19 @@ type Props = RoutingProps & {
icon?: string;
};
-const SubNavigation: FC = ({ to, activeOnlyWhenExact, icon, title, label, children }) => {
+const SubNavigation: FC = ({ to, activeOnlyWhenExact, activeWhenMatch, icon, title, label, children }) => {
+ const context = useMenuContext();
+ const collapsed = context.isCollapsed();
+
const parents = to.split("/");
parents.splice(-1, 1);
const parent = parents.join("/");
- const match = useRouteMatch({
- path: parent,
- exact: activeOnlyWhenExact
- });
-
- const context = useMenuContext();
- const collapsed = context.isCollapsed();
+ const active = useActiveMatch({
+ to: parent,
+ activeOnlyWhenExact,
+ activeWhenMatch
+ })
let defaultIcon = "fas fa-cog";
if (icon) {
@@ -52,13 +54,13 @@ const SubNavigation: FC = ({ to, activeOnlyWhenExact, icon, title, label,
}
let childrenList = null;
- if (match && !collapsed) {
+ if (active && !collapsed) {
childrenList =
{children}
;
}
return (
-
+
{collapsed ? "" : label}
{childrenList}
diff --git a/scm-ui/ui-components/src/navigation/useActiveMatch.ts b/scm-ui/ui-components/src/navigation/useActiveMatch.ts
new file mode 100644
index 0000000000..1ff949d8aa
--- /dev/null
+++ b/scm-ui/ui-components/src/navigation/useActiveMatch.ts
@@ -0,0 +1,48 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020-present Cloudogu GmbH and Contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import {useLocation, useRouteMatch} from "react-router-dom";
+import {RoutingProps} from "./RoutingProps";
+
+const useActiveMatch = ({to, activeOnlyWhenExact, activeWhenMatch}: RoutingProps) => {
+ const match = useRouteMatch({
+ path: to,
+ exact: activeOnlyWhenExact
+ });
+
+ const location = useLocation();
+
+ const isActiveWhenMatch = () => {
+ if (activeWhenMatch) {
+ return activeWhenMatch({
+ location
+ });
+ }
+ return false;
+ };
+
+ return !!match || isActiveWhenMatch();
+};
+
+export default useActiveMatch;