feat(filters): improve RegexField validation (#803)

* make sure fields are validated on page load

* make red border only show if useRegex enabled

* ensure tooltips have higher z-index in RegexField

removed z-index in customtooltip.tsx as its causing issues with tooltips in other components

* improved regex validation

return false for cases that are unsupported by Go

* improved check for unsupported conditionals
thanks nuxen
This commit is contained in:
soup 2023-04-10 14:36:13 +02:00 committed by GitHub
parent 169863dded
commit 195b2929e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 8 deletions

View file

@ -1,8 +1,9 @@
import { Field, FieldProps } from "formik";
import { Field, FieldProps, useFormikContext } from "formik";
import { classNames } from "../../utils";
import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
import { useToggle } from "../../hooks/hooks";
import { CustomTooltip } from "../tooltips/CustomTooltip";
import { useEffect } from "react";
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
@ -100,17 +101,53 @@ export const RegexField = ({
tooltip,
disabled
}: RegexFieldProps) => {
const golangRegex = /^((\\\*|\\\?|\\[^\s\\])+|\(\?i\))(\|((\\\*|\\\?|\\[^\s\\])+|\(\?i\)))*$/;
const validRegex = (pattern: string) => {
// Check for unsupported lookahead and lookbehind assertions
if (/\(\?<=|\(\?<!|\(\?=|\(\?!/.test(pattern)) {
return false;
}
// Check for unsupported atomic groups
if (/\(\?>/.test(pattern)) {
return false;
}
// Check for unsupported recursive patterns
if (/\(\?(R|0)\)/.test(pattern)) {
return false;
}
// Check for unsupported possessive quantifiers
if (/[*+?]{1}\+|\{[0-9]+,[0-9]*\}\+/.test(pattern)) {
return false;
}
// Check for unsupported control verbs
if (/\\g</.test(pattern)) {
return false;
}
// Check for unsupported conditionals
if (/\(\?\((\?[=!][^)]*)\)[^)]*\|?[^)]*\)/.test(pattern)) {
return false;
}
// Check for unsupported backreferences
if (/\\k</.test(pattern)) {
return false;
}
// Check if the pattern is a valid regex
try {
new RegExp(golangRegex.source + pattern);
new RegExp(pattern);
return true;
} catch (e) {
return false;
}
};
const validateRegexp = (val: string) => {
let error = "";
@ -121,6 +158,13 @@ export const RegexField = ({
return error;
};
const { validateForm } = useFormikContext();
useEffect(() => {
if (useRegex) {
validateForm();
}
}, [useRegex]);
return (
<div
className={classNames(
@ -135,7 +179,7 @@ export const RegexField = ({
>
<div className="flex">
{label}
{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}
<span className="z-10">{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}</span>
</div>
</label>
)}
@ -152,7 +196,7 @@ export const RegexField = ({
defaultValue={defaultValue}
autoComplete={autoComplete}
className={classNames(
meta.touched && meta.error
useRegex && 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
@ -166,7 +210,7 @@ export const RegexField = ({
{useRegex && (
<div className="relative">
<div className="flex float-right items-center">
{meta.touched && !meta.error ? (
{!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" }} />

View file

@ -18,7 +18,7 @@ export const CustomTooltip = ({
const id = `${anchorId}-tooltip`;
return (
<div className="flex items-center">
<svg id={id} className="z-10 ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
<svg id={id} className="ml-1 w-4 h-4 text-gray-500 dark:text-gray-400 fill-current" viewBox="0 0 72 72"><path d="M32 2C15.432 2 2 15.432 2 32s13.432 30 30 30s30-13.432 30-30S48.568 2 32 2m5 49.75H27v-24h10v24m-5-29.5a5 5 0 1 1 0-10a5 5 0 0 1 0 10"/></svg>
<Tooltip style= {{ maxWidth: "350px", fontSize: "12px", textTransform: "none", fontWeight: "normal", borderRadius: "0.375rem", backgroundColor: "#34343A", color: "#fff", opacity: "1" }} delayShow={100} delayHide={150} place={place} anchorId={id} data-html={true} clickable={clickable}>
{children}
</Tooltip>