Launch: implement guidance for Oracle (HMS-9004)

This commit adds launch modal for guiding users through launching a Oracle instance from their image. It provides a link to Oracle's cloud and a link for importing the image on the user's side.
This commit is contained in:
Anna Vítová 2025-08-20 11:29:17 +02:00 committed by Gianluca Zuccarelli
parent 0b96c64c93
commit 4d783537fb
2 changed files with 147 additions and 1 deletions

View file

@ -26,6 +26,7 @@ import {
} from '@patternfly/react-table';
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
import { ChromeUser } from '@redhat-cloud-services/types';
import { useFlag } from '@unleash/proxy-client-react';
import { useDispatch } from 'react-redux';
import { NavigateFunction, useNavigate } from 'react-router-dom';
@ -87,6 +88,7 @@ import {
timestampToDisplayString,
timestampToDisplayStringDetailed,
} from '../../Utilities/time';
import { OciLaunchModal } from '../Launch/OciLaunchModal';
const ImagesTable = () => {
const [page, setPage] = useState(1);
@ -403,13 +405,18 @@ type OciRowPropTypes = {
};
const OciRow = ({ compose, rowIndex }: OciRowPropTypes) => {
const launchEofFlag = useFlag('image-builder.launcheof');
const daysToExpiration = Math.floor(
computeHoursToExpiration(compose.created_at) / 24,
);
const isExpired = daysToExpiration >= OCI_STORAGE_EXPIRATION_TIME_IN_DAYS;
const details = <OciDetails compose={compose} />;
const instance = <OciInstance compose={compose} isExpired={isExpired} />;
const instance = launchEofFlag ? (
<OciLaunchModal compose={compose} isExpired={isExpired} />
) : (
<OciInstance compose={compose} isExpired={isExpired} />
);
const status = (
<ExpiringStatus
compose={compose}

View file

@ -0,0 +1,139 @@
import React, { Fragment, useState } from 'react';
import {
Button,
ClipboardCopy,
ClipboardCopyVariant,
List,
ListComponent,
ListItem,
Modal,
ModalBody,
ModalFooter,
ModalHeader,
ModalVariant,
OrderType,
Skeleton,
} from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { useNavigate } from 'react-router-dom';
import {
ComposesResponseItem,
useGetComposeStatusQuery,
} from '../../store/imageBuilderApi';
import { isOciUploadStatus } from '../../store/typeGuards';
import { resolveRelPath } from '../../Utilities/path';
type LaunchProps = {
isExpired: boolean;
compose: ComposesResponseItem;
};
export const OciLaunchModal = ({ isExpired, compose }: LaunchProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const { data, isSuccess, isFetching } = useGetComposeStatusQuery({
composeId: compose.id,
});
const navigate = useNavigate();
if (!isSuccess) {
return <Skeleton />;
}
const options = data?.image_status.upload_status?.options;
if (options && !isOciUploadStatus(options)) {
throw TypeError(
`Error: options must be of type OciUploadStatus, not ${typeof options}.`,
);
}
if (isExpired) {
return (
<Button
component='a'
target='_blank'
variant='link'
onClick={() => navigate(resolveRelPath(`imagewizard/${compose.id}`))}
isInline
>
Recreate image
</Button>
);
}
const handleModalToggle = () => {
setIsModalOpen(!isModalOpen);
};
return (
<Fragment>
<Button
variant='link'
isInline
isDisabled={data?.image_status.status === 'success' ? false : true}
onClick={handleModalToggle}
>
Image link
</Button>
<Modal
isOpen={isModalOpen}
onClose={handleModalToggle}
variant={ModalVariant.large}
aria-label='Open launch guide modal'
>
<ModalHeader
title={'Launch with Oracle Cloud Infrastructure'}
labelId='modal-title'
description={compose.image_name}
/>
<ModalBody id='modal-box-body-basic'>
<List component={ListComponent.ol} type={OrderType.number}>
<ListItem>
Navigate to the{' '}
<Button
component='a'
target='_blank'
variant='link'
icon={<ExternalLinkAltIcon />}
iconPosition='right'
href={`https://cloud.oracle.com/compute/images`}
className='pf-v6-u-pl-0'
>
Oracle Cloud&apos;s Custom Images
</Button>{' '}
page.
</ListItem>
<ListItem>
Select{' '}
<span className='pf-v6-u-font-weight-bold'>Import image</span>,
and enter the Object Storage URL of the image.
{!isFetching && (
<ClipboardCopy
isReadOnly
isExpanded
hoverTip='Copy'
clickTip='Copied'
variant={ClipboardCopyVariant.expansion}
>
{options?.url || ''}
</ClipboardCopy>
)}
{isFetching && <Skeleton />}
</ListItem>
<ListItem>
After the image is available, click on{' '}
<span className='pf-v6-u-font-weight-bold'>Create instance</span>.
</ListItem>
</List>
</ModalBody>
<ModalFooter>
<Button key='close' variant='primary' onClick={handleModalToggle}>
Close
</Button>
</ModalFooter>
</Modal>
</Fragment>
);
};