Skip to content

Commit

Permalink
feat: tag management panel MAASENG-1427
Browse files Browse the repository at this point in the history
  • Loading branch information
petermakowski committed Jul 13, 2023
1 parent fa6eebb commit 053c192
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 170 deletions.
6 changes: 4 additions & 2 deletions src/app/base/components/AppSidePanel/AppSidePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import type { ReactNode } from "react";
import { Col, Row, useOnEscapePressed } from "@canonical/react-components";
import classNames from "classnames";

import type { SidePanelSize } from "app/base/side-panel-context";
import { useSidePanel } from "app/base/side-panel-context";

type Props = {
title?: string | null;
size?: "wide" | "default" | "narrow";
size?: SidePanelSize;
content?: ReactNode;
};

Expand All @@ -23,8 +24,9 @@ const AppSidePanel = ({
aria-label={title ?? undefined}
className={classNames("l-aside", {
"is-collapsed": !content,
"is-wide": size === "wide",
"is-narrow": size === "narrow",
"is-large": size === "large",
"is-wide": size === "wide",
})}
data-testid="section-header-content"
id="aside-panel"
Expand Down
3 changes: 2 additions & 1 deletion src/app/base/components/PageContent/PageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Footer from "../Footer";
import MainContentSection from "../MainContentSection";
import SecondaryNavigation from "../SecondaryNavigation";

import { useSidePanel } from "app/base/side-panel-context";
import { useThemeContext } from "app/base/theme-context";
import { preferencesNavItems } from "app/preferences/constants";
import { settingsNavItems } from "app/settings/constants";
Expand All @@ -28,7 +29,6 @@ const PageContent = ({
sidebar,
isNotificationListHidden = false,
sidePanelContent,
sidePanelSize,
sidePanelTitle,
...props
}: Props): JSX.Element => {
Expand All @@ -37,6 +37,7 @@ const PageContent = ({
const isPreferencesPage = matchPath("account/prefs/*", pathname);
const isSideNavVisible = isSettingsPage || isPreferencesPage;
const { theme } = useThemeContext();
const { sidePanelSize } = useSidePanel();

return (
<>
Expand Down
28 changes: 24 additions & 4 deletions src/app/base/side-panel-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,38 @@ export type SidePanelContent =

export type SetSidePanelContent = (sidePanelContent: SidePanelContent) => void;

export type SidePanelSize = "narrow" | "regular" | "large" | "wide";
export type SidePanelContextType<T = SidePanelContent> = {
sidePanelContent: T;
sidePanelSize: SidePanelSize;
};

export type SetSidePanelContextType = {
setSidePanelContent: SetSidePanelContent;
setSidePanelSize: (size: SidePanelSize) => void;
};

const SidePanelContext = createContext<SidePanelContextType>({
sidePanelContent: null,
sidePanelSize: "regular",
});

const SetSidePanelContext = createContext<SetSidePanelContextType>({
setSidePanelContent: () => {},
setSidePanelSize: () => {},
});

const useSidePanelContext = (): SidePanelContextType =>
useContext(SidePanelContext);
const useSetSidePanelContext = (): SetSidePanelContextType =>
// TODO: remove this export
export const useSetSidePanelContext = (): SetSidePanelContextType =>
useContext(SetSidePanelContext);

// TODO: move set side panel size to separate context
export const useSidePanel = (): SidePanelContextType &
SetSidePanelContextType => {
const { sidePanelContent } = useSidePanelContext();
const { setSidePanelContent } = useSetSidePanelContext();
const { sidePanelSize, sidePanelContent } = useSidePanelContext();
const { setSidePanelContent, setSidePanelSize } = useSetSidePanelContext();
const { pathname } = useLocation();
const previousPathname = usePrevious(pathname);

Expand All @@ -78,7 +85,17 @@ export const useSidePanel = (): SidePanelContextType &
return () => setSidePanelContent(null);
}, [setSidePanelContent]);

return { sidePanelContent, setSidePanelContent };
// reset side panel size to defaul on unmount
useEffect(() => {
return () => setSidePanelSize("regular");
}, [setSidePanelSize]);

return {
sidePanelContent,
setSidePanelContent,
sidePanelSize,
setSidePanelSize,
};
};

const SidePanelContextProvider = ({
Expand All @@ -87,16 +104,19 @@ const SidePanelContextProvider = ({
}: PropsWithChildren<{ value?: SidePanelContent }>): React.ReactElement => {
const [sidePanelContent, setSidePanelContent] =
useState<SidePanelContent>(value);
const [sidePanelSize, setSidePanelSize] = useState<SidePanelSize>("regular");

return (
<SetSidePanelContext.Provider
value={{
setSidePanelContent,
setSidePanelSize,
}}
>
<SidePanelContext.Provider
value={{
sidePanelContent,
sidePanelSize,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type Props = {
onTagCreated: (tag: Tag) => void;
viewingDetails?: boolean;
viewingMachineConfig?: boolean;
onCancel?: () => void;
} & Partial<MachineActionFormProps>;

export const AddTagForm = ({
Expand All @@ -17,6 +18,7 @@ export const AddTagForm = ({
searchFilter,
viewingDetails,
viewingMachineConfig,
onCancel,
}: Props): JSX.Element => {
let location = "list";
if (viewingMachineConfig) {
Expand All @@ -37,6 +39,7 @@ export const AddTagForm = ({
: `${count} selected machines are deployed. The new kernel options will not be applied to these machines until they are redeployed.`
}
name={name}
onCancel={onCancel}
onSaveAnalytics={{
action: "Manual tag created",
category: `Machine ${location} create tag form`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,11 @@ it("discards added tags", async () => {
});

it("displays a tag details modal when chips are clicked", async () => {
tags[0].name = "tag1";
tags[0].machine_count = 2;
const expectedTag = tags[0];
expectedTag.name = "tag1";
expectedTag.machine_count = 2;
const store = mockStore(state);
const handleToggleTagDetails = jest.fn();
render(
<Provider store={store}>
<MemoryRouter>
Expand All @@ -181,14 +183,21 @@ it("displays a tag details modal when chips are clicked", async () => {
initialValues={{ added: [], removed: [] }}
onSubmit={jest.fn()}
>
<TagFormChanges newTags={[]} selectedCount={2} tags={tags} />
<TagFormChanges
newTags={[]}
selectedCount={2}
tags={tags}
toggleTagDetails={handleToggleTagDetails}
/>
</Formik>
</CompatRouter>
</MemoryRouter>
</Provider>
);
await userEvent.click(screen.getByRole("button", { name: "tag1 (2/2)" }));
expect(screen.getByRole("dialog", { name: "tag1" })).toBeInTheDocument();
await userEvent.click(
screen.getByRole("button", { name: `${expectedTag.name} (2/2)` })
);
expect(handleToggleTagDetails).toHaveBeenCalledWith(expectedTag);
});

it("can remove manual tags", async () => {
Expand Down
Loading

0 comments on commit 053c192

Please sign in to comment.