mirror of
https://github.com/we-promise/sure.git
synced 2026-09-07 23:54:25 +00:00
feat(rules): add not-equal, does-not-contain, and is-not-empty condition operators (#2529)
* feat(rules): add not-equal, does-not-contain, is-not-empty condition operators Extend transaction rule conditions beyond "equal to" / "is empty": - text: add "does not contain" (not_like), "not equal to" (!=), "is not empty" (is_not_null) - number: add "not equal to" (!=) - select: add "not equal to" (!=), "is not empty" (is_not_null) NULL handling is inclusive so the operators match user intent: - "!=" uses IS DISTINCT FROM, so e.g. "category not equal to X" also matches uncategorized (NULL) transactions - "does not contain" also matches rows where the field is NULL transaction_type keeps its custom operator set, and transaction_details is pinned to the original operators since its JSONB apply only supports contains/equals/empty semantics. The conditions Stimulus controller hides the value field for both valueless operators (is_null and is_not_null). * refactor(rules): address PR review feedback on condition operators - Pass VALUELESS_OPERATORS from Ruby to JS via Stimulus value attribute instead of duplicating the list as a static class property, so there is a single source of truth for which operators suppress the value field - Clarify IS DISTINCT FROM comment to note the NULL-inclusion behaviour is intentional for select-type fields (merchant_id, category_id) and not applicable to number fields where NULL is impossible at the DB level - Add test that exercises the OR IS NULL branch of not_like by using transaction_notes (entries.notes is nullable, unlike entries.name) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(rules): localize condition operator labels via i18n Moves all Rule::ConditionFilter operator labels (including ones that predate this PR) out of OPERATORS_MAP and into config/locales, so operators() resolves them through t() per request instead of hardcoded English strings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GvxjdTgH34cPoJenQAqnpN --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
7ffe877531
commit
9714612bb1
@@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus";
|
||||
|
||||
// Connects to data-controller="rule--conditions"
|
||||
export default class extends Controller {
|
||||
static values = { conditionFilters: Array };
|
||||
static values = { conditionFilters: Array, valuelessOperators: Array };
|
||||
static targets = [
|
||||
"destroyField",
|
||||
"filterValue",
|
||||
@@ -12,7 +12,7 @@ export default class extends Controller {
|
||||
];
|
||||
|
||||
connect() {
|
||||
// Hide value field on initial load if operator is "is_null"
|
||||
// Hide value field on initial load for valueless operators (e.g. "is_null")
|
||||
this.#toggleValueFieldVisibility();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export default class extends Controller {
|
||||
#toggleValueFieldVisibility() {
|
||||
const operator = this.operatorSelectTarget.value;
|
||||
|
||||
if (operator === "is_null") {
|
||||
if (this.valuelessOperatorsValue.includes(operator)) {
|
||||
this.filterValueTarget.classList.add("hidden");
|
||||
// Clear the value since it's not needed
|
||||
if (this.valueInputEl) {
|
||||
|
||||
Reference in New Issue
Block a user