Skip to content

Commit

Permalink
fix: settings top padding (#5319)
Browse files Browse the repository at this point in the history
  • Loading branch information
petermakowski committed Feb 22, 2024
1 parent 7a91c70 commit 352f85c
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,7 @@ import MainContentSection from "./MainContentSection";

import { renderWithMockStore, screen, within } from "@/testing/utils";

it("renders sidebar", () => {
renderWithMockStore(
<MainContentSection header="Settings" sidebar={<div>Sidebar</div>}>
content
</MainContentSection>
);
expect(screen.getByRole("complementary")).toBeInTheDocument();
});

it("renders without a sidebar", () => {
it("renders", () => {
renderWithMockStore(
<MainContentSection header="Settings">content</MainContentSection>
);
Expand Down
20 changes: 2 additions & 18 deletions src/app/base/components/MainContentSection/MainContentSection.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import type { HTMLProps, ReactNode } from "react";

import { Col, Row } from "@canonical/react-components";
import type { ColSize } from "@canonical/react-components";
import classNames from "classnames";

import NotificationList from "@/app/base/components/NotificationList";
import { COL_SIZES } from "@/app/base/constants";

export type Props = {
children?: ReactNode;
Expand All @@ -19,11 +16,8 @@ export const MAIN_CONTENT_SECTION_ID = "main-content-section";
const MainContentSection = ({
children,
header,
sidebar,
isNotificationListHidden = false,
...props
}: Props): JSX.Element => {
const { SIDEBAR, TOTAL } = COL_SIZES;
return (
<div {...props} id={MAIN_CONTENT_SECTION_ID}>
<div>
Expand All @@ -33,18 +27,8 @@ const MainContentSection = ({
</header>
) : null}
<Row>
{sidebar && (
<Col className="section__sidebar" element="aside" size={SIDEBAR}>
{sidebar}
</Col>
)}
<Col
className={classNames({
"u-nudge-down": !isNotificationListHidden,
})}
size={(sidebar ? TOTAL - SIDEBAR : TOTAL) as ColSize}
>
{!isNotificationListHidden && <NotificationList />}
<Col size={12}>
<NotificationList />
{children}
</Col>
</Row>
Expand Down
22 changes: 22 additions & 0 deletions src/app/base/components/NotificationList/NotificationList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,4 +208,26 @@ describe("NotificationList", () => {
).not.toBeInTheDocument();
expect(screen.queryByTestId("notification-count")).not.toBeInTheDocument();
});

it("applies the correct className when has content", () => {
const notificationsWithContent = [
notificationFactory({
id: 1,
category: NotificationCategory.INFO,
message: "Informational message",
}),
];
const stateWithContent = rootStateFactory({
notification: notificationStateFactory({
items: notificationsWithContent,
}),
});

const store = mockStore(stateWithContent);
const { container } = renderWithBrowserRouter(<NotificationList />, {
route: "/machines",
store,
});
expect(container.firstChild).toHaveClass("u-nudge-down");
});
});
53 changes: 33 additions & 20 deletions src/app/base/components/NotificationList/NotificationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
Notification,
NotificationSeverity,
} from "@canonical/react-components";
import classNames from "classnames";
import { useDispatch, useSelector } from "react-redux";
import type { Dispatch } from "redux";

import NotificationGroup from "@/app/base/components/NotificationGroup";
import NotificationGroupNotification from "@/app/base/components/NotificationGroup/Notification";
Expand All @@ -14,21 +14,28 @@ import type { Message } from "@/app/store/message/types";
import { actions as notificationActions } from "@/app/store/notification";
import notificationSelectors from "@/app/store/notification/selectors";

const generateMessages = (messages: Message[], dispatch: Dispatch) =>
messages.map(({ id, message, severity, temporary }) => (
<Notification
data-testid="message"
key={id}
onDismiss={() => dispatch(messageActions.remove(id))}
severity={severity}
timeout={temporary ? 5000 : undefined}
>
{message}
</Notification>
));
const Messages = ({ messages }: { messages: Message[] }) => {
const dispatch = useDispatch();

const NotificationList = (): JSX.Element => {
const messages = useSelector(messageSelectors.all);
return (
<>
{messages.map(({ id, message, severity, temporary }) => (
<Notification
data-testid="message"
key={id}
onDismiss={() => dispatch(messageActions.remove(id))}
severity={severity}
timeout={temporary ? 5000 : undefined}
>
{message}
</Notification>
))}
</>
);
};

export const useNotifications = () => {
useFetchActions([notificationActions.fetch]);

const notifications = {
warnings: {
Expand All @@ -49,12 +56,18 @@ const NotificationList = (): JSX.Element => {
},
};

const dispatch = useDispatch();
return notifications;
};

useFetchActions([notificationActions.fetch]);
const NotificationList = (): JSX.Element => {
const notifications = useNotifications();
const messages = useSelector(messageSelectors.all);
const messageCount = useSelector(messageSelectors.count);
const notificationCount = useSelector(notificationSelectors.count);
const hasContent = messageCount > 0 || notificationCount > 0;

return (
<>
<div className={classNames({ "u-nudge-down": hasContent })}>
{Object.values(notifications).map((group) => {
const items = group.items;
const severity = group.severity;
Expand All @@ -77,8 +90,8 @@ const NotificationList = (): JSX.Element => {
}
return null;
})}
{generateMessages(messages, dispatch)}
</>
<Messages messages={messages} />
</div>
);
};

Expand Down
7 changes: 1 addition & 6 deletions src/app/base/components/PageContent/PageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const PageContent = ({
children,
header,
sidebar,
isNotificationListHidden = false,
sidePanelContent,
sidePanelTitle,
...props
Expand Down Expand Up @@ -70,11 +69,7 @@ const PageContent = ({
</div>
) : null}
<div className="l-main__content" id="main-content">
<MainContentSection
header={header}
isNotificationListHidden={isNotificationListHidden}
{...props}
>
<MainContentSection header={header} {...props}>
<ErrorBoundary>{children}</ErrorBoundary>
</MainContentSection>
</div>
Expand Down
14 changes: 14 additions & 0 deletions src/app/store/message/selectors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,18 @@ describe("messages", () => {
expect(items.length).toEqual(1);
expect(items[0].message).toEqual("User added");
});

it("can get the count of messages", () => {
const state = rootStateFactory({
message: messageStateFactory({
items: [
messageFactory({
message: "User added",
}),
],
}),
});
const count = messages.count(state);
expect(count).toEqual(1);
});
});
4 changes: 3 additions & 1 deletion src/app/store/message/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type { RootState } from "@/app/store/root/types";
*/
const all = (state: RootState): Message[] => state.message.items;

const messages = { all };
const count = (state: RootState): number => state.message.items.length;

const messages = { all, count };

export default messages;

0 comments on commit 352f85c

Please sign in to comment.