feat(HMS-2789): simplfy activation key creation
This commit is contained in:
parent
2c0c85f241
commit
16cf421c68
5 changed files with 146 additions and 18 deletions
|
|
@ -7,7 +7,7 @@ const config: ConfigFile = {
|
|||
outputFile: '../../src/store/rhsmApi.ts',
|
||||
exportName: 'rhsmApi',
|
||||
hooks: true,
|
||||
filterEndpoints: ['listActivationKeys', 'showActivationKey'],
|
||||
filterEndpoints: ['listActivationKeys', 'showActivationKey', 'createActivationKeys'],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
|
|
@ -2,17 +2,66 @@ import React, { useEffect, useState } from 'react';
|
|||
|
||||
import useFieldApi from '@data-driven-forms/react-form-renderer/use-field-api';
|
||||
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
|
||||
import { Alert, FormGroup, Spinner } from '@patternfly/react-core';
|
||||
import {
|
||||
Alert,
|
||||
FormGroup,
|
||||
Spinner,
|
||||
EmptyState,
|
||||
Button,
|
||||
EmptyStateIcon,
|
||||
EmptyStateBody,
|
||||
EmptyStateHeader,
|
||||
EmptyStateFooter,
|
||||
EmptyStateActions,
|
||||
} from '@patternfly/react-core';
|
||||
import {
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from '@patternfly/react-core/deprecated';
|
||||
import { WrenchIcon, AddCircleOIcon } from '@patternfly/react-icons';
|
||||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { useListActivationKeysQuery } from '../../../store/rhsmApi';
|
||||
import {
|
||||
useListActivationKeysQuery,
|
||||
useCreateActivationKeysMutation,
|
||||
} from '../../../store/rhsmApi';
|
||||
import { useGetEnvironment } from '../../../Utilities/useGetEnvironment';
|
||||
|
||||
const EmptyActivationsKeyState = ({ handleActivationKeyFn, isLoading }) => (
|
||||
<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>
|
||||
);
|
||||
|
||||
EmptyActivationsKeyState.propTypes = {
|
||||
handleActivationKeyFn: PropTypes.func.isRequired,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
const ActivationKeys = ({ label, isRequired, ...props }) => {
|
||||
const { isProd } = useGetEnvironment();
|
||||
const { change, getState } = useFormApi();
|
||||
|
|
@ -22,6 +71,8 @@ const ActivationKeys = ({ label, isRequired, ...props }) => {
|
|||
getState()?.values?.['subscription-activation-key']
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const {
|
||||
data: activationKeys,
|
||||
isFetching: isFetchingActivationKeys,
|
||||
|
|
@ -30,6 +81,8 @@ const ActivationKeys = ({ label, isRequired, ...props }) => {
|
|||
refetch,
|
||||
} = useListActivationKeysQuery();
|
||||
|
||||
const [createActivationKey, { isLoading: isLoadingActivationKey }] =
|
||||
useCreateActivationKeysMutation();
|
||||
useEffect(() => {
|
||||
if (isProd()) {
|
||||
change('subscription-server-url', 'subscription.rhsm.redhat.com');
|
||||
|
|
@ -58,6 +111,28 @@ const ActivationKeys = ({ label, isRequired, ...props }) => {
|
|||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
const handleCreateActivationKey = async () => {
|
||||
const res = await createActivationKey({
|
||||
body: {
|
||||
name: 'activation-key-default',
|
||||
serviceLevel: 'Self-Support',
|
||||
},
|
||||
});
|
||||
refetch();
|
||||
if (res.error) {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Error creating activation key',
|
||||
description: res.error?.data?.error?.message,
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const isActivationKeysEmpty =
|
||||
isSuccessActivationKeys && activationKeys.body.length === 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
|
|
@ -77,11 +152,17 @@ const ActivationKeys = ({ label, isRequired, ...props }) => {
|
|||
typeAheadAriaLabel="Select activation key"
|
||||
isDisabled={!isSuccessActivationKeys}
|
||||
>
|
||||
{isActivationKeysEmpty && (
|
||||
<EmptyActivationsKeyState
|
||||
handleActivationKeyFn={handleCreateActivationKey}
|
||||
isLoading={isLoadingActivationKey}
|
||||
/>
|
||||
)}
|
||||
{isSuccessActivationKeys &&
|
||||
activationKeys.body.map((key, index) => (
|
||||
<SelectOption key={index} value={key.name} />
|
||||
))}
|
||||
{isFetchingActivationKeys && (
|
||||
{!isSuccessActivationKeys && isFetchingActivationKeys && (
|
||||
<SelectOption
|
||||
isNoResultsOption={true}
|
||||
data-testid="activation-keys-loading"
|
||||
|
|
|
|||
|
|
@ -118,17 +118,21 @@ const registrationStep = {
|
|||
component: componentTypes.PLAIN_TEXT,
|
||||
name: 'subscription-activation-description',
|
||||
label: (
|
||||
<Button
|
||||
component="a"
|
||||
target="_blank"
|
||||
variant="link"
|
||||
icon={<ExternalLinkAltIcon />}
|
||||
iconPosition="right"
|
||||
isInline
|
||||
href="https://console.redhat.com/insights/connector/activation-keys"
|
||||
>
|
||||
Create and manage activation keys here
|
||||
</Button>
|
||||
<span>
|
||||
By default, activation key is generated and preset for you. Admins can
|
||||
create and manage keys by visiting the
|
||||
<Button
|
||||
component="a"
|
||||
target="_blank"
|
||||
variant="link"
|
||||
icon={<ExternalLinkAltIcon />}
|
||||
iconPosition="right"
|
||||
isInline
|
||||
href="https://console.redhat.com/insights/connector/activation-keys"
|
||||
>
|
||||
Activation keys page
|
||||
</Button>
|
||||
</span>
|
||||
),
|
||||
condition: {
|
||||
or: [
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@ const injectedRtkApi = api.injectEndpoints({
|
|||
>({
|
||||
query: () => ({ url: `/activation_keys` }),
|
||||
}),
|
||||
createActivationKeys: build.mutation<
|
||||
CreateActivationKeysApiResponse,
|
||||
CreateActivationKeysApiArg
|
||||
>({
|
||||
query: (queryArg) => ({
|
||||
url: `/activation_keys`,
|
||||
method: "POST",
|
||||
body: queryArg.body,
|
||||
}),
|
||||
}),
|
||||
showActivationKey: build.query<
|
||||
ShowActivationKeyApiResponse,
|
||||
ShowActivationKeyApiArg
|
||||
|
|
@ -22,6 +32,22 @@ export type ListActivationKeysApiResponse =
|
|||
body?: ActivationKeys[];
|
||||
};
|
||||
export type ListActivationKeysApiArg = void;
|
||||
export type CreateActivationKeysApiResponse = /** status 200 Activation key */ {
|
||||
body?: ActivationKeys;
|
||||
};
|
||||
export type CreateActivationKeysApiArg = {
|
||||
/** Create an activation key */
|
||||
body: {
|
||||
additionalRepositories?: {
|
||||
repositoryLabel?: string;
|
||||
}[];
|
||||
name: string;
|
||||
releaseVersion?: string;
|
||||
role?: string;
|
||||
serviceLevel?: string;
|
||||
usage?: string;
|
||||
};
|
||||
};
|
||||
export type ShowActivationKeyApiResponse = /** status 200 Activation key */ {
|
||||
body?: ActivationKeys;
|
||||
};
|
||||
|
|
@ -45,5 +71,8 @@ export type ErrorDetails = {
|
|||
code?: number;
|
||||
message?: string;
|
||||
};
|
||||
export const { useListActivationKeysQuery, useShowActivationKeyQuery } =
|
||||
injectedRtkApi;
|
||||
export const {
|
||||
useListActivationKeysQuery,
|
||||
useCreateActivationKeysMutation,
|
||||
useShowActivationKeyQuery,
|
||||
} = injectedRtkApi;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { rest } from 'msw';
|
|||
|
||||
import CreateImageWizard from '../../../Components/CreateImageWizard/CreateImageWizard';
|
||||
import ShareImageModal from '../../../Components/ShareImageModal/ShareImageModal';
|
||||
import { PROVISIONING_API } from '../../../constants.js';
|
||||
import { PROVISIONING_API, RHSM_API } from '../../../constants.js';
|
||||
import { server } from '../../mocks/server.js';
|
||||
import {
|
||||
clickBack,
|
||||
|
|
@ -574,6 +574,20 @@ describe('Step Registration', () => {
|
|||
await verifyCancelButton(router);
|
||||
});
|
||||
|
||||
test('activation key dropdown empty state', async () => {
|
||||
server.use(
|
||||
rest.get(`${RHSM_API}/activation_keys`, (req, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json({ body: [] }))
|
||||
)
|
||||
);
|
||||
await setUp();
|
||||
const activationKeyDropdown = await screen.findByRole('textbox', {
|
||||
name: 'Select activation key',
|
||||
});
|
||||
await user.click(activationKeyDropdown);
|
||||
await screen.findByText('No activation keys found');
|
||||
});
|
||||
|
||||
test('should allow registering with rhc', async () => {
|
||||
await setUp();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue