simplify TeamsDropdown component and update ManageHostPage to keep po… (#7606)

* simplify TeamsDropdown component and update ManageHostPage to keep policy filter across team change

* fix TeamDropdown for users not on global team
This commit is contained in:
Gabriel Hernandez
2022-09-12 16:18:12 +01:00
committed by GitHub
parent 5614ab2501
commit eb06ef8049
8 changed files with 145 additions and 60 deletions
@@ -0,0 +1 @@
- keep policy filter on Manage Hosts Page changes across a team changes
@@ -0,0 +1,82 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { noop } from "lodash";
import { renderWithAppContext } from "test/test-utils";
import TeamsDropdown from "./TeamsDropdown";
describe("TeamsDropdown - component", () => {
const USER_TEAMS = [
{ id: 1, name: "Team 1" },
{ id: 2, name: "Team 2" },
];
it("renders the given selected team from selectedTeamId", () => {
render(
<TeamsDropdown
currentUserTeams={USER_TEAMS}
selectedTeamId={1}
onChange={noop}
/>
);
const selectedTeam = screen.getByText("Team 1");
expect(selectedTeam).toBeInTheDocument();
});
it("renders the first team option when includeAll is false and when no selectedTeamId is given", () => {
render(
<TeamsDropdown
currentUserTeams={USER_TEAMS}
includeAll={false}
onChange={noop}
/>
);
const selectedTeam = screen.getByText("Team 1");
expect(selectedTeam).toBeInTheDocument();
});
describe("user is on the global team", () => {
const contextValue = {
isOnGlobalTeam: true,
};
it("renders 'All teams' when no selectedTeamId is given", () => {
renderWithAppContext(
<TeamsDropdown currentUserTeams={USER_TEAMS} onChange={noop} />,
{ contextValue }
);
const selectedTeam = screen.getByText("All teams");
expect(selectedTeam).toBeInTheDocument();
});
it("renders the first team option when includeAll is false and when no selectedTeamId is given", () => {
renderWithAppContext(
<TeamsDropdown
currentUserTeams={USER_TEAMS}
includeAll={false}
onChange={noop}
/>,
{ contextValue }
);
const selectedTeam = screen.getByText("Team 1");
expect(selectedTeam).toBeInTheDocument();
});
});
describe("user is not on the global team", () => {
const contextValue = { isOnGlobalTeam: false };
it("renders the first team when no selectedTeamId is given", () => {
renderWithAppContext(
<TeamsDropdown currentUserTeams={USER_TEAMS} onChange={noop} />,
{ contextValue }
);
expect(screen.getByText("Team 1")).toBeInTheDocument();
});
});
});
@@ -1,14 +1,14 @@
import React, { useContext, useMemo } from "react";
import classnames from "classnames";
import { AppContext } from "context/app";
import { ITeamSummary } from "interfaces/team";
// @ts-ignore
import Dropdown from "components/forms/fields/Dropdown";
import { AppContext } from "context/app";
const generateDropdownOptions = (
teams: ITeamSummary[] | undefined,
includeAll: boolean | undefined
includeAll: boolean
) => {
if (!teams) {
return [];
@@ -30,12 +30,10 @@ const generateDropdownOptions = (
return options;
};
interface ITeamsDropdownProps {
currentUserTeams: ITeamSummary[];
selectedTeamId: number;
includeAll?: boolean; // Include "All Teams" option for all users
disableAll?: boolean; // Disable "All Teams" option for global users
selectedTeamId?: number;
includeAll?: boolean; // Include the "All Teams" option;
isDisabled?: boolean;
onChange: (newSelectedValue: number) => void;
onOpen?: () => void;
@@ -47,22 +45,18 @@ const baseClass = "component__team-dropdown";
const TeamsDropdown = ({
currentUserTeams,
selectedTeamId,
includeAll = false,
disableAll = false,
includeAll = true,
isDisabled,
onChange,
onOpen,
onClose,
}: ITeamsDropdownProps): JSX.Element => {
const { isOnGlobalTeam } = useContext(AppContext);
const { isOnGlobalTeam = false } = useContext(AppContext);
const teamOptions = useMemo(
() =>
generateDropdownOptions(
currentUserTeams,
(isOnGlobalTeam && !disableAll) || includeAll
),
[currentUserTeams, isOnGlobalTeam]
generateDropdownOptions(currentUserTeams, includeAll && isOnGlobalTeam),
[currentUserTeams, includeAll, isOnGlobalTeam]
);
const selectedValue = teamOptions.find(
@@ -24,7 +24,7 @@ interface IAutoSizeInputFieldProps {
const baseClass = "component__auto-size-input-field";
const TeamsDropdown = ({
const AutoSizeInputField = ({
name,
placeholder,
value,
@@ -102,4 +102,4 @@ const TeamsDropdown = ({
);
};
export default TeamsDropdown;
export default AutoSizeInputField;
+21 -21
View File
@@ -57,32 +57,32 @@ type Props = {
};
type InitialStateType = {
availableTeams: ITeamSummary[] | undefined;
availableTeams?: ITeamSummary[];
config: IConfig | null;
currentUser: IUser | null;
currentTeam: ITeamSummary | undefined;
currentTeam?: ITeamSummary;
enrollSecret: IEnrollSecret[] | null;
isPreviewMode: boolean | undefined;
isSandboxMode: boolean | undefined;
isFreeTier: boolean | undefined;
isPremiumTier: boolean | undefined;
isGlobalAdmin: boolean | undefined;
isGlobalMaintainer: boolean | undefined;
isGlobalObserver: boolean | undefined;
isOnGlobalTeam: boolean | undefined;
isAnyTeamMaintainer: boolean | undefined;
isAnyTeamMaintainerOrTeamAdmin: boolean | undefined;
isTeamObserver: boolean | undefined;
isTeamMaintainer: boolean | undefined;
isTeamMaintainerOrTeamAdmin: boolean | undefined;
isAnyTeamAdmin: boolean | undefined;
isTeamAdmin: boolean | undefined;
isOnlyObserver: boolean | undefined;
isNoAccess: boolean | undefined;
isPreviewMode?: boolean;
isSandboxMode?: boolean;
isFreeTier?: boolean;
isPremiumTier?: boolean;
isGlobalAdmin?: boolean;
isGlobalMaintainer?: boolean;
isGlobalObserver?: boolean;
isOnGlobalTeam?: boolean;
isAnyTeamMaintainer?: boolean;
isAnyTeamMaintainerOrTeamAdmin?: boolean;
isTeamObserver?: boolean;
isTeamMaintainer?: boolean;
isTeamMaintainerOrTeamAdmin?: boolean;
isAnyTeamAdmin?: boolean;
isTeamAdmin?: boolean;
isOnlyObserver?: boolean;
isNoAccess?: boolean;
sandboxExpiry?: string;
setAvailableTeams: (availableTeams: ITeamSummary[]) => void;
setCurrentUser: (user: IUser) => void;
setCurrentTeam: (team: ITeamSummary | undefined) => void;
setCurrentTeam: (team?: ITeamSummary) => void;
setConfig: (config: IConfig) => void;
setEnrollSecret: (enrollSecret: IEnrollSecret[]) => void;
setSandboxExpiry: (sandboxExpiry: string) => void;
@@ -90,7 +90,7 @@ type InitialStateType = {
export type IAppContext = InitialStateType;
const initialState = {
export const initialState = {
availableTeams: undefined,
config: null,
currentUser: null,
@@ -414,7 +414,7 @@ const TeamDetailsWrapper = ({
selectedTeamId={toNumber(routeParams.team_id)}
currentUserTeams={adminTeams || []}
isDisabled={isLoadingTeams}
disableAll
includeAll={false}
onChange={(newSelectedValue: number) =>
handleTeamSelect(newSelectedValue)
}
@@ -338,13 +338,7 @@ const ManageHostsPage = ({
useQuery<IPolicyAPIResponse, Error>(
["policy"],
() => {
const teamId = parseInt(queryParams?.team_id, 10) || 0;
const request = teamId
? teamPoliciesAPI.load(teamId, policyId)
: globalPoliciesAPI.load(policyId);
return request;
},
() => globalPoliciesAPI.load(policyId),
{
enabled: !!policyId,
onSuccess: ({ policy: policyAPIResponse }) => {
@@ -408,10 +402,6 @@ const ManageHostsPage = ({
}
};
const getLabelSelected = () => {
return selectedFilters.find((f) => f.includes(LABEL_SLUG_PREFIX));
};
const getStatusSelected = () => {
return selectedFilters.find((f) => !f.includes(LABEL_SLUG_PREFIX));
};
@@ -714,22 +704,19 @@ const ManageHostsPage = ({
const handleTeamSelect = (teamId: number) => {
const { MANAGE_HOSTS } = PATHS;
const teamIdParam = getValidatedTeamId(
availableTeams || [],
teamId,
currentUser,
isOnGlobalTeam as boolean
isOnGlobalTeam ?? false
);
const slimmerParams = omit(queryParams, [
"policy_id",
"policy_response",
"team_id",
]);
const slimmerParams = omit(queryParams, ["team_id"]);
const newQueryParams = !teamIdParam
? slimmerParams
: Object.assign({}, slimmerParams, { team_id: teamIdParam });
: Object.assign(slimmerParams, { team_id: teamIdParam });
const nextLocation = getNextLocationPath({
pathPrefix: MANAGE_HOSTS,
@@ -1168,9 +1155,7 @@ const ManageHostsPage = ({
const renderTeamsFilterDropdown = () => (
<TeamsDropdown
currentUserTeams={availableTeams || []}
selectedTeamId={
(policyId && policy?.team_id) || (currentTeam?.id as number)
}
selectedTeamId={currentTeam?.id}
isDisabled={isHostsLoading || isHostCountLoading}
onChange={(newSelectedValue: number) =>
handleTeamSelect(newSelectedValue)
@@ -1257,7 +1242,7 @@ const ManageHostsPage = ({
/>
<FilterPill
icon={PolicyIcon}
label={policy?.name ?? ""}
label={policy?.name ?? "..."}
onClear={handleClearPoliciesFilter}
className={`${baseClass}__policies-filter-pill`}
/>
+23
View File
@@ -0,0 +1,23 @@
import React from "react";
import { render, RenderOptions } from "@testing-library/react";
import { AppContext, IAppContext, initialState } from "context/app";
type RenderOptionsWithProviderProps = RenderOptions & {
contextValue: Partial<IAppContext>;
};
/**
* A custom render method that provides a configurable App context when testing components
*/
// eslint-disable-next-line import/prefer-default-export
export const renderWithAppContext = (
component: React.ReactNode,
{ contextValue, ...renderOptions }: RenderOptionsWithProviderProps
) => {
const value: IAppContext = { ...initialState, ...contextValue };
return render(
<AppContext.Provider value={value}>{component}</AppContext.Provider>,
renderOptions
);
};