refactor(FR-2772): unify deployment card UX with BAICard conventions#7146
Conversation
Coverage report for
|
St.❔ |
Category | Percentage | Covered / Total |
|---|---|---|---|
| 🔴 | Statements | 8.12% (-0.01% 🔻) |
1859/22897 |
| 🔴 | Branches | 7.35% (-0.01% 🔻) |
1187/16152 |
| 🔴 | Functions | 4.83% (+0.01% 🔼) |
297/6152 |
| 🔴 | Lines | 7.89% (-0.01% 🔻) |
1750/22183 |
Test suite run success
865 tests passing in 40 suites.
Report generated by 🧪jest coverage report action from ca553e6
ad435dd to
aafe474
Compare
There was a problem hiding this comment.
Pull request overview
Refactors deployment pages/components to align card-based sections with Backend.AI’s BAICard UX conventions (header/extra layout, Suspense-in-card pattern), and adjusts supporting components to match the new structure.
Changes:
- Migrate deployment detail sections from
antdCardtoBAICard, moving section-level actions (refresh/add) into card headers. - Refactor
DeploymentConfigurationSectioninto multiple Suspense-friendly subcomponents/queries and add a “current revision” modal that unmounts after close. - Introduce an internal rule for using
BAICardconsistently (.claude/rules/use-bai-card.md) and adjust related components (status tag colors, list nullability, Skeleton fallbacks).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| react/src/pages/DeploymentListPage.tsx | Always renders DeploymentList (now nullable-friendly) inside a BAICard + Suspense layout. |
| react/src/pages/AdminDeploymentListPage.tsx | Same structural change as user list; keeps tabbed BAICard container. |
| react/src/pages/DeploymentDetailPage.tsx | Replaces antd Cards with BAICard/card-owned sections and simplifies Suspense placement. |
| react/src/components/DeploymentStatusTag.tsx | Adjusts tag color mapping to use antd preset status colors (e.g., processing). |
| react/src/components/DeploymentList.tsx | Makes fragment prop nullable and updates table rendering (notably removes custom empty text). |
| react/src/components/DeploymentConfigurationSection.tsx | Large refactor: split into overview/revision/modal content components with Suspense + BAICard. |
| react/src/components/DeploymentAutoScalingTab.tsx | Wraps autoscaling list in BAICard with header actions and Suspense. |
| react/src/components/DeploymentAddRevisionModal.tsx | Switches Suspense fallback from spinner to Skeleton. |
| react/src/components/DeploymentAccessTokensTab.tsx | Wraps access tokens UI in BAICard; moves fetch into an inner Suspense component. |
| react/src/components/AutoScalingRuleList.tsx | Adds header-action hiding flags and attempts to expose an imperative “open add modal” API. |
| .claude/rules/use-bai-card.md | Adds repository guidance for BAICard usage and padding/Suspense conventions. |
Comments suppressed due to low confidence (2)
react/src/components/AutoScalingRuleList.tsx:355
AutoScalingRuleListis trying to expose an imperative API viaref, butrefis a reserved React attribute and is not delivered to function components as a normal prop. As written,refhere will always beundefined, souseImperativeHandle()won’t connect and callers like<AutoScalingRuleList ref={...} />won’t be able to open the add modal.
Convert this component to React.forwardRef (and remove ref from AutoScalingRuleListProps) so the parent can receive a working AutoScalingRuleListRef handle.
ref?: React.Ref<AutoScalingRuleListRef>;
}
const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
deploymentId,
react/src/components/DeploymentList.tsx:450
- The table’s custom empty-state copy was removed (
locale.emptyText: t('deployment.NoDeployments')). Without this, the empty state falls back to Ant Design’s default (which may be generic and/or not match the intended deployment-specific messaging).
Consider restoring a localized locale.emptyText (or provide an equivalent empty-state via BAITable/BAICard conventions) so an empty deployment list shows the expected message.
<BAITable<DeploymentNode>
rowKey="id"
scroll={{ x: 'max-content' }}
showSorterTooltip={false}
{...tableProps}
1a6e009 to
a254fa5
Compare
aafe474 to
2f19399
Compare
Merge activity
|
…7146) Resolves #7145 ([FR-2772](https://lablup.atlassian.net/browse/FR-2772)) ## Summary - All deployment cards now use `BAICard` with `styles={{ body: { paddingTop: 0 } }}` so the body sits flush against the header. Tabbed `BAICard`s keep BAICard's default tab-aware paddingTop. - Card-scoped actions (refresh button, primary `+ Add` / `+ Create`, `Edit configuration`) live in `BAICard.extra`. Only content-scoped controls (filter, search) remain inside the body. - Suspense boundary now lives **inside** each card so the header is always visible while the body shows `Skeleton active`. - `DeploymentConfigurationSection` is split into `DeploymentOverviewContent`, `DeploymentRevisionInfoContent`, and `DeploymentCurrentRevisionModalContent`. Each owns its own `useLazyLoadQuery` and internal `Suspense` / `Skeleton`. `currentRevision { id }` was added to the parent fragment so the Revision Info card's frame can be rendered conditionally without waiting for the inner fetch. - `AutoScalingRuleList` gained `hideInlineAddButton` / `hideInlineRefreshButton` props and an imperative `ref` exposing `openAddModal()`, so `DeploymentAutoScalingTab` can render the title, refresh, and `+ Add rule` button in the card `extra` while the list owns the editor modal. EndpointDetailPage usage is unaffected (defaults preserved). - `DeploymentAccessTokensTab` is wrapped in its own BAICard with refresh + create in `extra`; the list query was extracted into `DeploymentAccessTokensTable` so the card header stays visible during fetch. - `Descriptions` no longer overrides `backgroundColor` to `colorBgBase` — label / value strips render correctly in dark mode (the `colorFillAlter` label band is restored). - `DeploymentStatusTag` maps in-flight statuses (`DEPLOYING`, `SCALING`, `PENDING`) to `'processing'` instead of the non-preset `'info'`, fixing the vivid dark-mode tag and matching the doc-comment intent. - `DeploymentList`'s `deploymentsFrgmt` prop is nullable; both `DeploymentListPage` and `AdminDeploymentListPage` drop the `: null` branch so transient `myDeployments === null` shows the toolbar + empty table instead of an empty card. - Add Revision modal Suspense fallback unified to `Skeleton active` (was a centered `Spin`). - New `.claude/rules/use-bai-card.md` documents the BAICard convention: prefer over `Card`, `body.paddingTop: 0` (except tabbed), card-scoped actions go in `extra`, Suspense lives inside the card with `Skeleton` fallback. ## Test plan - [ ] `bash scripts/verify.sh` passes (Relay / Lint / Format / TypeScript). - [ ] Deployment list page (light + dark): toolbar (filter, search, refresh, create) renders normally; navigating into a deployment and back does not leave an empty card — table + "no data" / rows render. - [ ] Deployment detail page (light + dark): Overview, Revision Info, AutoScaling, Access Tokens, Replicas/Revisions tabs all show their card title during loading; bodies show `Skeleton`; refresh + primary action sit in each card header. - [ ] Descriptions in Overview / Revision Info: in dark mode the label column shows the `colorFillAlter` band and the value column matches card background (no flat black plane). - [ ] Status tag: an in-flight deployment (e.g. `DEPLOYING` / `PENDING`) shows the antd `processing` preset (transparent body, processing dot) — not the vivid default tag. - [ ] AutoScaling card: clicking `+ Add rule` in the card header opens the editor modal; refresh button in header refetches; AutoScalingRuleList in `EndpointDetailPage` (legacy) still has its inline buttons (no regression). - [ ] Access Tokens card: clicking `+ Create access token` in the card header opens the create modal; refresh button in header refetches. - [ ] Add Revision modal: while loading, body shows `Skeleton`, not a centered spinner. [FR-2772]: https://lablup.atlassian.net/browse/FR-2772?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
a254fa5 to
5de1b0e
Compare
2f19399 to
ca553e6
Compare

Resolves #7145 (FR-2772)
Summary
BAICardwithstyles={{ body: { paddingTop: 0 } }}so the body sits flush against the header. TabbedBAICards keep BAICard's default tab-aware paddingTop.+ Add/+ Create,Edit configuration) live inBAICard.extra. Only content-scoped controls (filter, search) remain inside the body.Skeleton active.DeploymentConfigurationSectionis split intoDeploymentOverviewContent,DeploymentRevisionInfoContent, andDeploymentCurrentRevisionModalContent. Each owns its ownuseLazyLoadQueryand internalSuspense/Skeleton.currentRevision { id }was added to the parent fragment so the Revision Info card's frame can be rendered conditionally without waiting for the inner fetch.AutoScalingRuleListgainedhideInlineAddButton/hideInlineRefreshButtonprops and an imperativerefexposingopenAddModal(), soDeploymentAutoScalingTabcan render the title, refresh, and+ Add rulebutton in the cardextrawhile the list owns the editor modal. EndpointDetailPage usage is unaffected (defaults preserved).DeploymentAccessTokensTabis wrapped in its own BAICard with refresh + create inextra; the list query was extracted intoDeploymentAccessTokensTableso the card header stays visible during fetch.Descriptionsno longer overridesbackgroundColortocolorBgBase— label / value strips render correctly in dark mode (thecolorFillAlterlabel band is restored).DeploymentStatusTagmaps in-flight statuses (DEPLOYING,SCALING,PENDING) to'processing'instead of the non-preset'info', fixing the vivid dark-mode tag and matching the doc-comment intent.DeploymentList'sdeploymentsFrgmtprop is nullable; bothDeploymentListPageandAdminDeploymentListPagedrop the: nullbranch so transientmyDeployments === nullshows the toolbar + empty table instead of an empty card.Skeleton active(was a centeredSpin)..claude/rules/use-bai-card.mddocuments the BAICard convention: prefer overCard,body.paddingTop: 0(except tabbed), card-scoped actions go inextra, Suspense lives inside the card withSkeletonfallback.Test plan
bash scripts/verify.shpasses (Relay / Lint / Format / TypeScript).Skeleton; refresh + primary action sit in each card header.colorFillAlterband and the value column matches card background (no flat black plane).DEPLOYING/PENDING) shows the antdprocessingpreset (transparent body, processing dot) — not the vivid default tag.+ Add rulein the card header opens the editor modal; refresh button in header refetches; AutoScalingRuleList inEndpointDetailPage(legacy) still has its inline buttons (no regression).+ Create access tokenin the card header opens the create modal; refresh button in header refetches.Skeleton, not a centered spinner.