@patternfly/react-core#FormGroup JavaScript Examples
The following examples show how to use
@patternfly/react-core#FormGroup.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
CertFileRow = ({ setCertFile, mode }) => {
return (
<FormGroup label={_("Certificate path")}>
<FileAutoComplete id="cert-file"
isOptionCreatable
superuser="try"
fileExists={mode === "import"}
placeholder={mode === "request" ? _("Path to store the certificate") : _("Path to an existing certificate file")}
onChange={value => setCertFile(value)} />
</FormGroup>
);
}
Example #2
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
StorageRow = ({ storage, setStorage }) => {
return (
<FormGroup label={_("Certificate storage")}
id="storage-row"
isInline
hasNoPaddingTop>
<Radio isChecked={storage === "nssdb"}
name="storage"
onChange={() => setStorage("nssdb")}
label="NSSDB"
id="nssdb"
value="nssdb" />
<Radio isChecked={storage === "file"}
name="storage"
onChange={() => setStorage("file")}
label="File"
id="file"
value="file" />
</FormGroup>
);
}
Example #3
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
PrincipalNameRow = ({ principalName, setPricipalName }) => {
return (
<FormGroup fieldId="principal-name" label={_("Principal name")}>
<TextInput value={principalName}
id="principal-name"
onChange={value => setPricipalName(value)} />
</FormGroup>
);
}
Example #4
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
DNSNameRow = ({ dnsName, setDnsName }) => {
return (
<FormGroup fieldId="dns-name" label={_("DNS names")}
helperText={_("Comma separated list of DNS names. Example: example.com,sub.example.com")}>
<TextArea value={dnsName}
id="dns-name"
onChange={value => setDnsName(value)}
resizeOrientation='vertical' />
</FormGroup>
);
}
Example #5
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
SubjectNameRow = ({ subjectName, setSubjectName }) => {
return (
<FormGroup fieldId="subject-name" label={_("Subject name")}>
<TextInput value={subjectName}
id="subject-name"
onChange={value => setSubjectName(value)} />
</FormGroup>
);
}
Example #6
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
SetSigningParametersRow = ({ signingParameters, setSigningParameters }) => {
return (
<FormGroup>
<Checkbox id='set-signing-parameters'
isChecked={signingParameters}
label={_("Set optional signing request parameters")}
onChange={() => setSigningParameters(!signingParameters)} />
</FormGroup>
);
}
Example #7
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
CAsRow = ({ ca, setCa, cas }) => {
return (
<FormGroup fieldId="ca" label={_("CA")}>
<FormSelect id="ca"
value={ca}
onChange={value => setCa(value)}>
{cas.map(ca => {
const nick = ca.nickname.v == "SelfSign" ? _("Self-signed") : ca.nickname.v;
return (
<FormSelectOption value={ca.nickname.v} key={ca.nickname.v}
label={nick} />
);
})}
</FormSelect>
</FormGroup>
);
}
Example #8
Source File: ActivationKeysFormSelect.js From sed-frontend with Apache License 2.0 | 6 votes |
ActivationKeysFormSelect = (props) => {
const {
label,
popover,
data,
onSelect,
helperText,
name,
value,
placeholderValue,
disableDefaultValues,
} = props;
const [selected, setSelected] = useState('');
const options = data.map((role) => {
return <FormSelectOption key={role} value={role} label={role} />;
});
const valueChange = (value) => {
setSelected(value);
onSelect(value);
};
return (
<FormGroup label={label} labelIcon={popover} helperText={helperText}>
<FormSelect
onChange={valueChange}
value={selected || value}
name={name}
aria-label={placeholderValue}
>
<FormSelectOption
label={placeholderValue}
isPlaceholder={true}
isDisabled={disableDefaultValues}
/>
{options}
</FormSelect>
</FormGroup>
);
}
Example #9
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
NicknameRow = ({ nickname, setNickname }) => {
return (
<FormGroup fieldId="nickname" label={_("Nickname")}>
<TextInput value={nickname}
id="nickname"
onChange={value => setNickname(value)}
aria-label={_("Nickname input text")} />
</FormGroup>
);
}
Example #10
Source File: RegisterWithActivationKey.js From sed-frontend with Apache License 2.0 | 6 votes |
RegisterWithActivationKey = () => (
<FormGroup
label={
<span>
Register with an activation key
<Tooltip
content={
<div>
Organization administrators can view, create, and edit activation
keys on the "Activation keys" section of
console.redhat.com. The organization ID is a Candlepin-specific
identifier, which can be accessed from the activation keys page.
</div>
}
>
<OutlinedQuestionCircleIcon />
</Tooltip>
</span>
}
helperText={<CopyHelperText />}
>
<ClipboardCopy>
rhc connect -a <activation-key> -o <organization-id>
</ClipboardCopy>
</FormGroup>
)
Example #11
Source File: requestCertificate.jsx From cockpit-certificates with GNU Lesser General Public License v2.1 | 6 votes |
KeyFileRow = ({ setKeyFile, mode }) => {
return (
<FormGroup label={_("Key path")}>
<FileAutoComplete id="key-file"
isOptionCreatable
superuser="try"
fileExists={mode === "import"}
placeholder={mode === "request"
? _("Path to store the generated key or to an existing key")
: _("Path to an existing key file")}
onChange={value => setKeyFile(value)} />
</FormGroup>
);
}
Example #12
Source File: SSHInputField.js From edge-frontend with Apache License 2.0 | 6 votes |
SSHInputField = (props) => {
const { input: sshKeyInput, meta } = useFieldApi({
name: 'credentials',
...props,
});
return (
<FormGroup>
<FormGroup
label="SSH key"
helperTextInvalid={meta.error}
validated={meta.error && meta.touched ? 'error' : 'default'}
isRequired
>
<TextArea
className="pf-u-h-25vh"
id="credentials"
placeholder="Paste your public SSH key"
{...sshKeyInput}
/>
</FormGroup>
<Fragment>
<Text component={TextVariants.small}>
<Text
target="_blank"
href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/assembly_using-secure-communications-between-two-systems-with-openssh_configuring-basic-system-settings#generating-ssh-key-pairs_assembly_using-secure-communications-between-two-systems-with-openssh"
isVisitedLink
component={TextVariants.a}
>
Learn more about SSH keys
<ExternalLinkAltIcon className="pf-u-ml-sm" />
</Text>
</Text>
</Fragment>
</FormGroup>
);
}
Example #13
Source File: new-dashboard-modal.js From ibutsu-server with MIT License | 6 votes |
render () {
return (
<Modal
variant={ModalVariant.small}
title="New Dashboard"
isOpen={this.props.isOpen}
onClose={this.onClose}
actions={[
<Button key="save" variant="primary" onClick={this.onSave}>Save</Button>,
<Button key="cancel" variant="link" onClick={this.onClose}>Cancel</Button>
]}
>
<Form>
<FormGroup label="Title" fieldId="dashboard-title" helperTextInvalid="A dashboard title is required" helperTextInvalidIcon={<ExclamationCircleIcon />} validated={this.state.isTitleValid} isRequired>
<TextInput type="text" id="dashboard-title" name="dashboard-title" value={this.state.title} onChange={this.onTitleChange} validated={this.state.isTitleValid} isRequired />
</FormGroup>
<FormGroup label="Description" fieldId="dashboard-description">
<TextInput type="text" id="dashboard-description" name="dashboard-description" value={this.state.description} onChange={this.onDescriptionChange} />
</FormGroup>
</Form>
</Modal>
);
}
Example #14
Source File: report-builder.js From ibutsu-server with MIT License | 5 votes |
render() {
document.title = 'Report Builder | Ibutsu';
const { columns, rows, actions } = this.state;
const reportTypes = this.state.reportTypes.map((reportType) => <FormSelectOption key={reportType.type} value={reportType.type} label={reportType.name} />);
const pagination = {
page: this.state.page,
pageSize: this.state.pageSize,
totalItems: this.state.totalItems
};
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<TextContent>
<Text component="h1">Report Builder</Text>
</TextContent>
</PageSection>
<PageSection>
<Card>
<CardBody>
<Form isHorizontal>
<FormGroup isRequired label="Report Type" helperText="The type of report" fieldId="report-type">
<FormSelect id="report-type" value={this.state.reportType} onChange={this.onReportTypeChange}>
{reportTypes}
</FormSelect>
</FormGroup>
<FormGroup label="Filter" fieldId="report-filter">
<TextInput type="text" id="report-filter" value={this.state.reportFilter} onChange={this.onReportFilterChange} />
<ExpandableSection toggleText="Filter Help" onToggle={this.onHelpToggle} isExpanded={this.state.isHelpExpanded}>
<TextContent>
<p>The filter parameter takes a comma-separated list of filters to apply. <Linkify componentDecorator={linkifyDecorator}>https://docs.ibutsu-project.org/en/latest/user-guide/filter-help.html</Linkify></p>
</TextContent>
</ExpandableSection>
</FormGroup>
<FormGroup label="Source" helperText="The source of report" fieldId="report-source">
<TextInput type="text" id="report-source" value={this.state.reportSource} onChange={this.onReportSourceChange} />
</FormGroup>
<ActionGroup>
<Button variant="primary" onClick={this.onRunReportClick}>Run Report</Button>
</ActionGroup>
</Form>
</CardBody>
<CardFooter>
<Text className="disclaimer" component="h4">
* Note: reports can only show a maximum of 100,000 results.
</Text>
</CardFooter>
</Card>
</PageSection>
<PageSection>
<Card>
<CardBody>
<FilterTable
columns={columns}
rows={rows}
actions={actions}
pagination={pagination}
isEmpty={this.state.isEmpty}
isError={this.state.isError}
onSetPage={this.setPage}
onSetPageSize={this.setPageSize}
/>
</CardBody>
</Card>
</PageSection>
</React.Fragment>
);
}
Example #15
Source File: add-token-modal.js From ibutsu-server with MIT License | 5 votes |
render () {
return (
<Modal
variant={ModalVariant.small}
title="Add Token"
isOpen={this.props.isOpen}
onClose={this.onClose}
actions={[
<Button key="save" variant="primary" onClick={this.onSave}>Save</Button>,
<Button key="cancel" variant="link" onClick={this.onClose}>Cancel</Button>
]}
>
<Form>
<FormGroup
label="Name"
fieldId="token-name"
helperTextInvalid="A token name is required"
helperTextInvalidIcon={<ExclamationCircleIcon />}
validated={this.state.isNameValid ? ValidatedOptions.default : ValidatedOptions.error}
isRequired
>
<TextInput
type="text"
id="token-name"
name="token-name"
value={this.state.name}
onChange={this.onNameChange}
validated={this.state.isNameValid ? ValidatedOptions.default : ValidatedOptions.error}
isRequired
/>
</FormGroup>
<FormGroup
label="Expiry"
fieldId="token-expiry-date"
helperTextInvalid="A valid epiry date is required"
helperTextInvalidIcon={<ExclamationCircleIcon />}
validated={this.state.isExpiryValid ? ValidatedOptions.default : ValidatedOptions.error}
isRequired
>
<DatePicker
onChange={this.onExpiryDateChange}
value={this.state.expiryDate}
inputProps={{
id: "token-expiry-date",
validated: this.state.isExpiryValid ? ValidatedOptions.default : ValidatedOptions.error
}}
/>
</FormGroup>
</Form>
</Modal>
);
}
Example #16
Source File: forgot-password.js From ibutsu-server with MIT License | 5 votes |
render() {
const signUpForAccountMessage = (
<LoginMainFooterBandItem>
Need an account? <NavLink to="/sign-up">Sign up.</NavLink>
</LoginMainFooterBandItem>
);
const forgotCredentials = (
<LoginMainFooterBandItem>
Already registered? <NavLink to="/login">Log in.</NavLink>
</LoginMainFooterBandItem>
);
const backgroundImages = {
lg: '/images/pfbg_1200.jpg',
sm: '/images/pfbg_768.jpg',
sm2x: '/images/[email protected]',
xs: '/images/pfbg_576.jpg',
xs2x: '/images/[email protected]'
};
return (
<LoginPage
footerListVariants="inline"
brandImgSrc="/images/ibutsu-wordart-164.png"
brandImgAlt="Ibutsu"
backgroundImgSrc={backgroundImages}
backgroundImgAlt="Background image"
textContent="Ibutsu is an open source test result aggregation. Collect and display your test results, view artifacts, and monitor tests."
loginTitle="Recover your account"
loginSubtitle="Please type in your e-mail address and a reset link will be sent to it."
signUpForAccountMessage={signUpForAccountMessage}
forgotCredentials={forgotCredentials}
>
<Form>
{this.state.showAlert &&
<FormAlert>
<Alert variant={this.state.alertType} title={this.state.alertText} aria-live="polite" isInline/>
</FormAlert>
}
<FormGroup
label="Email address"
isRequired
fieldId="email"
validated={this.state.isValidEmail ? 'default' : 'error'}
helperText="The e-mail address you signed up with"
>
<TextInput
isRequired
type="email"
id="email"
name="email"
validated={this.state.isValidEmail ? 'default' : 'error'}
aria-describedby="email-helper"
value={this.state.emailValue}
onChange={this.onEmailChange}
/>
</FormGroup>
<ActionGroup>
<Button variant="primary" isBlock onClick={this.onRecoverAccountClick}>Recover account</Button>
</ActionGroup>
</Form>
</LoginPage>
);
}
Example #17
Source File: project-edit.js From ibutsu-server with MIT License | 5 votes |
render() {
const { project, users, owner } = this.state;
return (
<React.Fragment>
<PageSection variant={PageSectionVariants.light}>
<Title headingLevel="h1" size='2xl' className="pf-c-title">
Projects / {project && project.title}
</Title>
</PageSection>
<PageSection>
{!project && <Alert variant="info" title="Loading..." />}
{project &&
<Card>
<CardBody>
<Form>
<FormGroup label="Title" isRequired fieldId="projectTitle" helperText="The project's friendly name">
<TextInput
isRequired
type="text"
id="projectTitle"
name="projectTitle"
aria-describedby="The project's friendly name"
value={project.title}
onChange={this.onProjectTitleChanged}
/>
</FormGroup>
<FormGroup label="Name" isRequired fieldId="projectName" helperText="The project's machine name">
<TextInput
isRequired
type="text"
id="projectName"
name="projectName"
aria-describedby="The project's machine name"
value={project.name}
onChange={this.onProjectNameChanged}
/>
</FormGroup>
<FormGroup fieldId="owner" label="Owner" helperText="The user who owns the project">
<Select
variant={SelectVariant.typeahead}
typeAheadAriaLabel="Select user"
onToggle={this.onOwnerToggle}
onSelect={this.onOwnerSelect}
onClear={this.onOwnerClear}
onTypeaheadInputChanged={this.onOwnerChanged}
selections={owner}
isOpen={this.state.isOwnerOpen}
aria-labelledby="owner"
placeholderText="Select user"
>
{users.map(user => (
<SelectOption key={user.id} value={userToOption(user)} description={user.email} />
))}
</Select>
</FormGroup>
<ActionGroup>
<Button
variant="primary"
ouiaId="admin-project-edit-save"
onClick={this.onSubmitClick}
>
Submit
</Button>
<Button
variant="secondary"
ouiaId="admin-project-edit-cancel"
component={(props: any) => <Link {...props} to="/admin/projects" />}
>
Cancel
</Button>
</ActionGroup>
</Form>
</CardBody>
</Card>
}
</PageSection>
</React.Fragment>
);
}
Example #18
Source File: RegisterWithUserName.js From sed-frontend with Apache License 2.0 | 5 votes |
RegisterWithUserName = () => {
return (
<FormGroup
label={
<span>
Register with a username and password
<Popover
position="right"
bodyContent={
<TextContent>
<Text>
Recommended for users with accounts with Simple Content Access
(SCA) enabled. If SCA is not enabled for your account,
subscriptions will be auto-attached.
<Text
href="https://access.redhat.com/articles/simple-content-access"
component="a"
target="_blank"
rel="noopener noreferrer"
>
Learn about Simple Content Access
<ExternalLinkAltIcon />
</Text>
</Text>
<Text>
Any credentials of a user with a valid subscription can be
used.
</Text>
</TextContent>
}
>
<OutlinedQuestionCircleIcon />
</Popover>
</span>
}
helperText={<CopyHelperText />}
>
<ClipboardCopy>
rhc connect -u <username> -p <password>
</ClipboardCopy>
</FormGroup>
);
}
Example #19
Source File: RegistrationCreds.js From edge-frontend with Apache License 2.0 | 5 votes |
RegistrationCreds = (props) => {
const { input, meta } = useFieldApi(props);
const toggleCheckbox = useCallback(
(checked, event) => {
input.onChange(
checked
? [...input.value, event.currentTarget.id]
: input.value.filter((item) => item !== event.currentTarget.id)
);
},
[input.onChange]
);
const { input: passwordInput } = useFieldApi({ name: 'password' });
const { input: sshKeyInput } = useFieldApi({ name: 'sshKey' });
return (
<FormGroup
label="Select at least one to validate credentials"
isHelperTextBeforeField
hasNoPaddingTop
isRequired
isStack
>
<Checkbox
label="Password"
id="password"
isChecked={input.value.includes('password')}
onChange={toggleCheckbox}
/>
{input.value.includes('password') ? (
<FormGroup
helperTextInvalid={
meta.dirty && meta.error['password'] !== undefined
? meta.error['password']
: undefined
}
>
<TextInput type="password" {...passwordInput} />
</FormGroup>
) : null}
<Checkbox
label="SSH"
id="sshKey"
isChecked={input.value.includes('sshKey')}
onChange={toggleCheckbox}
/>
{input.value.includes('sshKey') ? (
<FormGroup
helperTextInvalid={
meta.dirty && meta.error['sshKey'] !== undefined
? meta.error['sshKey']
: undefined
}
>
<TextArea {...sshKeyInput} />
</FormGroup>
) : null}
</FormGroup>
);
}
Example #20
Source File: ImageOutputCheckbox.js From edge-frontend with Apache License 2.0 | 5 votes |
ImageOutputCheckbox = (props) => {
const { getState } = useFormApi();
const { input } = useFieldApi(props);
const toggleCheckbox = useCallback(
(checked, event) => {
input.onChange(
checked
? [...input.value, event.currentTarget.id]
: input.value.filter((item) => item !== event.currentTarget.id)
);
},
[input.onChange]
);
return (
<FormGroup
label="Output type"
isHelperTextBeforeField
hasNoPaddingTop
isRequired
isStack
>
{props.options.map(({ value, label }, index) => (
<Fragment key={index}>
<Checkbox
label={label}
id={value}
isChecked={input.value.includes(value)}
onChange={toggleCheckbox}
isDisabled={value === 'rhel-edge-commit'}
/>
<TextContent>
{getState()?.initialValues?.isUpdate &&
value === 'rhel-edge-installer' ? (
<WarningInstallerHelperText />
) : (
<HelperText className="pf-u-ml-lg pf-u-pb-sm">
<HelperTextItem variant="indeterminate">
{outputHelperText[value]}
</HelperTextItem>
</HelperText>
)}
</TextContent>
{value === 'rhel-edge-installer' && (
<Fragment>
<Text component={TextVariants.small}>
<Text
target="_blank"
href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/composing_installing_and_managing_rhel_for_edge_images/index#edge-how-to-compose-and-deploy-a-rhel-for-edge-image_introducing-rhel-for-edge-images"
component={TextVariants.a}
isVisitedLink
>
Learn more about image types.
<ExternalLinkAltIcon className="pf-u-ml-sm" />
</Text>
</Text>
</Fragment>
)}
</Fragment>
))}
</FormGroup>
);
}
Example #21
Source File: CustomPackageTextArea.js From edge-frontend with Apache License 2.0 | 5 votes |
CustomPackageTextArea = ({ ...props }) => {
const { change, getState } = useFormApi();
const { input } = useFieldApi(props);
const wizardState = getState()?.values?.[input.name];
const [value, setValue] = useState(
wizardState?.map((repo) => repo.name).join('\n')
);
useEffect(() => {
const customRepoArray = value
.split(/[/,/\n\r\s\t]+/g)
.reduce((acc, repo) => {
const onlyText = repo.replace(/[/ /\n\r\s\t]+/g, '');
if (onlyText !== '' && onlyText !== '\n') {
return (acc = [...acc, { name: `${onlyText}` }]);
}
return acc;
}, []);
change(input.name, customRepoArray);
}, [value]);
useEffect(() => {
const availableSearchInput = document.querySelector(
'[aria-label="custom-package-wizard-step"]'
);
availableSearchInput?.addEventListener('keydown', handleSearchOnEnter);
return () =>
availableSearchInput.removeEventListener('keydown', handleSearchOnEnter);
}, []);
const handleSearchOnEnter = (e) => {
if (e.key === 'Enter') {
e.stopPropagation();
}
};
return (
<FormGroup label="Packages" type="string">
<TextArea
aria-label="custom-package-wizard-step"
placeholder="Enter or paste packages from linked repositories, one entry per line. ExamplePackage example-package examplapackage"
value={value}
onChange={(newValue) => setValue(newValue)}
style={{
paddingRight: '32px',
height: '25vh',
}}
></TextArea>
</FormGroup>
);
}
Example #22
Source File: IPSettingsForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
IPSettingsForm = ({ connection, ipVersion = 'ipv4', isOpen, onClose }) => {
const dispatch = useNetworkDispatch();
const settings = connection[ipVersion];
const [bootProto, setBootProto] = useState(settings.bootProto);
const [addresses, setAddresses] = useState(settings.addresses);
const [addressRequired, setAddressRequired] = useState(settings.bootProto === bootProtocol.STATIC);
const [errorMessages, setErrorMessages] = useState([]);
/**
* Performs an update of the internal addresses state
*
* When the "Static" boot protocol is selected, it ensures that there is at least one {@link
* module:/model~AddressConfig} in the collection, which helps displaying needed fields in the
* UI.
*
* @param {Array<module:model~AddressConfig>} [nextAddresses] - Addresses to be used for the
* update. When not given, current addresses will be used.
*/
const forceAddressesUpdate = useCallback((nextAddresses) => {
nextAddresses ||= addresses;
if (bootProto === bootProtocol.STATIC && nextAddresses.length === 0) {
nextAddresses = [createAddressConfig()];
}
setAddresses(nextAddresses);
}, [addresses, bootProto]);
/**
* Performs validations using given addresses
*
* @param {Array<module:model~AddressConfig>} sanitizedAddresses - a collection of sanitize
* addresses. See {@link sanitize}
* @return {boolean} true when all validations success; false otherwise
*/
const validate = (sanitizedAddresses) => {
/**
* TODO: improve validations
* TODO: highlight addresses with errors?
*/
let result = true;
const errors = [];
// Clean previous error messages
setErrorMessages([]);
if (bootProto === bootProtocol.STATIC && sanitizedAddresses.length === 0) {
result = false;
errors.push({
key: 'static-address-required',
message: format(
_('At least one address must be provided when using the "$bootProto" boot protocol'),
{ bootProto: bootProtocol.label(bootProtocol.STATIC) }
)
});
}
if (findInvalidIP(sanitizedAddresses)) {
result = false;
errors.push({
key: 'invalid-ips',
message: _("There are invalid IPs")
});
}
if (findRepeatedLabel(sanitizedAddresses)) {
result = false;
errors.push({
key: 'repeated-labels',
message: _("There are repeated labels")
});
}
setErrorMessages(errors);
return result;
};
/**
* Handles the form submit, performing a connection update when proceed
*
* @see {@link validate}
* @see {@link module/context/network~updateConnection}
*/
const handleSubmit = () => {
const sanitizedAddresses = sanitize(addresses);
// Do not proceed if errors were found
if (!validate(sanitizedAddresses)) {
forceAddressesUpdate(sanitizedAddresses);
return;
}
// If everything looks good, send requested changes and close
updateConnection(
dispatch,
connection,
{ [ipVersion]: { bootProto, addresses: sanitizedAddresses } }
);
onClose();
};
/**
* Updates the UI according to the bootProtocol selected
*
* Basically, setting the internal form state in order to ensure that the AddressDataList
* component displays the fields for at least one {@link module/model~AddressConfig} item.
*/
useEffect(() => {
forceAddressesUpdate();
setAddressRequired(bootProto === bootProtocol.STATIC);
}, [forceAddressesUpdate, bootProto]);
/**
* Renders error messages in an Patternfly/Alert component, if any
*/
const renderErrors = () => {
if (errorMessages.length === 0) return null;
return (
<Alert
isInline
variant="danger"
aria-live="polite"
title={_("Data is not valid, please check it")}
>
{errorMessages.map(({ key, message }) => <p key={key}>{message}</p>)}
</Alert>
);
};
return (
<ModalForm
caption={connection.name}
title={_(`${ipVersion.toUpperCase()} Settings`)}
isOpen={isOpen}
onSubmit={handleSubmit}
onCancel={onClose}
variant={ModalVariant.medium}
>
{renderErrors()}
<FormGroup label={_("Boot Protocol")} isRequired>
<BootProtoSelector value={bootProto} onChange={setBootProto} />
</FormGroup>
<FormGroup label={_("Addresses")}>
<AddressesDataList
addresses={addresses}
updateAddresses={setAddresses}
allowEmpty={!addressRequired}
/>
</FormGroup>
</ModalForm>
);
}
Example #23
Source File: RouteForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
RouteForm = ({ isOpen, onClose, route }) => {
const isEditing = !!route;
const [isDefault, setIsDefault] = useState(route?.isDefault || false);
const [gateway, setGateway] = useState(route?.gateway || "");
const [destination, setDestination] = useState(route?.destination || "");
const [device, setDevice] = useState(route?.device || "");
const [options, setOptions] = useState(route?.options || "");
const [errors, setErrors] = useState([]);
const { interfaces, routes } = useNetworkState();
const [candidateInterfaces, setCandidateInterfaces] = useState([]);
const dispatch = useNetworkDispatch();
useEffect(() => {
setCandidateInterfaces([{ name: "" }, ...Object.values(interfaces)]);
}, [interfaces]);
/**
* Performs the form validations
*
* To be considered a valid form both, destination and gateway must be valid IPs values. There
* is only an exception for destination, which can be "default" too.
*
* @return {boolean} true when route is valid; false otherwise
*/
const validate = () => {
const errors = [];
if (!isDefault && !isValidIP(destination)) {
errors.push({
key: 'invalid-destination',
message: _("Destination is not valid.")
});
}
if (!isValidIP(gateway)) {
errors.push({
key: 'invalid-gateway',
message: _("Gateway is not valid.")
});
}
setErrors(errors);
return errors.length === 0;
};
const addOrUpdateRoute = () => {
if (!validate()) return;
if (isEditing) {
updateRoute(dispatch, routes, route.id, buildRouteData());
} else {
addRoute(dispatch, routes, buildRouteData());
}
onClose();
};
const buildRouteData = () => {
return {
isDefault,
destination: isDefault ? "default" : destination,
gateway,
device,
options
};
};
const isIncomplete = () => {
if (!isDefault && destination.length == 0) return true;
if (gateway.length == 0) return true;
return false;
};
/**
* Renders error messages in an Patternfly/Alert component, if any
*/
const renderErrors = () => {
if (errors.length === 0) return null;
return (
<Alert
isInline
variant="danger"
aria-live="polite"
title={_("Route is not valid, please check it.")}
>
{errors.map(({ key, message }) => <p key={key}>{message}</p>)}
</Alert>
);
};
/**
* Renders the destination input only when needed (i.e., route is not marked as a default)
*/
const renderDestination = () => {
if (isDefault) return null;
return (
<FormGroup
isRequired
label={_("Destination")}
fieldId="destination"
helperText={_("Destination")}
>
<TextInput
isRequired
id="destination"
value={destination}
onChange={setDestination}
/>
</FormGroup>
);
};
return (
<ModalForm
title={isEditing ? _("Edit Route") : _("Add Route")}
isOpen={isOpen}
onCancel={onClose}
onSubmit={addOrUpdateRoute}
onSubmitLabel={isEditing ? _("Change") : _("Add")}
onSubmitDisable={isIncomplete()}
>
{renderErrors()}
<FormGroup
label={_("Default route")}
fieldId="isDefault"
>
<Checkbox
id="isDefault"
isChecked={isDefault}
onChange={setIsDefault}
/>
</FormGroup>
{renderDestination()}
<FormGroup
isRequired
label={_("Gateway")}
fieldId="gateway"
>
<TextInput
isRequired
id="gateway"
value={gateway}
onChange={setGateway}
/>
</FormGroup>
<FormGroup
label={_("Device")}
fieldId="device"
>
<FormSelect value={device} onChange={setDevice} id="device">
{candidateInterfaces.map(({ name }, index) => (
<FormSelectOption key={index} value={name} label={name} />
))}
</FormSelect>
</FormGroup>
<FormGroup
label={_("Options")}
fieldId="options"
>
<TextInput
id="options"
value={options}
onChange={setOptions}
/>
</FormGroup>
</ModalForm>
);
}
Example #24
Source File: VlanForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
VlanForm = ({ isOpen, onClose, connection }) => {
const { vlan } = connection || {};
const isEditing = !!connection;
const [name, setName] = useState(connection?.name);
const [vlanId, setVlanId] = useState(vlan?.vlanId || 0);
const [parentDevice, setParentDevice] = useState(vlan?.parentDevice);
const [candidateInterfaces, setCandidateInterfaces] = useState([]);
const { interfaces } = useNetworkState();
const dispatch = useNetworkDispatch();
const [suggestName, setSuggestName] = useState(!isEditing);
useEffect(() => {
setCandidateInterfaces(Object.values(interfaces).filter(i => i.type !== interfaceType.VLAN));
if (!parentDevice) setParentDevice(Object.values(interfaces)[0]?.name);
}, [interfaces, parentDevice]);
useEffect(() => {
if (!suggestName) return;
setName(`${parentDevice}.${vlanId}`);
}, [suggestName, parentDevice, vlanId]);
const addOrUpdateConnection = () => {
if (isEditing) {
updateConnection(dispatch, connection, { vlan: { name, vlanId, parentDevice } });
} else {
addConnection(dispatch, { name, type: interfaceType.VLAN, vlan: { vlanId, parentDevice } });
}
onClose();
};
const isIncomplete = () => {
if (name === "") return true;
if (vlanId === "") return true;
if (parentDevice === "") return true;
return false;
};
const updateName = (value) => {
setName(value);
setSuggestName(false);
};
if (!parentDevice) return null;
return (
<ModalForm
caption={connection?.name}
title={isEditing ? _("Edit VLAN") : _("Add VLAN")}
isOpen={isOpen}
onCancel={onClose}
onSubmit={addOrUpdateConnection}
onSubmitLabel={isEditing ? _("Change") : _("Add")}
onSubmitDisable={isIncomplete()}
>
<FormGroup
label={_("Parent")}
isRequired
fieldId="parentDevice"
>
<FormSelect value={parentDevice} onChange={setParentDevice} id="parentDevice">
{candidateInterfaces.map(({ name }) => (
<FormSelectOption key={name} value={name} label={name} />
))}
</FormSelect>
</FormGroup>
<FormGroup
label={_("VLAN ID")}
isRequired
fieldId="vlan_id"
helperText={_("Please, provide the VLAN ID (e.g., 10)")}
>
<TextInput
isRequired
id="vlan_id"
value={vlanId}
onChange={setVlanId}
type="number"
/>
</FormGroup>
<FormGroup
label={_("Name")}
isRequired
fieldId="interface-name"
helperText={_("Please, provide the interface name (e.g., vlan10)")}
>
<TextInput
isRequired
id="interface-name"
value={name}
onChange={updateName}
/>
</FormGroup>
</ModalForm>
);
}
Example #25
Source File: DnsSettingsForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
DnsSettingsForm = ({ isOpen, onClose, dns }) => {
const dispatch = useNetworkDispatch();
const [nameserver1, setNameserver1] = useState(dns.nameServers[0]);
const [nameserver2, setNameserver2] = useState(dns.nameServers[1]);
const [nameserver3, setNameserver3] = useState(dns.nameServers[2]);
const [policy, setPolicy] = useState(dns.policy);
const [searchListInput, setSearchListInput] = useState(dns.searchList.join(" "));
const [errorMessages, setErrorMessages] = useState([]);
const validate = () => {
const errors = [];
// Clean previous error messages
setErrorMessages([]);
if (searchList().some((d) => !isValidDomain(d))) {
errors.push({
key: 'invalid-searchlist',
message: _("There are invalid domains in the search list.")
});
setSearchListInput(searchList().join(" "));
}
if (nameServers().some((s) => !isValidIP(s))) {
errors.push({
key: 'invalid-nameservers',
message: _("There are invalid name servers.")
});
}
setErrorMessages(errors);
return (errors.length == 0);
};
const searchList = () => searchListInput.split(" ").filter(Boolean);
const nameServers = () => [nameserver1, nameserver2, nameserver3].filter(Boolean);
const configChanged = () => {
return !deep_equal(dns, createDnsSettings({ policy, searchList: searchList(), nameServers: nameServers() }));
};
const handleSubmit = () => {
if (!validate()) return false;
if (configChanged()) {
updateDnsSettings(dispatch, { nameServers: nameServers(), policy, searchList: searchList() });
}
onClose();
};
/**
* Renders error messages in an Patternfly/Alert component, if any
*/
const renderErrors = () => {
if (errorMessages.length === 0) return null;
return (
<Alert
isInline
variant="danger"
aria-live="polite"
title={_("Data is not valid, please check it")}
>
{errorMessages.map(({ key, message }) => <p key={key}>{message}</p>)}
</Alert>
);
};
const handleError = (value) => console.log("Invalid value", value, "for nameserver 1");
return (
<ModalForm
title={_("DNS Settings")}
isOpen={isOpen}
onCancel={onClose}
onSubmit={handleSubmit}
>
{renderErrors()}
<FormGroup
label={_("Policy")}
fieldId="dns_policy"
helperText={_("Defines the DNS merge policy as documented in netconfig(8) manual page.")}
>
<TextInput
isRequired
id="dns_policy"
value={policy}
onChange={setPolicy}
/>
</FormGroup>
<FormGroup
label={_("Search List")}
isRequired
fieldId="dns_search_list"
helperText={_("Space separated list of DNS domain names used for host-name lookup")}
>
<TextInput
id="dns_search_list"
placeholder={_("example.com another.com")}
value={searchListInput}
onChange={setSearchListInput}
/>
</FormGroup>
<FormGroup
label={_("Static Name Servers")}
helperText={_("Name Server IP address used for host-name lookup.")}
>
<IPInput
id="dns_nameserver_one"
onChange={setNameserver1}
placeholder={_("Nameserver IP")}
defaultValue={nameserver1}
onError={handleError}
/>
</FormGroup>
<FormGroup>
<IPInput
id="dns_nameserver_two"
placeholder={_("Name Server IP")}
defaultValue={nameserver2}
onChange={setNameserver2}
onError={handleError}
/>
</FormGroup>
<FormGroup>
<IPInput
id="dns_nameserver_three"
placeholder={_("Name Server IP")}
defaultValue={nameserver3}
onChange={setNameserver3}
onError={handleError}
/>
</FormGroup>
</ModalForm>
);
}
Example #26
Source File: BridgeForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
BridgeForm = ({ isOpen, onClose, connection }) => {
const { bridge } = connection || {};
const isEditing = !!connection;
const [name, setName] = useState(connection?.name || "");
const [selectedPorts, setSelectedPorts] = useState(bridge?.ports || []);
const [candidatePorts, setCandidatePorts] = useState([]);
const { interfaces } = useNetworkState();
const dispatch = useNetworkDispatch();
useEffect(() => {
if (isEditing) {
setCandidatePorts(Object.values(interfaces).filter(i => i.name !== connection.name));
} else {
setCandidatePorts(Object.values(interfaces));
}
}, [connection, isEditing, interfaces]);
const addOrUpdateConnection = () => {
if (isEditing) {
updateConnection(
dispatch, connection, { name, bridge: { ports: selectedPorts } }
);
} else {
addConnection(
dispatch, { name, type: interfaceType.BRIDGE, bridge: { ports: selectedPorts, } }
);
}
onClose();
};
const handleSelectedPorts = (name) => (value) => {
if (value) {
setSelectedPorts([...selectedPorts, name]);
} else {
setSelectedPorts(selectedPorts.filter(i => i !== name));
}
};
const isIncomplete = () => {
return (name === "" || selectedPorts.length === 0);
};
return (
<ModalForm
caption={connection?.name}
title={isEditing ? _("Edit Bridge") : _("Add Bridge")}
isOpen={isOpen}
onCancel={onClose}
onSubmit={addOrUpdateConnection}
onSubmitLabel={isEditing ? _("Change") : _("Add")}
onSubmitDisable={isIncomplete()}
>
<FormGroup
label={_("Name")}
isRequired
fieldId="interface-name"
helperText={_("Please, provide the interface name (e.g., br0)")}
>
<TextInput
isRequired
isDisabled={isEditing}
id="interface-name"
value={name}
onChange={setName}
/>
</FormGroup>
<FormGroup
label={_("Ports")}
isRequired
>
{candidatePorts.map(({ name }) => (
<Checkbox
label={name}
key={name}
isChecked={selectedPorts.includes(name)}
onChange={handleSelectedPorts(name)}
/>
))}
</FormGroup>
</ModalForm>
);
}
Example #27
Source File: BondForm.js From cockpit-wicked with GNU General Public License v2.0 | 4 votes |
BondForm = ({ isOpen, onClose, connection }) => {
const { bond } = connection || {};
const isEditing = !!connection;
const [name, setName] = useState(connection?.name || "");
const [mode, setMode] = useState(bond?.mode || bondingModes.ACTIVE_BACKUP);
const [options, setOptions] = useState(bond?.options || "miimon=100");
const [selectedInterfaces, setSelectedInterfaces] = useState(bond?.interfaces || []);
const [candidateInterfaces, setCandidateInterfaces] = useState([]);
const { interfaces } = useNetworkState();
const dispatch = useNetworkDispatch();
useEffect(() => {
if (isEditing) {
setCandidateInterfaces(Object.values(interfaces).filter(i => i.name !== connection.name));
} else {
setCandidateInterfaces(Object.values(interfaces));
}
}, [connection, isEditing, interfaces]);
const addOrUpdateConnection = () => {
const bondingAttrs = {
name,
bond: {
mode,
interfaces: selectedInterfaces,
options
}
};
if (isEditing) {
updateConnection(dispatch, connection, bondingAttrs);
} else {
addConnection(dispatch, { ...bondingAttrs, type: interfaceType.BONDING });
}
onClose();
};
const handleSelectedInterfaces = (name) => (value) => {
if (value) {
setSelectedInterfaces([...selectedInterfaces, name]);
} else {
setSelectedInterfaces(selectedInterfaces.filter(i => i !== name));
}
};
const isIncomplete = () => {
return (name === "" || selectedInterfaces.length === 0);
};
return (
<ModalForm
caption={connection?.name}
title={isEditing ? _("Edit Bond") : _("Add Bond")}
isOpen={isOpen}
onCancel={onClose}
onSubmit={addOrUpdateConnection}
onSubmitDisable={isIncomplete()}
onSubmitLabel={isEditing ? _("Change") : _("Add")}
>
<FormGroup
label={_("Name")}
isRequired
fieldId="interface-name"
helperText={_("Please, provide the interface name (e.g., bond0)")}
>
<TextInput
isRequired
isDisabled={isEditing}
id="interface-name"
value={name}
onChange={setName}
/>
</FormGroup>
<FormGroup
label={_("Interfaces")}
isRequired
>
{candidateInterfaces.map(({ name }) => (
<Checkbox
label={name}
key={name}
isChecked={selectedInterfaces.includes(name)}
onChange={handleSelectedInterfaces(name)}
/>
))}
</FormGroup>
<FormGroup
label={_("Mode")}
isRequired
fieldId="bonding-mode"
>
<FormSelect value={mode} onChange={setMode} id="bonding-mode">
{modeOptions.map((option, index) => (
<FormSelectOption key={index} {...option} />
))}
</FormSelect>
</FormGroup>
<FormGroup
label={_("Options")}
fieldId="bond-options"
helperText={_("Use this field to provide more options using the key=value format")}
>
<TextInput
isRequired
id="bond-options"
value={options}
onChange={setOptions}
/>
</FormGroup>
</ModalForm>
);
}
Example #28
Source File: EditRequestModal.js From access-requests-frontend with Apache License 2.0 | 4 votes |
RequestDetailsForm = ({
user = {},
targetAccount,
setTargetAccount,
targetOrg,
setTargetOrg,
start,
setStart,
end,
setEnd,
disableAccount,
disableOrgId,
isLoading,
error,
}) => {
let [startDate, setStartDate] = React.useState();
const [validatedAccount, setValidatedAccount] = React.useState(
error ? 'error' : 'default'
);
const [validatedOrgId, setValidatedOrgId] = React.useState(
error ? 'error' : 'default'
);
// https://github.com/RedHatInsights/insights-rbac/blob/master/rbac/api/cross_access/model.py#L49
const startValidator = (date) => {
if (isValidDate(date)) {
if (date < today) {
setEnd('');
return 'Start date must be today or later';
}
if (date > maxStartDate) {
setEnd('');
return 'Start date must be within 60 days of today';
}
}
return '';
};
const endValidator = (date) => {
if (isValidDate(startDate)) {
if (startDate > date) {
return 'End date must be after from date';
}
}
const maxToDate = new Date(startDate);
maxToDate.setFullYear(maxToDate.getFullYear() + 1);
if (date > maxToDate) {
return 'Access duration may not be longer than one year';
}
return '';
};
const onStartChange = (str, date) => {
setStartDate(new Date(date));
setStart(str);
if (isValidDate(date) && !startValidator(date)) {
date.setDate(date.getDate() + 7);
setEnd(dateFormat(date));
} else {
setEnd('');
}
};
const onEndChange = (str, date) => {
if (endValidator(date)) {
setEnd('');
} else {
setEnd(str);
}
};
return (
<Form onSubmit={(ev) => ev.preventDefault()} isDisabled={isLoading}>
<Title headingLevel="h2">Request details</Title>
<Split hasGutter>
<SplitItem isFilled>
<FormGroup label="First name" labelIcon={getLabelIcon('first name')}>
<TextInput id="first-name" value={user.first_name} isDisabled />
</FormGroup>
</SplitItem>
<SplitItem isFilled>
<FormGroup label="Last name" labelIcon={getLabelIcon('last name')}>
<TextInput id="last-name" value={user.last_name} isDisabled />
</FormGroup>
</SplitItem>
</Split>
<FormGroup
label="Account number"
isRequired
labelIcon={getLabelIcon('account number')}
helperText="Enter the account number you would like access to"
helperTextInvalid="Please enter a valid account number"
validated={validatedAccount}
>
<TextInput
id="account-number"
value={targetAccount}
onChange={(val) => {
setTargetAccount(val);
setValidatedAccount('default');
}}
isRequired
placeholder="Example, 8675309"
validated={validatedAccount}
isDisabled={disableAccount}
/>
</FormGroup>
<FormGroup
label="Organization id"
isRequired
labelIcon={getLabelIcon('organization id')}
helperText="Enter the organization id you would like access to"
helperTextInvalid="Please enter a valid organization id"
validated={validatedOrgId}
>
<TextInput
id="org-id"
value={targetOrg}
onChange={(val) => {
setTargetOrg(val);
setValidatedOrgId('default');
}}
isRequired
placeholder="Example, 1234567"
validated={validatedOrgId}
isDisabled={disableOrgId}
/>
</FormGroup>
<FormGroup
label="Access duration"
isRequired
labelIcon={getLabelIcon('access duration')}
>
<Split>
<SplitItem>
<DatePicker
width="300px"
aria-label="Start date"
value={start}
dateFormat={dateFormat}
dateParse={dateParse}
placeholder="mm/dd/yyyy"
onChange={onStartChange}
validators={[startValidator]}
/>
</SplitItem>
<SplitItem style={{ padding: '6px 12px 0 12px' }}>to</SplitItem>
<SplitItem>
<DatePicker
width="300px"
aria-label="End date"
value={end}
dateFormat={dateFormat}
dateParse={dateParse}
placeholder="mm/dd/yyyy"
onChange={onEndChange}
validators={[endValidator]}
rangeStart={start}
/>
</SplitItem>
</Split>
</FormGroup>
</Form>
);
}
Example #29
Source File: sign-up.js From ibutsu-server with MIT License | 4 votes |
render() {
const loginMessage = (
<LoginMainFooterBandItem>
Already registered? <NavLink to="/login">Log in.</NavLink>
</LoginMainFooterBandItem>
);
const forgotCredentials = (
<LoginMainFooterBandItem>
<NavLink to="/forgot-password">Forgot username or password?</NavLink>
</LoginMainFooterBandItem>
);
const backgroundImages = {
lg: '/images/pfbg_1200.jpg',
sm: '/images/pfbg_768.jpg',
sm2x: '/images/[email protected]',
xs: '/images/pfbg_576.jpg',
xs2x: '/images/[email protected]'
};
return (
<LoginPage
footerListVariants="inline"
brandImgSrc="/images/ibutsu-wordart-164.png"
brandImgAlt="Ibutsu"
backgroundImgSrc={backgroundImages}
backgroundImgAlt="Background image"
textContent="Ibutsu is an open source test result aggregation. Collect and display your test results, view artifacts, and monitor tests."
loginTitle="Register a new account"
loginSubtitle="Please type in your e-mail address and a secure password"
signUpForAccountMessage={loginMessage}
forgotCredentials={forgotCredentials}
>
<Form>
{this.state.showAlert &&
<FormAlert>
<Alert variant={this.state.alertType} title={this.state.alertText} aria-live="polite" isInline/>
</FormAlert>
}
<FormGroup
label="Email address"
isRequired
fieldId="email"
validated={this.state.isValidEmail ? 'default' : 'error'}
helperText="The e-mail address you want to use to log in"
>
<TextInput
isRequired
type="email"
id="email"
name="email"
validated={this.state.isValidEmail ? 'default' : 'error'}
aria-describedby="email-helper"
value={this.state.emailValue}
onChange={this.onEmailChange}
/>
</FormGroup>
<FormGroup
label="Password"
isRequired
fieldId="password"
validated={this.state.isValidPassword ? 'default' : 'error'}
>
<InputGroup>
{!this.state.isPasswordVisible &&
<TextInput
isRequired
type="password"
id="password"
name="password"
validated={this.state.isValidPassword ? 'default' : 'error'}
aria-describedby="password-helper"
value={this.state.passwordValue}
onChange={this.onPasswordChange} />
}
{this.state.isPasswordVisible &&
<TextInput
isRequired
type="text"
id="password"
name="password"
validated={this.state.isValidPassword ? 'default' : 'error'}
aria-describedby="password-helper"
value={this.state.passwordValue}
onChange={this.onPasswordChange} />}
<Button variant="control" aria-label="Show password" onClick={this.onPasswordVisibleClick}>
{!this.state.isPasswordVisible && <EyeIcon/>}
{this.state.isPasswordVisible && <EyeSlashIcon/>}
</Button>
</InputGroup>
<PasswordErrorBoundary>
<Suspense fallback={""}>
<PasswordStrengthBar password={this.state.passwordValue}/>
</Suspense>
</PasswordErrorBoundary>
</FormGroup>
<FormGroup
label="Confirm password"
isRequired
fieldId="confirm-password"
helperText={this.state.confirmPasswordHelpText}
helperTextInvalid="Passwords do not match"
validated={this.state.confirmPasswordValidation}
>
<InputGroup>
{!this.state.isConfirmPasswordVisible && <TextInput isRequired type="password" id="confirm-password" name="confirm-password" aria-describedby="confirm-password-helper" value={this.state.confirmPasswordValue} onChange={this.onConfirmPasswordChange} validated={this.state.confirmPasswordValidation} />}
{this.state.isConfirmPasswordVisible && <TextInput isRequired type="text" id="confirm-password" name="confirm-password" aria-describedby="confirm-password-helper" value={this.state.confirmPasswordValue} onChange={this.onConfirmPasswordChange} validated={this.state.confirmPasswordValidation} />}
<Button variant="control" aria-label="Show password" onClick={this.onConfirmPasswordVisibleClick}>
{!this.state.isConfirmPasswordVisible && <EyeIcon/>}
{this.state.isConfirmPasswordVisible && <EyeSlashIcon/>}
</Button>
</InputGroup>
</FormGroup>
<ActionGroup>
<Button variant="primary" isBlock onClick={this.onRegisterButtonClick}>Register</Button>
</ActionGroup>
</Form>
</LoginPage>
);
}