@patternfly/react-core#TextInput JavaScript Examples

The following examples show how to use @patternfly/react-core#TextInput. 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: tokens.js    From ibutsu-server with MIT License 6 votes vote down vote up
tokenToRow(token) {
    return {
      "cells": [
        {title: token.name},
        {title: (
          <InputGroup>
            <TextInput value={token.token} aria-label={`token-input-${token.id}`} ouiaId={`token-input-${token.id}`} />
            <Button variant="control" onClick={() => this.copyToClipboard(token.token)} ouiaId={`copy-button-${token.id}`}><CopyIcon /></Button>
          </InputGroup>
        )},
        {title: token.expires},
        {title: <Button variant="danger" onClick={() => this.onDeleteTokenClick(token)}>Delete</Button>}
      ]
    };
  }
Example #2
Source File: HostSelector.js    From content-preview with Apache License 2.0 6 votes vote down vote up
HostSelector = ({ baseUrl, setBaseUrl }) => {
    const [input, setInput] = useState(baseUrl);
    const history = useHistory();

    const setUrl = (url) => {
        setInput(url);
        setBaseUrl(url);
        setBaseUrlConstant(url);
        history.push(history.location.pathname);
    };

    return <InputGroup>
        <Button id="select-production" variant="control" onClick={() => setUrl(PRODUCTION_URL)}>Production</Button>
        <Button id="select-localhost" variant="control" onClick={() => setUrl(LOCALHOST)}>Localhost</Button>
        <TextInput id="custom-input" type='url' aria-label="custom input field" value={input} onChange={(input) => setInput(input)} />
        <Button variant="primary" onClick={() => setUrl(input)}>Submit</Button>
    </InputGroup>;
}
Example #3
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 #4
Source File: multivalueinput.js    From ibutsu-server with MIT License 6 votes vote down vote up
render() {
    let style = clone(this.style);
    style["width"] = "auto";
    return (
      <React.Fragment>
        <ChipGroup>
          {this.state.values.map(value => (
            <Chip key={value} onClick={() => this.handleItemRemove(value)}>
              {value}
            </Chip>
          ))}
        </ChipGroup>
        <TextInput
          type="text"
          onChange={this.handleTextInputChange}
          onKeyPress={this.handleKeyPress}
          value={this.state.value}
          aria-label="multi-text-input"
          placeholder="Type any value and hit <Enter>"
          style={style}  // necessary to get chips on same line
        />
      </React.Fragment>
    );
  }
Example #5
Source File: IPInput.js    From cockpit-wicked with GNU General Public License v2.0 6 votes vote down vote up
IPInput = ({ placeholder, onError = () => null, ...props }) => {
    const [validated, setValidated] = useState("default");

    return (
        <TextInput
            placeholder={ placeholder || _("IP Address")}
            validated={ValidatedOptions[validated]}
            onFocus={(e) => setValidated("default")}
            onBlur={(e) => {
                const value = e.target.value;

                if (value === "" || isValidIP(value)) {
                    return;
                }

                setValidated("error");
                onError(value);
            }}
            {...props}
        />
    );
}
Example #6
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 #7
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 #8
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 #9
Source File: user-list.js    From ibutsu-server with MIT License 5 votes vote down vote up
render() {
    document.title = 'Users - Administration | Ibutsu';
    const { columns, rows, textFilter } = this.state;
    const pagination = {
      pageSize: this.state.pageSize,
      page: this.state.page,
      totalItems: this.state.totalItems
    };
    const filters = [
      <TextInput type="text" id="filter" placeholder="Search for user..." value={textFilter || ''} onChange={this.onTextChanged} style={{height: "inherit"}} key="textFilter"/>
    ];
    return (
      <React.Fragment>
        <PageSection id="page" variant={PageSectionVariants.light}>
          <TextContent>
            <Text className="title" component="h1" ouiaId="users">Users</Text>
          </TextContent>
        </PageSection>
        <PageSection className="pf-u-pb-0">
          <Card>
            <CardBody className="pf-u-p-0">
              <FilterTable
                columns={columns}
                rows={rows}
                filters={filters}
                pagination={pagination}
                isEmpty={this.state.isEmpty}
                isError={this.state.isError}
                onSetPage={this.setPage}
                onSetPageSize={this.setPageSize}
              />
            </CardBody>
          </Card>
        </PageSection>
        <Modal
          title="Confirm Delete"
          variant="small"
          isOpen={this.state.isDeleteModalOpen}
          onClose={this.onDeleteModalClose}
          actions={[
            <Button key="delete" variant="danger" isLoading={this.state.isDeleting} isDisabled={this.state.isDeleting} onClick={this.onModalDeleteClick}>
              {this.state.isDeleting ? 'Deleting...' : 'Delete'}
            </Button>,
            <Button key="cancel" variant="secondary" isDisabled={this.state.isDeleting} onClick={this.onDeleteModalClose}>
              Cancel
            </Button>
          ]}
        >
          Are you sure you want to delete &ldquo;{this.state.selectedUser && this.state.selectedUser.name}&rdquo;? This cannot be undone!
        </Modal>
      </React.Fragment>
    );
  }
Example #10
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 #11
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 #12
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 #13
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 #14
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 #15
Source File: WirelessEssidSelect.js    From cockpit-wicked with GNU General Public License v2.0 5 votes vote down vote up
WirelessEssidSelect = ({ essid, setEssid, iface }) => {
    const [isOpen, setIsOpen] = useState(false);
    const [essidList, setEssidList] = useState(undefined);

    const refreshList = (name) => {
        fetchEssidList(name)
                .then(result => {
                    const list = [...new Set([...result])];
                    setEssidList(list.sort());
                })
                .catch(console.error);
    };

    const onToggle = isOpen => {
        if (isOpen) {
            setEssidList(undefined);
            refreshList(iface.name);
        }

        setIsOpen(isOpen);
    };

    const onSelect = (selection) => {
        setEssid(selection);
        setIsOpen(false);
    };

    const renderOptions = () => {
        if (!essidList) {
            return [
                <DropdownItem isDisabled key="scanning" icon={<Spinner size="md" />}>
                    {_("Scanning...")}
                </DropdownItem>
            ];
        }

        if (essidList.length === 0) {
            return [
                <DropdownItem isDisabled key="no-networks-found" icon={<ExclamationIcon />}>
                    {_("No networks found")}
                </DropdownItem>
            ];
        }

        return essidList.map(value => <DropdownItem key={value} onClick={() => onSelect(value)}>{value}</DropdownItem>);
    };

    return (
        <InputGroup>
            <TextInput id="essid" value={essid} onChange={setEssid} type="text" aria-label="Essid" />
            <Dropdown
              position={DropdownPosition.right}
              isOpen={isOpen}
              dropdownItems={renderOptions()}
              toggle={
                  <DropdownToggle id="essid-scanned-list" toggleIndicator={null} onToggle={onToggle} aria-label="Essid scanned list">
                      <SearchIcon />
                  </DropdownToggle>
              }
            />
        </InputGroup>
    );
}
Example #16
Source File: jenkinsjob.js    From ibutsu-server with MIT License 4 votes vote down vote up
render() {
    const {
      columns,
      rows,
      boolSelection,
      fieldSelection,
      isFieldOpen,
      fieldOptions,
      isBoolOpen,
      isEmpty,
      isError,
      isOperationOpen,
      operationSelection,
      pagination,
      textFilter,
    } = this.state;

    const filterMode = getFilterMode(fieldSelection);
    const operationMode = getOperationMode(operationSelection);
    const operations = getOperationsFromField(fieldSelection);
    const filters = [
      <Select
        aria-label="Select a field"
        placeholderText="Select a field"
        selections={fieldSelection}
        isOpen={isFieldOpen}
        isCreatable={true}
        variant={SelectVariant.typeahead}
        maxHeight={"1140%"}
        onToggle={this.onFieldToggle}
        onSelect={this.onFieldSelect}
        onCreateOption={this.onFieldCreate}
        onClear={this.onFieldClear}
        key="field"
      >
        {fieldOptions.map((option, index) => (
          <SelectOption key={index} value={option} />
        ))}
      </Select>,
      <Select
        variant={SelectVariant.single}
        onToggle={this.onOperationToggle}
        onSelect={this.onOperationSelect}
        isOpen={isOperationOpen}
        selections={operationSelection}
        key="operation"
      >
        {Object.keys(operations).map((option, index) => <SelectOption key={index} value={option}/>)}
      </Select>,
      <React.Fragment key="value">
        {(operationMode === 'bool') &&
        <Select
          aria-label="Select True/False"
          placeholderText="Select True/False"
          variant={SelectVariant.single}
          isOpen={isBoolOpen}
          selections={boolSelection}
          onToggle={this.onBoolToggle}
          onSelect={this.onBoolSelect}
          onClear={this.onBoolClear}
        >
          {["True", "False"].map((option, index) => (
            <SelectOption key={index} value={option} />
          ))}
        </Select>
        }
        {(filterMode === 'text' && operationMode === 'single') &&
          <TextInput type="text" id="textSelection" placeholder="Type in value" value={textFilter || ''} onChange={this.onTextChanged} style={{height: "inherit"}}/>
        }
        {(operationMode === 'multi') &&
          <MultiValueInput onValuesChange={this.onInValuesChange} style={{height: "inherit"}}/>
        }
      </React.Fragment>
    ];

    return (
      <Card>
        <CardBody className="pf-u-p-0">
          <FilterTable
            columns={columns}
            rows={rows}
            filters={filters}
            pagination={pagination}
            isEmpty={isEmpty}
            isError={isError}
            onSetPage={this.setPage}
            onSetPageSize={this.setPageSize}
            onApplyFilter={this.applyFilter}
            onRemoveFilter={this.removeFilter}
            onClearFilters={this.clearFilters}
            activeFilters={this.state.filters}
          />
        </CardBody>
      </Card>
    );
  }
Example #17
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>
    );
  }
Example #18
Source File: user-edit.js    From ibutsu-server with MIT License 4 votes vote down vote up
render() {
    const { user, projects, userProjects } = this.state;
    return (
      <React.Fragment>
        <PageSection variant={PageSectionVariants.light}>
          <Title headingLevel="h1" size='2xl' className="pf-c-title">
            Users / {user && user.name} {' '}
            {user && user.is_superadmin &&
              <Label className="super-admin-label" variant="outline" color="blue">Administrator</Label>
            }
          </Title>
        </PageSection>
        <PageSection>
          {!user && <Alert variant="info" title="Loading..." />}
          {user &&
          <Card>
            <CardBody>
              <Form>
                <FormGroup label="Name" isRequired fieldId="userName" helperText="The user's name">
                  <TextInput
                    isRequired
                    type="text"
                    id="userName"
                    name="userName"
                    aria-describedby="The user's name"
                    value={user.name}
                    onChange={this.onUserNameChanged}
                  />
                </FormGroup>
                <FormGroup label="E-mail" isRequired fieldId="userEmail" helperText="The user's e-mail address">
                  <TextInput
                    isRequired
                    type="email"
                    id="userEmail"
                    name="userEmail"
                    aria-describedby="The user's e-mail address"
                    value={user.email}
                    onChange={this.onUserEmailChanged}
                  />
                </FormGroup>
                <FormGroup fieldId="userStatus" label="User status">
                  <Checkbox
                    label="Is active"
                    id="userIsActive"
                    name="userIsActive"
                    aria-label="User is active"
                    isChecked={user.is_active}
                    onChange={this.onIsActiveToggle}
                  />
                  <Checkbox
                    label="Is administrator"
                    id="userIsAdmin"
                    name="userIsAdmin"
                    aria-label="User is administrator"
                    isChecked={user.is_superadmin}
                    onChange={this.onIsAdminToggle}
                  />
                </FormGroup>
                <FormGroup fieldId="userProjects" label="Projects" helperText="The projects to which a user has access">
                   <Select
                     variant={SelectVariant.typeaheadMulti}
                     typeAheadAriaLabel="Select one or more projects"
                     onToggle={this.onProjectsToggle}
                     onSelect={this.onProjectsSelect}
                     onClear={this.onProjectsClear}
                     selections={userProjects}
                     isOpen={this.state.isProjectsOpen}
                     aria-labelledby="userProjects"
                     placeholderText="Select one or more projects"
                   >
                     {projects.map(project => (
                       <SelectOption key={project.id} value={projectToOption(project)} description={project.name} />
                     ))}
                   </Select>
                </FormGroup>
                <ActionGroup>
                  <Button variant="primary" onClick={this.onSubmitClick}>Submit</Button>
                  <Button variant="secondary" onClick={this.props.history.goBack}>Cancel</Button>
                </ActionGroup>
              </Form>
            </CardBody>
          </Card>
          }
        </PageSection>
      </React.Fragment>
    );
  }
Example #19
Source File: run.js    From ibutsu-server with MIT License 4 votes vote down vote up
render() {
    let passed = 0, failed = 0, errors = 0, xfailed = 0, xpassed = 0, skipped = 0, not_run = 0;
    let created = 0;
    let calculatePasses = true;
    const { run, columns, rows, classificationTable, artifactTabs } = this.state;
    const jsonViewTheme = getTheme() === 'dark' ? 'tomorrow' : 'rjv-default';

    if (run.start_time) {
      created = new Date(run.start_time);
    }
    else {
      created = new Date(run.created);
    }
    if (run.summary) {
      if (run.summary.passes) {
        passed = run.summary.passes;
        calculatePasses = false;
      }
      if (run.summary.tests && calculatePasses) {
        passed = run.summary.tests;
      }
      if (run.summary.failures) {
        passed -= calculatePasses ? run.summary.failures : 0;
        failed = run.summary.failures;
      }
      if (run.summary.errors) {
        passed -= calculatePasses ? run.summary.errors : 0;
        errors = run.summary.errors;
      }
      if (run.summary.xfailures) {
        passed -= calculatePasses ? run.summary.xfailures : 0;
        xfailed = run.summary.xfailures;
      }
      if (run.summary.xpasses) {
        passed -= calculatePasses ? run.summary.xpasses : 0;
        xpassed = run.summary.xpasses;
      }
      if (run.summary.skips) {
        passed -= calculatePasses ? run.summary.skips : 0;
        skipped = run.summary.skips;
      }
      if (run.summary.not_run) {
        not_run = run.summary.not_run;
      }
      else if (run.summary.collected) {
        not_run = run.summary.collected - run.summary.tests;
      }
    }
    const pagination = {
      pageSize: this.state.pageSize,
      page: this.state.page,
      totalItems: this.state.totalItems
    }
    return (
      <React.Fragment>
        <PageSection variant={PageSectionVariants.light}>
          <TextContent>
            <Text component="h1" className="pf-c-title">Run {run.id}</Text>
          </TextContent>
        </PageSection>
        <PageSection>
          {!this.state.isRunValid &&
          <EmptyObject headingText="Run not found" returnLink="/runs" returnLinkText="Return to runs list" />
          }
          {this.state.isRunValid &&
            <Tabs activeKey={this.state.activeTab} onSelect={this.onTabSelect} isBox>
              <Tab eventKey={'summary'} title={<TabTitle icon={InfoCircleIcon} text="Summary" />}>
                <Card>
                  <CardBody style={{padding: 0}} id="run-detail">
                    <Grid style={{backgroundColor: '#fff'}}>
                      <GridItem span={6}>
                        <DataList selectedDataListItemId={null} aria-label="Run properties" style={{borderBottom: 'none', borderTop: 'none'}}>
                          <DataListItem aria-labelledby="Duration">
                            <DataListItemRow>
                              <DataListItemCells
                                dataListCells={[
                                  <DataListCell key={1} width={2}><strong>Duration:</strong></DataListCell>,
                                  <DataListCell key={2} width={4}>{round(run.duration)}s</DataListCell>
                                ]}
                              />
                            </DataListItemRow>
                          </DataListItem>
                          <DataListItem aria-labelledby="Started">
                            <DataListItemRow>
                              <DataListItemCells
                                dataListCells={[
                                  <DataListCell key={1} width={2}><strong>Started:</strong></DataListCell>,
                                  <DataListCell key={2} width={4}>{created.toLocaleString()}</DataListCell>
                                ]}
                              />
                            </DataListItemRow>
                          </DataListItem>
                          {run.metadata && run.metadata.component &&
                          <DataListItem aria-labelledby="Component">
                            <DataListItemRow>
                              <DataListItemCells
                                dataListCells={[
                                  <DataListCell key={1} width={2}><strong>Component:</strong></DataListCell>,
                                  <DataListCell key={2} width={4}>{run.metadata.component}</DataListCell>
                                ]}
                              />
                            </DataListItemRow>
                          </DataListItem>
                          }
                          {run.metadata && run.metadata.env &&
                            <DataListItem aria-labelledby="Environment">
                              <DataListItemRow>
                                <DataListItemCells
                                  dataListCells={[
                                    <DataListCell key={1} width={2}><strong>Environment:</strong></DataListCell>,
                                    <DataListCell key={2} width={4}>{run.metadata.env}</DataListCell>
                                  ]}
                                />
                              </DataListItemRow>
                            </DataListItem>
                          }
                          {run.metadata && run.metadata.tags &&
                            <DataListItem aria-labelledby="tags-label">
                              <DataListItemRow>
                                <DataListItemCells
                                  dataListCells={[
                                    <DataListCell key="tags-label" width={2}><strong>Tags:</strong></DataListCell>,
                                    <DataListCell key="tags-data" width={4}>
                                      <Flex>
                                        {run.metadata.tags.map((tag) => <FlexItem spacer={{ default: 'spacerXs' }} key={tag}><Label color="blue" variant="filled">{tag}</Label></FlexItem>)}
                                      </Flex>
                                    </DataListCell>
                                  ]}
                                />
                              </DataListItemRow>
                            </DataListItem>
                          }
                        {run.metadata && run.metadata.jenkins && run.metadata.jenkins.job_name &&
                          <DataListItem aria-labelledby="Jenkins Job Name">
                            <DataListItemRow>
                              <DataListItemCells
                                dataListCells={[
                                  <DataListCell key={1} width={2}><strong>Jenkins Job Name:</strong></DataListCell>,
                                  <DataListCell key={2} width={4}>{run.metadata.jenkins.job_name}</DataListCell>
                                ]}
                              />
                            </DataListItemRow>
                          </DataListItem>
                          }
                          {run.source &&
                            <DataListItem aria-labelledby="Source">
                              <DataListItemRow>
                                <DataListItemCells
                                  dataListCells={[
                                    <DataListCell key={1} width={2}><strong>Source:</strong></DataListCell>,
                                    <DataListCell key={2} width={4}>{run.source}</DataListCell>
                                  ]}
                                />
                              </DataListItemRow>
                            </DataListItem>
                          }
                        </DataList>
                      </GridItem>
                      <GridItem span={6}>
                        <DataList selectedDataListItemId={null} aria-label="Summary properties" style={{borderBottom: 0, borderTop: 0}}>
                          <DataListItem aria-labelledby="Summary">
                            <DataListItemRow>
                              <DataListItemCells
                                style={{paddingBottom: 0}}
                                dataListCells={[
                                  <DataListCell key={1} width={2}><strong>Summary:</strong></DataListCell>,
                                  <DataListCell key={2} width={4} style={{paddingTop: 0}}>
                                    <DataList selectedDataListItemId={null} aria-label="Summary" style={{borderBottom: 0, borderTop: 0}}>
                                      <DataListItem aria-labelledby="Total">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Total:</DataListCell>,
                                              <DataListCell key={2}>{run.summary.collected ? run.summary.collected : run.summary.tests}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Passed">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Passed:</DataListCell>,
                                              <DataListCell key={2}>{passed}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Failed">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Failed:</DataListCell>,
                                              <DataListCell key={2}>{failed}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Error">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Error:</DataListCell>,
                                              <DataListCell key={2}>{errors}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Xfailed">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Xfailed:</DataListCell>,
                                              <DataListCell key={2}>{xfailed}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Xpassed">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Xpassed:</DataListCell>,
                                              <DataListCell key={2}>{xpassed}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Skipped">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Skipped:</DataListCell>,
                                              <DataListCell key={2}>{skipped}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                      <DataListItem aria-labelledby="Not Run">
                                        <DataListItemRow>
                                          <DataListItemCells
                                            dataListCells={[
                                              <DataListCell key={1}>Not Run:</DataListCell>,
                                              <DataListCell key={2}>{not_run}</DataListCell>
                                            ]}
                                          />
                                        </DataListItemRow>
                                      </DataListItem>
                                    </DataList>
                                  </DataListCell>
                                ]}
                              />
                            </DataListItemRow>
                          </DataListItem>
                        </DataList>
                      </GridItem>
                    </Grid>
                  </CardBody>
                </Card>
              </Tab>
              <Tab eventKey={'results-list'} title={<TabTitle icon={CatalogIcon} text="Results List" />}>
                <Card className="pf-u-mt-lg">
                  <CardHeader>
                    <Flex style={{ width: '100%' }}>
                      <FlexItem grow={{ default: 'grow' }}>
                        <TextContent>
                          <Text component="h2" className="pf-c-title pf-m-xl">Test Results</Text>
                        </TextContent>
                      </FlexItem>
                      <FlexItem>
                        <Button variant="secondary" onClick={this.refreshResults}>Refresh results</Button>
                      </FlexItem>
                      <FlexItem>
                        <Link to={`/results?run_id[eq]=${run.id}`} className="pf-c-button pf-m-primary" style={{marginLeft: '2px'}}>See all results <ChevronRightIcon /></Link>
                      </FlexItem>
                    </Flex>
                  </CardHeader>
                  <CardBody>
                    <FilterTable
                      columns={columns}
                      rows={rows}
                      pagination={pagination}
                      isEmpty={this.state.isEmpty}
                      isError={this.state.isError}
                      onSetPage={this.setPage}
                      onSetPageSize={this.pageSizeSelect}
                    />
                  </CardBody>
                </Card>
              </Tab>
              <Tab eventKey={'results-tree'} title={<TabTitle icon={RepositoryIcon} text="Results Tree" />}>
                <Card className="pf-u-mt-lg">
                  <CardBody>
                    <Grid gutter="sm">
                      {false && <GridItem span={12}>
                        <div style={{paddingTop: "1em"}}>
                          <TextInput value={this.state.treeSearch} type="text" onChange={this.onSearch} placeholder="Search tree..." aria-label="Filter tree" />
                        </div>
                      </GridItem>
                      }
                      {this.state.resultsTree.core.data.length === 0 &&
                        <GridItem span={12}>
                          <Bullseye><center><Spinner size="xl"/></center></Bullseye>
                        </GridItem>
                      }
                      {this.state.resultsTree.core.data !== 0 &&
                        <React.Fragment>
                          <GridItem span={5}>
                            <TreeView treeData={this.state.resultsTree} onChange={(e, data) => this.handleJSTreeChange(e, data)}/>
                          </GridItem>
                          <GridItem span={7}>
                            {this.state.testResult &&
                            <Card className={this.state.testResult.result}>
                              <CardHeader>
                                {this.state.testResult.test_id}
                                {this.state.testResult.metadata.markers &&
                                  <div style={{float: 'right'}}>
                                    {this.state.testResult.metadata.markers.map((marker) => {
                                      return <Badge isRead key={marker.name}>{marker.name}</Badge>;
                                    })}
                                  </div>
                                }
                              </CardHeader>
                              <CardBody style={{backgroundColor: "var(--pf-c-page__main-section--BackgroundColor)", paddingTop: "1.2em"}}>
                                <ResultView testResult={this.state.testResult}/>
                              </CardBody>
                            </Card>
                            }
                          </GridItem>
                        </React.Fragment>
                      }
                    </Grid>
                  </CardBody>
                </Card>
              </Tab>
              <Tab eventKey={'classify-failures'} title={<TabTitle icon={MessagesIcon} text="Classify Failures" />}>
                {classificationTable}
              </Tab>
              {artifactTabs}
              <Tab eventKey={'run-object'} title={<TabTitle icon={CodeIcon} text="Run Object" />}>
                <Card>
                  <CardBody>
                    <ReactJson src={run} name={null} iconStyle={"triangle"} collapseStringsAfterLength={120} enableClipboard={false} displayDataTypes={false} theme={jsonViewTheme} />
                  </CardBody>
                </Card>
              </Tab>
            </Tabs>
          }
        </PageSection>
      </React.Fragment>
    );
  }
Example #20
Source File: AddressesDataList.js    From cockpit-wicked with GNU General Public License v2.0 4 votes vote down vote up
AddressesDataList = ({ addresses, updateAddresses, allowEmpty = true }) => {
    const addAddress = () => {
        const address = createAddressConfig();
        const currentAddresses = [...addresses];
        currentAddresses.push(address);
        updateAddresses(currentAddresses);
    };

    const updateAddress = (id, field, value) => {
        const nextAddresses = [...addresses];
        const address = nextAddresses.find((addr) => addr.id == id);
        address[field] = value;

        // TODO: check if this do not generate not needed re-renders
        updateAddresses(nextAddresses);
    };

    const deleteAddress = (id) => {
        const nextAddresses = [...addresses];
        const addressIdx = nextAddresses.findIndex((addr) => addr.id == id);
        nextAddresses.splice(addressIdx, 1);
        updateAddresses(nextAddresses);
    };

    const renderAddress = ({ id, local, label }) => {
        const renderDeleteAction = () => {
            if (!allowEmpty && addresses.length === 1) return null;

            return (
                <DataListAction>
                    <Button variant="secondory" className="btn-sm" onClick={() => deleteAddress(id)}>
                        <MinusIcon />
                    </Button>
                </DataListAction>
            );
        };

        const cells = [
            <DataListCell key={`address-${id}-local`}>
                <IPInput
                  defaultValue={local}
                  onChange={(value) => updateAddress(id, 'local', value)}
                  placeholder={_("Address")}
                  aria-label={_("Address")}
                />
            </DataListCell>,
            <DataListCell key={`address-${id}-label`}>
                <TextInput
                  defaultValue={label}
                  onChange={(value) => updateAddress(id, 'label', value)}
                  placeholder={_("Label")}
                  aria-label={_("Label")}
                />
            </DataListCell>
        ];

        return (
            <DataListItem key={`address-${id}`}>
                <DataListItemRow>
                    <DataListItemCells dataListCells={cells} />
                    { renderDeleteAction() }
                </DataListItemRow>
            </DataListItem>
        );
    };

    return (
        <Stack className="data-list-form" hasGutter>
            <StackItem>
                <Split hasGutter>
                    <SplitItem isFilled />
                    <SplitItem>
                        <Button variant="primary" className="btn-sm" onClick={() => addAddress() }>
                            <PlusIcon />
                        </Button>
                    </SplitItem>
                </Split>
            </StackItem>
            <StackItem>
                <DataList isCompact aria-label={_("Addresses data list")}>
                    {addresses.map((address) => renderAddress(address))}
                </DataList>
            </StackItem>
        </Stack>
    );
}
Example #21
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 #22
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 #23
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 #24
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 #25
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 #26
Source File: WirelessForm.js    From cockpit-wicked with GNU General Public License v2.0 4 votes vote down vote up
WirelessForm = ({ isOpen, onClose, iface, connection }) => {
    const { wireless } = connection || {};
    const isEditing = !!connection;
    const [essid, setEssid] = useState(wireless?.essid);
    const [mode, setMode] = useState(wireless?.mode || wirelessModes.MANAGED);
    const [authMode, setAuthMode] = useState(wireless?.authMode || wirelessAuthModes.WEP_OPEN);
    const [password, setPassword] = useState(wireless?.password || "");
    const dispatch = useNetworkDispatch();

    const addOrUpdateConnection = () => {
        if (isEditing) {
            updateConnection(
                dispatch, connection,
                { wireless: { essid, mode, authMode, password } }
            );
        } else {
            addConnection(
                dispatch, { name: iface.name, type: interfaceType.WIRELESS, wireless: { essid, mode, authMode, password } }
            );
        }
        onClose();
    };

    return (
        <Modal
            variant={ModalVariant.small}
            title={isEditing ? _("Edit WiFi settings") : _("Add WiFi settings")}
            isOpen={isOpen}
            onClose={onClose}
            actions={[
                <Button key="confirm" variant="primary" onClick={addOrUpdateConnection}>
                    {isEditing ? _("Change") : _("Add")}
                </Button>,
                <Button key="cancel" variant="link" onClick={onClose}>
                    {_("Cancel")}
                </Button>
            ]}
        >
            <Form>
                <FormGroup
                    label={_("Mode")}
                    isRequired
                    fieldId="wireless-mode"
                >
                    <FormSelect value={mode} onChange={setMode} id="wireless-mode">
                        {modeOptions.map((option, index) => (
                            <FormSelectOption key={index} {...option} />
                        ))}
                    </FormSelect>
                </FormGroup>

                <FormGroup
                    label={_("ESSID")}
                    isRequired
                    fieldId="essid"
                >
                    <WirelessEssidSelect essid={essid} setEssid={setEssid} iface={iface} />
                </FormGroup>
                <FormGroup
                    label={_("Auth Mode")}
                    isRequired
                    fieldId="wireless-auth-mode"
                >
                    <FormSelect value={authMode} onChange={setAuthMode} id="wireless-auth-mode">
                        {authModeOptions.map((option, index) => (
                            <FormSelectOption key={index} {...option} />
                        ))}
                    </FormSelect>
                </FormGroup>
                { (authMode === "psk") &&
                    <FormGroup
                        label={_("Password")}
                        isRequired
                        fieldId="password"
                    >
                        <TextInput
                            isRequired
                            id="password"
                            value={password}
                            onChange={setPassword}
                            type='password'
                        />
                    </FormGroup>}
            </Form>
        </Modal>
    );
}
Example #27
Source File: run-list.js    From ibutsu-server with MIT License 4 votes vote down vote up
render() {
    document.title = 'Test Runs | Ibutsu';
    const {
      columns,
      rows,
      fieldSelection,
      isFieldOpen,
      fieldOptions,
      isOperationOpen,
      operationSelection,
      textFilter,
      boolSelection,
      isBoolOpen,
    } = this.state;
    const filterMode = getFilterMode(fieldSelection);
    const operationMode = getOperationMode(operationSelection);
    const operations = getOperationsFromField(fieldSelection);
    const filters = [
      <Select
        aria-label="Select a field"
        placeholderText="Select a field"
        selections={fieldSelection}
        isOpen={isFieldOpen}
        isCreatable={true}
        variant={SelectVariant.typeahead}
        maxHeight={"1140%"}
        onToggle={this.onFieldToggle}
        onSelect={this.onFieldSelect}
        onCreateOption={this.onFieldCreate}
        onClear={this.onFieldClear}
        key="field"
      >
        {fieldOptions.map((option, index) => (
          <SelectOption key={index} value={option} />
        ))}
      </Select>,
      <Select
        variant={SelectVariant.single}
        onToggle={this.onOperationToggle}
        onSelect={this.onOperationSelect}
        isOpen={isOperationOpen}
        selections={operationSelection}
        key="operation"
      >
        {Object.keys(operations).map((option, index) => <SelectOption key={index} value={option}/>)}
      </Select>,
      <React.Fragment key="value">
        {(operationMode === 'bool') &&
        <Select
          aria-label="Select True/False"
          placeholderText="Select True/False"
          variant={SelectVariant.single}
          isOpen={isBoolOpen}
          selections={boolSelection}
          onToggle={this.onBoolToggle}
          onSelect={this.onBoolSelect}
          onClear={this.onBoolClear}
        >
          {["True", "False"].map((option, index) => (
            <SelectOption key={index} value={option} />
          ))}
        </Select>
        }
        {(filterMode === 'text' && operationMode === 'single') &&
          <TextInput type="text" id="textSelection" placeholder="Type in value" value={textFilter || ''} onChange={this.onTextChanged} style={{height: "inherit"}}/>
        }
        {(operationMode === 'multi') &&
          <MultiValueInput onValuesChange={this.onInValuesChange} style={{height: "inherit"}}/>
        }
      </React.Fragment>
    ];
    const pagination = {
      pageSize: this.state.pageSize,
      page: this.state.page,
      totalItems: this.state.totalItems
    };
    return (
      <React.Fragment>
        <PageSection id="page" variant={PageSectionVariants.light}>
          <TextContent>
            <Text className="title" component="h1">Test runs</Text>
          </TextContent>
        </PageSection>
        <PageSection>
          <Card>
            <CardBody className="pf-u-p-0">
              <FilterTable
                columns={columns}
                rows={rows}
                filters={filters}
                activeFilters={this.state.filters}
                pagination={pagination}
                isEmpty={this.state.isEmpty}
                isError={this.state.isError}
                onApplyFilter={this.applyFilter}
                onRemoveFilter={this.removeFilter}
                onClearFilters={this.clearFilters}
                onSetPage={this.setPage}
                onSetPageSize={this.setPageSize}
                hideFilters={["project_id"]}
              />
            </CardBody>
            <CardFooter>
              <Text className="disclaimer" component="h4">
                * Note: for performance reasons, the total number of items is an approximation.
                Use the API with &lsquo;estimate=false&rsquo; if you need an accurate count.
              </Text>
            </CardFooter>
          </Card>
        </PageSection>
      </React.Fragment>
    );
  }
Example #28
Source File: result-list.js    From ibutsu-server with MIT License 4 votes vote down vote up
render() {
    document.title = 'Test Results | Ibutsu';
    const {
      columns,
      rows,
      filteredRuns,
      fieldSelection,
      isFieldOpen,
      fieldOptions,
      operationSelection,
      isOperationOpen,
      textFilter,
      runSelection,
      isRunOpen,
      resultSelection,
      isResultOpen,
      boolSelection,
      isBoolOpen,
    } = this.state;
    const filterMode = getFilterMode(fieldSelection);
    const operationMode = getOperationMode(operationSelection);
    const operations = getOperationsFromField(fieldSelection);
    const filters = [
      <Select
        aria-label="Select a field"
        placeholderText="Select a field"
        selections={fieldSelection}
        isOpen={isFieldOpen}
        isCreatable={true}
        variant={SelectVariant.typeahead}
        maxHeight={"1140%"}
        onToggle={this.onFieldToggle}
        onSelect={this.onFieldSelect}
        onCreateOption={this.onFieldCreate}
        onClear={this.onFieldClear}
        key="field"
      >
        {fieldOptions.map((option, index) => (
          <SelectOption key={index} value={option} />
        ))}
      </Select>,
      <Select
        variant={SelectVariant.single}
        onToggle={this.onOperationToggle}
        onSelect={this.onOperationSelect}
        isOpen={isOperationOpen}
        selections={operationSelection}
        key="operation"
      >
        {Object.keys(operations).map((option, index) => <SelectOption key={index} value={option}/>)}
      </Select>,
      <React.Fragment key="value">
        {(operationMode === 'bool') &&
        <Select
          aria-label="Select True/False"
          placeholderText="Select True/False"
          variant={SelectVariant.single}
          isOpen={isBoolOpen}
          selections={boolSelection}
          onToggle={this.onBoolToggle}
          onSelect={this.onBoolSelect}
          onClear={this.onBoolClear}
        >
          {["True", "False"].map((option, index) => (
            <SelectOption key={index} value={option} />
          ))}
        </Select>
        }
        {(filterMode === 'text' && operationMode === 'single') &&
          <TextInput type="text" id="textSelection" placeholder="Type in value" value={textFilter || ''} onChange={this.onTextChanged} style={{height: "inherit"}}/>
        }
        {(filterMode === 'text' && operationMode === 'multi') &&
          <MultiValueInput onValuesChange={this.onInValuesChange} style={{height: "inherit"}}/>
        }
        {(filterMode === 'run' && operationMode !== 'bool') &&
          <Select
            aria-label="Select a run"
            placeholderText="Select a run"
            variant={operationMode === 'multi' ? SelectVariant.typeaheadMulti : SelectVariant.typeahead}
            isOpen={isRunOpen}
            selections={runSelection}
            maxHeight={"1140%"}
            onToggle={this.onRunToggle}
            onSelect={this.onRunSelect}
            onClear={this.onRunClear}
            onFilter={this.onRunFilter}
          >
            {filteredRuns.map((option, index) => (
              <SelectOption key={index} value={option} isDisabled={option === DEFAULT_RUNS[0]} />
            ))}
          </Select>
        }
        {(filterMode === 'result' && operationMode !== 'bool') &&
          <Select
            aria-label="Select a result"
            placeholderText="Select a result"
            variant={operationMode === 'multi' ? SelectVariant.typeaheadMulti : SelectVariant.single}
            isOpen={isResultOpen}
            selections={resultSelection}
            onToggle={this.onResultToggle}
            onSelect={this.onResultSelect}
          >
            {["passed", "xpassed", "failed", "xfailed", "skipped", "error"].map((option, index) => (
              <SelectOption key={index} value={option} />
            ))}
          </Select>
        }
      </React.Fragment>
    ];
    const pagination = {
      pageSize: this.state.pageSize,
      page: this.state.page,
      totalItems: this.state.totalItems
    };
    return (
      <React.Fragment>
        <PageSection id="page" variant={PageSectionVariants.light}>
          <TextContent>
            <Text className="title" component="h1">Test results</Text>
          </TextContent>
        </PageSection>
        <PageSection className="pf-u-pb-0">
          <Card>
            <CardBody className="pf-u-p-0">
              <FilterTable
                columns={columns}
                rows={rows}
                filters={filters}
                activeFilters={this.state.filters}
                pagination={pagination}
                isEmpty={this.state.isEmpty}
                isError={this.state.isError}
                onApplyFilter={this.applyFilter}
                onRemoveFilter={this.removeFilter}
                onClearFilters={this.clearFilters}
                onApplyReport={this.applyReport}
                onSetPage={this.setPage}
                onSetPageSize={this.setPageSize}
                hideFilters={["project_id"]}
              />
            </CardBody>
            <CardFooter>
              <Text className="disclaimer" component="h4">
                * Note: for performance reasons, the total number of items is an approximation.
                Use the API with &lsquo;estimate=false&rsquo; if you need an accurate count.
              </Text>
            </CardFooter>
          </Card>
        </PageSection>
      </React.Fragment>
    );
  }
Example #29
Source File: reset-password.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="Reset your password"
        loginSubtitle="Please type in 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="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.onResetButtonClick}>Reset Password</Button>
          </ActionGroup>
        </Form>
      </LoginPage>
    );
  }