forked from UKSOURCE/cms.hailearning.edu.vn
Merge branch 'main' of https://gits.techvanguard.vn/UKSOURCE/cms.hailearning.edu.vn into fea/thanh-02022026-news
This commit is contained in:
48
models/HeaderMenu.js
Normal file
48
models/HeaderMenu.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const HeaderMenuSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
lowercase: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
parentId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'HeaderMenu',
|
||||
default: null
|
||||
},
|
||||
order: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['active', 'inactive'],
|
||||
default: 'active'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['internal', 'external'],
|
||||
default: 'internal'
|
||||
}
|
||||
}, {
|
||||
timestamps: true
|
||||
});
|
||||
|
||||
// Indexes for optimization
|
||||
HeaderMenuSchema.index({ order: 1 });
|
||||
HeaderMenuSchema.index({ status: 1 });
|
||||
HeaderMenuSchema.index({ parentId: 1, order: 1 }); // Useful for fetching children in order
|
||||
|
||||
module.exports = mongoose.model('HeaderMenu', HeaderMenuSchema);
|
||||
226
models/header.js
226
models/header.js
@@ -1,129 +1,115 @@
|
||||
const mongoose = require('mongoose');
|
||||
const mongoose = require("mongoose");
|
||||
|
||||
// Schema cho các link trong topbar
|
||||
const topbarLinkSchema = new mongoose.Schema({
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
}
|
||||
}, { _id: false });
|
||||
const socialLinkSchema = new mongoose.Schema(
|
||||
{
|
||||
platform: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ["linkedin", "twitter", "instagram", "youtube", "facebook"],
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: String,
|
||||
order: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
{ _id: false },
|
||||
);
|
||||
|
||||
// Schema cho contact info trong topbar
|
||||
const contactInfoSchema = new mongoose.Schema({
|
||||
phone: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
}
|
||||
}, { _id: false });
|
||||
const languageSchema = new mongoose.Schema(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{ _id: false },
|
||||
);
|
||||
|
||||
// Schema cho topbar
|
||||
const topbarSchema = new mongoose.Schema({
|
||||
contactInfo: {
|
||||
type: contactInfoSchema,
|
||||
required: true
|
||||
},
|
||||
links: {
|
||||
type: [topbarLinkSchema],
|
||||
default: []
|
||||
}
|
||||
}, { _id: false });
|
||||
const menuItemSchema = new mongoose.Schema(
|
||||
{
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: String,
|
||||
order: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
children: [this],
|
||||
},
|
||||
{ _id: false },
|
||||
);
|
||||
|
||||
// Main Header Schema
|
||||
const headerSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
unique: true
|
||||
},
|
||||
topbar: {
|
||||
type: topbarSchema,
|
||||
required: true
|
||||
},
|
||||
logo: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
}
|
||||
}, {
|
||||
timestamps: true
|
||||
});
|
||||
const headerSchema = new mongoose.Schema(
|
||||
{
|
||||
// Top bar
|
||||
top: {
|
||||
phone: String,
|
||||
email: String,
|
||||
location: String,
|
||||
socialLinks: [socialLinkSchema],
|
||||
languages: [languageSchema],
|
||||
},
|
||||
|
||||
// Method để lấy menu tree từ collection menuHeader
|
||||
headerSchema.statics.getMenuTree = async function() {
|
||||
try {
|
||||
const Menu = require('./menuHeader');
|
||||
return await Menu.getMenuTree();
|
||||
} catch (error) {
|
||||
console.error('Error getting menu tree:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
// Offcanvas
|
||||
offcanvas: {
|
||||
description: String,
|
||||
contactInfo: {
|
||||
address: String,
|
||||
email: String,
|
||||
workingHours: String,
|
||||
phone: String,
|
||||
},
|
||||
},
|
||||
|
||||
// Method để lấy menu tree với programmes từ collection menuHeader
|
||||
headerSchema.statics.getMenuTreeWithProgrammes = async function() {
|
||||
try {
|
||||
const Menu = require('./menuHeader');
|
||||
return await Menu.getMenuTreeWithProgrammes();
|
||||
} catch (error) {
|
||||
console.error('Error getting menu tree with programmes:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
// Menu
|
||||
menu: [menuItemSchema],
|
||||
|
||||
// Method để lấy programmes theo menu ID
|
||||
headerSchema.statics.getProgrammesByMenuId = async function(menuId) {
|
||||
try {
|
||||
const Menu = require('./menuHeader');
|
||||
return await Menu.getProgrammesByMenuId(menuId);
|
||||
} catch (error) {
|
||||
console.error('Error getting programmes by menu ID:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
// Logo
|
||||
logo: {
|
||||
light: String,
|
||||
dark: String,
|
||||
alt: String,
|
||||
},
|
||||
|
||||
// Tạo migration script để import dữ liệu từ menu.json
|
||||
headerSchema.statics.migrateFromJson = async function(jsonData) {
|
||||
try {
|
||||
// Kiểm tra xem đã có header mặc định chưa
|
||||
const existingHeader = await this.findOne({ name: 'default' });
|
||||
|
||||
// Chỉ giữ lại topbar và logo, bỏ search và mainMenu
|
||||
const headerData = {
|
||||
topbar: jsonData.topbar,
|
||||
logo: jsonData.logo
|
||||
};
|
||||
|
||||
if (existingHeader) {
|
||||
// Cập nhật header hiện có
|
||||
Object.assign(existingHeader, headerData);
|
||||
await existingHeader.save();
|
||||
console.log('Header data updated successfully');
|
||||
return existingHeader;
|
||||
} else {
|
||||
// Tạo header mới với dữ liệu từ JSON
|
||||
const newHeader = await this.create({
|
||||
name: 'default',
|
||||
...headerData
|
||||
});
|
||||
console.log('Header data imported successfully');
|
||||
return newHeader;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error migrating header data:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
// CTA Button
|
||||
ctaButton: {
|
||||
label: String,
|
||||
href: String,
|
||||
style: {
|
||||
type: String,
|
||||
enum: ["primary", "secondary", "outline"],
|
||||
default: "primary",
|
||||
},
|
||||
},
|
||||
|
||||
module.exports = mongoose.model('Header', headerSchema);
|
||||
// Status
|
||||
status: {
|
||||
type: String,
|
||||
enum: ["active", "inactive"],
|
||||
default: "active",
|
||||
},
|
||||
|
||||
order: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
},
|
||||
{ timestamps: true },
|
||||
);
|
||||
|
||||
module.exports = mongoose.model("Header", headerSchema);
|
||||
|
||||
Reference in New Issue
Block a user