diff --git a/api/config/rhsm.ts b/api/config/rhsm.ts index d2b362a1..5626d8b9 100644 --- a/api/config/rhsm.ts +++ b/api/config/rhsm.ts @@ -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; diff --git a/src/Components/CreateImageWizard/formComponents/ActivationKeys.js b/src/Components/CreateImageWizard/formComponents/ActivationKeys.js index 7287f8d7..1b798d7b 100644 --- a/src/Components/CreateImageWizard/formComponents/ActivationKeys.js +++ b/src/Components/CreateImageWizard/formComponents/ActivationKeys.js @@ -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 }) => ( + + } + /> + + Get started by building a default key, which will be generated and present + for you. + + + + + + + +); + +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 ( <> { typeAheadAriaLabel="Select activation key" isDisabled={!isSuccessActivationKeys} > + {isActivationKeysEmpty && ( + + )} {isSuccessActivationKeys && activationKeys.body.map((key, index) => ( ))} - {isFetchingActivationKeys && ( + {!isSuccessActivationKeys && isFetchingActivationKeys && ( } - iconPosition="right" - isInline - href="https://console.redhat.com/insights/connector/activation-keys" - > - Create and manage activation keys here - + + By default, activation key is generated and preset for you. Admins can + create and manage keys by visiting the  + + ), condition: { or: [ diff --git a/src/store/rhsmApi.ts b/src/store/rhsmApi.ts index 84c028de..19440440 100644 --- a/src/store/rhsmApi.ts +++ b/src/store/rhsmApi.ts @@ -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; diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js index f7b6ab98..5b4b075f 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js @@ -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();