101 lines
3.5 KiB
TypeScript
101 lines
3.5 KiB
TypeScript
import { FileText, FolderOpen } from 'lucide-react';
|
|
|
|
import type { WorkspaceNode } from './types';
|
|
import { isPreviewableWorkspaceFile, workspaceFileAction } from './utils';
|
|
|
|
interface WorkspaceEntriesLabels {
|
|
download: string;
|
|
fileNotPreviewable: string;
|
|
folder: string;
|
|
goUp: string;
|
|
goUpTitle: string;
|
|
openFolderTitle: string;
|
|
previewTitle: string;
|
|
}
|
|
|
|
interface WorkspaceEntriesListProps {
|
|
nodes: WorkspaceNode[];
|
|
workspaceParentPath: string | null;
|
|
selectedBotId: string;
|
|
workspaceFileLoading: boolean;
|
|
workspaceDownloadExtensionSet: ReadonlySet<string>;
|
|
labels: WorkspaceEntriesLabels;
|
|
onLoadWorkspaceTree: (botId: string, path?: string) => Promise<void> | void;
|
|
onOpenWorkspaceFilePreview: (path: string) => Promise<void> | void;
|
|
onShowWorkspaceHoverCard: (node: WorkspaceNode, anchor: HTMLElement) => void;
|
|
onHideWorkspaceHoverCard: () => void;
|
|
}
|
|
|
|
export function WorkspaceEntriesList({
|
|
nodes,
|
|
workspaceParentPath,
|
|
selectedBotId,
|
|
workspaceFileLoading,
|
|
workspaceDownloadExtensionSet,
|
|
labels,
|
|
onLoadWorkspaceTree,
|
|
onOpenWorkspaceFilePreview,
|
|
onShowWorkspaceHoverCard,
|
|
onHideWorkspaceHoverCard,
|
|
}: WorkspaceEntriesListProps) {
|
|
return (
|
|
<>
|
|
{workspaceParentPath !== null ? (
|
|
<button
|
|
key="dir:.."
|
|
className="workspace-entry dir nav-up"
|
|
onClick={() => void onLoadWorkspaceTree(selectedBotId, workspaceParentPath || '')}
|
|
title={labels.goUpTitle}
|
|
>
|
|
<FolderOpen size={14} />
|
|
<span className="workspace-entry-name">..</span>
|
|
<span className="workspace-entry-meta">{labels.goUp}</span>
|
|
</button>
|
|
) : null}
|
|
|
|
{nodes.map((node) => {
|
|
const key = `${node.type}:${node.path}`;
|
|
if (node.type === 'dir') {
|
|
return (
|
|
<button
|
|
key={key}
|
|
className="workspace-entry dir"
|
|
onClick={() => void onLoadWorkspaceTree(selectedBotId, node.path)}
|
|
title={labels.openFolderTitle}
|
|
>
|
|
<FolderOpen size={14} />
|
|
<span className="workspace-entry-name" title={node.name}>{node.name}</span>
|
|
<span className="workspace-entry-meta">{labels.folder}</span>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
const previewable = isPreviewableWorkspaceFile(node, workspaceDownloadExtensionSet);
|
|
const downloadOnlyFile = workspaceFileAction(node.path, workspaceDownloadExtensionSet) === 'download';
|
|
|
|
return (
|
|
<button
|
|
key={key}
|
|
className={`workspace-entry file ${previewable ? '' : 'disabled'}`}
|
|
disabled={workspaceFileLoading}
|
|
aria-disabled={!previewable || workspaceFileLoading}
|
|
onClick={() => {
|
|
if (workspaceFileLoading || !previewable) return;
|
|
void onOpenWorkspaceFilePreview(node.path);
|
|
}}
|
|
onMouseEnter={(event) => onShowWorkspaceHoverCard(node, event.currentTarget)}
|
|
onMouseLeave={onHideWorkspaceHoverCard}
|
|
onFocus={(event) => onShowWorkspaceHoverCard(node, event.currentTarget)}
|
|
onBlur={onHideWorkspaceHoverCard}
|
|
title={previewable ? (downloadOnlyFile ? labels.download : labels.previewTitle) : labels.fileNotPreviewable}
|
|
>
|
|
<FileText size={14} />
|
|
<span className="workspace-entry-name" title={node.name}>{node.name}</span>
|
|
<span className="workspace-entry-meta mono">{node.ext || '-'}</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</>
|
|
);
|
|
}
|