mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 08:49:13 +00:00
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:
parent
169863dded
commit
195b2929e0
2 changed files with 52 additions and 8 deletions
|
@ -1,8 +1,9 @@
|
||||||
import { Field, FieldProps } from "formik";
|
import { Field, FieldProps, useFormikContext } from "formik";
|
||||||
import { classNames } from "../../utils";
|
import { classNames } from "../../utils";
|
||||||
import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";
|
||||||
import { useToggle } from "../../hooks/hooks";
|
import { useToggle } from "../../hooks/hooks";
|
||||||
import { CustomTooltip } from "../tooltips/CustomTooltip";
|
import { CustomTooltip } from "../tooltips/CustomTooltip";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||||
|
|
||||||
|
@ -100,16 +101,52 @@ export const RegexField = ({
|
||||||
tooltip,
|
tooltip,
|
||||||
disabled
|
disabled
|
||||||
}: RegexFieldProps) => {
|
}: RegexFieldProps) => {
|
||||||
const golangRegex = /^((\\\*|\\\?|\\[^\s\\])+|\(\?i\))(\|((\\\*|\\\?|\\[^\s\\])+|\(\?i\)))*$/;
|
|
||||||
|
|
||||||
const validRegex = (pattern: string) => {
|
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 {
|
try {
|
||||||
new RegExp(golangRegex.source + pattern);
|
new RegExp(pattern);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const validateRegexp = (val: string) => {
|
const validateRegexp = (val: string) => {
|
||||||
let error = "";
|
let error = "";
|
||||||
|
@ -121,6 +158,13 @@ export const RegexField = ({
|
||||||
return error;
|
return error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { validateForm } = useFormikContext();
|
||||||
|
useEffect(() => {
|
||||||
|
if (useRegex) {
|
||||||
|
validateForm();
|
||||||
|
}
|
||||||
|
}, [useRegex]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
|
@ -135,7 +179,7 @@ export const RegexField = ({
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{label}
|
{label}
|
||||||
{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}
|
<span className="z-10">{tooltip && <CustomTooltip anchorId={name}>{tooltip}</CustomTooltip>}</span>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
@ -152,7 +196,7 @@ export const RegexField = ({
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
autoComplete={autoComplete}
|
autoComplete={autoComplete}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
meta.touched && meta.error
|
useRegex && meta.error
|
||||||
? "focus:ring-red-500 focus:border-red-500 border-red-500"
|
? "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",
|
: "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
|
disabled
|
||||||
|
@ -166,7 +210,7 @@ export const RegexField = ({
|
||||||
{useRegex && (
|
{useRegex && (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="flex float-right items-center">
|
<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" }} />
|
<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" }} />
|
<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" }} />
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const CustomTooltip = ({
|
||||||
const id = `${anchorId}-tooltip`;
|
const id = `${anchorId}-tooltip`;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center">
|
<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}>
|
<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}
|
{children}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue