formik#useFormikContext TypeScript Examples

The following examples show how to use formik#useFormikContext. 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: SystemSettings.tsx    From nextclade with MIT License 6 votes vote down vote up
export function FormikAutoSubmit() {
  const { values, submitForm, isValid } = useFormikContext()
  React.useEffect(() => {
    if (isValid) {
      void submitForm() // eslint-disable-line no-void
    }
  }, [values, submitForm, isValid])
  return null
}
Example #2
Source File: formikAutoSave.tsx    From amplication with Apache License 2.0 6 votes vote down vote up
FormikAutoSave = ({ debounceMS = 1000, onError }: Props) => {
  const formik = useFormikContext();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  const debouncedSubmit = useCallback(
    debounce(() => {
      return formik
        .submitForm()
        .then(() => {})
        .catch(onError);
    }, debounceMS),
    [formik.submitForm, debounceMS]
  );

  useEffect(() => {
    if (formik.dirty) {
      debouncedSubmit();
    }
  }, [debouncedSubmit, formik.values, formik.dirty]);
  return null;
}
Example #3
Source File: Button.tsx    From frontegg-react with MIT License 6 votes vote down vote up
FButton = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
  const { isValid, dirty } = useFormikContext();
  const { formikDisableIfNotDirty, disabled, ...restProps } = props;
  const _disabled = disabled || !isValid || ((formikDisableIfNotDirty ?? true) && !dirty) || props.loading;
  return (
    <Button
      data-test-id='disabled-btn'
      ref={ref}
      inForm
      {...restProps}
      disabled={_disabled}
      size={props.size ?? props.type === 'submit' ? 'large' : undefined}
      fullWidth={props.fullWidth ?? true}
    />
  );
})
Example #4
Source File: index.tsx    From formik-chakra-ui with MIT License 6 votes vote down vote up
PercentComplete: FC<PercentCompleteProps> = (
  props: PercentCompleteProps
) => {
  const { progressFn = calculateProgress, progressProps, ...rest } = props;
  const { errors, values, validateForm, dirty } = useFormikContext();
  const numFields = Object.keys(values as object).length;
  const numErrors = Object.keys(errors).length;

  useEffect(() => {
    validateForm();
  }, [dirty]);

  return (
    <Box marginY={5} {...rest}>
      <Progress
        hasStripe
        isAnimated
        value={progressFn(numFields, numErrors)}
        {...progressProps}
      />
    </Box>
  );
}
Example #5
Source File: useFormContext.tsx    From Account-Manager with MIT License 6 votes vote down vote up
function useFormContext<V = Values>(): UseFormContextOutput<V> {
  const {errors, isValid, setFieldTouched, setFieldValue, touched, values} = useFormikContext<V>();

  return {
    errors,
    isValid,
    setFieldTouched,
    setFieldValue,
    touched,
    values,
  };
}
Example #6
Source File: AgentsSelectionUtils.ts    From assisted-ui-lib with Apache License 2.0 6 votes vote down vote up
useAgentsAutoSelection = <FormValues extends AllowedFormValues>(
  availableAgents: AgentK8sResource[],
) => {
  const { setFieldValue, values } = useFormikContext<FormValues>();
  const { hostCount, locations, autoSelectedHostIds } = values;

  const [matchingAgents, selectedAgents] = React.useMemo(() => {
    const mAgents = availableAgents.filter((agent) => {
      const agentLocation =
        agent.metadata?.labels?.[AGENT_LOCATION_LABEL_KEY] || AGENT_NOLOCATION_VALUE;
      return locations.length ? locations.includes(agentLocation) : true;
    });
    const sAgents = mAgents.filter((a) => autoSelectedHostIds.includes(a.metadata?.uid || ''));
    return [mAgents, sAgents];
  }, [availableAgents, locations, autoSelectedHostIds]);

  React.useEffect(() => {
    const ids = matchingAgents.map((a) => a.metadata?.uid).splice(0, hostCount);
    if (!isEqual(ids, autoSelectedHostIds)) {
      setTimeout(() => setFieldValue('autoSelectedHostIds', ids, true));
    }
  }, [matchingAgents, setFieldValue, autoSelectedHostIds, hostCount]);

  return { matchingAgents, selectedAgents, hostCount };
}
Example #7
Source File: ErrorFocus.tsx    From firecms with MIT License 6 votes vote down vote up
ErrorFocus = ({ containerRef }:
                               { containerRef?: React.RefObject<HTMLDivElement> }) => {
    const { isSubmitting, isValidating, errors } = useFormikContext();

    useEffect(() => {
        const keys = Object.keys(errors);

        // Whenever there are errors and the form is submitting but finished validating.
        if (keys.length > 0 && isSubmitting && !isValidating) {
            const errorElement = containerRef?.current?.querySelector<HTMLDivElement>(
                `#form_field_${keys[0]}`
            );

            if (errorElement && containerRef?.current) {
                const scrollableParent = getScrollableParent(containerRef.current);
                if (scrollableParent) {
                    const top = errorElement.getBoundingClientRect().top;
                    scrollableParent.scrollTo({
                        top: scrollableParent.scrollTop + top - 64,
                        behavior: "smooth"
                    });
                }
                const input = errorElement.querySelector("input");
                if (input) input.focus();
            }
        }
    }, [isSubmitting, isValidating, errors, containerRef]);

    // This component does not render anything by itself.
    return null;
}
Example #8
Source File: index.tsx    From Account-Manager with MIT License 6 votes vote down vote up
FormButton: FC<FormButtonProps> = ({children, ignoreDirty = false, submitting = false, ...baseButtonProps}) => {
  const {disabled = false, onClick, type = ButtonType.button} = baseButtonProps;
  const {dirty, handleReset, handleSubmit, isValid} = useFormikContext();

  const buttonIsDisabled = useMemo(() => {
    switch (type) {
      case ButtonType.submit:
        return disabled || (!ignoreDirty && !dirty) || !isValid || submitting;
      case ButtonType.reset:
        return disabled || (!ignoreDirty && !dirty) || submitting;
      default:
        return disabled || submitting;
    }
  }, [disabled, dirty, ignoreDirty, isValid, submitting, type]);

  const handleClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
    e?.preventDefault();
    if (buttonIsDisabled) return;

    if (type === ButtonType.submit) handleSubmit();

    if (type === ButtonType.reset) handleReset();

    if (type === ButtonType.button) onClick?.(e);
  };

  return (
    <Button {...baseButtonProps} disabled={buttonIsDisabled} onClick={handleClick}>
      {type === ButtonType.submit && submitting ? <Loader /> : children}
    </Button>
  );
}
Example #9
Source File: StatusSelect.tsx    From frontend with MIT License 6 votes vote down vote up
export default function StatusSelect({ name = 'status' }) {
  const { t } = useTranslation('irregularity')
  const values = Object.values(IrregularityStatus)

  const [field, meta] = useField(name)
  const { setFieldValue } = useFormikContext()

  const helperText = meta.touched ? translateError(meta.error as TranslatableField, t) : ''

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setFieldValue(name, event.target.value)
  }
  return (
    <TextField
      {...field}
      select
      variant="outlined"
      fullWidth
      onChange={handleChange}
      label={t('admin.fields.status')}
      error={Boolean(meta.error) && Boolean(meta.touched)}
      helperText={helperText}>
      {values.map((value, index) => (
        <MenuItem key={index} value={value}>
          {t('admin.fields.status-type.' + value.toLowerCase())}
        </MenuItem>
      ))}
    </TextField>
  )
}
Example #10
Source File: TableUploaderStep.tsx    From querybook with Apache License 2.0 6 votes vote down vote up
TableUploaderStepFooter: React.FC<{
    step: number;
    maxStep: number;
    setStep: (step: number) => void;
}> = ({ step, maxStep, setStep }) => {
    const { submitForm } = useFormikContext<ITableUploadFormikForm>();

    return (
        <div className="TableUploaderStep-footer horizontal-space-between pb12 ph8">
            <div>
                {step >= 1 && (
                    <Button title="Previous" onClick={() => setStep(-1)} />
                )}
            </div>
            <div>
                {step < TableUploaderStepsDOM.length - 1 ? (
                    <Button
                        title="Next"
                        onClick={() => setStep(1)}
                        disabled={step >= maxStep}
                    />
                ) : (
                    <AsyncButton
                        color="confirm"
                        icon="Upload"
                        title="Create Table"
                        onClick={submitForm}
                    />
                )}
            </div>
        </div>
    );
}
Example #11
Source File: OCSDisksManualFormattingHint.tsx    From assisted-ui-lib with Apache License 2.0 6 votes vote down vote up
OCSDisksManualFormattingHint = () => {
  const { values } = useFormikContext<HostDiscoveryValues>();
  return values.useExtraDisksForLocalStorage ? (
    <Text component="p">
      <Popover bodyContent={<Hint />} minWidth="30rem">
        <Button variant={ButtonVariant.link} isInline>
          <ExclamationTriangleIcon className="status-icon" color={warningColor.value} size="sm" />
          &nbsp;Format all non-installation disks
        </Button>
      </Popover>
    </Text>
  ) : null;
}
Example #12
Source File: PluralDisplayNameField.tsx    From amplication with Apache License 2.0 6 votes vote down vote up
PluralDisplayNameField = (props: TextFieldProps) => {
  const formik = useFormikContext<{ displayName: string }>();
  const previousNameValue = useRef<string>();

  useEffect(() => {
    const nextDisplayNameValue = formik.values.displayName;
    if (previousNameValue.current !== nextDisplayNameValue) {
      const pluralDisplayName = generatePluralDisplayName(nextDisplayNameValue);
      formik.setFieldValue(props.name, pluralDisplayName);
    }
    previousNameValue.current = nextDisplayNameValue;
  }, [formik, props.name]);

  // @ts-ignore
  return <TextField {...props} />;
}
Example #13
Source File: StaticIpForm.tsx    From assisted-ui-lib with Apache License 2.0 6 votes vote down vote up
AutosaveWithParentUpdate = <StaticIpFormValues extends object>({
  onFormStateChange,
  getEmptyValues,
}: {
  onFormStateChange: StaticIpFormProps<StaticIpFormValues>['onFormStateChange'];
  getEmptyValues: StaticIpFormProps<StaticIpFormValues>['getEmptyValues'];
}) => {
  // eslint-disable-next-line react-hooks/exhaustive-deps
  const emptyValues = React.useMemo(() => getEmptyValues(), []);
  const { isSubmitting, isValid, touched, errors, values } = useFormikContext<StaticIpFormValues>();
  const isEmpty = React.useMemo<boolean>(() => {
    return isEqual(values, emptyValues);
  }, [values, emptyValues]);
  const isAutoSaveRunning = useFormikAutoSave();
  React.useEffect(() => {
    onFormStateChange({ isSubmitting, isAutoSaveRunning, isValid, touched, errors, isEmpty });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isSubmitting, isValid, isAutoSaveRunning, touched, errors]);
  return null;
}
Example #14
Source File: RelatedFieldDialog.tsx    From amplication with Apache License 2.0 6 votes vote down vote up
RelatedFieldDisplayNameField = ({
  disabled,
}: {
  disabled: boolean;
}): React.ReactElement => {
  const formik = useFormikContext<Values>();

  const handleLabelChange = useCallback(
    (event) => {
      const newValue = camelCase(event.target.value);
      formik.values.relatedFieldName = newValue;
    },
    [formik.values]
  );

  return (
    <DisplayNameField
      name="relatedFieldDisplayName"
      label="Display Name"
      required
      disabled={disabled}
      onChange={handleLabelChange}
    />
  );
}
Example #15
Source File: ProxyFields.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
ProxyInputFields = () => {
  const { setFieldValue, values } = useFormikContext<ProxyFieldsType>();
  const onNoProxyBlur = () => {
    if (values.noProxy) {
      setFieldValue('noProxy', trimCommaSeparatedList(values.noProxy));
    }
  };
  return (
    <Grid hasGutter>
      <InputField
        label={
          <>
            {'HTTP proxy URL'}
            <PopoverIcon
              variant={'plain'}
              bodyContent={
                'The HTTP proxy URL that agents should use to access the discovery service.'
              }
            />
          </>
        }
        name="httpProxy"
        placeholder="http://<user>:<password>@<ipaddr>:<port>"
        helperText={
          <div>
            URL must start with <b>http</b>.
          </div>
        }
      />
      <InputField
        label={
          <>
            {'HTTPS proxy URL'}
            <PopoverIcon
              variant={'plain'}
              bodyContent={
                "Specify the HTTPS proxy that agents should use to access the discovery service. If you don't provide a value, your HTTP proxy URL will be used by default for both HTTP and HTTPS connections."
              }
            />
          </>
        }
        name="httpsProxy"
        placeholder="http://<user>:<password>@<ipaddr>:<port>"
        helperText={
          <div>
            URL must start with <b>http</b> (https schemes are not currently supported).
          </div>
        }
      />
      <InputField
        label={
          <>
            {'No proxy domains'}
            <PopoverIcon
              variant={'plain'}
              bodyContent={
                'Exclude destination domain names, IP addresses, or other network CIDRs from proxying by adding them to this comma-separated list.'
              }
            />
          </>
        }
        name="noProxy"
        placeholder="one.domain.com,second.domain.com"
        helperText={
          <div>
            Use a comma to separate each listed domain. Preface a domain with <b>.</b> to include
            its subdomains. Use <b>*</b> to bypass the proxy for all destinations.
          </div>
        }
        onBlur={onNoProxyBlur}
      />
    </Grid>
  );
}
Example #16
Source File: IdentificationNumberInput.tsx    From mayoor with MIT License 5 votes vote down vote up
IdentificationNumberInput: React.FC = () => {
	const { t } = useTranslation();

	const formikContext = useFormikContext<UserFormValues>();
	const [{ onChange, value }, { error }, { setError }] = useField('identificationNumber');
	const [isLoadingHelperInfo, setIsLoadingHelperInfo] = useState(false);

	const helperInfoQuery = useQuery<GetCustomerHelperInfo, GetCustomerHelperInfoVariables>(
		GET_CUSTOMER_HELPER_INFO,
		{
			skip: true,
			onError: console.error,
		},
	);

	const queryForHelperInfo = async () => {
		setIsLoadingHelperInfo(true);
		if (!value) {
			return setError(t('Identification number required for the search'));
		}
		try {
			const {
				data: { getCustomerHelperInfo },
			} = await helperInfoQuery.refetch({
				partialIdentificationNumber: value,
			});

			const {
				taxIdentificationNumber,
				name,
				city,
				street,
				postNumber,
			} = getCustomerHelperInfo;

			formikContext.setValues({
				...formikContext.values,
				taxIdentificationNumber:
					taxIdentificationNumber || formikContext.values.taxIdentificationNumber,
				name: name || formikContext.values.name,
			});
			formikContext.setFieldValue('addresses.0', { city, street, postNumber });
		} catch (err) {
			if (err instanceof ApolloError) {
				if (err.graphQLErrors[0].extensions?.code === 'INFO_NOT_FOUND') {
					setError(t('company_not_found_in_ares'));
				}
			}
		}
		setIsLoadingHelperInfo(false);
	};

	return (
		<StyledFormItem validateStatus={error ? 'error' : ''} help={error}>
			<Input.Search
				name={'identificationNumber'}
				prefix={<NumberOutlined />}
				placeholder={t('Identification number')}
				onSearch={queryForHelperInfo}
				onChange={onChange}
				value={value || ''}
				enterButton
				loading={isLoadingHelperInfo}
			/>
		</StyledFormItem>
	);
}
Example #17
Source File: SecurityFields.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
SecurityFields: React.FC<SecurityFieldsFieldsProps> = ({ clusterSshKey, imageSshKey }) => {
  //shareSshKey shouldn't response to changes. imageSshKey stays the same, there's a loading state while it's requested
  //clusterSshKey updating causes the textarea to disappear when the user clears it to edit it
  const defaultShareSshKey = !!imageSshKey && (clusterSshKey === imageSshKey || !clusterSshKey);
  const [shareSshKey, setShareSshKey] = React.useState(defaultShareSshKey);
  const { values, setFieldValue, errors, touched } =
    useFormikContext<Pick<NetworkConfigurationValues, 'sshPublicKey'>>();

  const errorMsg = errors.sshPublicKey;

  const handleSshKeyBlur = () => {
    if (values.sshPublicKey) {
      setFieldValue('sshPublicKey', trimSshPublicKey(values.sshPublicKey));
    }
  };

  React.useEffect(() => {
    if (shareSshKey) {
      setFieldValue('sshPublicKey', imageSshKey);
    }
  }, [shareSshKey, imageSshKey, setFieldValue]);

  const fieldId = getFieldId('shareDiscoverySshKey', 'checkbox');
  return (
    <>
      <FormGroup
        fieldId={fieldId}
        label={label}
        helperTextInvalid={errorMsg}
        validated={touched && errorMsg ? 'error' : 'default'}
      >
        <RenderIf condition={Boolean(imageSshKey)}>
          <Checkbox
            name="shareDiscoverySshKey"
            id={fieldId}
            label="Use the same host discovery SSH key"
            aria-describedby={`${fieldId}-helper`}
            isChecked={shareSshKey}
            onChange={setShareSshKey}
          />
        </RenderIf>
        <RenderIf condition={!shareSshKey}>
          <TextAreaField
            name="sshPublicKey"
            helperText={<SshPublicKeyHelperText />}
            onBlur={handleSshKeyBlur}
          />
        </RenderIf>
      </FormGroup>
    </>
  );
}
Example #18
Source File: LoginForm.tsx    From frontend with MIT License 5 votes vote down vote up
function LoginForm() {
  const { t } = useTranslation('one-time-donation')
  const formik = useFormikContext<OneTimeDonation>()
  return (
    <Collapse in={!formik.values.anonymousDonation} timeout="auto">
      <Grid sx={{ marginBottom: theme.spacing(4) }} container rowSpacing={3}>
        <Grid item xs={12}>
          <Typography fontWeight={'bold'} fontSize={16} color="#343434">
            {t('second-step.login')}
          </Typography>
        </Grid>
        <Grid item xs={12}>
          <FormTextField name="personsEmail" type="text" label="Email" fullWidth size="medium" />
        </Grid>
        <Grid item xs={12}>
          <FormTextField
            name="personsPassword"
            type="password"
            label={t('second-step.password')}
            fullWidth
            size="medium"
          />
        </Grid>
        <Box display={'flex'} justifyContent="space-between" width="100%" alignItems="center">
          <FormControlLabel
            control={<Checkbox />}
            label={t('second-step.checkbox-label') as string}
          />
          <Box sx={{ opacity: 0.85 }}>
            <Typography display="inline" color="GrayText">
              Don&apos;t have an account?
            </Typography>{' '}
            <Link color={theme.palette.primary.dark} href="#">
              Sign up
            </Link>
          </Box>
        </Box>
        <Button color="info" variant="contained" fullWidth sx={{ marginTop: theme.spacing(3) }}>
          {t('second-step.btn-login')}
        </Button>
        <Button
          size="large"
          color="primary"
          variant="outlined"
          fullWidth
          sx={{ marginTop: theme.spacing(3) }}>
          <Box display="inline-flex" alignItems="center" marginRight={theme.spacing(2)}>
            <Google />
          </Box>
          Log in with Google
        </Button>
      </Grid>
    </Collapse>
  )
}
Example #19
Source File: SingleNodeCheckbox.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
SingleNodeCheckbox: React.FC<SingleNodeCheckboxProps> = ({
  versions,
  validate,
  idPostfix,
  ...props
}) => {
  const {
    values: { openshiftVersion },
  } = useFormikContext<ClusterCreateParams>();
  const isSingleNodeOpenshiftEnabled = useFeature('ASSISTED_INSTALLER_SNO_FEATURE');
  const [field, meta, helpers] = useField<'None' | 'Full'>({ name: props.name, validate });
  const featureSupportLevelContext = useFeatureSupportLevel();
  const prevVersionRef = React.useRef(openshiftVersion);
  const fieldId = getFieldId(props.name, 'input', idPostfix);

  const { value } = meta;
  const { setValue } = helpers;
  const isSupportedVersionAvailable = !!versions.find((version) =>
    featureSupportLevelContext.isFeatureSupported(version.value, 'SNO'),
  );
  const onChanged = React.useCallback(
    (checked: boolean) => setValue(checked ? 'None' : 'Full'),
    [setValue],
  );

  const disabledReason = featureSupportLevelContext.getFeatureDisabledReason(
    openshiftVersion,
    'SNO',
  );

  React.useEffect(() => {
    if (
      prevVersionRef.current !== openshiftVersion &&
      !featureSupportLevelContext.isFeatureSupported(openshiftVersion, 'SNO')
    ) {
      //invoke updating SNO value only if the version changed to not be in danger of touching existing clusters
      onChanged(false);
    }
    prevVersionRef.current = openshiftVersion;
  }, [openshiftVersion, onChanged, featureSupportLevelContext]);

  if (isSingleNodeOpenshiftEnabled && isSupportedVersionAvailable) {
    return (
      <FormGroup isInline fieldId={fieldId}>
        <Tooltip hidden={!disabledReason} content={disabledReason}>
          <Checkbox
            {...field}
            {...props}
            id={fieldId}
            label={
              <>
                Install single node OpenShift (SNO)&nbsp;
                <FeatureSupportLevelBadge
                  featureId="SNO"
                  openshiftVersion={openshiftVersion}
                ></FeatureSupportLevelBadge>
              </>
            }
            aria-describedby={`${fieldId}-helper`}
            description={
              <HelperText fieldId={fieldId}>
                SNO enables you to install OpenShift using only one host.
              </HelperText>
            }
            isChecked={value === 'None'}
            onChange={onChanged}
            className="with-tooltip"
          />
        </Tooltip>
      </FormGroup>
    );
  }
  return null;
}
Example #20
Source File: CampaignSelect.tsx    From frontend with MIT License 5 votes vote down vote up
export default function CampaignSelect({ label, name, campaigns, ...textFieldProps }: Props) {
  const { t } = useTranslation('transfer')

  const [field, meta] = useField(name)
  const { setFieldValue } = useFormikContext()

  const helperText = meta.touched ? translateError(meta.error as TranslatableField, t) : ''

  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setFieldValue(name, event.target.value)
  }

  return (
    <TextField
      {...textFieldProps}
      {...field}
      select
      variant="outlined"
      fullWidth
      onChange={handleChange}
      label={t(label)}
      error={Boolean(meta.error) && Boolean(meta.touched)}
      helperText={helperText}>
      {[{ id: '', title: '' }, ...(campaigns || [])].map((p) => {
        return (
          <MenuItem key={p.id} value={p.id}>
            {p.title}
          </MenuItem>
        )
      })}
    </TextField>
  )
}
Example #21
Source File: EnvironmentSelection.tsx    From querybook with Apache License 2.0 5 votes vote down vote up
EnvironmentSelection = ({
    options = [],
    name,
    label,
}: {
    label: string;
    options: OptionsType[];
    name: string;
}) => {
    const [field, , helper] = useField({ name });
    const { values, setFieldValue } = useFormikContext<{
        setFieldValue: () => void;
        url_regex: string;
    }>();

    const value = useMemo(
        () =>
            options.find((o) => {
                const regexPattern = new RegExp(values.url_regex);
                return !!`/${o.value}/`.match(regexPattern);
            }),
        [options, values.url_regex]
    );

    return (
        <SimpleField
            stacked
            type="select"
            {...field}
            label={label}
            value={value?.key}
            onChange={(selectedValue) => {
                helper.setValue(selectedValue);
                setFieldValue('url_regex', `/${selectedValue}/`);
            }}
            options={[
                {
                    value: '',
                    key: '',
                    hidden: true,
                },
                ...options,
            ]}
            help="You can specify the environment for this announcement."
        />
    );
}
Example #22
Source File: NetworkConfigurationForm.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
NetworkConfigurationForm: React.FC<{
  cluster: Cluster;
  hostSubnets: HostSubnets;
  defaultNetworkSettings: Pick<NetworkConfigurationValues, 'serviceNetworks' | 'clusterNetworks'>;
  infraEnv?: InfraEnv;
}> = ({ cluster, hostSubnets, defaultNetworkSettings, infraEnv }) => {
  const { alerts } = useAlerts();
  const clusterWizardContext = useClusterWizardContext();
  const { errors, touched, isSubmitting, isValid } = useFormikContext<NetworkConfigurationValues>();
  const isAutoSaveRunning = useFormikAutoSave();
  const errorFields = getFormikErrorFields(errors, touched);

  const footer = (
    <ClusterWizardFooter
      cluster={cluster}
      errorFields={errorFields}
      isSubmitting={isSubmitting}
      isNextDisabled={
        isSubmitting ||
        isAutoSaveRunning ||
        !canNextNetwork({ cluster }) ||
        !!alerts.length ||
        !isValid
      }
      onNext={() => clusterWizardContext.moveNext()}
      onBack={() => clusterWizardContext.moveBack()}
    />
  );
  return (
    <ClusterWizardStep navigation={<ClusterWizardNavigation cluster={cluster} />} footer={footer}>
      <Form>
        <Grid hasGutter>
          <GridItem>
            <ClusterWizardStepHeader
              extraItems={<ClusterWizardHeaderExtraActions cluster={cluster} />}
            >
              Networking
            </ClusterWizardStepHeader>
          </GridItem>
          <GridItem span={12} lg={10} xl={9} xl2={7}>
            <NetworkConfigurationFormFields
              cluster={cluster}
              hostSubnets={hostSubnets}
              defaultNetworkSettings={defaultNetworkSettings}
              infraEnv={infraEnv}
            />
          </GridItem>
          <GridItem>
            <TextContent>
              <Text component="h2">Host inventory</Text>
            </TextContent>
            <NetworkConfigurationTable cluster={cluster} />
          </GridItem>
        </Grid>
      </Form>
    </ClusterWizardStep>
  );
}
Example #23
Source File: index.tsx    From formik-chakra-ui with MIT License 5 votes vote down vote up
NumberInputControl: FC<NumberInputControlProps> = React.forwardRef(
  (
    props: NumberInputControlProps,
    ref: React.ForwardedRef<HTMLInputElement>
  ) => {
    const {
      name,
      label,
      showStepper = true,
      children,
      numberInputProps,
      ...rest
    } = props;
    const [field, { error, touched }] = useField(name);
    const { setFieldValue } = useFormikContext();

    const $setFieldValue = (name: string) => (value: any) =>
      setFieldValue(name, value);

    return (
      <FormControl name={name} label={label} {...rest}>
        <NumberInput
          {...field}
          id={name}
          onChange={$setFieldValue(name)}
          isInvalid={!!error && touched}
          {...numberInputProps}
        >
          <NumberInputField name={name} ref={ref} />
          {showStepper && (
            <NumberInputStepper>
              <NumberIncrementStepper />
              <NumberDecrementStepper />
            </NumberInputStepper>
          )}
          {children}
        </NumberInput>
      </FormControl>
    );
  }
)
Example #24
Source File: useFormButton.tsx    From SQForm with MIT License 5 votes vote down vote up
export function useFormButton<Values>({
  isDisabled = false,
  shouldRequireFieldUpdates = false,
  onClick,
  buttonType,
}: UseFormButtonProps): UseFormButtonReturnType<Values> {
  const {values, initialValues, isValid, dirty, ...rest} =
    useFormikContext<Values>();

  const isButtonDisabled = React.useMemo(() => {
    if (isDisabled) {
      return true;
    }

    if (buttonType === BUTTON_TYPES.SUBMIT) {
      if (!isValid) {
        return true;
      }

      if (shouldRequireFieldUpdates && !dirty) {
        return true;
      }
    }

    if (buttonType === BUTTON_TYPES.RESET) {
      if (!dirty) {
        return true;
      }
    }

    return false;
  }, [buttonType, dirty, isDisabled, isValid, shouldRequireFieldUpdates]);

  const handleClick = useDebouncedCallback<
    React.MouseEventHandler<HTMLButtonElement>
  >((event) => onClick && onClick(event), 500, {
    leading: true,
    trailing: false,
  });

  return {
    isButtonDisabled,
    values,
    initialValues,
    isValid,
    handleClick,
    dirty,
    ...rest,
  };
}
Example #25
Source File: BMCForm.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
MacMapping = () => {
  const [field, { touched, error }] = useField<{ macAddress: string; name: string }[]>({
    name: 'macMapping',
  });
  const { errors } = useFormikContext();

  const fieldId = getFieldId('macMapping', 'input');
  const isValid = !(touched && error);
  return (
    <FormGroup
      fieldId={fieldId}
      label="Mac to interface name mapping"
      validated={isValid ? 'default' : 'error'}
    >
      <FieldArray
        name="macMapping"
        render={({ push, remove }) => (
          <Grid hasGutter>
            <GridItem span={5}>
              <Text component={TextVariants.small}>MAC address</Text>
            </GridItem>
            <GridItem span={5}>
              <Text component={TextVariants.small}>NIC</Text>
            </GridItem>
            {field.value.map((mac, index) => {
              const macField = `macMapping[${index}].macAddress`;
              const nameField = `macMapping[${index}].name`;
              return (
                <React.Fragment key={index}>
                  <GridItem span={5}>
                    <InputField name={macField} inputError={errors[macField]?.[0]} />
                  </GridItem>
                  <GridItem span={5}>
                    <InputField name={nameField} inputError={errors[nameField]?.[0]} />
                  </GridItem>
                  {index !== 0 && (
                    <GridItem span={2}>
                      <MinusCircleIcon onClick={() => remove(index)} />
                    </GridItem>
                  )}
                </React.Fragment>
              );
            })}
            <GridItem span={6}>
              <Button
                icon={<PlusCircleIcon />}
                onClick={() => push({ macAddress: '', name: '' })}
                variant="link"
                isInline
              >
                Add more
              </Button>
            </GridItem>
          </Grid>
        )}
      />
    </FormGroup>
  );
}
Example #26
Source File: SQFormTextarea.tsx    From SQForm with MIT License 5 votes vote down vote up
function SQFormTextarea({
  name,
  label,
  isDisabled = false,
  placeholder = '',
  size = 'auto',
  onBlur,
  onChange,
  rows = 3,
  rowsMax = 3,
  maxCharacters,
  inputProps = {},
  muiFieldProps = {},
}: SQFormTextareaProps): JSX.Element {
  const {values}: FormikProps<FormValues> = useFormikContext();
  const {
    fieldState: {isFieldError, isFieldRequired},
    fieldHelpers: {
      handleBlur,
      handleChange: handleChangeHelper,
      HelperTextComponent,
    },
  } = useForm<string, React.ChangeEvent<HTMLInputElement>>({
    name,
    onBlur,
    onChange,
  });

  const [valueLength, setValueLength] = React.useState<number>(
    values[name]?.length || 0
  );

  const handleChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    setValueLength(event.target.value.length);
    handleChangeHelper(event);
  };

  const maxCharactersValue = inputProps.maxLength || maxCharacters;
  const characterCounter =
    maxCharactersValue && `: ${valueLength}/${maxCharactersValue}`;

  const labelText = (
    <span>
      {label} {characterCounter}
    </span>
  );

  return (
    <Grid item sm={size}>
      <TextField
        id={toKebabCase(name)}
        color="primary"
        disabled={isDisabled}
        error={isFieldError}
        fullWidth={true}
        InputLabelProps={{shrink: true}}
        FormHelperTextProps={{error: isFieldError}}
        name={name}
        label={labelText}
        multiline={true}
        helperText={!isDisabled && HelperTextComponent}
        placeholder={placeholder}
        onChange={handleChange}
        onBlur={handleBlur}
        required={isFieldRequired}
        minRows={rows}
        maxRows={rowsMax}
        variant="outlined"
        value={values[name]}
        inputProps={{
          maxLength: maxCharacters,
          ...inputProps,
        }}
        {...muiFieldProps}
      />
    </Grid>
  );
}
Example #27
Source File: TangServers.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
TangServers: React.FC<{ isDisabled?: boolean }> = ({ isDisabled = false }) => {
  const { values } = useFormikContext<ClusterDetailsValues>();

  return (
    <FieldArray name="diskEncryptionTangServers">
      {({ remove, push }) => (
        <Stack hasGutter>
          {values.diskEncryptionTangServers.length > 0 &&
            values.diskEncryptionTangServers.map((tang, index) => (
              <StackItem key={index}>
                <RemovableField
                  hideRemoveButton={index === 0 || isDisabled}
                  onRemove={() => remove(index)}
                >
                  <div>
                    <InputField
                      type={TextInputTypes.url}
                      name={`diskEncryptionTangServers.${index}.url`}
                      placeholder="http//tang.srv"
                      label="Server URL"
                      isRequired
                      isDisabled={isDisabled}
                    />
                    &thinsp;
                    <InputField
                      type={TextInputTypes.text}
                      name={`diskEncryptionTangServers.${index}.thumbprint`}
                      label="Server Thumbprint"
                      isRequired
                      isDisabled={isDisabled}
                    />
                  </div>
                </RemovableField>{' '}
              </StackItem>
            ))}

          {!isDisabled && (
            <StackItem>
              <AddButton onAdd={() => push({ url: '', thumbprint: '' })} isInline>
                Add another Tang server
              </AddButton>
            </StackItem>
          )}
        </Stack>
      )}
    </FieldArray>
  );
}
Example #28
Source File: SQFormMaskedTextField.tsx    From SQForm with MIT License 5 votes vote down vote up
function SQFormMaskedTextField({
  mask,
  name,
  label,
  isDisabled = false,
  placeholder,
  size = 'auto',
  onBlur,
  onChange,
  startAdornment,
  endAdornment,
  type = 'text',
  InputProps,
  inputProps = {},
  muiFieldProps = {},
  stripNonNumeric = false,
}: SQFormMaskedTextFieldProps): React.ReactElement {
  const {setFieldValue} = useFormikContext();

  const handleChangeStripNonNumeric = (
    event: React.ChangeEvent<HTMLInputElement>
  ) => {
    onChange && onChange(event);
    setFieldValue(name, event.target.value.replace(/[^\d]/g, ''));
  };
  return (
    <SQFormTextField
      name={name}
      label={label}
      isDisabled={isDisabled}
      placeholder={placeholder}
      size={size}
      onBlur={onBlur}
      onChange={stripNonNumeric ? handleChangeStripNonNumeric : onChange}
      startAdornment={startAdornment}
      endAdornment={endAdornment}
      type={type}
      InputProps={{
        ...InputProps,
        inputComponent: TextFieldMask,
      }}
      inputProps={{
        ...inputProps,
        mask,
      }}
      muiFieldProps={muiFieldProps}
    />
  );
}
Example #29
Source File: ClusterDeploymentHostsSelection.tsx    From assisted-ui-lib with Apache License 2.0 5 votes vote down vote up
ClusterDeploymentHostsSelection: React.FC<ClusterDeploymentHostsSelectionProps> = ({
  agentClusterInstall,
  clusterDeployment,
  agents,
  aiConfigMap,
  onEditRole,
  onAutoSelectChange,
  onHostSelect,
}) => {
  const { values } = useFormikContext<ClusterDeploymentHostsSelectionValues>();
  const { autoSelectHosts } = values;
  const isSNOCluster = getIsSNOCluster(agentClusterInstall);

  const cdName = clusterDeployment?.metadata?.name;
  const cdNamespace = clusterDeployment?.metadata?.namespace;

  const availableAgents = React.useMemo(
    () =>
      getAgentsForSelection(agents).filter(
        (agent) =>
          (agent.spec.clusterDeploymentName?.name === cdName &&
            agent.spec.clusterDeploymentName?.namespace === cdNamespace) ||
          (!agent.spec.clusterDeploymentName?.name && !agent.spec.clusterDeploymentName?.namespace),
      ),
    [agents, cdNamespace, cdName],
  );

  return (
    <Grid hasGutter>
      <GridItem>
        <TextContent>
          {isSNOCluster
            ? 'Exactly 1 host is required, capable of functioning both as control plane and worker node.'
            : 'At least 3 hosts are required, capable of functioning as control plane nodes.'}
        </TextContent>
      </GridItem>
      {aiConfigMap && (
        <GridItem>
          <MinimalHWRequirements aiConfigMap={aiConfigMap} isSNOCluster={isSNOCluster} />
        </GridItem>
      )}

      <GridItem>
        {availableAgents.length ? (
          <Form>
            <SwitchField
              name="autoSelectHosts"
              label="Auto-select hosts"
              onChange={onAutoSelectChange}
            />

            {autoSelectHosts && (
              <ClusterDeploymentHostsSelectionBasic
                availableAgents={availableAgents}
                isSNOCluster={isSNOCluster}
              />
            )}

            {!autoSelectHosts && (
              <ClusterDeploymentHostsSelectionAdvanced<ClusterDeploymentHostsSelectionValues>
                availableAgents={availableAgents}
                onEditRole={onEditRole}
                onHostSelect={onHostSelect}
              />
            )}
          </Form>
        ) : (
          <NoAgentsAlert />
        )}
      </GridItem>
    </Grid>
  );
}