buildImageButton: add support of building image with mulitple targets <HMS-4066>
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.
This commit is contained in:
parent
67ec26bead
commit
39b29e303c
2 changed files with 174 additions and 10 deletions
|
|
@ -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 { selectSelectedBlueprintId } from '../../store/BlueprintSlice';
|
||||||
import { useAppSelector } from '../../store/hooks';
|
import {useAppDispatch, useAppSelector} from '../../store/hooks';
|
||||||
import { useComposeBlueprintMutation } from '../../store/imageBuilderApi';
|
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<ImageTypes[]>([]);
|
||||||
|
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<Element, 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 (
|
||||||
|
<Dropdown
|
||||||
|
isOpen={isOpen}
|
||||||
|
onOpenChange={(isOpen: boolean) => setIsOpen(isOpen)}
|
||||||
|
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
||||||
|
<MenuToggle
|
||||||
|
variant="primary"
|
||||||
|
ref={toggleRef}
|
||||||
|
isFullWidth
|
||||||
|
onClick={onToggleClick}
|
||||||
|
isExpanded={isOpen}
|
||||||
|
splitButtonOptions={{
|
||||||
|
variant: 'action',
|
||||||
|
items: [
|
||||||
|
<MenuToggleAction
|
||||||
|
key="split-action"
|
||||||
|
onClick={onBuildHandler}
|
||||||
|
id="wizard-build-image-btn"
|
||||||
|
isDisabled={
|
||||||
|
!selectedBlueprintId ||
|
||||||
|
deselectedTargets.length === blueprintImageType?.length
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Flex display={{ default: 'inlineFlex' }}>
|
||||||
|
{imageBuildLoading && (
|
||||||
|
<FlexItem>
|
||||||
|
<Spinner
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
'--pf-v5-c-spinner--Color': '#fff',
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
isInline
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
</FlexItem>
|
||||||
|
)}
|
||||||
|
<FlexItem>
|
||||||
|
{deselectedTargets.length !== 0
|
||||||
|
? 'Build selected'
|
||||||
|
: 'Build image'}
|
||||||
|
</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</MenuToggleAction>,
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
></MenuToggle>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Menu onSelect={onSelect} selected={blueprintImageType}>
|
||||||
|
<MenuContent>
|
||||||
|
<MenuList>
|
||||||
|
{blueprintImageType?.map((imageType, index) => (
|
||||||
|
<MenuItem
|
||||||
|
key={imageType}
|
||||||
|
hasCheckbox
|
||||||
|
itemId={index}
|
||||||
|
isSelected={
|
||||||
|
!deselectedTargets || !deselectedTargets.includes(imageType)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{handleToggleEnvironment(imageType)}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</MenuList>
|
||||||
|
</MenuContent>
|
||||||
|
</Menu>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type BuildImagesButtonEmptyStatePropTypes = {
|
||||||
variant?: ButtonProps['variant'];
|
variant?: ButtonProps['variant'];
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BuildImagesButton = ({
|
export const BuildImagesButtonEmptyState = ({
|
||||||
variant,
|
variant,
|
||||||
children,
|
children,
|
||||||
}: BuildImagesButtonPropTypes) => {
|
}: BuildImagesButtonEmptyStatePropTypes) => {
|
||||||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||||
const [buildBlueprint, { isLoading: imageBuildLoading }] =
|
const [buildBlueprint, { isLoading: imageBuildLoading }] =
|
||||||
useComposeBlueprintMutation();
|
useComposeBlueprintMutation();
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@ import {
|
||||||
CREATING_IMAGES_WITH_IB_SERVICE_URL,
|
CREATING_IMAGES_WITH_IB_SERVICE_URL,
|
||||||
MANAGING_WITH_DNF_URL,
|
MANAGING_WITH_DNF_URL,
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { BuildImagesButton } from '../Blueprints/BuildImagesButton';
|
|
||||||
|
import { BuildImagesButtonEmptyState } from '../Blueprints/BuildImagesButton';
|
||||||
|
|
||||||
type ImagesEmptyStateProps = {
|
type ImagesEmptyStateProps = {
|
||||||
selectedBlueprint?: string;
|
selectedBlueprint?: string;
|
||||||
|
|
@ -44,9 +45,9 @@ const EmptyBlueprintsImagesTable = () => (
|
||||||
</EmptyStateBody>
|
</EmptyStateBody>
|
||||||
<EmptyStateFooter>
|
<EmptyStateFooter>
|
||||||
<EmptyStateActions>
|
<EmptyStateActions>
|
||||||
<BuildImagesButton variant="link">
|
<BuildImagesButtonEmptyState variant="link">
|
||||||
Build latest images
|
Build latest images
|
||||||
</BuildImagesButton>
|
</BuildImagesButtonEmptyState>
|
||||||
</EmptyStateActions>
|
</EmptyStateActions>
|
||||||
</EmptyStateFooter>
|
</EmptyStateFooter>
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue