mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-29 23:04:23 +00:00
feat: filters relationships in findings and scans page (#8046)
Co-authored-by: Pablo Lara <larabjj@gmail.com>
This commit is contained in:
1 parent
b3f2a1c532
commit
6b7b700a98
22 files changed
+576
-265
No files matched your search
@@ -282,7 +282,10 @@ export const CustomDropdownFilter = ({
|
||||
onValueChange={onSelectionChange}
|
||||
className="font-bold"
|
||||
>
|
||||
{filter?.showSelectAll !== false && (
|
||||
{filterValues.length === 0 && (
|
||||
<span className="text-small font-normal">No results found</span>
|
||||
)}
|
||||
{filter?.showSelectAll !== false && filterValues.length > 0 && (
|
||||
<>
|
||||
<Checkbox
|
||||
classNames={{
|
||||
@@ -296,45 +299,49 @@ export const CustomDropdownFilter = ({
|
||||
<Divider orientation="horizontal" className="mt-2" />
|
||||
</>
|
||||
)}
|
||||
<ScrollShadow
|
||||
hideScrollBar
|
||||
className="flex max-h-96 max-w-full flex-col gap-y-2 py-2"
|
||||
>
|
||||
{filterValues.map((value) => {
|
||||
const entity: FilterEntity | undefined =
|
||||
filter.valueLabelMapping?.find((entry) => entry[value])?.[
|
||||
value
|
||||
];
|
||||
|
||||
return (
|
||||
<Checkbox
|
||||
classNames={{
|
||||
label: "text-small font-normal",
|
||||
wrapper: "checkbox-update",
|
||||
}}
|
||||
key={value}
|
||||
value={value}
|
||||
>
|
||||
{entity ? (
|
||||
isScanEntity(entity as ScanEntity) ? (
|
||||
<ComplianceScanInfo scan={entity as ScanEntity} />
|
||||
) : (
|
||||
<EntityInfoShort
|
||||
cloudProvider={(entity as ProviderEntity).provider}
|
||||
entityAlias={
|
||||
(entity as ProviderEntity).alias ?? undefined
|
||||
}
|
||||
entityId={(entity as ProviderEntity).uid}
|
||||
hideCopyButton
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
{filterValues.length > 0 && (
|
||||
<ScrollShadow
|
||||
hideScrollBar
|
||||
className="flex max-h-96 max-w-full flex-col gap-y-2 py-2"
|
||||
>
|
||||
{filterValues.map((value) => {
|
||||
const entity: FilterEntity | undefined =
|
||||
filter.valueLabelMapping?.find((entry) => entry[value])?.[
|
||||
value
|
||||
)}
|
||||
</Checkbox>
|
||||
);
|
||||
})}
|
||||
</ScrollShadow>
|
||||
];
|
||||
|
||||
return (
|
||||
<Checkbox
|
||||
classNames={{
|
||||
label: "text-small font-normal",
|
||||
wrapper: "checkbox-update",
|
||||
}}
|
||||
key={value}
|
||||
value={value}
|
||||
>
|
||||
{entity ? (
|
||||
isScanEntity(entity as ScanEntity) ? (
|
||||
<ComplianceScanInfo scan={entity as ScanEntity} />
|
||||
) : (
|
||||
<EntityInfoShort
|
||||
cloudProvider={
|
||||
(entity as ProviderEntity).provider
|
||||
}
|
||||
entityAlias={
|
||||
(entity as ProviderEntity).alias ?? undefined
|
||||
}
|
||||
entityId={(entity as ProviderEntity).uid}
|
||||
hideCopyButton
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
value
|
||||
)}
|
||||
</Checkbox>
|
||||
);
|
||||
})}
|
||||
</ScrollShadow>
|
||||
)}
|
||||
</CheckboxGroup>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
|
||||
import { ClearFiltersButton } from "@/components/filters";
|
||||
import { CustomFilterIcon } from "@/components/icons";
|
||||
import { CustomButton, CustomDropdownFilter } from "@/components/ui/custom";
|
||||
import { useUrlFilters } from "@/hooks/use-url-filters";
|
||||
@@ -11,11 +12,13 @@ import { FilterOption } from "@/types";
|
||||
export interface DataTableFilterCustomProps {
|
||||
filters: FilterOption[];
|
||||
defaultOpen?: boolean;
|
||||
showClearButton?: boolean;
|
||||
}
|
||||
|
||||
export const DataTableFilterCustom = ({
|
||||
filters,
|
||||
defaultOpen = false,
|
||||
showClearButton = false,
|
||||
}: DataTableFilterCustomProps) => {
|
||||
const { updateFilter } = useUrlFilters();
|
||||
const [showFilters, setShowFilters] = useState(defaultOpen);
|
||||
@@ -43,39 +46,33 @@ export const DataTableFilterCustom = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex ${
|
||||
sortedFilters.length > 4 ? "flex-col" : "flex-col md:flex-row"
|
||||
} gap-4`}
|
||||
>
|
||||
<CustomButton
|
||||
ariaLabel={showFilters ? "Hide Filters" : "Show Filters"}
|
||||
variant="flat"
|
||||
color={showFilters ? "action" : "primary"}
|
||||
size="md"
|
||||
startContent={<CustomFilterIcon size={16} />}
|
||||
onPress={() => setShowFilters(!showFilters)}
|
||||
className="w-full max-w-fit"
|
||||
>
|
||||
<h3 className="text-small">
|
||||
{showFilters ? "Hide Filters" : "Show Filters"}
|
||||
</h3>
|
||||
</CustomButton>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-row gap-4">
|
||||
<CustomButton
|
||||
ariaLabel={showFilters ? "Hide Filters" : "Show Filters"}
|
||||
variant="flat"
|
||||
color={showFilters ? "action" : "primary"}
|
||||
size="md"
|
||||
startContent={<CustomFilterIcon size={16} />}
|
||||
onPress={() => setShowFilters(!showFilters)}
|
||||
className="w-full max-w-fit"
|
||||
>
|
||||
<h3 className="text-small">
|
||||
{showFilters ? "Hide Filters" : "Show Filters"}
|
||||
</h3>
|
||||
</CustomButton>
|
||||
|
||||
{showClearButton && <ClearFiltersButton />}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`transition-all duration-700 ease-in-out ${
|
||||
showFilters
|
||||
? "max-h-96 w-full translate-x-0 overflow-visible opacity-100"
|
||||
: "max-h-0 -translate-x-full overflow-hidden opacity-0"
|
||||
? "w-full translate-x-0 overflow-visible opacity-100"
|
||||
: "mt-[-16px] max-h-0 -translate-x-full overflow-hidden opacity-0"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`grid gap-4 ${
|
||||
sortedFilters.length >= 4
|
||||
? "grid-cols-1 md:grid-cols-4"
|
||||
: "grid-cols-1 md:grid-cols-3"
|
||||
}`}
|
||||
>
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-4">
|
||||
{sortedFilters.map((filter) => (
|
||||
<CustomDropdownFilter
|
||||
key={filter.key}
|
||||
|
||||
Reference in new issue
Block a user