src: Rename "V2" folders to just Wizard

This replaces all occurences of "CreateImageWizardV2" with just "CreateImageWizard" as it is the only version now.
This commit is contained in:
regexowl 2024-07-16 17:10:37 +02:00 committed by Ondřej Ezr
parent b1e5a8c7c6
commit 4fb37c187e
93 changed files with 20 additions and 22 deletions

View file

@ -0,0 +1,168 @@
import React from 'react';
import {
Alert,
Spinner,
Text,
TextContent,
TextList,
TextListItem,
TextListItemVariants,
TextListVariants,
TextVariants,
} from '@patternfly/react-core';
import { Button, Popover } from '@patternfly/react-core';
import { HelpIcon } from '@patternfly/react-icons';
import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
import { useAppSelector } from '../../../../store/hooks';
import { useShowActivationKeyQuery } from '../../../../store/rhsmApi';
import { selectActivationKey } from '../../../../store/wizardSlice';
const ActivationKeyInformation = (): JSX.Element => {
const activationKey = useAppSelector(selectActivationKey);
const {
data: activationKeyInfo,
isFetching: isFetchingActivationKeyInfo,
isSuccess: isSuccessActivationKeyInfo,
isError: isErrorActivationKeyInfo,
} = useShowActivationKeyQuery(
{ name: activationKey! },
{
skip: !activationKey,
}
);
return (
<>
{isFetchingActivationKeyInfo && <Spinner size="lg" />}
{isSuccessActivationKeyInfo && (
<TextContent>
<TextList component={TextListVariants.dl}>
<TextListItem component={TextListItemVariants.dt}>
Name:
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{activationKey}
</TextListItem>
<TextListItem component={TextListItemVariants.dt}>
Role:
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{activationKeyInfo.body?.role || 'Not defined'}
</TextListItem>
<TextListItem component={TextListItemVariants.dt}>
SLA:
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{activationKeyInfo.body?.serviceLevel || 'Not defined'}
</TextListItem>
<TextListItem component={TextListItemVariants.dt}>
Usage:
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{activationKeyInfo.body?.usage || 'Not defined'}
</TextListItem>
<TextListItem component={TextListItemVariants.dt}>
Additional repositories:
<Popover
bodyContent={
<TextContent>
<Text>
The core repositories for your operating system version
are always enabled and do not need to be explicitly added
to the activation key.
</Text>
</TextContent>
}
>
<Button
variant="plain"
aria-label="About additional repositories"
className="pf-u-pl-sm pf-u-pt-0 pf-u-pb-0"
>
<HelpIcon />
</Button>
</Popover>
</TextListItem>
<TextListItem
component={TextListItemVariants.dd}
className="pf-u-display-flex pf-u-align-items-flex-end"
>
{activationKeyInfo.body?.additionalRepositories &&
activationKeyInfo.body?.additionalRepositories?.length > 0 ? (
<Popover
position="right"
minWidth="30rem"
bodyContent={
<TextContent>
<Text component={TextVariants.h3}>
Additional repositories
</Text>
<Table
aria-label="Additional repositories table"
variant="compact"
>
<Thead>
<Tr>
<Th>Name</Th>
</Tr>
</Thead>
<Tbody data-testid="additional-repositories-table">
{activationKeyInfo.body?.additionalRepositories?.map(
(repo, index) => (
<Tr key={index}>
<Td>{repo.repositoryLabel}</Td>
</Tr>
)
)}
</Tbody>
</Table>
</TextContent>
}
>
<Button
data-testid="repositories-popover-button"
variant="link"
aria-label="Show additional repositories"
className="pf-u-pl-0 pf-u-pt-0 pf-u-pb-0"
>
{activationKeyInfo.body?.additionalRepositories?.length}{' '}
repositories
</Button>
</Popover>
) : (
'None'
)}
</TextListItem>
</TextList>
</TextContent>
)}
{isErrorActivationKeyInfo && (
<TextContent>
<TextList component={TextListVariants.dl}>
<TextListItem component={TextListItemVariants.dt}>
Name:
</TextListItem>
<TextListItem component={TextListItemVariants.dd}>
{activationKey}
</TextListItem>
</TextList>
<br />
<Alert
title="Information about the activation key unavailable"
variant="danger"
isPlain
isInline
>
Information about the activation key cannot be loaded. Please check
the key was not removed and try again later.
</Alert>
</TextContent>
)}
</>
);
};
export default ActivationKeyInformation;

View file

@ -0,0 +1,292 @@
import React, { useEffect, useState } from 'react';
import {
Alert,
FormGroup,
Spinner,
EmptyState,
Button,
EmptyStateIcon,
EmptyStateBody,
EmptyStateHeader,
EmptyStateFooter,
EmptyStateActions,
Text,
TextContent,
Popover,
} from '@patternfly/react-core';
import {
Select,
SelectOption,
SelectVariant,
} from '@patternfly/react-core/deprecated';
import { WrenchIcon, AddCircleOIcon } from '@patternfly/react-icons';
import { ExternalLinkAltIcon, HelpIcon } from '@patternfly/react-icons';
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
import {
ACTIVATION_KEYS_PROD_URL,
ACTIVATION_KEYS_STAGE_URL,
CDN_PROD_URL,
CDN_STAGE_URL,
} from '../../../../constants';
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
import {
useListActivationKeysQuery,
useCreateActivationKeysMutation,
} from '../../../../store/rhsmApi';
import {
changeActivationKey,
changeBaseUrl,
changeServerUrl,
selectActivationKey,
} from '../../../../store/wizardSlice';
import { useGetEnvironment } from '../../../../Utilities/useGetEnvironment';
export const PopoverActivation = () => {
const [orgId, setOrgId] = useState<string | undefined>(undefined);
const { auth } = useChrome();
useEffect(() => {
(async () => {
const userData = await auth?.getUser();
const id = userData?.identity?.internal?.org_id;
setOrgId(id);
})();
});
return (
<Popover
hasAutoWidth
maxWidth="35rem"
bodyContent={
<TextContent>
<Text>
Activation keys enable you to register a system with appropriate
subscriptions, system purpose, and repositories attached.
</Text>
<Text>
If using an activation key with command line registration, you must
provide your organization&apos;s ID.
</Text>
{orgId ? (
<Text>Your organization&apos;s ID is {orgId}</Text>
) : (
<Spinner size="md" />
)}
</TextContent>
}
>
<Button
variant="plain"
aria-label="Activation key popover"
aria-describedby="subscription-activation-key"
className="pf-u-pl-sm pf-u-pt-0 pf-u-pb-0 pf-u-pr-0"
>
<HelpIcon />
</Button>
</Popover>
);
};
type EmptyActivationsKeyStateProps = {
handleActivationKeyFn: Function;
isLoading: boolean;
};
const EmptyActivationsKeyState = ({
handleActivationKeyFn,
isLoading,
}: EmptyActivationsKeyStateProps) => (
<EmptyState variant="xs">
<EmptyStateHeader
titleText="No activation keys found"
headingLevel="h4"
icon={<EmptyStateIcon icon={WrenchIcon} />}
/>
<EmptyStateBody>
Get started by building a default key, which will be generated and present
for you.
</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateActions>
<Button
onClick={() => handleActivationKeyFn()}
icon={<AddCircleOIcon />}
isLoading={isLoading}
iconPosition="left"
variant="link"
>
Create activation key
</Button>
</EmptyStateActions>
</EmptyStateFooter>
</EmptyState>
);
const ManageKeysButton = () => {
const { isProd } = useGetEnvironment();
return (
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={isProd() ? ACTIVATION_KEYS_PROD_URL : ACTIVATION_KEYS_STAGE_URL}
>
Activation keys page
</Button>
);
};
const ActivationKeysList = () => {
const dispatch = useAppDispatch();
const activationKey = useAppSelector(selectActivationKey);
const { isProd } = useGetEnvironment();
const [isOpen, setIsOpen] = useState(false);
const {
data: activationKeys,
isFetching: isFetchingActivationKeys,
isSuccess: isSuccessActivationKeys,
isError: isErrorActivationKeys,
refetch,
} = useListActivationKeysQuery();
const [createActivationKey, { isLoading: isLoadingActivationKey }] =
useCreateActivationKeysMutation();
useEffect(() => {
if (isProd()) {
dispatch(changeServerUrl('subscription.rhsm.redhat.com'));
dispatch(changeBaseUrl(CDN_PROD_URL));
} else {
dispatch(changeServerUrl('subscription.rhsm.stage.redhat.com'));
dispatch(changeBaseUrl(CDN_STAGE_URL));
}
}, [dispatch, isProd]);
const setActivationKey = (
_event: React.MouseEvent<Element, MouseEvent>,
selection: string
) => {
setIsOpen(false);
dispatch(changeActivationKey(selection));
};
const handleClear = () => {
dispatch(changeActivationKey(undefined));
};
const handleToggle = () => {
if (!isOpen) {
refetch();
}
setIsOpen(!isOpen);
};
const handleCreateActivationKey = async () => {
try {
await createActivationKey({
body: {
name: 'activation-key-default',
serviceLevel: 'Self-Support',
},
});
refetch();
} catch (error) {
dispatch(
addNotification({
variant: 'danger',
title: 'Error creating activation key',
description: error?.data?.error?.message,
})
);
}
};
const setSelectOptions = () => {
const selectOptions = [];
if (isActivationKeysEmpty) {
selectOptions.push(
<EmptyActivationsKeyState
handleActivationKeyFn={handleCreateActivationKey}
isLoading={isLoadingActivationKey}
key={'Empty'}
/>
);
}
if (isSuccessActivationKeys) {
activationKeys.body?.map((key, index) =>
selectOptions.push(<SelectOption key={index} value={key.name} />)
);
}
if (!isSuccessActivationKeys && isFetchingActivationKeys) {
selectOptions.push(
<SelectOption
key={'Fetching'}
isNoResultsOption={true}
data-testid="activation-keys-loading"
>
<Spinner size="md" />
</SelectOption>
);
}
return selectOptions;
};
const isActivationKeysEmpty =
isSuccessActivationKeys && activationKeys.body?.length === 0;
return (
<>
<FormGroup
isRequired={true}
label={
<>
Activation key to use for this image <PopoverActivation />
</>
}
data-testid="subscription-activation-key"
>
<Select
ouiaId="activation_key_select"
variant={SelectVariant.typeahead}
onToggle={handleToggle}
onSelect={setActivationKey}
onClear={handleClear}
selections={activationKey}
isOpen={isOpen}
placeholderText="Select activation key"
typeAheadAriaLabel="Select activation key"
isDisabled={!isSuccessActivationKeys}
>
{setSelectOptions()}
</Select>
<TextContent>
<Text>
By default, activation key is generated and preset for you. Admins
can create and manage keys by visiting the <ManageKeysButton />
</Text>
</TextContent>
</FormGroup>
{isErrorActivationKeys && (
<Alert
title="Activation keys unavailable"
variant="danger"
isPlain
isInline
>
Activation keys cannot be reached, try again later.
</Alert>
)}
</>
);
};
export default ActivationKeysList;

View file

@ -0,0 +1,41 @@
import React from 'react';
import {
Button,
Text,
TextContent,
TextVariants,
} from '@patternfly/react-core';
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
import { RHC_URL } from '../../../../constants';
const RegisterLaterInformation = () => {
return (
<TextContent>
<Text component={TextVariants.h3}>Register later</Text>
<Text>
On initial boot, systems will need to be registered manually before
having access to updates or Red Hat services. Registering and connecting
your systems during the image creation is recommended.
</Text>
<Text>
If you prefer to register later, review the instructions for manual
registration with remote host configuration.
</Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={RHC_URL}
>
Registering with remote host configuration
</Button>
</TextContent>
);
};
export default RegisterLaterInformation;

View file

@ -0,0 +1,254 @@
import React, { useState } from 'react';
import {
Button,
Checkbox,
FormGroup,
Popover,
Radio,
Text,
TextContent,
} from '@patternfly/react-core';
import { HelpIcon, ExternalLinkAltIcon } from '@patternfly/react-icons';
import {
INSIGHTS_URL,
RHC_URL,
SUBSCRIPTION_MANAGEMENT_URL,
} from '../../../../constants';
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
import {
changeActivationKey,
changeRegistrationType,
selectRegistrationType,
} from '../../../../store/wizardSlice';
const RHSMPopover = () => {
return (
<Popover
headerContent="About Red Hat Subscription Management"
position="right"
minWidth="30rem"
bodyContent={
<TextContent>
<Text>
Registered systems are entitled to support services, errata,
patches, and upgrades.
</Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={SUBSCRIPTION_MANAGEMENT_URL}
>
Learn more about Red Hat Subscription Management
</Button>
</TextContent>
}
>
<Button
variant="plain"
className="pf-u-pl-sm pf-u-pt-0 pf-u-pb-0"
aria-label="About remote host configuration (rhc)"
isInline
>
<HelpIcon />
</Button>
</Popover>
);
};
const InsightsPopover = () => {
return (
<Popover
headerContent="About Red Hat Insights"
position="right"
minWidth="30rem"
bodyContent={
<TextContent>
<Text>
Red Hat Insights client provides actionable intelligence about your
Red Hat Enterprise Linux environments, helping to identify and
address operational and vulnerability risks before an issue results
in downtime.
</Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={INSIGHTS_URL}
>
Learn more about Red Hat Insights
</Button>
</TextContent>
}
>
<Button
variant="plain"
className="pf-u-pl-sm pf-u-pt-0 pf-u-pb-0"
aria-label="About remote host configuration (rhc)"
isInline
>
<HelpIcon />
</Button>
</Popover>
);
};
const RhcPopover = () => {
return (
<Popover
headerContent="About remote host configuration (rhc)"
position="right"
minWidth="30rem"
bodyContent={
<TextContent>
<Text>
Remote host configuration allows Red Hat Enterprise Linux hosts to
connect to Red Hat Insights. Remote host configuration is required
to use the Red Hat Insights Remediations service.
</Text>
<Button
component="a"
target="_blank"
variant="link"
icon={<ExternalLinkAltIcon />}
iconPosition="right"
isInline
href={RHC_URL}
>
Learn more about remote host configuration
</Button>
</TextContent>
}
>
<Button
variant="plain"
className="pf-u-pl-sm pf-u-pt-0 pf-u-pb-0"
aria-label="About remote host configuration (rhc)"
isInline
>
<HelpIcon />
</Button>
</Popover>
);
};
const Registration = () => {
const dispatch = useAppDispatch();
const registrationType = useAppSelector(selectRegistrationType);
const [showOptions, setShowOptions] = useState(
registrationType === 'register-now-insights' ||
registrationType === 'register-now'
);
return (
<FormGroup label="Registration method">
<Radio
autoFocus
label={
(!showOptions &&
'Automatically register and enable advanced capabilities') || (
<>
Monitor & manage subscriptions and access to Red Hat content
<RHSMPopover />
</>
)
}
data-testid="registration-radio-now"
name="register-system"
id="register-system-now"
isChecked={registrationType.startsWith('register-now')}
onChange={() => {
dispatch(changeRegistrationType('register-now-rhc'));
}}
description={
!showOptions && (
<Button
component="a"
data-testid="registration-additional-options"
variant="link"
isDisabled={!registrationType.startsWith('register-now')}
isInline
onClick={() => setShowOptions(!showOptions)}
>
Show additional connection options
</Button>
)
}
body={
showOptions && (
<Checkbox
className="pf-u-ml-lg"
label={
<>
Enable predictive analytics and management capabilities
<InsightsPopover />
</>
}
data-testid="registration-checkbox-insights"
isChecked={
registrationType === 'register-now-insights' ||
registrationType === 'register-now-rhc'
}
onChange={(_event, checked) => {
if (checked) {
dispatch(changeRegistrationType('register-now-insights'));
} else {
dispatch(changeRegistrationType('register-now'));
}
}}
id="register-system-now-insights"
name="register-system-insights"
body={
<Checkbox
label={
<>
Enable remote remediations and system management with
automation
<RhcPopover />
</>
}
data-testid="registration-checkbox-rhc"
isChecked={registrationType === 'register-now-rhc'}
onChange={(_event, checked) => {
if (checked) {
dispatch(changeRegistrationType('register-now-rhc'));
} else {
dispatch(changeRegistrationType('register-now-insights'));
}
}}
id="register-system-now-rhc"
name="register-system-rhc"
/>
}
/>
)
}
/>
<Radio
name="register-system"
className="pf-u-mt-md"
data-testid="registration-radio-later"
id="register-system-later"
label="Register later"
isChecked={registrationType === 'register-later'}
onChange={() => {
setShowOptions(false);
dispatch(changeRegistrationType('register-later'));
dispatch(changeActivationKey(undefined));
}}
/>
</FormGroup>
);
};
export default Registration;

View file

@ -0,0 +1,50 @@
import React from 'react';
import { Text, Form, Title, FormGroup } from '@patternfly/react-core';
import ActivationKeyInformation from './ActivationKeyInformation';
import ActivationKeysList from './ActivationKeysList';
import RegisterLaterInformation from './RegisterLaterInformation';
import Registration from './Registration';
import { useAppSelector } from '../../../../store/hooks';
import {
selectActivationKey,
selectRegistrationType,
} from '../../../../store/wizardSlice';
const RegistrationStep = () => {
const registrationType = useAppSelector(selectRegistrationType);
const activationKey = useAppSelector(selectActivationKey);
return (
<Form>
<Title headingLevel="h1" size="xl">
Register systems using this image
</Title>
<Text>
To enhance security and track your spending, you can register your
systems automatically with Red Hat now, or manually during the initial
boot later.
</Text>
<Registration />
{registrationType !== 'register-later' ? (
<>
<ActivationKeysList />
{activationKey && (
<FormGroup
isRequired={true}
label={'Selected activation key'}
data-testid="selected-activation-key"
>
<ActivationKeyInformation />
</FormGroup>
)}
</>
) : (
<RegisterLaterInformation />
)}
</Form>
);
};
export default RegistrationStep;