182 lines
7.4 KiB
TypeScript
182 lines
7.4 KiB
TypeScript
import client, { ensureAuthenticated } from '../lib/directus';
|
|
import { updateSettings, uploadFiles } from '@directus/sdk';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
// Helper for ESM __dirname
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
async function setupBranding() {
|
|
console.log('🎨 Refining Directus Branding for Premium Website Look...');
|
|
|
|
// 1. Authenticate
|
|
await ensureAuthenticated();
|
|
|
|
try {
|
|
// 2. Upload Assets (MIME FIXED)
|
|
console.log('📤 Re-uploading assets for clean IDs...');
|
|
|
|
const getMimeType = (filePath: string) => {
|
|
const ext = path.extname(filePath).toLowerCase();
|
|
switch (ext) {
|
|
case '.svg': return 'image/svg+xml';
|
|
case '.png': return 'image/png';
|
|
case '.jpg':
|
|
case '.jpeg': return 'image/jpeg';
|
|
case '.ico': return 'image/x-icon';
|
|
default: return 'application/octet-stream';
|
|
}
|
|
};
|
|
|
|
const uploadAsset = async (filePath: string, title: string) => {
|
|
if (!fs.existsSync(filePath)) {
|
|
console.warn(`⚠️ File not found: ${filePath}`);
|
|
return null;
|
|
}
|
|
const mimeType = getMimeType(filePath);
|
|
const form = new FormData();
|
|
const fileBuffer = fs.readFileSync(filePath);
|
|
const blob = new Blob([fileBuffer], { type: mimeType });
|
|
form.append('file', blob, path.basename(filePath));
|
|
form.append('title', title);
|
|
const res = await client.request(uploadFiles(form));
|
|
return res.id;
|
|
};
|
|
|
|
const logoWhiteId = await uploadAsset(path.resolve(__dirname, '../public/logo-white.svg'), 'Logo White');
|
|
const logoBlueId = await uploadAsset(path.resolve(__dirname, '../public/logo-blue.svg'), 'Logo Blue');
|
|
const faviconId = await uploadAsset(path.resolve(__dirname, '../public/favicon.ico'), 'Favicon');
|
|
|
|
// Smoother Background SVG
|
|
const bgSvgPath = path.resolve(__dirname, '../public/login-bg.svg');
|
|
fs.writeFileSync(bgSvgPath, `<svg width="1920" height="1080" viewBox="0 0 1920 1080" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width="1920" height="1080" fill="#001a4d"/>
|
|
<ellipse cx="960" cy="540" rx="800" ry="600" fill="url(#paint0_radial_premium)"/>
|
|
<defs>
|
|
<radialGradient id="paint0_radial_premium" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(960 540) rotate(90) scale(600 800)">
|
|
<stop stop-color="#003d82" stop-opacity="0.8"/>
|
|
<stop offset="1" stop-color="#001a4d" stop-opacity="0"/>
|
|
</radialGradient>
|
|
</defs>
|
|
</svg>`);
|
|
const backgroundId = await uploadAsset(bgSvgPath, 'Login Bg');
|
|
if (fs.existsSync(bgSvgPath)) fs.unlinkSync(bgSvgPath);
|
|
|
|
// 3. Update Settings with "Premium Web" Theme
|
|
console.log('⚙️ Updating Directus settings...');
|
|
|
|
const COLOR_PRIMARY = '#001a4d'; // Deep Blue
|
|
const COLOR_ACCENT = '#82ed20'; // Sustainability Green
|
|
const COLOR_SECONDARY = '#003d82';
|
|
|
|
const cssInjection = `
|
|
<style>
|
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
|
|
/* Global Login Styles */
|
|
body, .v-app {
|
|
font-family: 'Inter', sans-serif !important;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
/* Glassmorphism Effect for Login Card */
|
|
.public-view .v-card {
|
|
background: rgba(255, 255, 255, 0.95) !important;
|
|
backdrop-filter: blur(20px);
|
|
border: 1px solid rgba(255, 255, 255, 0.3) !important;
|
|
border-radius: 32px !important;
|
|
box-shadow: 0 50px 100px -20px rgba(0, 0, 0, 0.4) !important;
|
|
padding: 40px !important;
|
|
}
|
|
|
|
.public-view .v-button {
|
|
border-radius: full !important;
|
|
height: 56px !important;
|
|
font-weight: 600 !important;
|
|
letter-spacing: -0.01em !important;
|
|
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important;
|
|
}
|
|
|
|
.public-view .v-button:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 15px 30px rgba(130, 237, 32, 0.2) !important;
|
|
}
|
|
|
|
.public-view .v-input {
|
|
--v-input-border-radius: 12px !important;
|
|
--v-input-background-color: #f8f9fa !important;
|
|
}
|
|
</style>
|
|
<div style="font-family: 'Inter', sans-serif; text-align: center; margin-top: 24px;">
|
|
<p style="color: rgba(255,255,255,0.7); font-size: 14px; margin-bottom: 4px; font-weight: 500;">KLZ INFRASTRUCTURE ENGINE</p>
|
|
<h1 style="color: #ffffff; font-size: 18px; font-weight: 700; margin: 0;">Sustainable Energy. <span style="color: #82ed20;">Industrial Reliability.</span></h1>
|
|
</div>
|
|
`;
|
|
|
|
await client.request(updateSettings({
|
|
project_name: 'KLZ Cables',
|
|
project_url: 'https://klz-cables.com',
|
|
project_color: COLOR_ACCENT,
|
|
project_descriptor: 'Sustainable Energy Infrastructure',
|
|
project_owner: 'KLZ Cables',
|
|
|
|
// FIXED: Use WHITE logo for the Blue Sidebar
|
|
project_logo: logoWhiteId as any,
|
|
|
|
public_foreground: logoWhiteId as any,
|
|
public_background: backgroundId as any,
|
|
public_note: cssInjection,
|
|
public_favicon: faviconId as any,
|
|
|
|
// DEEP PREMIUM THEME
|
|
theme_light_overrides: {
|
|
// Brands
|
|
"primary": COLOR_ACCENT, // Buttons/Actions are GREEN like the website
|
|
"secondary": COLOR_SECONDARY,
|
|
|
|
// Content Area
|
|
"background": "#f1f3f7",
|
|
"backgroundNormal": "#ffffff",
|
|
"backgroundAccent": "#eef2ff",
|
|
|
|
// Sidebar Branding
|
|
"navigationBackground": COLOR_PRIMARY,
|
|
"navigationForeground": "#ffffff",
|
|
"navigationBackgroundHover": "rgba(255,255,255,0.05)",
|
|
"navigationForegroundHover": "#ffffff",
|
|
"navigationBackgroundActive": "rgba(130, 237, 32, 0.15)", // Subtle Green highlight
|
|
"navigationForegroundActive": COLOR_ACCENT, // Active item is GREEN
|
|
|
|
// Module Bar (Thin far left)
|
|
"moduleBarBackground": "#000d26",
|
|
"moduleBarForeground": "#ffffff",
|
|
"moduleBarForegroundActive": COLOR_ACCENT,
|
|
|
|
// UI Standards
|
|
"borderRadius": "16px", // Larger radius for modern feel
|
|
"borderWidth": "1px",
|
|
"borderColor": "#e2e8f0",
|
|
"formFieldHeight": "48px" // Touch-target height
|
|
} as any,
|
|
|
|
theme_dark_overrides: {
|
|
"primary": COLOR_ACCENT,
|
|
"background": "#0a0a0a",
|
|
"navigationBackground": "#000000",
|
|
"moduleBarBackground": COLOR_PRIMARY,
|
|
"borderRadius": "16px",
|
|
"formFieldHeight": "48px"
|
|
} as any
|
|
}));
|
|
|
|
console.log('✨ Premium Theme applied successfully!');
|
|
|
|
} catch (error: any) {
|
|
console.error('❌ Error:', JSON.stringify(error, null, 2));
|
|
}
|
|
}
|
|
|
|
setupBranding();
|