DomainNamesField.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import { Field, useFormikContext } from "formik";
  2. import type { ActionMeta, MultiValue } from "react-select";
  3. import CreatableSelect from "react-select/creatable";
  4. import { intl } from "src/locale";
  5. import { validateDomain, validateDomains } from "src/modules/Validations";
  6. export type SelectOption = {
  7. label: string;
  8. value: string;
  9. color?: string;
  10. };
  11. interface Props {
  12. id?: string;
  13. maxDomains?: number;
  14. isWildcardPermitted?: boolean;
  15. dnsProviderWildcardSupported?: boolean;
  16. name?: string;
  17. label?: string;
  18. }
  19. export function DomainNamesField({
  20. name = "domainNames",
  21. label = "domain-names",
  22. id = "domainNames",
  23. maxDomains,
  24. isWildcardPermitted = true,
  25. dnsProviderWildcardSupported = true,
  26. }: Props) {
  27. const { setFieldValue } = useFormikContext();
  28. const handleChange = (v: MultiValue<SelectOption>, _actionMeta: ActionMeta<SelectOption>) => {
  29. const doms = v?.map((i: SelectOption) => {
  30. return i.value;
  31. });
  32. setFieldValue(name, doms);
  33. };
  34. const helperTexts: string[] = [];
  35. if (maxDomains) {
  36. helperTexts.push(intl.formatMessage({ id: "domain-names.max" }, { count: maxDomains }));
  37. }
  38. if (!isWildcardPermitted) {
  39. helperTexts.push(intl.formatMessage({ id: "domain-names.wildcards-not-permitted" }));
  40. } else if (!dnsProviderWildcardSupported) {
  41. helperTexts.push(intl.formatMessage({ id: "domain-names.wildcards-not-supported" }));
  42. }
  43. return (
  44. <Field name={name} validate={validateDomains(isWildcardPermitted && dnsProviderWildcardSupported, maxDomains)}>
  45. {({ field, form }: any) => (
  46. <div className="mb-3">
  47. <label className="form-label" htmlFor={id}>
  48. {intl.formatMessage({ id: label })}
  49. </label>
  50. <CreatableSelect
  51. className="react-select-container"
  52. classNamePrefix="react-select"
  53. name={field.name}
  54. id={id}
  55. closeMenuOnSelect={true}
  56. isClearable={false}
  57. isValidNewOption={validateDomain(isWildcardPermitted && dnsProviderWildcardSupported)}
  58. isMulti
  59. placeholder={intl.formatMessage({ id: "domain-names.placeholder" })}
  60. onChange={handleChange}
  61. value={field.value?.map((d: string) => ({ label: d, value: d }))}
  62. />
  63. {form.errors[field.name] && form.touched[field.name] ? (
  64. <small className="text-danger">{form.errors[field.name]}</small>
  65. ) : helperTexts.length ? (
  66. helperTexts.map((i) => (
  67. <small key={i} className="text-info">
  68. {i}
  69. </small>
  70. ))
  71. ) : null}
  72. </div>
  73. )}
  74. </Field>
  75. );
  76. }