Skip to content

Commit

Permalink
feat(vault): Display warning icon next to controller nav link if not …
Browse files Browse the repository at this point in the history
…all region controllers are configured with Vault (#4504)

- Add warning icon next to controller nav link if not all region controllers are configured with Vault
- Add test to check if icon is displayed or not
  • Loading branch information
ndv99 authored Oct 20, 2022
1 parent ce46036 commit a3e3917
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 8 deletions.
34 changes: 34 additions & 0 deletions src/app/base/components/Header/Header.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
authState as authStateFactory,
config as configFactory,
configState as configStateFactory,
controller as controllerFactory,
controllerState as controllerStateFactory,
rootState as rootStateFactory,
user as userFactory,
userState as userStateFactory,
Expand All @@ -39,6 +41,9 @@ beforeEach(() => {
],
loaded: true,
}),
controller: controllerStateFactory({
items: [controllerFactory()],
}),
user: userStateFactory({
auth: authStateFactory({
user: userFactory({
Expand Down Expand Up @@ -218,6 +223,35 @@ it("highlights sub-urls", () => {
expect(currentMenuItem).toHaveTextContent("Machines");
});

it("displays a warning icon next to controllers if vault is not fully configured", () => {
state.controller.items = [
controllerFactory({ vault_configured: true }),
controllerFactory({ vault_configured: false }),
];
renderWithBrowserRouter(<Header />, { route: "/", wrapperProps: { state } });

const controllerLink = screen.getByRole("link", {
name: "warning Controllers",
});
const warningIcon = within(controllerLink).getByTestId("warning-icon");
expect(warningIcon).toHaveClass(
"p-navigation--item-icon p-icon--security-warning-grey"
);
});

it("does not display a warning icon next to controllers if vault is fully configured", () => {
state.controller.items = [
controllerFactory({ vault_configured: true }),
controllerFactory({ vault_configured: true }),
];
renderWithBrowserRouter(<Header />, { route: "/", wrapperProps: { state } });

const controllerLink = screen.getByRole("link", { name: "Controllers" });
expect(
within(controllerLink).queryByTestId("warning-icon")
).not.toBeInTheDocument();
});

it("links from the logo to the dashboard for admins", () => {
state.user.auth.user = userFactory({ is_superuser: true });
renderWithBrowserRouter(<Header />, {
Expand Down
62 changes: 54 additions & 8 deletions src/app/base/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useContext } from "react";

import type { NavLink } from "@canonical/react-components";
import {
Icon,
isNavigationButton,
Theme,
Navigation,
Expand All @@ -26,6 +27,9 @@ import ThemePreviewContext from "app/base/theme-preview-context";
import urls from "app/base/urls";
import authSelectors from "app/store/auth/selectors";
import configSelectors from "app/store/config/selectors";
import { actions as controllerActions } from "app/store/controller";
import controllerSelectors from "app/store/controller/selectors";
import type { RootState } from "app/store/root/types";
import { actions as statusActions } from "app/store/status";

type NavItem = {
Expand Down Expand Up @@ -137,11 +141,17 @@ const isSelected = (path: string, link: NavItem) => {
);
};

const generateItems = (
links: NavItem[],
path: string,
forHardwareMenu: boolean
) => {
const generateItems = ({
links,
path,
forHardwareMenu,
vaultIncomplete,
}: {
links: NavItem[];
path: string;
forHardwareMenu: boolean;
vaultIncomplete: boolean;
}) => {
if (forHardwareMenu) {
// Only include the items for the hardware menu.
links = links.filter((link) => link.inHardwareMenu);
Expand All @@ -155,7 +165,21 @@ const generateItems = (
}),
isSelected: isSelected(path, link),
key: link.url,
label: link.label,
label:
link.label === "Controllers" && vaultIncomplete ? ( // check if vault is set up on all controllers
<>
<Icon
aria-label="warning"
className="p-navigation--item-icon"
data-testid="warning-icon"
name="security-warning-grey"
/>
{link.label}
{/** Display a warning icon if setup is incomplete */}
</>
) : (
link.label
),
url: link.url,
}));
};
Expand Down Expand Up @@ -203,6 +227,18 @@ export const Header = (): JSX.Element => {
setTheme(maasTheme ? maasTheme : "default");
}, [location, maasTheme, setTheme]);

useEffect(() => {
dispatch(controllerActions.fetch());
}, [dispatch]);

const { unconfiguredControllers, configuredControllers } = useSelector(
(state: RootState) =>
controllerSelectors.getVaultConfiguredControllers(state)
);

const vaultIncomplete =
unconfiguredControllers.length >= 1 && configuredControllers.length >= 1;

// Hide the navigation items when the user is not authenticated or hasn't been
// through the intro process.
const showLinks = isAuthenticated && completedIntro && completedUserIntro;
Expand Down Expand Up @@ -233,10 +269,20 @@ export const Header = (): JSX.Element => {
? [
{
className: "p-navigation__hardware-menu",
items: generateItems(links, path, true),
items: generateItems({
links: links,
path: path,
forHardwareMenu: true,
vaultIncomplete: vaultIncomplete,
}),
label: "Hardware",
},
...generateItems(links, path, false),
...generateItems({
links: links,
path: path,
forHardwareMenu: false,
vaultIncomplete: vaultIncomplete,
}),
]
: null
}
Expand Down
4 changes: 4 additions & 0 deletions src/app/base/components/Header/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,8 @@
.p-navigation--red {
background-color: #A71B33 !important;
}

.p-navigation--item-icon {
margin-right: $sph--small;
}
}

0 comments on commit a3e3917

Please sign in to comment.