Files
multica/server/internal/handler
Deoanddeo 46c9ea38a7 feat(issues): extend property filter to text / number / date / url (MUL-6423) (#7240)
* feat(issues): extend property filter to text / number / date / url

Widen the custom-property filter (value + "No value" / __none__) from
select / multi_select / checkbox / actor to the four scalar types.

Backend:
- parsePropertiesFilterParam emits a jsonb number containment form for
  numeric filter values, guarding against NaN / Infinity (not representable
  as JSON). Date / text / url stay on the string form.
- Property table facets gain text / url / date (string) and number
  branches, replacing the 422 default, with the unset "__none__" bucket.

Frontend:
- isFilterablePropertyType (core) now admits the scalar types; the filter
  menu renders a value input plus a mutually-exclusive "No value" option
  for text / number / date / url (PropertyFilterOptions). The scalar value
  and "No value" are both disabled when a saved view locks the dimension.
- Filter chips show the scalar value directly; the client matcher compares
  number values numerically, matching the server's jsonb containment.
- New store action setPropertyFilterValues replaces a property's full
  filter value set.

Tests cover numeric + NaN/Infinity parse, scalar facet buckets, number
client matching (incl. non-canonical forms), isScalarPropertyType, and
the store action.

Note: a text property value literally stored as "__none__" is reserved —
the sentinel means "no value", and the filter input rejects it.

* fix(issues): address review on scalar property filter (PR #7240)

Respond to Bohan-J's review:

- Scalar value input could not be typed into: Base UI's menu popup stops
  every printable key on the role="menu" element, which bubbled up from the
  input and swallowed characters. The input's onKeyDown now stops
  propagation for every key except Escape/Tab (Enter still commits and also
  stops propagation so it cannot activate the highlighted "No value" item).
- Scalar facet branches were unbounded: text/url/date/number grouped by
  distinct value with no LIMIT, but the menu only reads the "__none__"
  bucket. They now compute just the "__set__"/"__none__" buckets.
- New UI surface lacked tests: added issues-header.property-filter.test.tsx
  driving the real Base UI menu, covering typing, Enter/blur commit, the
  value <-> "No value" exclusion, and the blur-vs-click ordering.
- Draft staleness: sync the draft to the committed scalar value via an
  effect (keying the input did not reliably reset it), so an external clear
  cannot be written back by unchecking "No value".
- Make onSetValues required; note that isFilterablePropertyType stays an
  explicit enumeration so future property types opt into filtering.

* fix(issues): compose scalar value and No-value filters OR-style

Review round 2 on PR #7240: unchecking "No value" dropped a committed
scalar value. The draft round-trip engineered for mutual exclusion was
the root cause — checking No-value changed the committed set, the draft
effect wiped the input, and unchecking read an empty draft.

Scalars now treat "No value" as a plain member of the same OR-set as
every other property type:

- Checking/unchecking toggles membership only and never touches the
  committed value member, so no restore-on-uncheck machinery is needed.
- Committing a value replaces just the value member and preserves
  existing No-value membership.
- The string branch of issueMatchesPropertyFilters skips the sentinel
  when matching stored values, so a literal "__none__" text value cannot
  satisfy a No-value filter (agreeing with the server's key-absence
  predicate).

Component tests cover the exact reviewed sequence (commit -> check ->
uncheck restores the value) and the uncommitted-draft path.

---------

Co-authored-by: deo <deo@deo的macbook\032pro.tyaio>
2026-08-28 15:56:34 +08:00
..