+
- ) : thereIsNoProvidersConnected ? (
- <>
-
- >
- ) : (
-
- )}
- >
-
+ )}
>
);
diff --git a/ui/components/scans/launch-workflow/launch-scan-workflow-form.tsx b/ui/components/scans/launch-workflow/launch-scan-workflow-form.tsx
index b0047445c7..6ee64724ba 100644
--- a/ui/components/scans/launch-workflow/launch-scan-workflow-form.tsx
+++ b/ui/components/scans/launch-workflow/launch-scan-workflow-form.tsx
@@ -11,23 +11,15 @@ import { Button } from "@/components/shadcn";
import { CustomInput } from "@/components/ui/custom";
import { Form } from "@/components/ui/form";
import { toast } from "@/components/ui/toast";
-import { onDemandScanFormSchema } from "@/types";
+import { onDemandScanFormSchema, ScanProviderInfo } from "@/types";
import { SCAN_LAUNCHED_EVENT } from "../table/scans/scans-table-with-polling";
import { SelectScanProvider } from "./select-scan-provider";
-type ProviderInfo = {
- providerId: string;
- alias: string;
- providerType: string;
- uid: string;
- connected: boolean;
-};
-
export const LaunchScanWorkflow = ({
providers,
}: {
- providers: ProviderInfo[];
+ providers: ScanProviderInfo[];
}) => {
const formSchema = z.object({
...onDemandScanFormSchema().shape,
diff --git a/ui/components/scans/launch-workflow/select-scan-provider.tsx b/ui/components/scans/launch-workflow/select-scan-provider.tsx
index 999c65bea4..9d8be12e3e 100644
--- a/ui/components/scans/launch-workflow/select-scan-provider.tsx
+++ b/ui/components/scans/launch-workflow/select-scan-provider.tsx
@@ -11,18 +11,13 @@ import {
} from "@/components/shadcn";
import { EntityInfo } from "@/components/ui/entities";
import { FormControl, FormField, FormMessage } from "@/components/ui/form";
+import { ScanProviderInfo } from "@/types";
interface SelectScanProviderProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath
= FieldPath,
> {
- providers: {
- providerId: string;
- alias: string;
- providerType: string;
- uid: string;
- connected: boolean;
- }[];
+ providers: ScanProviderInfo[];
control: Control;
name: TName;
}
diff --git a/ui/components/scans/no-providers-added.tsx b/ui/components/scans/no-providers-added.tsx
index b5f7e08766..a108009c2d 100644
--- a/ui/components/scans/no-providers-added.tsx
+++ b/ui/components/scans/no-providers-added.tsx
@@ -1,45 +1,38 @@
"use client";
-import { useState } from "react";
-
-import { ProviderWizardModal } from "@/components/providers/wizard";
import { Button, Card, CardContent } from "@/components/shadcn";
import { InfoIcon } from "../icons/Icons";
-export const NoProvidersAdded = () => {
- const [open, setOpen] = useState(false);
+interface NoProvidersAddedProps {
+ onOpenWizard: () => void;
+}
- return (
- <>
-
-
-
-
-
-
- No Providers Configured
-
-
-
-
- No providers have been configured. Start by setting up a
- provider.
-
-
+export const NoProvidersAdded = ({ onOpenWizard }: NoProvidersAddedProps) => (
+
+
+
+
+
+
+ No Providers Configured
+
+
+
+
+ No providers have been configured. Start by setting up a provider.
+
+
-
-
-
-
-
- >
- );
-};
+
+
+
+
+);
diff --git a/ui/components/scans/scans-launch-section.test.tsx b/ui/components/scans/scans-launch-section.test.tsx
new file mode 100644
index 0000000000..7abee44117
--- /dev/null
+++ b/ui/components/scans/scans-launch-section.test.tsx
@@ -0,0 +1,62 @@
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { describe, expect, it, vi } from "vitest";
+
+import { ScansLaunchSection } from "./scans-launch-section";
+
+vi.mock("@/components/providers/wizard", () => ({
+ ProviderWizardModal: ({ open }: { open: boolean }) =>
+ open ? Provider wizard
: null,
+}));
+
+vi.mock("@/components/scans/launch-workflow", () => ({
+ LaunchScanWorkflow: () => Launch scan workflow
,
+}));
+
+vi.mock("@/components/scans/no-providers-connected", () => ({
+ NoProvidersConnected: () => No providers connected
,
+}));
+
+vi.mock("@/components/ui/custom/custom-banner", () => ({
+ CustomBanner: ({ title }: { title: string }) => {title}
,
+}));
+
+const connectedProvider = {
+ providerId: "provider-1",
+ alias: "Production",
+ providerType: "aws",
+ uid: "123456789012",
+ connected: true,
+};
+
+describe("ScansLaunchSection", () => {
+ it("should keep the provider wizard open when providers data refreshes after adding the first provider", async () => {
+ // Given
+ const user = userEvent.setup();
+ const { rerender } = render(
+ ,
+ );
+
+ // When
+ await user.click(
+ screen.getByRole("button", { name: /open add provider modal/i }),
+ );
+ rerender(
+ ,
+ );
+
+ // Then
+ expect(screen.getByRole("dialog")).toHaveTextContent("Provider wizard");
+ expect(screen.getByText("Launch scan workflow")).toBeInTheDocument();
+ });
+});
diff --git a/ui/components/scans/scans-launch-section.tsx b/ui/components/scans/scans-launch-section.tsx
new file mode 100644
index 0000000000..f683155a21
--- /dev/null
+++ b/ui/components/scans/scans-launch-section.tsx
@@ -0,0 +1,47 @@
+"use client";
+
+import { useState } from "react";
+
+import { ProviderWizardModal } from "@/components/providers/wizard";
+import { LaunchScanWorkflow } from "@/components/scans/launch-workflow";
+import { NoProvidersAdded } from "@/components/scans/no-providers-added";
+import { NoProvidersConnected } from "@/components/scans/no-providers-connected";
+import { CustomBanner } from "@/components/ui/custom/custom-banner";
+import { ScanProviderInfo } from "@/types";
+
+interface ScansLaunchSectionProps {
+ providers: ScanProviderInfo[];
+ hasManageScansPermission: boolean;
+ thereIsNoProviders: boolean;
+ thereIsNoProvidersConnected: boolean;
+}
+
+export function ScansLaunchSection({
+ providers,
+ hasManageScansPermission,
+ thereIsNoProviders,
+ thereIsNoProvidersConnected,
+}: ScansLaunchSectionProps) {
+ const [isProviderWizardOpen, setIsProviderWizardOpen] = useState(false);
+
+ return (
+ <>
+ {thereIsNoProviders ? (
+ setIsProviderWizardOpen(true)} />
+ ) : !hasManageScansPermission ? (
+
+ ) : thereIsNoProvidersConnected ? (
+
+ ) : (
+
+ )}
+
+ >
+ );
+}
diff --git a/ui/types/scans.ts b/ui/types/scans.ts
index 2cfabf009d..b90689440d 100644
--- a/ui/types/scans.ts
+++ b/ui/types/scans.ts
@@ -45,18 +45,26 @@ export interface ScanRelationships {
task: RelationshipWrapper;
}
-export interface ScanProviderInfo {
+export interface ScanResultProviderInfo {
provider: ProviderType;
uid: string;
alias: string;
}
+export interface ScanProviderInfo {
+ providerId: string;
+ alias: string;
+ providerType: string;
+ uid: string;
+ connected: boolean;
+}
+
export interface ScanProps {
type: "scans";
id: string;
attributes: ScanAttributes;
relationships: ScanRelationships;
- providerInfo?: ScanProviderInfo;
+ providerInfo?: ScanResultProviderInfo;
}
export interface ScanEntityProviderInfo {
@@ -77,7 +85,7 @@ export interface ScanEntity {
}
export interface ExpandedScanData extends ScanProps {
- providerInfo: ScanProviderInfo;
+ providerInfo: ScanResultProviderInfo;
}
export interface IncludedResource {