feat(HMS-2789): simplfy activation key creation

This commit is contained in:
Amir Fefer 2023-11-16 20:29:23 +02:00 committed by Klara Simickova
parent 2c0c85f241
commit 16cf421c68
5 changed files with 146 additions and 18 deletions

View file

@ -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;

View file

@ -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"

View file

@ -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&nbsp;
<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: [

View file

@ -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;

View file

@ -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();