Skip to content

feat(devices): filter device table by platform and bundle version - #2792

Merged
riderx merged 20 commits into
mainfrom
cursor/device-table-platform-bundle-filters-d0a8
Jul 31, 2026
Merged

feat(devices): filter device table by platform and bundle version#2792
riderx merged 20 commits into
mainfrom
cursor/device-table-platform-bundle-filters-d0a8

Conversation

@riderx

@riderx riderx commented Jul 30, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Add Platform and Bundle filters on the devices table so users can filter large fleets by platform, bundle version, or both.
  • Filters open in a modal after clicking Filters (replacing the cramped dropdown).
  • Platform uses large touch-friendly chips; bundle is a labeled text input with suggestions.
  • Wire platform through /private/devices (count + list) for Supabase and Cloudflare Analytics Engine backends.
  • Keep Override / Custom ID filters and device-id search.

Motivation (AI generated)

Customers with tens of thousands of devices reported that search + existing filters are not enough to find devices on a specific bundle/platform combination. The previous Filters dropdown was too tight for selects/inputs; a modal matches Capgo console patterns and gives readable, accessible controls.

Business Impact (AI generated)

Makes the console usable for large fleets, reducing support friction and helping customers inspect rollout status by platform/bundle without leaving Capgo.

Visual changes (AI generated)

Filters button opens a modal with platform chips, bundle input, options, Clear, and Done:

Devices Filters modal with Platform and Bundle

Full page context:

Devices page with Filters modal open

Test Plan (AI generated)

  • Unit tests for CF query platform+version outer filters + SB platform/version combo
  • Private /private/devices accepts platform + versionName; rejects invalid platform
  • Local screenshot of Filters modal with platform chips + bundle field
  • Open Filters on /app/<app>/devices, set platform + bundle, confirm table + badge count update
  • Confirm Override / Custom ID still work with the new filters
  • Confirm Clear filters resets platform, bundle, and boolean options
  • Confirm typing a bundle not in the suggestion list still filters

Generated with AI

Allow filtering the devices list by platform and/or bundle version so
large fleets can be narrowed without exporting data offline.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

DeviceTable adds platform and bundle/version filters with debounced reloads. The private devices endpoint validates and forwards platform filters to Cloudflare Analytics Engine and Supabase queries, with tests covering validation, propagation, and generated query conditions.

Changes

Device filtering

Layer / File(s) Summary
Device filter controls
src/components/tables/DeviceTable.vue, src/components/DataTable.vue, messages/en.json, playwright/visual-diff.config.ts
Adds platform and bundle selectors, bundle-name loading, filter synchronization, debounced reloads, extra-filter support, translations, and visual-diff preparation.
Platform request validation and propagation
supabase/functions/_backend/private/devices.ts, supabase/functions/_backend/utils/types.ts, supabase/functions/_backend/utils/stats.ts
Adds the optional platform field, validates supported enum values, and forwards it to device reads and counts.
Backend platform query support
supabase/functions/_backend/utils/cloudflare.ts, supabase/functions/_backend/utils/supabase.ts
Applies platform filtering to latest Cloudflare device state and Supabase read/count queries.
Platform filter validation coverage
tests/cloudflare-device-pagination.unit.test.ts, tests/private-analytics-validation.unit.test.ts
Tests generated query conditions, Supabase filters, invalid platform rejection, and endpoint forwarding.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DeviceTable
  participant PrivateDevices
  participant Stats
  participant CloudflareAnalytics
  participant Supabase

  DeviceTable->>PrivateDevices: POST platform and versionName filters
  PrivateDevices->>Stats: Forward platform to countDevices
  Stats->>CloudflareAnalytics: Count devices by latest platform
  Stats->>Supabase: Count devices with platform filter as fallback
  PrivateDevices->>CloudflareAnalytics: Read devices with latest-state conditions
  PrivateDevices->>Supabase: Read devices with platform filter as fallback
Loading

Suggested labels: codex

Suggested reviewers: dalanir, wcaleniewolny

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding platform and bundle version filters to the devices table.
Description check ✅ Passed The description covers summary, motivation, impact, visuals, and test plan, with only the checklist section missing.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@cursor
cursor Bot temporarily deployed to deepsec-pr July 30, 2026 17:49 Inactive
@codspeed-hq

codspeed-hq Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing cursor/device-table-platform-bundle-filters-d0a8 (3272f3c) with main (52eac24)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Visual diff passed

Visual changes

Generated at 2026-07-30T23:52:51.679Z. Threshold: 0.1% pixel difference.

Route Diff % Status
login 0.000 unchanged
dashboard 2.879 changed
apps 0.470 changed
app-overview 1.354 changed
channels 0.832 changed
devices 52.758 changed
observe 0.000 unchanged
observe-plugins 0.000 unchanged
api-keys-app-preview 0.000 unchanged

Commit: 3272f3c5e5ac495e3af484716bd196fd702a1af2
Download the HTML report from workflow artifacts (artifact: visual-diff-report-3272f3c5e5ac495e3af484716bd196fd702a1af2).

Open index.html from the artifact for side-by-side before/after/diff screenshots.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr July 30, 2026 17:55 Inactive
@cursor
cursor Bot marked this pull request as ready for review July 30, 2026 18:07
Comment thread src/components/tables/DeviceTable.vue
@coderabbitai coderabbitai Bot added the codex label Jul 30, 2026
Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot requested review from Dalanir and WcaleNieWolny July 30, 2026 18:10

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot completed as skipped and reported an unresolved finding, and this PR is above the low-risk approval threshold (user-facing filters plus private device list/count API changes). Assigning human reviewers.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor
cursor Bot temporarily deployed to deepsec-pr July 30, 2026 18:10 Inactive
Comment thread src/components/tables/DeviceTable.vue

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot completed as skipped on the latest commit, and this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API changes). Human reviewers are already assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/tables/DeviceTable.vue`:
- Around line 104-109: Update getVersionNameFilter so an empty
selectedVersionName explicitly clears the bundle filter instead of falling back
to props.versionName. Also synchronize selectedVersionName with later non-empty
prop changes using the component’s existing reactive/watch mechanism, while
preserving the user’s current selection when appropriate.
- Around line 128-149: Update loadBundleNames to capture the current props.appId
before the Supabase await, then verify it still matches props.appId immediately
after the await and return if it changed. Only update bundleNames from responses
belonging to the current app, preserving the existing error and option-building
behavior.

In `@supabase/functions/_backend/utils/cloudflare.ts`:
- Around line 984-1005: Update the platform-filtered query construction in the
device-count logic, including the corresponding path around the related second
occurrence, so the inner aggregation selects the latest platform and
version_name per blob1 before the outer query applies both platform and
bundle/version predicates. Remove version filtering from the inner device_info
conditions, preserve current-state semantics matching Supabase, and update the
associated SQL test expectations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: da1b13e4-3fa2-47ab-8e67-e473e01fb13d

📥 Commits

Reviewing files that changed from the base of the PR and between fd3d989 and 038bc5d.

📒 Files selected for processing (9)
  • messages/en.json
  • src/components/tables/DeviceTable.vue
  • supabase/functions/_backend/private/devices.ts
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/stats.ts
  • supabase/functions/_backend/utils/supabase.ts
  • supabase/functions/_backend/utils/types.ts
  • tests/cloudflare-device-pagination.unit.test.ts
  • tests/private-analytics-validation.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

Comment thread src/components/tables/DeviceTable.vue
Comment thread src/components/tables/DeviceTable.vue
Comment thread supabase/functions/_backend/utils/cloudflare.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot completed as skipped and left an unresolved finding, so this is not approved. Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

Use selected bundle only (no prop fallback), sync prop changes into the
dropdown, and filter CF device queries on latest version_name + platform
after aggregation so combinations match Supabase semantics.

Co-authored-by: Martin DONADIEU <martindonadieu@gmail.com>
@cursor
cursor Bot temporarily deployed to deepsec-pr July 30, 2026 18:16 Inactive

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot did not reach a successful terminal state within the wait window (pending/skipped) and is not a clean pass, so this is not approved. Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (3)
src/components/tables/DeviceTable.vue (3)

464-468: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Guard the entire app-switch watcher against stale executions.

When an app switch makes loadBundleNames() return because its request is stale, this watcher still calls refreshData(). It also leaves the previous app’s bundle options visible while the new request is pending.

Proposed fix
-watch(() => props.appId, async () => {
+watch(() => props.appId, async (appId) => {
   selectedPlatform.value = ''
   selectedVersionName.value = props.versionName ?? ''
+  bundleNames.value = []
   await loadBundleNames()
+  if (appId !== props.appId)
+    return
   await refreshData()
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tables/DeviceTable.vue` around lines 464 - 468, Update the
appId watcher around loadBundleNames and refreshData so stale executions stop
before refreshing data, and clear the bundle options immediately when the app
changes. Ensure only the current app-switch execution proceeds to refreshData
after loadBundleNames completes, using the existing stale-request signal or
return value from loadBundleNames.

464-468: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Avoid duplicate reloads when the application changes.

Resetting selectedPlatform or selectedVersionName triggers debouncedReload(), while the app watcher separately calls refreshData(). A typical app switch therefore performs two count/list cycles. Suppress the filter watcher during app reset or make a single watcher responsible for the refresh.

Also applies to: 476-478

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tables/DeviceTable.vue` around lines 464 - 468, Update the
appId watcher and related filter watcher in the DeviceTable component so
resetting selectedPlatform and selectedVersionName does not trigger
debouncedReload during the app reset. Ensure the appId watcher performs only one
refresh flow after applying the new values, while preserving normal
filter-triggered reloads outside app changes.

286-289: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Invalidate in-flight loads immediately when filters change.

The watcher changes filter state but waits 300 ms before reload() increments activeLoadId. During that window, an existing reload can count with the old filters and then fetch rows with the new platform/versionName, producing mismatched totals and pages. Invalidate the active load in the watcher or pass one immutable filter snapshot through both requests.

Also applies to: 307-308, 476-478

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tables/DeviceTable.vue` around lines 286 - 289, Update the
filter watcher and debouncedReload flow in DeviceTable so changing filters
immediately invalidates any in-flight load before the 300 ms debounce,
preventing old requests from using new platform/versionName values. Increment or
otherwise invalidate activeLoadId at watcher time, while preserving the existing
debounced reload behavior and applying the same fix to the additional watcher
locations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/tables/DeviceTable.vue`:
- Around line 464-468: Update the appId watcher around loadBundleNames and
refreshData so stale executions stop before refreshing data, and clear the
bundle options immediately when the app changes. Ensure only the current
app-switch execution proceeds to refreshData after loadBundleNames completes,
using the existing stale-request signal or return value from loadBundleNames.
- Around line 464-468: Update the appId watcher and related filter watcher in
the DeviceTable component so resetting selectedPlatform and selectedVersionName
does not trigger debouncedReload during the app reset. Ensure the appId watcher
performs only one refresh flow after applying the new values, while preserving
normal filter-triggered reloads outside app changes.
- Around line 286-289: Update the filter watcher and debouncedReload flow in
DeviceTable so changing filters immediately invalidates any in-flight load
before the 300 ms debounce, preventing old requests from using new
platform/versionName values. Increment or otherwise invalidate activeLoadId at
watcher time, while preserving the existing debounced reload behavior and
applying the same fix to the additional watcher locations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e590877f-0f25-42ff-baec-7bbcf913d25b

📥 Commits

Reviewing files that changed from the base of the PR and between 038bc5d and 4d06f7e.

📒 Files selected for processing (1)
  • src/components/tables/DeviceTable.vue
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/components/tables/DeviceTable.vue
Comment thread src/components/tables/DeviceTable.vue
Comment thread src/components/tables/DeviceTable.vue
Comment thread src/components/tables/DeviceTable.vue Outdated
cursor[bot]
cursor Bot approved these changes Jul 30, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed with no unresolved findings, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
src/components/tables/DeviceTable.vue (1)

126-152: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not truncate bundle filter options at 200 versions.

Apps with more than 200 active versions cannot select older bundles, so filtering is incomplete. Paginate this query or replace the static list with server-side search.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tables/DeviceTable.vue` around lines 126 - 152, Update
loadBundleNames so it retrieves all active app_versions instead of limiting
results to 200, using pagination or server-side search while preserving the
existing stale-response, error, deduplication, and selected-filter behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/tables/DeviceTable.vue`:
- Around line 126-152: Update loadBundleNames so it retrieves all active
app_versions instead of limiting results to 200, using pagination or server-side
search while preserving the existing stale-response, error, deduplication, and
selected-filter behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: af759e92-6e0c-4a9d-8074-12d33c7335a3

📥 Commits

Reviewing files that changed from the base of the PR and between 4d06f7e and 25711f5.

📒 Files selected for processing (3)
  • src/components/tables/DeviceTable.vue
  • supabase/functions/_backend/utils/cloudflare.ts
  • tests/cloudflare-device-pagination.unit.test.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Cap-go/capacitor-updater (manual)

@riderx
riderx marked this pull request as ready for review July 30, 2026 23:33

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed and all findings are resolved, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

Keep keyboard users on the Filters control after dismissing the modal instead of dropping focus to the document.

Co-authored-by: Cursor <cursoragent@cursor.com>
cursor[bot]
cursor Bot approved these changes Jul 30, 2026
@riderx
riderx marked this pull request as draft July 30, 2026 23:35

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/components/DataTable.vue Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed with no unresolved findings, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

cursor[bot]
cursor Bot approved these changes Jul 30, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread playwright/visual-diff.config.ts
Comment thread src/components/DataTable.vue Outdated
@riderx
riderx marked this pull request as ready for review July 30, 2026 23:45
cursor[bot]
cursor Bot approved these changes Jul 30, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed with no unresolved findings, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

…wait

Use a per-instance heading id for accessibility, and only fall back to the legacy Override wait when the modal itself is missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
@riderx
riderx marked this pull request as draft July 30, 2026 23:47

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Approved — Cursor Bugbot passed with no unresolved findings, and this change is within the medium-risk approval threshold. Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed with no unresolved findings, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@sonarqubecloud

Copy link
Copy Markdown

@riderx
riderx marked this pull request as ready for review July 30, 2026 23:53

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Left a non-blocking comment — Cursor Bugbot passed with no unresolved findings, but this PR is above the low-risk approval threshold (user-facing device filters plus private list/count API/query changes). Human reviewers are already requested (2); no new reviewers assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Approved — Cursor Bugbot passed and its findings are resolved; no approval-policy blockers. Human reviewers were already assigned, so none were added.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found and verified against the latest diff

Confidence score: 4/5

  • In src/components/DataTable.vue, checkbox IDs for filters are not instance-unique/stable, so in pages with multiple tables or reordered filters a label can toggle the wrong input, causing confusing filter behavior and accessibility regressions—derive IDs from a component-scoped useId() prefix plus a stable filter key/index.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/DataTable.vue">

<violation number="1" location="src/components/DataTable.vue:665">
P3: Filter checkbox IDs are not instance-unique or stable across filter ordering, so labels can target the wrong checkbox when multiple tables/modals exist. Generate them from a component `useId()` prefix plus the filter key.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

class="flex min-h-11 cursor-pointer items-center rounded-md px-2 py-2 transition-colors duration-150 hover:bg-slate-50 dark:hover:bg-slate-800"
>
<input
:id="`filter-radio-example-${i}`"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Filter checkbox IDs are not instance-unique or stable across filter ordering, so labels can target the wrong checkbox when multiple tables/modals exist. Generate them from a component useId() prefix plus the filter key.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/DataTable.vue, line 663:

<comment>Filter checkbox IDs are not instance-unique or stable across filter ordering, so labels can target the wrong checkbox when multiple tables/modals exist. Generate them from a component `useId()` prefix plus the filter key.</comment>

<file context>
@@ -509,30 +602,105 @@ const paginationClass = computed(() => props.mobileFixedPagination
+                      class="flex min-h-11 cursor-pointer items-center rounded-md px-2 py-2 transition-colors duration-150 hover:bg-slate-50 dark:hover:bg-slate-800"
+                    >
+                      <input
+                        :id="`filter-radio-example-${i}`"
+                        :checked="filters?.[f]"
+                        type="checkbox"
</file context>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 13 files

Confidence score: 5/5

  • In src/components/DataTable.vue, the shared filter subtitle now over-describes controls for non-device tables (e.g., mentioning platform/bundle where those filters don’t exist), which can mislead users and cause incorrect filtering expectations—make the subtitle generic (or context-specific per table) to keep the UI copy accurate.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/components/DataTable.vue">

<violation number="1" location="src/components/DataTable.vue:631">
P3: Filter dialogs outside the device table now describe controls they do not have; for example API-key scope and bundle storage/deletion filters claim to filter platform and bundle. Make this shared subtitle generic or provide it from the device-specific slot.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

{{ t(filterText ?? 'Filters') }}
</h2>
<p class="mt-1 text-sm leading-5 text-slate-600 dark:text-slate-300">
{{ t('filter-modal-subtitle') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Filter dialogs outside the device table now describe controls they do not have; for example API-key scope and bundle storage/deletion filters claim to filter platform and bundle. Make this shared subtitle generic or provide it from the device-specific slot.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/DataTable.vue, line 631:

<comment>Filter dialogs outside the device table now describe controls they do not have; for example API-key scope and bundle storage/deletion filters claim to filter platform and bundle. Make this shared subtitle generic or provide it from the device-specific slot.</comment>

<file context>
@@ -509,30 +604,105 @@ const paginationClass = computed(() => props.mobileFixedPagination
+                      {{ t(filterText ?? 'Filters') }}
+                    </h2>
+                    <p class="mt-1 text-sm leading-5 text-slate-600 dark:text-slate-300">
+                      {{ t('filter-modal-subtitle') }}
+                    </p>
+                  </div>
</file context>

@riderx
riderx merged commit a81f8b3 into main Jul 31, 2026
55 of 75 checks passed
@riderx
riderx deleted the cursor/device-table-platform-bundle-filters-d0a8 branch July 31, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants