CSV/JSON/XLSX mapping wizard expands artist-level rows to all paintings, blocks duplicate file/data imports via content and payload hashes, and documents the workflow in influence-import.md. Co-authored-by: Cursor <cursoragent@cursor.com>
80 lines
3.6 KiB
Markdown
80 lines
3.6 KiB
Markdown
# Influence links import & curator tool
|
|
|
|
Curator tool to **list / add / delete** influence edges, **visualize** an artist neighborhood, and **import** CSV / JSON / XLSX files through a mapping wizard.
|
|
|
|
Entry: header **Influences** (curator session). Data lives in `painting_influence_sources` (legacy `painting_influences` mirrored for painting→painting).
|
|
|
|
---
|
|
|
|
## Expansion rule (artist-level files)
|
|
|
|
Input workbooks such as [`Inputs/artist_influences_web_sources.xlsx`](../Inputs/artist_influences_web_sources.xlsx) are **artist-centric**. On import:
|
|
|
|
- **Influenced by** tokens → attach as sources on **all paintings** of the subject artist
|
|
- **Influenced** tokens that resolve to an artist → reverse link: subject artist becomes a source on **all paintings** of the influenced artist (same as PainterPalette `Influencedon`)
|
|
|
|
Unresolved names (artists / movements / paintings not in the DB) are **skipped** with warnings — no auto-create stubs.
|
|
|
|
---
|
|
|
|
## Wizard column roles
|
|
|
|
| Role | Meaning |
|
|
|------|---------|
|
|
| `subject_artist` | Artist the row is about (required) |
|
|
| `subject_painting` | Optional work hint (contextual; expansion still uses all works) |
|
|
| `influenced_by` | Who/what influenced the subject (`;` / `,` separated) |
|
|
| `influenced` | Who the subject influenced |
|
|
| `notes` / `reference` / `source_url` | Citation metadata (URLs scraped from reference text) |
|
|
| `ignore` | Skip column |
|
|
|
|
### Presets
|
|
|
|
| Preset | Typical headers |
|
|
|--------|-----------------|
|
|
| Web sources | `Artist`, `Painting`, `Influenced by`, `Influenced`, `Reference (source + link)` |
|
|
| Story of Art | Same Title Case (+ chapter reference column) |
|
|
| Art influences | `artist`, `painting`, `influenced_by`, `influenced`, `reference` |
|
|
| Custom | Map any columns manually |
|
|
|
|
Token classification order: **artist → movement → painting title** (under subject artist, then global).
|
|
|
|
Committed edges use `confidence=curated`, `discovered_via=import-wizard`.
|
|
|
|
### Duplicate file / data guard
|
|
|
|
Each successful commit stores SHA-256 fingerprints in `curator_audit_log` (`influence.import` details):
|
|
|
|
- `contentHash` — raw file bytes
|
|
- `payloadHash` — normalized mapped rows (same data under another filename still matches)
|
|
|
|
On parse/preview, if either hash matches a prior import, the UI warns and **blocks commit** unless the curator checks **Import anyway (force)**. Individual edges remain unique via DB `ON CONFLICT` either way.
|
|
|
|
---
|
|
|
|
## API (curator)
|
|
|
|
| Method | Path | Purpose |
|
|
|--------|------|---------|
|
|
| `GET` | `/api/influences` | List (`artistId`, `paintingId`, `q`, `limit`, `offset`) |
|
|
| `GET` | `/api/influences/graph?artistId=` | Nodes + edges for SVG neighborhood |
|
|
| `POST` | `/api/influences` | Create one edge |
|
|
| `PATCH` | `/api/influences/:id` | Update metadata / remap source |
|
|
| `DELETE` | `/api/influences/:id` | Delete (+ legacy mirror) |
|
|
| `POST` | `/api/influences/import/parse` | `{ filename, contentBase64, sheet? }` → columns, hashes, `alreadyImported` |
|
|
| `POST` | `/api/influences/import/preview` | `{ rows, mapping, contentHash?, payloadHash? }` → proposals + duplicate check |
|
|
| `POST` | `/api/influences/import/commit` | `{ proposals, fileName?, contentHash?, payloadHash?, force? }` — `409 ALREADY_IMPORTED` unless `force` |
|
|
|
|
Audit: `influence.create` / `update` / `delete` / `import` in `curator_audit_log`.
|
|
|
|
---
|
|
|
|
## CLI still available
|
|
|
|
- `npm run dev:update-influences` — curated [`scripts/art-influences-data.js`](../scripts/art-influences-data.js)
|
|
- `npm run dev:import-painter-palette` — PainterPalette CSV
|
|
|
|
The wizard is the interactive path for ad-hoc spreadsheets under `Inputs/`.
|
|
|
|
See also [API.md](API.md), [DB_structure.md](DB_structure.md), [Plans.md](Plans.md).
|