| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import { Field, useFormikContext } from "formik";
- import type { ActionMeta, MultiValue } from "react-select";
- import CreatableSelect from "react-select/creatable";
- import { intl } from "src/locale";
- export type SelectOption = {
- label: string;
- value: string;
- color?: string;
- };
- interface Props {
- id?: string;
- maxDomains?: number;
- isWildcardPermitted?: boolean;
- dnsProviderWildcardSupported?: boolean;
- name?: string;
- label?: string;
- }
- export function DomainNamesField({
- name = "domainNames",
- label = "domain-names",
- id = "domainNames",
- maxDomains,
- isWildcardPermitted,
- dnsProviderWildcardSupported,
- }: Props) {
- const { values, setFieldValue } = useFormikContext();
- const getDomainCount = (v: string[] | undefined): number => {
- if (v?.length) {
- return v.length;
- }
- return 0;
- };
- const handleChange = (v: MultiValue<SelectOption>, _actionMeta: ActionMeta<SelectOption>) => {
- const doms = v?.map((i: SelectOption) => {
- return i.value;
- });
- setFieldValue(name, doms);
- };
- const isDomainValid = (d: string): boolean => {
- const dom = d.trim().toLowerCase();
- const v: any = values;
- // Deny if the list of domains is hit
- if (maxDomains && getDomainCount(v?.[name]) >= maxDomains) {
- return false;
- }
- if (dom.length < 3) {
- return false;
- }
- // Prevent wildcards
- if ((!isWildcardPermitted || !dnsProviderWildcardSupported) && dom.indexOf("*") !== -1) {
- return false;
- }
- // Prevent duplicate * in domain
- if ((dom.match(/\*/g) || []).length > 1) {
- return false;
- }
- // Prevent some invalid characters
- if ((dom.match(/(@|,|!|&|\$|#|%|\^|\(|\))/g) || []).length > 0) {
- return false;
- }
- // This will match *.com type domains,
- return dom.match(/\*\.[^.]+$/m) === null;
- };
- const helperTexts: string[] = [];
- if (maxDomains) {
- helperTexts.push(intl.formatMessage({ id: "domain_names.max" }, { count: maxDomains }));
- }
- if (!isWildcardPermitted) {
- helperTexts.push(intl.formatMessage({ id: "wildcards-not-permitted" }));
- } else if (!dnsProviderWildcardSupported) {
- helperTexts.push(intl.formatMessage({ id: "wildcards-not-supported" }));
- }
- return (
- <Field name={name}>
- {({ field, form }: any) => (
- <div className="mb-3">
- <label className="form-label" htmlFor={id}>
- {intl.formatMessage({ id: label })}
- </label>
- <CreatableSelect
- className="react-select-container"
- classNamePrefix="react-select"
- name={field.name}
- id={id}
- closeMenuOnSelect={true}
- isClearable={false}
- isValidNewOption={isDomainValid}
- isMulti
- placeholder="Start typing to add domain..."
- onChange={handleChange}
- value={field.value?.map((d: string) => ({ label: d, value: d }))}
- />
- {form.errors[field.name] ? (
- <div className="invalid-feedback">
- {form.errors[field.name] && form.touched[field.name] ? form.errors[field.name] : null}
- </div>
- ) : helperTexts.length ? (
- helperTexts.map((i) => (
- <div key={i} className="invalid-feedback text-info">
- {i}
- </div>
- ))
- ) : null}
- </div>
- )}
- </Field>
- );
- }
|