feat(filters): regex validation for supported fields (#773)

* initial commit

* minor visual improvements

* lock validation to golang flavor

* made a new field called regexfield

reverted old textfield to be up2date with develop

* added Formik Validation

* removed yup as its not needed

* improvements

* refactor: simplify and make more generic

---------

Co-authored-by: ze0s <ze0s@riseup.net>
This commit is contained in:
soup 2023-03-30 23:41:03 +02:00 committed by GitHub
parent 59f41be3ef
commit 8a0c6e8180
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 18 deletions

View file

@ -1,21 +1,21 @@
import { Field, FieldProps } from "formik";
import { classNames } from "../../utils";
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
import { useToggle } from "../../hooks/hooks";
import { CustomTooltip } from "../tooltips/CustomTooltip";
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
interface TextFieldProps {
name: string;
defaultValue?: string;
label?: string;
placeholder?: string;
columns?: COL_WIDTHS;
autoComplete?: string;
hidden?: boolean;
disabled?: boolean;
tooltip?: JSX.Element;
name: string;
defaultValue?: string;
label?: string;
placeholder?: string;
columns?: COL_WIDTHS;
autoComplete?: string;
hidden?: boolean;
disabled?: boolean;
tooltip?: JSX.Element;
}
export const TextField = ({
@ -75,6 +75,113 @@ export const TextField = ({
</div>
);
interface RegexFieldProps {
name: string;
defaultValue?: string;
label?: string;
placeholder?: string;
columns?: COL_WIDTHS;
autoComplete?: string;
useRegex?: boolean;
hidden?: boolean;
disabled?: boolean;
tooltip?: JSX.Element;
}
export const RegexField = ({
name,
defaultValue,
label,
placeholder,
columns,
autoComplete,
useRegex,
hidden,
tooltip,
disabled
}: RegexFieldProps) => {
const golangRegex = /^((\\\*|\\\?|\\[^\s\\])+|\(\?i\))(\|((\\\*|\\\?|\\[^\s\\])+|\(\?i\)))*$/;
const validRegex = (pattern: string) => {
try {
new RegExp(golangRegex.source + pattern);
return true;
} catch (e) {
return false;
}
};
const validateRegexp = (val: string) => {
let error = "";
if (!validRegex(val)) {
error = "Invalid regex";
}
return error;
};
return (
<div
className={classNames(
hidden ? "hidden" : "",
columns ? `col-span-${columns}` : "col-span-12"
)}
>
{label && (
<label
htmlFor={name}
className="flex float-left mb-2 text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"
>
<div className="flex">
{label}
{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}
</div>
</label>
)}
<Field
name={name}
validate={useRegex && validateRegexp}
>
{({ field, meta }: FieldProps) => (
<div className="relative">
<input
{...field}
name={name}
type="text"
defaultValue={defaultValue}
autoComplete={autoComplete}
className={classNames(
meta.touched && meta.error
? "focus:ring-red-500 focus:border-red-500 border-red-500"
: "focus:ring-blue-500 dark:focus:ring-blue-500 focus:border-blue-500 dark:focus:border-blue-500 border-gray-300 dark:border-gray-700",
disabled
? "bg-gray-100 dark:bg-gray-700 cursor-not-allowed"
: "dark:bg-gray-800",
"mt-2 block w-full dark:text-gray-100 rounded-md"
)}
disabled={disabled}
placeholder={placeholder}
/>
{useRegex && (
<div className="relative">
<div className="flex float-right items-center">
{meta.touched && !meta.error ? (
<CheckCircleIcon className="dark:bg-gray-800 bg-white h-8 w-8 mb-2.5 pl-1 text-green-500 right-2 absolute transform -translate-y-1/2" aria-hidden="true" style={{ overflow: "hidden" }} />
) : (
<XCircleIcon className="dark:bg-gray-800 bg-white h-8 w-8 mb-2.5 pl-1 text-red-500 right-2 absolute transform -translate-y-1/2" aria-hidden="true" style={{ overflow: "hidden" }} />
)}
</div>
</div>
)}
</div>
)}
</Field>
</div>
);
};
interface TextAreaProps {
name: string;
defaultValue?: string;