mirror of
https://github.com/agregarr/agregarr.git
synced 2026-01-09 07:45:17 +08:00
parent
d32c041faf
commit
15d343e8ee
@ -197,7 +197,8 @@ export interface ConditionRule {
|
|||||||
| 'contains' // string contains
|
| 'contains' // string contains
|
||||||
| 'regex' // regex match
|
| 'regex' // regex match
|
||||||
| 'begins' // string begins with
|
| 'begins' // string begins with
|
||||||
| 'ends'; // string ends with
|
| 'ends' // string ends with
|
||||||
|
| 'exists'; // field exists (has non-null/undefined value)
|
||||||
value: string | number | boolean | (string | number)[];
|
value: string | number | boolean | (string | number)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -185,6 +185,12 @@ function evaluateRule(
|
|||||||
if (rule.operator === 'neq') {
|
if (rule.operator === 'neq') {
|
||||||
return conditionValue !== undefined && conditionValue !== null;
|
return conditionValue !== undefined && conditionValue !== null;
|
||||||
}
|
}
|
||||||
|
// For 'exists', we need to evaluate based on the presence/absence of value
|
||||||
|
if (rule.operator === 'exists') {
|
||||||
|
// value is null/undefined, so field does NOT exist
|
||||||
|
// Return true if conditionValue is false (checking for non-existence)
|
||||||
|
return conditionValue === false;
|
||||||
|
}
|
||||||
// For all other operators (eq, gt, gte, lt, lte, contains, in, etc.)
|
// For all other operators (eq, gt, gte, lt, lte, contains, in, etc.)
|
||||||
// undefined/null means the condition can't be evaluated, so false
|
// undefined/null means the condition can't be evaluated, so false
|
||||||
return false;
|
return false;
|
||||||
@ -292,6 +298,14 @@ function evaluateRule(
|
|||||||
typeof conditionValue === 'string' &&
|
typeof conditionValue === 'string' &&
|
||||||
value.toLowerCase().endsWith(conditionValue.toLowerCase())
|
value.toLowerCase().endsWith(conditionValue.toLowerCase())
|
||||||
);
|
);
|
||||||
|
case 'exists':
|
||||||
|
// Check if field has a non-null/undefined value
|
||||||
|
// conditionValue should be boolean: true = exists, false = not exists
|
||||||
|
if (typeof conditionValue === 'boolean') {
|
||||||
|
const hasValue = value !== undefined && value !== null;
|
||||||
|
return conditionValue ? hasValue : !hasValue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,7 @@ const messages = defineMessages({
|
|||||||
opBegins: 'begins with',
|
opBegins: 'begins with',
|
||||||
opEnds: 'ends with',
|
opEnds: 'ends with',
|
||||||
opIn: 'in',
|
opIn: 'in',
|
||||||
|
opExists: 'exists',
|
||||||
and: 'AND',
|
and: 'AND',
|
||||||
or: 'OR',
|
or: 'OR',
|
||||||
});
|
});
|
||||||
@ -143,6 +144,7 @@ const RuleItem: React.FC<RuleItemProps> = ({
|
|||||||
const isRadarrTags = field === 'radarrTags';
|
const isRadarrTags = field === 'radarrTags';
|
||||||
const isSonarrTags = field === 'sonarrTags';
|
const isSonarrTags = field === 'sonarrTags';
|
||||||
const isTagField = isRadarrTags || isSonarrTags;
|
const isTagField = isRadarrTags || isSonarrTags;
|
||||||
|
const isExistsOperator = operator === 'exists';
|
||||||
|
|
||||||
// Fetch all tags from all Radarr instances
|
// Fetch all tags from all Radarr instances
|
||||||
const { data: radarrTags } = useSWR<ArrTag[]>(
|
const { data: radarrTags } = useSWR<ArrTag[]>(
|
||||||
@ -218,14 +220,14 @@ const RuleItem: React.FC<RuleItemProps> = ({
|
|||||||
const numericOnlyOperators = ['gt', 'gte', 'lt', 'lte'];
|
const numericOnlyOperators = ['gt', 'gte', 'lt', 'lte'];
|
||||||
const isCurrentOperatorInvalid =
|
const isCurrentOperatorInvalid =
|
||||||
(!isNewFieldNumeric && numericOnlyOperators.includes(operator)) ||
|
(!isNewFieldNumeric && numericOnlyOperators.includes(operator)) ||
|
||||||
(isNewFieldBoolean && !['eq', 'neq'].includes(operator));
|
(isNewFieldBoolean && !['eq', 'neq', 'exists'].includes(operator));
|
||||||
|
|
||||||
// Reset to appropriate defaults when changing field
|
// Reset to appropriate defaults when changing field
|
||||||
onChange({
|
onChange({
|
||||||
...rule,
|
...rule,
|
||||||
field: newField,
|
field: newField,
|
||||||
operator: isCurrentOperatorInvalid ? 'eq' : rule.operator,
|
operator: isCurrentOperatorInvalid ? 'eq' : rule.operator,
|
||||||
value: isNewFieldBoolean ? true : '',
|
value: operator === 'exists' || isNewFieldBoolean ? true : '',
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="flex-1 select-none rounded border border-stone-600 bg-stone-700 px-2 py-1 text-sm text-white"
|
className="flex-1 select-none rounded border border-stone-600 bg-stone-700 px-2 py-1 text-sm text-white"
|
||||||
@ -247,9 +249,12 @@ const RuleItem: React.FC<RuleItemProps> = ({
|
|||||||
<select
|
<select
|
||||||
value={operator}
|
value={operator}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
const newOperator = e.target.value as ConditionRule['operator'];
|
||||||
onChange({
|
onChange({
|
||||||
...rule,
|
...rule,
|
||||||
operator: e.target.value as ConditionRule['operator'],
|
operator: newOperator,
|
||||||
|
// Set value to true when switching to 'exists' operator
|
||||||
|
value: newOperator === 'exists' ? true : rule.value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
className="w-32 rounded border border-stone-600 bg-stone-700 px-2 py-1 text-sm text-white"
|
className="w-32 rounded border border-stone-600 bg-stone-700 px-2 py-1 text-sm text-white"
|
||||||
@ -287,10 +292,11 @@ const RuleItem: React.FC<RuleItemProps> = ({
|
|||||||
<option value="ends">{intl.formatMessage(messages.opEnds)}</option>
|
<option value="ends">{intl.formatMessage(messages.opEnds)}</option>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<option value="exists">{intl.formatMessage(messages.opExists)}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
{/* Value Input */}
|
{/* Value Input */}
|
||||||
{isBoolean ? (
|
{isBoolean || isExistsOperator ? (
|
||||||
<select
|
<select
|
||||||
value={String(value)}
|
value={String(value)}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|||||||
@ -139,7 +139,8 @@ export interface ConditionRule {
|
|||||||
| 'contains' // string contains
|
| 'contains' // string contains
|
||||||
| 'regex' // regex match
|
| 'regex' // regex match
|
||||||
| 'begins' // string begins with
|
| 'begins' // string begins with
|
||||||
| 'ends'; // string ends with
|
| 'ends' // string ends with
|
||||||
|
| 'exists'; // field exists (has non-null/undefined value)
|
||||||
value: string | number | boolean | (string | number)[];
|
value: string | number | boolean | (string | number)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user