Skip to content

feat(UI): timeout limit checkbox to remove query limits - BED-7032#2436

Open
catsiller wants to merge 65 commits intomainfrom
BED-7032--timeout-limit-checkbox-remove-query-limits
Open

feat(UI): timeout limit checkbox to remove query limits - BED-7032#2436
catsiller wants to merge 65 commits intomainfrom
BED-7032--timeout-limit-checkbox-remove-query-limits

Conversation

@catsiller
Copy link
Contributor

@catsiller catsiller commented Mar 2, 2026

Description

Required behaviors:

  1. When the timeout limit parameter is enabled: false, the Explore page Cypher query tab should display a checkbox allowing the user to remove query limits for that query execution.
  2. This control should only be visible when the timeout limit param is enabled: false and should default to unchecked.
  3. Checkbox and label should be to the left of the tag button and has a label clearly indicates its purpose (“Disable query timeout”)
  4. Selecting the checkbox signals that the query should run without query-limit enforcement.
  5. Once the checkbox is selected, it should preserve state across sessions. It should behave the same as "Auto Run Selected Query" (see screenshot below), which maintains its setting when users log out and back in.
  6. The query request must include the header prefer:wait=-1 header or equivalent
  7. Normal query-limit behavior applies (header is removed from cypher query)

Motivation and Context

Resolves https://specterops.atlassian.net/browse/BED-7032

Why is this change required? What problem does it solve?

How Has This Been Tested?

Added unit tests
Manual testing

  1. logging in and out and state of checkbox maintaining same state as when user logged out
  2. checking POST when checkbox is checked/unchecked
  3. checking POST after page refresh when checkbox is checked/unchecked

Reviewer: make sure timeout limit parameter is enabled: false in the DB

Screenshots (optional):

Types of changes

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Database Migrations

Checklist:

Summary by CodeRabbit

  • New Features

    • "Disable query timeout" checkbox added to Explore search (shown when server config allows); preference is persistable and surfaced across the UI.
    • New context/hook to manage the disable-query-limit setting.
  • Behavior

    • Query requests now honor the disable-timeout preference (via request settings) and toggling triggers a re-run to apply the change.
  • Tests

    • Added tests covering the conditional checkbox, persistence, and timeout-related request behavior.

@catsiller catsiller self-assigned this Mar 4, 2026
@catsiller catsiller added the user interface A pull request containing changes affecting the UI code. label Mar 4, 2026
@catsiller catsiller marked this pull request as ready for review March 4, 2026 16:49
@coderabbitai coderabbitai bot added enhancement New feature or request api A pull request containing changes affecting the API code. labels Mar 4, 2026
Copy link
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: 4

🧹 Nitpick comments (2)
packages/javascript/bh-shared-ui/src/views/Explore/providers/index.ts (1)

17-17: Prefer direct provider imports over expanding barrel exports.

Line 17 adds another provider barrel export; this can increase circular dependency risk in provider modules. Consider importing DisableQueryLimitProvider directly where needed unless this must be part of the package’s stable public surface.

Based on learnings: In the BloodHound codebase, prefer direct imports over barrel exports to avoid circular dependencies, especially for provider modules like SavedQueriesProvider.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/javascript/bh-shared-ui/src/views/Explore/providers/index.ts` at
line 17, Remove the barrel export for DisableQueryLimitProvider from the
providers index (the export statement exporting './DisableQueryLimitProvider')
to avoid expanding the barrel and potential circular deps; instead, delete that
export line from the file and update any modules that currently import it from
the providers barrel to import DisableQueryLimitProvider directly from its
module path (./DisableQueryLimitProvider) so only direct imports reference the
provider.
packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx (1)

94-103: useUserSettings can be simplified to a pure conditional return.

Current object mutation + delete works, but a direct return is clearer and easier to maintain.

♻️ Suggested refactor
 export const useUserSettings = () => {
     const { isDisableQueryLimit } = useDisableQueryLimitContext();
-
-    const settings: UserSettings = {
-        headers: { Prefer: '' },
-    };
-
-    if (isDisableQueryLimit) {
-        settings.headers = { Prefer: 'wait=-1' };
-    } else {
-        delete settings.headers;
-    }
-
-    return settings;
+    return isDisableQueryLimit ? { headers: { Prefer: 'wait=-1' } } : {};
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx`
around lines 94 - 103, The current settings object is created and then
mutated/deleted; simplify by returning the appropriate UserSettings directly
based on isDisableQueryLimit: if isDisableQueryLimit return { headers: { Prefer:
'wait=-1' } } otherwise return {} (or undefined) as the UserSettings value;
update the code around the settings: UserSettings declaration and usages
(referenced by settings and the isDisableQueryLimit flag) to remove the mutation
and delete flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/ui/src/ducks/global/reducer.ts`:
- Line 29: The reducer globalViewReducer currently initializes timeoutSetting
but never handles actions of type types.GLOBAL_SET_TIMEOUT_SETTING, so calls to
setTimeoutSetting(...) are ignored; add a case for
types.GLOBAL_SET_TIMEOUT_SETTING in globalViewReducer that returns a new state
with timeoutSetting set to the action payload (ensuring you read the boolean
from action.payload) so dispatched toggles update the store; reference the
globalViewReducer switch and the action type types.GLOBAL_SET_TIMEOUT_SETTING
and update state.timeoutSetting accordingly.

In `@cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx`:
- Around line 265-269: The test is a false negative because it calls setup()
before updating serverState and also renders the default (non‑Cypher) tab, so
the config‑gated "Disable query timeout" checkbox is never exercised; fix by
initializing serverState with setInitialServerState(savedConfigurationValue)
before calling setup() or by ensuring the Cypher tab is selected after setup()
so the checkbox render path runs (referencing the setup() helper, serverState
variable, and setInitialServerState(savedConfigurationValue) call in this test).

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`:
- Around line 142-144: The refetchFlag boolean is never cleared, so the if
(refetchFlag && cypherQuery !== '') { refetch(); } in CypherSearch.tsx continues
to cause extra refetches; after calling refetch() reset/clear refetchFlag (e.g.,
call the corresponding setter like setRefetchFlag(false) or invoke an
onRefetchHandled callback) so the flag only triggers a single refetch, and keep
the existing cypherQuery check (consider using cypherQuery.trim() !== '' if
needed).
- Around line 354-355: The visibility check for the timeout limit UI currently
uses a falsy check on timeoutLimitEnabled which shows the checkbox when the
config is undefined; update the condition to explicitly check for false (e.g.,
timeoutLimitEnabled === false) so only an explicit disabled setting renders the
element; locate the JSX around the timeoutLimitEnabled usage in the CypherSearch
component and replace the falsy conditional with the explicit equality check to
ensure undefined does not trigger visibility.

---

Nitpick comments:
In
`@packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx`:
- Around line 94-103: The current settings object is created and then
mutated/deleted; simplify by returning the appropriate UserSettings directly
based on isDisableQueryLimit: if isDisableQueryLimit return { headers: { Prefer:
'wait=-1' } } otherwise return {} (or undefined) as the UserSettings value;
update the code around the settings: UserSettings declaration and usages
(referenced by settings and the isDisableQueryLimit flag) to remove the mutation
and delete flow.

In `@packages/javascript/bh-shared-ui/src/views/Explore/providers/index.ts`:
- Line 17: Remove the barrel export for DisableQueryLimitProvider from the
providers index (the export statement exporting './DisableQueryLimitProvider')
to avoid expanding the barrel and potential circular deps; instead, delete that
export line from the file and update any modules that currently import it from
the providers barrel to import DisableQueryLimitProvider directly from its
module path (./DisableQueryLimitProvider) so only direct imports reference the
provider.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 7ee0ed68-62dc-4bc3-895a-d5b49eb7efc3

📥 Commits

Reviewing files that changed from the base of the PR and between ca8d3cb and 20b41a1.

📒 Files selected for processing (25)
  • cmd/ui/src/ducks/global/actions.ts
  • cmd/ui/src/ducks/global/reducer.ts
  • cmd/ui/src/ducks/global/types.ts
  • cmd/ui/src/store.ts
  • cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx
  • cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.tsx
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/aclInheritanceSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/compositionSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/cypherSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/nodeSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/pathfindingSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/relationshipSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/utils.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.test.tsx
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.test.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/QuerySearchFilter.test.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/types.ts
  • packages/javascript/bh-shared-ui/src/views/Explore/providers/DisableQueryLimitProvider/DisableQueryLimitContext.ts
  • packages/javascript/bh-shared-ui/src/views/Explore/providers/DisableQueryLimitProvider/DisableQueryLimitContextProvider.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/providers/DisableQueryLimitProvider/index.ts
  • packages/javascript/bh-shared-ui/src/views/Explore/providers/index.ts
  • packages/javascript/js-client-library/src/client.ts
  • packages/javascript/js-client-library/src/utils/config.ts
💤 Files with no reviewable changes (1)
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/SavedQueries/QuerySearchFilter.test.tsx

Copy link
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 the current code and only fix it if needed.

Inline comments:
In `@cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx`:
- Around line 260-263: The test currently asserts the config-gated checkbox
synchronously which can race the async config fetch in
useTimeoutLimitConfiguration()/useGetConfiguration(); update the assertion in
the test that calls setup('cypher') to await the checkbox with
screen.findByRole('checkbox', { name: /Disable query timeout/i }) instead of
screen.getByRole so the test waits for the element to appear after the async
config resolves.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`:
- Around line 135-145: The handler handleCypherSearch can call both
performSearch() and refetch() in one click when refetchFlag is true, causing
duplicate queries; change the control flow so only one execution path runs:
check the refetchFlag branch first and perform refetch() (and
setRefetchFlag(false)) when refetchFlag && cypherQuery !== '', otherwise call
performSearch() only when cypherQuery is set; update logic around performSearch,
refetchFlag, refetch, and setRefetchFlag to be mutually exclusive (e.g., if
(refetchFlag && cypherQuery !== '') { refetch(); setRefetchFlag(false); } else
if (cypherQuery) { performSearch(); }).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: fb99e667-8aec-48e3-99f4-288e9a067a2d

📥 Commits

Reviewing files that changed from the base of the PR and between 20b41a1 and 0a0978a.

📒 Files selected for processing (2)
  • cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx

Comment on lines 135 to +145
const handleCypherSearch = () => {
if (cypherQuery) {
performSearch();
}

// If query is selected and "Run", user refreshes page and clicks "Run" again (disable query limit checkbox checked or unchecked)
// If user presses "Run" and then checks or unchecks disable query limit checkbox and presses "Run" again
if (refetchFlag && cypherQuery !== '') {
refetch();
setRefetchFlag(false);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid issuing two query executions in one Run action.

Line 136 and Line 142 can both execute on the same click when refetchFlag is true, which risks duplicate requests and inconsistent final results.

🔧 Proposed fix (single execution path)
 const handleCypherSearch = () => {
-    if (cypherQuery) {
-        performSearch();
-    }
-
-    // If query is selected and "Run", user refreshes page and clicks "Run" again (disable query limit checkbox checked or unchecked)
-    // If user presses "Run" and then checks or unchecks disable query limit checkbox and presses "Run" again
-    if (refetchFlag && cypherQuery !== '') {
-        refetch();
-        setRefetchFlag(false);
-    }
+    if (cypherQuery !== '') {
+        if (refetchFlag) {
+            refetch();
+            setRefetchFlag(false);
+        } else {
+            performSearch();
+        }
+    }

     setMessageState((prev) => ({
         ...prev,
         showMessage: false,
     }));
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`
around lines 135 - 145, The handler handleCypherSearch can call both
performSearch() and refetch() in one click when refetchFlag is true, causing
duplicate queries; change the control flow so only one execution path runs:
check the refetchFlag branch first and perform refetch() (and
setRefetchFlag(false)) when refetchFlag && cypherQuery !== '', otherwise call
performSearch() only when cypherQuery is set; update logic around performSearch,
refetchFlag, refetch, and setRefetchFlag to be mutually exclusive (e.g., if
(refetchFlag && cypherQuery !== '') { refetch(); setRefetchFlag(false); } else
if (cypherQuery) { performSearch(); }).

Copy link
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.

♻️ Duplicate comments (1)
packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx (1)

135-149: ⚠️ Potential issue | 🟠 Major

Make the Run flow mutually exclusive to avoid double execution.

Line 136 runs performSearch(), and Line 142/Line 147 can also run refetch() in the same click path. That can execute two query paths for one Run action.

🔧 Proposed fix
 const handleCypherSearch = () => {
-    if (cypherQuery) {
-        performSearch();
-    }
-
-    // If query is selected and "Run", user refreshes page and clicks "Run" again (disable query limit checkbox checked or unchecked)
-    if (refetchFlag === false && cypherQuery !== '') {
-        refetch();
-    }
-
-    // If user presses "Run" and then checks or unchecks disable query limit checkbox and presses "Run" again (without updating the cypher)
-    if (refetchFlag && cypherQuery !== '') {
-        refetch();
-        setRefetchFlag(false);
-    }
+    if (cypherQuery !== '') {
+        if (refetchFlag) {
+            refetch();
+            setRefetchFlag(false);
+        } else {
+            performSearch();
+        }
+    }

     setMessageState((prev) => ({
         ...prev,
         showMessage: false,
     }));
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`
around lines 135 - 149, The current handleCypherSearch can call both
performSearch() and refetch() on one click, causing duplicate executions; change
the control flow so the actions are mutually exclusive: first guard that
cypherQuery is non-empty, then branch on refetchFlag using an if/else (or early
return) so that when refetchFlag is true you call refetch() and
setRefetchFlag(false), and when refetchFlag is false you call performSearch();
update handleCypherSearch to remove the overlapping calls and only invoke either
performSearch or refetch (references: handleCypherSearch, performSearch,
refetchFlag, refetch, setRefetchFlag, cypherQuery).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`:
- Around line 135-149: The current handleCypherSearch can call both
performSearch() and refetch() on one click, causing duplicate executions; change
the control flow so the actions are mutually exclusive: first guard that
cypherQuery is non-empty, then branch on refetchFlag using an if/else (or early
return) so that when refetchFlag is true you call refetch() and
setRefetchFlag(false), and when refetchFlag is false you call performSearch();
update handleCypherSearch to remove the overlapping calls and only invoke either
performSearch or refetch (references: handleCypherSearch, performSearch,
refetchFlag, refetch, setRefetchFlag, cypherQuery).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 1c0d26a0-edc0-4d5b-b6a5-248dc2d8040c

📥 Commits

Reviewing files that changed from the base of the PR and between 0a0978a and e5ae44f.

📒 Files selected for processing (2)
  • cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.test.tsx

Copy link
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.

Caution

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

⚠️ Outside diff range comments (1)
packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx (1)

135-155: ⚠️ Potential issue | 🟠 Major

Multiple query executions on single Run click.

The current logic can execute both performSearch() and refetch() in the same handler invocation:

  1. Line 137: performSearch() runs when cypherQuery is truthy
  2. Line 142: refetch() runs when refetchFlag === false && cypherQuery !== ''

On a normal Run click (where refetchFlag is false and query exists), both execute, causing duplicate requests.

🔧 Proposed fix (mutually exclusive execution paths)
 const handleCypherSearch = () => {
-    if (cypherQuery) {
-        performSearch();
-    }
-
-    // If query is selected and "Run", user refreshes page and clicks "Run" again (disable query limit checkbox checked or unchecked)
-    if (refetchFlag === false && cypherQuery !== '') {
-        refetch();
-    }
-
-    // If user presses "Run" and then checks or unchecks disable query limit checkbox and presses "Run" again (without updating the cypher)
-    if (refetchFlag && cypherQuery !== '') {
-        refetch();
-        setRefetchFlag(false);
-    }
+    if (cypherQuery !== '') {
+        if (refetchFlag) {
+            // Re-run with updated settings (e.g., disable query limit toggled)
+            refetch();
+            setRefetchFlag(false);
+        } else {
+            performSearch();
+        }
+    }

     setMessageState((prev) => ({
         ...prev,
         showMessage: false,
     }));
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`
around lines 135 - 155, The handler sometimes calls both performSearch() and
refetch(); make the branches mutually exclusive inside handleCypherSearch: first
check if cypherQuery is empty and return early; then use an if/else (or switch)
on refetchFlag so only one action runs (e.g., if refetchFlag === false -> call
refetch(); else -> call performSearch() and, if needed, call
setRefetchFlag(false) after). Update the conditions around performSearch,
refetch, and setRefetchFlag so they cannot all execute on one Run click (refer
to handleCypherSearch, performSearch, refetch, setRefetchFlag).
🧹 Nitpick comments (3)
packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx (2)

69-83: Unnecessary spread of userSettings into useQuery options.

Line 82 spreads userSettings (which contains headers) into the useQuery options object. However, react-query's useQuery doesn't use a headers property—headers are already correctly passed to the API client via queryFn in cypherSearchGraphQuery. This spread has no effect and may cause confusion.

♻️ Remove unnecessary spread
     return useQuery({
         ...queryConfig,
         onError: (error: any) => {
             const { message, key } = query.getErrorMessage(error);
             if (onError) {
                 onError(message);
             }

             addNotification(message, key, {
                 autoHideDuration: SNACKBAR_DURATION_LONG,
             });
         },
         ...rest,
-        ...userSettings,
     });
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx`
around lines 69 - 83, The spread of userSettings into the useQuery options is
unnecessary and potentially confusing because react-query's useQuery does not
consume a headers property; remove the spread of userSettings from the returned
useQuery call in useExploreGraph so that useQuery({...queryConfig, onError: ...,
...rest}) is used instead, leaving headers handling to
cypherSearchGraphQuery/queryFn where the API client already receives
userSettings; update the return in useExploreGraph (the useQuery invocation) to
omit ...userSettings.

92-107: Simplify useUserSettings by conditionally constructing the object.

Creating an object with headers, then deleting it is less efficient and harder to read than conditionally building the object.

♻️ Cleaner implementation
 export const useUserSettings = () => {
     const { isDisableQueryLimit } = useDisableQueryLimitContext();
     const timeoutLimitEnabled = useTimeoutLimitConfiguration();

-    const settings: UserSettings = {
-        headers: { Prefer: '' },
-    };
-
-    if (isDisableQueryLimit && timeoutLimitEnabled === false) {
-        settings.headers = { Prefer: 'wait=-1' };
-    } else {
-        delete settings.headers;
-    }
-
-    return settings;
+    if (isDisableQueryLimit && timeoutLimitEnabled === false) {
+        return { headers: { Prefer: 'wait=-1' } };
+    }
+
+    return {};
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx`
around lines 92 - 107, The useUserSettings function currently creates a settings
object with headers and then deletes headers conditionally; instead, construct
the UserSettings object only with headers when needed: inside useUserSettings
(which uses useDisableQueryLimitContext and useTimeoutLimitConfiguration) build
and return either { headers: { Prefer: 'wait=-1' } } when isDisableQueryLimit &&
timeoutLimitEnabled === false, or an empty object (or {} as UserSettings)
otherwise, ensuring the returned type matches UserSettings and removing the
initial assignment + delete flow.
packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx (1)

127-133: Consider simplifying the conditional.

The if-else can be reduced to a single assignment since disableQueryLimit is already a boolean.

♻️ Simplified version
-        if (disableQueryLimit) {
-            setIsDisableQueryLimit(true);
-        } else {
-            setIsDisableQueryLimit(false);
-        }
+        setIsDisableQueryLimit(disableQueryLimit);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`
around lines 127 - 133, The if/else that sets state based on disableQueryLimit
is verbose; replace the conditional block with a direct assignment using
setIsDisableQueryLimit(disableQueryLimit) (or Boolean(disableQueryLimit) if you
want to coerce), inside the same effect where disableQueryLimit and
setIsDisableQueryLimit are referenced, removing the redundant if-else.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`:
- Around line 135-155: The handler sometimes calls both performSearch() and
refetch(); make the branches mutually exclusive inside handleCypherSearch: first
check if cypherQuery is empty and return early; then use an if/else (or switch)
on refetchFlag so only one action runs (e.g., if refetchFlag === false -> call
refetch(); else -> call performSearch() and, if needed, call
setRefetchFlag(false) after). Update the conditions around performSearch,
refetch, and setRefetchFlag so they cannot all execute on one Run click (refer
to handleCypherSearch, performSearch, refetch, setRefetchFlag).

---

Nitpick comments:
In
`@packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx`:
- Around line 69-83: The spread of userSettings into the useQuery options is
unnecessary and potentially confusing because react-query's useQuery does not
consume a headers property; remove the spread of userSettings from the returned
useQuery call in useExploreGraph so that useQuery({...queryConfig, onError: ...,
...rest}) is used instead, leaving headers handling to
cypherSearchGraphQuery/queryFn where the API client already receives
userSettings; update the return in useExploreGraph (the useQuery invocation) to
omit ...userSettings.
- Around line 92-107: The useUserSettings function currently creates a settings
object with headers and then deletes headers conditionally; instead, construct
the UserSettings object only with headers when needed: inside useUserSettings
(which uses useDisableQueryLimitContext and useTimeoutLimitConfiguration) build
and return either { headers: { Prefer: 'wait=-1' } } when isDisableQueryLimit &&
timeoutLimitEnabled === false, or an empty object (or {} as UserSettings)
otherwise, ensuring the returned type matches UserSettings and removing the
initial assignment + delete flow.

In
`@packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx`:
- Around line 127-133: The if/else that sets state based on disableQueryLimit is
verbose; replace the conditional block with a direct assignment using
setIsDisableQueryLimit(disableQueryLimit) (or Boolean(disableQueryLimit) if you
want to coerce), inside the same effect where disableQueryLimit and
setIsDisableQueryLimit are referenced, removing the redundant if-else.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: c1417762-7b63-4590-a040-755c1f6cd199

📥 Commits

Reviewing files that changed from the base of the PR and between 91e0849 and 867ccc9.

📒 Files selected for processing (3)
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/queries/cypherSearch.ts
  • packages/javascript/bh-shared-ui/src/hooks/useExploreGraph/useExploreGraph.tsx
  • packages/javascript/bh-shared-ui/src/views/Explore/ExploreSearch/CypherSearch.tsx

Comment on lines +119 to +122
console.log(timeoutLimitEnabled);

console.log(disableQueryLimit);

Copy link
Contributor

Choose a reason for hiding this comment

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

These got through

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah good catch, removed!

Comment on lines +119 to +122
console.log(timeoutLimitEnabled);

console.log(disableQueryLimit);

Copy link
Contributor

Choose a reason for hiding this comment

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

They slipped through

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah good catch, removed!

disabled={cypherSearchIsRunning}
aria-label='Run cypher query'
className={cn({
'bg-slate-600 max-w-[83px] hover:bg-slate-700': cypherSearchIsRunning,
Copy link
Contributor

Choose a reason for hiding this comment

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

We might not have the exact color in the themes, but wonder if we should get the closest tokenized one from our theme design/system instead of using a color utility class directly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i dont see a similar variant in the DUI colors 🤔 maybe a good idea to get that added into the design system and come back/replace this

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

Labels

api A pull request containing changes affecting the API code. enhancement New feature or request user interface A pull request containing changes affecting the UI code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants