debian-image-builder-frontend/src/Components/CreateImageWizard/steps/googleCloud.js
lucasgarfield c28e0d15b6 CreateImageWizard: Make steps autofocus on first input upon render
The default behavior of Data Driven Forms when moving to the previous or
next step is to maintain focus on the previous or next button,
respectively.

This commit makes the UI more friendly to keyboard users by focusing
on the first input element of a given step when it is rendered.

Whenever possible, autofocus is achieved by passing components the
autoFocus prop. When this is not possible, then useRef and useEffect hooks
are used to set focus.

At the moment, it is not possible to autofocus the image output step's
release selector or the file system configuration step's toggle using the
above methods. This is because these PatternFly components do not
currently pass props to the appropriate child component and do not
support ref forwarding. The best option for autofocus in these cases is
currently being investigated.
2022-03-25 15:47:48 +01:00

138 lines
5.2 KiB
JavaScript

import React from 'react';
import componentTypes from '@data-driven-forms/react-form-renderer/component-types';
import validatorTypes from '@data-driven-forms/react-form-renderer/validator-types';
import { HelpIcon } from '@patternfly/react-icons';
import nextStepMapper from './imageOutputStepMapper';
import { Title, Text, Popover, TextContent, TextList, TextListItem, Button } from '@patternfly/react-core';
import PropTypes from 'prop-types';
import StepTemplate from './stepTemplate';
export const googleAccType = {
googleAccount: 'Google account',
serviceAccount: 'Service account',
googleGroup: 'Google group',
domain: 'Domain'
};
const PopoverInfo = ({ appendTo }) => {
return <Popover
appendTo={ appendTo }
hasAutoWidth
maxWidth='35rem'
headerContent={ 'Valid account types' }
flipBehavior={ [ 'right', 'bottom', 'top', 'left' ] }
bodyContent={ <TextContent>
<Text>The following account types can have an image shared with them:</Text>
<TextList className='pf-u-ml-0'>
<TextListItem>
<strong>Google account:</strong> A Google account represents a developer, an administrator,
or any other person who interacts with Google Cloud. e.g., <em>`alice@gmail.com`</em>.
</TextListItem>
<TextListItem>
<strong>Service account:</strong> A service account is an account for an application instead
of an individual end user. e.g., <em>`myapp@appspot.gserviceaccount.com`</em>.
</TextListItem>
<TextListItem>
<strong>Google group:</strong> A Google group is a named collection of Google accounts and
service accounts. e.g., <em>`admins@example.com`</em>.
</TextListItem>
<TextListItem>
<strong>Google Workspace domain/Cloud Identity domain:</strong> A Google workspace or cloud identity
domain represents a virtual group of all the Google accounts in an organization. These domains
represent your organization&apos;s internet domain name. e.g., <em>`mycompany.com`</em>.
</TextListItem>
</TextList>
</TextContent> }>
<Button
variant="plain"
aria-label="Account info"
aria-describedby="google-account-type"
className="pf-c-form__group-label-help">
<HelpIcon />
</Button>
</Popover>;
};
PopoverInfo.propTypes = {
appendTo: PropTypes.any
};
export default {
StepTemplate,
id: 'wizard-target-gcp',
title: 'Google Cloud Platform',
customTitle: <Title headingLevel="h1" size="xl">Target environment - Google Cloud Platform</Title>,
name: 'google-cloud-target-env',
substepOf: 'Target environment',
nextStep: ({ values }) => nextStepMapper(values, { skipGoogle: true, skipAws: true }),
fields: [
{
component: componentTypes.PLAIN_TEXT,
name: 'google-cloud-text-component',
label: <Text>
Your image will be uploaded to Google Cloud Platform and shared with the email you provide below. <br />
The image should be copied to your account within 14 days.
</Text>
},
{
component: 'radio-popover',
label: 'Type',
isRequired: true,
Popover: PopoverInfo,
name: 'google-account-type',
initialValue: 'googleAccount',
options: Object.entries(googleAccType).map(([ value, label ]) => ({
label: value === 'domain' ? 'Google Workspace domain or Cloud Identity domain' : label,
value,
autoFocus: value === 'googleAccount' ? true : false
})),
validate: [
{
type: validatorTypes.REQUIRED,
},
],
},
{
component: componentTypes.TEXT_FIELD,
name: 'google-email',
'data-testid': 'input-google-email',
type: 'text',
label: 'Email address',
condition: {
or: [
{ when: 'google-account-type', is: 'googleAccount' },
{ when: 'google-account-type', is: 'serviceAccount' },
{ when: 'google-account-type', is: 'googleGroup' },
{ when: 'google-account-type', is: null },
]
},
isRequired: true,
validate: [
{
type: validatorTypes.REQUIRED,
},
{
type: validatorTypes.PATTERN,
pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,}$',
message: 'Please enter a valid email address'
}
],
},
{
component: componentTypes.TEXT_FIELD,
name: 'google-domain',
type: 'text',
label: 'Domain',
condition: {
when: 'google-account-type',
is: 'domain'
},
isRequired: true,
validate: [
{
type: validatorTypes.REQUIRED,
},
],
}
]
};