import React, { useEffect, useState } from 'react'; import { ActionGroup, Button, Form, FormGroup, FormHelperText, HelperText, HelperTextItem, Label, LabelGroup, MenuToggle, Popover, Select, SelectList, SelectOption, TextInputGroup, TextInputGroupMain, TextInputGroupUtilities, ValidatedOptions, } from '@patternfly/react-core'; import { MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle/MenuToggle'; import { ExclamationCircleIcon, HelpIcon, TimesIcon, } from '@patternfly/react-icons'; import { useNavigate } from 'react-router-dom'; import { AWS_REGIONS } from '../../constants'; import { useCloneComposeWithNotification as useCloneComposeMutation } from '../../Hooks'; import { ComposeStatus, useGetComposeStatusQuery, } from '../../store/imageBuilderApi'; import { resolveRelPath } from '../../Utilities/path'; const generateRequests = ( composeId: string, composeStatus: ComposeStatus, regions: string[], ) => { return regions.map((region) => { const options = composeStatus.request.image_requests[0].upload_request.options; return { composeId: composeId, cloneRequest: { region: region, share_with_sources: 'share_with_sources' in options ? options.share_with_sources : undefined, share_with_accounts: 'share_with_accounts' in options ? options.share_with_accounts : undefined, }, }; }); }; type RegionsSelectPropTypes = { composeId: string; handleClose: () => void; }; const RegionsSelect = ({ composeId, handleClose }: RegionsSelectPropTypes) => { const navigate = useNavigate(); const [isOpen, setIsOpen] = useState(false); const [isSaving, setIsSaving] = useState(false); const [validated, setValidated] = useState( ValidatedOptions.default, ); const initialRegions = AWS_REGIONS; const [inputValue, setInputValue] = useState(''); const [selected, setSelected] = useState([]); const [selectOptions, setSelectOptions] = useState(initialRegions); // Filter dropdown items when there is a typed input useEffect(() => { let newSelectOptions = initialRegions; if (inputValue) { newSelectOptions = initialRegions.filter((region) => region.value.toLowerCase().includes(inputValue.toLowerCase()), ); // When no options are found after filtering, display 'No results found' if (!newSelectOptions.length) { newSelectOptions = [ { disableRegion: false, description: `No results found for "${inputValue}"`, value: 'empty', }, ]; } // Open the menu when the input value changes and the new value is not empty if (!isOpen) { setIsOpen(true); } } setSelectOptions(newSelectOptions); }, [inputValue, isOpen, initialRegions]); const onTextInputChange = ( _event: React.FormEvent, value: string, ) => { setInputValue(value); }; const onSelect = (value: string) => { if (value && value !== 'no results') { setSelected( selected.includes(value) ? selected.filter((selection) => selection !== value) : [...selected, value], ); setValidated(ValidatedOptions.success); } else { setValidated(ValidatedOptions.error); } }; const { trigger: cloneCompose } = useCloneComposeMutation(); const { data: composeStatus, isSuccess } = useGetComposeStatusQuery({ composeId, }); if (!isSuccess) { return undefined; } const handleSubmit = async () => { setIsSaving(true); const requests = generateRequests(composeId, composeStatus!, selected); await Promise.allSettled(requests.map((request) => cloneCompose(request))); navigate(resolveRelPath('')); }; const handleToggle = () => { if (!selected.length) setValidated(ValidatedOptions.error); setIsOpen(!isOpen); }; const toggle = (toggleRef: React.Ref) => ( {selected.map((selection, index) => ( ))} {selected.length > 0 && ( ); }; export default RegionsSelect;