Skip to content

EDM-3204: Do not allow invalid search values for name/alias fields#579

Open
celdrake wants to merge 1 commit intoflightctl:mainfrom
celdrake:EDM-3204-invalid-search
Open

EDM-3204: Do not allow invalid search values for name/alias fields#579
celdrake wants to merge 1 commit intoflightctl:mainfrom
celdrake:EDM-3204-invalid-search

Conversation

@celdrake
Copy link
Collaborator

@celdrake celdrake commented Mar 18, 2026

Fields for "search by name" should not accept spaces as the API responses return error 400.

no-space-field

Summary by CodeRabbit

  • New Features
    • Search input now blocks spaces and shows a localized error message when spaces are entered (new English translation added).
  • Accessibility
    • Improved accessibility attributes for device tables' switches so assistive tech reports their checked state.

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

Walkthrough

Refactors TableTextSearch to add internal state and validation preventing spaces in search input, exposes setValue to parent, and shows a localized error message. Adds a new English translation key. Adds aria-checked attributes to two device table switches for accessibility.

Changes

Cohort / File(s) Summary
Translations
libs/i18n/locales/en/translation.json
Added key: "Search value cannot contain spaces".
Search input component
libs/ui-components/src/components/Table/TableTextSearch.tsx
Reworked to internal state (actualValue, hasError), added whitespace validation (blocks spaces), handleChange/handleClear handlers, effect to reset internal state when external value clears, removed onClear from props, uses i18n string and renders conditional HelperText error.
Accessibility tweaks — Device tables
libs/ui-components/src/components/Device/DevicesPage/DecommissionedDevicesTable.tsx, libs/ui-components/src/components/Device/DevicesPage/EnrolledDevicesTable.tsx
Added aria-checked attribute to the Show decommissioned devices and enrolled devices Switch components (accessibility only).

Sequence Diagram(s)

sequenceDiagram
participant User as User
participant TableSearch as TableTextSearch
participant SearchInput as SearchInput
participant Parent as ParentComponent
participant I18n as i18n

User->>SearchInput: type input
SearchInput->>TableSearch: onChange(value)
TableSearch->>TableSearch: validate (contains spaces?)
alt contains spaces
    TableSearch->>TableSearch: set hasError = true, actualValue = value
    TableSearch->>I18n: get "Search value cannot contain spaces"
    TableSearch->>SearchInput: render error (HelperText)
    TableSearch-->>Parent: (do not call setValue with invalid value)
else valid
    TableSearch->>TableSearch: set hasError = false, actualValue = value
    TableSearch->>Parent: setValue(value)
end
User->>TableSearch: click clear
TableSearch->>TableSearch: handleClear -> actualValue = '', hasError = false
TableSearch->>Parent: setValue('')
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'EDM-3204: Do not allow invalid search values for name/alias fields' accurately and clearly summarizes the main change: preventing spaces in search fields for name/alias. It directly aligns with the core objective shown in the PR description and the changes across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

@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 (1)
libs/ui-components/src/components/Table/TableTextSearch.tsx (1)

15-21: Consider syncing with all external value changes, not just empty.

The effect only resets state when value === ''. If a parent component ever sets a non-empty value programmatically, actualValue won't sync. Current usage patterns only clear to empty, so this works, but for robustness consider:

Optional: Full sync with external value
  React.useEffect(() => {
-   // When the value is cleared externally, reset the component state
-   if (value === '') {
-     setActualValue('');
+   // Sync with external value changes
+   if (value !== undefined) {
+     setActualValue(value);
      setHasError(false);
    }
  }, [value]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/ui-components/src/components/Table/TableTextSearch.tsx` around lines 15
- 21, The effect in TableTextSearch.tsx currently only resets state when value
=== '' causing actualValue to become out of sync when a parent sets a non-empty
value; update the React.useEffect watching value to synchronize actualValue with
value on any external change (e.g., if value !== actualValue then call
setActualValue(value)) and clear validation state as appropriate
(setHasError(false) or similar) so the component mirrors external updates;
target the useEffect that references value, and the state setters setActualValue
and setHasError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@libs/ui-components/src/components/Table/TableTextSearch.tsx`:
- Around line 48-58: The SearchInput spread order allows callers to override
internal handlers: move the {...rest} spread before the explicit props in
TableTextSearch so internal handlers win; specifically, in the TableTextSearch
return JSX place {...rest} before aria-label={placeholder},
onChange={handleChange}, value={actualValue}, placeholder={placeholder}, and
onClear={handleClear} so handleClear continues to reset error state and
handleChange/other props aren’t accidentally overridden.

---

Nitpick comments:
In `@libs/ui-components/src/components/Table/TableTextSearch.tsx`:
- Around line 15-21: The effect in TableTextSearch.tsx currently only resets
state when value === '' causing actualValue to become out of sync when a parent
sets a non-empty value; update the React.useEffect watching value to synchronize
actualValue with value on any external change (e.g., if value !== actualValue
then call setActualValue(value)) and clear validation state as appropriate
(setHasError(false) or similar) so the component mirrors external updates;
target the useEffect that references value, and the state setters setActualValue
and setHasError.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 007c4259-e342-40c9-af41-956b7062e93a

📥 Commits

Reviewing files that changed from the base of the PR and between d7b8a07 and d232beb.

📒 Files selected for processing (2)
  • libs/i18n/locales/en/translation.json
  • libs/ui-components/src/components/Table/TableTextSearch.tsx

@celdrake celdrake force-pushed the EDM-3204-invalid-search branch from d232beb to f032c85 Compare March 18, 2026 15:16
<Switch
id="decommissioned-devices-switch"
label={<span className="fctl-switch__label">{t('Show decommissioned devices')}</span>}
aria-checked
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Adds the required accessibility field for checkboxes (same for the enrolledDevicesTable)

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.

🧹 Nitpick comments (1)
libs/ui-components/src/components/Table/TableTextSearch.tsx (1)

15-21: External non-empty value changes are not synchronized to internal state.

The useEffect only resets actualValue when value === ''. When a parent component like FleetsPage updates the value prop to a non-empty string (e.g., via URL search parameters), actualValue won't update to reflect it. This causes the input to display a stale value while the parent state has moved on.

For example, in FleetsPage, when the URL changes from ?name=abc to ?name=xyz, the name prop updates but actualValue remains at 'abc', creating a desynchronization.

Consider syncing on all external value changes:

Suggested refactor
  React.useEffect(() => {
-   // When the value is cleared externally, reset the component state
-   if (value === '') {
-     setActualValue('');
-     setHasError(false);
-   }
+   // Sync internal state when external value changes
+   if (value !== undefined && value !== actualValue) {
+     setActualValue(value);
+     setHasError(value.includes(' '));
+   }
  }, [value]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@libs/ui-components/src/components/Table/TableTextSearch.tsx` around lines 15
- 21, The effect in the TableTextSearch component only resets internal state
when value === '' so external non-empty updates (e.g., from FleetsPage/URL
params) aren't reflected; change the useEffect that currently watches [value] to
setActualValue(value) on any change (and also setHasError(false) when
appropriate) so the internal actualValue always syncs to the incoming prop value
instead of only clearing on empty strings; update the effect referencing
actualValue/setActualValue/hasError/setHasError in TableTextSearch accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@libs/ui-components/src/components/Table/TableTextSearch.tsx`:
- Around line 15-21: The effect in the TableTextSearch component only resets
internal state when value === '' so external non-empty updates (e.g., from
FleetsPage/URL params) aren't reflected; change the useEffect that currently
watches [value] to setActualValue(value) on any change (and also
setHasError(false) when appropriate) so the internal actualValue always syncs to
the incoming prop value instead of only clearing on empty strings; update the
effect referencing actualValue/setActualValue/hasError/setHasError in
TableTextSearch accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc9e1bc6-d8cf-434f-9c6e-5f4ec8e12c37

📥 Commits

Reviewing files that changed from the base of the PR and between d232beb and f032c85.

📒 Files selected for processing (4)
  • libs/i18n/locales/en/translation.json
  • libs/ui-components/src/components/Device/DevicesPage/DecommissionedDevicesTable.tsx
  • libs/ui-components/src/components/Device/DevicesPage/EnrolledDevicesTable.tsx
  • libs/ui-components/src/components/Table/TableTextSearch.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/i18n/locales/en/translation.json

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