diff --git a/src/web/src/hooks/useDatasets.ts b/src/web/src/hooks/useDatasets.ts index bd361e87..19d124eb 100644 --- a/src/web/src/hooks/useDatasets.ts +++ b/src/web/src/hooks/useDatasets.ts @@ -367,6 +367,7 @@ export interface CreateDatasetInput { languages?: string[]; num_examples?: number; license_use?: string; + connection?: string; } export function useCreateDataset() { @@ -387,6 +388,7 @@ export function useCreateDataset() { languages: input.languages ?? null, num_examples: input.num_examples ?? null, license_use: input.license_use ?? null, + connection: input.connection ?? null, }), }); if (!res.ok) { diff --git a/src/web/src/pages/Datasets.tsx b/src/web/src/pages/Datasets.tsx index 13abf98b..3e8458ff 100644 --- a/src/web/src/pages/Datasets.tsx +++ b/src/web/src/pages/Datasets.tsx @@ -20,6 +20,14 @@ interface Org { name: string; } +interface ConnOption { + id: string; + name: string; + purpose: string; + bucket: string; + is_default: boolean; +} + function clipsOf(d: Dataset): number | null { const c = d.metadata?.["clips"]; if (typeof c === "number") return c; @@ -254,12 +262,27 @@ function NewDatasetModal({ orgs, onClose }: { orgs: Org[]; onClose: () => void } const [sourceUri, setSourceUri] = useState(""); const [description, setDescription] = useState(""); const [numExamples, setNumExamples] = useState(""); + const [conns, setConns] = useState([]); + const [connection, setConnection] = useState(""); const [err, setErr] = useState(null); useEffect(() => { if (!orgId && orgs[0]) setOrgId(orgs[0].id); }, [orgs, orgId]); + // Load the org's storage connections so the user can bind the dataset to one. + useEffect(() => { + setConns([]); + setConnection(""); + if (!orgId) return; + let live = true; + apiFetch(`/organizations/${orgId}/storage-connections`) + .then((r) => (r.ok ? r.json() : [])) + .then((d) => { if (live) setConns(Array.isArray(d) ? d : []); }) + .catch(() => { if (live) setConns([]); }); + return () => { live = false; }; + }, [orgId]); + const submit = async () => { setErr(null); if (!orgId || !name.trim()) { @@ -278,6 +301,7 @@ function NewDatasetModal({ orgs, onClose }: { orgs: Org[]; onClose: () => void } tasks: tasks.split(",").map((t) => t.trim()).filter(Boolean), num_examples: numExamples.trim() && !Number.isNaN(Number(numExamples)) ? Number(numExamples) : undefined, license_use: licenseUse || undefined, + connection: connection || undefined, }); onClose(); } catch (e) { @@ -345,8 +369,24 @@ function NewDatasetModal({ orgs, onClose }: { orgs: Org[]; onClose: () => void } setTasks(e.target.value)} placeholder="translation, summarization" style={styles.input} /> + + + - setSourceUri(e.target.value)} placeholder="s3://… or hf:org/name" style={styles.input} /> + setSourceUri(e.target.value)} + placeholder={connection ? "set from connection" : "s3://… or hf:org/name"} + style={{ ...styles.input, ...(connection ? { opacity: 0.5 } : {}) }} + disabled={!!connection} + /> setNumExamples(e.target.value)} placeholder="120000" style={styles.input} />