diff --git a/src/Components/Blueprints/BuildImagesButton.tsx b/src/Components/Blueprints/BuildImagesButton.tsx index 7f9b4f69..9461baa3 100644 --- a/src/Components/Blueprints/BuildImagesButton.tsx +++ b/src/Components/Blueprints/BuildImagesButton.tsx @@ -1,20 +1,183 @@ -import React from 'react'; +import React, { useState } from 'react'; -import { Button, ButtonProps } from '@patternfly/react-core'; +import { + Dropdown, + MenuToggle, + MenuToggleElement, + Menu, + MenuContent, + MenuList, + MenuItem, + Flex, + FlexItem, + Spinner, + MenuToggleAction, + ButtonProps, + Button, +} from '@patternfly/react-core'; +import { skipToken } from '@reduxjs/toolkit/query'; import { selectSelectedBlueprintId } from '../../store/BlueprintSlice'; -import { useAppSelector } from '../../store/hooks'; -import { useComposeBlueprintMutation } from '../../store/imageBuilderApi'; +import {useAppDispatch, useAppSelector} from '../../store/hooks'; +import { + ImageTypes, + useComposeBlueprintMutation, + useGetBlueprintQuery, +} from '../../store/imageBuilderApi'; +import {addNotification} from "@redhat-cloud-services/frontend-components-notifications/redux"; -type BuildImagesButtonPropTypes = { +export const BuildImagesButton = () => { + const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); + const [deselectedTargets, setDeselectedTargets] = useState([]); + const [buildBlueprint, { isLoading: imageBuildLoading, isError: imageBuildError }] = + useComposeBlueprintMutation(); + const dispatch = useAppDispatch(); + + const onBuildHandler = async () => { + if (selectedBlueprintId) { + try{ + await buildBlueprint({ + id: selectedBlueprintId, + body: { + image_types: blueprintImageType?.filter( + (target) => !deselectedTargets?.includes(target) + ), + }, + })} + catch(imageBuildError) { + dispatch( + addNotification({ + variant: 'warning', + title: 'No blueprint was build', + }) + ); + } + } + }; + 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]); + } + }; + + const handleToggleEnvironment = (target: ImageTypes) => { + switch (target) { + case 'aws': + return 'Amazon Web Services (AWS)'; + case 'gcp': + return 'Google Cloud Platform (GCP)'; + case 'azure': + return 'Microsoft Azure'; + case 'oci': + return 'Oracle Cloud Infrastructure'; + case 'vsphere-ova': + return 'VMware vSphere'; + case 'guest-image': + return 'Virtualization - Guest image (.qcow2)'; + case 'image-installer': + return 'Bare metal - Installer'; + } + }; + return ( + setIsOpen(isOpen)} + toggle={(toggleRef: React.Ref) => ( + + + {imageBuildLoading && ( + + + + )} + + {deselectedTargets.length !== 0 + ? 'Build selected' + : 'Build image'} + + + , + ], + }} + > + )} + > + + + + {blueprintImageType?.map((imageType, index) => ( + + {handleToggleEnvironment(imageType)} + + ))} + + + + + ); +}; + +type BuildImagesButtonEmptyStatePropTypes = { variant?: ButtonProps['variant']; children?: React.ReactNode; }; -export const BuildImagesButton = ({ +export const BuildImagesButtonEmptyState = ({ variant, children, -}: BuildImagesButtonPropTypes) => { +}: BuildImagesButtonEmptyStatePropTypes) => { const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const [buildBlueprint, { isLoading: imageBuildLoading }] = useComposeBlueprintMutation(); diff --git a/src/Components/ImagesTable/EmptyState.tsx b/src/Components/ImagesTable/EmptyState.tsx index e5ba9f2b..fa9549fc 100644 --- a/src/Components/ImagesTable/EmptyState.tsx +++ b/src/Components/ImagesTable/EmptyState.tsx @@ -22,7 +22,8 @@ import { CREATING_IMAGES_WITH_IB_SERVICE_URL, MANAGING_WITH_DNF_URL, } from '../../constants'; -import { BuildImagesButton } from '../Blueprints/BuildImagesButton'; + +import { BuildImagesButtonEmptyState } from '../Blueprints/BuildImagesButton'; type ImagesEmptyStateProps = { selectedBlueprint?: string; @@ -44,9 +45,9 @@ const EmptyBlueprintsImagesTable = () => ( - + Build latest images - +