@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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
RegisterWithActivationKey = () => (
  <FormGroup
    label={
      <span>
        Register with an activation key&nbsp;
        <Tooltip
          content={
            <div>
              Organization administrators can view, create, and edit activation
              keys on the &quot;Activation keys&quot; 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 &#60;activation-key&#62; -o&nbsp; &#60;organization-id&#62;
    </ClipboardCopy>
  </FormGroup>
)
Example #11
Source File: requestCertificate.jsx    From cockpit-certificates with GNU Lesser General Public License v2.1 6 votes vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
RegisterWithUserName = () => {
  return (
    <FormGroup
      label={
        <span>
          Register with a username and password&nbsp;
          <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.&nbsp;
                  <Text
                    href="https://access.redhat.com/articles/simple-content-access"
                    component="a"
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    Learn about Simple Content Access&nbsp;
                    <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 &#60;username&#62; -p &#60;password&#62;
      </ClipboardCopy>
    </FormGroup>
  );
}
Example #19
Source File: RegistrationCreds.js    From edge-frontend with Apache License 2.0 5 votes vote down vote up
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 vote down vote up
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 vote down vote up
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.&#13;ExamplePackage&#13;example-package&#13;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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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>
    );
  }