forked from UKSOURCE/cms.hailearning.edu.vn
refactor: restructure code and implement active tab UI
This commit is contained in:
BIN
.env.example
BIN
.env.example
Binary file not shown.
@@ -1,5 +1,5 @@
|
|||||||
const Header = require("../models/header");
|
const Header = require("../models/header");
|
||||||
const HeaderMenu = require("../models/HeaderMenu");
|
const HeaderMenu = require("../models/headerMenu");
|
||||||
const writeAuditLog = require("../audit/writeAuditLog");
|
const writeAuditLog = require("../audit/writeAuditLog");
|
||||||
const diffObject = require("../audit/diffObject");
|
const diffObject = require("../audit/diffObject");
|
||||||
const AUDIT_ACTIONS = require("../constants/auditAction");
|
const AUDIT_ACTIONS = require("../constants/auditAction");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const HeaderMenu = require("../models/HeaderMenu");
|
const HeaderMenu = require("../models/headerMenu");
|
||||||
const slugify = require("slugify");
|
const slugify = require("slugify");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"migrate-fresh": "node scripts/migrate-fresh.js",
|
"migrate-fresh": "node scripts/migrate-fresh.js",
|
||||||
"migrate-status": "node scripts/migrate-status.js",
|
"migrate-status": "node scripts/migrate-status.js",
|
||||||
"migrate-rollback": "node scripts/migrate-rollback.js",
|
"migrate-rollback": "node scripts/migrate-rollback.js",
|
||||||
"make-migration": "node scripts/make-migration.js"
|
"make-migration": "node scripts/make-migration.js",
|
||||||
|
"db:seed": "node scripts/seedDatabase.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cms",
|
"cms",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const mongoose = require('mongoose');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
const HeaderMenu = require('../models/HeaderMenu');
|
const HeaderMenu = require('../models/headerMenu');
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
|
|||||||
92
scripts/seedDatabase.txt
Normal file
92
scripts/seedDatabase.txt
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
require("dotenv").config();
|
||||||
|
const mongoose = require("mongoose");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
// Import models
|
||||||
|
const About = require("../models/aboutUs");
|
||||||
|
const Blog = require("../models/blog");
|
||||||
|
const Service = require("../models/service");
|
||||||
|
const Contact = require("../models/contact");
|
||||||
|
const Footer = require("../models/footer");
|
||||||
|
const Header = require("../models/header");
|
||||||
|
const HeaderMenu = require("../models/headerMenu");
|
||||||
|
const Home = require("../models/home");
|
||||||
|
const FAQ = require("../models/faq");
|
||||||
|
const Visa = require("../models/visa");
|
||||||
|
const Appointment = require("../models/appointment");
|
||||||
|
const Pricing = require("../models/pricing");
|
||||||
|
const Activity = require("../models/activity");
|
||||||
|
|
||||||
|
// Data mapping
|
||||||
|
const dataMap = {
|
||||||
|
about: { model: About, file: "about.json" },
|
||||||
|
blog: { model: Blog, file: "blog.json" },
|
||||||
|
service: { model: Service, file: "service.json" },
|
||||||
|
contact: { model: Contact, file: "contact.json" },
|
||||||
|
footer: { model: Footer, file: "footer.json" },
|
||||||
|
header: { model: Header, file: "header.json" },
|
||||||
|
headerMenu: { model: HeaderMenu, file: "header-menu.json" },
|
||||||
|
home: { model: Home, file: "home.json" },
|
||||||
|
faq: { model: FAQ, file: "faq-data.json" },
|
||||||
|
visa: { model: Visa, file: "visa.json" },
|
||||||
|
appointment: { model: Appointment, file: "appointment.json" },
|
||||||
|
pricing: { model: Pricing, file: "pricing.json" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const seedDatabase = async () => {
|
||||||
|
try {
|
||||||
|
// Kết nối MongoDB
|
||||||
|
if (!process.env.MONGODB_URI) {
|
||||||
|
throw new Error("MONGODB_URI is not defined in environment variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🔗 Connecting to MongoDB...");
|
||||||
|
await mongoose.connect(process.env.MONGODB_URI);
|
||||||
|
console.log("✅ MongoDB Connected");
|
||||||
|
|
||||||
|
// Seed từng collection
|
||||||
|
for (const [key, config] of Object.entries(dataMap)) {
|
||||||
|
try {
|
||||||
|
const jsonPath = path.join(__dirname, "../data", config.file);
|
||||||
|
|
||||||
|
if (!fs.existsSync(jsonPath)) {
|
||||||
|
console.warn(`⚠️ ${config.file} không tồn tại, bỏ qua...`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawData = fs.readFileSync(jsonPath, "utf8");
|
||||||
|
const jsonData = JSON.parse(rawData);
|
||||||
|
|
||||||
|
if (Array.isArray(jsonData)) {
|
||||||
|
// Nếu là array, xóa tất cả và thêm mới
|
||||||
|
await config.model.deleteMany({});
|
||||||
|
await config.model.insertMany(jsonData);
|
||||||
|
console.log(`✅ Seeded ${key} (${jsonData.length} items)`);
|
||||||
|
} else {
|
||||||
|
// Nếu là object, dùng upsert
|
||||||
|
await config.model.findOneAndUpdate({}, jsonData, {
|
||||||
|
upsert: true,
|
||||||
|
new: true,
|
||||||
|
setDefaultsOnInsert: true
|
||||||
|
});
|
||||||
|
console.log(`✅ Seeded ${key}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Error seeding ${key}:`, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("🎉 Database seeding completed successfully!");
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Seeding failed:", error.message);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
await mongoose.connection.close();
|
||||||
|
console.log("👋 Database connection closed");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
seedDatabase();
|
||||||
@@ -41,14 +41,9 @@
|
|||||||
aria-selected="false"><i class="fas fa-info-circle me-2"></i>Intro</a>
|
aria-selected="false"><i class="fas fa-info-circle me-2"></i>Intro</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link <%= locals.activeTab === 'mission' ? 'active' : '' %>" id="mission-tab"
|
<a class="nav-link <%= locals.activeTab === 'mission-vision' ? 'active' : '' %>" id="mission-vision-tab"
|
||||||
data-bs-toggle="tab" href="#mission" role="tab"
|
data-bs-toggle="tab" href="#mission-vision" role="tab"
|
||||||
aria-selected="false"><i class="fas fa-bullseye me-2"></i>Mission</a>
|
aria-selected="false"><i class="fas fa-bullseye me-2"></i>Mission & Vision</a>
|
||||||
</li>
|
|
||||||
<li class="nav-item" role="presentation">
|
|
||||||
<a class="nav-link <%= locals.activeTab === 'features' ? 'active' : '' %>" id="features-tab"
|
|
||||||
data-bs-toggle="tab" href="#features" role="tab"
|
|
||||||
aria-selected="false"><i class="fas fa-star me-2"></i>Features</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<a class="nav-link <%= locals.activeTab === 'news' ? 'active' : '' %>" id="news-tab"
|
<a class="nav-link <%= locals.activeTab === 'news' ? 'active' : '' %>" id="news-tab"
|
||||||
@@ -146,7 +141,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mission Tab -->
|
<!-- Mission Tab -->
|
||||||
<div class="tab-pane fade <%= locals.activeTab === 'mission' ? 'show active' : '' %>" id="mission" role="tabpanel">
|
<div class="tab-pane fade <%= locals.activeTab === 'mission-vision' ? 'show active' : '' %>" id="mission-vision" role="tabpanel">
|
||||||
<div class="card border shadow-sm">
|
<div class="card border shadow-sm">
|
||||||
<div class="card-header bg-white">
|
<div class="card-header bg-white">
|
||||||
<h6 class="mb-0"><i class="fas fa-bullseye me-2"></i>Mission Section</h6>
|
<h6 class="mb-0"><i class="fas fa-bullseye me-2"></i>Mission Section</h6>
|
||||||
@@ -215,10 +210,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Features Tab -->
|
|
||||||
<div class="tab-pane fade <%= locals.activeTab === 'features' ? 'show active' : '' %>" id="features" role="tabpanel">
|
|
||||||
<div class="card border shadow-sm">
|
<div class="card border shadow-sm">
|
||||||
<div class="card-header bg-white">
|
<div class="card-header bg-white">
|
||||||
<h6 class="mb-0"><i class="fas fa-star me-2"></i>Features Section</h6>
|
<h6 class="mb-0"><i class="fas fa-star me-2"></i>Features Section</h6>
|
||||||
@@ -361,11 +353,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script id="serverAboutData" type="application/json">
|
||||||
|
<%- JSON.stringify(locals.data || {}) %>
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let originalFormData = null;
|
let originalFormData = null;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
originalFormData = <%- JSON.stringify(data) %>;
|
// Lấy nội dung text từ thẻ script ẩn và parse nó thành Object
|
||||||
|
const dataElement = document.getElementById('serverAboutData');
|
||||||
|
|
||||||
|
try {
|
||||||
|
originalFormData = JSON.parse(dataElement.textContent || '{}');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Lỗi khi parse dữ liệu từ server:', error);
|
||||||
|
originalFormData = {}; // Giá trị mặc định an toàn nếu parse xịt
|
||||||
|
}
|
||||||
|
|
||||||
updateAllJsonInputs(originalFormData);
|
updateAllJsonInputs(originalFormData);
|
||||||
initializeFormHandlers();
|
initializeFormHandlers();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
<h6 class="mb-0">
|
<h6 class="mb-0">
|
||||||
<i class="fas fa-image me-2"></i>Hero Background
|
<i class="fas fa-image me-2"></i>Hero Background
|
||||||
</h6>
|
</h6>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" id="switchCheckChecked" checked>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user