Add curator Movement links config with proof URLs and admin-gated delete votes.
Persist lineage in PostgreSQL, seed documented edges, and keep timeline/tree consumers API-backed with a static fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
2b4cdc5a9f
commit
1b760faf0d
36 files changed
+2051
-43
No files matched your search
@@ -1,10 +1,12 @@
|
||||
/**
|
||||
* Documented art-historical movement lineage (predecessor → successor).
|
||||
* Sources: Met Museum essays, TheArtStory, Sotheby's movement guides.
|
||||
*
|
||||
* Art-historical movement lineage (predecessor → successor).
|
||||
* Defaults match museum essays; live data comes from GET /api/movement-links.
|
||||
* Multiple parents are allowed (e.g. Post-Impressionism feeding several modern paths).
|
||||
*/
|
||||
export const MOVEMENT_LINEAGE: ReadonlyArray<readonly [parent: string, child: string]> = [
|
||||
|
||||
export type MovementLineageEdge = readonly [parent: string, child: string];
|
||||
|
||||
export const FALLBACK_MOVEMENT_LINEAGE: ReadonlyArray<MovementLineageEdge> = [
|
||||
// Classical & medieval
|
||||
['Ancient Greek & Roman', 'Byzantine'],
|
||||
['Byzantine', 'Gothic'],
|
||||
@@ -21,17 +23,17 @@ export const MOVEMENT_LINEAGE: ReadonlyArray<readonly [parent: string, child: st
|
||||
['Rococo', 'Neoclassicism'],
|
||||
['Neoclassicism', 'Romanticism'],
|
||||
['Romanticism', 'Realism'],
|
||||
['Romanticism', 'Impressionism'], // Turner, Delacroix → light and atmosphere
|
||||
['Romanticism', 'Impressionism'],
|
||||
['Realism', 'Impressionism'],
|
||||
|
||||
// Modern origins (Met / ArtStory: Impressionism → Post-Impressionism → …)
|
||||
// Modern origins
|
||||
['Impressionism', 'Post-Impressionism'],
|
||||
['Post-Impressionism', 'Symbolism'],
|
||||
['Post-Impressionism', 'Fauvism'],
|
||||
['Post-Impressionism', 'Expressionism'],
|
||||
['Post-Impressionism', 'Cubism'], // Cézanne's structure → Picasso/Braque
|
||||
['Post-Impressionism', 'Cubism'],
|
||||
['Symbolism', 'Art Nouveau'],
|
||||
['Fauvism', 'Cubism'], // Braque, Matisse → geometric turn
|
||||
['Fauvism', 'Cubism'],
|
||||
['Cubism', 'Futurism'],
|
||||
['Cubism', 'Suprematism'],
|
||||
['Cubism', 'Constructivism'],
|
||||
@@ -43,10 +45,35 @@ export const MOVEMENT_LINEAGE: ReadonlyArray<readonly [parent: string, child: st
|
||||
['Abstract Expressionism', 'Pop Art'],
|
||||
];
|
||||
|
||||
let activeLineage: ReadonlyArray<MovementLineageEdge> = FALLBACK_MOVEMENT_LINEAGE;
|
||||
|
||||
/** Active edges for timeline / tree layout (API-backed when loaded). */
|
||||
export function getMovementLineage(): ReadonlyArray<MovementLineageEdge> {
|
||||
return activeLineage;
|
||||
}
|
||||
|
||||
/** Apply curator DB rows; empty list keeps the static fallback. */
|
||||
export function setMovementLineageFromApi(
|
||||
items: ReadonlyArray<{ source_name: string; target_name: string }>
|
||||
): void {
|
||||
if (!items.length) {
|
||||
activeLineage = FALLBACK_MOVEMENT_LINEAGE;
|
||||
return;
|
||||
}
|
||||
activeLineage = items.map((row) => [row.source_name, row.target_name] as const);
|
||||
}
|
||||
|
||||
/** @deprecated Use getMovementLineage() — alias for older imports. */
|
||||
export const MOVEMENT_LINEAGE = FALLBACK_MOVEMENT_LINEAGE;
|
||||
|
||||
export function lineageParentsByName(childName: string): string[] {
|
||||
return MOVEMENT_LINEAGE.filter(([, child]) => child === childName).map(([parent]) => parent);
|
||||
return getMovementLineage()
|
||||
.filter(([, child]) => child === childName)
|
||||
.map(([parent]) => parent);
|
||||
}
|
||||
|
||||
export function lineageChildrenByName(parentName: string): string[] {
|
||||
return MOVEMENT_LINEAGE.filter(([parent]) => parent === parentName).map(([, child]) => child);
|
||||
return getMovementLineage()
|
||||
.filter(([parent]) => parent === parentName)
|
||||
.map(([, child]) => child);
|
||||
}
|
||||
Reference in new issue
Block a user