Fleet UI: Unreleased bug fixes for policy automations filtering (#41991)
This commit is contained in:
@@ -34,12 +34,14 @@ import { TooltipContent } from "interfaces/dropdownOption";
|
||||
|
||||
import configAPI from "services/entities/config";
|
||||
import globalPoliciesAPI, {
|
||||
GlobalPoliciesAutomationType,
|
||||
IPoliciesCountQueryKey,
|
||||
IPoliciesQueryKey,
|
||||
} from "services/entities/global_policies";
|
||||
import teamPoliciesAPI, {
|
||||
ITeamPoliciesCountQueryKey,
|
||||
ITeamPoliciesQueryKey,
|
||||
AutomationType,
|
||||
} from "services/entities/team_policies";
|
||||
import teamsAPI, { ILoadTeamResponse } from "services/entities/teams";
|
||||
|
||||
@@ -88,6 +90,7 @@ interface IManagePoliciesPageProps {
|
||||
order_key?: string;
|
||||
order_direction?: "asc" | "desc";
|
||||
page?: string;
|
||||
automation_type?: AutomationType;
|
||||
};
|
||||
search: string;
|
||||
};
|
||||
@@ -104,6 +107,16 @@ const [
|
||||
"Could not update policy automations.",
|
||||
];
|
||||
|
||||
const AUTOMATION_TYPES: AutomationType[] = [
|
||||
"software",
|
||||
"scripts",
|
||||
"calendar",
|
||||
"conditional_access",
|
||||
"other",
|
||||
];
|
||||
|
||||
const GLOBAL_AUTOMATION_TYPES: GlobalPoliciesAutomationType[] = ["other"];
|
||||
|
||||
const baseClass = "manage-policies-page";
|
||||
|
||||
const ManagePolicyPage = ({
|
||||
@@ -194,6 +207,21 @@ const ManagePolicyPage = ({
|
||||
DEFAULT_SORT_DIRECTION)();
|
||||
const page =
|
||||
queryParams && queryParams.page ? parseInt(queryParams?.page, 10) : 0;
|
||||
const initialAutomationFilter = (() => {
|
||||
const automationQueryParam = queryParams.automation_type;
|
||||
|
||||
if (!automationQueryParam) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const validValues = isAllTeamsSelected
|
||||
? GLOBAL_AUTOMATION_TYPES
|
||||
: AUTOMATION_TYPES;
|
||||
|
||||
return (validValues as string[]).includes(automationQueryParam)
|
||||
? automationQueryParam
|
||||
: null;
|
||||
})();
|
||||
|
||||
// Needs update on location change or table state might not match URL
|
||||
const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
|
||||
@@ -205,16 +233,9 @@ const ManagePolicyPage = ({
|
||||
const [sortDirection, setSortDirection] = useState<
|
||||
"asc" | "desc" | undefined
|
||||
>(initialSortDirection);
|
||||
const [automationFilter, setAutomationFilter] = useState<string | null>(null);
|
||||
|
||||
// Maps frontend dropdown values to backend automation_type query param values
|
||||
const AUTOMATION_FILTER_TO_API: Record<string, string> = {
|
||||
install_software: "software",
|
||||
run_script: "scripts",
|
||||
calendar_events: "calendar",
|
||||
conditional_access: "conditional_access",
|
||||
other_workflows: "other",
|
||||
};
|
||||
const [automationFilter, setAutomationFilter] = useState<
|
||||
AutomationType | GlobalPoliciesAutomationType | null
|
||||
>(initialAutomationFilter);
|
||||
|
||||
useEffect(() => {
|
||||
setLastEditedQueryPlatform(null);
|
||||
@@ -227,12 +248,14 @@ const ManagePolicyPage = ({
|
||||
setSearchQuery(initialSearchQuery);
|
||||
setSortHeader(initialSortHeader);
|
||||
setSortDirection(initialSortDirection);
|
||||
setAutomationFilter(initialAutomationFilter);
|
||||
}, [
|
||||
location,
|
||||
isRouteOk,
|
||||
initialSearchQuery,
|
||||
initialSortHeader,
|
||||
initialSortDirection,
|
||||
initialAutomationFilter,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -271,6 +294,7 @@ const ManagePolicyPage = ({
|
||||
query: searchQuery,
|
||||
orderDirection: sortDirection,
|
||||
orderKey: sortHeader,
|
||||
automationType: automationFilter as GlobalPoliciesAutomationType,
|
||||
},
|
||||
],
|
||||
({ queryKey }) => {
|
||||
@@ -292,6 +316,7 @@ const ManagePolicyPage = ({
|
||||
{
|
||||
scope: "policiesCount",
|
||||
query: !isAllTeamsSelected ? "" : searchQuery,
|
||||
automationType: automationFilter as GlobalPoliciesAutomationType,
|
||||
},
|
||||
],
|
||||
({ queryKey }) => globalPoliciesAPI.getCount(queryKey[0]),
|
||||
@@ -327,9 +352,7 @@ const ManagePolicyPage = ({
|
||||
teamId: teamIdForApi || 0,
|
||||
// no teams does inherit
|
||||
mergeInherited: true,
|
||||
automationType: automationFilter
|
||||
? AUTOMATION_FILTER_TO_API[automationFilter]
|
||||
: undefined,
|
||||
automationType: automationFilter as AutomationType,
|
||||
},
|
||||
],
|
||||
({ queryKey }) => {
|
||||
@@ -357,6 +380,7 @@ const ManagePolicyPage = ({
|
||||
query: searchQuery,
|
||||
teamId: teamIdForApi || 0, // TODO: Fix number/undefined type
|
||||
mergeInherited: true,
|
||||
automationType: automationFilter as AutomationType,
|
||||
},
|
||||
],
|
||||
({ queryKey }) => teamPoliciesAPI.getCount(queryKey[0]),
|
||||
@@ -929,6 +953,21 @@ const ManagePolicyPage = ({
|
||||
toggleDeletePoliciesModal,
|
||||
]);
|
||||
|
||||
const onChangeAutomationFilter = (val: SingleValue<CustomOptionType>) => {
|
||||
const automationType = val?.value;
|
||||
|
||||
const locationPath = getNextLocationPath({
|
||||
pathPrefix: PATHS.MANAGE_POLICIES,
|
||||
queryParams: {
|
||||
...queryParams,
|
||||
page: "0",
|
||||
automation_type: automationType === "all" ? undefined : automationType,
|
||||
},
|
||||
});
|
||||
|
||||
router?.push(locationPath);
|
||||
};
|
||||
|
||||
const policiesErrors = !isAllTeamsSelected
|
||||
? teamPoliciesError
|
||||
: globalPoliciesError;
|
||||
@@ -974,7 +1013,7 @@ const ManagePolicyPage = ({
|
||||
count?: number,
|
||||
policies?: IPolicyStats[]
|
||||
) => {
|
||||
// Hide count if fetching count || there are errors OR there are no policy results with no a search filter
|
||||
// Hide count if fetching count || there are errors OR there are no policy results with no filters (search or automation dropdown)
|
||||
const isFetchingCount = !isAllTeamsSelected
|
||||
? isFetchingTeamCountMergeInherited
|
||||
: isFetchingGlobalCount;
|
||||
@@ -982,7 +1021,7 @@ const ManagePolicyPage = ({
|
||||
const hide =
|
||||
isFetchingCount ||
|
||||
policiesErrors ||
|
||||
(!policyResults && searchQuery === "");
|
||||
(!policyResults && searchQuery === "" && !automationFilter);
|
||||
|
||||
if (hide) {
|
||||
return null;
|
||||
@@ -1009,61 +1048,80 @@ const ManagePolicyPage = ({
|
||||
);
|
||||
};
|
||||
|
||||
// Client-side filtering is still needed for global policies since the
|
||||
// global policies endpoint does not support automation_type. Team policies
|
||||
// use the server-side automation_type query param instead.
|
||||
const filterGlobalPoliciesByAutomation = (
|
||||
policies: IPolicyStats[]
|
||||
): IPolicyStats[] => {
|
||||
if (!automationFilter) return policies;
|
||||
return policies.filter((p) => {
|
||||
switch (automationFilter) {
|
||||
case "install_software":
|
||||
return !!p.install_software;
|
||||
case "run_script":
|
||||
return !!p.run_script;
|
||||
case "calendar_events":
|
||||
return p.calendar_events_enabled;
|
||||
case "conditional_access":
|
||||
return p.conditional_access_enabled;
|
||||
case "other_workflows":
|
||||
return currentAutomatedPolicies.includes(p.id);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const automationFilterOptions: CustomOptionType[] = [
|
||||
{ label: "All automations", value: "all" },
|
||||
{ label: "Software", value: "install_software" },
|
||||
{ label: "Scripts", value: "run_script" },
|
||||
{ label: "Calendar", value: "calendar_events" },
|
||||
{ label: "Conditional access", value: "conditional_access" },
|
||||
{ label: "Other", value: "other_workflows" },
|
||||
{
|
||||
label: "All policies",
|
||||
value: "all",
|
||||
helpText: "All policies added to Fleet.",
|
||||
},
|
||||
{
|
||||
label: "Software",
|
||||
value: "software",
|
||||
helpText: "Policies with software automation enabled.",
|
||||
},
|
||||
{
|
||||
label: "Scripts",
|
||||
value: "scripts",
|
||||
helpText: "Policies with script automation enabled.",
|
||||
},
|
||||
{
|
||||
label: "Calendar",
|
||||
value: "calendar",
|
||||
helpText: "Policies with calendar event automation enabled.",
|
||||
},
|
||||
{
|
||||
label: "Conditional access",
|
||||
value: "conditional_access",
|
||||
helpText: "Policies with conditional access automation enabled.",
|
||||
},
|
||||
{
|
||||
label: "Other",
|
||||
value: "other",
|
||||
helpText: "Policies with other automation enabled.",
|
||||
},
|
||||
];
|
||||
|
||||
const allPoliciesOption = automationFilterOptions[0]; // value: "all"
|
||||
|
||||
const getSelectedFilterOption = () => {
|
||||
if (!automationFilter) {
|
||||
return allPoliciesOption; // Default to all policies option
|
||||
}
|
||||
return automationFilterOptions.find(
|
||||
(opt) => opt.value === automationFilter
|
||||
);
|
||||
};
|
||||
|
||||
const renderAutomationFilter = isPremiumTier
|
||||
? () => (
|
||||
<DropdownWrapper
|
||||
className={`${baseClass}__filter-automation-dropdown`}
|
||||
name="filter-by-automation"
|
||||
onChange={(val: SingleValue<CustomOptionType>) => {
|
||||
const newFilter =
|
||||
val?.value && val.value !== "all" ? val.value : null;
|
||||
setAutomationFilter(newFilter);
|
||||
// Reset to first page when filter changes
|
||||
const locationPath = getNextLocationPath({
|
||||
pathPrefix: PATHS.MANAGE_POLICIES,
|
||||
queryParams: { ...queryParams, page: "0" },
|
||||
});
|
||||
router?.push(locationPath);
|
||||
}}
|
||||
placeholder="Filter by automation"
|
||||
options={automationFilterOptions}
|
||||
variant="table-filter"
|
||||
/>
|
||||
)
|
||||
? () => {
|
||||
// Hide dropdown if there are errors OR there are no policy results with no filters (search or automation dropdown)
|
||||
const hide =
|
||||
policiesErrors ||
|
||||
(!policyResults && searchQuery === "" && !automationFilter);
|
||||
|
||||
if (hide) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// No team ID = All fleets → only show "all" and "other" options
|
||||
const optionsForTeam = teamIdForApi
|
||||
? automationFilterOptions
|
||||
: automationFilterOptions.filter((opt) =>
|
||||
["all", "other"].includes(opt.value as string)
|
||||
);
|
||||
|
||||
return (
|
||||
<DropdownWrapper
|
||||
className={`${baseClass}__filter-automation-dropdown`}
|
||||
name="filter-by-automation"
|
||||
value={getSelectedFilterOption()}
|
||||
onChange={onChangeAutomationFilter}
|
||||
placeholder="Filter by automation"
|
||||
options={optionsForTeam}
|
||||
variant="table-filter"
|
||||
/>
|
||||
);
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const renderMainTable = () => {
|
||||
@@ -1076,15 +1134,9 @@ const ManagePolicyPage = ({
|
||||
if (globalPoliciesError) {
|
||||
return <TableDataError verticalPaddingSize="pad-xxxlarge" />;
|
||||
}
|
||||
const filteredGlobalPolicies = filterGlobalPoliciesByAutomation(
|
||||
globalPolicies || []
|
||||
);
|
||||
const filteredGlobalCount = automationFilter
|
||||
? filteredGlobalPolicies.length
|
||||
: globalPoliciesCount || 0;
|
||||
return (
|
||||
<PoliciesTable
|
||||
policiesList={filteredGlobalPolicies}
|
||||
policiesList={globalPolicies || []}
|
||||
isLoading={isFetchingGlobalPolicies || isFetchingGlobalConfig}
|
||||
onDeletePoliciesClick={onDeletePoliciesClick}
|
||||
canAddOrDeletePolicies={canAddOrDeletePolicies}
|
||||
@@ -1094,11 +1146,11 @@ const ManagePolicyPage = ({
|
||||
isPremiumTier={isPremiumTier}
|
||||
renderPoliciesCount={() =>
|
||||
renderPoliciesCountAndLastUpdated(
|
||||
filteredGlobalCount,
|
||||
filteredGlobalPolicies
|
||||
globalPoliciesCount,
|
||||
globalPolicies
|
||||
)
|
||||
}
|
||||
count={filteredGlobalCount}
|
||||
count={globalPoliciesCount || 0}
|
||||
searchQuery={searchQuery}
|
||||
sortHeader={sortHeader}
|
||||
sortDirection={sortDirection}
|
||||
@@ -1115,11 +1167,7 @@ const ManagePolicyPage = ({
|
||||
return <TableDataError verticalPaddingSize="pad-xxxlarge" />;
|
||||
}
|
||||
const displayedTeamPolicies = teamPolicies || [];
|
||||
// When a filter is active, use the returned array length as the count
|
||||
// since the count endpoint doesn't support automation_type yet.
|
||||
const displayedTeamCount = automationFilter
|
||||
? displayedTeamPolicies.length
|
||||
: teamPoliciesCountMergeInherited || 0;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PoliciesTable
|
||||
@@ -1136,12 +1184,12 @@ const ManagePolicyPage = ({
|
||||
currentAutomatedPolicies={currentAutomatedPolicies}
|
||||
renderPoliciesCount={() =>
|
||||
renderPoliciesCountAndLastUpdated(
|
||||
displayedTeamCount,
|
||||
teamPoliciesCountMergeInherited,
|
||||
displayedTeamPolicies
|
||||
)
|
||||
}
|
||||
isPremiumTier={isPremiumTier}
|
||||
count={displayedTeamCount}
|
||||
count={teamPoliciesCountMergeInherited || 0}
|
||||
searchQuery={searchQuery}
|
||||
sortHeader={sortHeader}
|
||||
sortDirection={sortDirection}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
}
|
||||
|
||||
&__filter-automation-dropdown {
|
||||
min-width: 200px;
|
||||
min-width: 277px;
|
||||
}
|
||||
|
||||
&__manage-automations-wrapper {
|
||||
|
||||
+33
-10
@@ -21,7 +21,9 @@ import teamPoliciesAPI, {
|
||||
IPoliciesApiParams,
|
||||
IPoliciesCountApiParams,
|
||||
} from "services/entities/team_policies";
|
||||
import globalPoliciesAPI from "services/entities/global_policies";
|
||||
import globalPoliciesAPI, {
|
||||
IGlobalPoliciesApiQueryParams,
|
||||
} from "services/entities/global_policies";
|
||||
|
||||
import { APP_CONTEXT_ALL_TEAMS_ID } from "interfaces/team";
|
||||
import { QueryablePlatform, isQueryablePlatform } from "interfaces/platform";
|
||||
@@ -164,10 +166,12 @@ function PoliciesPaginatedList(
|
||||
orderDirection: "asc" as const,
|
||||
orderKey: DEFAULT_SORT_COLUMN,
|
||||
teamId,
|
||||
automationType: undefined,
|
||||
};
|
||||
countQueryKey = {
|
||||
query: "",
|
||||
teamId,
|
||||
automationType: undefined,
|
||||
};
|
||||
} else {
|
||||
policiesQueryKey = {
|
||||
@@ -178,11 +182,13 @@ function PoliciesPaginatedList(
|
||||
orderKey: DEFAULT_SORT_COLUMN,
|
||||
teamId,
|
||||
mergeInherited: false,
|
||||
automationType: undefined,
|
||||
};
|
||||
countQueryKey = {
|
||||
query: "",
|
||||
teamId,
|
||||
mergeInherited: false,
|
||||
automationType: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -206,11 +212,18 @@ function PoliciesPaginatedList(
|
||||
ILoadAllPoliciesResponse,
|
||||
Error,
|
||||
IFormPolicy[]
|
||||
>([policiesQueryKey], () => globalPoliciesAPI.loadAllNew(policiesQueryKey), {
|
||||
enabled: teamId === APP_CONTEXT_ALL_TEAMS_ID,
|
||||
keepPreviousData: true,
|
||||
select: marshallApiResponse,
|
||||
});
|
||||
>(
|
||||
[policiesQueryKey],
|
||||
() =>
|
||||
globalPoliciesAPI.loadAllNew(
|
||||
policiesQueryKey as IGlobalPoliciesApiQueryParams
|
||||
),
|
||||
{
|
||||
enabled: teamId === APP_CONTEXT_ALL_TEAMS_ID,
|
||||
keepPreviousData: true,
|
||||
select: marshallApiResponse,
|
||||
}
|
||||
);
|
||||
|
||||
// Team policies query
|
||||
const { data: teamData, isFetching: teamIsLoading } = useQuery<
|
||||
@@ -232,10 +245,20 @@ function PoliciesPaginatedList(
|
||||
IPoliciesCountResponse,
|
||||
Error,
|
||||
number
|
||||
>([countQueryKey], () => globalPoliciesAPI.getCount(countQueryKey), {
|
||||
enabled: teamId === APP_CONTEXT_ALL_TEAMS_ID,
|
||||
select: (countResponse: IPoliciesCountResponse) => countResponse.count,
|
||||
});
|
||||
>(
|
||||
[countQueryKey],
|
||||
() =>
|
||||
globalPoliciesAPI.getCount(
|
||||
countQueryKey as Pick<
|
||||
IGlobalPoliciesApiQueryParams,
|
||||
"query" | "automationType"
|
||||
>
|
||||
),
|
||||
{
|
||||
enabled: teamId === APP_CONTEXT_ALL_TEAMS_ID,
|
||||
select: (countResponse: IPoliciesCountResponse) => countResponse.count,
|
||||
}
|
||||
);
|
||||
|
||||
// Team count query
|
||||
const { data: teamCount, isFetching: teamIsFetchingCount } = useQuery<
|
||||
|
||||
@@ -11,21 +11,28 @@ import {
|
||||
buildQueryStringFromParams,
|
||||
convertParamsToSnakeCase,
|
||||
} from "utilities/url";
|
||||
import { AutomationType } from "./team_policies";
|
||||
|
||||
interface IPoliciesApiParams {
|
||||
export type GlobalPoliciesAutomationType = Exclude<
|
||||
AutomationType,
|
||||
"software" | "scripts" | "conditional_access" | "calendar"
|
||||
>;
|
||||
|
||||
export interface IGlobalPoliciesApiQueryParams {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
orderKey?: string;
|
||||
orderDirection?: "asc" | "desc";
|
||||
query?: string;
|
||||
automationType?: GlobalPoliciesAutomationType;
|
||||
}
|
||||
|
||||
export interface IPoliciesQueryKey extends IPoliciesApiParams {
|
||||
export interface IPoliciesQueryKey extends IGlobalPoliciesApiQueryParams {
|
||||
scope: "globalPolicies";
|
||||
}
|
||||
|
||||
export interface IPoliciesCountQueryKey
|
||||
extends Pick<IPoliciesApiParams, "query"> {
|
||||
extends Pick<IGlobalPoliciesApiQueryParams, "query" | "automationType"> {
|
||||
scope: "policiesCount";
|
||||
}
|
||||
|
||||
@@ -68,7 +75,8 @@ export default {
|
||||
orderKey = ORDER_KEY,
|
||||
orderDirection: orderDir = ORDER_DIRECTION,
|
||||
query,
|
||||
}: IPoliciesApiParams): Promise<ILoadAllPoliciesResponse> => {
|
||||
automationType,
|
||||
}: IGlobalPoliciesApiQueryParams): Promise<ILoadAllPoliciesResponse> => {
|
||||
const { GLOBAL_POLICIES } = endpoints;
|
||||
|
||||
const queryParams = {
|
||||
@@ -77,6 +85,7 @@ export default {
|
||||
orderKey,
|
||||
orderDirection: orderDir,
|
||||
query,
|
||||
automationType,
|
||||
};
|
||||
|
||||
const snakeCaseParams = convertParamsToSnakeCase(queryParams);
|
||||
@@ -87,11 +96,16 @@ export default {
|
||||
},
|
||||
getCount: ({
|
||||
query,
|
||||
}: Pick<IPoliciesApiParams, "query">): Promise<IPoliciesCountResponse> => {
|
||||
automationType,
|
||||
}: Pick<
|
||||
IGlobalPoliciesApiQueryParams,
|
||||
"query" | "automationType"
|
||||
>): Promise<IPoliciesCountResponse> => {
|
||||
const { GLOBAL_POLICIES } = endpoints;
|
||||
const path = `${GLOBAL_POLICIES}/count`;
|
||||
const queryParams = {
|
||||
query,
|
||||
automationType,
|
||||
};
|
||||
const snakeCaseParams = convertParamsToSnakeCase(queryParams);
|
||||
const queryString = buildQueryStringFromParams(snakeCaseParams);
|
||||
|
||||
@@ -11,6 +11,14 @@ import {
|
||||
} from "interfaces/policy";
|
||||
import { API_NO_TEAM_ID } from "interfaces/team";
|
||||
import { buildQueryStringFromParams, QueryParams } from "utilities/url";
|
||||
import { GlobalPoliciesAutomationType } from "./global_policies";
|
||||
|
||||
export type AutomationType =
|
||||
| "software"
|
||||
| "scripts"
|
||||
| "calendar"
|
||||
| "conditional_access"
|
||||
| "other";
|
||||
|
||||
interface IPoliciesApiQueryParams {
|
||||
page?: number;
|
||||
@@ -18,7 +26,7 @@ interface IPoliciesApiQueryParams {
|
||||
orderKey?: string;
|
||||
orderDirection?: "asc" | "desc";
|
||||
query?: string;
|
||||
automationType?: string;
|
||||
automationType?: AutomationType | GlobalPoliciesAutomationType;
|
||||
}
|
||||
|
||||
export interface IPoliciesApiParams extends IPoliciesApiQueryParams {
|
||||
@@ -31,7 +39,10 @@ export interface ITeamPoliciesQueryKey extends IPoliciesApiParams {
|
||||
}
|
||||
|
||||
export interface ITeamPoliciesCountQueryKey
|
||||
extends Pick<IPoliciesApiParams, "query" | "teamId" | "mergeInherited"> {
|
||||
extends Pick<
|
||||
IPoliciesApiParams,
|
||||
"query" | "teamId" | "mergeInherited" | "automationType"
|
||||
> {
|
||||
scope: "teamPoliciesCountMergeInherited" | "teamPoliciesCount";
|
||||
}
|
||||
|
||||
@@ -39,6 +50,7 @@ export interface IPoliciesCountApiParams {
|
||||
teamId: number;
|
||||
query?: string;
|
||||
mergeInherited?: boolean;
|
||||
automationType?: AutomationType;
|
||||
}
|
||||
|
||||
const ORDER_KEY = "name";
|
||||
@@ -179,15 +191,17 @@ export default {
|
||||
query,
|
||||
teamId,
|
||||
mergeInherited = true,
|
||||
automationType,
|
||||
}: Pick<
|
||||
IPoliciesCountApiParams,
|
||||
"query" | "teamId" | "mergeInherited"
|
||||
"query" | "teamId" | "mergeInherited" | "automationType"
|
||||
>): Promise<IPoliciesCountResponse> => {
|
||||
const { TEAM_POLICIES } = endpoints;
|
||||
const path = `${TEAM_POLICIES(teamId)}/count`;
|
||||
const queryParams = {
|
||||
query,
|
||||
mergeInherited,
|
||||
automationType,
|
||||
};
|
||||
const snakeCaseParams = convertParamsToSnakeCase(queryParams);
|
||||
const queryString = buildQueryStringFromParams(snakeCaseParams);
|
||||
|
||||
Reference in New Issue
Block a user