chunker ui redo
This commit is contained in:
84
ui/common/components/FileManager.tsx
Normal file
84
ui/common/components/FileManager.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* FileManager — pluggable file browser for S3/MinIO files.
|
||||
*
|
||||
* Handles both input file selection and output file listing.
|
||||
* Used by timeline (assets + output), chunker (assets + chunk output),
|
||||
* and future tools.
|
||||
*/
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { formatSize } from "../utils/format";
|
||||
import "./FileManager.css";
|
||||
|
||||
export interface FileEntry {
|
||||
key: string;
|
||||
name: string;
|
||||
size?: number;
|
||||
meta?: string;
|
||||
}
|
||||
|
||||
interface FileManagerProps {
|
||||
title: string;
|
||||
files: FileEntry[];
|
||||
selectedKey?: string | null;
|
||||
onSelect?: (file: FileEntry) => void;
|
||||
onScan?: () => void;
|
||||
scanning?: boolean;
|
||||
emptyMessage?: string;
|
||||
renderActions?: (file: FileEntry) => ReactNode;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export function FileManager({
|
||||
title,
|
||||
files,
|
||||
selectedKey,
|
||||
onSelect,
|
||||
onScan,
|
||||
scanning = false,
|
||||
emptyMessage = "No files",
|
||||
renderActions,
|
||||
disabled = false,
|
||||
}: FileManagerProps) {
|
||||
return (
|
||||
<div className="file-manager">
|
||||
<div className="fm-header">
|
||||
<h2>{title}</h2>
|
||||
{onScan && (
|
||||
<button
|
||||
className="fm-scan-btn"
|
||||
onClick={onScan}
|
||||
disabled={scanning || disabled}
|
||||
>
|
||||
{scanning ? "Scanning..." : "Scan Folder"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<ul className="fm-list">
|
||||
{files.length === 0 ? (
|
||||
<li className="fm-empty">{emptyMessage}</li>
|
||||
) : (
|
||||
files.map((file) => (
|
||||
<li
|
||||
key={file.key}
|
||||
className={`fm-item ${selectedKey === file.key ? "fm-selected" : ""} ${onSelect && !disabled ? "fm-clickable" : ""}`}
|
||||
onClick={() => onSelect && !disabled && onSelect(file)}
|
||||
title={file.name}
|
||||
>
|
||||
<div className="fm-item-info">
|
||||
<span className="fm-filename">{file.name}</span>
|
||||
<span className="fm-meta">
|
||||
{file.size != null && formatSize(file.size)}
|
||||
{file.meta && (file.size != null ? ` · ${file.meta}` : file.meta)}
|
||||
</span>
|
||||
</div>
|
||||
{renderActions && (
|
||||
<div className="fm-actions">{renderActions(file)}</div>
|
||||
)}
|
||||
</li>
|
||||
))
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user