import React, { useEffect, useState } from 'react'; import { Button, ButtonProps, Dropdown, Flex, FlexItem, Menu, MenuContent, MenuItem, MenuList, MenuToggle, MenuToggleAction, Spinner, } from '@patternfly/react-core'; import { MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle/MenuToggle'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; import { ChromeUser } from '@redhat-cloud-services/types'; import { skipToken } from '@reduxjs/toolkit/query'; import { AMPLITUDE_MODULE_NAME, targetOptions } from '../../constants'; import { useComposeBPWithNotification as useComposeBlueprintMutation } from '../../Hooks'; import { useGetBlueprintQuery } from '../../store/backendApi'; import { selectSelectedBlueprintId } from '../../store/BlueprintSlice'; import { useAppSelector } from '../../store/hooks'; import { ImageTypes } from '../../store/imageBuilderApi'; type BuildImagesButtonPropTypes = { // default children is 'Build images' children?: React.ReactNode; }; export const BuildImagesButton = ({ children }: BuildImagesButtonPropTypes) => { const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const [deselectedTargets, setDeselectedTargets] = useState([]); const { trigger: buildBlueprint, isLoading: imageBuildLoading } = useComposeBlueprintMutation(); const { analytics, auth } = useChrome(); const [userData, setUserData] = useState(undefined); useEffect(() => { (async () => { const data = await auth.getUser(); setUserData(data); })(); // This useEffect hook should run *only* on mount and therefore has an empty // dependency array. eslint's exhaustive-deps rule does not support this use. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onBuildHandler = async () => { if (selectedBlueprintId) { await buildBlueprint({ id: selectedBlueprintId, body: { image_types: blueprintImageType?.filter( (target) => !deselectedTargets.includes(target), ), }, }); if (!process.env.IS_ON_PREMISE) { analytics.track(`${AMPLITUDE_MODULE_NAME} - Image Requested`, { module: AMPLITUDE_MODULE_NAME, trigger: 'synchronize images', account_id: userData?.identity.internal?.account_id || 'Not found', }); } } }; const [isOpen, setIsOpen] = useState(false); const onToggleClick = () => { setIsOpen(!isOpen); }; const { data: blueprintDetails } = useGetBlueprintQuery( selectedBlueprintId ? { id: selectedBlueprintId } : skipToken, ); const blueprintImageType = blueprintDetails?.image_requests.map( (image) => image.image_type, ); const onSelect = ( _event: React.MouseEvent, itemId: number, ) => { const imageType = blueprintImageType?.[itemId]; if (imageType && deselectedTargets.includes(imageType)) { setDeselectedTargets( deselectedTargets.filter((target) => target !== imageType), ); } else if (imageType) { setDeselectedTargets([...deselectedTargets, imageType]); } }; return ( setIsOpen(isOpen)} toggle={(toggleRef: React.Ref) => ( {imageBuildLoading && ( )} {children ? children : 'Build images'} , ]} > )} > {blueprintImageType?.map((imageType, index) => ( {targetOptions[imageType]} ))} ); }; type BuildImagesButtonEmptyStatePropTypes = { variant?: ButtonProps['variant']; children?: React.ReactNode; }; export const BuildImagesButtonEmptyState = ({ variant, children, }: BuildImagesButtonEmptyStatePropTypes) => { const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const { trigger: buildBlueprint, isLoading: imageBuildLoading } = useComposeBlueprintMutation(); const onBuildHandler = async () => { if (selectedBlueprintId) { await buildBlueprint({ id: selectedBlueprintId, body: {} }); } }; return ( ); };