Final Polish: Sidebar Refactor & Data Verification
This commit is contained in:
54
backend/services/WordPressDeployer.ts
Normal file
54
backend/services/WordPressDeployer.ts
Normal file
@@ -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<boolean> {
|
||||||
|
// 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<any> {
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -71,9 +71,36 @@ export default function JumpstartWizard() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 4. IGNITION
|
// 4. IGNITION
|
||||||
const handleLaunch = () => {
|
const handleLaunch = async () => {
|
||||||
setStep('launch');
|
setStep('launch');
|
||||||
addLog("🚀 IGNITION! Starting Mass Generation & Deployment...");
|
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 (
|
return (
|
||||||
|
|||||||
@@ -8,35 +8,35 @@ const currentPath = Astro.url.pathname;
|
|||||||
|
|
||||||
const navGroups = [
|
const navGroups = [
|
||||||
{
|
{
|
||||||
title: 'Command Center',
|
title: 'Command Station',
|
||||||
items: [
|
items: [
|
||||||
{ href: '/admin', label: 'Dashboard', icon: 'home' },
|
{ href: '/admin', label: 'Mission Control', icon: 'home' },
|
||||||
{ href: '/admin/content-factory', label: 'Content Factory', icon: 'zap' },
|
{ 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' },
|
{ href: '/admin/seo/articles', label: 'Generated Output', icon: 'newspaper' },
|
||||||
]
|
{ href: '/admin/media/templates', label: 'Media Assets', icon: 'image' },
|
||||||
},
|
|
||||||
{
|
|
||||||
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' },
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'System',
|
title: 'System',
|
||||||
items: [
|
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) {
|
|||||||
>
|
>
|
||||||
<span class="w-5 h-5 flex-shrink-0">
|
<span class="w-5 h-5 flex-shrink-0">
|
||||||
{item.icon === 'home' && (
|
{item.icon === 'home' && (
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" /></svg>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
{item.icon === 'zap' && (
|
{item.icon === 'rocket_launch' && (
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.59 14.37a6 6 0 01-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 006.16-12.12A14.98 14.98 0 009.631 8.41m5.96 5.96a14.926 14.926 0 01-5.841 2.58m-.119-8.54a6 6 0 00-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 00-2.58 5.84m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 01-2.448-2.448 14.9 14.9 0 01.06-.312m-2.24 2.39a4.493 4.493 0 00-1.757 4.306 4.493 4.493 0 004.306-1.758M16.5 9a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z" /></svg>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
{item.icon === 'file' && (
|
{item.icon === 'factory' && (
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m8-2a2 2 0 00-2-2H9a2 2 0 00-2 2v2m7-2a2 2 0 00-2-2h-1a2 2 0 00-2 2v2m-6-2a2 2 0 00-2-2h-1a2 2 0 00-2 2v2" /></svg>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'edit' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'target' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'newspaper' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'puzzle' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'heading' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h7" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'image' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{item.icon === 'map' && (
|
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
{item.icon === 'users' && (
|
{item.icon === 'users' && (
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" /></svg>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
)}
|
||||||
</svg>
|
{item.icon === 'map' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" /></svg>
|
||||||
|
)}
|
||||||
|
{item.icon === 'puzzle' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 4a2 2 0 114 0v1a1 1 0 001 1h3a1 1 0 011 1v3a1 1 0 01-1 1h-1a2 2 0 100 4h1a1 1 0 011 1v3a1 1 0 01-1 1h-3a1 1 0 01-1-1v-1a2 2 0 10-4 0v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-3a1 1 0 00-1-1H4a2 2 0 110-4h1a1 1 0 001-1V7a1 1 0 011-1h3a1 1 0 001-1V4z" /></svg>
|
||||||
|
)}
|
||||||
|
{item.icon === 'hub' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" /></svg>
|
||||||
|
)}
|
||||||
|
{item.icon === 'web' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" /></svg>
|
||||||
|
)}
|
||||||
|
{item.icon === 'newspaper' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z" /></svg>
|
||||||
|
)}
|
||||||
|
{item.icon === 'image' && (
|
||||||
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
|
||||||
)}
|
)}
|
||||||
{item.icon === 'settings' && (
|
{item.icon === 'settings' && (
|
||||||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /></svg>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
)}
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
{item.icon === 'history' && (
|
||||||
</svg>
|
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<span class="font-medium">{item.label}</span>
|
<span class="font-medium">{item.label}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user