Skip to content

OSAC-4026: [UI] Storage Tier details page - #146

Merged
openshift-merge-bot[bot] merged 15 commits into
osac-project:mainfrom
ElayAharoni:OSAC-4026-storage-tier-details-page
Aug 17, 2026
Merged

OSAC-4026: [UI] Storage Tier details page#146
openshift-merge-bot[bot] merged 15 commits into
osac-project:mainfrom
ElayAharoni:OSAC-4026-storage-tier-details-page

Conversation

@ElayAharoni

@ElayAharoni ElayAharoni commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

OSAC-4026: [UI] Storage Tier details page

Jira: https://redhat.atlassian.net/browse/OSAC-4026
Story type: [UI]

Summary

Adds a StorageTierDetailsPage at /admin/infrastructure/storage/tiers/:id, giving a Cloud Provider Admin a full view of a single storage tier's backend associations (protocol, bandwidth, quota, encryption) before assigning it to a tenant or troubleshooting one. Follows the existing BareMetalDetailsPage/BareMetalDetails split — the only prior codebase precedent composing ResourceDetailHeader + ResourceDetailsPageLoading + ResourceDetailsPageError.

Changes

  • New pages/components:
    • StorageTierDetailsPage — data fetch via usePrivateStorageTier(id), loading/error/not-found branching
    • StorageTierDetails — presentational header + details card + backend-associations card
    • StorageTierBackendAssociationsTable — one row per spec.backends entry (resolved name, protocol, bandwidth, quota, encryption)
    • StorageTierDetailActionButtons — Edit (navigate) / Delete (reuses StorageTierDeleteConfirmModal)
  • Refactor: extracted protocolLabel/uniqueBackendIds out of StorageTiersListPage.tsx into a shared storageTierBackendResolution.ts module, used by both the list and details pages
  • List page: StorageTiersListPage's Name column now links to the new details route
  • Routing: registered tiers/:id in StorageRoutes.tsx
  • Test infra: added an onStorageTierGet override to the shared mock Connect transport (existing pattern for other RPCs was missing on Get)
  • i18n: synced newly-extracted keys

Testing

  • Unit/component tests: 26 new tests across the new components/page, plus extensions to StorageTiersListPage.test.tsx (+1) and StorageRoutes.test.tsx (+1). Covers loading, full success rendering, status message present/absent, description present/absent, backend-name resolution and its raw-ID fallback, the resolution-failure warning banner, generic load error, not-found + return-to-list navigation, Edit navigation, delete success, and referential-integrity delete error.
  • Integration tests: N/A — UI-only change consuming an already-integrated private gRPC RPC; this repo has no persisted UI-level integration/E2E suite.
  • Coverage: comprehensive through public interfaces; full regression run (pnpm test) passes (two unrelated, pre-existing flaky timeouts observed under full-suite parallel load, both confirmed to pass in isolation — see validation report).

Acceptance Criteria

  • AC-1: /admin/infrastructure/storage/tiers/:id renders a details page for the tier fetched via usePrivateStorageTier(id).
  • AC-2: The Name column in StorageTiersListPage links to this route instead of rendering plain text.
  • AC-3: The page shows name, description, state (via StorageTierStatusLabel), and the status message when present.
  • AC-4: A table lists every entry in spec.backends, with the backend name resolved the same way StorageTiersListPage resolves it (falling back to backendId when resolution fails), its protocol, max read/write bandwidth, quota, and encryption enabled.
  • AC-5: Header actions match the row-actions kebab: Edit routes to /admin/infrastructure/storage/tiers/:id/edit; Delete opens StorageTierDeleteConfirmModal and navigates back to the list on success. (Implemented as two standalone buttons rather than a kebab dropdown — matches this codebase's only existing detail-page-header precedent (BareMetalActionButtons) and preserves identical behavior; flagging for reviewer awareness.)
  • AC-6: Deleting a tier that is referenced by a Tenant shows the server's error as-is without navigating away, consistent with the list page.
  • AC-7: Loading state uses ResourceDetailsPageLoading; an unknown/deleted ID or fetch failure uses ResourceDetailsPageError with a "Return to Storage Tiers" action.
  • AC-8: Breadcrumb: Storage Tiers ❭ {name}.
image

…ared module

Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
@openshift-ci-robot

openshift-ci-robot commented Aug 16, 2026

Copy link
Copy Markdown

@ElayAharoni: This pull request references OSAC-4026 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

OSAC-4026: [UI] Storage Tier details page

Jira: https://redhat.atlassian.net/browse/OSAC-4026
Story type: [UI]

Summary

Adds a StorageTierDetailsPage at /admin/infrastructure/storage/tiers/:id, giving a Cloud Provider Admin a full view of a single storage tier's backend associations (protocol, bandwidth, quota, encryption) before assigning it to a tenant or troubleshooting one. Follows the existing BareMetalDetailsPage/BareMetalDetails split — the only prior codebase precedent composing ResourceDetailHeader + ResourceDetailsPageLoading + ResourceDetailsPageError.

Changes

  • New pages/components:
  • StorageTierDetailsPage — data fetch via usePrivateStorageTier(id), loading/error/not-found branching
  • StorageTierDetails — presentational header + details card + backend-associations card
  • StorageTierBackendAssociationsTable — one row per spec.backends entry (resolved name, protocol, bandwidth, quota, encryption)
  • StorageTierDetailActionButtons — Edit (navigate) / Delete (reuses StorageTierDeleteConfirmModal)
  • Refactor: extracted protocolLabel/uniqueBackendIds out of StorageTiersListPage.tsx into a shared storageTierBackendResolution.ts module, used by both the list and details pages
  • List page: StorageTiersListPage's Name column now links to the new details route
  • Routing: registered tiers/:id in StorageRoutes.tsx
  • Test infra: added an onStorageTierGet override to the shared mock Connect transport (existing pattern for other RPCs was missing on Get)
  • i18n: synced newly-extracted keys

Testing

  • Unit/component tests: 26 new tests across the new components/page, plus extensions to StorageTiersListPage.test.tsx (+1) and StorageRoutes.test.tsx (+1). Covers loading, full success rendering, status message present/absent, description present/absent, backend-name resolution and its raw-ID fallback, the resolution-failure warning banner, generic load error, not-found + return-to-list navigation, Edit navigation, delete success, and referential-integrity delete error.
  • Integration tests: N/A — UI-only change consuming an already-integrated private gRPC RPC; this repo has no persisted UI-level integration/E2E suite.
  • Coverage: comprehensive through public interfaces; full regression run (pnpm test) passes (two unrelated, pre-existing flaky timeouts observed under full-suite parallel load, both confirmed to pass in isolation — see validation report).

Acceptance Criteria

  • AC-1: /admin/infrastructure/storage/tiers/:id renders a details page for the tier fetched via usePrivateStorageTier(id).
  • AC-2: The Name column in StorageTiersListPage links to this route instead of rendering plain text.
  • AC-3: The page shows name, description, state (via StorageTierStatusLabel), and the status message when present.
  • AC-4: A table lists every entry in spec.backends, with the backend name resolved the same way StorageTiersListPage resolves it (falling back to backendId when resolution fails), its protocol, max read/write bandwidth, quota, and encryption enabled.
  • AC-5: Header actions match the row-actions kebab: Edit routes to /admin/infrastructure/storage/tiers/:id/edit; Delete opens StorageTierDeleteConfirmModal and navigates back to the list on success. (Implemented as two standalone buttons rather than a kebab dropdown — matches this codebase's only existing detail-page-header precedent (BareMetalActionButtons) and preserves identical behavior; flagging for reviewer awareness.)
  • AC-6: Deleting a tier that is referenced by a Tenant shows the server's error as-is without navigating away, consistent with the list page.
  • AC-7: Loading state uses ResourceDetailsPageLoading; an unknown/deleted ID or fetch failure uses ResourceDetailsPageError with a "Return to Storage Tiers" action.
  • AC-8: Breadcrumb: Storage Tiers ❭ {name}.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d85ff33-d114-4c29-b63d-ba66d050950a


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.

@ElayAharoni
ElayAharoni marked this pull request as ready for review August 16, 2026 08:11
@ElayAharoni
ElayAharoni requested review from batzionb and rawagner and removed request for eliorerz and omer-vishlitzky August 16, 2026 08:12
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Signed-off-by: Elay Aharoni <elayaha@gmail.com>
Comment on lines +106 to +110
<Alert variant="warning" isInline title={t('Unable to resolve backend names')}>
{t(
'Backend IDs are shown in place of names until this recovers. This is separate from the normal fallback shown when a tier references a backend that no longer exists.',
)}
</Alert>

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.

just render the error as we typically do

Suggested change
<Alert variant="warning" isInline title={t('Unable to resolve backend names')}>
{t(
'Backend IDs are shown in place of names until this recovers. This is separate from the normal fallback shown when a tier references a backend that no longer exists.',
)}
</Alert>
<Alert variant="error" isInline title={t('Failed to fetch Storage backends')}>
{getErrorMessage(backendsError)}
</Alert>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — switched to the standard danger-alert-with-server-message pattern (getErrorMessage(backendsError)), matching StorageTierDeleteConfirmModal.tsx and friends. One tweak: Alert's variant is danger, not errorerror is a valid HelperTextItem variant but not a valid PatternFly Alert variant. Used danger to match every other error alert in this codebase. Fixed in 9d2034d.

Comment on lines +23 to +29
const { data: backends = [], error: backendsError } = usePrivateStorageBackends(
{ filter: storageBackendIdsFilter(backendIds) },
{ enabled: backendIds.length > 0 },
);
const backendsById = useMemo(
() => new Map(backends.map((backend) => [backend.id, backend])),
[backends],

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.

Lets move this to StorageTierDetails.tsx. You are not doing anything with this data in this component

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, moved — StorageTierDetailsPage now only fetches the tier itself; StorageTierDetails owns fetching and resolving its own backend associations. Fixed in 9d2034d.

import type { StorageTier } from '@osac/types/private';
import { StorageProtocol } from '@osac/types/private';

export const protocolLabel = (t: TFunction, protocol: StorageProtocol): string => {

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.

Lets use Record to get TS validation that we handle all cases of StorageProtocol

Suggested change
export const protocolLabel = (t: TFunction, protocol: StorageProtocol): string => {
export const protocolLabel = (t: TFunction): Record<StorageProtocol, string> => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed — also brings this in line with StorageTierStatusLabel's existing Record-based map, which this was inconsistent with. Fixed in 0196c31.

…ol-label mapping

Signed-off-by: Elay Aharoni <elayaha@gmail.com>
…rageTierDetails, render fetch errors verbatim

Signed-off-by: Elay Aharoni <elayaha@gmail.com>
@ElayAharoni
ElayAharoni requested a review from rawagner August 17, 2026 08:52
@openshift-ci

openshift-ci Bot commented Aug 17, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ElayAharoni, rawagner

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [ElayAharoni,rawagner]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot
openshift-merge-bot Bot merged commit 79af504 into osac-project:main Aug 17, 2026
7 checks passed
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.

3 participants