upcoming: [UIE-10430] - Reserved IP: Implement Landing Screen.#13549
upcoming: [UIE-10430] - Reserved IP: Implement Landing Screen.#13549tanushree-akamai wants to merge 2 commits intolinode:developfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Implements the Reserved IPs landing experience (table + row rendering) and adds supporting MSW “CRUD preset” wiring and seed data so the page can be exercised locally behind the feature flag.
Changes:
- Added Reserved IPs landing UI (table, row rendering, action menu) with pagination and ordering driven by query params/preferences.
- Extended MSW mock state/types and added Reserved IP list handler + seeder to populate mock data.
- Wired Reserved IP mocks/seeders into the baseline CRUD preset and DevTools seed list.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/manager/src/mocks/types.ts | Adds “Reserved IPs” to CRUD groups/IDs and adds reservedIPs to MockState. |
| packages/manager/src/mocks/presets/crud/seeds/networking.ts | Adds reservedIPSeeder using reservedIPsFactory and IndexedDB seed state. |
| packages/manager/src/mocks/presets/crud/seeds/index.ts | Registers reservedIPSeeder in dbSeeders. |
| packages/manager/src/mocks/presets/crud/networking.ts | Adds reservedIPsCrudPreset to expose Reserved IP handlers in CRUD preset. |
| packages/manager/src/mocks/presets/crud/handlers/networking.ts | Adds MSW GET handler for /v4beta/networking/reserved/ips. |
| packages/manager/src/mocks/presets/baseline/crud.ts | Includes networking and reserved IP handlers in the baseline CRUD preset. |
| packages/manager/src/mocks/mockState.ts | Initializes reservedIPs: [] in the empty mock store. |
| packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsLandingTable.tsx | New table component rendering Reserved IPs list with sorting + pagination. |
| packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsLandingRow.tsx | New row renderer with assigned-entity link logic and tag overflow handling. |
| packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsLanding.tsx | Hooks up queries/pagination/sorting and renders empty/loading/error states. |
| packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsActionMenu.tsx | Adds action menu skeleton for Edit/Unreserve actions. |
| packages/manager/src/factories/networking.ts | Adds reservedIPsFactory seed data for Reserved IPs (regions/tags/assigned entities). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| request, | ||
| }); | ||
| } | ||
| ), |
There was a problem hiding this comment.
Reserved IP MSW support currently only mocks the GET list endpoint. If the landing screen’s action menu / create button is later wired to reserveIP, updateReservedIP, or unReserveIP, those requests will bypass MSW (or fail) because there are no handlers for POST /networking/reserved/ips, PUT /networking/reserved/ips/:address, or DELETE /networking/reserved/ips/:address. Implement those handlers here (and include them in the preset) to fulfill the intended CRUD mock behavior.
| ), | |
| ), | |
| http.post( | |
| '*/v4beta/networking/reserved/ips', | |
| async ({ | |
| request, | |
| }): Promise<StrictResponse<APIErrorResponse | IPAddress>> => { | |
| const payload = await request.clone().json(); | |
| const reservedIP = ipAddressFactory.build({ | |
| ...payload, | |
| }); | |
| await mswDB.add('reservedIPs', reservedIP, mockState); | |
| return makeResponse(reservedIP); | |
| } | |
| ), | |
| http.put( | |
| '*/v4beta/networking/reserved/ips/:address', | |
| async ({ | |
| params, | |
| request, | |
| }): Promise<StrictResponse<APIErrorResponse | IPAddress>> => { | |
| const reservedIPs = await mswDB.getAll('reservedIPs'); | |
| const existing = reservedIPs?.find( | |
| ({ address }) => address === params.address | |
| ); | |
| if (!existing) { | |
| return makeNotFoundResponse(); | |
| } | |
| const payload = await request.clone().json(); | |
| const updatedReservedIP: IPAddress = { | |
| ...existing, | |
| ...payload, | |
| }; | |
| await mswDB.add('reservedIPs', updatedReservedIP, mockState); | |
| return makeResponse(updatedReservedIP); | |
| } | |
| ), | |
| http.delete( | |
| '*/v4beta/networking/reserved/ips/:address', | |
| async ({ | |
| params, | |
| }): Promise<StrictResponse<APIErrorResponse | {}>> => { | |
| const reservedIPs = await mswDB.getAll('reservedIPs'); | |
| const existing = reservedIPs?.find( | |
| ({ address }) => address === params.address | |
| ); | |
| if (!existing) { | |
| return makeNotFoundResponse(); | |
| } | |
| await mswDB.delete('reservedIPs', existing.address, mockState); | |
| return makeResponse({}); | |
| } | |
| ), |
packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsLanding.tsx
Show resolved
Hide resolved
packages/manager/src/features/ReservedIps/ReservedIpsLanding/ReservedIpsLanding.tsx
Show resolved
Hide resolved
4aba464 to
e90983d
Compare
Cloud Manager UI test results🔺 1 failing test on test run #3 ↗︎
Details
TroubleshootingUse this command to re-run the failing tests: pnpm cy:run -s "cypress/e2e/core/objectStorageMulticluster/object-storage-objects-multicluster.spec.ts" |
|||||||||||||||||
There was a problem hiding this comment.
Let’s get figma screens for mobile view. Currently horizontal scroll is applying in mobile view. I think we will have to hide few columns in mobile view.
| )} | ||
| </TableCell> | ||
| <TableCell>{regionLabel}</TableCell> | ||
| <TableCell>{tags?.length > 0 ? <TagsList tags={tags} /> : ''}</TableCell> |
There was a problem hiding this comment.
In mobile view, with more tags, action menu is overlapped by tags
| * Displays up to 3 non-clickable tag chips, with a "+N" ShowMore popover | ||
| * for any overflow tags. | ||
| */ | ||
| const MAX_VISIBLE_TAGS = 3; |
There was a problem hiding this comment.
Can we limit this to 2? If the tag is long, then accommodating 3 tags need not be required.
|
|
||
| const mockQueryReturn = vi.hoisted(() => | ||
| vi.fn().mockReturnValue({ | ||
| data: undefined, |
| routeTree, | ||
| }); | ||
|
|
||
| expect(getByText('Reserve an IP Address')).toBeVisible(); |
There was a problem hiding this comment.
This button is shown even when there are IPs to show in the table. So let's look for text within empty state.
| }); | ||
|
|
||
| it('renders the table when reserved IPs are returned', () => { | ||
| mockQueryReturn.mockReturnValue({ |
There was a problem hiding this comment.
we could use reservedIPsFactory to generate list instead of hardcoding it here.
| /> | ||
| ); | ||
|
|
||
| expect(queryByTestId('show-more')).not.toBeInTheDocument(); |
There was a problem hiding this comment.
When there are no tags, looking for "Show more" doesn't makes sense. So let's look for empty string instead.
| ); | ||
| }; | ||
|
|
||
| const StyledTagChip = styled(Chip, { |
There was a problem hiding this comment.
See if we can use Badge web component instead of chip here.
|
|
||
| return ( | ||
| <> | ||
| <LandingHeader |
There was a problem hiding this comment.
We also need to show docs link before the create button. Placeholder URL would be "https://techdocs.akamai.com/cloud-computing/update/docs/reserved-ips"
There was a problem hiding this comment.
What should be the default sorting for the table? Should it be by IP Address or by region? Also sort icon is shown only on hover for IP address. Is that the expected behavior?
Description 📝
Implement Reserved IP Landing Table alongwith CRUD MSW mock setup.
Changes 🔄
Scope 🚢
Upon production release, changes in this PR will be visible to:
Target release date 🗓️
Please specify a release date (and environment, if applicable) to guarantee timely review of this PR. If exact date is not known, please approximate and update it as needed.
Preview 📷
How to test 🧪
Prerequisites
Verification steps
Author Checklists
As an Author, to speed up the review process, I considered 🤔
👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support
As an Author, before moving this PR from Draft to Open, I confirmed ✅