Improve timeline UX and add catalog restore scripts for paintings and portraits.
Load the home-page catalog once with a lightweight artists API, batch pan/zoom updates per frame, use dynamic year labels, and speed up movement-flow zoom. Add sync-image-paths and fetch-artist-images plus docs for the post-seed pipeline.
This commit is contained in:
@@ -26,11 +26,14 @@ File names are sanitised `{Artist}_{Title}.{ext}`. The image service can redisco
|
||||
|
||||
| Script | npm command | Role |
|
||||
|--------|-------------|------|
|
||||
| `seed-wikipedia.js` | `npm run seed` | Initial eras, movements, artists, paintings, influences |
|
||||
| `seed-wikipedia.js` | `npm run seed` | Initial eras, movements, artists, one flagship painting per artist |
|
||||
| `seed-catalog-data.js` | *(data only)* | Eras, movements, artist metadata consumed by seed |
|
||||
| `sync-image-paths.js` | `npm run sync-image-paths` | Import painting rows from disk; set `image_path` / `thumbnail_path` |
|
||||
| `fetch-artist-images.js` | `npm run fetch-artist-images` | Download or link artist portraits under `data/images/portraits/` |
|
||||
| `fetch-artist-bios.js` | `npm run fetch-artist-bios` | Wikipedia intros → `bio_short` / `bio_full` |
|
||||
| `famous-paintings-data.js` | *(data only)* | Curated list of notable works per artist |
|
||||
| `expand-paintings.js` | `npm run expand-catalog` | Inserts works from data file for thin catalogs |
|
||||
| `art-influences-data.js` | *(data only)* | Curated painting-to-painting influence edges |
|
||||
| `art-influences-data.js` | *(data only)* | Curated influence edges (painting / artist / movement) |
|
||||
| `update-influences.js` | `npm run update-influences` | Applies influence graph; creates missing artists/works |
|
||||
| `fetch-missing-images.js` | `npm run fetch-images` | Downloads files for paintings missing on disk |
|
||||
| `image-fetcher.js` | *(library)* | Wikimedia / museum resolution used by fetch scripts and API |
|
||||
@@ -42,23 +45,26 @@ File names are sanitised `{Artist}_{Title}.{ext}`. The image service can redisco
|
||||
## Typical workflow
|
||||
|
||||
```text
|
||||
migrate → seed → fetch-artist-bios → expand-catalog → update-influences → fetch-images (per artist or batch) → build client
|
||||
migrate → seed → sync-image-paths → fetch-artist-images → fetch-artist-bios → expand-catalog → update-influences → fetch-images (per artist or batch) → build client
|
||||
```
|
||||
|
||||
1. **Seed** creates the base catalog (often one flagship painting per modern artist).
|
||||
2. **fetch-artist-bios** fills biography fields for every artist with a `wikipedia_title`.
|
||||
3. **expand-catalog** brings each artist up to at least **6** notable works (configurable via `MIN_PAINTINGS`).
|
||||
4. **fetch-images** downloads artwork files; the 3D gallery needs local files for reliable textures.
|
||||
1. **Seed** creates the base catalog (one flagship painting per artist; ~100 artists).
|
||||
2. **sync-image-paths** imports additional paintings when `data/images/paintings/` already contains files from a full clone (filename pattern `{Artist}_{Title}.jpg`).
|
||||
3. **fetch-artist-images** sets `portrait_path` from local files or Wikipedia.
|
||||
4. **fetch-artist-bios** fills biography fields for every artist with a `wikipedia_title`.
|
||||
5. **expand-catalog** brings each artist up to at least **6** notable works (configurable via `MIN_PAINTINGS`).
|
||||
6. **update-influences** loads the influence graph (*Influenced By* / *Influenced* panels, 3D hall lamps, exit navigation).
|
||||
7. **fetch-images** downloads artwork files still missing on disk; the 3D gallery needs local files for reliable textures.
|
||||
|
||||
## Seeding pipeline
|
||||
|
||||
`npm run seed` runs `scripts/seed-wikipedia.js`, which:
|
||||
|
||||
1. Inserts **historical eras** and **art movements** (curated date ranges and colours).
|
||||
1. Inserts **historical eras** and **art movements** (curated date ranges and colours from `seed-catalog-data.js`).
|
||||
2. For each curated **artist**:
|
||||
- Creates **artist periods** and **paintings**.
|
||||
- May download portraits and painting images (depending on seed script version).
|
||||
3. Writes **painting_influences** edges from curated scholarship references (mirrored into `painting_influence_sources` when you run `npm run migrate:influence-sources` and `npm run update-influences`).
|
||||
- Creates **artist periods** and one **flagship painting**.
|
||||
- May download portraits and painting images when run with `--fetch-images`.
|
||||
3. Does **not** insert influence edges — run `npm run update-influences` after seed (see [Painting influence graph](#painting-influence-graph)).
|
||||
|
||||
Those influence edges power **3D hall navigation** and painting detail panels via **`painting_influence_sources`** (see `GET /api/artists/:id/navigation` and `GET /api/paintings/:id` in [API.md](API.md)).
|
||||
|
||||
@@ -111,7 +117,44 @@ To add more works, append entries to `famous-paintings-data.js`:
|
||||
|
||||
`wikipedia_title` is optional; it defaults to `title`. Use it when the Wikipedia article name differs from the display title.
|
||||
|
||||
Renaissance and medieval masters with large museum catalog dumps (e.g. Raphael, Dürer) are usually above the minimum already; expansion targets Impressionists, modernists, and other artists who had only a single seed painting.
|
||||
Renaissance and medieval masters with large museum catalog dumps (e.g. Raphael, Dürer) are usually above the minimum already when **`sync-image-paths`** has imported files from disk; expansion targets Impressionists, modernists, and other artists who had only a single seed painting.
|
||||
|
||||
## Importing paintings from disk
|
||||
|
||||
When the repository includes a full `data/images/paintings/` tree but the database was seeded fresh (one row per artist), run:
|
||||
|
||||
```bash
|
||||
npm run sync-image-paths
|
||||
```
|
||||
|
||||
`scripts/sync-image-paths.js`:
|
||||
|
||||
1. Scans `data/images/paintings/` for full-size files (not `thumbs/`).
|
||||
2. Matches filenames to artists using the same `{Artist}_{Title}` sanitisation as `server/image-service.js`.
|
||||
3. **Updates** `image_path` / `thumbnail_path` on existing rows when files are found.
|
||||
4. **Inserts** missing painting rows for files not yet in the catalog.
|
||||
|
||||
Flags:
|
||||
|
||||
- `--dry-run` — report counts only, no DB writes.
|
||||
|
||||
Safe to re-run; already-imported works are skipped by normalized title matching.
|
||||
|
||||
Typical result on a full clone: ~1,000+ paintings linked from ~1,000 on-disk files.
|
||||
|
||||
## Artist portraits
|
||||
|
||||
`npm run fetch-artist-images` runs `scripts/fetch-artist-images.js`:
|
||||
|
||||
1. For each artist, checks `data/images/portraits/{Artist}.jpg` (or other extensions) and sets `portrait_path` when a local file exists.
|
||||
2. Otherwise downloads from Wikipedia / search fallbacks via `image-fetcher.js`.
|
||||
|
||||
Flags:
|
||||
|
||||
- `--force` — re-fetch even when `portrait_path` is already set.
|
||||
- `--limit=N` — process only the first N artists needing portraits.
|
||||
|
||||
Run after seed when portrait files exist on disk but the DB still has null `portrait_path` values.
|
||||
|
||||
## Painting influence graph
|
||||
|
||||
@@ -216,6 +259,8 @@ Wing layout (up to 55 works per wing, side-wall-only hang, window gap placement)
|
||||
| Storage | TypeScript module in the client — **not** a database table |
|
||||
| Format | `{ id, name, startYear, endYear?, shortLabel? }` — omit `endYear` for a single-year pin |
|
||||
| Interaction | Click a marker to zoom the shared timeline/movement view to that period |
|
||||
| Year axis labels | Dynamic density in `Timeline.tsx` via `chooseTimelineTickInterval()` — fewer labels when zoomed out |
|
||||
| Pan/zoom batching | `createViewChangeScheduler()` in `timelineView.ts` — one React update per animation frame |
|
||||
| Vertical guides | `TimelineEventGuides.tsx` draws faint gold lines (or shaded spans) from the marker row down through the movement flow, aligned to the same year scale |
|
||||
|
||||
Edit `HISTORICAL_EVENTS` and rebuild the client to extend the set.
|
||||
|
||||
Reference in New Issue
Block a user