mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
feat(ui): filter providers list by provider group
- Add the provider group selector to the Providers page filters - Mock getAllProviderGroups in the providers page data tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -118,6 +118,7 @@ const ProvidersTabContent = async ({
|
||||
isCloud={process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true"}
|
||||
filters={providersView.filters}
|
||||
providers={providersView.providers}
|
||||
providerGroups={providersView.providerGroups}
|
||||
metadata={providersView.metadata}
|
||||
rows={providersView.rows}
|
||||
/>
|
||||
|
||||
@@ -18,6 +18,10 @@ const schedulesActionsMock = vi.hoisted(() => ({
|
||||
getSchedules: vi.fn(),
|
||||
}));
|
||||
|
||||
const manageGroupsActionsMock = vi.hoisted(() => ({
|
||||
getAllProviderGroups: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/actions/providers", () => providersActionsMock);
|
||||
vi.mock(
|
||||
"@/actions/organizations/organizations",
|
||||
@@ -25,6 +29,7 @@ vi.mock(
|
||||
);
|
||||
vi.mock("@/actions/scans", () => scansActionsMock);
|
||||
vi.mock("@/actions/schedules", () => schedulesActionsMock);
|
||||
vi.mock("@/actions/manage-groups/manage-groups", () => manageGroupsActionsMock);
|
||||
|
||||
import { SearchParamsProps } from "@/types";
|
||||
import { ProvidersApiResponse } from "@/types/providers";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { getAllProviderGroups } from "@/actions/manage-groups/manage-groups";
|
||||
import {
|
||||
listOrganizationsSafe,
|
||||
listOrganizationUnitsSafe,
|
||||
@@ -483,6 +484,7 @@ export async function loadProvidersAccountsViewData({
|
||||
const [
|
||||
providersResponse,
|
||||
allProvidersResponse,
|
||||
allProviderGroupsResponse,
|
||||
scansResponse,
|
||||
schedulesResponse,
|
||||
organizationsResponse,
|
||||
@@ -500,6 +502,8 @@ export async function loadProvidersAccountsViewData({
|
||||
// Unfiltered fetch for ProviderTypeSelector — only needs distinct types;
|
||||
// TODO: Replace with a dedicated lightweight endpoint when available.
|
||||
resolveActionResult(getAllProviders()),
|
||||
// Unfiltered fetch for the Provider Group selector dropdown.
|
||||
resolveActionResult(getAllProviderGroups()),
|
||||
// Fetch active scheduled scans to flag providers whose schedule has fired.
|
||||
resolveActionResult(
|
||||
getScans({
|
||||
@@ -545,6 +549,7 @@ export async function loadProvidersAccountsViewData({
|
||||
filters: createProvidersFilters(),
|
||||
metadata: providersResponse?.meta,
|
||||
providers: allProvidersResponse?.data ?? [],
|
||||
providerGroups: allProviderGroupsResponse?.data ?? [],
|
||||
rows,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
getTourTargetSelector,
|
||||
} from "@/lib/tours/use-driver-tour";
|
||||
import type { FilterOption, MetaDataProps, ProviderProps } from "@/types";
|
||||
import type { ProviderGroup } from "@/types/components";
|
||||
import type { ProvidersTableRow } from "@/types/providers-table";
|
||||
import type { ScanScheduleCapability } from "@/types/schedules";
|
||||
|
||||
@@ -51,6 +52,7 @@ interface ProvidersAccountsViewProps {
|
||||
filters: FilterOption[];
|
||||
metadata?: MetaDataProps;
|
||||
providers: ProviderProps[];
|
||||
providerGroups?: ProviderGroup[];
|
||||
rows: ProvidersTableRow[];
|
||||
/** Cloud overlay seam for provider-creation scan launch. */
|
||||
scanScheduleCapability?: ScanScheduleCapability;
|
||||
@@ -62,6 +64,7 @@ export function ProvidersAccountsView({
|
||||
filters,
|
||||
metadata,
|
||||
providers,
|
||||
providerGroups = [],
|
||||
rows,
|
||||
scanScheduleCapability,
|
||||
isScanLimitReached,
|
||||
@@ -141,6 +144,7 @@ export function ProvidersAccountsView({
|
||||
<ProvidersFilters
|
||||
filters={filters}
|
||||
providers={providers}
|
||||
providerGroups={providerGroups}
|
||||
actions={
|
||||
<>
|
||||
<MutedFindingsConfigButton />
|
||||
|
||||
@@ -16,6 +16,13 @@ vi.mock("@/app/(prowler)/_overview/_components/provider-type-selector", () => ({
|
||||
ProviderTypeSelector: () => <div>Provider type selector</div>,
|
||||
}));
|
||||
|
||||
vi.mock(
|
||||
"@/app/(prowler)/_overview/_components/provider-group-selector",
|
||||
() => ({
|
||||
ProviderGroupSelector: () => <div>Provider group selector</div>,
|
||||
}),
|
||||
);
|
||||
|
||||
vi.mock("@/components/filters/clear-filters-button", () => ({
|
||||
ClearFiltersButton: () => <button type="button">Clear</button>,
|
||||
}));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import { ProviderGroupSelector } from "@/app/(prowler)/_overview/_components/provider-group-selector";
|
||||
import { ProviderTypeSelector } from "@/app/(prowler)/_overview/_components/provider-type-selector";
|
||||
import { ClearFiltersButton } from "@/components/filters/clear-filters-button";
|
||||
import {
|
||||
@@ -18,6 +19,7 @@ import { EntityInfo } from "@/components/ui/entities/entity-info";
|
||||
import { useUrlFilters } from "@/hooks/use-url-filters";
|
||||
import { isConnectionStatus, isGroupFilterEntity } from "@/lib/helper-filters";
|
||||
import { FilterEntity, FilterOption, ProviderEntity } from "@/types";
|
||||
import { ProviderGroup } from "@/types/components";
|
||||
import {
|
||||
GroupFilterEntity,
|
||||
ProviderConnectionStatus,
|
||||
@@ -31,12 +33,14 @@ function isNonEmptyString(value: string | null | undefined): value is string {
|
||||
interface ProvidersFiltersProps {
|
||||
filters: FilterOption[];
|
||||
providers: ProviderProps[];
|
||||
providerGroups?: ProviderGroup[];
|
||||
actions?: ReactNode;
|
||||
}
|
||||
|
||||
export const ProvidersFilters = ({
|
||||
filters,
|
||||
providers,
|
||||
providerGroups = [],
|
||||
actions,
|
||||
}: ProvidersFiltersProps) => {
|
||||
const { updateFilter } = useUrlFilters();
|
||||
@@ -153,6 +157,9 @@ export const ProvidersFilters = ({
|
||||
<div className="min-w-[200px] flex-1 md:max-w-[280px]">
|
||||
<ProviderTypeSelector providers={providers} />
|
||||
</div>
|
||||
<div className="max-w-[240px] min-w-[180px] flex-1">
|
||||
<ProviderGroupSelector groups={providerGroups} />
|
||||
</div>
|
||||
{sortedFilters.map((filter) => {
|
||||
const selectedValues = getSelectedValues(filter);
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MetaDataProps } from "./components";
|
||||
import { MetaDataProps, ProviderGroup } from "./components";
|
||||
import { FilterOption } from "./filters";
|
||||
import {
|
||||
OrganizationResource,
|
||||
@@ -83,6 +83,7 @@ export interface ProvidersAccountsViewData {
|
||||
filters: FilterOption[];
|
||||
metadata?: MetaDataProps;
|
||||
providers: ProviderProps[];
|
||||
providerGroups: ProviderGroup[];
|
||||
rows: ProvidersTableRow[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user