diff --git a/ui/components/providers/organizations/org-discovery-loader.tsx b/ui/components/providers/organizations/org-discovery-loader.tsx deleted file mode 100644 index 8feb2b8eaf..0000000000 --- a/ui/components/providers/organizations/org-discovery-loader.tsx +++ /dev/null @@ -1,125 +0,0 @@ -"use client"; - -import { Loader2, RefreshCw } from "lucide-react"; -import { useEffect, useRef, useState } from "react"; - -import { getDiscovery } from "@/actions/organizations/organizations"; -import { - buildOrgTreeData, - getSelectableAccountIds, -} from "@/actions/organizations/organizations.adapter"; -import { Button } from "@/components/shadcn"; -import { useOrgSetupStore } from "@/store/organizations/store"; -import { DISCOVERY_STATUS, DiscoveryResult } from "@/types/organizations"; - -const POLL_INTERVAL_MS = 3000; -const MAX_RETRIES = 60; - -interface OrgDiscoveryLoaderProps { - onDiscoveryComplete: () => void; -} - -export function OrgDiscoveryLoader({ - onDiscoveryComplete, -}: OrgDiscoveryLoaderProps) { - const { organizationId, discoveryId, setDiscovery, setSelectedAccountIds } = - useOrgSetupStore(); - - const [status, setStatus] = useState(DISCOVERY_STATUS.PENDING); - const [errorMessage, setErrorMessage] = useState(null); - const retryCountRef = useRef(0); - const pollRef = useRef | null>(null); - - const pollDiscovery = async () => { - if (!organizationId || !discoveryId) return; - - const result = await getDiscovery(organizationId, discoveryId); - - if (result?.error) { - setStatus(DISCOVERY_STATUS.FAILED); - setErrorMessage(result.error); - return; - } - - const discoveryStatus = result.data.attributes.status; - setStatus(discoveryStatus); - - if (discoveryStatus === DISCOVERY_STATUS.SUCCEEDED) { - const discoveryResult = result.data.attributes.result as DiscoveryResult; - - // Store discovery result - setDiscovery(discoveryId, discoveryResult); - - // Pre-select all selectable accounts - const selectableIds = getSelectableAccountIds(discoveryResult); - setSelectedAccountIds(selectableIds); - - // Pre-build tree data to ensure it's valid - buildOrgTreeData(discoveryResult); - - onDiscoveryComplete(); - return; - } - - if (discoveryStatus === DISCOVERY_STATUS.FAILED) { - setErrorMessage( - result.data.attributes.error ?? "Discovery failed. Please try again.", - ); - return; - } - - // Still pending or running — schedule next poll - if (retryCountRef.current >= MAX_RETRIES) { - setStatus(DISCOVERY_STATUS.FAILED); - setErrorMessage("Discovery timed out. Please try again."); - return; - } - retryCountRef.current += 1; - pollRef.current = setTimeout(pollDiscovery, POLL_INTERVAL_MS); - }; - - useEffect(() => { - pollDiscovery(); - - return () => { - if (pollRef.current) clearTimeout(pollRef.current); - }; - // Only run on mount - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const handleRetry = () => { - setStatus(DISCOVERY_STATUS.PENDING); - setErrorMessage(null); - retryCountRef.current = 0; - pollDiscovery(); - }; - - if (status === DISCOVERY_STATUS.FAILED || errorMessage) { - return ( -
-
- {errorMessage ?? "An unknown error occurred during discovery."} -
- -
- ); - } - - return ( -
- -
-

- Discovering your AWS Organization... -

-

- This may take a few moments -

-
-
- ); -} diff --git a/ui/components/providers/organizations/org-setup-form.tsx b/ui/components/providers/organizations/org-setup-form.tsx index 5f3b0ec606..78fb901afe 100644 --- a/ui/components/providers/organizations/org-setup-form.tsx +++ b/ui/components/providers/organizations/org-setup-form.tsx @@ -1,7 +1,7 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Check, Copy, ExternalLink, Loader2 } from "lucide-react"; +import { Check, Copy, ExternalLink } from "lucide-react"; import { useSession } from "next-auth/react"; import { FormEvent, useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; @@ -612,13 +612,6 @@ export function OrgSetupForm({ )} )} - - {setupPhase === ORG_SETUP_PHASE.DETAILS && isSubmitting && ( -
- - Setting up organization... -
- )} ); } diff --git a/ui/components/providers/wizard/provider-wizard-modal.tsx b/ui/components/providers/wizard/provider-wizard-modal.tsx index 9b7e689c8f..ae9a8393f3 100644 --- a/ui/components/providers/wizard/provider-wizard-modal.tsx +++ b/ui/components/providers/wizard/provider-wizard-modal.tsx @@ -5,7 +5,6 @@ import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { OrgAccountSelection } from "@/components/providers/organizations/org-account-selection"; -import { OrgDiscoveryLoader } from "@/components/providers/organizations/org-discovery-loader"; import { OrgLaunchScan } from "@/components/providers/organizations/org-launch-scan"; import { OrgSetupForm } from "@/components/providers/organizations/org-setup-form"; import { Button } from "@/components/shadcn/button/button"; @@ -47,13 +46,6 @@ const WIZARD_VARIANT = { type WizardVariant = (typeof WIZARD_VARIANT)[keyof typeof WIZARD_VARIANT]; -const VALIDATE_PHASE = { - DISCOVERY: "discovery", - SELECTION: "selection", -} as const; - -type ValidatePhase = (typeof VALIDATE_PHASE)[keyof typeof VALIDATE_PHASE]; - const EMPTY_FOOTER_CONFIG: WizardFooterConfig = { showBack: false, backLabel: "Back", @@ -97,9 +89,6 @@ export function ProviderWizardModal({ const [orgCurrentStep, setOrgCurrentStep] = useState( ORG_WIZARD_STEP.SETUP, ); - const [validatePhase, setValidatePhase] = useState( - VALIDATE_PHASE.DISCOVERY, - ); const [footerConfig, setFooterConfig] = useState(EMPTY_FOOTER_CONFIG); const [providerTypeHint, setProviderTypeHint] = useState( @@ -108,7 +97,7 @@ export function ProviderWizardModal({ const [orgSetupPhase, setOrgSetupPhase] = useState( ORG_SETUP_PHASE.DETAILS, ); - const scrollHintRefreshToken = `${wizardVariant}-${currentStep}-${orgCurrentStep}-${orgSetupPhase}-${validatePhase}`; + const scrollHintRefreshToken = `${wizardVariant}-${currentStep}-${orgCurrentStep}-${orgSetupPhase}`; const { containerRef, showScrollHint, handleScroll } = useScrollHint({ enabled: open, refreshToken: scrollHintRefreshToken, @@ -123,11 +112,7 @@ export function ProviderWizardModal({ mode, providerType, } = useProviderWizardStore(); - const { connectionResults, reset: resetOrgWizard } = useOrgSetupStore(); - - const hasConnectionErrors = Object.values(connectionResults).some( - (status) => status === "error", - ); + const { reset: resetOrgWizard } = useOrgSetupStore(); useEffect(() => { if (!open) { @@ -152,7 +137,6 @@ export function ProviderWizardModal({ ); setCurrentStep(PROVIDER_WIZARD_STEP.CREDENTIALS); setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setValidatePhase(VALIDATE_PHASE.DISCOVERY); setFooterConfig(EMPTY_FOOTER_CONFIG); setProviderTypeHint(initialData.providerType); setOrgSetupPhase(ORG_SETUP_PHASE.DETAILS); @@ -164,7 +148,6 @@ export function ProviderWizardModal({ setWizardVariant(WIZARD_VARIANT.PROVIDER); setCurrentStep(PROVIDER_WIZARD_STEP.CONNECT); setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setValidatePhase(VALIDATE_PHASE.DISCOVERY); setFooterConfig(EMPTY_FOOTER_CONFIG); setProviderTypeHint(null); setOrgSetupPhase(ORG_SETUP_PHASE.DETAILS); @@ -185,7 +168,6 @@ export function ProviderWizardModal({ setWizardVariant(WIZARD_VARIANT.PROVIDER); setCurrentStep(PROVIDER_WIZARD_STEP.CONNECT); setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setValidatePhase(VALIDATE_PHASE.DISCOVERY); setFooterConfig(EMPTY_FOOTER_CONFIG); setProviderTypeHint(null); setOrgSetupPhase(ORG_SETUP_PHASE.DETAILS); @@ -213,7 +195,6 @@ export function ProviderWizardModal({ resetOrgWizard(); setWizardVariant(WIZARD_VARIANT.ORGANIZATIONS); setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setValidatePhase(VALIDATE_PHASE.DISCOVERY); setFooterConfig(EMPTY_FOOTER_CONFIG); setProviderTypeHint(null); setOrgSetupPhase(ORG_SETUP_PHASE.DETAILS); @@ -252,33 +233,6 @@ export function ProviderWizardModal({ } : footerConfig; - useEffect(() => { - if (isProviderFlow) { - return; - } - - if ( - orgCurrentStep === ORG_WIZARD_STEP.VALIDATE && - validatePhase === VALIDATE_PHASE.DISCOVERY - ) { - setFooterConfig({ - showBack: true, - backLabel: "Back", - onBack: () => { - setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setOrgSetupPhase(ORG_SETUP_PHASE.DETAILS); - }, - showSecondaryAction: false, - secondaryActionLabel: "", - secondaryActionVariant: "outline", - secondaryActionType: WIZARD_FOOTER_ACTION_TYPE.BUTTON, - showAction: false, - actionLabel: "Next", - actionType: WIZARD_FOOTER_ACTION_TYPE.BUTTON, - }); - } - }, [isProviderFlow, orgCurrentStep, validatePhase]); - return ( )} @@ -362,7 +315,6 @@ export function ProviderWizardModal({ onBack={backToProviderFlow} onNext={() => { setOrgCurrentStep(ORG_WIZARD_STEP.VALIDATE); - setValidatePhase(VALIDATE_PHASE.SELECTION); }} onFooterChange={setFooterConfig} onPhaseChange={setOrgSetupPhase} @@ -370,40 +322,27 @@ export function ProviderWizardModal({ /> )} - {!isProviderFlow && - orgCurrentStep === ORG_WIZARD_STEP.VALIDATE && - validatePhase === VALIDATE_PHASE.DISCOVERY && ( - { - setValidatePhase(VALIDATE_PHASE.SELECTION); - }} - /> - )} - - {!isProviderFlow && - orgCurrentStep === ORG_WIZARD_STEP.VALIDATE && - validatePhase === VALIDATE_PHASE.SELECTION && ( - { - setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); - setOrgSetupPhase(ORG_SETUP_PHASE.ACCESS); - }} - onNext={() => { - setOrgCurrentStep(ORG_WIZARD_STEP.LAUNCH); - }} - onSkip={() => { - setOrgCurrentStep(ORG_WIZARD_STEP.LAUNCH); - }} - onFooterChange={setFooterConfig} - /> - )} + {!isProviderFlow && orgCurrentStep === ORG_WIZARD_STEP.VALIDATE && ( + { + setOrgCurrentStep(ORG_WIZARD_STEP.SETUP); + setOrgSetupPhase(ORG_SETUP_PHASE.ACCESS); + }} + onNext={() => { + setOrgCurrentStep(ORG_WIZARD_STEP.LAUNCH); + }} + onSkip={() => { + setOrgCurrentStep(ORG_WIZARD_STEP.LAUNCH); + }} + onFooterChange={setFooterConfig} + /> + )} {!isProviderFlow && orgCurrentStep === ORG_WIZARD_STEP.LAUNCH && ( { setOrgCurrentStep(ORG_WIZARD_STEP.VALIDATE); - setValidatePhase(VALIDATE_PHASE.SELECTION); }} onFooterChange={setFooterConfig} /> diff --git a/ui/components/providers/wizard/wizard-stepper.tsx b/ui/components/providers/wizard/wizard-stepper.tsx index 229600d5d7..2ae67291ee 100644 --- a/ui/components/providers/wizard/wizard-stepper.tsx +++ b/ui/components/providers/wizard/wizard-stepper.tsx @@ -9,7 +9,6 @@ import { IconComponent, IconSvgProps } from "@/types/components"; interface WizardStepperProps { currentStep: number; - hasConnectionErrors?: boolean; stepOffset?: number; } @@ -46,7 +45,6 @@ const STEPS: StepConfig[] = [ export function WizardStepper({ currentStep, - hasConnectionErrors: _hasConnectionErrors = false, stepOffset = 0, }: WizardStepperProps) { const activeVisualStep = Math.max(