Skip to content

Commit d5f78df

Browse files
committed
feat(FR-2838): show private-deployment alert with access-token shortcut on deployment detail (#7294)
Resolves #7293 ([FR-2838](https://lablup.atlassian.net/browse/FR-2838)) > Stacked on #7287 (FR-2834). <img width="1231" height="601" alt="image" src="https://github.com/user-attachments/assets/b59e6692-6a8d-4b4e-95ff-3d3852c4db6d" /> ## Summary - Show an info `Alert` on the deployment detail page when the deployment is private (`openToPublic === false`) and not destroying. The alert names the state and offers a "Manage Access Tokens" action that smooth-scrolls to the access tokens section (`#deployment-access-tokens`). - Lifted all deployment-level alerts (`DeploymentReady`, `NoCurrentRevisionDeployed`, `PrivateDeployment`) and the `DeploymentAddRevisionModal` from `DeploymentConfigurationCards` up to `DeploymentDetailPage` so they live where they semantically belong (page-wide notifications, not tied to the configuration cards). - Lifted the page-level `fetchKey` / `revisionFetchKey` / refresh transition state to `DeploymentDetailPage`. `DeploymentConfigurationSection` now receives them via props and exposes `onAddRevision` for both the alert and the section's own "Add Revision" tab-bar button. - Added new i18n keys (`deployment.PrivateDeploymentAlertTitle`, `deployment.PrivateDeploymentAlertDescription`, `deployment.ManageAccessTokens`) across all 22 supported languages. ## Test plan - [ ] On a public deployment detail page, verify no private alert is shown. - [ ] On a private (`openToPublic = false`) deployment, verify the info alert appears with the expected title and description. - [ ] Click "Manage Access Tokens" and verify the page scrolls smoothly to the access tokens section. - [ ] Verify alert ordering is: DeploymentReady → NoCurrentRevisionDeployed → PrivateDeployment. - [ ] Verify the existing "Add Revision" tab-bar button in the configuration section still opens the AddRevision modal (now hosted by the page). - [ ] Verify the refresh button in the configuration overview still works and propagates the loading state. - [ ] On a destroying/stopped deployment, verify the private alert is suppressed. - [ ] Spot-check at least Korean, Japanese, and one Latin-script locale to confirm new keys are translated. [FR-2838]: https://lablup.atlassian.net/browse/FR-2838?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 18d3fe9 commit d5f78df

23 files changed

Lines changed: 219 additions & 103 deletions

react/src/components/DeploymentConfigurationSection.tsx

Lines changed: 21 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
*/
55
import { DeploymentConfigurationSectionQuery } from '../__generated__/DeploymentConfigurationSectionQuery.graphql';
66
import type { DeploymentRevisionDetail_revision$key } from '../__generated__/DeploymentRevisionDetail_revision.graphql';
7-
import { useSuspendedBackendaiClient, useWebUINavigate } from '../hooks';
8-
import DeploymentAddRevisionModal from './DeploymentAddRevisionModal';
97
import DeploymentRevisionDetail from './DeploymentRevisionDetail';
108
import DeploymentRevisionDetailDrawer from './DeploymentRevisionDetailDrawer';
119
import DeploymentRevisionHistoryTab from './DeploymentRevisionHistoryTab';
@@ -33,19 +31,21 @@ import {
3331
BooleanTag,
3432
INITIAL_FETCH_KEY,
3533
filterOutEmpty,
36-
toLocalId,
37-
useFetchKey,
3834
useInterval,
3935
} from 'backend.ai-ui';
40-
import { BotMessageSquareIcon } from 'lucide-react';
4136
import { parseAsStringLiteral, useQueryState } from 'nuqs';
42-
import React, { Suspense, useState, useTransition } from 'react';
37+
import React, { Suspense, useState } from 'react';
4338
import { useTranslation } from 'react-i18next';
4439
import { graphql, useLazyLoadQuery } from 'react-relay';
4540

4641
interface DeploymentConfigurationSectionProps {
4742
deploymentId: string;
4843
isDeploymentDestroying?: boolean;
44+
fetchKey: string;
45+
revisionFetchKey: string;
46+
isPendingRefetch: boolean;
47+
onRefetch: () => void;
48+
onAddRevision: () => void;
4949
}
5050

5151
type DeploymentSectionData =
@@ -141,13 +141,18 @@ const DeploymentOverviewContent: React.FC<{
141141

142142
const DeploymentConfigurationSection: React.FC<
143143
DeploymentConfigurationSectionProps
144-
> = ({ deploymentId, isDeploymentDestroying = false }) => {
144+
> = ({
145+
deploymentId,
146+
isDeploymentDestroying = false,
147+
fetchKey,
148+
revisionFetchKey,
149+
isPendingRefetch,
150+
onRefetch,
151+
onAddRevision,
152+
}) => {
145153
'use memo';
146154

147155
const { t } = useTranslation();
148-
const [isPendingRefetch, startRefetchTransition] = useTransition();
149-
const [fetchKey, updateFetchKey] = useFetchKey();
150-
const [revisionFetchKey, updateRevisionFetchKey] = useFetchKey();
151156
const [drawerState, setDrawerState] = useState<{
152157
revisionFrgmt: DeploymentRevisionDetail_revision$key;
153158
status?: 'current' | 'deploying' | 'none';
@@ -162,23 +167,12 @@ const DeploymentConfigurationSection: React.FC<
162167
setDrawerState({ revisionFrgmt: frgmt, status, title });
163168
};
164169

165-
const handleRefetch = () => {
166-
startRefetchTransition(() => updateFetchKey());
167-
};
168-
169-
const handleRevisionAdded = () => {
170-
startRefetchTransition(() => {
171-
updateFetchKey();
172-
updateRevisionFetchKey();
173-
});
174-
};
175-
176170
const overviewExtra = (
177171
<BAIFlex gap="xs" align="center">
178172
<BAIFetchKeyButton
179173
loading={isPendingRefetch}
180174
value=""
181-
onChange={handleRefetch}
175+
onChange={onRefetch}
182176
/>
183177
</BAIFlex>
184178
);
@@ -218,9 +212,9 @@ const DeploymentConfigurationSection: React.FC<
218212
revisionFetchKey={revisionFetchKey}
219213
overviewExtra={overviewExtra}
220214
onShowRevisionDrawer={handleShowRevisionDrawer}
221-
onRevisionAdded={handleRevisionAdded}
215+
onAddRevision={onAddRevision}
222216
isDeploymentDestroying={isDeploymentDestroying}
223-
onRefetch={handleRefetch}
217+
onRefetch={onRefetch}
224218
/>
225219
</Suspense>
226220
<BAIUnmountAfterClose>
@@ -252,7 +246,7 @@ const DeploymentConfigurationCards: React.FC<{
252246
status?: 'current' | 'deploying' | 'none',
253247
title?: string,
254248
) => void;
255-
onRevisionAdded: () => void;
249+
onAddRevision: () => void;
256250
isDeploymentDestroying?: boolean;
257251
onRefetch: () => void;
258252
}> = ({
@@ -261,16 +255,13 @@ const DeploymentConfigurationCards: React.FC<{
261255
revisionFetchKey,
262256
overviewExtra,
263257
onShowRevisionDrawer,
264-
onRevisionAdded,
258+
onAddRevision,
265259
isDeploymentDestroying = false,
266260
onRefetch,
267261
}) => {
268262
'use memo';
269263
const { t } = useTranslation();
270264
const { token } = theme.useToken();
271-
const webuiNavigate = useWebUINavigate();
272-
const baiClient = useSuspendedBackendaiClient();
273-
const isChatBlocked = !!baiClient?._config?.blockList?.includes('chat');
274265

275266
const [activeRevisionTab, setActiveRevisionTab] = useQueryState(
276267
'revisionTab',
@@ -287,10 +278,6 @@ const DeploymentConfigurationCards: React.FC<{
287278
settingModalOpen,
288279
{ setLeft: closeSettingModal, setRight: openSettingModal },
289280
] = useToggle(false);
290-
const [
291-
addRevisionOpen,
292-
{ toggle: toggleAddRevision, setLeft: closeAddRevision },
293-
] = useToggle(false);
294281

295282
const { deployment } = useLazyLoadQuery<DeploymentConfigurationSectionQuery>(
296283
graphql`
@@ -339,12 +326,10 @@ const DeploymentConfigurationCards: React.FC<{
339326
},
340327
);
341328

342-
const hasNoRevision = !deployment?.currentRevision;
343329
const currentRevision = deployment?.currentRevision;
344330
const deployingRevision = deployment?.deployingRevision;
345331
const isDeployingDifferentRevision =
346332
!!deployingRevision && deployingRevision.id !== currentRevision?.id;
347-
const isDeploymentReady = deployment?.metadata.status === 'READY';
348333

349334
// While a different revision is being applied, poll so the UI moves off
350335
// the "applying" state once the deployment finishes rolling out. We don't
@@ -354,49 +339,6 @@ const DeploymentConfigurationCards: React.FC<{
354339

355340
return (
356341
<>
357-
{isDeploymentReady && !hasNoRevision && (
358-
<Alert
359-
type="success"
360-
showIcon
361-
title={t('deployment.DeploymentReady')}
362-
action={
363-
!isChatBlocked && (
364-
<Button
365-
type="primary"
366-
icon={<BotMessageSquareIcon size={token.fontSizeLG} />}
367-
onClick={() => {
368-
webuiNavigate({
369-
pathname: '/chat',
370-
search: new URLSearchParams({
371-
endpointId: toLocalId(deploymentId),
372-
}).toString(),
373-
});
374-
}}
375-
>
376-
{t('deployment.StartChatTest')}
377-
</Button>
378-
)
379-
}
380-
/>
381-
)}
382-
{hasNoRevision && (
383-
<Alert
384-
type="info"
385-
showIcon
386-
title={t('deployment.NoCurrentRevisionDeployed')}
387-
description={t('deployment.NoCurrentRevisionDeployedDescription')}
388-
action={
389-
<Button
390-
type="primary"
391-
icon={<PlusOutlined />}
392-
onClick={toggleAddRevision}
393-
disabled={isDeploymentDestroying}
394-
>
395-
{t('deployment.AddRevision')}
396-
</Button>
397-
}
398-
/>
399-
)}
400342
<BAICard
401343
title={t('deployment.BasicInformation')}
402344
extra={
@@ -437,7 +379,7 @@ const DeploymentConfigurationCards: React.FC<{
437379
type="primary"
438380
icon={<PlusOutlined />}
439381
disabled={isDeploymentDestroying}
440-
onClick={toggleAddRevision}
382+
onClick={onAddRevision}
441383
>
442384
{t('deployment.AddRevision')}
443385
</Button>
@@ -503,17 +445,6 @@ const DeploymentConfigurationCards: React.FC<{
503445
if (success) onRefetch();
504446
}}
505447
/>
506-
<BAIUnmountAfterClose>
507-
<DeploymentAddRevisionModal
508-
open={addRevisionOpen}
509-
onCancel={closeAddRevision}
510-
onSuccess={() => {
511-
closeAddRevision();
512-
onRevisionAdded();
513-
}}
514-
deploymentId={deploymentId}
515-
/>
516-
</BAIUnmountAfterClose>
517448
</>
518449
);
519450
};

0 commit comments

Comments
 (0)