Skip to content

Commit

Permalink
feat: introduce regacy folder explorer for calling explorer at anywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
ironAiken2 committed Jul 15, 2024
1 parent 13c6f51 commit 3ff8d45
Show file tree
Hide file tree
Showing 9 changed files with 2,352 additions and 75 deletions.
9 changes: 7 additions & 2 deletions react/src/components/BAIModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ export const DEFAULT_BAI_MODAL_Z_INDEX = 1001;
export interface BAIModalProps extends ModalProps {
okText?: string; // customize text of ok button with adequate content
draggable?: boolean; // modal can be draggle
className?: string;
}
const BAIModal: React.FC<BAIModalProps> = ({ styles, ...modalProps }) => {
const BAIModal: React.FC<BAIModalProps> = ({
className,
styles,
...modalProps
}) => {
const { token } = theme.useToken();
const [disabled, setDisabled] = useState(true);
const [bounds, setBounds] = useState({
Expand Down Expand Up @@ -46,7 +51,7 @@ const BAIModal: React.FC<BAIModalProps> = ({ styles, ...modalProps }) => {
keyboard={false}
{...modalProps}
centered={modalProps.centered ?? true}
className="bai-modal"
className={`bai-modal ${className ?? ''}`}
wrapClassName={modalProps.draggable ? 'draggable' : ''}
styles={{
...styles,
Expand Down
32 changes: 23 additions & 9 deletions react/src/components/FolderExplorerOpener.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useBaiSignedRequestWithPromise } from '../helper';
import { useCurrentProjectValue } from '../hooks/useCurrentProject';
import { jotaiStore } from './DefaultProviders';
import LegacyFolderExplorer from './LegacyFolderExplorer';
import { VFolder } from './VFolderSelect';
import { atom, useAtomValue } from 'jotai';
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { StringParam, useQueryParam } from 'use-query-params';

// TODO: Separate Folder Explorer from `backend-ai-data-view` and make it opened directly on all pages.
Expand All @@ -18,6 +19,8 @@ document.addEventListener('backend-ai-data-view:disconnected', () => {

const FolderExplorerOpener = () => {
const [folderId] = useQueryParam('folder', StringParam) || '';
const [vfolderName, setVFolderName] = useState<string>('');
const [open, setOpen] = useState(false);
const normalizedFolderId = folderId?.replaceAll('-', '');
const currentProject = useCurrentProjectValue();
const baiRequestWithPromise = useBaiSignedRequestWithPromise();
Expand All @@ -38,22 +41,33 @@ const FolderExplorerOpener = () => {
// `id` of `/folders` API is not UUID, but UUID without `-`
(vFolder) => vFolder.id === normalizedFolderId,
);
document.dispatchEvent(
new CustomEvent('folderExplorer:open', {
detail: {
vFolder,
},
}),
);
// document.dispatchEvent(
// new CustomEvent('folderExplorer:open', {
// detail: {
// vFolder,
// },
// }),
// );
setVFolderName(vFolder?.name || '');
})
.catch(() => {
// do nothing
});
setOpen(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isDataViewReady, folderId]); // don't need to watch `folderId` because this used only once right after the backend-ai-data-view is ready

return null;
// return null;
return (
<LegacyFolderExplorer
vfolderName={vfolderName}
vfolderID={normalizedFolderId || ''}
open={open}
onRequestClose={() => setOpen(false)}
destroyOnClose
/>
);
};

export default FolderExplorerOpener;
168 changes: 168 additions & 0 deletions react/src/components/LegacyFolderExplorer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import BAIModal, { BAIModalProps } from './BAIModal';
import Flex from './Flex';
import {
FileAddOutlined,
FolderAddOutlined,
UploadOutlined,
} from '@ant-design/icons';
import { Button, Dropdown, Image, Tooltip, Typography, theme } from 'antd';
import { createStyles } from 'antd-style';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

const useStyles = createStyles(({ token, css }) => ({
baiModalHeader: css`
.ant-modal-title {
width: 100%;
margin-right: ${token.marginXXL}px;
}
`,
}));

interface LegacyFolderExplorerProps extends BAIModalProps {
vfolderName: string;
vfolderID: string;
onRequestClose: () => void;
}

const LegacyFolderExplorer: React.FC<LegacyFolderExplorerProps> = ({
vfolderName,
vfolderID,
onRequestClose,
...modalProps
}) => {
const { t } = useTranslation();
const { token } = theme.useToken();
const { styles } = useStyles();
const [isWritable, setIsWritable] = useState<boolean>(false);
// TODO: Events are sent and received as normal,
// but the Lit Element is not rendered and the values inside are not available but ref is available.
const folderExplorerRef = useRef<HTMLDivElement>(null);
const navigate = useNavigate();

useEffect(() => {
const handleConnected = (e: any) => {
setIsWritable(e.detail || false);
};

document.addEventListener('folderExplorer:connected', handleConnected);
return () => {
document.removeEventListener('folderExplorer:connected', handleConnected);
};
}, []);

return (
<BAIModal
className={styles.baiModalHeader}
title={
<Flex justify="between" gap={token.marginMD} style={{ width: '100%' }}>
<Flex gap={token.marginMD} style={{ width: '300px' }}>
<Tooltip title={vfolderName}>
<Typography.Title
level={3}
style={{ marginTop: token.marginSM }}
ellipsis
>
{vfolderName}
</Typography.Title>
</Tooltip>
</Flex>
<Flex justify="end" gap={token.marginSM}>
<Button
disabled={!isWritable}
icon={<FolderAddOutlined />}
onClick={() => {
//@ts-ignore
folderExplorerRef.current?.openMkdirDialog();
document.dispatchEvent(
new CustomEvent('folderExplorer:openMkdirDialog'),
);
}}
>
Create
</Button>
<Dropdown
disabled={!isWritable}
menu={{
items: [
{
key: 'upload files',
label: t('data.explorer.UploadFiles'),
icon: <FileAddOutlined />,
onClick: () => {
// @ts-ignore
folderExplorerRef.current?.handleUpload('file');
},
},
{
key: 'upload folder',
label: t('data.explorer.UploadFolder'),
icon: <FolderAddOutlined />,
onClick: () => {
// @ts-ignore
folderExplorerRef.current?.handleUpload('folder');
},
},
],
}}
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Dropdown>
<Button
icon={
<Image
width="18px"
src="/resources/icons/filebrowser.svg"
alt="File Browser"
preview={false}
/>
}
onClick={() =>
// @ts-ignore
folderExplorerRef.current?._executeFileBrowser()
}
>
{t('data.explorer.ExecuteFileBrowser')}
</Button>
<Button
icon={
<Image
width="18px"
src="/resources/icons/sftp.png"
alt="SSH / SFTP"
preview={false}
/>
}
onClick={() => {
// @ts-ignore
folderExplorerRef.current?._executeSSHProxyAgent();
}}
>
{t('data.explorer.RunSSH/SFTPserver')}
</Button>
</Flex>
</Flex>
}
centered
onCancel={() => {
onRequestClose();
navigate('/data');
}}
width={1000}
destroyOnClose
footer={null}
{...modalProps}
>
{/* @ts-ignore */}
<backend-ai-folder-explorer
ref={folderExplorerRef}
active
vfolderID={vfolderID}
style={{ width: '100%' }}
/>
</BAIModal>
);
};

export default LegacyFolderExplorer;
Loading

0 comments on commit 3ff8d45

Please sign in to comment.