Skip to content

refactor(network): floating IPs UI/UX Improvements#703

Draft
vlad-schur-external-sap wants to merge 11 commits intomainfrom
vlad-floatingip-uiux-tweaks
Draft

refactor(network): floating IPs UI/UX Improvements#703
vlad-schur-external-sap wants to merge 11 commits intomainfrom
vlad-floatingip-uiux-tweaks

Conversation

@vlad-schur-external-sap
Copy link
Copy Markdown
Contributor

@vlad-schur-external-sap vlad-schur-external-sap commented Apr 15, 2026

Summary

Addressed a set of UI improvements and interaction fixes for the Floating IPs list and detail pages, including layout corrections, accessibility enhancements, and DataGrid row interactivity.

Changes Made

  • Changes from UI/UX improvements issue
  • Migrated search in ListToolbar from custom debounce to the one integrated in TanStack/forms
  • Small performance changes like lazy-loading modals inside sec-groups
  • Changed nesting inside client/network directories, as there were a lot of router duplicates
    • Moved separate components related to SecurityGroups directly under the SecurityGroups/components directory
  • Fixed externalNetwork request as schema was too strict for optional fields

Related Issues

Testing Instructions

  1. pnpm i
  2. pnpm run test

Checklist

  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have made corresponding changes to the documentation (if applicable).
  • My changes generate no new warnings or errors.

Summary by CodeRabbit

  • New Features

    • Clickable Floating IP table rows to open details.
  • Bug Fixes

    • Allocation form selects disable correctly while loading.
    • Description fields show “—” when empty.
    • Route guards redirect away from network pages when services are unavailable.
  • Refactor

    • Search now uses a debounced form field.
    • Sort controls simplified and inlined in list toolbars; legacy sort component removed.
    • Floating IP details no longer include breadcrumbs.
  • Style

    • Primary action uses the primary variant; minor utility class updates.
  • Accessibility

    • Filter control label changed to “Filter by”.

@vlad-schur-external-sap vlad-schur-external-sap requested a review from a team as a code owner April 15, 2026 10:25
@vlad-schur-external-sap vlad-schur-external-sap marked this pull request as draft April 15, 2026 10:25
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

📝 Walkthrough

Walkthrough

Refactors ListToolbar search to use @tanstack/react-form; removes SortInput and inlines sort controls; converts Floating IP details from DataGrid to DescriptionList with explicit fallbacks; adds row-level navigation for floating IPs; adds route-level beforeLoad guards and updates generated routeTree; assorted import, test, and UI tweaks.

Changes

Cohort / File(s) Summary
ListToolbar search & sort
apps/aurora-portal/src/client/components/ListToolbar/index.tsx, apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx
Replaced manual debounced search with a form.Field (onChangeDebounceMs: 500); removed searchInputProps; inlined Select + SortButton for sort controls; updated tests (async waitFor, special-character sort option test).
SortInput removal
apps/aurora-portal/src/client/components/ListToolbar/SortInput.tsx, apps/aurora-portal/src/client/components/ListToolbar/SortInput.test.tsx
Removed SortInput component and its test suite.
Filter label update
apps/aurora-portal/src/client/components/ListToolbar/FiltersInput.tsx, apps/aurora-portal/src/client/routes/.../securitygroups/-components/-details/SecurityGroupRulesTable.test.tsx
Changed filter select label from t\Filters`tot`Filter by`` and updated tests to query by new label.
Floating IP details & tests
apps/aurora-portal/src/client/routes/.../floatingips/-components/-details/FloatingIpDetailsView.tsx, .../FloatingIpDetailsView.test.tsx
Replaced DataGrid layout with DescriptionList terms/definitions; always render Description with em-dash fallback; use optional chaining/fallbacks for network/router/port-forwarding fields; tests updated accordingly.
Floating IP routes & routeTree
apps/aurora-portal/src/client/routes/.../network/floatingips/index.tsx, apps/aurora-portal/src/client/routes/.../network/floatingips.tsx, apps/aurora-portal/src/client/routeTree.gen.ts
Added beforeLoad guards that fetch trpcClient.auth.getAvailableServices and conditionally redirect; removed some file-route modules; updated generated routeTree path/parent wiring and aggregated network children typing.
Floating IP table & allocate modal
apps/aurora-portal/src/client/routes/.../floatingips/-components/-table/FloatingIpTableRow.tsx, .../FloatingIps.tsx, .../-modals/AllocateFloatingIpModal.tsx
Enabled row-level navigation on DataGridRow (action cell stops propagation); changed Allocate button variant to primary; adjusted Select disable logic to depend on isPending/loading flags and marked External Network select as required.
Route file cleanup
apps/aurora-portal/src/client/routes/.../$floatingIpId.tsx
Removed breadcrumb rendering and unused navigate-to-network callback; render path now returns FloatingIpDetailsView when data present.
Security groups list & modal imports / modal hook
apps/aurora-portal/src/client/routes/.../securitygroups/-components/-table/*
Adjusted several import paths for container/modals; switched modal state from local booleans to useModal hook and ensured single delete dialog instance; updated related tests' mock paths.
Generated route type updates
apps/aurora-portal/src/client/routeTree.gen.ts
Removed network parent-route entries and updated child route path/parentRoute metadata; added aggregated NetworkRouteChildren interface and removed per-child children interfaces.
Misc UI / tests / styling
apps/aurora-portal/src/client/components/ListToolbar/FiltersInput.tsx, apps/aurora-portal/src/client/components/navigation/MainNavigation.tsx, apps/aurora-portal/src/server/Compute/helpers/imageHelpers.test.ts, apps/aurora-portal/src/server/Network/types/network.ts
Small changes: filter label text, replace Tailwind flex-shrink-0shrink-0, tweak a mocked ZodError input value, and make several network schema fields nullable/optional and port_security_enabled optional.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Router as Route.beforeLoad
  participant TRPC as trpcClient.auth
  participant App as Component
  User->>Router: navigate to /network/(securitygroups|floatingips)
  Router->>TRPC: getAvailableServices.query()
  TRPC-->>Router: availableServices
  alt network service missing
    Router->>User: redirect to /accounts/$accountId/projects
  else neutron missing
    Router->>User: redirect to /accounts/$accountId/projects/$projectId/network/overview
  else
    Router->>App: allow route load → render component
  end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

Suggested Labels

network, aurora-portal

Suggested Reviewers

  • KirylSAP
  • TilmanHaupt

Poem

🐰 I hop through code with tiny paws,

Debounced fields now follow laws,
Sorts inline and rows that roam,
Routes that guard the network home,
A carrot for tests — I celebrate the cause! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The pull request description is largely incomplete and off-topic, containing only placeholder text and missing substantive details about the changes. Fill in the 'Summary' section with a clear explanation of the PR's purpose. Replace placeholder 'Change 1-3' items with actual changes. Replace placeholder 'Issue 1' with the real issue number (691). Add screenshots if applicable. Check all relevant checklist items based on actual work completed.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor(network): floating IPs UI/UX Improvements' accurately summarizes the main changes across the pull request, which focus on floating IP interface improvements, ListToolbar refactoring, and related UI component updates.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch vlad-floatingip-uiux-tweaks

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.

@vlad-schur-external-sap vlad-schur-external-sap linked an issue Apr 15, 2026 that may be closed by this pull request
12 tasks
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

UI/UX refactor for Network-related views, consolidating sort/search/filter controls into the shared ListToolbar and updating Floating IP list/detail presentation accordingly.

Changes:

  • Refactored ListToolbar to inline sort controls and debounce search via @tanstack/react-form; updated filter label to “Filter by”.
  • Updated Floating IP list/detail UI (primary allocate button, clickable rows, details view switched from DataGrid to DescriptionList; details route breadcrumb removed).
  • Updated/added tests to align with the new toolbar and UI labels/structures.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/aurora-portal/src/server/Compute/helpers/imageHelpers.test.ts Updates Zod error expectation shape (received vs input).
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/$securityGroupId/-components/-details/SecurityGroupRulesTable.test.tsx Updates test label to match “Filter by”.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/FloatingIps.tsx Primary styling for Allocate button.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx Makes rows clickable to navigate; adjusts actions cell styling.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx Tweaks select disabled/required behavior for allocation form.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-details/FloatingIpDetailsView.tsx Switches details layout to DescriptionList-based presentation.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-details/FloatingIpDetailsView.test.tsx Updates tests for DescriptionList layout and em-dash fallback.
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/$floatingIpId.tsx Removes breadcrumb wrapper; keeps loading/error states.
apps/aurora-portal/src/client/components/navigation/MainNavigation.tsx Tailwind class normalization (flex-shrink-0shrink-0).
apps/aurora-portal/src/client/components/ListToolbar/index.tsx Major refactor: inline sort UI + debounced search via react-form; removes searchInputProps.
apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx Adjusts tests for debounce + adds coverage for special-character sort keys.
apps/aurora-portal/src/client/components/ListToolbar/SortInput.tsx Removes standalone SortInput component (functionality moved into ListToolbar).
apps/aurora-portal/src/client/components/ListToolbar/SortInput.test.tsx Removes SortInput tests (now covered via ListToolbar tests).
apps/aurora-portal/src/client/components/ListToolbar/FiltersInput.tsx Renames filter select label to “Filter by”.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to +59
const form = useForm({
defaultValues: {
search: searchTerm ?? "",
},
})
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

useForm({ defaultValues: { search: searchTerm ?? "" } }) only seeds the initial value; when the searchTerm prop changes (e.g., URL-driven search params in Swift Containers), the SearchInput will stay stale because the form state is not synchronized. Consider adding a useEffect that updates/resets the search field when searchTerm changes (without triggering onSearch again) so the toolbar remains controlled from the outside.

Copilot uses AI. Check for mistakes.
Comment on lines +173 to +181
<SearchInput
id={field.name}
name={field.name}
value={field.state.value}
onInput={(e) => field.handleChange(e.currentTarget.value)}
onClear={handleSearchClear}
placeholder={t`Search...`}
data-testid="searchbar"
/>
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

The toolbar no longer passes a search-submit handler to SearchInput (previously onSearch existed). As a result, the Search button/Enter action may no longer trigger an immediate search (only the debounced field-change does). Please wire SearchInput’s submit/search event (or wrap it in a form with onSubmit) so explicit user search actions still call onSearch immediately.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@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 `@apps/aurora-portal/src/client/components/ListToolbar/index.tsx`:
- Around line 164-184: The SearchInput in the form.Field children render is
missing the onSearch prop so clicking its search button doesn't trigger an
immediate lookup; update the SearchInput invocation inside the children callback
to pass an onSearch handler that calls the existing onSearch prop with the
current field value (use field.state.value) so a button click invokes onSearch
immediately (in addition to the existing debounced onChange and
onClear/handleSearchClear wiring).
- Around line 55-59: The form's defaultValues (useForm) only initialize on mount
so add a syncing effect: create a useEffect that watches the searchTerm prop and
calls form.setValue('search', searchTerm ?? '') (or form.reset({ search:
searchTerm ?? "" }) if you want to reset other fields) to update the TanStack
form state when searchTerm changes; ensure you import React's useEffect and
reference the existing form and searchTerm identifiers.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 95383667-4819-4bcb-b2f4-8608a14be54b

📥 Commits

Reviewing files that changed from the base of the PR and between cc7df5a and f900f06.

📒 Files selected for processing (14)
  • apps/aurora-portal/src/client/components/ListToolbar/FiltersInput.tsx
  • apps/aurora-portal/src/client/components/ListToolbar/SortInput.test.tsx
  • apps/aurora-portal/src/client/components/ListToolbar/SortInput.tsx
  • apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx
  • apps/aurora-portal/src/client/components/ListToolbar/index.tsx
  • apps/aurora-portal/src/client/components/navigation/MainNavigation.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/$floatingIpId.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-details/FloatingIpDetailsView.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-details/FloatingIpDetailsView.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/-components/FloatingIps.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/$securityGroupId/-components/-details/SecurityGroupRulesTable.test.tsx
  • apps/aurora-portal/src/server/Compute/helpers/imageHelpers.test.ts
💤 Files with no reviewable changes (2)
  • apps/aurora-portal/src/client/components/ListToolbar/SortInput.test.tsx
  • apps/aurora-portal/src/client/components/ListToolbar/SortInput.tsx

Comment on lines +55 to +59
const form = useForm({
defaultValues: {
search: searchTerm ?? "",
},
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if any callers update searchTerm after initial render (e.g., from URL params)
rg -n "searchTerm.*=.*useSearch|searchTerm.*=.*useState|setSearchTerm" --type=ts --type=tsx -g '!*.test.*' apps/aurora-portal/src/client/routes/

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 102


🏁 Script executed:

#!/bin/bash
# First, let's find the ListToolbar component and see its prop definition
cat -n apps/aurora-portal/src/client/components/ListToolbar/index.tsx | head -80

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 2856


🏁 Script executed:

#!/bin/bash
# Search for where ListToolbar is imported and used
rg -n "ListToolbar" --type=ts apps/aurora-portal/src/client/ -g '!*.test.*' | head -20

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 3680


🏁 Script executed:

#!/bin/bash
# Look for searchTerm prop usage/definition in route files
rg -n "searchTerm" --type=ts apps/aurora-portal/src/client/routes/ -g '!*.test.*' -B 2 -A 2

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 43123


🏁 Script executed:

#!/bin/bash
# Get more of the ListToolbar component to see how form fields are used
cat -n apps/aurora-portal/src/client/components/ListToolbar/index.tsx | sed -n '100,200p'

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 4621


🏁 Script executed:

#!/bin/bash
# Check if there are any useEffect hooks in ListToolbar that handle prop changes
cat -n apps/aurora-portal/src/client/components/ListToolbar/index.tsx | grep -A 10 "useEffect"

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check the entire ListToolbar component for any effect hooks or prop sync logic
wc -l apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 141


🏁 Script executed:

#!/bin/bash
# Get the complete file to check for useEffect
cat apps/aurora-portal/src/client/components/ListToolbar/index.tsx | tail -100

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 3676


🏁 Script executed:

#!/bin/bash
# Look at a parent component that passes dynamic searchTerm to see the actual usage pattern
cat -n apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/storage/-components/Swift/Containers/index.tsx | grep -B 5 -A 5 "searchParam"

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 216


🏁 Script executed:

#!/bin/bash
# Find the Containers component file
find apps/aurora-portal/src/client/routes -name "Containers/index.tsx" | head -1

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

#!/bin/bash
# Check where searchParam is defined and how it's set
rg -n "searchParam" apps/aurora-portal/src/client/routes/_auth/accounts -A 3 -B 3 | head -80

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 12186


🏁 Script executed:

#!/bin/bash
# Check if TanStack Form's useForm initializes defaultValues only once
# by looking at how it handles prop changes - search for any existing patterns
rg -n "defaultValues" apps/aurora-portal/src/client/components/ -A 5 -B 2 | head -100

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 724


🏁 Script executed:

#!/bin/bash
# Check the actual route handler to see if it's truly dynamic (URL changes trigger re-render)
cat -n apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/storage/-components/Swift/Objects/index.tsx | sed -n '160,180p'

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 213


🏁 Script executed:

#!/bin/bash
# Find the actual Swift Objects component path
find apps/aurora-portal/src/client/routes -path "*Swift/Objects/index.tsx" -type f

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 201


🏁 Script executed:

#!/bin/bash
# Check how handleSearchChange is implemented in a parent component
rg -n "handleSearchChange" apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/storage -A 3 -B 1 | head -50

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 185


🏁 Script executed:

#!/bin/bash
# Get the Swift Objects component and look for handleSearchChange
cat "apps/aurora-portal/src/client/routes/_auth/accounts/\$accountId/projects/\$projectId/storage/-components/Swift/Objects/index.tsx" | grep -n "handleSearchChange" -A 3 -B 1

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 514


🏁 Script executed:

#!/bin/bash
# Let's check if TanStack React Form handles dynamic defaultValues
# by looking at the library documentation or usage patterns
rg -n "useForm" apps/aurora-portal/src/client/components/ListToolbar/index.tsx -A 10 -B 2

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 772


🏁 Script executed:

#!/bin/bash
# Check if there's any reset or field update logic when props change
rg -n "form\.reset|form\.setFieldValue|form\.getFieldValue" apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 115


🏁 Script executed:

#!/bin/bash
# Check TanStack Router behavior - does it remount or rerender when params change?
# Look at how the component is structured
cat "apps/aurora-portal/src/client/routes/_auth/accounts/\$accountId/projects/\$projectId/storage/-components/Swift/Objects/index.tsx" | head -50

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1999


🏁 Script executed:

#!/bin/bash
# Verify: Does the parent actually update searchTerm after initial mount?
# Check if there's any scenario where searchTerm changes without remounting
rg -n "Route.useSearch" apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects -A 5 | head -40

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 176


🏁 Script executed:

#!/bin/bash
# Check if TanStack React Form handles defaultValues updates
# by examining the actual field rendering and form behavior
cat "apps/aurora-portal/src/client/routes/_auth/accounts/\$accountId/projects/\$projectId/storage/-components/Swift/Objects/index.tsx" | sed -n '160,175p'

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 832


🏁 Script executed:

#!/bin/bash
# Check if component is remounted or just re-rendered on URL change
# Look for key prop or other remount indicators
rg -n "ListToolbar|Form|useForm|defaultValues" apps/aurora-portal/src/client/components/ListToolbar/ -B 2 -A 2

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 5115


🏁 Script executed:

#!/bin/bash
# Test: Check TanStack Form documentation behavior with defaultValues
# by looking at actual implementation - does it update on prop changes?
python3 << 'EOF'
# TanStack React Form behavior: defaultValues only initialize once on mount
# They do NOT automatically update when the prop changes
# This is standard form library behavior
print("TanStack React Form behavior:")
print("- useForm({ defaultValues }) initializes form state once on mount")
print("- Changing defaultValues prop does NOT update the form's internal state")
print("- Must explicitly use form.setFieldValue() or form.reset() to sync prop changes")
print("\nConclusion: The concern is VALID - form state can become stale if searchTerm prop changes")
EOF

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 413


Form's search field state won't sync when searchTerm prop updates after mount.

TanStack React Form's defaultValues only initialize once on component mount. If the parent component updates the searchTerm prop (e.g., from URL params via external navigation), the form's internal state won't reflect the new value. This causes the search input to display stale data when the URL changes externally (browser back/forward, navigation from another page, etc.).

Add a useEffect to sync prop changes to the form:

🛠️ Suggested approach
+ import { useEffect } from "react"
  // ...
  const form = useForm({
    defaultValues: {
      search: searchTerm ?? "",
    },
  })

+ useEffect(() => {
+   if (searchTerm !== undefined && searchTerm !== form.getFieldValue("search")) {
+     form.setFieldValue("search", searchTerm)
+   }
+ }, [searchTerm, form])
📝 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 form = useForm({
defaultValues: {
search: searchTerm ?? "",
},
})
import { useCallback } from "react"
import { useEffect } from "react"
// ... other imports ...
const form = useForm({
defaultValues: {
search: searchTerm ?? "",
},
})
useEffect(() => {
if (searchTerm !== undefined && searchTerm !== form.getFieldValue("search")) {
form.setFieldValue("search", searchTerm)
}
}, [searchTerm, form])
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/aurora-portal/src/client/components/ListToolbar/index.tsx` around lines
55 - 59, The form's defaultValues (useForm) only initialize on mount so add a
syncing effect: create a useEffect that watches the searchTerm prop and calls
form.setValue('search', searchTerm ?? '') (or form.reset({ search: searchTerm ??
"" }) if you want to reset other fields) to update the TanStack form state when
searchTerm changes; ensure you import React's useEffect and reference the
existing form and searchTerm identifiers.

Comment on lines +164 to 184
{onSearch && (
<div className="w-full md:ml-auto md:w-auto md:min-w-25">
<SearchInput {...searchProps} />
<form.Field
name="search"
listeners={{
onChangeDebounceMs: 500,
onChange: ({ value }) => onSearch?.(value),
}}
children={(field) => (
<SearchInput
id={field.name}
name={field.name}
value={field.state.value}
onInput={(e) => field.handleChange(e.currentTarget.value)}
onClear={handleSearchClear}
placeholder={t`Search...`}
data-testid="searchbar"
/>
)}
/>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check SearchInput component API for onSearch prop
ast-grep --pattern 'export $_ SearchInput = $_($$$)'
rg -n "onSearch" --type=ts -A3 -B3 "juno-ui-components"

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 133


🏁 Script executed:

# First, find the ListToolbar file and see the imports
grep -n "SearchInput" /dev/stdin << 'EOF'
$(head -50 apps/aurora-portal/src/client/components/ListToolbar/index.tsx)
EOF

# Let's read the file directly to see imports
head -100 apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 3106


🏁 Script executed:

# Find SearchInput import in the ListToolbar file
rg -n "import.*SearchInput" apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Find SearchInput component definition in the project
fd -e tsx -e ts | xargs rg -l "export.*SearchInput" 2>/dev/null | head -5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Search for SearchInput component definition
rg -n "const SearchInput|function SearchInput|export.*SearchInput" --type=tsx --type=ts -A 10

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 102


🏁 Script executed:

# Read the ListToolbar file to see the SearchInput usage in context (around lines 164-184)
sed -n '150,200p' apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1974


🏁 Script executed:

# Find handleSearchClear implementation
rg -n "handleSearchClear" apps/aurora-portal/src/client/components/ListToolbar/index.tsx -A 5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 460


🏁 Script executed:

# Check if there are other usages of SearchInput in the codebase
rg -n "SearchInput" --type=ts --type=tsx -B 2 -A 10 | grep -E "(SearchInput|onSearch)" | head -30

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 102


🏁 Script executed:

# Check if SearchInput is documented or has type definitions in the project
find . -name "*.d.ts" -o -name "*.ts" -o -name "*.tsx" | xargs grep -l "SearchInput" | grep -v node_modules | head -10

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 251


🏁 Script executed:

# Check how SearchInput is used in ProjectOverviewNavBar
grep -n "SearchInput" apps/aurora-portal/src/client/routes/_auth/accounts/\$accountId/projects/-components/ProjectOverviewNavBar.tsx -B 3 -A 10

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1163


🏁 Script executed:

# Check node_modules for SearchInput component definition or try to find type definitions
find . -path "*/node_modules/*juno*" -name "*.d.ts" 2>/dev/null | head -5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Look for package.json to find the juno-ui-components version
grep -r "juno-ui-components" package.json package-lock.json pnpm-lock.yaml 2>/dev/null | head -5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 301


🏁 Script executed:

# Check if there are tests for ListToolbar that show SearchInput usage
find . -name "*ListToolbar*test*" -o -name "*ListToolbar*spec*" 2>/dev/null | head -5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Look for test files for ListToolbar to understand the expected behavior
find . -path "*/ListToolbar*" -name "*.test.*" -o -path "*/ListToolbar*" -name "*.spec.*" 2>/dev/null

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 301


🏁 Script executed:

# Check if there's a SearchInput component locally defined
fd -e tsx -e ts -type f | xargs grep -l "export.*const.*SearchInput\|export.*function.*SearchInput" 2>/dev/null | grep -v node_modules

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 245


🏁 Script executed:

# Search for how SearchInput is documented or used with onChange vs onInput
rg -n "SearchInput" --type=tsx --type=ts -B 2 -A 15 | grep -E "(onChange|onInput|onSearch)" -B 2 -A 2

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 102


🏁 Script executed:

# Let's check the juno-ui-components in node_modules for SearchInput definition
find node_modules/@cloudoperators/juno-ui-components -name "*.d.ts" 2>/dev/null | xargs grep -l "SearchInput" | head -3

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Read the ListToolbar test file to understand the expected behavior
cat apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 8072


🏁 Script executed:

# Also check if there's documentation or examples showing SearchInput with onChange
rg -n "onChange.*SearchInput|SearchInput.*onChange" -A 5 -B 5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Check the full ListToolbar file to understand the complete context
wc -l apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 141


🏁 Script executed:

# Read the full ListToolbar file to see all imports and the complete context
cat -n apps/aurora-portal/src/client/components/ListToolbar/index.tsx | head -120

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 4600


🏁 Script executed:

# Check the test more carefully - look for how the SearchInput behaves with the search button
grep -n "Search" apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx -B 5 -A 5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 5385


🏁 Script executed:

# Check if SearchInput is documented anywhere in the juno-ui-components
find node_modules/@cloudoperators/juno-ui-components -type f -name "*.d.ts" -o -name "*.ts" 2>/dev/null | head -10

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Try a simpler approach - list what's in juno-ui-components
ls -la node_modules/@cloudoperators/juno-ui-components/ 2>/dev/null | head -20

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Read more of the ListToolbar file to see if there's anything else relevant
sed -n '165,200p' apps/aurora-portal/src/client/components/ListToolbar/index.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1462


🏁 Script executed:

# Check if SearchInput is exported from juno-ui-components and what props it accepts
python3 << 'EOF'
import json

# Try to find and read type definitions if they exist
try:
    with open('node_modules/@cloudoperators/juno-ui-components/package.json', 'r') as f:
        package_info = json.load(f)
        print("Package info found:")
        print(f"Main: {package_info.get('main')}")
        print(f"Types: {package_info.get('types')}")
        print(f"Version: {package_info.get('version')}")
except Exception as e:
    print(f"Error: {e}")
EOF

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 181


🏁 Script executed:

# Check the exact test behavior - does it expect onSearch to fire when button clicked?
sed -n '109,120p' apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 580


🏁 Script executed:

# Look at ProjectOverviewNavBar to see if it shows SearchInput usage pattern
sed -n '57,65p' apps/aurora-portal/src/client/routes/_auth/accounts/\$accountId/projects/-components/ProjectOverviewNavBar.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 342


🏁 Script executed:

# Check if the test is currently passing by looking at the test more holistically
# Check if there's a mock setup that might make the button click trigger onSearch
grep -n "vi.fn\|Mock\|jest" apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx | head -20

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1075


🏁 Script executed:

# Look at the complete test setup to understand how it works
sed -n '109,125p' apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 793


🏁 Script executed:

# Check if SearchInput from juno-ui-components passes through onClick to a button
# by searching for other components that might show the pattern
rg -n "onClick.*SearchInput|SearchInput.*onClick" -B 3 -A 3

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 57


🏁 Script executed:

# Check if the ListToolbar tests are currently passing
# by running them or checking test results
cd apps/aurora-portal && npm test -- ListToolbar/index.test.tsx --run 2>&1 | head -100

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 190


🏁 Script executed:

# If tests can't run, check the git history to see if this test was recently added
git log --oneline apps/aurora-portal/src/client/components/ListToolbar/index.test.tsx | head -5

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 124


🏁 Script executed:

# Check if there's a way SearchInput receives the onSearch callback through context or parent props
grep -n "SearchInput" apps/aurora-portal/src/client/components/ListToolbar/index.tsx -B 5 -A 15

Repository: cobaltcore-dev/aurora-dashboard

Length of output: 1623


Add onSearch handler to SearchInput for immediate search on button click.

The SearchInput component has a search button that should trigger an immediate search, independent of the debounced input changes. Currently, only onInput and onClear are wired. Without onSearch, clicking the button before the 500ms debounce completes won't trigger the search.

🛠️ Suggested fix
  <SearchInput
    id={field.name}
    name={field.name}
    value={field.state.value}
    onInput={(e) => field.handleChange(e.currentTarget.value)}
+   onSearch={() => onSearch?.(field.state.value)}
    onClear={handleSearchClear}
    placeholder={t`Search...`}
    data-testid="searchbar"
  />
📝 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
{onSearch && (
<div className="w-full md:ml-auto md:w-auto md:min-w-25">
<SearchInput {...searchProps} />
<form.Field
name="search"
listeners={{
onChangeDebounceMs: 500,
onChange: ({ value }) => onSearch?.(value),
}}
children={(field) => (
<SearchInput
id={field.name}
name={field.name}
value={field.state.value}
onInput={(e) => field.handleChange(e.currentTarget.value)}
onClear={handleSearchClear}
placeholder={t`Search...`}
data-testid="searchbar"
/>
)}
/>
</div>
{onSearch && (
<div className="w-full md:ml-auto md:w-auto md:min-w-25">
<form.Field
name="search"
listeners={{
onChangeDebounceMs: 500,
onChange: ({ value }) => onSearch?.(value),
}}
children={(field) => (
<SearchInput
id={field.name}
name={field.name}
value={field.state.value}
onInput={(e) => field.handleChange(e.currentTarget.value)}
onSearch={() => onSearch?.(field.state.value)}
onClear={handleSearchClear}
placeholder={t`Search...`}
data-testid="searchbar"
/>
)}
/>
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/aurora-portal/src/client/components/ListToolbar/index.tsx` around lines
164 - 184, The SearchInput in the form.Field children render is missing the
onSearch prop so clicking its search button doesn't trigger an immediate lookup;
update the SearchInput invocation inside the children callback to pass an
onSearch handler that calls the existing onSearch prop with the current field
value (use field.state.value) so a button click invokes onSearch immediately (in
addition to the existing debounced onChange and onClear/handleSearchClear
wiring).

Copy link
Copy Markdown

@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)
apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/index.tsx (1)

9-29: Extract this network-service guard into a shared helper.

apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network.tsx already owns the top-level "network" gate, and this same child-level block now exists here and in apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/index.tsx. Pulling it into one helper will keep the redirect rules from drifting.

♻️ Possible extraction
+// apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/-helpers/requireNeutron.ts
+import { redirect } from "@tanstack/react-router"
+import { getServiceIndex } from "@/server/Authentication/helpers"
+
+export async function requireNeutron({
+  trpcClient,
+  accountId,
+  projectId,
+}: {
+  trpcClient: { auth: { getAvailableServices: { query: () => Promise<{ name: string; type: string }[]> } } } | undefined
+  accountId: string
+  projectId: string
+}) {
+  const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []
+  const serviceIndex = getServiceIndex(availableServices)
+
+  if (!serviceIndex["network"]) {
+    throw redirect({
+      to: "/accounts/$accountId/projects",
+      params: { accountId },
+    })
+  }
+
+  if (!serviceIndex["network"]["neutron"]) {
+    throw redirect({
+      to: "/accounts/$accountId/projects/$projectId/network/overview",
+      params: { accountId, projectId },
+    })
+  }
+}
-  beforeLoad: async ({ context, params }) => {
-    const { trpcClient } = context
-    const { accountId, projectId } = params
-
-    const availableServices = (await trpcClient?.auth.getAvailableServices.query()) || []
-    const serviceIndex = getServiceIndex(availableServices)
-
-    if (!serviceIndex["network"]) {
-      throw redirect({
-        to: "/accounts/$accountId/projects",
-        params: { accountId },
-      })
-    }
-
-    if (!serviceIndex["network"]["neutron"]) {
-      throw redirect({
-        to: "/accounts/$accountId/projects/$projectId/network/overview",
-        params: { accountId, projectId },
-      })
-    }
-  },
+  beforeLoad: async ({ context, params }) =>
+    requireNeutron({
+      trpcClient: context.trpcClient,
+      accountId: params.accountId,
+      projectId: params.projectId,
+    }),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/aurora-portal/src/client/routes/_auth/accounts/`$accountId/projects/$projectId/network/securitygroups/index.tsx
around lines 9 - 29, Extract the duplicated network-service guard into a shared
helper (e.g., ensureNeutronServiceAvailable) that accepts ({ context, params })
and runs the same logic currently in beforeLoad: call
trpcClient.auth.getAvailableServices.query(), compute
getServiceIndex(availableServices), and if network or network.neutron is missing
perform the same redirect calls (use the same redirect destinations and params:
{ accountId } or { accountId, projectId }). Replace the duplicated beforeLoad
blocks in beforeLoad (this file) and in the floatingips route with a single
import and call to ensureNeutronServiceAvailable, and keep the top-level
network.tsx gate as-is so the helper only enforces the child-level neutron
redirect.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@apps/aurora-portal/src/client/routes/_auth/accounts/`$accountId/projects/$projectId/network/securitygroups/index.tsx:
- Around line 9-29: Extract the duplicated network-service guard into a shared
helper (e.g., ensureNeutronServiceAvailable) that accepts ({ context, params })
and runs the same logic currently in beforeLoad: call
trpcClient.auth.getAvailableServices.query(), compute
getServiceIndex(availableServices), and if network or network.neutron is missing
perform the same redirect calls (use the same redirect destinations and params:
{ accountId } or { accountId, projectId }). Replace the duplicated beforeLoad
blocks in beforeLoad (this file) and in the floatingips route with a single
import and call to ensureNeutronServiceAvailable, and keep the top-level
network.tsx gate as-is so the helper only enforces the child-level neutron
redirect.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e29172d-62b3-471e-893e-ac4448fe4ccf

📥 Commits

Reviewing files that changed from the base of the PR and between f900f06 and d77dad3.

📒 Files selected for processing (20)
  • apps/aurora-portal/src/client/routeTree.gen.ts
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/$floatingIpId.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/index.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/$securityGroupId/index.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/CreateSecurityGroupModal.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/CreateSecurityGroupModal.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/DeleteSecurityGroupDialog.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/DeleteSecurityGroupDialog.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/List.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/List.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupTableRow.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupTableRow.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/index.tsx
  • apps/aurora-portal/src/server/Compute/helpers/imageHelpers.test.ts
💤 Files with no reviewable changes (4)
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/CreateSecurityGroupModal.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-modals/EditSecurityGroupModal.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips.tsx
✅ Files skipped from review due to trivial changes (4)
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/$securityGroupId/index.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/List.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/floatingips/$floatingIpId.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/aurora-portal/src/server/Compute/helpers/imageHelpers.test.ts

Copy link
Copy Markdown

@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)
apps/aurora-portal/src/server/Network/types/network.ts (1)

96-104: Add explicit null-focused tests for the newly nullable fields.

Lines 96-97 and Line 104 now allow null, but current tests only prove omission-based success. Please add safeParse cases with explicit null for ipv4_address_scope, ipv6_address_scope, and "provider:physical_network" (and omission for port_security_enabled on Line 101) to lock in this behavior.

Proposed test additions
diff --git a/apps/aurora-portal/src/server/Network/types/network.test.ts b/apps/aurora-portal/src/server/Network/types/network.test.ts
@@
   it("should validate with only required fields", () => {
@@
     expect(result.success).toBe(true)
   })
+
+  it("should validate nullable address scopes and provider physical network", () => {
+    const result = NetworkSchema.safeParse({
+      admin_state_up: true,
+      created_at: "2026-03-10T10:00:00Z",
+      id: "network-3",
+      mtu: 1450,
+      name: "private-network-nullables",
+      project_id: "project-1",
+      "router:external": false,
+      shared: false,
+      status: "DOWN",
+      tenant_id: "tenant-1",
+      ipv4_address_scope: null,
+      ipv6_address_scope: null,
+      "provider:physical_network": null,
+    })
+
+    expect(result.success).toBe(true)
+  })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/aurora-portal/src/server/Network/types/network.ts` around lines 96 -
104, Tests don't assert explicit nulls for the newly nullable fields
ipv4_address_scope, ipv6_address_scope and "provider:physical_network" and only
assert omission; add safeParse-based tests that pass explicit null for these
three fields to the existing schema tests (use the same schema used in
network.ts), and ensure there remains a test that omits port_security_enabled to
confirm omission still validates; reference the field names ipv4_address_scope,
ipv6_address_scope, "provider:physical_network" and the schema under test when
adding these safeParse cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/aurora-portal/src/server/Network/types/network.ts`:
- Around line 96-104: Tests don't assert explicit nulls for the newly nullable
fields ipv4_address_scope, ipv6_address_scope and "provider:physical_network"
and only assert omission; add safeParse-based tests that pass explicit null for
these three fields to the existing schema tests (use the same schema used in
network.ts), and ensure there remains a test that omits port_security_enabled to
confirm omission still validates; reference the field names ipv4_address_scope,
ipv6_address_scope, "provider:physical_network" and the schema under test when
adding these safeParse cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3fe9b897-7803-4c0e-b56e-09e5eba6e035

📥 Commits

Reviewing files that changed from the base of the PR and between d77dad3 and a384b18.

📒 Files selected for processing (5)
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/List.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.test.tsx
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.tsx
  • apps/aurora-portal/src/server/Network/types/network.test.ts
  • apps/aurora-portal/src/server/Network/types/network.ts
💤 Files with no reviewable changes (1)
  • apps/aurora-portal/src/server/Network/types/network.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/aurora-portal/src/client/routes/_auth/accounts/$accountId/projects/$projectId/network/securitygroups/-components/-table/SecurityGroupListContainer.tsx

@vlad-schur-external-sap vlad-schur-external-sap changed the title refactor(network): ui-ux changes and moved sort to common ListToolbar refactor(network): floating IPs UI/UX Improvements Apr 16, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 34 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

<InputGroup className="flex w-full items-end sm:w-auto">
<Select
value={sortSettings.sortBy}
onChange={(value) => onSort({ ...sortSettings, sortBy: value ?? "", sortDirection })}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

SortSettings.sortBy is optional, but the new handler coerces an undefined selection to an empty string (value ?? ""). Passing "" as a sort key can produce invalid API requests or inconsistent behavior; it’s safer to propagate undefined (or keep the previous sortBy) when no value is selected.

Suggested change
onChange={(value) => onSort({ ...sortSettings, sortBy: value ?? "", sortDirection })}
onChange={(value) => onSort({ ...sortSettings, sortBy: value, sortDirection })}

Copilot uses AI. Check for mistakes.
@vlad-schur-external-sap vlad-schur-external-sap marked this pull request as draft April 16, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Task](network): Floating IPs UI/UX Improvements

2 participants