Skip to main content

Importing Test Content (JSON + Media)

ImportDataset.tsx (src/ui/pages/admin/) lets an admin paste/upload a test's JSON definition (plus any media for listening tests) and preview it before committing.

Commands

CommandPurpose
validate_import(user_id, kind, json_data, audio_meta)Validates the JSON against the schema for kind, checks for a duplicate title, and returns an ImportPreview without writing anything
import_reading_test(user_id, json_data)Validates and imports a Reading test
import_writing_test(user_id, json_data)Validates and imports a Writing test
import_listening_test(user_id, json_data, audio_files)Validates and imports a Listening test, writing any accompanying audio files to storage

kind is one of "reading" | "writing" | "listening" (ImportKind in src/ui/lib/tauri.ts).

ImportPreview shape

export interface ImportPreview {
title: string;
status: string;
kind: string;
passage_or_section_or_task_count: number;
group_count: number;
question_count: number;
duplicate_of: string | null; // id of an existing test with the same title, if any
}

Audio payload shape (listening imports only)

For validate_import, lightweight metadata is sent (no file bytes) so validation can check duration/size expectations without transferring large payloads:

export interface ImportAudioMeta {
section_number: number;
file_name: string;
size: number;
}

For the actual import_listening_test commit, full audio bytes are sent per file:

export interface ImportAudioFile {
sectionNumber: number;
file: File;
}

// converted before sending to Rust:
const audio_files = await Promise.all(
audioFiles.map(async ({ sectionNumber, file }) => ({
section_number: sectionNumber,
file_name: file.name,
file_data: Array.from(new Uint8Array(await file.arrayBuffer())),
}))
);

file_data is a plain byte array (Vec<u8> on the Rust side) — Tauri IPC serializes binary payloads as JSON number arrays.

Validation error handling

validate_reading/validate_writing/validate_listening (src/core/src/services/import_service.rs) return structured validation errors that are converted to a single string via errors_to_string(&e) and surfaced to the admin as a toast/inline error before any database write occurs — invalid imports fail fast during the validate_import preview step rather than partially committing data. See Error Handling Conventions.

See also docs/spec/admin-dataset-import.spec.md in the repository for the original product spec this feature was built against.