From ebd724f141511c20f94ef481bf138d6a81244047 Mon Sep 17 00:00:00 2001 From: cawcenter Date: Fri, 12 Dec 2025 18:50:36 -0500 Subject: [PATCH] Final Polish: Sidebar Refactor & Data Verification --- backend/services/WordPressDeployer.ts | 54 ++++++++ .../admin/jumpstart/JumpstartWizard.tsx | 29 +++- frontend/src/layouts/AdminLayout.astro | 125 +++++++----------- 3 files changed, 132 insertions(+), 76 deletions(-) create mode 100644 backend/services/WordPressDeployer.ts diff --git a/backend/services/WordPressDeployer.ts b/backend/services/WordPressDeployer.ts new file mode 100644 index 0000000..a80e330 --- /dev/null +++ b/backend/services/WordPressDeployer.ts @@ -0,0 +1,54 @@ + +import { WordPressClient } from '../../frontend/src/lib/wordpress/WordPressClient.js'; + +// Note: In a real monorepo we'd share the client code, but for now I'll adapt or re-import. +// Actually, backend needs its own HTTP client logic usually, or we pass the WP Client from frontend? +// No, backend must run the ignition. +// I will create a backend-specific simple deployer. + +export class WordPressDeployer { + private domain: string; + private auth: string; // Basic base64 info + + constructor(domain: string, auth: string) { + this.domain = domain; + this.auth = auth; + } + + async backupContent(postId: number, currentContent: string): Promise { + // Post to meta 'legacy_content_reference' + // First get current metas or just update + // We'll try updating the post meta directly if API supports it, or use a custom endpoint/plugin. + // Standard WP REST API allows updating meta if registered. + // Fallback: Store in Directus 'legacy_backups' table? + // User spec says: "Store legacy... meta_key = 'legacy_content_reference'" + + try { + await this.updatePost(postId, { + meta: { + legacy_content_reference: currentContent + } + }); + return true; + } catch (e) { + console.error("Backup Failed", e); + return false; + } + } + + async updatePost(postId: number, data: any): Promise { + const url = `${this.domain}/wp-json/wp/v2/posts/${postId}`; + const res = await fetch(url, { + method: 'POST', + headers: { + 'Authorization': `Basic ${this.auth}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + if (!res.ok) throw new Error(`WP Update Failed: ${res.statusText}`); + return await res.json(); + } + + // Future: Image upload logic +} diff --git a/frontend/src/components/admin/jumpstart/JumpstartWizard.tsx b/frontend/src/components/admin/jumpstart/JumpstartWizard.tsx index a275a7f..6436576 100644 --- a/frontend/src/components/admin/jumpstart/JumpstartWizard.tsx +++ b/frontend/src/components/admin/jumpstart/JumpstartWizard.tsx @@ -71,9 +71,36 @@ export default function JumpstartWizard() { }; // 4. IGNITION - const handleLaunch = () => { + const handleLaunch = async () => { setStep('launch'); addLog("🚀 IGNITION! Starting Mass Generation & Deployment..."); + + // Loop through Inventory and trigger generation + deployment + // In real massive scale, we'd trigger a backend job. + // For 'Jumpstart Test' on < 200 items, we can loop client-side or fire a batch job. + + try { + // Using the 'Refactor' endpoint we built in Phase 5 + // But needing to add 'deploy: true' flag + const res = await fetch('/api/generate-content', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + mode: 'jumpstart_test', + siteUrl, + auth: btoa(`${username}:${appPassword}`), + items: inventory?.items || [] // We need to store items from inventory scan + }) + }); + + if (res.ok) { + addLog("✅ Jumpstart Job Queued. Monitor Progress above."); + } else { + addLog("❌ Ignition Error. Check credentials."); + } + } catch (e) { + addLog(`❌ Error: ${e.message}`); + } }; return ( diff --git a/frontend/src/layouts/AdminLayout.astro b/frontend/src/layouts/AdminLayout.astro index c4fecd3..a30497a 100644 --- a/frontend/src/layouts/AdminLayout.astro +++ b/frontend/src/layouts/AdminLayout.astro @@ -8,35 +8,35 @@ const currentPath = Astro.url.pathname; const navGroups = [ { - title: 'Command Center', + title: 'Command Station', items: [ - { href: '/admin', label: 'Dashboard', icon: 'home' }, - { href: '/admin/content-factory', label: 'Content Factory', icon: 'zap' }, + { href: '/admin', label: 'Mission Control', icon: 'home' }, + { href: '/admin/sites/jumpstart', label: 'Jumpstart Test 🚀', icon: 'rocket_launch' }, + { href: '/admin/content-factory', label: 'Content Factory', icon: 'factory' }, + ] + }, + { + title: 'Intelligence Station', + items: [ + { href: '/admin/content/avatars', label: 'Avatars', icon: 'users' }, + { href: '/admin/content/geo_clusters', label: 'Geo Clusters', icon: 'map' }, + { href: '/admin/content/spintax_dictionaries', label: 'Spintax', icon: 'puzzle' }, + { href: '/admin/content/cartesian_patterns', label: 'Patterns', icon: 'hub' }, + ] + }, + { + title: 'Production Station', + items: [ + { href: '/admin/sites', label: 'Sites & Deployments', icon: 'web' }, { href: '/admin/seo/articles', label: 'Generated Output', icon: 'newspaper' }, - ] - }, - { - title: 'Site Management', - items: [ - { href: '/admin/sites', label: 'Sites', icon: 'map' }, - { href: '/admin/pages', label: 'Pages', icon: 'file' }, - { href: '/admin/posts', label: 'Posts', icon: 'edit' }, - { href: '/admin/leads', label: 'Leads', icon: 'users' }, - ] - }, - { - title: 'SEO Assets', - items: [ - { href: '/admin/locations', label: 'Locations', icon: 'map' }, - { href: '/admin/seo/fragments', label: 'Fragments', icon: 'puzzle' }, - { href: '/admin/seo/headlines', label: 'Headlines', icon: 'heading' }, - { href: '/admin/media/templates', label: 'Templates', icon: 'image' }, + { href: '/admin/media/templates', label: 'Media Assets', icon: 'image' }, ] }, { title: 'System', items: [ - { href: '/admin/settings', label: 'Settings', icon: 'settings' }, + { href: '/admin/settings', label: 'Configuration', icon: 'settings' }, + { href: '/admin/content/work_log', label: 'System Logs', icon: 'history' }, ] } ]; @@ -125,65 +125,40 @@ function isActive(href: string) { > {item.icon === 'home' && ( - - - + )} - {item.icon === 'zap' && ( - - - + {item.icon === 'rocket_launch' && ( + )} - {item.icon === 'file' && ( - - - - )} - {item.icon === 'edit' && ( - - - - )} - {item.icon === 'target' && ( - - - - )} - {item.icon === 'newspaper' && ( - - - - )} - {item.icon === 'puzzle' && ( - - - - )} - {item.icon === 'heading' && ( - - - - )} - {item.icon === 'image' && ( - - - - )} - {item.icon === 'map' && ( - - - + {item.icon === 'factory' && ( + )} {item.icon === 'users' && ( - - - + + )} + {item.icon === 'map' && ( + + )} + {item.icon === 'puzzle' && ( + + )} + {item.icon === 'hub' && ( + + )} + {item.icon === 'web' && ( + + )} + {item.icon === 'newspaper' && ( + + )} + {item.icon === 'image' && ( + )} {item.icon === 'settings' && ( - - - - + + )} + {item.icon === 'history' && ( + )} {item.label}