Skip to content

Conversation

mtrezza
Copy link
Member

@mtrezza mtrezza commented Sep 10, 2025

New Pull Request Checklist

Issue Description

Data browser filter is missing a "contained in" filter condition.

Approach

Adds new filter condition "contained in" to data browser. For example, allows to filter for objects with IDs contained in [1, 2].

Summary by CodeRabbit

  • New Features

    • Added a “Contained in” filter for Pointer, Boolean, Number, String, and Date fields.
    • Added a dedicated input that accepts and displays JSON arrays for the contained-in filter, preserving keyboard/focus behavior.
  • Refactor

    • Standardized filter payloads to use compareTo (including audience device type).
    • Updated query handling to support the new “Contained in” constraint.
  • UX Improvements

    • Replaced multi-tab pointer-opening with a single filtered view, improved messages for no/mixed-pointer cases.

Copy link

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

Copy link

coderabbitai bot commented Sep 10, 2025

Warning

Rate limit exceeded

@mtrezza has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 42 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d5e2cf9 and 5d193da.

📒 Files selected for processing (1)
  • src/components/Filter/Filter.react.js (1 hunks)
📝 Walkthrough

Walkthrough

Adds a new "containedIn" constraint across Filters, UI, and query translation. Adds constraint metadata, a JSON-array input path in FilterRow, switches containedIn filter payloads to use compareTo, and updates callers (query builder, PushAudiencesSelector, Views) to construct and consume containedIn filters.

Changes

Cohort / File(s) Summary of Changes
Constraint definition and availability
src/lib/Filters.js
Adds Constraints.containedIn ({ name: 'contained in', comparable: true }) and inserts 'containedIn' into FieldConstraints for Pointer, Boolean, Number, String, and Date.
Filter UI input handling
src/components/BrowserFilter/FilterRow.react.js
Extends compareValue(...) signature to accept currentConstraint. Adds branch to render a text input for containedIn that displays arrays with JSON.stringify and attempts to parse JSON array on change; propagates parsed array (or raw string on parse failure). Preserves focus and key handling.
Query translation and consumers
src/lib/queryFromFilters.js, src/components/PushAudiencesSelector/PushAudiencesSelector.react.js
For containedIn, use filter.get('compareTo') (not array) when building query.containedIn. PushAudiencesSelector constructs containedIn filters with compareTo instead of array.
Views pointer-filter workflow
src/dashboard/Data/Views/Views.react.js
Replaces per-pointer multi-tab opening with single filtered navigation: groups pointers by class, validates single-class, builds a containedIn filter for objectId (using compareTo array), opens one browser tab with the encoded filters, and replaces prior per-pointer notifications with a single success/failure path and explicit messages for zero or mixed-class pointers.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant FR as FilterRow (UI)
  participant FS as Filters State
  participant QF as queryFromFilters
  participant Q as Query Builder
  participant V as Views (handleOpenAllPointers)

  U->>FR: Select constraint = "containedIn" and enter text
  FR->>FR: Render input as JSON string if value is array
  FR->>FR: On change -> try JSON.parse
  alt parsed is array
    FR->>FS: onChangeCompareTo([values])
  else parsed not array or parse error
    FR->>FS: onChangeCompareTo(raw string)
  end

  U->>V: Click "Open pointers" on column
  V->>V: Collect pointers, group by class
  alt single class & ids present
    V->>FS: Build filter { field: 'objectId', constraint:'containedIn', compareTo: [ids] }
    V->>Q: Navigate to browser/<Class>?filters=<encoded_filters>
  else zero pointers
    V-->>U: Show note "No pointers found in this column"
  else multiple classes
    V-->>U: Show error about multiple classes
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The description includes the checklist, an Issue Description, and an Approach, but it omits the required "Closes: FILL_THIS_OUT" line and does not include the "TODOs before merging" checklist items (tests and documentation) from the repository template, leaving the template incomplete. Add the missing "Closes: " line to reference the related issue and populate the "TODOs before merging" checklist (at minimum add entries for tests and documentation), and optionally expand the Approach with brief implementation/testing notes so reviewers can validate completeness.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately summarizes the primary change—adding a "containedIn" filter condition to the data browser—and uses the conventional "feat:" prefix; it is concise, specific, and appropriate for quick scanning of PR history.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Sep 10, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

Copy link

uffizzi-cloud bot commented Sep 10, 2025

Uffizzi Ephemeral Environment deployment-65269

⌚ Updated Sep 10, 2025, 23:53 UTC

☁️ https://app.uffizzi.com/github.com/parse-community/parse-dashboard/pull/2979

📄 View Application Logs etc.

What is Uffizzi? Learn more

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/PushAudiencesSelector/PushAudiencesSelector.react.js (1)

23-29: Avoid converting compareTo array to Immutable.List.
fromJS turns the $in array into an Immutable.List, which then reaches query.containedIn and breaks. Construct this filter with Map so compareTo stays a plain array.

Apply this diff:

-import { fromJS } from 'immutable';
+import { fromJS, Map } from 'immutable';
@@
-          ? filters.push(
-            fromJS({
-              field: 'deviceType',
-              constraint: 'containedIn',
-              compareTo: query.deviceType['$in'],
-            })
-          )
+          ? filters.push(
+              Map({
+                field: 'deviceType',
+                constraint: 'containedIn',
+                compareTo: query.deviceType['$in'],
+              })
+            )
🧹 Nitpick comments (2)
src/lib/queryFromFilters.js (1)

99-104: Minor: guard JSON.parse errors in key helpers.*
If compareTo is not a JSON string here, JSON.parse will throw. Not new but becomes more likely as compareTo usage expands. Consider try/catch to avoid breaking the whole filter pipeline.

src/components/BrowserFilter/FilterRow.react.js (1)

251-253: Nice: passing currentConstraint into compareValue. One more UX tweak suggested.
When switching to containedIn, consider initializing compareTo to [] so users start from a valid value and we avoid accidental string submissions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2a24de and 1705f12.

📒 Files selected for processing (4)
  • src/components/BrowserFilter/FilterRow.react.js (2 hunks)
  • src/components/PushAudiencesSelector/PushAudiencesSelector.react.js (1 hunks)
  • src/lib/Filters.js (1 hunks)
  • src/lib/queryFromFilters.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/lib/Filters.js (1)
src/components/ExplorerQueryComposer/ExplorerFilter.js (2)
  • FieldConstraints (47-54)
  • FieldConstraints (47-54)
src/components/BrowserFilter/FilterRow.react.js (2)
src/components/PushAudienceDialog/InstallationCondition.react.js (1)
  • setFocus (26-30)
src/components/ExplorerQueryComposer/ExplorerQueryComposer.react.js (1)
  • setFocus (103-107)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (3)
src/lib/Filters.js (2)

178-182: Good addition: new constraint descriptor is consistent with existing shape.
containedIn is correctly introduced and marked comparable: true. No issues here.


185-189: Ensure 'containedIn' values are coerced to the correct Parse types

src/lib/Filters.js enables containedIn for Pointer, Boolean, Number, String, and Date — ensure the query builder (FilterRow / queryFromFilters) encodes/coerces values before sending to Parse: Pointers → Pointer-format/Parse.Object, Dates → Date objects / Parse-encoded dates, Booleans/Numbers → native types; otherwise Parse will receive mismatched types. I could not locate FilterRow or queryFromFilters in the repo — verify/implement this serialization where filters are turned into Parse queries.

src/components/BrowserFilter/FilterRow.react.js (1)

31-33: Signature change looks good.
Passing currentConstraint into compareValue is the right hook for rendering the containedIn-specific input.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/dashboard/Data/Views/Views.react.js (3)

575-576: Accessibility copy: minor polish and consistency.

Consider shorter, action-first phrasing and keep aria-label/title in sync with other headers. Example: “Filter rows by pointers in {name}.” This is optional, purely UX copy.

-aria-label={`Filter to show all pointers from ${name} column`}
-title="Filter to show all pointers from this column"
+aria-label={`Filter rows by pointers in ${name}`}
+title="Filter rows by pointers in this column"

873-876: Use a neutral note for “no pointers” instead of an error.

This is an expected state, not an error. Show a neutral/positive note for better UX signal.

-  this.showNote('No pointers found in this column', true);
+  this.showNote('No pointers found in this column', false);

894-903: Stabilize filter URL by sorting IDs (optional).

Sorting makes the generated URL deterministic across renders (useful for caching/sharing and tests).

-const uniqueObjectIds = Array.from(pointersByClass.get(targetClassName));
+const uniqueObjectIds = Array.from(pointersByClass.get(targetClassName)).sort();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1705f12 and d5e2cf9.

📒 Files selected for processing (1)
  • src/dashboard/Data/Views/Views.react.js (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/dashboard/Data/Views/Views.react.js (1)
src/lib/generatePath.js (2)
  • filters (8-8)
  • generatePath (3-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Docker linux/amd64
🔇 Additional comments (5)
src/dashboard/Data/Views/Views.react.js (5)

878-885: Good deduping by class and objectId.

Using Map + Set avoids duplicates and keeps the flow clear.


887-892: Clear guard against mixed target classes.

Good user-facing error with actionable guidance.


913-915: Success note is helpful.

Good concise feedback with pluralization handled.


899-912: Guard extremely long filter URLs

Search shows filters are embedded in generated URLs in multiple places — e.g. src/dashboard/Data/Views/Views.react.js (generatePath + window.open), src/dashboard/Data/Browser/Browser.react.js (generatePath/navigate and several containedIn usages), src/components/PermissionsDialog/PermissionsDialog.react.js, src/components/CategoryList/CategoryList.react.js, src/components/PushAudiencesSelector/PushAudiencesSelector.react.js. Implement a single length guard in generatePath or your navigation helper (conservative threshold ~4000 chars); on exceed, show a short user message or fall back to a short server-side filterId (or chunk/post) instead of embedding the full filters. If centralizing is not possible, apply the same conservative check before any window.open/navigate call.


899-903: Confirm containedIn payload contract across the app.

queryFromFilters passes filter.get('compareTo') directly to Parse.Query.containedIn (so it must be an array, not an un-parsed JSON/string). Verify the UI/storage/serialization consistently produce an array for containedIn.

  • Check src/lib/queryFromFilters.js — case 'containedIn' calls query.containedIn(filter.get('field'), filter.get('compareTo')).
  • Check src/components/BrowserFilter/FilterRow.react.js — currentConstraint === 'containedIn' renders a text input; confirm compareValue/onChangeCompareTo normalize to an array (or otherwise produce a JSON-parsed array).
  • Check src/dashboard/Data/Views/Views.react.js — filters are JSON.stringify([...]) with compareTo: uniqueObjectIds (array); ensure consumers parse/preserve the array before query construction.

@mtrezza mtrezza merged commit c1dc5bb into parse-community:alpha Sep 11, 2025
11 checks passed
@mtrezza mtrezza deleted the feat/add-conatinedIn-filter branch September 11, 2025 00:16
parseplatformorg pushed a commit that referenced this pull request Sep 11, 2025
# [7.5.0-alpha.2](7.5.0-alpha.1...7.5.0-alpha.2) (2025-09-11)

### Features

* Add data browser filter condition `containedIn` ([#2979](#2979)) ([c1dc5bb](c1dc5bb))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 7.5.0-alpha.2

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Sep 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:released-alpha Released as alpha version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants