Add remaining admin dashboard files (final chunk)
This commit is contained in:
parent
758728a093
commit
7f70170fe1
513 changed files with 7857 additions and 0 deletions
272
admin-dashboard/scripts/sync-to-main.js
Normal file
272
admin-dashboard/scripts/sync-to-main.js
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { execSync } = require("child_process");
|
||||
|
||||
class AdminSync {
|
||||
constructor() {
|
||||
this.mainRepoPath = "temp-main";
|
||||
this.adminRepoPath = process.cwd();
|
||||
this.mainRepoUrl = "https://git.kh3group.com/george/website.git";
|
||||
this.syncLog = [];
|
||||
}
|
||||
|
||||
async syncToMain() {
|
||||
console.log("🚀 Starting sync to main site...");
|
||||
this.log("Starting sync process");
|
||||
|
||||
try {
|
||||
// Step 1: Clone main repository
|
||||
await this.cloneMainRepo();
|
||||
|
||||
// Step 2: Sync products.json
|
||||
await this.syncProducts();
|
||||
|
||||
// Step 3: Sync images
|
||||
await this.syncImages();
|
||||
|
||||
// Step 4: Validate changes
|
||||
await this.validateChanges();
|
||||
|
||||
// Step 5: Commit and push
|
||||
await this.commitAndPush();
|
||||
|
||||
// Step 6: Cleanup
|
||||
this.cleanup();
|
||||
|
||||
console.log("✅ Successfully synced to main site!");
|
||||
console.log("🌐 Your changes should be live shortly.");
|
||||
this.log("Sync completed successfully");
|
||||
} catch (error) {
|
||||
console.error("❌ Sync failed:", error.message);
|
||||
this.log(`Sync failed: ${error.message}`, "error");
|
||||
this.cleanup();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async cloneMainRepo() {
|
||||
console.log("📥 Cloning main repository...");
|
||||
this.log("Cloning main repository");
|
||||
|
||||
if (fs.existsSync(this.mainRepoPath)) {
|
||||
execSync(`rm -rf ${this.mainRepoPath}`);
|
||||
}
|
||||
|
||||
try {
|
||||
execSync(`git clone ${this.mainRepoUrl} ${this.mainRepoPath}`, {
|
||||
stdio: "pipe",
|
||||
});
|
||||
execSync(`cd ${this.mainRepoPath} && git checkout main`, {
|
||||
stdio: "pipe",
|
||||
});
|
||||
this.log("Main repository cloned successfully");
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to clone repository: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async syncProducts() {
|
||||
console.log("📦 Syncing products.json...");
|
||||
this.log("Syncing products data");
|
||||
|
||||
const adminProductsPath = path.join(
|
||||
this.adminRepoPath,
|
||||
"data/products.json"
|
||||
);
|
||||
const mainProductsPath = path.join(this.mainRepoPath, "data/products.json");
|
||||
|
||||
if (!fs.existsSync(adminProductsPath)) {
|
||||
throw new Error("products.json not found in admin repo");
|
||||
}
|
||||
|
||||
// Ensure main data directory exists
|
||||
const mainDataDir = path.dirname(mainProductsPath);
|
||||
if (!fs.existsSync(mainDataDir)) {
|
||||
fs.mkdirSync(mainDataDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy products.json
|
||||
fs.copyFileSync(adminProductsPath, mainProductsPath);
|
||||
console.log(" ✅ Products synced");
|
||||
this.log("Products data synced successfully");
|
||||
}
|
||||
|
||||
async syncImages() {
|
||||
console.log("🖼️ Syncing images...");
|
||||
this.log("Syncing product images");
|
||||
|
||||
const adminImagesPath = path.join(
|
||||
this.adminRepoPath,
|
||||
"assets/images/products"
|
||||
);
|
||||
const mainImagesPath = path.join(
|
||||
this.mainRepoPath,
|
||||
"assets/images/products"
|
||||
);
|
||||
|
||||
// Create main images directory if it doesn't exist
|
||||
if (!fs.existsSync(mainImagesPath)) {
|
||||
fs.mkdirSync(mainImagesPath, { recursive: true });
|
||||
}
|
||||
|
||||
let imagesProcessed = 0;
|
||||
let imagesRemoved = 0;
|
||||
|
||||
if (fs.existsSync(adminImagesPath)) {
|
||||
// Get all files in admin images directory
|
||||
const adminImages = fs.readdirSync(adminImagesPath);
|
||||
const mainImages = fs.existsSync(mainImagesPath)
|
||||
? fs.readdirSync(mainImagesPath)
|
||||
: [];
|
||||
|
||||
// Copy new/updated images
|
||||
for (const image of adminImages) {
|
||||
const srcPath = path.join(adminImagesPath, image);
|
||||
const destPath = path.join(mainImagesPath, image);
|
||||
|
||||
if (fs.statSync(srcPath).isFile()) {
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
console.log(` 📸 Copied: ${image}`);
|
||||
imagesProcessed++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove orphaned images (in main but not in admin)
|
||||
for (const image of mainImages) {
|
||||
const adminImagePath = path.join(adminImagesPath, image);
|
||||
if (!fs.existsSync(adminImagePath)) {
|
||||
fs.unlinkSync(path.join(mainImagesPath, image));
|
||||
console.log(` 🗑️ Removed: ${image}`);
|
||||
imagesRemoved++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
` ✅ Images synced (${imagesProcessed} copied, ${imagesRemoved} removed)`
|
||||
);
|
||||
this.log(
|
||||
`Images synced: ${imagesProcessed} copied, ${imagesRemoved} removed`
|
||||
);
|
||||
}
|
||||
|
||||
async validateChanges() {
|
||||
console.log("🔍 Validating changes...");
|
||||
this.log("Validating synced data");
|
||||
|
||||
// Validate JSON
|
||||
const productsPath = path.join(this.mainRepoPath, "data/products.json");
|
||||
if (!fs.existsSync(productsPath)) {
|
||||
throw new Error("products.json not found after sync");
|
||||
}
|
||||
|
||||
let productsData;
|
||||
try {
|
||||
productsData = JSON.parse(fs.readFileSync(productsPath, "utf8"));
|
||||
} catch (error) {
|
||||
throw new Error("Invalid JSON in products.json");
|
||||
}
|
||||
|
||||
if (!productsData.products || !Array.isArray(productsData.products)) {
|
||||
throw new Error("Invalid products.json structure");
|
||||
}
|
||||
|
||||
// Check if all referenced images exist
|
||||
let missingImages = 0;
|
||||
for (const product of productsData.products) {
|
||||
if (product.images) {
|
||||
for (const imagePath of product.images) {
|
||||
const fullPath = path.join(this.mainRepoPath, imagePath);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
console.warn(`⚠️ Warning: Image not found: ${imagePath}`);
|
||||
missingImages++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (missingImages > 0) {
|
||||
console.warn(`⚠️ Found ${missingImages} missing images`);
|
||||
}
|
||||
|
||||
console.log(" ✅ Validation passed");
|
||||
this.log(`Validation passed (${missingImages} missing images)`);
|
||||
}
|
||||
|
||||
async commitAndPush() {
|
||||
console.log("💾 Committing and pushing changes...");
|
||||
this.log("Committing and pushing changes");
|
||||
|
||||
try {
|
||||
// Add all changes
|
||||
execSync(`cd ${this.mainRepoPath} && git add .`, { stdio: "pipe" });
|
||||
|
||||
// Check if there are changes to commit
|
||||
try {
|
||||
execSync(`cd ${this.mainRepoPath} && git diff --cached --quiet`, {
|
||||
stdio: "pipe",
|
||||
});
|
||||
console.log(" ℹ️ No changes to commit");
|
||||
this.log("No changes to commit");
|
||||
return;
|
||||
} catch (error) {
|
||||
// There are changes, proceed with commit
|
||||
}
|
||||
|
||||
// Commit changes
|
||||
const commitMessage = `Update products and images from admin dashboard - ${new Date().toISOString()}`;
|
||||
execSync(`cd ${this.mainRepoPath} && git commit -m "${commitMessage}"`, {
|
||||
stdio: "pipe",
|
||||
});
|
||||
|
||||
// Push to main branch
|
||||
execSync(`cd ${this.mainRepoPath} && git push origin main`, {
|
||||
stdio: "pipe",
|
||||
});
|
||||
|
||||
console.log(" ✅ Changes pushed to main repository");
|
||||
this.log("Changes pushed successfully");
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to commit/push: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
console.log("🧹 Cleaning up...");
|
||||
this.log("Cleaning up temporary files");
|
||||
if (fs.existsSync(this.mainRepoPath)) {
|
||||
execSync(`rm -rf ${this.mainRepoPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
log(message, type = "info") {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logEntry = {
|
||||
timestamp,
|
||||
type,
|
||||
message,
|
||||
};
|
||||
this.syncLog.push(logEntry);
|
||||
|
||||
// Save log to file
|
||||
const logPath = path.join(this.adminRepoPath, "sync-log.json");
|
||||
fs.writeFileSync(logPath, JSON.stringify(this.syncLog, null, 2));
|
||||
}
|
||||
|
||||
// Method to get sync history
|
||||
getSyncHistory() {
|
||||
const logPath = path.join(this.adminRepoPath, "sync-log.json");
|
||||
if (fs.existsSync(logPath)) {
|
||||
return JSON.parse(fs.readFileSync(logPath, "utf8"));
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Run sync if called directly
|
||||
if (require.main === module) {
|
||||
const sync = new AdminSync();
|
||||
sync.syncToMain();
|
||||
}
|
||||
|
||||
module.exports = AdminSync;
|
||||
Loading…
Add table
Add a link
Reference in a new issue