Skip to content

chore(APICP): revamp the portal UI with a scope-aware app shell - #3281

Merged
Induwara04 merged 13 commits into
wso2:mainfrom
ShavinAnjithaAlpha:feat/apicp-portal-ui-rewamp
Aug 28, 2026
Merged

chore(APICP): revamp the portal UI with a scope-aware app shell#3281
Induwara04 merged 13 commits into
wso2:mainfrom
ShavinAnjithaAlpha:feat/apicp-portal-ui-rewamp

Conversation

@ShavinAnjithaAlpha

@ShavinAnjithaAlpha ShavinAnjithaAlpha commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Purpose

Revamp the API Control Plane portal's app shell so it reads and behaves like Bijira, and restructure the source tree around it. The sidebar, header and layout are the visible half; underneath, the scope model (organization → project → API) is made explicit in the route builders, the navigation registry and a new ScopeGate, so what the sidebar offers and what a page can actually render can no longer disagree.

Resolves https://github.com/wso2-enterprise/apim-saas/issues/2897, https://github.com/wso2-enterprise/apim-saas/issues/2907

App shell

Sidebar

  • Replaced per-scope sidebar headings with three divider-separated clusters: Place, API, and Global.
  • Added nested submenus for Test, Insights, Observability, and Manage, with active-child expansion and explicit navigation in the collapsed rail.
  • Made all items available at every scope via scope-less aliases, with ScopeGate resolving missing scope.
  • Made Overview scope-adaptive and highlighted across nested scopes.
  • Limited capability gating to API scope so API-level entry points remain accessible while an API is unloaded.

Header

  • Organization / Project / API switchers, each a new searchable SearchableComplexSelect (icon + primary/secondary rows, bounded trigger width, ellipsized option text) in place of the plain ComplexSelect.
  • Quick selectors (ProjectQuickSelector, APIQuickSelector) appear for the levels not yet selected, with their own loading/error states.
  • Step-back affordances: an inline clear button on the project and API switchers navigates back to organization / project level.
  • Options resolve displayName with a fallback to the handle, and keep the current value selectable before the list loads so the switcher never renders out of range.
  • All shell strings moved to react-intl (brand title, switcher labels, search / empty / no-results copy, notification tooltip, footer links, panel title).

Layout

  • Breadcrumbs moved inside PageContent (full width, Stack-spaced above the outlet) instead of floating above it, and now label from displayName.
  • Footer and notification-panel strings i18n'd.

Scope model, routes and gating

  • projectPath / apiPath builders with an explicit unresolved-scope marker. A null handle produces the page's scope-less alias by substituting a reserved select-scope segment (/organizations/acme/select-scope/apis) rather than dropping segments, which would make /organizations/acme/projects/apis read positionally as project apis, and would collide project Settings/Home with their organization-level equivalents.
  • ScopeGate renders a project/API picker in place of the page body until the route carries the scope the page needs, then navigates to the fully-scoped URL.
  • projectScopedPaths / apiScopedPaths / apiScopeSelectPaths generate both the route patterns AppRoutes registers and the match predicates the sidebar highlights on, from the same builder, the route table and the highlight can't drift apart. Submenu parents match only the aliases, so parent and child never both claim active.
  • ConsoleScopeProvider / ConsoleScopeContext now expose isProjectScope / isApiScope, projects and their error state, and API capabilities, typed against the generated resource clients (RestApi, Organization, Project) rather than hand-written domain types.
  • Runtime logs moved from project-wide observe/runtimelogs to API-scoped observability/logs.
  • New ComingSoon placeholder pages for Admin, API Insights, Compliance, Metrics, Alerts, Monetize, LifeCycle, API Console and API Chat, so every sidebar destination resolves to something.

Restructuring

  • src/features/*src/pages/appShell/appShellPages/* (apis, deploy, gateways, projects, organizations, observability, insights, manage, test, admin, settings), with each page's own components/ and utils/ subfolders.
  • src/features/authsrc/contexts/auth; features/billing/ProductActivationsrc/hooks; layouts → src/pages/appShell; src/pages/auth for login/callback.
  • API resource index modules added under src/api/resources/* (organizations, projects, restApis, apiKeys, gateways).
  • Project listing gains pagination, sorting and a reworked card grid; project forms moved onto Oxygen form controls.

Theme

  • Shared sx recipes (glassSurfaceSx, hairline, interactiveCardSx, stickyBottomBarSx) so surfaces stay consistent across pages.

Documentation

N/A

Tests

  • New: AppSidebar.test.tsx, ScopeGate.test.tsx, paths.test.ts, useNavigationItems.test.tsx.
  • Expanded: navigationRegistry.test.ts (clusters, submenus, adaptive items, alias matching), ApiListPage.test.tsx, ProjectListPage.test.tsx, NewProjectDialog.test.tsx, apiCapabilities.test.ts.

Related

Test environment

  • Node.js 24.x (per engines in package.json), npm
  • Vite 5.0.11, TypeScript 5.8.3, React 19.2.3, react-intl 10.1.20
  • Vitest 2.1.8 on jsdom 25.0.1

- Restructure the pages, components, hooks and contexts.
- Restructure pages, components, hooks, and contexts
- Fix issues introduced by the restructuring
- Enhance project listing with pagination, sorting, and improved UI
- Add an index to the project API resource section
- Add form controls to project-related forms
- Temporarily make the app sidebar static
…ome restructuring

- Make the App Side Bar and Header consistent with the bijira.
- Updated projectPath and apiPath functions to manage unresolved project and API scopes.
- Refactored routes to utilize new path builders for project and API-level pages.
- Improved ConsoleScopeContext and ConsoleScopeProvider to handle new API capabilities and project management.
- Added ScopeGate component to manage access to pages based on selected scopes.
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 166 files, which is 66 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c5617f1-b2a7-4cfa-b967-01a241343f99

📥 Commits

Reviewing files that changed from the base of the PR and between 44bc16b and 587b24e.

⛔ Files ignored due to path filters (1)
  • portals/api-control-plane/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (166)
  • portals/api-control-plane/.claude/skills/apicp-ui/SKILL.md
  • portals/api-control-plane/.eslintignore
  • portals/api-control-plane/.prettierignore
  • portals/api-control-plane/.prettierrc.json
  • portals/api-control-plane/CLAUDE.md
  • portals/api-control-plane/eslint.config.js
  • portals/api-control-plane/package.json
  • portals/api-control-plane/src/App.smoke.test.tsx
  • portals/api-control-plane/src/App.tsx
  • portals/api-control-plane/src/api/core/http.test.ts
  • portals/api-control-plane/src/api/core/http.ts
  • portals/api-control-plane/src/api/mocks/data.ts
  • portals/api-control-plane/src/api/mocks/handlers.ts
  • portals/api-control-plane/src/api/organizations/organizationClient.ts
  • portals/api-control-plane/src/api/platform/platformClient.test.ts
  • portals/api-control-plane/src/api/platform/platformClient.ts
  • portals/api-control-plane/src/api/projects/projectClient.ts
  • portals/api-control-plane/src/api/resources/apiKeys/index.ts
  • portals/api-control-plane/src/api/resources/applications/index.ts
  • portals/api-control-plane/src/api/resources/gatewayCustomPolicies/index.ts
  • portals/api-control-plane/src/api/resources/gateways/index.ts
  • portals/api-control-plane/src/api/resources/organizations/index.ts
  • portals/api-control-plane/src/api/resources/projects/index.ts
  • portals/api-control-plane/src/api/resources/projects/projects.hooks.ts
  • portals/api-control-plane/src/api/resources/restApis/index.ts
  • portals/api-control-plane/src/api/resources/secrets/index.ts
  • portals/api-control-plane/src/api/resources/subscriptionPlans/index.ts
  • portals/api-control-plane/src/api/resources/subscriptions/index.ts
  • portals/api-control-plane/src/components/ComingSoon.tsx
  • portals/api-control-plane/src/components/ConfirmDialog.tsx
  • portals/api-control-plane/src/components/ErrorBoundary.tsx
  • portals/api-control-plane/src/components/cards/ApiCard.tsx
  • portals/api-control-plane/src/components/cards/ProjectCard.tsx
  • portals/api-control-plane/src/components/cards/ProjectsGrid.tsx
  • portals/api-control-plane/src/components/cards/SummaryCardSection.tsx
  • portals/api-control-plane/src/components/common/SearchableComplexSelect.tsx
  • portals/api-control-plane/src/components/errors/ErrorBoundary.test.tsx
  • portals/api-control-plane/src/components/errors/ErrorBoundary.tsx
  • portals/api-control-plane/src/components/errors/ErrorFallback.tsx
  • portals/api-control-plane/src/contexts/auth/AuthProvider.test.tsx
  • portals/api-control-plane/src/contexts/auth/AuthProvider.tsx
  • portals/api-control-plane/src/contexts/auth/AuthStateContext.ts
  • portals/api-control-plane/src/contexts/auth/authConstants.ts
  • portals/api-control-plane/src/contexts/auth/authTypes.ts
  • portals/api-control-plane/src/extensions.tsx
  • portals/api-control-plane/src/features/apis/ApiCreatePage.test.tsx
  • portals/api-control-plane/src/features/apis/ApiDetailPage.test.tsx
  • portals/api-control-plane/src/features/apis/ApiDetailPage.tsx
  • portals/api-control-plane/src/features/apis/ApiListPage.test.tsx
  • portals/api-control-plane/src/features/apis/overview/OverviewTab.test.tsx
  • portals/api-control-plane/src/features/deploy/DeployPage.test.tsx
  • portals/api-control-plane/src/features/manage/ManagePage.tsx
  • portals/api-control-plane/src/features/projects/NewProjectDialog.tsx
  • portals/api-control-plane/src/features/projects/ProjectListPage.test.tsx
  • portals/api-control-plane/src/features/projects/ProjectListPage.tsx
  • portals/api-control-plane/src/features/settings/SettingsLayout.tsx
  • portals/api-control-plane/src/hooks/ProductActivation.tsx
  • portals/api-control-plane/src/hooks/useFooterHeight.ts
  • portals/api-control-plane/src/i18n/messages/en.json
  • portals/api-control-plane/src/layouts/AppHeader.tsx
  • portals/api-control-plane/src/layouts/AppLayout.tsx
  • portals/api-control-plane/src/layouts/AppSidebar.tsx
  • portals/api-control-plane/src/navigation/navigationRegistry.test.ts
  • portals/api-control-plane/src/navigation/navigationRegistry.tsx
  • portals/api-control-plane/src/navigation/navigationTypes.ts
  • portals/api-control-plane/src/navigation/useNavigationItems.test.tsx
  • portals/api-control-plane/src/navigation/useNavigationItems.ts
  • portals/api-control-plane/src/navigation/useSettingsTabs.tsx
  • portals/api-control-plane/src/pages/appShell/APIQuickSelector.tsx
  • portals/api-control-plane/src/pages/appShell/AppHeader.test.tsx
  • portals/api-control-plane/src/pages/appShell/AppHeader.tsx
  • portals/api-control-plane/src/pages/appShell/AppLayout.tsx
  • portals/api-control-plane/src/pages/appShell/AppSidebar.test.tsx
  • portals/api-control-plane/src/pages/appShell/AppSidebar.tsx
  • portals/api-control-plane/src/pages/appShell/HeaderScopeSwitchers.tsx
  • portals/api-control-plane/src/pages/appShell/ProjectQuickSelector.tsx
  • portals/api-control-plane/src/pages/appShell/appLayoutConstants.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/admin/AdminPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiCardGrid.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiCreatePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiDetailPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiListPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiListView.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/components/ApiCard.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/components/RestApiChips.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/AttachedPolicyList.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/AvailablePoliciesPanel.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/DevelopPageShell.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/DocumentsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/DocumentsTab.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/PoliciesPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/PolicyConfigDrawer.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/PolicyTab.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/RoutingPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/RoutingTab.test.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/RoutingTab.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/SchemaField.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/backendDiscovery.test.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/backendDiscovery.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/components/SaveBar.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/developEdit.test.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/developEdit.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/policyDnd.test.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/develop/policyDnd.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/overview/ApiKeysPanel.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/overview/InvokeUrlPanel.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/overview/OverviewTab.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/overview/ProgressBanner.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/overview/ResourcesPanel.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/restApiDisplay.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/utils/apiCapabilities.test.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/apis/utils/apiCapabilities.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/DeployPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/GatewayDeploymentHistory.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/components/GatewayDeployCard.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/components/GatewayDeployEnvCard.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/components/GatewayDeploymentRow.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/components/GatewayDeploymentSelector.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/deploy/utils/gatewayDeployUtils.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/GatewayCreatePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/GatewayDetailPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/GatewaysPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/components/CopyableCommand.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/gatewayEnvironments.test.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/gatewayEnvironments.ts
  • portals/api-control-plane/src/pages/appShell/appShellPages/gateways/gatewaysUi.css
  • portals/api-control-plane/src/pages/appShell/appShellPages/insights/CompliancePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/insights/InsightsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/manage/LifeCyclePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/manage/MonetizePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/observability/AlertsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/observability/MetricsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/observability/RuntimeLogsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/organizations/ExploreMoreCard.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/organizations/OrganizationHomePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/NewProjectDialog.test.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/NewProjectDialog.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/ProjectHomePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/ProjectListPage.test.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/ProjectListPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/projects/ProjectsGrid.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/settings/GeneralSettingsPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/settings/SettingsLayout.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/system/SystemPages.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/test/ApiChatPage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/test/ApiConsolePage.tsx
  • portals/api-control-plane/src/pages/appShell/appShellPages/test/TestPage.tsx
  • portals/api-control-plane/src/pages/auth/AuthCallbackPage.tsx
  • portals/api-control-plane/src/pages/auth/LoginPage.tsx
  • portals/api-control-plane/src/routes/AppRoutes.orgSettings.test.tsx
  • portals/api-control-plane/src/routes/AppRoutes.settingsTab.test.tsx
  • portals/api-control-plane/src/routes/AppRoutes.tsx
  • portals/api-control-plane/src/routes/ProtectedRoute.tsx
  • portals/api-control-plane/src/routes/paths.test.ts
  • portals/api-control-plane/src/routes/paths.ts
  • portals/api-control-plane/src/scope/ConsoleScopeContext.ts
  • portals/api-control-plane/src/scope/ConsoleScopeProvider.tsx
  • portals/api-control-plane/src/scope/ScopeGate.test.tsx
  • portals/api-control-plane/src/scope/ScopeGate.tsx
  • portals/api-control-plane/src/scope/consoleRouteParams.ts
  • portals/api-control-plane/src/test/mockAuthState.ts
  • portals/api-control-plane/src/test/mockScope.ts
  • portals/api-control-plane/src/test/utils.tsx
  • portals/api-control-plane/src/theme/index.ts
  • portals/api-control-plane/src/theme/receipes.ts
  • portals/api-control-plane/src/utils/errors/errorClassification.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands.

Comment thread portals/api-control-plane/src/api/resources/apiKeys/index.ts Outdated
Comment thread portals/api-control-plane/.claude/oxygen-ui/components.md Outdated

@AnuGayan AnuGayan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review — scope-aware app shell

A large app-shell rewrite: three-cluster sidebar with submenus, searchable org/project/API header switchers, an explicit scope model (projectPath/apiPath + ScopeGate + the select-scope marker), and a src/features/*src/pages/appShell/appShellPages/* restructure.

The scope model is the strongest part. Generating route patterns and sidebar match predicates from one builder (projectScopedPaths/apiScopedPaths/apiScopeSelectPaths) closes a whole class of drift, and the SELECT_SCOPE_SEGMENT rationale in paths.ts — spelling out why dropping segments would make /projects/apis read positionally as project apis — is exactly the reasoning that usually gets lost. toRouteRegex escapes metacharacters before substituting :param, in the right order. ConfirmDialog's rework to a real <form> with useId()-bound labels is a genuine a11y improvement, and ProjectListPage (debounced server-side search, page reset on filter change, page > lastPage clamping after a delete, defineMessages for every string) reads like the standard the other new pages should be held to.

Against that, the branch does not build reproducibly, ships a placeholder page copy-pasted from the AI Workspace portal with an inert primary button, reverts the extension seam #3259 just landed, and deletes ~875 lines of tests for pages it rewrites.

Checks I ran on c8fba03

Command Result
npm ci fails — lockfile out of sync with the pinned versions
npm run typecheck ✅ clean
npm test ✅ 59 files, 732 tests pass (17 MUI out-of-range warnings)
npm run lint ❌ 2 errors, both in files added by this PR
npm run i18n:extract ⚠️ 2 duplicate ids; en.json 21 lines stale

Findings

13 inline comments below, each with a reproduction and a paste-ready prompt. Headlines:

  • 🔴 npm ci failsc8fba03 pinned versions without regenerating package-lock.json. Dockerfile:27 and apip-api-control-plane-release.yml:53 both run npm ci, so the image and the release job break.
  • 🟠 The #3259 Slot/Port seam is reverted, not built onrender(port)element, scopelevel, useSettingsTabs.tsx and its test deleted, src/slots/ orphaned.
  • 🟠 "Deploy to Gateway" does nothingApiDetailPage.tsx:159 has its link commented out.
  • 🟠 A failed project load shows "Loading…" foreverAppHeader.tsx:240 folds the error into the loading flag.

One finding I could not anchor inline (deleted files)

Severity: 🟠 major
Subject: Six test files deleted with no replacement, and the PR body describes one of them as "expanded"

Description
Deleted with no equivalent anywhere on the branch: ApiCreatePage.test.tsx (100), ApiDetailPage.test.tsx (101), ApiListPage.test.tsx (118), OverviewTab.test.tsx (218), DeployPage.test.tsx (232), AppRoutes.settingsTab.test.tsx (106). The pages themselves survive in rewritten form — ApiListPage.tsx is +86/−112, DeployPage.tsx +37/−11, ApiDetailPage.tsx is brand new — so the rewrite lands untested. The PR body's Tests section lists ApiListPage.test.tsx under "Expanded", but no file by that name exists on the branch.

How to verify

git ls-tree -r --name-only 44a453e -- portals/api-control-plane/src | grep -E '\.test\.tsx?$' \
  | sed 's|.*/||' | sort -u > /tmp/base.txt
git ls-tree -r --name-only c8fba03 -- portals/api-control-plane/src | grep -E '\.test\.tsx?$' \
  | sed 's|.*/||' | sort -u > /tmp/pr.txt
comm -23 /tmp/base.txt /tmp/pr.txt
find portals/api-control-plane/src -name 'ApiListPage.test.tsx'   # no output

Suggested fix
Port the deleted suites to the new file locations. At minimum restore ApiListPage.test.tsx and DeployPage.test.tsx, whose pages changed substantially, and correct the PR body's Tests section.

Prompt for Claude

This branch deletes six test files without replacing them. Restore the two highest-value ones.
1. First confirm they are gone: `find portals/api-control-plane/src -name 'ApiListPage.test.tsx'
   -o -name 'DeployPage.test.tsx'`. If either exists, stop and tell me which — the finding is
   partly wrong.
2. Recover the originals:
   `git show 44a453e:portals/api-control-plane/src/features/apis/ApiListPage.test.tsx`
   `git show 44a453e:portals/api-control-plane/src/features/deploy/DeployPage.test.tsx`
3. Port each to its page's new location (src/pages/appShell/appShellPages/apis/ and .../deploy/),
   updating import paths and any assertions the rewrite invalidated. Where the page's behaviour
   genuinely changed, update the assertion rather than deleting the test.
4. Do not weaken assertions just to make them pass, and do not add `.skip`.
5. Confirm with `npm test` — all suites must pass and the file count must rise from 59.

Nits, not worth their own thread

  • aiWorkspace.* message ids leak in: ApiDetailPage.tsx:127,138 (one names LLMProxyOverview), ProjectQuickSelector.tsx:126,153,159,167, APIQuickSelector.tsx, ExploreMoreCard.tsx:99. Every other id uses appShell.* / apiControlPlane.* — worth renaming before these reach a translation memory.
  • ExploreMoreCard.tsx:80-90 links to AI Workspace docs — "Manage Existing App LLM Proxies" pointing at .../ai-workspace/llm-proxies/manage-proxy/. Wrong product for this page.
  • Hardcoded English despite the "all shell strings moved to react-intl" claim: every ScopeGate prompt (12 call sites — prompt is typed string, so <FormattedMessage> can't be passed; widening it to ReactNode would fix that), ScopeGate's DEFAULT_PROMPT / "Unable to load projects" / "Loading projects", all of restApiDisplay.ts ('REST API', 'Published', 'Not deployed', 'Unknown' — these render straight into chips), SettingsPage.tsx in full, AppLayout.tsx:164 "You're all caught up.", SaveBar.tsx 'Save changes' / 'Saving…'. ProjectQuickSelector.tsx:134 hardcodes placeholder="Search" where the API one uses intl.formatMessage.
  • src/theme/receipes.ts is misspelled (recipes), and glassSurfaceSx is exported from theme/index.ts with no consumer.
  • src/theme/emotionCache.ts carries authoring leftovers: a redundant // src/theme/emotionCache.ts path header, and // ...read the per-request nonce from a meta tag (see §10) — a cross-reference to a document that isn't in the repo. The code also reads .nonce off a meta[property="csp-nonce"] element; if the nonce is carried in content= (the usual convention) that yields '', not the nonce. Unverified — I found no csp-nonce meta in index.html, so this path may never fire today.
  • AppHeader.tsx:229,308 — the clear IconButton is width: 20, height: 10; the 10px height looks like a typo and gives a sub-minimum tap target.
  • ApiDetailPage.tsx:38-48truncateProviderDisplayName is declared inside the component body, after the early returns, at the wrong indent level. It's a pure helper that belongs at module scope, and it truncates an API display name, not a provider's.
  • useNavigationItems.ts:139-146 — the sort comparator calls combinedRegistry.find() twice per comparison. Fine at ~20 items, but a precomputed Map<id, order> would be faster and clearer.

Reviewed at c8fba03 against base 44a453e, with a local install (npm install), typecheck, full test run, lint and i18n extract. Findings marked "Confirmed" were reproduced; anything I could not reproduce is labelled unverified inline.

Comment thread portals/api-control-plane/package.json
Comment thread portals/api-control-plane/src/extensions.tsx Outdated
Comment thread portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiDetailPage.tsx Outdated
Comment thread portals/api-control-plane/src/pages/appShell/AppHeader.tsx Outdated
Comment thread portals/api-control-plane/src/scope/ScopeGate.tsx Outdated
Comment thread portals/api-control-plane/src/pages/appShell/AppHeader.tsx Outdated
Comment thread portals/api-control-plane/src/pages/appShell/appShellPages/apis/ApiDetailPage.tsx Outdated
Comment thread portals/api-control-plane/src/navigation/navigationTypes.ts
Comment thread portals/api-control-plane/src/pages/appShell/ProjectQuickSelector.tsx Outdated
- scope: reserve `new` as a non-handle path segment, so the API create page
  (.../apis/new) no longer reads back as an API called "new",  which had put a
  phantom entry in the header switcher and breadcrumbs, turned isApiScope on
  mid-creation, and fired a GET for that API
- shell: hide breadcrumbs on full-page creation flows (newApi, newGateway)
- header: give apiOptions the current-value fallback orgOptions already had, so
  the API switcher never renders an out-of-range value on first paint
- header: fix isProjectsLoading so ProjectQuickSelector's error branch is
  reachable instead of showing "Loading..." forever on a failed query
- apis: wire the inert "Deploy to Gateway" button to routes.apiDeploy
- i18n: split scopeGate.noProjects/noApis, each carrying two different sentences
- some code refactoring
@ShavinAnjithaAlpha
ShavinAnjithaAlpha force-pushed the feat/apicp-portal-ui-rewamp branch from dee386c to c2b7c5b Compare August 25, 2026 06:33
Induwara04
Induwara04 previously approved these changes Aug 25, 2026
- Boundary around the routed page in AppLayout, above Suspense, so the shell survives and stale lazy() chunks are caught too.
- Recovery actions that work: Try again / Go home, or Reload for a stale chunk.
- resetKeys keyed on pathname, so a fallback clears on navigation.
- Header switchers and sidebar guarded separately; switchers extracted to HeaderScopeSwitchers so logout stays reachable. Both degrade visibly.
- Raw error.message shown in dev builds only.
@Induwara04
Induwara04 merged commit 0134cd7 into wso2:main Aug 28, 2026
6 checks passed
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.

3 participants