From 39b29e303c02f5edf46bfca3cfd320bb5c56bebb Mon Sep 17 00:00:00 2001 From: Michal Gold Date: Thu, 23 May 2024 12:57:25 +0300 Subject: [PATCH] buildImageButton: add support of building image with mulitple targets this commit add support of building an image with mulitple targets, when user build an image, he can choose which targets he wants to build. --- .../Blueprints/BuildImagesButton.tsx | 177 +++++++++++++++++- src/Components/ImagesTable/EmptyState.tsx | 7 +- 2 files changed, 174 insertions(+), 10 deletions(-) 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 - +