Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177import React, { useRef, useState } from "react";import { UploadSimple, FileText, FilePdf, Plus } from "@phosphor-icons/react";import { api } from "./api.js";import { handleTabListKeyDown, Modal } from "./ui.jsx";
export function ImportDialog({ open, onOpenChange, kind, onImported, notify }) { const [tab, setTab] = useState("upload"), [title, setTitle] = useState(""), [body, setBody] = useState(""), [busy, setBusy] = useState(false), [drag, setDrag] = useState(false); const input = useRef(); const importFile = async (file) => { if (!file) return; setBusy(true); try { const form = new FormData(); form.append("file", file); const material = await api("/import", { method: "POST", body: form }); await onImported(material); onOpenChange(false); notify( material.restored ? `Restored ${material.restored} materials.` : "Imported successfully.", ); } catch (e) { notify(e.message, "error"); } finally { setBusy(false); if (input.current) input.current.value = ""; } }; return ( <Modal open={open} onOpenChange={onOpenChange} title={kind === "book" ? "Add a book" : "Add an article"} description={ kind === "book" ? "Import a PDF from this device. Its searchable text is indexed locally." : "Import an agent-authored lesson bundle, Markdown, or write an article." } wide > {kind !== "book" && ( <div className="segmented import-tabs" role="tablist" aria-label="Article import mode" data-selected={tab === "write" ? "second" : "first"} onKeyDown={handleTabListKeyDown} > <button type="button" role="tab" aria-selected={tab === "upload"} tabIndex={tab === "upload" ? 0 : -1} className={tab === "upload" ? "active" : ""} onClick={() => setTab("upload")} > Import file </button> <button type="button" role="tab" aria-selected={tab === "write"} tabIndex={tab === "write" ? 0 : -1} className={tab === "write" ? "active" : ""} onClick={() => setTab("write")} > Write / paste Markdown </button> </div> )} {tab === "upload" || kind === "book" ? ( <> <input ref={input} type="file" className="sr-only" tabIndex={-1} aria-hidden="true" accept={kind === "book" ? ".pdf,.zip" : ".md,.json,.zip,.pdf"} aria-label="Choose a lesson, PDF or backup" onChange={(e) => importFile(e.target.files[0])} /> <button disabled={busy} className={"dropzone " + (drag ? "dragging" : "")} onClick={() => input.current.click()} onDragOver={(e) => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)} onDrop={(e) => { e.preventDefault(); setDrag(false); importFile(e.dataTransfer.files[0]); }} > <UploadSimple size={35} weight="light" /> <strong> {busy ? "Importing…" : "Choose a file or drop it here"} </strong> <span> {kind === "book" ? "PDF, up to 256 MB" : "Lesson ZIP, Markdown, JSON or PDF"} </span> </button> <div className="import-info"> <FileText size={21} /> <p> Agent lessons use <code>lesson.json</code>,{" "} <code>content.md</code> and an <code>assets/</code> folder inside a ZIP. Mermaid diagrams, math and cited sources are supported. </p> </div> </> ) : ( <form onSubmit={async (e) => { e.preventDefault(); setBusy(true); try { const m = await api("/materials", { method: "POST", body: { title, content: body }, }); await onImported(m); onOpenChange(false); setTitle(""); setBody(""); } catch (e) { notify(e.message, "error"); } finally { setBusy(false); } }} > <label> Title <input value={title} onChange={(e) => setTitle(e.target.value)} required maxLength={200} placeholder="What are you learning?" /> </label> <label> Article <textarea className="code-editor" rows={14} value={body} onChange={(e) => setBody(e.target.value)} required placeholder="## Start here…" /> </label> <div className="form-actions"> <button className="primary" disabled={busy || !title.trim() || !body.trim()} > {busy ? "Saving…" : "Create article"} </button> </div> </form> )} </Modal> );}