Skip to content

Commit b8bcd94

Browse files
committed
fix(FR-2813): render folder-create notification with VFolder node card
1 parent 052967a commit b8bcd94

5 files changed

Lines changed: 58 additions & 41 deletions

File tree

react/src/components/BAINodeNotificationItem.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*/
55
import { NotificationState } from '../hooks/useBAINotification';
66
import BAIComputeSessionNodeNotificationItem from './BAIComputeSessionNodeNotificationItem';
7-
import BAIVFolderNotificationItem from './BAIVFolderNotificationItem';
87
import BAIVirtualFolderNodeNotificationItem from './BAIVirtualFolderNodeNotificationItem';
8+
import BAIVirtualFolderNodeNotificationItemV2 from './BAIVirtualFolderNodeNotificationItemV2';
99
import React from 'react';
1010
import { graphql, useRefetchableFragment } from 'react-relay';
1111
import { BAINodeNotificationItemFragment$key } from 'src/__generated__/BAINodeNotificationItemFragment.graphql';
@@ -28,7 +28,8 @@ const nodeFragmentOperation = graphql`
2828
}
2929
... on VFolder {
3030
__typename
31-
...BAIVFolderNotificationItemFragment @alias(as: "vfolderFrgmt")
31+
...BAIVirtualFolderNodeNotificationItemV2Fragment
32+
@alias(as: "vfolderFrgmt")
3233
}
3334
... on VirtualFolderNode {
3435
__typename
@@ -57,7 +58,7 @@ const BAINodeNotificationItem: React.FC<{
5758
);
5859
} else if (node?.__typename === 'VFolder') {
5960
return (
60-
<BAIVFolderNotificationItem
61+
<BAIVirtualFolderNodeNotificationItemV2
6162
notification={notification}
6263
vfolderFrgmt={node.vfolderFrgmt || null}
6364
showDate={showDate}

react/src/components/BAIVirtualFolderNodeNotificationItem.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Copyright (c) 2015-2026 Lablup Inc. All rights reserved.
44
*/
55
import BAINotificationBackgroundProgress from './BAINotificationBackgroundProgress';
6+
import { useFolderExplorerOpener } from './FolderExplorerOpener';
67
import { useToggle } from 'ahooks';
78
import { Card, List, theme, Typography } from 'antd';
89
import { BAIFlex, BAILink, BAINotificationItem, BAIText } from 'backend.ai-ui';
@@ -11,7 +12,6 @@ import * as _ from 'lodash-es';
1112
import { useTranslation } from 'react-i18next';
1213
import { graphql, useFragment } from 'react-relay';
1314
import { BAIVirtualFolderNodeNotificationItemFragment$key } from 'src/__generated__/BAIVirtualFolderNodeNotificationItemFragment.graphql';
14-
import { useWebUINavigate } from 'src/hooks';
1515
import {
1616
NotificationState,
1717
useSetBAINotification,
@@ -25,7 +25,7 @@ interface BAIVirtualFolderNodeNotificationItemProps {
2525

2626
/**
2727
* @deprecated Renders V1 `VirtualFolderNode` notifications. The V2 counterpart
28-
* `BAIVFolderNotificationItem` (operating on `VFolder implements Node` from
28+
* `BAIVirtualFolderNodeNotificationItemV2` (operating on `VFolder implements Node` from
2929
* the Strawberry GraphQL API, FR-2573) is the preferred path going forward.
3030
* This component will be removed once all V1 callers migrate.
3131
*/
@@ -34,7 +34,7 @@ const BAIVirtualFolderNodeNotificationItem: React.FC<
3434
> = ({ notification, virtualFolderNodeFrgmt, showDate }) => {
3535
'use memo';
3636

37-
const navigate = useWebUINavigate();
37+
const { open: openFolderExplorer } = useFolderExplorerOpener();
3838
const { t } = useTranslation();
3939
const { token } = theme.useToken();
4040
const { closeNotification } = useSetBAINotification();
@@ -65,9 +65,9 @@ const BAIVirtualFolderNodeNotificationItem: React.FC<
6565
}}
6666
title={node.name || ''}
6767
onClick={() => {
68-
navigate(
69-
`/data${node.row_id ? `?${new URLSearchParams({ folder: node.row_id }).toString()}` : ''}`,
70-
);
68+
if (node.row_id) {
69+
openFolderExplorer(node.row_id);
70+
}
7171
closeNotification(notification.key);
7272
}}
7373
>

react/src/components/BAIVFolderNotificationItem.tsx renamed to react/src/components/BAIVirtualFolderNodeNotificationItemV2.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Copyright (c) 2015-2026 Lablup Inc. All rights reserved.
44
*/
55
import BAINotificationBackgroundProgress from './BAINotificationBackgroundProgress';
6+
import { useFolderExplorerOpener } from './FolderExplorerOpener';
67
import { useToggle } from 'ahooks';
78
import { Card, List, theme, Typography } from 'antd';
89
import {
@@ -16,16 +17,15 @@ import dayjs from 'dayjs';
1617
import * as _ from 'lodash-es';
1718
import { useTranslation } from 'react-i18next';
1819
import { graphql, useFragment } from 'react-relay';
19-
import { BAIVFolderNotificationItemFragment$key } from 'src/__generated__/BAIVFolderNotificationItemFragment.graphql';
20-
import { useWebUINavigate } from 'src/hooks';
20+
import { BAIVirtualFolderNodeNotificationItemV2Fragment$key } from 'src/__generated__/BAIVirtualFolderNodeNotificationItemV2Fragment.graphql';
2121
import {
2222
NotificationState,
2323
useSetBAINotification,
2424
} from 'src/hooks/useBAINotification';
2525

26-
interface BAIVFolderNotificationItemProps {
26+
interface BAIVirtualFolderNodeNotificationItemV2Props {
2727
notification: NotificationState;
28-
vfolderFrgmt: BAIVFolderNotificationItemFragment$key | null;
28+
vfolderFrgmt: BAIVirtualFolderNodeNotificationItemV2Fragment$key | null;
2929
showDate?: boolean;
3030
}
3131

@@ -34,14 +34,12 @@ interface BAIVFolderNotificationItemProps {
3434
// list/mutation flows can pass `node: vfolder` to `upsertNotification` and
3535
// get the same rich folder-link + extra-description rendering as the legacy
3636
// V1 path. The V1 component stays in place until all callers migrate.
37-
const BAIVFolderNotificationItem: React.FC<BAIVFolderNotificationItemProps> = ({
38-
notification,
39-
vfolderFrgmt,
40-
showDate,
41-
}) => {
37+
const BAIVirtualFolderNodeNotificationItemV2: React.FC<
38+
BAIVirtualFolderNodeNotificationItemV2Props
39+
> = ({ notification, vfolderFrgmt, showDate }) => {
4240
'use memo';
4341

44-
const navigate = useWebUINavigate();
42+
const { open: openFolderExplorer } = useFolderExplorerOpener();
4543
const { t } = useTranslation();
4644
const { token } = theme.useToken();
4745
const { closeNotification } = useSetBAINotification();
@@ -50,7 +48,7 @@ const BAIVFolderNotificationItem: React.FC<BAIVFolderNotificationItemProps> = ({
5048

5149
const node = useFragment(
5250
graphql`
53-
fragment BAIVFolderNotificationItemFragment on VFolder {
51+
fragment BAIVirtualFolderNodeNotificationItemV2Fragment on VFolder {
5452
id
5553
metadata {
5654
name
@@ -76,9 +74,9 @@ const BAIVFolderNotificationItem: React.FC<BAIVFolderNotificationItemProps> = ({
7674
}}
7775
title={folderName || ''}
7876
onClick={() => {
79-
navigate(
80-
`/data${localId ? `?${new URLSearchParams({ folder: localId }).toString()}` : ''}`,
81-
);
77+
if (localId) {
78+
openFolderExplorer(localId);
79+
}
8280
closeNotification(notification.key);
8381
}}
8482
>
@@ -148,4 +146,4 @@ const BAIVFolderNotificationItem: React.FC<BAIVFolderNotificationItemProps> = ({
148146
);
149147
};
150148

151-
export default BAIVFolderNotificationItem;
149+
export default BAIVirtualFolderNodeNotificationItemV2;

react/src/components/FolderCreateModalV2.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ const FolderCreateModalV2: React.FC<FolderCreateModalProps> = ({
197197
createVfolderV2(input: $input) {
198198
vfolder {
199199
id
200-
status
200+
vfolderStatus: status
201201
host
202202
metadata {
203203
name
@@ -214,6 +214,7 @@ const FolderCreateModalV2: React.FC<FolderCreateModalProps> = ({
214214
projectId
215215
creatorEmail
216216
}
217+
...BAINodeNotificationItemFragment @alias(as: "notificationFrgmt")
217218
}
218219
}
219220
}
@@ -232,7 +233,7 @@ const FolderCreateModalV2: React.FC<FolderCreateModalProps> = ({
232233
createVFolderInProject(projectId: $projectId, input: $input) {
233234
vfolder {
234235
id
235-
status
236+
vfolderStatus: status
236237
host
237238
metadata {
238239
name
@@ -249,6 +250,7 @@ const FolderCreateModalV2: React.FC<FolderCreateModalProps> = ({
249250
projectId
250251
creatorEmail
251252
}
253+
...BAINodeNotificationItemFragment @alias(as: "notificationFrgmt")
252254
}
253255
}
254256
}
@@ -323,19 +325,14 @@ const FolderCreateModalV2: React.FC<FolderCreateModalProps> = ({
323325
user: vfolder.ownership.userId ?? '',
324326
group: vfolder.ownership.projectId ?? null,
325327
cloneable: vfolder.metadata.cloneable,
326-
status: vfolder.status ?? '',
328+
status: vfolder.vfolderStatus ?? '',
327329
};
328330

329331
upsertNotification({
330332
key: `folder-create-success-${result.id}`,
331333
icon: 'folder',
332-
message: `${result.name}: ${t('data.folders.FolderCreated')}`,
333-
toText: t('data.folders.OpenAFolder'),
334-
to: {
335-
search: new URLSearchParams({
336-
folder: result.id,
337-
}).toString(),
338-
},
334+
node: vfolder.notificationFrgmt ?? null,
335+
description: t('data.folders.FolderCreated'),
339336
open: true,
340337
});
341338
document.dispatchEvent(new CustomEvent('backend-ai-folder-list-changed'));

react/src/components/ImportRepoForm.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,30 @@ import {
1515
} from 'antd';
1616
import {
1717
BAIButton,
18+
toGlobalId,
1819
useBAILogger,
1920
useErrorMessageResolver,
2021
useGetAvailableFolderName,
2122
} from 'backend.ai-ui';
2223
import { FolderInput } from 'lucide-react';
2324
import { useRef } from 'react';
2425
import { useTranslation } from 'react-i18next';
26+
import { fetchQuery, graphql, useRelayEnvironment } from 'react-relay';
27+
import { ImportRepoFormVFolderNotificationQuery } from 'src/__generated__/ImportRepoFormVFolderNotificationQuery.graphql';
2528
import { useSetBAINotification } from 'src/hooks/useBAINotification';
2629
import {
2730
StartSessionWithDefaultValue,
2831
useStartSession,
2932
} from 'src/hooks/useStartSession';
3033

34+
const IMPORT_REPO_FORM_VFOLDER_NOTIFICATION_QUERY = graphql`
35+
query ImportRepoFormVFolderNotificationQuery($id: String!) {
36+
vfolder_node(id: $id) {
37+
...BAINodeNotificationItemFragment @alias(as: "notificationFrgmt")
38+
}
39+
}
40+
`;
41+
3142
type URLType = 'github' | 'gitlab';
3243

3344
type VFolderUsageModeForImport = 'general' | 'model';
@@ -94,6 +105,7 @@ const ImportRepoForm: React.FC<ImportFromURLFormProps> = ({
94105
const formRef = useRef<FormInstance<ImportFromURLFormValues> | null>(null);
95106
const baiClient = useSuspendedBackendaiClient();
96107
const { upsertNotification } = useSetBAINotification();
108+
const relayEnv = useRelayEnvironment();
97109
const app = App.useApp();
98110
const { getErrorMessage } = useErrorMessageResolver();
99111

@@ -226,16 +238,25 @@ const ImportRepoForm: React.FC<ImportFromURLFormProps> = ({
226238
'rw', // permission
227239
);
228240

241+
// REST `/folders` does not return a Relay fragment, so query the new
242+
// VirtualFolderNode by id to drive the rich folder-card notification
243+
// (BAINodeNotificationItem). Falls back gracefully — if the node is
244+
// unreachable, the notification still opens but without the folder-link
245+
// header; the import session creation flow continues regardless.
246+
const notificationData =
247+
await fetchQuery<ImportRepoFormVFolderNotificationQuery>(
248+
relayEnv,
249+
IMPORT_REPO_FORM_VFOLDER_NOTIFICATION_QUERY,
250+
{ id: toGlobalId('VirtualFolderNode', vfolderInfo.id) },
251+
)
252+
.toPromise()
253+
.catch(() => null);
254+
229255
upsertNotification({
230256
key: `folder-create-success-${vfolderInfo.id}`,
231257
icon: 'folder',
232-
message: `${vfolderInfo.name}: ${t('data.folders.FolderCreated')}`,
233-
toText: t('data.folders.OpenAFolder'),
234-
to: {
235-
search: new URLSearchParams({
236-
folder: vfolderInfo.id,
237-
}).toString(),
238-
},
258+
node: notificationData?.vfolder_node?.notificationFrgmt ?? undefined,
259+
description: t('data.folders.FolderCreated'),
239260
open: true,
240261
duration: 0,
241262
});

0 commit comments

Comments
 (0)