Merge branch 'chore/unify-filter-search-and-batch-patterns' into fix/resources-filters-and-drawer-polish

This commit is contained in:
Alejandro Bailo
2026-04-23 12:50:27 +02:00
committed by GitHub
10 changed files with 77 additions and 35 deletions
+2
View File
@@ -151,6 +151,8 @@ node_modules
# Persistent data
_data/
/openspec/
/.gitmodules
# AI Instructions (generated by skills/setup.sh from AGENTS.md)
CLAUDE.md
+1
View File
@@ -22,6 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libtool \
libxslt1-dev \
python3-dev \
git \
&& rm -rf /var/lib/apt/lists/*
# Install PowerShell
+10 -10
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand.
[[package]]
name = "about-time"
@@ -2974,7 +2974,7 @@ files = [
[package.dependencies]
autopep8 = "*"
Django = ">=4.2"
gprof2dot = ">=2017.09.19"
gprof2dot = ">=2017.9.19"
sqlparse = "*"
[[package]]
@@ -4582,7 +4582,7 @@ files = [
[package.dependencies]
attrs = ">=22.2.0"
jsonschema-specifications = ">=2023.03.6"
jsonschema-specifications = ">=2023.3.6"
referencing = ">=0.28.4"
rpds-py = ">=0.7.1"
@@ -4790,7 +4790,7 @@ librabbitmq = ["librabbitmq (>=2.0.0) ; python_version < \"3.11\""]
mongodb = ["pymongo (==4.15.3)"]
msgpack = ["msgpack (==1.1.2)"]
pyro = ["pyro4 (==4.82)"]
qpid = ["qpid-python (==1.36.0-1)", "qpid-tools (==1.36.0-1)"]
qpid = ["qpid-python (==1.36.0.post1)", "qpid-tools (==1.36.0.post1)"]
redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2,<6.5)"]
slmq = ["softlayer_messaging (>=1.0.3)"]
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
@@ -4811,7 +4811,7 @@ files = [
]
[package.dependencies]
certifi = ">=14.05.14"
certifi = ">=14.5.14"
durationpy = ">=0.7"
google-auth = ">=1.0.1"
oauthlib = ">=3.2.2"
@@ -6964,11 +6964,11 @@ description = "C parser in Python"
optional = false
python-versions = ">=3.10"
groups = ["main", "dev"]
markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""
files = [
{file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
{file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
]
markers = {main = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\"", dev = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\""}
[[package]]
name = "pydantic"
@@ -7194,7 +7194,7 @@ files = [
]
[package.dependencies]
astroid = ">=3.2.2,<=3.3.0-dev0"
astroid = ">=3.2.2,<=3.3.0.dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = [
{version = ">=0.3.7", markers = "python_version >= \"3.12\""},
@@ -7216,7 +7216,7 @@ description = "The MSALRuntime Python Interop Package"
optional = false
python-versions = ">=3.6"
groups = ["main"]
markers = "(platform_system == \"Windows\" or platform_system == \"Darwin\" or platform_system == \"Linux\") and sys_platform == \"win32\""
markers = "sys_platform == \"win32\" and (platform_system == \"Windows\" or platform_system == \"Darwin\" or platform_system == \"Linux\")"
files = [
{file = "pymsalruntime-0.18.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:0c22e2e83faa10de422bbfaacc1bb2887c9025ee8a53f0fc2e4f7db01c4a7b66"},
{file = "pymsalruntime-0.18.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:8ce2944a0f944833d047bb121396091e00287e2b6373716106da86ea99abf379"},
@@ -8209,10 +8209,10 @@ files = [
]
[package.dependencies]
botocore = ">=1.37.4,<2.0a.0"
botocore = ">=1.37.4,<2.0a0"
[package.extras]
crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
crt = ["botocore[crt] (>=1.37.4,<2.0a0)"]
[[package]]
name = "safety"
Generated
+6 -5
View File
@@ -1934,6 +1934,7 @@ files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
markers = {dev = "platform_system == \"Windows\" or sys_platform == \"win32\""}
[[package]]
name = "contextlib2"
@@ -3102,7 +3103,7 @@ files = [
[package.dependencies]
attrs = ">=22.2.0"
jsonschema-specifications = ">=2023.03.6"
jsonschema-specifications = ">=2023.3.6"
referencing = ">=0.28.4"
rpds-py = ">=0.7.1"
@@ -3182,7 +3183,7 @@ files = [
]
[package.dependencies]
certifi = ">=14.05.14"
certifi = ">=14.5.14"
durationpy = ">=0.7"
google-auth = ">=1.0.1"
oauthlib = ">=3.2.2"
@@ -4988,7 +4989,7 @@ files = [
]
[package.dependencies]
astroid = ">=3.3.8,<=3.4.0-dev0"
astroid = ">=3.3.8,<=3.4.0.dev0"
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
dill = [
{version = ">=0.2", markers = "python_version < \"3.11\""},
@@ -5834,10 +5835,10 @@ files = [
]
[package.dependencies]
botocore = ">=1.37.4,<2.0a.0"
botocore = ">=1.37.4,<2.0a0"
[package.extras]
crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"]
crt = ["botocore[crt] (>=1.37.4,<2.0a0)"]
[[package]]
name = "safety"
+10 -4
View File
@@ -6,17 +6,23 @@ All notable changes to the **Prowler UI** are documented in this file.
### 🔄 Changed
- Redesign compliance page, client-side search for compliance frameworks, compact scan selector trigger, enhanced compliance cards [(#10767)](https://github.com/prowler-cloud/prowler/pull/10767)
- Allows tenant owners to expel users from their organizations [(#10787)](https://github.com/prowler-cloud/prowler/pull/10787)
- Shared filter dropdowns now support local option search and auto-scroll to the first visible match across table and provider filters
- Resources now use batch-applied filters, render metadata JSON with syntax highlighting, simplify metadata/tags tabs, and keep finding-row Learn more links interactive inside the drawer [(#10861)](https://github.com/prowler-cloud/prowler/pull/10861)
### ❌ Removed
- Redesign compliance page with a horizontal ThreatScore card (always-visible pillar breakdown + ActionDropdown), client-side search for compliance frameworks, compact scan selector trigger, responsive mobile filters, download-started toasts for CSV/PDF exports, enhanced compliance cards with truncated titles, and Alert-based empty/error states; migrate Progress component from HeroUI to shadcn [(#10767)](https://github.com/prowler-cloud/prowler/pull/10767)
- Shared filter dropdowns now support local option search and auto-scroll to the first visible match across table and provider filters [(#10859)](https://github.com/prowler-cloud/prowler/pull/10859)
- Backward-compatibility middleware redirect from `/sign-up?invitation_token=…` to `/invitation/accept?invitation_token=…`; new invitation emails use `/invitation/accept` directly [(#10797)](https://github.com/prowler-cloud/prowler/pull/10797)
---
## [1.24.4] (Prowler UNRELEASED)
### 🐞 Fixed
- Provider wizard no longer advances to the Launch Scan step when rotating credentials [(#10851)](https://github.com/prowler-cloud/prowler/pull/10851)
---
## [1.24.2] (Prowler v5.24.2)
### 🐞 Fixed
@@ -153,7 +153,7 @@ describe("useProviderWizardController", () => {
expect(onOpenChange).not.toHaveBeenCalled();
});
it("moves to launch step after a successful connection test in update mode", async () => {
it("closes the wizard after a successful connection test in update mode", async () => {
// Given
const onOpenChange = vi.fn();
const { result } = renderHook(() =>
@@ -181,9 +181,10 @@ describe("useProviderWizardController", () => {
result.current.handleTestSuccess();
});
// Then
expect(result.current.currentStep).toBe(PROVIDER_WIZARD_STEP.LAUNCH);
expect(onOpenChange).not.toHaveBeenCalled();
// Then: credential rotation never surfaces the launch/schedule step
expect(onOpenChange).toHaveBeenCalledWith(false);
expect(refreshMock).toHaveBeenCalledTimes(1);
expect(result.current.currentStep).not.toBe(PROVIDER_WIZARD_STEP.LAUNCH);
});
it("does not override launch footer config in the controller", () => {
@@ -197,6 +197,12 @@ export function useProviderWizardController({
};
const handleTestSuccess = () => {
if (
useProviderWizardStore.getState().mode === PROVIDER_WIZARD_MODE.UPDATE
) {
handleClose();
return;
}
setCurrentStep(PROVIDER_WIZARD_STEP.LAUNCH);
};
@@ -234,6 +240,7 @@ export function useProviderWizardController({
handleTestSuccess,
isOrgDirectEntry,
isProviderFlow,
mode,
modalTitle,
openOrganizationsFlow,
orgCurrentStep,
@@ -10,7 +10,10 @@ import { DialogHeader, DialogTitle } from "@/components/shadcn/dialog";
import { Modal } from "@/components/shadcn/modal";
import { useScrollHint } from "@/hooks/use-scroll-hint";
import { ORG_SETUP_PHASE, ORG_WIZARD_STEP } from "@/types/organizations";
import { PROVIDER_WIZARD_STEP } from "@/types/provider-wizard";
import {
PROVIDER_WIZARD_MODE,
PROVIDER_WIZARD_STEP,
} from "@/types/provider-wizard";
import { useProviderWizardController } from "./hooks/use-provider-wizard-controller";
import {
@@ -23,7 +26,12 @@ import { WIZARD_FOOTER_ACTION_TYPE } from "./steps/footer-controls";
import { LaunchStep } from "./steps/launch-step";
import { TestConnectionStep } from "./steps/test-connection-step";
import type { OrgWizardInitialData, ProviderWizardInitialData } from "./types";
import { WizardStepper } from "./wizard-stepper";
import { PROVIDER_WIZARD_STEPS, WizardStepper } from "./wizard-stepper";
const UPDATE_MODE_WIZARD_STEPS = PROVIDER_WIZARD_STEPS.slice(
0,
PROVIDER_WIZARD_STEP.LAUNCH,
);
interface ProviderWizardModalProps {
open: boolean;
@@ -47,6 +55,7 @@ export function ProviderWizardModal({
handleTestSuccess,
isOrgDirectEntry,
isProviderFlow,
mode,
modalTitle,
openOrganizationsFlow,
orgCurrentStep,
@@ -97,7 +106,14 @@ export function ProviderWizardModal({
<div className="mt-6 flex min-h-0 flex-1 flex-col overflow-hidden lg:mt-8 lg:flex-row">
<div className="mb-4 box-border w-full shrink-0 lg:mb-0 lg:w-[328px]">
{isProviderFlow ? (
<WizardStepper currentStep={currentStep} />
<WizardStepper
currentStep={currentStep}
steps={
mode === PROVIDER_WIZARD_MODE.UPDATE
? UPDATE_MODE_WIZARD_STEPS
: undefined
}
/>
) : (
<WizardStepper
currentStep={orgCurrentStep}
@@ -7,17 +7,18 @@ import { ProwlerShort } from "@/components/icons/prowler/ProwlerIcons";
import { cn } from "@/lib/utils";
import { IconComponent, IconSvgProps } from "@/types/components";
interface WizardStepperProps {
currentStep: number;
stepOffset?: number;
}
interface StepConfig {
label: string;
description: string;
icon: IconComponent;
}
interface WizardStepperProps {
currentStep: number;
stepOffset?: number;
steps?: StepConfig[];
}
const STEPS: StepConfig[] = [
{
label: "Link a Cloud Provider",
@@ -43,18 +44,21 @@ const STEPS: StepConfig[] = [
},
];
export const PROVIDER_WIZARD_STEPS = STEPS;
export function WizardStepper({
currentStep,
stepOffset = 0,
steps = STEPS,
}: WizardStepperProps) {
const activeVisualStep = Math.max(
0,
Math.min(currentStep + stepOffset, STEPS.length - 1),
Math.min(currentStep + stepOffset, steps.length - 1),
);
return (
<nav aria-label="Wizard progress" className="flex flex-col gap-0">
{STEPS.map((step, index) => {
{steps.map((step, index) => {
const isComplete = index < activeVisualStep;
const isActive = index === activeVisualStep;
const isInactive = index > activeVisualStep;
@@ -67,7 +71,7 @@ export function WizardStepper({
isActive={isActive}
icon={step.icon}
/>
{index < STEPS.length - 1 && (
{index < steps.length - 1 && (
<StepConnector isComplete={isComplete} />
)}
</div>
+5 -1
View File
@@ -1,8 +1,12 @@
"use client";
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from "react";
import { Command as CommandPrimitive } from "cmdk";
import { SearchIcon } from "lucide-react";
import {
type ComponentPropsWithoutRef,
type ElementRef,
forwardRef,
} from "react";
import {
Dialog,