Compare commits
5 Commits
db2f607e5a
...
staging
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1939563ef2 | ||
|
|
698716c34e | ||
|
|
488e024451 | ||
|
|
9c166817fa | ||
|
|
4b7f3f554b |
@@ -23,38 +23,10 @@
|
||||
{
|
||||
"id": "page_home",
|
||||
"slug": "/",
|
||||
"title": "Startseite (Hauptseite)",
|
||||
"title": "Startseite",
|
||||
"is_published": true,
|
||||
"sections": [
|
||||
{
|
||||
"id": "sec_hero_1",
|
||||
"type": "HeroSection",
|
||||
"settings": {
|
||||
"title": "Maßgeschneiderte Webseiten. Digital im Griff.",
|
||||
"subtitle": "Wir entwickeln blitzschnelle, DSGVO-konforme High-End Webseiten für Ihr Unternehmen.",
|
||||
"ctaPrimaryText": "Projekt anfragen",
|
||||
"ctaPrimaryLink": "#contact",
|
||||
"bg_color": "#0b0f19"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sec_bento_1",
|
||||
"type": "BentoGrid",
|
||||
"settings": {
|
||||
"sectionTitle": "High-End Features & Leistung",
|
||||
"sectionSubtitle": "Modernste Technologie & Höchster Datenschutz vereint."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sec_contact_1",
|
||||
"type": "ContactSection",
|
||||
"settings": {
|
||||
"title": "Bereit für Ihr Projekt?",
|
||||
"subtitle": "Schreiben Sie uns direkt. Wir antworten innerhalb von 24 Stunden persönlich."
|
||||
}
|
||||
}
|
||||
]
|
||||
"sections": []
|
||||
}
|
||||
],
|
||||
"updated_at": "2026-08-09T22:08:57.203Z"
|
||||
"updated_at": "2026-08-09T22:28:31.200Z"
|
||||
}
|
||||
BIN
app/data/waas.db
BIN
app/data/waas.db
Binary file not shown.
@@ -21,13 +21,39 @@
|
||||
const { type, payload } = event.data || {};
|
||||
|
||||
if (type === 'THEME_UPDATE') {
|
||||
// Injiziert CSS-Variablen live in den DOM (<head>)
|
||||
const root = document.documentElement;
|
||||
if (payload.colors) {
|
||||
Object.entries(payload.colors).forEach(([key, val]) => {
|
||||
root.style.setProperty(`--${key}`, val);
|
||||
});
|
||||
}
|
||||
|
||||
// Live Section DOM Patching
|
||||
if (payload.sectionId && payload.settings) {
|
||||
const secElement = document.querySelector(`[data-section-id="${payload.sectionId}"], #${payload.sectionId}`) || document.querySelector('section');
|
||||
if (secElement) {
|
||||
const { title, subtitle, cta_text, bg_color, accent_color } = payload.settings;
|
||||
|
||||
if (title !== undefined) {
|
||||
const h1OrH2 = secElement.querySelector('h1, h2, h3');
|
||||
if (h1OrH2) h1OrH2.textContent = title;
|
||||
}
|
||||
if (subtitle !== undefined) {
|
||||
const p = secElement.querySelector('p');
|
||||
if (p) p.textContent = subtitle;
|
||||
}
|
||||
if (cta_text !== undefined) {
|
||||
const btn = secElement.querySelector('a, button');
|
||||
if (btn) btn.textContent = cta_text;
|
||||
}
|
||||
if (bg_color !== undefined && bg_color !== '') {
|
||||
secElement.style.backgroundColor = bg_color;
|
||||
}
|
||||
if (accent_color !== undefined && accent_color !== '') {
|
||||
secElement.style.setProperty('--accent-color', accent_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'RELOAD_CANVAS') {
|
||||
|
||||
@@ -96,37 +96,14 @@ function seedInitialData(db: DatabaseSync) {
|
||||
now
|
||||
);
|
||||
|
||||
// Seed default pages & sections
|
||||
// Seed default page only (no prefilled sections/demo content)
|
||||
db.prepare('INSERT INTO pages (id, slug, title, status, homepage_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)').run(
|
||||
'page_home',
|
||||
'/',
|
||||
'Startseite (Hauptseite)',
|
||||
'Startseite',
|
||||
'published',
|
||||
'page_home',
|
||||
now,
|
||||
now
|
||||
);
|
||||
|
||||
const heroDraft = JSON.stringify({
|
||||
title: 'Maßgeschneiderte Webseiten. Digital im Griff.',
|
||||
subtitle: 'Wir entwickeln blitzschnelle, DSGVO-konforme High-End Webseiten für Ihr Unternehmen.',
|
||||
ctaPrimaryText: 'Projekt anfragen',
|
||||
ctaPrimaryLink: '#contact'
|
||||
});
|
||||
|
||||
const bentoDraft = JSON.stringify({
|
||||
sectionTitle: 'High-End Features & Leistung',
|
||||
sectionSubtitle: 'Modernste Technologie & Höchster Datenschutz vereint.'
|
||||
});
|
||||
|
||||
const contactDraft = JSON.stringify({
|
||||
title: 'Bereit für Ihr Projekt?',
|
||||
subtitle: 'Schreiben Sie uns direkt. Wir antworten innerhalb von 24 Stunden persönlich.'
|
||||
});
|
||||
|
||||
const stmt = db.prepare('INSERT INTO page_sections (id, page_id, section_type, order_index, content_draft_json, content_published_json, styles_json) VALUES (?, ?, ?, ?, ?, ?, ?)');
|
||||
|
||||
stmt.run('sec_hero_1', 'page_home', 'HeroSection', 0, heroDraft, heroDraft, JSON.stringify({ bg_color: '#0b0f19' }));
|
||||
stmt.run('sec_bento_1', 'page_home', 'BentoGrid', 1, bentoDraft, bentoDraft, JSON.stringify({}));
|
||||
stmt.run('sec_contact_1', 'page_home', 'ContactSection', 2, contactDraft, contactDraft, JSON.stringify({}));
|
||||
}
|
||||
|
||||
33
src/db/resetDb.ts
Normal file
33
src/db/resetDb.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { DatabaseSync } from 'node:sqlite';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
const DATA_DIR = process.env.DATA_DIR || path.join(process.cwd(), 'app', 'data');
|
||||
const DB_PATH = path.join(DATA_DIR, 'waas.db');
|
||||
|
||||
export function resetDatabaseToBlankSlate(): void {
|
||||
const db = new DatabaseSync(DB_PATH);
|
||||
|
||||
// Lösche bestehende Seiten & Sektionen
|
||||
db.exec('DELETE FROM page_sections');
|
||||
db.exec('DELETE FROM pages');
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
// Leere Startseite anlegen (ohne vordefinierte Sektionen/Inhalte)
|
||||
db.prepare('INSERT INTO pages (id, slug, title, status, homepage_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)').run(
|
||||
'page_home',
|
||||
'/',
|
||||
'Startseite',
|
||||
'published',
|
||||
'page_home',
|
||||
now,
|
||||
now
|
||||
);
|
||||
|
||||
console.log('[WaaS DB] Datenbank auf leeren Stand (Blank Slate) zurückgesetzt.');
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('resetDb.ts')) {
|
||||
resetDatabaseToBlankSlate();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
|
||||
return new Response(JSON.stringify({ success: true, section_id: secId }), { status: 201 });
|
||||
} catch (error) {
|
||||
console.error('[API /api/editor/add-section] Exception:', error);
|
||||
return new Response(JSON.stringify({ error: 'Fehler beim Hinzufügen der Sektion' }), { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
|
||||
return new Response(JSON.stringify({ success: true, message: 'Sektion gelöscht' }), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error('[API /api/editor/delete-section] Exception:', error);
|
||||
return new Response(JSON.stringify({ error: 'Fehler beim Löschen der Sektion' }), { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,6 +50,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
|
||||
return new Response(JSON.stringify({ success: true, settings: { ...updatedDraft, ...updatedStyles } }), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error('[API /api/editor/update-section-settings] Exception:', error);
|
||||
return new Response(JSON.stringify({ error: 'Fehler beim Aktualisieren der Sektions-Einstellungen' }), { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,6 +28,7 @@ export const POST: APIRoute = async ({ request }) => {
|
||||
{ status: 200 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('[API /api/editor/update-section] Exception:', error);
|
||||
return new Response(JSON.stringify({ error: 'Fehler beim Aktualisieren der Sektionen' }), { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { detectDeviceType } from './deviceDetect';
|
||||
import { getDb } from '../db/index';
|
||||
export interface UIComponent {
|
||||
id: string; // Eindeutige ID (z.B. uuid / timestamp)
|
||||
slotId: string; // Platz-ID (z.B. 'hero-badge-slot', 'hero-actions-slot', 'bento-slot-1')
|
||||
@@ -283,7 +284,29 @@ export function loadWaasConfigs(userAgent: string = '', isDraft: boolean = false
|
||||
const genericSitePath = path.join(dataDir, 'site.config.json');
|
||||
|
||||
let sitePath = genericSitePath;
|
||||
if (isDraft && fs.existsSync(draftSitePath)) {
|
||||
if (isDraft) {
|
||||
if (!fs.existsSync(draftSitePath)) {
|
||||
try {
|
||||
const db = getDb();
|
||||
const settingsRow = db.prepare('SELECT value_json FROM site_settings WHERE key = ?').get('site_config') as { value_json: string } | undefined;
|
||||
const baseConfig = settingsRow ? JSON.parse(settingsRow.value_json) : {};
|
||||
const pagesRows = db.prepare('SELECT * FROM pages ORDER BY created_at ASC').all() as any[];
|
||||
const pages = pagesRows.map((page) => {
|
||||
const sectionsRows = db.prepare('SELECT * FROM page_sections WHERE page_id = ? ORDER BY order_index ASC').all(page.id) as any[];
|
||||
const sections = sectionsRows.map((sec) => ({
|
||||
id: sec.id,
|
||||
type: sec.section_type,
|
||||
settings: { ...JSON.parse(sec.content_draft_json || '{}'), ...JSON.parse(sec.styles_json || '{}') }
|
||||
}));
|
||||
return { id: page.id, slug: page.slug, title: page.title, is_published: page.status === 'published', sections };
|
||||
});
|
||||
const fullDraftConfig = { ...baseConfig, pages, updated_at: new Date().toISOString() };
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
fs.writeFileSync(draftSitePath, JSON.stringify(fullDraftConfig, null, 2), 'utf-8');
|
||||
} catch (e) {
|
||||
console.warn('[WaaS ConfigLoader] Fallback draft compilation warning:', e);
|
||||
}
|
||||
}
|
||||
sitePath = draftSitePath;
|
||||
} else if (fs.existsSync(deviceSitePath)) {
|
||||
sitePath = deviceSitePath;
|
||||
|
||||
Reference in New Issue
Block a user