Files
Art-gallery/Documentation/influence-import.md
T
Danila KhodjaefandCursor 6656f91f25 Document Gariff influence workbook and pack timeline lanes by time span.
Add Inputs/gariff_influential_painters_influences.xlsx for curator import, document Inputs/Output conventions, and let non-overlapping movements share horizontal lanes on the timeline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 10:32:59 +03:00

93 lines
5.2 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 | Example file |
|--------|-----------------|--------------|
| Web sources | `Artist`, `Painting`, `Influenced by`, `Influenced`, `Reference (source + link)` | [`Inputs/artist_influences_web_sources.xlsx`](../Inputs/artist_influences_web_sources.xlsx) |
| Story of Art | Same Title Case (+ chapter reference column) | [`Inputs/story_of_art_influences.xlsx`](../Inputs/story_of_art_influences.xlsx) |
| Gariff influential painters | `artist`, `painting`, `influenced by`, `influenced`, `reference` | [`Inputs/gariff_influential_painters_influences.xlsx`](../Inputs/gariff_influential_painters_influences.xlsx) |
| Art influences | `artist`, `painting`, `influenced_by`, `influenced`, `reference` | [`Inputs/art_influences.xlsx`](../Inputs/art_influences.xlsx) |
| 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`.
### Book extract: Gariff (2008)
[`Inputs/gariff_influential_painters_influences.xlsx`](../Inputs/gariff_influential_painters_influences.xlsx) is distilled from David Gariff et al., *The World's Most Influential Painters and the Artists They Inspired* (Herbert Press / Quarto, 2008; local PDF `Inputs/1.pdf`, not committed).
- Columns match the import wizard (`artist` / `painting` / `influenced by` / `influenced` / `reference`).
- **`artist` and `painting`** are limited to catalog slices in `Inputs/artistslistdbdata-*.csv` and `Inputs/paintinglistdbdata-*.csv` (regenerate those from prod/dev as needed).
- **`influenced by` / `influenced`** may name artists, movements, or works from the book (including entities outside those CSVs).
- Multiple rows per subject when the book states several influences.
- Import via curator **Influences → Import** (Art influences / custom mapping) or keep as a curated source workbook.
See also [`Inputs/story_of_art_influences.xlsx`](../Inputs/story_of_art_influences.xlsx) (Gombrich) and optional local `Inputs/janson_short_history_influences.xlsx` (same column shape).
### 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).