feat(import): UI polish, contract requests, report
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
90a477691b
commit
c4df51f7ca
@@ -0,0 +1,11 @@
|
||||
# Contract requests from WP-B (Importer)
|
||||
|
||||
1. **`loadConfig` should add `<dataDir>/courses` to `courseDirs`.** The importer writes courses there. Worked around in `apps/server/src/main.ts` (the main guard pushes it) and in `packages/feature-import/dev/serve.ts`. `/api/import/info` reports `coursesDirServed` and the UI warns when it is false.
|
||||
2. **`startServer` accepts feature factories** (`Feature | ((ctx) => Feature)`). A `Feature` needs `ServerContext`, but `ServerContext.jobs` is built from the features' job handlers. `importFeature(ctx)` only reads `ctx` while a job or request runs, so `main.ts` now builds `ctx` first, resolves the factories, then assigns `ctx.jobs`. The edit is about ten lines in `apps/server/src/main.ts`; Phase 2 should keep or replace it.
|
||||
3. **Web entry for features.** `apps/web` must not pull a package's server code into the browser bundle. `@stc/feature-import` exposes a browser-safe entry as `./web` (package.json `exports`), but the root tsconfig `paths` (`@stc/*` to `packages/*/src`) cannot resolve `@stc/feature-import/web`, so `apps/web/src/features.ts` imports it by relative path. Suggest a tsconfig `paths` entry per feature, or a `src/web.ts` convention.
|
||||
4. **Derived cache layout (no contract defines one).** Written by the importer, to be read by the learner and AI packages:
|
||||
- `<dataDir>/cache/decks/<courseId>/<deckId>/p-001.jpg ...` (1280px wide JPEGs) and `text.json` (`[{ page, text }]`);
|
||||
- `<dataDir>/cache/covers/<courseId>/frame-N.jpg` and `deck-<deckId>.jpg` (cover candidates);
|
||||
- `<dataDir>/cache/transcripts/<courseId>/<lessonId>.json` (`{ lessonId, text, segments: [{ start, end, text }] }`).
|
||||
Suggest a `cacheDir`/`deckPageUrl` helper in core, and a media route for `cache/decks` so the deck viewer can load pages.
|
||||
5. **Video lessons have no description field.** Packt clips come with a one-line description. It is dropped, because `transcript` is the only Markdown a video lesson can carry and the transcription job writes it.
|
||||
@@ -65,7 +65,7 @@ function JobRow({ job }: { job: Job }) {
|
||||
{warnings.length ? (
|
||||
<details><summary>{warnings.length} warning{warnings.length > 1 ? "s" : ""}</summary><ul className="warn">{warnings.map((w, i) => <li key={i}>{w}</li>)}</ul></details>
|
||||
) : null}
|
||||
{job.status === "done" && job.kind !== "import.transcribe" && result?.courseId ? <CoverPicker courseId={result.courseId} /> : null}
|
||||
{job.status === "done" && (job.kind === "import.packt-video" || job.kind === "import.video-folder") && result?.courseId ? <CoverPicker courseId={result.courseId} /> : null}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
+1
@@ -26,6 +26,7 @@
|
||||
.imp-status[data-s="running"] { color: var(--accent); }
|
||||
.imp-job-bar { display: flex; align-items: center; gap: 12px; }
|
||||
.imp-job-msg { font-size: 12.5px; color: var(--faint); }
|
||||
.imp-job-bar .imp-job-msg { flex: none; width: 200px; text-align: right; }
|
||||
.imp-job details { font-size: 12.5px; color: var(--muted); }
|
||||
.imp-job summary { cursor: pointer; }
|
||||
.imp-job ul.warn { margin: 6px 0 0; padding-left: 18px; }
|
||||
|
||||
Reference in New Issue
Block a user