Skip to content

Commit

Permalink
refactor: use application layout components from react-components.
Browse files Browse the repository at this point in the history
  • Loading branch information
huwshimi committed Jul 4, 2024
1 parent 194fa66 commit 504d097
Show file tree
Hide file tree
Showing 56 changed files with 166 additions and 1,515 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"dependencies": {
"@canonical/jujulib": "7.0.0",
"@canonical/macaroon-bakery": "1.3.2",
"@canonical/react-components": "0.52.0",
"@canonical/react-components": "0.59.0",
"@reduxjs/toolkit": "2.2.4",
"@sentry/browser": "7.114.0",
"ansi-to-html": "0.7.2",
Expand Down
12 changes: 6 additions & 6 deletions src/components/Aside/Aside.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { PropsWithSpread } from "@canonical/react-components";
import { Spinner } from "@canonical/react-components";
import { AppAside, Spinner } from "@canonical/react-components";
import type {
AppAsideProps,
PanelProps,
PropsWithSpread,
} from "@canonical/react-components";
import classnames from "classnames";
import { useAnimate, usePresence } from "framer-motion";
import { useEffect, type PropsWithChildren } from "react";

import { AppAside } from "components/upstream/ApplicationLayout";
import type { AppAsideProps } from "components/upstream/ApplicationLayout/AppAside";
import type { PanelProps } from "components/upstream/Panel";

import "./_aside.scss";

export type Props = PropsWithSpread<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("AuditLogsTablePagination", () => {
const { router } = renderComponent(<AuditLogsTablePagination />, { state });
expect(
screen.getByRole("button", { name: Label.FIRST_PAGE }),
).toBeDisabled();
).toHaveAttribute("aria-disabled");
await userEvent.click(screen.getByRole("button", { name: "Next page" }));
expect(router.state.location.search).toEqual("?page=2");
await userEvent.click(
Expand Down
55 changes: 32 additions & 23 deletions src/components/Panel/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { PropsWithSpread } from "@canonical/react-components";
import { useListener } from "@canonical/react-components";
import { Button, Icon, useListener } from "@canonical/react-components";
import VanillaPanel from "@canonical/react-components/dist/components/Panel";
import classNames from "classnames";
import type { ReactNode, MouseEvent } from "react";
import { forwardRef, useId } from "react";
Expand Down Expand Up @@ -85,28 +86,36 @@ const Panel = forwardRef<HTMLDivElement, Props>(
</>
);
return (
<Aside
{...props}
aria-labelledby={titleId}
role="dialog"
onClose={onRemovePanelQueryParams}
panelProps={{
className: classNames("side-panel", panelClassName),
contentClassName: props.isSplit ? "aside-split-wrapper" : null,
forwardRef: ref,
title: <span id={titleId}>{title}</span>,
}}
>
{props.isSplit ? (
<div className="aside-split-col aside-split-col--left">{content}</div>
) : (
content
)}
{props.isSplit && splitContent ? (
<div className="aside-split-col aside-split-col--right">
<div className="side-panel__split-content">{splitContent}</div>
</div>
) : null}
<Aside {...props} aria-labelledby={titleId} role="dialog">
<VanillaPanel
className={classNames("side-panel", panelClassName)}
controls={
<Button
appearance="base"
className="u-no-margin--bottom"
hasIcon
onClick={onRemovePanelQueryParams}
>
<Icon name="close">Close</Icon>
</Button>
}
contentClassName={props.isSplit ? "aside-split-wrapper" : null}
forwardRef={ref}
title={<span id={titleId}>{title}</span>}
>
{props.isSplit ? (
<div className="aside-split-col aside-split-col--left">
{content}
</div>
) : (
content
)}
{props.isSplit && splitContent ? (
<div className="aside-split-col aside-split-col--right">
<div className="side-panel__split-content">{splitContent}</div>
</div>
) : null}
</VanillaPanel>
</Aside>
);
},
Expand Down
23 changes: 14 additions & 9 deletions src/components/PrimaryNav/PrimaryNav.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { dashboardUpdateAvailable } from "@canonical/jujulib/dist/api/versions";
import { Icon, StatusLabel, Tooltip } from "@canonical/react-components";
import {
Icon,
StatusLabel,
Tooltip,
SideNavigation,
SideNavigationText,
} from "@canonical/react-components";
import type { NavItem } from "@canonical/react-components/dist/components/SideNavigation/SideNavigation";
import type { HTMLProps, ReactNode } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useSelector } from "react-redux";
import type { NavLinkProps } from "react-router-dom";
import { NavLink } from "react-router-dom";

import UserMenu from "components/UserMenu";
import SideNavigation, {
SideNavigationText,
} from "components/upstream/SideNavigation";
import type { NavItem } from "components/upstream/SideNavigation/SideNavigation";
import UserMenu from "components/UserMenu/UserMenu";
import { DARK_THEME } from "consts";
import {
getAppVersion,
Expand Down Expand Up @@ -142,12 +145,14 @@ const PrimaryNav = () => {
<span className="version">Version {appVersion}</span>
</SideNavigationText>,
];
const groupedItems: NavItem<NavLinkProps | HTMLProps<HTMLAnchorElement>>[][] =
[navigation, extraNav];

return (
<>
<SideNavigation dark={DARK_THEME} items={groupedItems} />
<SideNavigation<NavLinkProps | HTMLProps<HTMLAnchorElement>>
dark={DARK_THEME}
items={[{ items: navigation }, { items: extraNav }]}
className="p-primary-nav"
/>
<UserMenu />
</>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/PrimaryNav/_primary-nav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
@import "vanilla-framework/scss/vanilla";
@import "../../scss/breakpoints";

.p-primary-nav {
.l-navigation__drawer > .p-panel {
// Required so that the user menu can be absolutely positioned within the
// side nav.
position: relative;
}

.p-primary-nav {
.entity-count {
border-radius: 50%;
display: inline-block;
Expand Down
85 changes: 46 additions & 39 deletions src/components/UserMenu/UserMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Button, Icon } from "@canonical/react-components";
import {
Button,
Icon,
SideNavigation,
SideNavigationText,
} from "@canonical/react-components";
import { unwrapResult } from "@reduxjs/toolkit";
import classNames from "classnames";
import { useEffect, useState } from "react";
import reactHotToast from "react-hot-toast";
import { Link } from "react-router-dom";

import ToastCard from "components/ToastCard";
import SideNavigation from "components/upstream/SideNavigation";
import { SideNavigationText } from "components/upstream/SideNavigation";
import { DARK_THEME } from "consts";
import useAnalytics from "hooks/useAnalytics";
import { thunks as appThunks } from "store/app";
Expand Down Expand Up @@ -51,43 +54,47 @@ const UserMenu = () => {
dark={DARK_THEME}
hasIcons
items={[
<SideNavigationText
icon="user"
key="user"
className="user-menu__toggle"
onClick={toggleUserMenuActive}
onKeyUp={toggleUserMenuActive}
role="button"
tabIndex={0}
status={<Icon name="chevron-up" light />}
>
{activeUser ? extractOwnerName(activeUser) : ""}
</SideNavigationText>,
{
component: Link,
to: urls.index,
label: "Log out",
onClick: () => {
dispatch(appThunks.logOut())
.then(unwrapResult)
.catch((error) => {
reactHotToast.custom((t) => (
<ToastCard toastInstance={t} type="negative">
<>
{Label.LOGOUT_ERROR} Try{" "}
<Button
appearance="link"
onClick={() => window.location.reload()}
>
refreshing
</Button>{" "}
the page.
</>
</ToastCard>
));
console.error(Label.LOGOUT_ERROR, error);
});
},
items: [
<SideNavigationText
icon="user"
key="user"
className="user-menu__toggle"
onClick={toggleUserMenuActive}
onKeyUp={toggleUserMenuActive}
role="button"
tabIndex={0}
status={<Icon name="chevron-up" light />}
>
{activeUser ? extractOwnerName(activeUser) : ""}
</SideNavigationText>,
{
component: Link,
to: urls.index,
label: "Log out",
onClick: () => {
dispatch(appThunks.logOut())
.then(unwrapResult)
.catch((error) => {
reactHotToast.custom((t) => (
<ToastCard toastInstance={t} type="negative">
<>
{Label.LOGOUT_ERROR} Try{" "}
<Button
appearance="link"
onClick={() => window.location.reload()}
>
refreshing
</Button>{" "}
the page.
</>
</ToastCard>
));
console.error(Label.LOGOUT_ERROR, error);
});
},
},
],
},
]}
/>
Expand Down
10 changes: 6 additions & 4 deletions src/components/secrets/SecretForm/Fields/Fields.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ describe("Fields", () => {
<Fields />
</Formik>,
);
expect(screen.getByRole("button", { name: Label.REMOVE })).toBeDisabled();
expect(screen.getByRole("button", { name: Label.REMOVE })).toHaveAttribute(
"aria-disabled",
);
});

it("allows you to remove pairs if there are more than one", async () => {
Expand All @@ -73,10 +75,10 @@ describe("Fields", () => {
);
await userEvent.click(screen.getByRole("button", { name: Label.ADD }));
const removeButtons = screen.getAllByRole("button", { name: Label.REMOVE });
expect(removeButtons[0]).not.toBeDisabled();
expect(removeButtons[1]).not.toBeDisabled();
expect(removeButtons[0]).not.toHaveAttribute("aria-disabled");
expect(removeButtons[1]).not.toHaveAttribute("aria-disabled");
await userEvent.click(removeButtons[1]);
expect(removeButtons[0]).toBeDisabled();
expect(removeButtons[0]).toHaveAttribute("aria-disabled");
});

it("displays an auto-prune option when editing", async () => {
Expand Down

This file was deleted.

59 changes: 0 additions & 59 deletions src/components/upstream/ApplicationLayout/AppAside/AppAside.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions src/components/upstream/ApplicationLayout/AppAside/index.ts

This file was deleted.

11 changes: 0 additions & 11 deletions src/components/upstream/ApplicationLayout/AppMain/AppMain.test.tsx

This file was deleted.

Loading

0 comments on commit 504d097

Please sign in to comment.