Skip to content

feat(webui): Add configurable max results limit to CLP search UI.#2289

Open
hoophalab wants to merge 2 commits into
y-scope:mainfrom
hoophalab:maxsearch
Open

feat(webui): Add configurable max results limit to CLP search UI.#2289
hoophalab wants to merge 2 commits into
y-scope:mainfrom
hoophalab:maxsearch

Conversation

@hoophalab
Copy link
Copy Markdown
Contributor

@hoophalab hoophalab commented May 20, 2026

Description

  1. Add a MaxResultsSelect dropdown allowing users to choose the number of search results (10-10,000) instead of using the hardcoded default of 1000.
  2. The selected limit is passed through the search state, query submission and backend API.
  3. Use flex on query row.
limit

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  1. search button and dragging on timeline submits query with limit
  2. the number of rows in the tables are the same as the limit

Summary by CodeRabbit

  • New Features

    • Added a dropdown to customize the maximum number of search results per query (default: 1,000); this limit is respected across search submission, results listing and timeline zooming.
  • Style

    • Adjusted search controls and input layouts for improved responsiveness (flex wrapping, size constraints).
    • Fine-tuned component sizing and select control styling for a more consistent UI.

Review Change Stack

@hoophalab hoophalab requested a review from a team as a code owner May 20, 2026 21:43
@hoophalab hoophalab requested a review from junhaoliao May 20, 2026 21:44
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4045623e-7342-4b57-b9f8-2d73a526607c

📥 Commits

Reviewing files that changed from the base of the PR and between 139464f and 3a09d4f.

📒 Files selected for processing (1)
  • components/webui/client/src/pages/SearchPage/SearchControls/MaxResultsSelect/index.module.css

Walkthrough

This pull request adds a user-facing maximum results selector to the search interface, wiring it through client state, server acceptance, and result-fetch constraints. Users choose result limits from predefined options; the selection flows into query submission, server job creation, and both cursor-based fetching and persisted result capping.

Changes

Configurable Maximum Search Results Selection

Layer / File(s) Summary
Result limit constants and API schema
components/webui/client/src/pages/SearchPage/SearchState/typings.ts, components/webui/common/src/schemas/search.ts, components/webui/server/src/routes/api/search/typings.ts
MAX_RESULTS_OPTIONS and DEFAULT_MAX_NUM_RESULTS define selectable limits. QueryJobCreationSchema and server props types gain an optional/required maxNumResults field.
Search state field and updater
components/webui/client/src/pages/SearchPage/SearchState/index.tsx
Store gains maxNumResults state field initialized to the default constant and an updateMaxNumResults function to mutate it.
MaxResultsSelect component and search controls layout
components/webui/client/src/pages/SearchPage/SearchControls/MaxResultsSelect/index.tsx, components/webui/client/src/pages/SearchPage/SearchControls/MaxResultsSelect/index.module.css, components/webui/client/src/pages/SearchPage/SearchControls/Native/NativeControls.tsx, components/webui/client/src/pages/SearchPage/SearchControls/index.module.css, components/webui/client/src/pages/SearchPage/SearchControls/TimeRangeInput/index.module.css, components/webui/client/src/pages/SearchPage/SearchControls/Dataset/index.module.css, components/webui/client/src/components/QueryBox/index.module.css
New MaxResultsSelect dropdown component reads state and options, disables during query execution, and invokes the updater on selection change. Component is rendered in NativeControls between time range and submit button. Search controls layout and dependent inputs are updated with flex wrapping and bounded sizing for responsive layout.
Pass maxNumResults in submit and timeline zoom
components/webui/client/src/pages/SearchPage/SearchControls/Native/SearchButton/SubmitButton/index.tsx, components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTimeline/Native/NativeResultsTimeline.tsx
SubmitButton and NativeResultsTimeline read maxNumResults from store and include it in handleQuerySubmit payloads; both update callback dependency arrays to refresh when the limit changes.
Server acceptance and result-fetch limiting
components/webui/server/src/routes/api/search/index.ts, components/webui/server/src/routes/api/search/utils.ts, components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Native/SearchResultsVirtualTable/useSearchResults.ts
Server /query route accepts maxNumResults and defaults it, forwarding to job submission and signal updates. updateSearchSignalWhenJobsFinish destructures maxNumResults from props and applies it to result capping instead of a fixed constant. useSearchResults reads maxNumResults from store and applies it to cursor limit.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(webui): Add configurable max results limit to CLP search UI' accurately and concisely describes the main feature addition across the changeset.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
Contributor

@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

🤖 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
`@components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Native/SearchResultsVirtualTable/useSearchResults.ts`:
- Line 13: The hook in useSearchResults.ts currently destructures the entire
useSearchStore state with "const {searchJobId, maxNumResults} =
useSearchStore()", causing subscriptions to all state changes; change this to
selective Zustand selectors by calling useSearchStore with a selector function
that returns only searchJobId and maxNumResults (e.g., useSearchStore(s => ({
searchJobId: s.searchJobId, maxNumResults: s.maxNumResults }))) or two separate
calls to subscribe individually, so the component only re-renders when those
specific properties change; update references in the file to use the new
selector-returned values.

In `@components/webui/common/src/schemas/search.ts`:
- Line 18: The schema for maxNumResults currently only specifies
Type.Optional(Type.Integer({minimum: 1})); update the field to enforce an upper
bound of 10000 so callers cannot request unbounded results — e.g. change the
integer constraints to include maximum: 10000 while keeping the field optional
(modify the maxNumResults declaration in
components/webui/common/src/schemas/search.ts to use Type.Integer({minimum: 1,
maximum: 10000})).
🪄 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: cf3a14e3-ee5a-45fa-88fa-fd46c626a74e

📥 Commits

Reviewing files that changed from the base of the PR and between e1efedd and 139464f.

📒 Files selected for processing (16)
  • components/webui/client/src/components/QueryBox/index.module.css
  • components/webui/client/src/pages/SearchPage/SearchControls/Dataset/index.module.css
  • components/webui/client/src/pages/SearchPage/SearchControls/MaxResultsSelect/index.module.css
  • components/webui/client/src/pages/SearchPage/SearchControls/MaxResultsSelect/index.tsx
  • components/webui/client/src/pages/SearchPage/SearchControls/Native/NativeControls.tsx
  • components/webui/client/src/pages/SearchPage/SearchControls/Native/SearchButton/SubmitButton/index.tsx
  • components/webui/client/src/pages/SearchPage/SearchControls/TimeRangeInput/index.module.css
  • components/webui/client/src/pages/SearchPage/SearchControls/index.module.css
  • components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Native/SearchResultsVirtualTable/useSearchResults.ts
  • components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTimeline/Native/NativeResultsTimeline.tsx
  • components/webui/client/src/pages/SearchPage/SearchState/index.tsx
  • components/webui/client/src/pages/SearchPage/SearchState/typings.ts
  • components/webui/common/src/schemas/search.ts
  • components/webui/server/src/routes/api/search/index.ts
  • components/webui/server/src/routes/api/search/typings.ts
  • components/webui/server/src/routes/api/search/utils.ts

*/
const useSearchResults = () => {
const {searchJobId} = useSearchStore();
const {searchJobId, maxNumResults} = useSearchStore();
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.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify full-state Zustand subscriptions in SearchPage code.
rg -nP --type=ts --type=tsx 'useSearchStore\s*\(\s*\)' components/webui/client/src/pages/SearchPage

Repository: y-scope/clp

Length of output: 83


🏁 Script executed:

# First, let's read the target file to verify the code at line 13
cat -n components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Native/SearchResultsVirtualTable/useSearchResults.ts | head -30

Repository: y-scope/clp

Length of output: 1276


🏁 Script executed:

# Search for full-state Zustand subscriptions using correct file type flags
rg -nP --type=ts 'useSearchStore\s*\(\s*\)' components/webui/client/src/pages/SearchPage

Repository: y-scope/clp

Length of output: 1376


🏁 Script executed:

# Also search for useSearchStore definition to understand the store structure
fd -e ts -e tsx useSearchStore | head -5

Repository: y-scope/clp

Length of output: 37


🏁 Script executed:

# Find the SearchState index file to see useSearchStore definition
cat -n components/webui/client/src/pages/SearchPage/SearchState/index.ts | head -100

Repository: y-scope/clp

Length of output: 153


🏁 Script executed:

# Check if there are any examples of selective Zustand subscriptions in the codebase
rg -A2 'useSearchStore\s*\(\s*\(\s*state\s*\)' components/webui/client/src/pages/SearchPage

Repository: y-scope/clp

Length of output: 19282


🏁 Script executed:

# Also search broader for state selector patterns
rg '\(\s*state\s*\)\s*=>' components/webui/client/src/pages/SearchPage --type=ts --type=tsx -A1 | head -30

Repository: y-scope/clp

Length of output: 83


🏁 Script executed:

# Find the SearchState definition file with different extensions
fd -e js -e jsx -e ts -e tsx SearchState/index components/webui/client/src/pages/SearchPage

Repository: y-scope/clp

Length of output: 37


🏁 Script executed:

# Also search for the file in the parent SearchState directory
ls -la components/webui/client/src/pages/SearchPage/SearchState/

Repository: y-scope/clp

Length of output: 562


🏁 Script executed:

# Read the SearchState store definition to confirm Zustand usage
cat -n components/webui/client/src/pages/SearchPage/SearchState/index.tsx | head -80

Repository: y-scope/clp

Length of output: 2874


Use selective Zustand store subscriptions instead of full-state destructuring.

This hook subscribes to all store property changes when only searchJobId and maxNumResults are needed. Using selector functions limits re-renders to changes in those specific properties, improving performance and following the established pattern throughout the codebase.

Proposed refactor
-    const {searchJobId, maxNumResults} = useSearchStore();
+    const searchJobId = useSearchStore((state) => state.searchJobId);
+    const maxNumResults = useSearchStore((state) => state.maxNumResults);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const {searchJobId, maxNumResults} = useSearchStore();
const searchJobId = useSearchStore((state) => state.searchJobId);
const maxNumResults = useSearchStore((state) => state.maxNumResults);
🤖 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
`@components/webui/client/src/pages/SearchPage/SearchResults/SearchResultsTable/Native/SearchResultsVirtualTable/useSearchResults.ts`
at line 13, The hook in useSearchResults.ts currently destructures the entire
useSearchStore state with "const {searchJobId, maxNumResults} =
useSearchStore()", causing subscriptions to all state changes; change this to
selective Zustand selectors by calling useSearchStore with a selector function
that returns only searchJobId and maxNumResults (e.g., useSearchStore(s => ({
searchJobId: s.searchJobId, maxNumResults: s.maxNumResults }))) or two separate
calls to subscribe individually, so the component only re-renders when those
specific properties change; update references in the file to use the new
selector-returned values.

const QueryJobCreationSchema = Type.Object({
datasets: Type.Array(Type.String()),
ignoreCase: Type.Boolean(),
maxNumResults: Type.Optional(Type.Integer({minimum: 1})),
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add an upper bound for maxNumResults in the request schema.

minimum: 1 alone lets callers send unbounded limits (for example via direct API calls), which can drive expensive query and fetch paths. Please enforce the same ceiling used by product behaviour (10,000) at schema level.

Suggested patch
-    maxNumResults: Type.Optional(Type.Integer({minimum: 1})),
+    maxNumResults: Type.Optional(Type.Integer({
+        minimum: 1,
+        maximum: 10000,
+    })),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
maxNumResults: Type.Optional(Type.Integer({minimum: 1})),
maxNumResults: Type.Optional(Type.Integer({
minimum: 1,
maximum: 10000,
})),
🤖 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 `@components/webui/common/src/schemas/search.ts` at line 18, The schema for
maxNumResults currently only specifies Type.Optional(Type.Integer({minimum:
1})); update the field to enforce an upper bound of 10000 so callers cannot
request unbounded results — e.g. change the integer constraints to include
maximum: 10000 while keeping the field optional (modify the maxNumResults
declaration in components/webui/common/src/schemas/search.ts to use
Type.Integer({minimum: 1, maximum: 10000})).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant