Skip to content

Commit 838f284

Browse files
committed
feat(FR-1093): migrate file browser function to react
1 parent 601fe05 commit 838f284

File tree

1 file changed

+160
-7
lines changed

1 file changed

+160
-7
lines changed

react/src/components/FolderExplorerHeader.tsx

Lines changed: 160 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import { FolderExplorerHeaderFragment$key } from '../__generated__/FolderExplorerHeaderFragment.graphql';
22
import EditableVFolderName from './EditableVFolderName';
33
import VFolderNodeIdenticon from './VFolderNodeIdenticon';
4-
import { Button, Tooltip, Image, Grid, theme, Typography } from 'antd';
4+
import { Button, Tooltip, Image, Grid, theme, Typography, App } from 'antd';
55
import { BAIFlex } from 'backend.ai-ui';
6-
import React, { LegacyRef } from 'react';
6+
import _ from 'lodash';
7+
import React, { LegacyRef, useState } from 'react';
78
import { useTranslation } from 'react-i18next';
8-
import { graphql, useFragment } from 'react-relay';
9+
import {
10+
fetchQuery,
11+
graphql,
12+
useFragment,
13+
useRelayEnvironment,
14+
} from 'react-relay';
15+
import { FolderExplorerHeader_ImageQuery } from 'src/__generated__/FolderExplorerHeader_ImageQuery.graphql';
16+
import { getImageFullName } from 'src/helper';
17+
import { useSuspendedBackendaiClient } from 'src/hooks';
18+
import { useStartSession } from 'src/hooks/useStartSession';
19+
import { SessionLauncherFormValue } from 'src/pages/SessionLauncherPage';
920

1021
interface FolderExplorerHeaderProps {
1122
vfolderNodeFrgmt?: FolderExplorerHeaderFragment$key | null;
@@ -18,16 +29,27 @@ const FolderExplorerHeader: React.FC<FolderExplorerHeaderProps> = ({
1829
folderExplorerRef,
1930
titleStyle,
2031
}) => {
32+
'use memo';
33+
2134
const { t } = useTranslation();
2235
const { token } = theme.useToken();
2336
const { lg } = Grid.useBreakpoint();
37+
const { message } = App.useApp();
38+
39+
const relayEnv = useRelayEnvironment();
40+
const baiClient = useSuspendedBackendaiClient();
41+
const { startSession, defaultFormValues, upsertSessionNotification } =
42+
useStartSession();
43+
const [isLoadingToStartFileBrowser, setIsLoadingToStartFileBrowser] =
44+
useState(false);
2445

2546
const vfolderNode = useFragment(
2647
graphql`
2748
fragment FolderExplorerHeaderFragment on VirtualFolderNode {
2849
id
2950
user
3051
permission
52+
row_id @required(action: THROW)
3153
unmanaged_path @since(version: "25.04.0")
3254
...VFolderNameTitleNodeFragment
3355
...VFolderNodeIdenticonFragment
@@ -105,10 +127,141 @@ const FolderExplorerHeader: React.FC<FolderExplorerHeaderProps> = ({
105127
preview={false}
106128
/>
107129
}
108-
onClick={() =>
109-
// @ts-ignore
110-
folderExplorerRef.current?._executeFileBrowser()
111-
}
130+
loading={isLoadingToStartFileBrowser}
131+
onClick={() => {
132+
// FIXME: Currently, file browser filtering by server-side is not supported.
133+
setIsLoadingToStartFileBrowser(true);
134+
fetchQuery<FolderExplorerHeader_ImageQuery>(
135+
relayEnv,
136+
graphql`
137+
query FolderExplorerHeader_ImageQuery(
138+
$installed: Boolean
139+
) {
140+
images(is_installed: $installed) {
141+
id
142+
name @deprecatedSince(version: "24.12.0")
143+
humanized_name
144+
tag
145+
registry
146+
architecture
147+
digest
148+
installed
149+
resource_limits {
150+
key
151+
min
152+
max
153+
}
154+
labels {
155+
key
156+
value
157+
}
158+
namespace @since(version: "24.12.0")
159+
base_image_name @since(version: "24.12.0")
160+
tags @since(version: "24.12.0") {
161+
key
162+
value
163+
}
164+
version @since(version: "24.12.0")
165+
supported_accelerators
166+
}
167+
}
168+
`,
169+
{
170+
installed: true,
171+
},
172+
{
173+
fetchPolicy: 'store-or-network',
174+
},
175+
)
176+
.toPromise()
177+
.then((response) =>
178+
response?.images?.filter((image) =>
179+
image?.labels?.find(
180+
(label) =>
181+
label?.key === 'ai.backend.service-ports' &&
182+
label?.value?.toLowerCase().includes('filebrowser'),
183+
),
184+
),
185+
)
186+
.then((filebrowserImages) => {
187+
if (_.isEmpty(filebrowserImages)) {
188+
message.error(
189+
t('data.explorer.NoImagesSupportingFileBrowser'),
190+
);
191+
setIsLoadingToStartFileBrowser(false);
192+
return;
193+
}
194+
195+
const registry = filebrowserImages?.[0]?.registry;
196+
const namespace = filebrowserImages?.[0]?.namespace;
197+
const customizedImageTag = _.find(
198+
filebrowserImages?.[0]?.labels,
199+
(item) =>
200+
item !== null &&
201+
item?.key === 'ai.backend.customized-image.name',
202+
)?.value;
203+
const fileBrowserFormValue: DeepPartial<SessionLauncherFormValue> =
204+
{
205+
sessionName: `filebrowser-${vfolderNode?.row_id.split('-')[0]}`,
206+
sessionType: 'interactive',
207+
// use systemSSHImage if configured and allowed
208+
...(baiClient._config?.systemSSHImage &&
209+
baiClient._config?.allow_manual_image_name_for_session
210+
? {
211+
environments: {
212+
environment: baiClient._config.systemSSHImage,
213+
},
214+
}
215+
: // otherwise use the first image found
216+
{
217+
environments: {
218+
customizedTag:
219+
customizedImageTag || undefined,
220+
environment: `${registry}/${namespace}`,
221+
image: filebrowserImages?.[0],
222+
version: getImageFullName(
223+
filebrowserImages?.[0],
224+
),
225+
},
226+
}),
227+
allocationPreset: 'minimum-required',
228+
cluster_mode: 'single-node',
229+
cluster_size: 1,
230+
mount_ids: [
231+
vfolderNode?.row_id?.replaceAll('-', '') || '',
232+
],
233+
resource: {
234+
cpu: 1,
235+
mem: '0.5g',
236+
},
237+
};
238+
const formValuesForSessionLauncher = _.merge(
239+
{},
240+
defaultFormValues,
241+
fileBrowserFormValue,
242+
) as SessionLauncherFormValue;
243+
244+
startSession(formValuesForSessionLauncher)
245+
.then((results) => {
246+
if (
247+
results?.fulfilled &&
248+
results.fulfilled.length > 0
249+
) {
250+
upsertSessionNotification(results.fulfilled);
251+
}
252+
})
253+
.catch((error) => {
254+
console.error(
255+
'Unexpected error during session creation:',
256+
error,
257+
);
258+
message.error(t('error.UnexpectedError'));
259+
})
260+
.finally(() => {
261+
setIsLoadingToStartFileBrowser(false);
262+
});
263+
});
264+
}}
112265
>
113266
{lg && t('data.explorer.ExecuteFileBrowser')}
114267
</Button>

0 commit comments

Comments
 (0)