101 lines
5.6 KiB
JavaScript
101 lines
5.6 KiB
JavaScript
/**
|
|
* Wave 2b — homepage-BEELD in het CMS. Maakt twee kleine collecties:
|
|
* - `hero_cards` (3 staande werkfoto-cards in de hero)
|
|
* - `galerij` (6 foto's in de bewijs-sectie "Echt werk, echte resultaten")
|
|
* met image-rijen (een repeater kan geen image-subveld). De galerij hergebruikt de
|
|
* werk-foto's die al in R2 staan (uit 0010_diensten_media); de hero gebruikt de kleine
|
|
* -768-varianten (perf, want boven de vouw) → 2 nieuwe media-rijen + uploads.
|
|
* Print UPLOAD-regels voor de 2 nieuwe bestanden.
|
|
*/
|
|
import { ulid } from "ulidx";
|
|
import { writeFileSync, mkdirSync } from "node:fs";
|
|
import { generate } from "./gen-cms-sql.mjs";
|
|
|
|
const q = (s) => "'" + String(s).replace(/'/g, "''") + "'";
|
|
|
|
// Bestaande media uit 0010_diensten_media (storage_key == id + ".webp").
|
|
const EXIST = {
|
|
"werk-1": { id: "01KVABG8HZENXT71V00NY1M2N5", file: "werk-1.webp", w: 1200, h: 1600 },
|
|
"werk-2": { id: "01KVABG8HZSPH8YKM0GJC0WDE2", file: "werk-2.webp", w: 1600, h: 1200 },
|
|
"werk-3": { id: "01KVABG8HZN66T8KPTBWHQSFZS", file: "werk-3.webp", w: 738, h: 1600 },
|
|
"werk-4": { id: "01KVABG8HZ2H1TAB7E4J3QRCSM", file: "werk-4.webp", w: 1200, h: 1600 },
|
|
"werk-5": { id: "01KVABG8HZ9KFWV8604FYYSEAY", file: "werk-5.webp", w: 1200, h: 1600 },
|
|
"werk-6": { id: "01KVABG8HZV3AHQ5RQGVAKW29F", file: "werk-6.webp", w: 1200, h: 1600 },
|
|
};
|
|
for (const k of Object.keys(EXIST)) EXIST[k].storageKey = EXIST[k].id + ".webp";
|
|
|
|
// Nieuwe kleine hero-varianten (worden geupload + krijgen een media-rij).
|
|
const NEW = {
|
|
"werk-1-768": { file: "werk-1-768.webp", w: 768, h: 1024, size: 172718, alt: "Herstelde schoorsteen met nieuw loodwerk op een dak" },
|
|
"werk-5-768": { file: "werk-5-768.webp", w: 768, h: 1024, size: 191256, alt: "Dak wordt op hoogte gereinigd" },
|
|
};
|
|
for (const k of Object.keys(NEW)) {
|
|
NEW[k].id = ulid();
|
|
NEW[k].storageKey = NEW[k].id + ".webp";
|
|
}
|
|
|
|
function imgJson(m, alt) {
|
|
return {
|
|
id: m.id, provider: "local", filename: m.file, mimeType: "image/webp",
|
|
width: m.w, height: m.h, alt, meta: { storageKey: m.storageKey },
|
|
};
|
|
}
|
|
|
|
// ---- Model: twee image-collecties met content (image-veld = media-JSON) ----
|
|
const model = [
|
|
{
|
|
slug: "hero_cards",
|
|
label: "Homepage · hero-foto's",
|
|
labelSingular: "Hero-foto",
|
|
supports: ["drafts"],
|
|
fields: [
|
|
{ slug: "sort", label: "Volgorde", type: "integer" },
|
|
{ slug: "image", label: "Foto", type: "image", required: false },
|
|
{ slug: "title", label: "Titel (op de foto)", type: "string", required: true },
|
|
{ slug: "sub", label: "Ondertitel (op de foto)", type: "string" },
|
|
{ slug: "alt", label: "Alt-tekst", type: "string" },
|
|
],
|
|
content: [
|
|
{ slug: "card-1", status: "published", data: { sort: 1, image: imgJson(EXIST["werk-3"], "Strak nieuw voegwerk tussen bakstenen van een gevel"), title: "Voegwerk", sub: "gevel hersteld", alt: "Strak nieuw voegwerk tussen bakstenen van een gevel" } },
|
|
{ slug: "card-2", status: "published", data: { sort: 2, image: imgJson(NEW["werk-1-768"], "Herstelde schoorsteen met nieuw loodwerk op een dak"), title: "Schoorsteen", sub: "nieuw loodwerk", alt: "Herstelde schoorsteen met nieuw loodwerk op een dak" } },
|
|
{ slug: "card-3", status: "published", data: { sort: 3, image: imgJson(NEW["werk-5-768"], "Dak wordt op hoogte gereinigd"), title: "Dakreiniging", sub: "op hoogte", alt: "Dak wordt op hoogte gereinigd" } },
|
|
],
|
|
},
|
|
{
|
|
slug: "galerij",
|
|
label: "Homepage · bewijs-galerij",
|
|
labelSingular: "Galerij-foto",
|
|
supports: ["drafts"],
|
|
fields: [
|
|
{ slug: "sort", label: "Volgorde", type: "integer" },
|
|
{ slug: "image", label: "Foto", type: "image", required: false },
|
|
{ slug: "caption", label: "Bijschrift", type: "string", required: true },
|
|
{ slug: "featured", label: "Uitgelicht (grote tegel)", type: "boolean" },
|
|
],
|
|
content: [
|
|
{ slug: "g-1", status: "published", data: { sort: 1, image: imgJson(EXIST["werk-3"], "Voegwerk aan de gevel"), caption: "Voegwerk aan de gevel", featured: true } },
|
|
{ slug: "g-2", status: "published", data: { sort: 2, image: imgJson(EXIST["werk-1"], "Schoorsteen met nieuw loodwerk"), caption: "Schoorsteen met nieuw loodwerk", featured: false } },
|
|
{ slug: "g-3", status: "published", data: { sort: 3, image: imgJson(EXIST["werk-4"], "Dak vol mos, voor reiniging"), caption: "Dak vol mos, voor reiniging", featured: false } },
|
|
{ slug: "g-4", status: "published", data: { sort: 4, image: imgJson(EXIST["werk-2"], "Tuinmuur en bestrating"), caption: "Tuinmuur en bestrating", featured: false } },
|
|
{ slug: "g-5", status: "published", data: { sort: 5, image: imgJson(EXIST["werk-5"], "Dakreiniging op hoogte"), caption: "Dakreiniging op hoogte", featured: false } },
|
|
{ slug: "g-6", status: "published", data: { sort: 6, image: imgJson(EXIST["werk-6"], "Metselwerk, tuintrap"), caption: "Metselwerk, tuintrap", featured: false } },
|
|
],
|
|
},
|
|
];
|
|
|
|
// ---- Media-rijen voor de 2 nieuwe hero-varianten ----
|
|
const mediaSql = [
|
|
"-- Nieuwe hero-card-varianten in de mediabibliotheek.",
|
|
"INSERT OR REPLACE INTO media (id, filename, mime_type, size, width, height, alt, storage_key, status, created_at) VALUES",
|
|
Object.values(NEW)
|
|
.map((m) => ` (${q(m.id)}, ${q(m.file)}, 'image/webp', ${m.size}, ${m.w}, ${m.h}, ${q(m.alt)}, ${q(m.storageKey)}, 'ready', datetime('now'))`)
|
|
.join(",\n") + ";",
|
|
].join("\n");
|
|
|
|
const sql = mediaSql + "\n\n" + generate(model);
|
|
mkdirSync("migrations", { recursive: true });
|
|
writeFileSync("migrations/0011_homepage_media.sql", sql, "utf8");
|
|
|
|
for (const m of Object.values(NEW)) console.log(`UPLOAD|public/images/${m.file}|${m.storageKey}`);
|
|
console.log("geschreven: migrations/0011_homepage_media.sql");
|