Merge pull request #42 from JustinZeus/bugfix/broken-import

fixed import
This commit is contained in:
JustinZeus 2026-03-02 00:03:55 +01:00 committed by GitHub
commit acf23a7d6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 5 deletions

View file

@ -19,7 +19,11 @@
"Bash(git add app/api/routers/runs.py app/services/arxiv/rate_limit.py tests/integration/test_run_lifecycle_consistency.py docs/website/package-lock.json)", "Bash(git add app/api/routers/runs.py app/services/arxiv/rate_limit.py tests/integration/test_run_lifecycle_consistency.py docs/website/package-lock.json)",
"Bash(git push)", "Bash(git push)",
"Bash(uvx ruff format --check app/api/routers/runs.py app/services/arxiv/rate_limit.py tests/integration/test_run_lifecycle_consistency.py)", "Bash(uvx ruff format --check app/api/routers/runs.py app/services/arxiv/rate_limit.py tests/integration/test_run_lifecycle_consistency.py)",
"Bash(test -f docs/website/package-lock.json)" "Bash(test -f docs/website/package-lock.json)",
"Bash(gh run list --branch openalex-size-reduction-scholar-hydration --limit 3 --json databaseId,status,conclusion,name,event)",
"Bash(gh run list --limit 10 --json databaseId,status,conclusion,name,event,headBranch)",
"Bash(gh run view 22554585841 --log-failed)",
"Bash(gh run rerun 22554585841 --failed)"
], ],
"additionalDirectories": [ "additionalDirectories": [
"/home/jv/src/personal/playground/scholar_scraper/scholar-scraper/frontend/src" "/home/jv/src/personal/playground/scholar_scraper/scholar-scraper/frontend/src"

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import datetime from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field, model_validator
from app.api.schemas.common import ApiMeta from app.api.schemas.common import ApiMeta
@ -128,11 +128,20 @@ class DataExportEnvelope(BaseModel):
class DataImportRequest(BaseModel): class DataImportRequest(BaseModel):
schema_version: int | None = None schema_version: int | None = None
exported_at: str | None = None
scholars: list[ScholarExportItemData] = Field(default_factory=list) scholars: list[ScholarExportItemData] = Field(default_factory=list)
publications: list[PublicationExportItemData] = Field(default_factory=list) publications: list[PublicationExportItemData] = Field(default_factory=list)
model_config = ConfigDict(extra="forbid") model_config = ConfigDict(extra="forbid")
@model_validator(mode="before")
@classmethod
def unwrap_export_envelope(cls, values: dict) -> dict: # type: ignore[override]
"""Accept the full export envelope format (with data/meta wrapper)."""
if isinstance(values, dict) and "data" in values and isinstance(values["data"], dict):
return values["data"]
return values
class DataImportResultData(BaseModel): class DataImportResultData(BaseModel):
scholars_created: int scholars_created: int

View file

@ -394,11 +394,16 @@ async function onImportFileSelected(event: Event): Promise<void> {
clearMessages(); clearMessages();
try { try {
const raw = await file.text(); const raw = await file.text();
const parsed = JSON.parse(raw) as DataImportPayload; let parsed = JSON.parse(raw);
if (!parsed || !Array.isArray(parsed.scholars) || !Array.isArray(parsed.publications)) { // Accept the full export envelope (with data/meta wrapper)
if (parsed?.data && Array.isArray(parsed.data.scholars)) {
parsed = parsed.data;
}
const payload = parsed as DataImportPayload;
if (!payload || !Array.isArray(payload.scholars) || !Array.isArray(payload.publications)) {
throw new Error("Invalid import file: expected scholars[] and publications[] arrays."); throw new Error("Invalid import file: expected scholars[] and publications[] arrays.");
} }
const result = await importScholarData(parsed); const result = await importScholarData(payload);
successMessage.value = importSummary(result); successMessage.value = importSummary(result);
await loadScholars(); await loadScholars();
} catch (error) { } catch (error) {